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