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