FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

polyBoundaryMesh.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
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 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00033 
00034 defineTypeNameAndDebug(Foam::polyBoundaryMesh, 0);
00035 
00036 
00037 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
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 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
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         // Read polyPatchList
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         // Check state of IOstream
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 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
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 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
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         // Initialize.
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         // From mesh edge (expressed as a point pair so as not to construct
00193         // point addressing) to patch + relative edge index.
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                 // Edge in patch local points
00210                 const edge& e = edges[edgei];
00211 
00212                 // Edge in mesh points.
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                     // First occurrence of mesh edge. Store patch and my
00221                     // local index.
00222                     pointsToEdge.insert
00223                     (
00224                         meshEdge,
00225                         labelPair
00226                         (
00227                             patchi,
00228                             edgei - pp.nInternalEdges()
00229                         )
00230                     );
00231                 }
00232                 else
00233                 {
00234                     // Second occurrence. Store.
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                     // Found all two occurrences of this edge so remove from
00244                     // hash to save space. Note that this will give lots of
00245                     // problems if the polyBoundaryMesh is multiply connected.
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     // Patch not found
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     // Not found, return -1
00358     return -1;
00359 }
00360 
00361 
00362 Foam::label Foam::polyBoundaryMesh::whichPatch(const label faceIndex) const
00363 {
00364     // Find out which patch the current face belongs to by comparing label
00365     // with patch start labels.
00366     // If the face is internal, return -1;
00367     // if it is off the end of the list, abort
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     // If not in any of above, it is trouble!
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         // Treat the given patch names as wild-cards and search the set
00422         // of all patch names for matches
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     // Collect non-proc patches and check proc patches are last.
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                 // There is processor patch inbetween normal patches.
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     // Have every processor check but only master print error.
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     // Change order of patches
00615     polyPatchList::reorder(oldToNew);
00616 
00617     // Adapt indices
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     // Check state of IOstream
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 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
00664 
00665 Foam::Ostream& Foam::operator<<(Ostream& os, const polyBoundaryMesh& pbm)
00666 {
00667     pbm.writeData(os);
00668     return os;
00669 }
00670 
00671 
00672 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines