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
00012
00013 static Time& refTimer()
00014 {
00015 static RCP<Time> rtn
00016 = TimeMonitor::getNewTimer("mesh refinement");
00017 return *rtn;
00018 }
00019
00020 static Time& m2rTimer()
00021 {
00022 static RCP<Time> rtn
00023 = TimeMonitor::getNewTimer("mesh to rivara copy");
00024 return *rtn;
00025 }
00026
00027 static Time& r2mTimer()
00028 {
00029 static RCP<Time> rtn
00030 = TimeMonitor::getNewTimer("rivara to mesh copy");
00031 return *rtn;
00032 }
00033
00034 static Time& volSetTimer()
00035 {
00036 static RCP<Time> rtn
00037 = TimeMonitor::getNewTimer("refinement stack building");
00038 return *rtn;
00039 }
00040
00041
00042 Mesh RefinementTransformation::apply(const Mesh& inputMesh) const
00043 {
00044 TimeMonitor timer(refTimer());
00045
00046 int dim = inputMesh.spatialDim();
00047 MPIComm comm = inputMesh.comm();
00048 int numElems = inputMesh.numCells(dim);
00049
00050 RCP<RivaraMesh> rivMesh = rcp(new RivaraMesh(dim, comm));
00051
00052 Array<int> lidMap;
00053
00054 meshToRivara(inputMesh, lidMap,rivMesh);
00055
00056 ExprFieldWrapper expr(errExpr_);
00057 TEST_FOR_EXCEPTION(expr.isPointData(), RuntimeError,
00058 "Expected cell-based discrete function for area specification");
00059
00060 {
00061 TimeMonitor timer(volSetTimer());
00062 numRefined_ = 0;
00063 for (int c=0; c<numElems; c++)
00064 {
00065 double err = expr.getData(dim,c,0);
00066 int rivLID = lidMap[c];
00067 Element* e = rivMesh->element(rivLID).get();
00068 double vol = e->volume();
00069 double newVol = vol * std::pow(reqErr_/(err+1.0e-12), 0.5*dim);
00070
00071 if (newVol >= vol) continue;
00072 rivMesh->refinementSet().push(e);
00073 rivMesh->refinementAreas().push(newVol);
00074 numRefined_ ++;
00075 }
00076 }
00077 Out::os() << "refining n=" << numRefined_ << " cells" << std::endl;
00078 rivMesh->refine();
00079
00080
00081 Mesh outputMesh = rivaraToMesh(rivMesh, comm);
00082
00083 return outputMesh;
00084 }
00085
00086
00087 void RefinementTransformation::meshToRivara(
00088 const Mesh& mesh,
00089 Array<int>& lidMap,
00090 RCP<RivaraMesh>& rivMesh) const
00091 {
00092 TimeMonitor timer(m2rTimer());
00093 int dim = mesh.spatialDim();
00094 int numNodes = mesh.numCells(0);
00095 int numElems = mesh.numCells(dim);
00096
00097 for (int n=0; n<numNodes; n++)
00098 {
00099 int gid = n;
00100 int label = mesh.label(0,n);
00101 int ownerProcID = mesh.ownerProcID(0,n);
00102 Point x = mesh.nodePosition(n);
00103 rivMesh->addVertex(gid, x, ownerProcID, label);
00104 }
00105
00106 lidMap.resize(numElems);
00107 for (int e=0; e<numElems; e++)
00108 {
00109 int gid = e;
00110 int label = mesh.label(dim,e);
00111 int ownerProcID = mesh.ownerProcID(dim,e);
00112 Array<int> verts;
00113 Array<int> fo;
00114 mesh.getFacetArray(dim, e, 0, verts, fo);
00115 int elemLID = rivMesh->addElement(gid, verts, ownerProcID, label);
00116 lidMap[e] = elemLID;
00117
00118 if (dim==2)
00119 {
00120 Array<int> edgeLIDs;
00121 mesh.getFacetArray(dim, e, 1, edgeLIDs, fo);
00122 for (int f=0; f<3; f++)
00123 {
00124 int edgeLabel = mesh.label(1,edgeLIDs[f]);
00125 rivMesh->element(elemLID)->edge(f)->setLabel(edgeLabel);
00126 }
00127 }
00128 else if (dim==3)
00129 {
00130 Array<int> faceLIDs;
00131 mesh.getFacetArray(dim, e, 2, faceLIDs, fo);
00132 for (int f=0; f<4; f++)
00133 {
00134 int faceLabel = mesh.label(2,faceLIDs[f]);
00135 rivMesh->element(elemLID)->face(f)->setLabel(faceLabel);
00136 }
00137 }
00138 }
00139 }
00140
00141
00142 Mesh RefinementTransformation::rivaraToMesh(const RCP<RivaraMesh>& rivMesh,
00143 const MPIComm& comm) const
00144 {
00145 TimeMonitor timer(r2mTimer());
00146 int dim = rivMesh->spatialDim();
00147 int numNodes = rivMesh->numNodes();
00148
00149 Mesh mesh = meshType_.createEmptyMesh(dim, comm);
00150
00151 for (int n=0; n<numNodes; n++)
00152 {
00153 const RCP<Node>& node = rivMesh->node(n);
00154 const Point& x = node->pt();
00155 int gid = node->globalIndex();
00156 int ownerProcID = node->ownerProc();
00157 int label = node->label();
00158 mesh.addVertex(gid, x, ownerProcID, label);
00159 }
00160
00161
00162 ElementIterator iter(rivMesh.get());
00163
00164 int gid=0;
00165
00166 Array<int> verts(dim+1);
00167 Array<int> fo;
00168 Array<int> edgeLIDs;
00169 Array<int> faceLIDs;
00170
00171 while (iter.hasMoreElements())
00172 {
00173 const Element* e = iter.getNextElement();
00174 int ownerProcID = e->ownerProc();
00175 int label = e->label();
00176 const Array<RCP<Node> >& nodes = e->nodes();
00177
00178 for (int i=0; i<nodes.size(); i++)
00179 {
00180 verts[i] = nodes[i]->globalIndex();
00181 }
00182 int lid = mesh.addElement(gid, verts, ownerProcID, label);
00183 gid++;
00184
00185 if (dim==2)
00186 {
00187 if (e->hasNoEdgeLabels()) continue;
00188 mesh.getFacetArray(dim, lid, 1, edgeLIDs, fo);
00189 for (int f=0; f<3; f++)
00190 {
00191 int edgeLabel = e->edge(f)->label();
00192 mesh.setLabel(1, edgeLIDs[f], edgeLabel);
00193 }
00194 }
00195 else if (dim==3)
00196 {
00197 if (e->hasNoFaceLabels()) continue;
00198 mesh.getFacetArray(dim, lid, 2, faceLIDs, fo);
00199 for (int f=0; f<4; f++)
00200 {
00201 int faceLabel = e->face(f)->label();
00202 mesh.setLabel(2, faceLIDs[f], faceLabel);
00203 }
00204 }
00205 }
00206
00207 return mesh;
00208
00209 }
00210
00211