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 #include "polyBoundaryMesh.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <OpenFOAM/primitiveMesh.H>
00029 #include <OpenFOAM/processorPolyPatch.H>
00030 #include <OpenFOAM/stringListOps.H>
00031
00032
00033
00034 defineTypeNameAndDebug(Foam::polyBoundaryMesh, 0);
00035
00036
00037
00038
00039 Foam::labelList Foam::polyBoundaryMesh::ident(const label len)
00040 {
00041 labelList elems(len);
00042 forAll(elems, elemI)
00043 {
00044 elems[elemI] = elemI;
00045 }
00046 return elems;
00047 }
00048
00049
00050
00051
00052 Foam::polyBoundaryMesh::polyBoundaryMesh
00053 (
00054 const IOobject& io,
00055 const polyMesh& mesh
00056 )
00057 :
00058 polyPatchList(),
00059 regIOobject(io),
00060 mesh_(mesh),
00061 neighbourEdgesPtr_(NULL)
00062 {
00063 if (readOpt() == IOobject::MUST_READ)
00064 {
00065 polyPatchList& patches = *this;
00066
00067
00068 Istream& is = readStream(typeName);
00069
00070 PtrList<entry> patchEntries(is);
00071 patches.setSize(patchEntries.size());
00072
00073 forAll(patches, patchI)
00074 {
00075 patches.set
00076 (
00077 patchI,
00078 polyPatch::New
00079 (
00080 patchEntries[patchI].keyword(),
00081 patchEntries[patchI].dict(),
00082 patchI,
00083 *this
00084 )
00085 );
00086 }
00087
00088
00089 is.check
00090 (
00091 "polyBoundaryMesh::polyBoundaryMesh"
00092 "(const IOobject&, const polyMesh&)"
00093 );
00094
00095 close();
00096 }
00097 }
00098
00099
00100 Foam::polyBoundaryMesh::polyBoundaryMesh
00101 (
00102 const IOobject& io,
00103 const polyMesh& pm,
00104 const label size
00105 )
00106 :
00107 polyPatchList(size),
00108 regIOobject(io),
00109 mesh_(pm),
00110 neighbourEdgesPtr_(NULL)
00111 {}
00112
00113
00114
00115
00116 Foam::polyBoundaryMesh::~polyBoundaryMesh()
00117 {
00118 deleteDemandDrivenData(neighbourEdgesPtr_);
00119 }
00120
00121
00122 void Foam::polyBoundaryMesh::clearGeom()
00123 {
00124 forAll (*this, patchi)
00125 {
00126 operator[](patchi).clearGeom();
00127 }
00128 }
00129
00130
00131 void Foam::polyBoundaryMesh::clearAddressing()
00132 {
00133 deleteDemandDrivenData(neighbourEdgesPtr_);
00134
00135 forAll (*this, patchi)
00136 {
00137 operator[](patchi).clearAddressing();
00138 }
00139 }
00140
00141
00142
00143
00144 void Foam::polyBoundaryMesh::calcGeometry()
00145 {
00146 forAll(*this, patchi)
00147 {
00148 operator[](patchi).initGeometry();
00149 }
00150
00151 forAll(*this, patchi)
00152 {
00153 operator[](patchi).calcGeometry();
00154 }
00155 }
00156
00157
00158 const Foam::List<Foam::labelPairList>&
00159 Foam::polyBoundaryMesh::neighbourEdges() const
00160 {
00161 if (Pstream::parRun())
00162 {
00163 WarningIn("polyBoundaryMesh::neighbourEdges() const")
00164 << "Neighbour edge addressing not correct across parallel"
00165 << " boundaries." << endl;
00166 }
00167
00168 if (!neighbourEdgesPtr_)
00169 {
00170 neighbourEdgesPtr_ = new List<labelPairList>(size());
00171 List<labelPairList>& neighbourEdges = *neighbourEdgesPtr_;
00172
00173
00174 label nEdgePairs = 0;
00175 forAll(*this, patchi)
00176 {
00177 const polyPatch& pp = operator[](patchi);
00178
00179 neighbourEdges[patchi].setSize(pp.nEdges() - pp.nInternalEdges());
00180
00181 forAll(neighbourEdges[patchi], i)
00182 {
00183 labelPair& edgeInfo = neighbourEdges[patchi][i];
00184
00185 edgeInfo[0] = -1;
00186 edgeInfo[1] = -1;
00187 }
00188
00189 nEdgePairs += pp.nEdges() - pp.nInternalEdges();
00190 }
00191
00192
00193
00194 HashTable<labelPair, edge, Hash<edge> > pointsToEdge(nEdgePairs);
00195
00196 forAll(*this, patchi)
00197 {
00198 const polyPatch& pp = operator[](patchi);
00199
00200 const edgeList& edges = pp.edges();
00201
00202 for
00203 (
00204 label edgei = pp.nInternalEdges();
00205 edgei < edges.size();
00206 edgei++
00207 )
00208 {
00209
00210 const edge& e = edges[edgei];
00211
00212
00213 edge meshEdge(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
00214
00215 HashTable<labelPair, edge, Hash<edge> >::iterator fnd =
00216 pointsToEdge.find(meshEdge);
00217
00218 if (fnd == pointsToEdge.end())
00219 {
00220
00221
00222 pointsToEdge.insert
00223 (
00224 meshEdge,
00225 labelPair
00226 (
00227 patchi,
00228 edgei - pp.nInternalEdges()
00229 )
00230 );
00231 }
00232 else
00233 {
00234
00235 const labelPair& edgeInfo = fnd();
00236
00237 neighbourEdges[patchi][edgei - pp.nInternalEdges()] =
00238 edgeInfo;
00239
00240 neighbourEdges[edgeInfo[0]][edgeInfo[1]]
00241 = labelPair(patchi, edgei - pp.nInternalEdges());
00242
00243
00244
00245
00246 pointsToEdge.erase(meshEdge);
00247 }
00248 }
00249 }
00250
00251 if (pointsToEdge.size())
00252 {
00253 FatalErrorIn("polyBoundaryMesh::neighbourEdges() const")
00254 << "Not all boundary edges of patches match up." << nl
00255 << "Is the outside of your mesh multiply connected?"
00256 << abort(FatalError);
00257 }
00258
00259 forAll(*this, patchi)
00260 {
00261 const polyPatch& pp = operator[](patchi);
00262
00263 const labelPairList& nbrEdges = neighbourEdges[patchi];
00264
00265 forAll(nbrEdges, i)
00266 {
00267 const labelPair& edgeInfo = nbrEdges[i];
00268
00269 if (edgeInfo[0] == -1 || edgeInfo[1] == -1)
00270 {
00271 label edgeI = pp.nInternalEdges() + i;
00272 const edge& e = pp.edges()[edgeI];
00273
00274 FatalErrorIn("polyBoundaryMesh::neighbourEdges() const")
00275 << "Not all boundary edges of patches match up." << nl
00276 << "Edge " << edgeI << " on patch " << pp.name()
00277 << " end points " << pp.localPoints()[e[0]] << ' '
00278 << pp.localPoints()[e[1]] << " is not matched to an"
00279 << " edge on any other patch." << nl
00280 << "Is the outside of your mesh multiply connected?"
00281 << abort(FatalError);
00282 }
00283 }
00284 }
00285 }
00286
00287 return *neighbourEdgesPtr_;
00288 }
00289
00290
00291 Foam::wordList Foam::polyBoundaryMesh::names() const
00292 {
00293 const polyPatchList& patches = *this;
00294
00295 wordList t(patches.size());
00296
00297 forAll (patches, patchI)
00298 {
00299 t[patchI] = patches[patchI].name();
00300 }
00301
00302 return t;
00303 }
00304
00305
00306 Foam::wordList Foam::polyBoundaryMesh::types() const
00307 {
00308 const polyPatchList& patches = *this;
00309
00310 wordList t(patches.size());
00311
00312 forAll (patches, patchI)
00313 {
00314 t[patchI] = patches[patchI].type();
00315 }
00316
00317 return t;
00318 }
00319
00320
00321 Foam::wordList Foam::polyBoundaryMesh::physicalTypes() const
00322 {
00323 const polyPatchList& patches = *this;
00324
00325 wordList t(patches.size());
00326
00327 forAll (patches, patchI)
00328 {
00329 t[patchI] = patches[patchI].physicalType();
00330 }
00331
00332 return t;
00333 }
00334
00335
00336 Foam::label Foam::polyBoundaryMesh::findPatchID(const word& patchName) const
00337 {
00338 const polyPatchList& patches = *this;
00339
00340 forAll (patches, patchI)
00341 {
00342 if (patches[patchI].name() == patchName)
00343 {
00344 return patchI;
00345 }
00346 }
00347
00348
00349 if (debug)
00350 {
00351 Pout<< "label polyBoundaryMesh::findPatchID(const word& "
00352 << "patchName) const"
00353 << "Patch named " << patchName << " not found. "
00354 << "List of available patch names: " << names() << endl;
00355 }
00356
00357
00358 return -1;
00359 }
00360
00361
00362 Foam::label Foam::polyBoundaryMesh::whichPatch(const label faceIndex) const
00363 {
00364
00365
00366
00367
00368 if (faceIndex >= mesh().nFaces())
00369 {
00370 FatalErrorIn
00371 (
00372 "polyBoundaryMesh::whichPatch(const label faceIndex) const"
00373 ) << "given label greater than the number of geometric faces"
00374 << abort(FatalError);
00375 }
00376
00377 if (faceIndex < mesh().nInternalFaces())
00378 {
00379 return -1;
00380 }
00381
00382 forAll (*this, patchI)
00383 {
00384 const polyPatch& bp = operator[](patchI);
00385
00386 if
00387 (
00388 faceIndex >= bp.start()
00389 && faceIndex < bp.start() + bp.size()
00390 )
00391 {
00392 return patchI;
00393 }
00394 }
00395
00396
00397 FatalErrorIn
00398 (
00399 "label polyBoundaryMesh::whichPatch(const label faceIndex) const"
00400 ) << "Cannot find face " << faceIndex << " in any of the patches "
00401 << names() << nl
00402 << "It seems your patches are not consistent with the mesh :"
00403 << " internalFaces:" << mesh().nInternalFaces()
00404 << " total number of faces:" << mesh().nFaces()
00405 << abort(FatalError);
00406
00407 return -1;
00408 }
00409
00410
00411 Foam::labelHashSet Foam::polyBoundaryMesh::patchSet
00412 (
00413 const wordList& patchNames
00414 ) const
00415 {
00416 wordList allPatchNames = names();
00417 labelHashSet ps(size());
00418
00419 forAll(patchNames, i)
00420 {
00421
00422
00423 labelList patchIDs = findStrings(patchNames[i], allPatchNames);
00424
00425 if (patchIDs.empty())
00426 {
00427 WarningIn("polyBoundaryMesh::patchSet(const wordList&)")
00428 << "Cannot find any patch names matching " << patchNames[i]
00429 << endl;
00430 }
00431
00432 forAll(patchIDs, j)
00433 {
00434 ps.insert(patchIDs[j]);
00435 }
00436 }
00437
00438 return ps;
00439 }
00440
00441
00442 bool Foam::polyBoundaryMesh::checkParallelSync(const bool report) const
00443 {
00444 if (!Pstream::parRun())
00445 {
00446 return false;
00447 }
00448
00449
00450 const polyBoundaryMesh& bm = *this;
00451
00452 bool boundaryError = false;
00453
00454
00455 wordList names(bm.size());
00456 wordList types(bm.size());
00457
00458 label nonProcI = 0;
00459
00460 forAll (bm, patchI)
00461 {
00462 if (!isA<processorPolyPatch>(bm[patchI]))
00463 {
00464 if (nonProcI != patchI)
00465 {
00466
00467 boundaryError = true;
00468
00469 if (debug || report)
00470 {
00471 Pout<< " ***Problem with boundary patch " << patchI
00472 << " named " << bm[patchI].name()
00473 << " of type " << bm[patchI].type()
00474 << ". The patch seems to be preceded by processor"
00475 << " patches. This is can give problems."
00476 << endl;
00477 }
00478 }
00479 else
00480 {
00481 names[nonProcI] = bm[patchI].name();
00482 types[nonProcI] = bm[patchI].type();
00483 nonProcI++;
00484 }
00485 }
00486 }
00487 names.setSize(nonProcI);
00488 types.setSize(nonProcI);
00489
00490 List<wordList> allNames(Pstream::nProcs());
00491 allNames[Pstream::myProcNo()] = names;
00492 Pstream::gatherList(allNames);
00493 Pstream::scatterList(allNames);
00494
00495 List<wordList> allTypes(Pstream::nProcs());
00496 allTypes[Pstream::myProcNo()] = types;
00497 Pstream::gatherList(allTypes);
00498 Pstream::scatterList(allTypes);
00499
00500
00501
00502 for (label procI = 1; procI < allNames.size(); procI++)
00503 {
00504 if
00505 (
00506 (allNames[procI] != allNames[0])
00507 || (allTypes[procI] != allTypes[0])
00508 )
00509 {
00510 boundaryError = true;
00511
00512 if (debug || (report && Pstream::master()))
00513 {
00514 Info<< " ***Inconsistent patches across processors, "
00515 "processor 0 has patch names:" << allNames[0]
00516 << " patch types:" << allTypes[0]
00517 << " processor " << procI << " has patch names:"
00518 << allNames[procI]
00519 << " patch types:" << allTypes[procI]
00520 << endl;
00521 }
00522 }
00523 }
00524
00525 return boundaryError;
00526 }
00527
00528
00529 bool Foam::polyBoundaryMesh::checkDefinition(const bool report) const
00530 {
00531 label nextPatchStart = mesh().nInternalFaces();
00532 const polyBoundaryMesh& bm = *this;
00533
00534 bool boundaryError = false;
00535
00536 forAll (bm, patchI)
00537 {
00538 if (bm[patchI].start() != nextPatchStart && !boundaryError)
00539 {
00540 boundaryError = true;
00541
00542 Info<< " ****Problem with boundary patch " << patchI
00543 << " named " << bm[patchI].name()
00544 << " of type " << bm[patchI].type()
00545 << ". The patch should start on face no " << nextPatchStart
00546 << " and the patch specifies " << bm[patchI].start()
00547 << "." << endl
00548 << "Possibly consecutive patches have this same problem."
00549 << " Suppressing future warnings." << endl;
00550 }
00551
00552 nextPatchStart += bm[patchI].size();
00553 }
00554
00555 reduce(boundaryError, orOp<bool>());
00556
00557 if (boundaryError)
00558 {
00559 if (debug || report)
00560 {
00561 Pout << " ***Boundary definition is in error." << endl;
00562 }
00563
00564 return true;
00565 }
00566 else
00567 {
00568 if (debug || report)
00569 {
00570 Info << " Boundary definition OK." << endl;
00571 }
00572
00573 return false;
00574 }
00575 }
00576
00577
00578 void Foam::polyBoundaryMesh::movePoints(const pointField& p)
00579 {
00580 polyPatchList& patches = *this;
00581
00582 forAll(patches, patchi)
00583 {
00584 patches[patchi].initMovePoints(p);
00585 }
00586
00587 forAll(patches, patchi)
00588 {
00589 patches[patchi].movePoints(p);
00590 }
00591 }
00592
00593
00594 void Foam::polyBoundaryMesh::updateMesh()
00595 {
00596 deleteDemandDrivenData(neighbourEdgesPtr_);
00597
00598 polyPatchList& patches = *this;
00599
00600 forAll(patches, patchi)
00601 {
00602 patches[patchi].initUpdateMesh();
00603 }
00604
00605 forAll(patches, patchi)
00606 {
00607 patches[patchi].updateMesh();
00608 }
00609 }
00610
00611
00612 void Foam::polyBoundaryMesh::reorder(const UList<label>& oldToNew)
00613 {
00614
00615 polyPatchList::reorder(oldToNew);
00616
00617
00618 polyPatchList& patches = *this;
00619
00620 forAll(patches, patchi)
00621 {
00622 patches[patchi].index() = patchi;
00623 }
00624
00625 updateMesh();
00626 }
00627
00628
00629 bool Foam::polyBoundaryMesh::writeData(Ostream& os) const
00630 {
00631 const polyPatchList& patches = *this;
00632
00633 os << patches.size() << nl << token::BEGIN_LIST << incrIndent << nl;
00634
00635 forAll(patches, patchi)
00636 {
00637 os << indent << patches[patchi].name() << nl
00638 << indent << token::BEGIN_BLOCK << nl
00639 << incrIndent << patches[patchi] << decrIndent
00640 << indent << token::END_BLOCK << endl;
00641 }
00642
00643 os << decrIndent << token::END_LIST;
00644
00645
00646 os.check("polyBoundaryMesh::writeData(Ostream& os) const");
00647
00648 return os.good();
00649 }
00650
00651
00652 bool Foam::polyBoundaryMesh::writeObject
00653 (
00654 IOstream::streamFormat fmt,
00655 IOstream::versionNumber ver,
00656 IOstream::compressionType cmp
00657 ) const
00658 {
00659 return regIOobject::writeObject(fmt, ver, IOstream::UNCOMPRESSED);
00660 }
00661
00662
00663
00664
00665 Foam::Ostream& Foam::operator<<(Ostream& os, const polyBoundaryMesh& pbm)
00666 {
00667 pbm.writeData(os);
00668 return os;
00669 }
00670
00671
00672