DOC: Spelling in freefoam.1.in.txt
[freefoam.git] / src / OpenFOAM / meshes / polyMesh / polyBoundaryMesh / polyBoundaryMesh.C
blobfd6cbcce74b040a1b441761d8d3984ebd7f9b410
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "polyBoundaryMesh.H"
27 #include <OpenFOAM/polyMesh.H>
28 #include <OpenFOAM/primitiveMesh.H>
29 #include <OpenFOAM/processorPolyPatch.H>
30 #include <OpenFOAM/stringListOps.H>
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 defineTypeNameAndDebug(Foam::polyBoundaryMesh, 0);
37 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
39 Foam::labelList Foam::polyBoundaryMesh::ident(const label len)
41     labelList elems(len);
42     forAll(elems, elemI)
43     {
44         elems[elemI] = elemI;
45     }
46     return elems;
50 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
52 Foam::polyBoundaryMesh::polyBoundaryMesh
54     const IOobject& io,
55     const polyMesh& mesh
58     polyPatchList(),
59     regIOobject(io),
60     mesh_(mesh),
61     neighbourEdgesPtr_(NULL)
63     if (readOpt() == IOobject::MUST_READ)
64     {
65         polyPatchList& patches = *this;
67         // Read polyPatchList
68         Istream& is = readStream(typeName);
70         PtrList<entry> patchEntries(is);
71         patches.setSize(patchEntries.size());
73         forAll(patches, patchI)
74         {
75             patches.set
76             (
77                 patchI,
78                 polyPatch::New
79                 (
80                     patchEntries[patchI].keyword(),
81                     patchEntries[patchI].dict(),
82                     patchI,
83                     *this
84                 )
85             );
86         }
88         // Check state of IOstream
89         is.check
90         (
91             "polyBoundaryMesh::polyBoundaryMesh"
92             "(const IOobject&, const polyMesh&)"
93         );
95         close();
96     }
100 Foam::polyBoundaryMesh::polyBoundaryMesh
102     const IOobject& io,
103     const polyMesh& pm,
104     const label size
107     polyPatchList(size),
108     regIOobject(io),
109     mesh_(pm),
110     neighbourEdgesPtr_(NULL)
114 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
116 Foam::polyBoundaryMesh::~polyBoundaryMesh()
118     deleteDemandDrivenData(neighbourEdgesPtr_);
122 void Foam::polyBoundaryMesh::clearGeom()
124     forAll (*this, patchi)
125     {
126         operator[](patchi).clearGeom();
127     }
131 void Foam::polyBoundaryMesh::clearAddressing()
133     deleteDemandDrivenData(neighbourEdgesPtr_);
135     forAll (*this, patchi)
136     {
137         operator[](patchi).clearAddressing();
138     }
142 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
144 void Foam::polyBoundaryMesh::calcGeometry()
146     forAll(*this, patchi)
147     {
148         operator[](patchi).initGeometry();
149     }
151     forAll(*this, patchi)
152     {
153         operator[](patchi).calcGeometry();
154     }
158 const Foam::List<Foam::labelPairList>&
159 Foam::polyBoundaryMesh::neighbourEdges() const
161     if (Pstream::parRun())
162     {
163         WarningIn("polyBoundaryMesh::neighbourEdges() const")
164             << "Neighbour edge addressing not correct across parallel"
165             << " boundaries." << endl;
166     }
168     if (!neighbourEdgesPtr_)
169     {
170         neighbourEdgesPtr_ = new List<labelPairList>(size());
171         List<labelPairList>& neighbourEdges = *neighbourEdgesPtr_;
173         // Initialize.
174         label nEdgePairs = 0;
175         forAll(*this, patchi)
176         {
177             const polyPatch& pp = operator[](patchi);
179             neighbourEdges[patchi].setSize(pp.nEdges() - pp.nInternalEdges());
181             forAll(neighbourEdges[patchi], i)
182             {
183                 labelPair& edgeInfo = neighbourEdges[patchi][i];
185                 edgeInfo[0] = -1;
186                 edgeInfo[1] = -1;
187             }
189             nEdgePairs += pp.nEdges() - pp.nInternalEdges();
190         }
192         // From mesh edge (expressed as a point pair so as not to construct
193         // point addressing) to patch + relative edge index.
194         HashTable<labelPair, edge, Hash<edge> > pointsToEdge(nEdgePairs);
196         forAll(*this, patchi)
197         {
198             const polyPatch& pp = operator[](patchi);
200             const edgeList& edges = pp.edges();
202             for
203             (
204                 label edgei = pp.nInternalEdges();
205                 edgei < edges.size();
206                 edgei++
207             )
208             {
209                 // Edge in patch local points
210                 const edge& e = edges[edgei];
212                 // Edge in mesh points.
213                 edge meshEdge(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
215                 HashTable<labelPair, edge, Hash<edge> >::iterator fnd =
216                     pointsToEdge.find(meshEdge);
218                 if (fnd == pointsToEdge.end())
219                 {
220                     // First occurrence of mesh edge. Store patch and my
221                     // local index.
222                     pointsToEdge.insert
223                     (
224                         meshEdge,
225                         labelPair
226                         (
227                             patchi,
228                             edgei - pp.nInternalEdges()
229                         )
230                     );
231                 }
232                 else
233                 {
234                     // Second occurrence. Store.
235                     const labelPair& edgeInfo = fnd();
237                     neighbourEdges[patchi][edgei - pp.nInternalEdges()] =
238                         edgeInfo;
240                     neighbourEdges[edgeInfo[0]][edgeInfo[1]]
241                          = labelPair(patchi, edgei - pp.nInternalEdges());
243                     // Found all two occurrences of this edge so remove from
244                     // hash to save space. Note that this will give lots of
245                     // problems if the polyBoundaryMesh is multiply connected.
246                     pointsToEdge.erase(meshEdge);
247                 }
248             }
249         }
251         if (pointsToEdge.size())
252         {
253             FatalErrorIn("polyBoundaryMesh::neighbourEdges() const")
254                 << "Not all boundary edges of patches match up." << nl
255                 << "Is the outside of your mesh multiply connected?"
256                 << abort(FatalError);
257         }
259         forAll(*this, patchi)
260         {
261             const polyPatch& pp = operator[](patchi);
263             const labelPairList& nbrEdges = neighbourEdges[patchi];
265             forAll(nbrEdges, i)
266             {
267                 const labelPair& edgeInfo = nbrEdges[i];
269                 if (edgeInfo[0] == -1 || edgeInfo[1] == -1)
270                 {
271                     label edgeI = pp.nInternalEdges() + i;
272                     const edge& e = pp.edges()[edgeI];
274                     FatalErrorIn("polyBoundaryMesh::neighbourEdges() const")
275                         << "Not all boundary edges of patches match up." << nl
276                         << "Edge " << edgeI << " on patch " << pp.name()
277                         << " end points " << pp.localPoints()[e[0]] << ' '
278                         << pp.localPoints()[e[1]] << " is not matched to an"
279                         << " edge on any other patch." << nl
280                         << "Is the outside of your mesh multiply connected?"
281                         << abort(FatalError);
282                 }
283             }
284         }
285     }
287     return *neighbourEdgesPtr_;
291 Foam::wordList Foam::polyBoundaryMesh::names() const
293     const polyPatchList& patches = *this;
295     wordList t(patches.size());
297     forAll (patches, patchI)
298     {
299         t[patchI] = patches[patchI].name();
300     }
302     return t;
306 Foam::wordList Foam::polyBoundaryMesh::types() const
308     const polyPatchList& patches = *this;
310     wordList t(patches.size());
312     forAll (patches, patchI)
313     {
314         t[patchI] = patches[patchI].type();
315     }
317     return t;
321 Foam::wordList Foam::polyBoundaryMesh::physicalTypes() const
323     const polyPatchList& patches = *this;
325     wordList t(patches.size());
327     forAll (patches, patchI)
328     {
329         t[patchI] = patches[patchI].physicalType();
330     }
332     return t;
336 Foam::label Foam::polyBoundaryMesh::findPatchID(const word& patchName) const
338     const polyPatchList& patches = *this;
340     forAll (patches, patchI)
341     {
342         if (patches[patchI].name() == patchName)
343         {
344             return patchI;
345         }
346     }
348     // Patch not found
349     if (debug)
350     {
351         Pout<< "label polyBoundaryMesh::findPatchID(const word& "
352             << "patchName) const"
353             << "Patch named " << patchName << " not found.  "
354             << "List of available patch names: " << names() << endl;
355     }
357     // Not found, return -1
358     return -1;
362 Foam::label Foam::polyBoundaryMesh::whichPatch(const label faceIndex) const
364     // Find out which patch the current face belongs to by comparing label
365     // with patch start labels.
366     // If the face is internal, return -1;
367     // if it is off the end of the list, abort
368     if (faceIndex >= mesh().nFaces())
369     {
370         FatalErrorIn
371         (
372             "polyBoundaryMesh::whichPatch(const label faceIndex) const"
373         )   << "given label greater than the number of geometric faces"
374             << abort(FatalError);
375     }
377     if (faceIndex < mesh().nInternalFaces())
378     {
379         return -1;
380     }
382     forAll (*this, patchI)
383     {
384         const polyPatch& bp = operator[](patchI);
386         if
387         (
388             faceIndex >= bp.start()
389          && faceIndex < bp.start() + bp.size()
390         )
391         {
392             return patchI;
393         }
394     }
396     // If not in any of above, it is trouble!
397     FatalErrorIn
398     (
399         "label polyBoundaryMesh::whichPatch(const label faceIndex) const"
400     )   << "Cannot find face " << faceIndex << " in any of the patches "
401         << names() << nl
402         << "It seems your patches are not consistent with the mesh :"
403         << " internalFaces:" << mesh().nInternalFaces()
404         << "  total number of faces:" << mesh().nFaces()
405         << abort(FatalError);
407     return -1;
411 Foam::labelHashSet Foam::polyBoundaryMesh::patchSet
413     const wordList& patchNames
414 ) const
416     wordList allPatchNames = names();
417     labelHashSet ps(size());
419     forAll(patchNames, i)
420     {
421         // Treat the given patch names as wild-cards and search the set
422         // of all patch names for matches
423         labelList patchIDs = findStrings(patchNames[i], allPatchNames);
425         if (patchIDs.empty())
426         {
427             WarningIn("polyBoundaryMesh::patchSet(const wordList&)")
428                 << "Cannot find any patch names matching " << patchNames[i]
429                 << endl;
430         }
432         forAll(patchIDs, j)
433         {
434             ps.insert(patchIDs[j]);
435         }
436     }
438     return ps;
442 bool Foam::polyBoundaryMesh::checkParallelSync(const bool report) const
444     if (!Pstream::parRun())
445     {
446         return false;
447     }
450     const polyBoundaryMesh& bm = *this;
452     bool boundaryError = false;
454     // Collect non-proc patches and check proc patches are last.
455     wordList names(bm.size());
456     wordList types(bm.size());
458     label nonProcI = 0;
460     forAll (bm, patchI)
461     {
462         if (!isA<processorPolyPatch>(bm[patchI]))
463         {
464             if (nonProcI != patchI)
465             {
466                 // There is processor patch inbetween normal patches.
467                 boundaryError = true;
469                 if (debug || report)
470                 {
471                     Pout<< " ***Problem with boundary patch " << patchI
472                         << " named " << bm[patchI].name()
473                         << " of type " <<  bm[patchI].type()
474                         << ". The patch seems to be preceded by processor"
475                         << " patches. This is can give problems."
476                         << endl;
477                 }
478             }
479             else
480             {
481                 names[nonProcI] = bm[patchI].name();
482                 types[nonProcI] = bm[patchI].type();
483                 nonProcI++;
484             }
485         }
486     }
487     names.setSize(nonProcI);
488     types.setSize(nonProcI);
490     List<wordList> allNames(Pstream::nProcs());
491     allNames[Pstream::myProcNo()] = names;
492     Pstream::gatherList(allNames);
493     Pstream::scatterList(allNames);
495     List<wordList> allTypes(Pstream::nProcs());
496     allTypes[Pstream::myProcNo()] = types;
497     Pstream::gatherList(allTypes);
498     Pstream::scatterList(allTypes);
500     // Have every processor check but only master print error.
502     for (label procI = 1; procI < allNames.size(); procI++)
503     {
504         if
505         (
506             (allNames[procI] != allNames[0])
507          || (allTypes[procI] != allTypes[0])
508         )
509         {
510             boundaryError = true;
512             if (debug || (report && Pstream::master()))
513             {
514                 Info<< " ***Inconsistent patches across processors, "
515                        "processor 0 has patch names:" << allNames[0]
516                     << " patch types:" << allTypes[0]
517                     << " processor " << procI << " has patch names:"
518                     << allNames[procI]
519                     << " patch types:" << allTypes[procI]
520                     << endl;
521             }
522         }
523     }
525     return boundaryError;
529 bool Foam::polyBoundaryMesh::checkDefinition(const bool report) const
531     label nextPatchStart = mesh().nInternalFaces();
532     const polyBoundaryMesh& bm = *this;
534     bool boundaryError = false;
536     forAll (bm, patchI)
537     {
538         if (bm[patchI].start() != nextPatchStart && !boundaryError)
539         {
540             boundaryError = true;
542             Info<< " ****Problem with boundary patch " << patchI
543                 << " named " << bm[patchI].name()
544                 << " of type " <<  bm[patchI].type()
545                 << ". The patch should start on face no " << nextPatchStart
546                 << " and the patch specifies " << bm[patchI].start()
547                 << "." << endl
548                 << "Possibly consecutive patches have this same problem."
549                 << " Suppressing future warnings." << endl;
550         }
552         nextPatchStart += bm[patchI].size();
553     }
555     reduce(boundaryError, orOp<bool>());
557     if (boundaryError)
558     {
559         if (debug || report)
560         {
561             Pout << " ***Boundary definition is in error." << endl;
562         }
564         return true;
565     }
566     else
567     {
568         if (debug || report)
569         {
570             Info << "    Boundary definition OK." << endl;
571         }
573         return false;
574     }
578 void Foam::polyBoundaryMesh::movePoints(const pointField& p)
580     polyPatchList& patches = *this;
582     forAll(patches, patchi)
583     {
584         patches[patchi].initMovePoints(p);
585     }
587     forAll(patches, patchi)
588     {
589         patches[patchi].movePoints(p);
590     }
594 void Foam::polyBoundaryMesh::updateMesh()
596     deleteDemandDrivenData(neighbourEdgesPtr_);
598     polyPatchList& patches = *this;
600     forAll(patches, patchi)
601     {
602         patches[patchi].initUpdateMesh();
603     }
605     forAll(patches, patchi)
606     {
607         patches[patchi].updateMesh();
608     }
612 void Foam::polyBoundaryMesh::reorder(const UList<label>& oldToNew)
614     // Change order of patches
615     polyPatchList::reorder(oldToNew);
617     // Adapt indices
618     polyPatchList& patches = *this;
620     forAll(patches, patchi)
621     {
622         patches[patchi].index() = patchi;
623     }
625     updateMesh();
629 bool Foam::polyBoundaryMesh::writeData(Ostream& os) const
631     const polyPatchList& patches = *this;
633     os  << patches.size() << nl << token::BEGIN_LIST << incrIndent << nl;
635     forAll(patches, patchi)
636     {
637         os  << indent << patches[patchi].name() << nl
638             << indent << token::BEGIN_BLOCK << nl
639             << incrIndent << patches[patchi] << decrIndent
640             << indent << token::END_BLOCK << endl;
641     }
643     os  << decrIndent << token::END_LIST;
645     // Check state of IOstream
646     os.check("polyBoundaryMesh::writeData(Ostream& os) const");
648     return os.good();
652 bool Foam::polyBoundaryMesh::writeObject
654     IOstream::streamFormat fmt,
655     IOstream::versionNumber ver,
656     IOstream::compressionType cmp
657 ) const
659     return regIOobject::writeObject(fmt, ver, IOstream::UNCOMPRESSED);
663 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
665 Foam::Ostream& Foam::operator<<(Ostream& os, const polyBoundaryMesh& pbm)
667     pbm.writeData(os);
668     return os;
672 // ************************ vim: set sw=4 sts=4 et: ************************ //