00001 #include "SundanceRivaraDriver.hpp"
00002 #include "SundanceMesh.hpp"
00003 #include "SundanceRivaraMesh.hpp"
00004 #include "SundanceExprFieldWrapper.hpp"
00005
00006 using namespace Sundance;
00007 using namespace Sundance;
00008 using namespace Teuchos;
00009 using namespace Sundance::Rivara;
00010 using Sundance::ExprFieldWrapper;
00011 using std::endl;
00012
00013 void sort(const Array<int>& in, Array<int>& rtn)
00014 {
00015 rtn.resize(in.size());
00016 const int* pIn = &(in[0]);
00017 int* pRtn = &(rtn[0]);
00018 for (int i=0; i<in.size(); i++) pRtn[i] = pIn[i];
00019
00020 for (int j=1; j<in.size(); j++)
00021 {
00022 int key = pRtn[j];
00023 int i=j-1;
00024 while (i>=0 && pRtn[i]>key)
00025 {
00026 pRtn[i+1]=pRtn[i];
00027 i--;
00028 }
00029 pRtn[i+1]=key;
00030 }
00031
00032 }
00033
00034 static Time& refTimer()
00035 {
00036 static RCP<Time> rtn
00037 = TimeMonitor::getNewTimer("mesh refinement");
00038 return *rtn;
00039 }
00040
00041 static Time& m2rTimer()
00042 {
00043 static RCP<Time> rtn
00044 = TimeMonitor::getNewTimer("mesh to rivara copy");
00045 return *rtn;
00046 }
00047
00048 static Time& r2mTimer()
00049 {
00050 static RCP<Time> rtn
00051 = TimeMonitor::getNewTimer("rivara to mesh copy");
00052 return *rtn;
00053 }
00054
00055 static Time& volSetTimer()
00056 {
00057 static RCP<Time> rtn
00058 = TimeMonitor::getNewTimer("refinement stack building");
00059 return *rtn;
00060 }
00061
00062
00063 Mesh RefinementTransformation::apply(const Mesh& inputMesh) const
00064 {
00065 TimeMonitor timer(refTimer());
00066
00067 int dim = inputMesh.spatialDim();
00068 MPIComm comm = inputMesh.comm();
00069 int numElems = inputMesh.numCells(dim);
00070
00071 RCP<RivaraMesh> rivMesh = rcp(new RivaraMesh(dim, comm));
00072
00073 Array<int> lidMap;
00074
00075 meshToRivara(inputMesh, lidMap,rivMesh);
00076
00077 ExprFieldWrapper expr(errExpr_);
00078 TEUCHOS_TEST_FOR_EXCEPTION(expr.isPointData(), std::runtime_error,
00079 "Expected cell-based discrete function for area specification");
00080
00081 {
00082 TimeMonitor timer(volSetTimer());
00083 numRefined_ = 0;
00084 for (int c=0; c<numElems; c++)
00085 {
00086 double err = expr.getData(dim,c,0);
00087 int rivLID = lidMap[c];
00088 Element* e = rivMesh->element(rivLID).get();
00089 double vol = e->volume();
00090 double newVol = vol * std::pow(reqErr_/(err+1.0e-12), 0.5*dim);
00091
00092 if (newVol >= vol) continue;
00093 rivMesh->refinementSet().push(e);
00094 rivMesh->refinementAreas().push(newVol);
00095 numRefined_ ++;
00096 }
00097 }
00098 Out::os() << "refining n=" << numRefined_ << " cells" << std::endl;
00099 rivMesh->refine();
00100
00101
00102 Mesh outputMesh = rivaraToMesh(rivMesh, comm);
00103
00104 return outputMesh;
00105 }
00106
00107
00108 void RefinementTransformation::meshToRivara(
00109 const Mesh& mesh,
00110 Array<int>& lidMap,
00111 RCP<RivaraMesh>& rivMesh) const
00112 {
00113 TimeMonitor timer(m2rTimer());
00114 int dim = mesh.spatialDim();
00115 int numNodes = mesh.numCells(0);
00116 int numElems = mesh.numCells(dim);
00117
00118 for (int n=0; n<numNodes; n++)
00119 {
00120 int gid = n;
00121 int label = mesh.label(0,n);
00122 int ownerProcID = mesh.ownerProcID(0,n);
00123 Point x = mesh.nodePosition(n);
00124 rivMesh->addVertex(gid, x, ownerProcID, label);
00125 }
00126
00127 lidMap.resize(numElems);
00128 for (int e=0; e<numElems; e++)
00129 {
00130 int gid = e;
00131 int label = mesh.label(dim,e);
00132 int ownerProcID = mesh.ownerProcID(dim,e);
00133 Array<int> verts;
00134 Array<int> fo;
00135 mesh.getFacetArray(dim, e, 0, verts, fo);
00136 int elemLID = rivMesh->addElement(gid, verts, ownerProcID, label);
00137 lidMap[e] = elemLID;
00138
00139 if (dim==2)
00140 {
00141 Array<int> edgeLIDs;
00142 mesh.getFacetArray(dim, e, 1, edgeLIDs, fo);
00143 for (int f=0; f<3; f++)
00144 {
00145 int edgeLabel = mesh.label(1,edgeLIDs[f]);
00146 rivMesh->element(elemLID)->edge(f)->setLabel(edgeLabel);
00147 }
00148 }
00149 else if (dim==3)
00150 {
00151 Array<int> faceLIDs;
00152 mesh.getFacetArray(dim, e, 2, faceLIDs, fo);
00153 for (int f=0; f<4; f++)
00154 {
00155 int faceLabel = mesh.label(2,faceLIDs[f]);
00156 rivMesh->element(elemLID)->face(f)->setLabel(faceLabel);
00157 }
00158 }
00159 }
00160 }
00161
00162
00163 Mesh RefinementTransformation::rivaraToMesh(const RCP<RivaraMesh>& rivMesh,
00164 const MPIComm& comm) const
00165 {
00166 TimeMonitor timer(r2mTimer());
00167 int dim = rivMesh->spatialDim();
00168 int numNodes = rivMesh->numNodes();
00169
00170 Mesh mesh = meshType_.createEmptyMesh(dim, comm);
00171
00172 for (int n=0; n<numNodes; n++)
00173 {
00174 const RCP<Node>& node = rivMesh->node(n);
00175 const Point& x = node->pt();
00176 int gid = node->globalIndex();
00177 int ownerProcID = node->ownerProc();
00178 int label = node->label();
00179 mesh.addVertex(gid, x, ownerProcID, label);
00180 }
00181
00182
00183 ElementIterator iter(rivMesh.get());
00184
00185 int gid=0;
00186
00187 Array<int> verts(dim+1);
00188 Array<int> fo;
00189 Array<int> edgeLIDs;
00190 Array<int> faceLIDs;
00191
00192 while (iter.hasMoreElements())
00193 {
00194 Tabs tab;
00195 const Element* e = iter.getNextElement();
00196 int ownerProcID = e->ownerProc();
00197 int label = e->label();
00198 const Array<RCP<Node> >& nodes = e->nodes();
00199
00200 for (int i=0; i<nodes.size(); i++)
00201 {
00202 verts[i] = nodes[i]->globalIndex();
00203 }
00204 int lid = mesh.addElement(gid, verts, ownerProcID, label);
00205 gid++;
00206
00207 Array<int> sortedVerts(verts.size());
00208 sort(verts, sortedVerts);
00209
00210 Out::os() << tab << "elem LID=" << lid << " verts=" << sortedVerts << endl;
00211
00212 if (dim==2)
00213 {
00214 if (e->hasNoEdgeLabels()) continue;
00215 mesh.getFacetArray(dim, lid, 1, edgeLIDs, fo);
00216 for (int f=0; f<3; f++)
00217 {
00218 int edgeLabel = e->edge(f)->label();
00219 if (edgeLabel < 0) continue;
00220 mesh.setLabel(1, edgeLIDs[f], edgeLabel);
00221 }
00222 }
00223 else if (dim==3)
00224 {
00225 Tabs tab1;
00226 if (e->hasNoFaceLabels()) continue;
00227 mesh.getFacetArray(dim, lid, 2, faceLIDs, fo);
00228 for (int f=0; f<4; f++)
00229 {
00230
00231 int faceLabel = e->face(f)->label();
00232 if (faceLabel <= 0) continue;
00233 const FaceNodes& nodes = e->face(f)->nodes();
00234 Array<int> nodeLIDs = nodes.nodes().elements();
00235 Out::os() << tab1 << "face nodes = " << nodeLIDs << endl;
00236 int faceNum = -1;
00237 if (nodeLIDs[0]==sortedVerts[0] && nodeLIDs[1]==sortedVerts[1]
00238 && nodeLIDs[2]==sortedVerts[2])
00239 {
00240 faceNum = 3;
00241 }
00242 else if (nodeLIDs[0]==sortedVerts[0] && nodeLIDs[1]==sortedVerts[1]
00243 && nodeLIDs[2]==sortedVerts[3])
00244 {
00245 faceNum = 2;
00246 }
00247 else if (nodeLIDs[0]==sortedVerts[0] && nodeLIDs[1]==sortedVerts[2]
00248 && nodeLIDs[2]==sortedVerts[3])
00249 {
00250 faceNum = 1;
00251 }
00252 else if (nodeLIDs[0]==sortedVerts[1] && nodeLIDs[1]==sortedVerts[2]
00253 && nodeLIDs[2]==sortedVerts[3])
00254 {
00255 faceNum = 0;
00256 }
00257 else
00258 {
00259 TEUCHOS_TEST_FOR_EXCEPT(true);
00260 }
00261 Out::os() << tab1 << "faceLID=" << faceLIDs[faceNum] << " UFC face num="
00262 << faceNum
00263 << " label = " << faceLabel
00264 << " parent = " << lid << std::endl;
00265 mesh.setLabel(2, faceLIDs[faceNum], faceLabel);
00266 }
00267 }
00268 }
00269
00270 return mesh;
00271
00272 }
00273
00274