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