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 #include "SundanceMesh.hpp"
00032 #include "SundanceExceptions.hpp"
00033 #include "SundanceVerboseFieldWriter.hpp"
00034 #include "SundanceFieldWriter.hpp"
00035 #include "SundanceOut.hpp"
00036 #include "SundanceSet.hpp"
00037 #include "SundanceMap.hpp"
00038 #include "SundanceTabs.hpp"
00039 #include "Teuchos_MPIContainerComm.hpp"
00040
00041 using namespace Sundance;
00042 using namespace Sundance;
00043 using namespace Teuchos;
00044 using namespace Sundance;
00045
00046
00047
00048 IncrementallyCreatableMesh* Mesh::creatableMesh()
00049 {
00050 IncrementallyCreatableMesh* mci
00051 = dynamic_cast<IncrementallyCreatableMesh*>(ptr().get());
00052 TEST_FOR_EXCEPTION(mci==0, RuntimeError,
00053 "Mesh::creatableMesh() could not convert mesh to "
00054 "a type deriving from IncrementallyCreatableMesh");
00055
00056 return mci;
00057 }
00058
00059
00060 void Mesh::dump(const std::string& filename) const
00061 {
00062 FieldWriter w = new VerboseFieldWriter(filename);
00063 w.addMesh(*this);
00064 w.write();
00065 }
00066
00067 bool Mesh::checkConsistency(const std::string& filename) const
00068 {
00069 std::string f = filename;
00070
00071 if (comm().getNProc() > 1)
00072 {
00073 f = f + "." + Teuchos::toString(comm().getRank());
00074 }
00075 std::ofstream os(f.c_str());
00076 return checkConsistency(os);
00077 }
00078
00079 bool Mesh::checkConsistency(std::ostream& os) const
00080 {
00081
00082 if (comm().getNProc()==1)
00083 {
00084 os << "Mesh is serial, thus it is consistent across processors" << std::endl;
00085 return true;
00086 }
00087
00088
00089 if (spatialDim() >= 2)
00090 const_cast<Mesh*>(this)->assignIntermediateCellGIDs(1);
00091 if (spatialDim() >= 3)
00092 const_cast<Mesh*>(this)->assignIntermediateCellGIDs(2);
00093 bool isOK = checkVertexConsistency(os);
00094 for (int d=1; d<=spatialDim(); d++)
00095 {
00096 isOK = checkCellConsistency(os, d) && isOK;
00097 }
00098
00099 return isOK;
00100 }
00101
00102
00103 bool Mesh::checkCellConsistency(std::ostream& os, int dim) const
00104 {
00105 TEST_FOR_EXCEPTION(dim==0, RuntimeError,
00106 "Mesh::checkCellConsistency called for d=0. "
00107 "checkVertexConsistency() should be called instead");
00108
00109 int myRank = comm().getRank();
00110 int nProcs = comm().getNProc();
00111 Array<int> nFacets(dim);
00112
00113 bool elemsAreOK = true;
00114
00115
00116
00117
00118 int dataSize = 2;
00119 for (int d=0; d<dim; d++)
00120 {
00121 nFacets[d] = numFacets(dim, 0, d);
00122 dataSize += 2*nFacets[d];
00123 if (d > 0) dataSize += nFacets[d]*numFacets(d, 0, 0);
00124 }
00125
00126 int nCells = numCells(dim);
00127 Array<int> elemData(dataSize*nCells);
00128
00129 for (int c=0; c<nCells; c++)
00130 {
00131 elemData[dataSize*c] = mapLIDToGID(dim, c);
00132 elemData[dataSize*c + 1] = ownerProcID(dim, c);
00133 int base = dataSize*c + 2;
00134 int k=0;
00135 for (int d=0; d<dim; d++)
00136 {
00137 for (int f=0; f<nFacets[d]; f++)
00138 {
00139 int orientation;
00140 int lid = facetLID(dim, c, d, f, orientation);
00141 int facetGID = mapLIDToGID(d, lid);
00142 int facetOwner = ownerProcID(d, lid);
00143 elemData[base + k++] = facetGID;
00144 elemData[base + k++] = facetOwner;
00145 if (d > 0)
00146 {
00147 int nNodes = numFacets(d, lid, 0);
00148 for (int v=0; v<nNodes; v++)
00149 {
00150 int nodeLID = facetLID(d, lid, 0, v, orientation);
00151 int nodeGID = mapLIDToGID(0, nodeLID);
00152 elemData[base + k++] = nodeGID;
00153 }
00154 }
00155 }
00156 }
00157 }
00158
00159
00160
00161 Array<Array<int> > outData(nProcs);
00162 for (int p=0; p<nProcs; p++)
00163 {
00164 outData[p] = elemData;
00165 }
00166
00167 Array<Array<int> > inData(nProcs);
00168
00169 MPIContainerComm<int>::allToAll(outData, inData, comm());
00170
00171 for (int p=0; p<nProcs; p++)
00172 {
00173 Tabs tab1;
00174 if (p==myRank) continue;
00175
00176 os << tab1 << "p=" << myRank << " testing " << dim
00177 << "-cells from remote p=" << p << std::endl;
00178
00179 const Array<int>& remoteData = inData[p];
00180 int nRemote = remoteData.size()/dataSize;
00181
00182 for (int c=0; c<nRemote; c++)
00183 {
00184 Tabs tab2;
00185 int cellGID = remoteData[dataSize*c];
00186 int cellOwner = remoteData[dataSize*c+1];
00187 int cellLID = -1;
00188 bool elemIsOK = checkRemoteEntity(os, p, dim, cellGID,
00189 cellOwner, false, cellLID);
00190 if (cellLID >= 0 && elemIsOK)
00191 {
00192 int base = dataSize*c + 2;
00193 int k = 0;
00194 for (int d=0; d<dim; d++)
00195 {
00196 Tabs tab3;
00197 int dir;
00198 os << tab3 << "checking " << d << "-facets" << std::endl;
00199
00200
00201
00202
00203
00204
00205
00206 Sundance::Map<int, int> remoteFacetToOwnerMap;
00207 Sundance::Map<int, int> localFacetToOwnerMap;
00208 Sundance::Map<int, Set<int> > remoteFacetToNodesMap;
00209 Sundance::Map<int, Set<int> > localFacetToNodesMap;
00210
00211 for (int f=0; f<nFacets[d]; f++)
00212 {
00213
00214 int lfLID = facetLID(dim, cellLID, d, f, dir);
00215 int lfGID = mapLIDToGID(d, lfLID);
00216 int lfOwner = ownerProcID(d, lfLID);
00217 localFacetToOwnerMap.put(lfGID, lfOwner);
00218 int rfGID = remoteData[base + k++];
00219 int rfOwner = remoteData[base + k++];
00220 remoteFacetToOwnerMap.put(rfGID, rfOwner);
00221 if (d > 0)
00222 {
00223 int numNodes = numFacets(d, 0, 0);
00224 Sundance::Set<int> localNodes;
00225 Sundance::Set<int> remoteNodes;
00226 for (int v=0; v<numNodes; v++)
00227 {
00228 int nodeLID = facetLID(d, lfLID, 0, v, dir);
00229 int nodeGID = mapLIDToGID(0, nodeLID);
00230 localNodes.put(nodeGID);
00231 int remoteNodeGID = remoteData[base + k++];
00232 remoteNodes.put(remoteNodeGID);
00233 }
00234 localFacetToNodesMap.put(lfGID, localNodes);
00235 remoteFacetToNodesMap.put(rfGID, remoteNodes);
00236 }
00237 }
00238
00239
00240 for (Sundance::Map<int,int>::const_iterator
00241 rf=remoteFacetToOwnerMap.begin(),
00242 lf=localFacetToOwnerMap.begin();
00243 rf != remoteFacetToOwnerMap.end();
00244 rf++, lf++)
00245 {
00246 int lfGID = lf->first;
00247 int lfOwner = lf->second;
00248 int rfGID = lf->first;
00249 int rfOwner = lf->second;
00250 Tabs tab4;
00251 os << tab4 << " local facet GID=" << lfGID
00252 << " remote GID=" << rfGID
00253 << " local Own=" << lfOwner
00254 << " remote Own=" << rfOwner << std::endl;
00255 elemIsOK = testIdentity(os, rfGID, lfGID,
00256 "facet GIDs") && elemIsOK;
00257 elemIsOK = testIdentity(os, rfOwner,
00258 lfOwner,
00259 "facet owners") && elemIsOK;
00260
00261 if (d > 0)
00262 {
00263 Tabs tab5;
00264
00265 const Set<int>& localNodes =
00266 localFacetToNodesMap.get(lfGID);
00267 const Set<int>& remoteNodes =
00268 remoteFacetToNodesMap.get(rfGID);
00269 elemIsOK = testIdentity(os, localNodes.elements(),
00270 remoteNodes.elements(),
00271 "facet nodes") && elemIsOK;
00272 os << tab5 << "facet node GIDs: local="
00273 << localNodes << " remote="
00274 << remoteNodes << std::endl;
00275 }
00276 }
00277 }
00278 }
00279
00280 elemsAreOK = elemsAreOK && elemIsOK;
00281 }
00282 }
00283
00284 return elemsAreOK;
00285 }
00286
00287 bool Mesh::testIdentity(std::ostream& os, int a, int b, const std::string& msg) const
00288 {
00289 Tabs tab;
00290 if (a != b)
00291 {
00292 os << tab << "CONFLICT in " << msg << std::endl;
00293 return false;
00294 }
00295 return true;
00296 }
00297
00298 bool Mesh::testIdentity(std::ostream& os,
00299 const Array<int>& a,
00300 const Array<int>& b, const std::string& msg) const
00301 {
00302 Tabs tab;
00303 bool ok = true;
00304 for (int i=0; i<a.size(); i++)
00305 {
00306 if (a[i] != b[i]) ok = false;
00307 }
00308 if (!ok)
00309 {
00310 os << tab << "CONFLICT in " << msg << std::endl;
00311 }
00312 return ok;
00313 }
00314
00315 bool Mesh::checkRemoteEntity(std::ostream& os, int p, int dim, int gid, int owner,
00316 bool mustExist, int& lid) const
00317 {
00318 Tabs tab;
00319 bool isOK = true;
00320
00321 int myRank = comm().getRank();
00322 lid = -1;
00323
00324 if (hasGID(dim, gid))
00325 {
00326 lid = mapGIDToLID(dim, gid);
00327 os << tab << "p=" << myRank << " got "
00328 << dim << "-cell GID=" << gid << " from proc=" << p
00329 << ", is LID=" << lid << " locally" << std::endl;
00330 }
00331 else
00332 {
00333 os << tab << "p=" << myRank << " got " << dim << "-cell GID=" << gid
00334 << " from proc=" << p << ", doesn't exist locally" << std::endl;
00335 if (mustExist) isOK = false;
00336 }
00337
00338 if (lid >= 0)
00339 {
00340 int localOwner = ownerProcID(dim, lid);
00341 os << tab << dim << "-cell GID=" << gid
00342 << " is locally LID=" << lid << " and owned by "
00343 << localOwner << std::endl;
00344 if (localOwner != owner)
00345 {
00346 os << tab << "OWNERSHIP CONFLICT: local p=" << myRank
00347 << " thinks " << dim << "-cell GID=" << gid << " is owned by "
00348 << localOwner << " but remote proc=" << p
00349 << " says it's owned by " << owner << std::endl;
00350 isOK = false;
00351 }
00352 }
00353
00354 return isOK;
00355
00356 }
00357
00358
00359
00360 bool Mesh::checkVertexConsistency(std::ostream& os) const
00361 {
00362 int dim = spatialDim();
00363 int myRank = comm().getRank();
00364 int nProcs = comm().getNProc();
00365 std::string pHdr = "p=" + Teuchos::toString(myRank);
00366
00367 Out::println(pHdr + " testing consistency of vertices");
00368
00369 int dataSize = 2;
00370 Array<int> vertData(dataSize*numCells(0));
00371 Array<double> vertPositions(numCells(0)*dim);
00372 for (int v=0; v<numCells(0); v++)
00373 {
00374 vertData[dataSize*v] = mapLIDToGID(0, v);
00375 vertData[dataSize*v + 1] = ownerProcID(0, v);
00376 Point x = nodePosition(v);
00377 for (int j=0; j<dim; j++)
00378 {
00379 vertPositions[dim*v + j] = x[j];
00380 }
00381 }
00382
00383
00384
00385 Array<Array<int> > outData(nProcs);
00386 Array<Array<double> > outPos(nProcs);
00387 for (int p=0; p<nProcs; p++)
00388 {
00389 outData[p] = vertData;
00390 outPos[p] = vertPositions;
00391 }
00392
00393 Array<Array<int> > inData(nProcs);
00394 Array<Array<double> > inPos(nProcs);
00395
00396 MPIContainerComm<int>::allToAll(outData,
00397 inData,
00398 comm());
00399
00400 MPIContainerComm<double>::allToAll(outPos, inPos, comm());
00401
00402 double tol = 1.0e-15;
00403
00404 bool ok = true;
00405 bool allVertsOK = true;
00406
00407
00408 for (int p=0; p<nProcs; p++)
00409 {
00410 Tabs tab1;
00411 if (p==myRank) continue;
00412
00413 os << tab1 << "p=" << myRank << " testing vertices from remote p="
00414 << p << std::endl;
00415
00416 int nVerts = inData[p].size()/dataSize;
00417
00418 for (int v=0; v<nVerts; v++)
00419 {
00420 Tabs tab2;
00421 int vertGID = inData[p][v*dataSize];
00422 int vertOwner = inData[p][v*dataSize+1];
00423 int vertLID = -1;
00424 bool vertIsOK = checkRemoteEntity(os, p, 0, vertGID, vertOwner,
00425 false, vertLID);
00426
00427 if (vertLID >= 0)
00428 {
00429 Point localX = nodePosition(vertLID);
00430
00431 Point remoteX = localX;
00432 for (int j=0; j<dim; j++) remoteX[j] = inPos[p][dim*v + j];
00433 double dx = remoteX.distance(localX);
00434 if (dx > tol)
00435 {
00436 os << tab2 << "POSITION CONFLICT: local p=" << myRank
00437 << " thinks GID=" << vertGID << " is at xLocal="
00438 << localX << " but remote proc=" << p
00439 << " says it's at xRemote" << remoteX << std::endl;
00440 os << tab2 << "distance = " << dx << std::endl;
00441 vertIsOK = false;
00442 }
00443 }
00444 allVertsOK = vertIsOK && allVertsOK;
00445 if (vertIsOK)
00446 {
00447 os << tab2 << "p=" << myRank
00448 << " says vertex GID=" << vertGID << " is OK" << std::endl;
00449 }
00450 }
00451 }
00452
00453 if (allVertsOK)
00454 {
00455 os << "p=" << myRank << " found all vertex data is OK" << std::endl;
00456 }
00457 else
00458 {
00459 os << "p=" << myRank << " detected conflicts in vertex data" << std::endl;
00460 }
00461
00462 ok = allVertsOK && ok;
00463
00464
00465
00466 return ok;
00467 }
00468