polyBoundaryMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "polyBoundaryMesh.H"
27 #include "polyMesh.H"
28 #include "primitiveMesh.H"
29 #include "processorPolyPatch.H"
30 #include "stringListOps.H"
31 #include "PstreamBuffers.H"
32 #include "lduSchedule.H"
33 #include "globalMeshData.H"
34 #include "stringListOps.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 defineTypeNameAndDebug(polyBoundaryMesh, 0);
41 }
42 
43 
44 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
45 
46 Foam::polyBoundaryMesh::polyBoundaryMesh
47 (
48  const IOobject& io,
49  const polyMesh& mesh
50 )
51 :
52  polyPatchList(),
53  regIOobject(io),
54  mesh_(mesh)
55 {
56  if
57  (
58  readOpt() == IOobject::MUST_READ
59  || readOpt() == IOobject::MUST_READ_IF_MODIFIED
60  )
61  {
62  if (readOpt() == IOobject::MUST_READ_IF_MODIFIED)
63  {
64  WarningIn
65  (
66  "polyBoundaryMesh::polyBoundaryMesh\n"
67  "(\n"
68  " const IOobject&,\n"
69  " const polyMesh&\n"
70  ")"
71  ) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
72  << " does not support automatic rereading."
73  << endl;
74  }
75 
76 
77  polyPatchList& patches = *this;
78 
79  // Read polyPatchList
80  Istream& is = readStream(typeName);
81 
82  PtrList<entry> patchEntries(is);
83  patches.setSize(patchEntries.size());
84 
85  forAll(patches, patchI)
86  {
87  patches.set
88  (
89  patchI,
91  (
92  patchEntries[patchI].keyword(),
93  patchEntries[patchI].dict(),
94  patchI,
95  *this
96  )
97  );
98  }
99 
100  // Check state of IOstream
101  is.check
102  (
103  "polyBoundaryMesh::polyBoundaryMesh"
104  "(const IOobject&, const polyMesh&)"
105  );
106 
107  close();
108  }
109 }
110 
111 
112 Foam::polyBoundaryMesh::polyBoundaryMesh
113 (
114  const IOobject& io,
115  const polyMesh& pm,
116  const label size
117 )
118 :
119  polyPatchList(size),
120  regIOobject(io),
121  mesh_(pm)
122 {}
123 
124 
125 Foam::polyBoundaryMesh::polyBoundaryMesh
126 (
127  const IOobject& io,
128  const polyMesh& pm,
129  const polyPatchList& ppl
130 )
131 :
132  polyPatchList(),
133  regIOobject(io),
134  mesh_(pm)
135 {
136  if
137  (
138  (this->readOpt() == IOobject::READ_IF_PRESENT && this->headerOk())
139  || this->readOpt() == IOobject::MUST_READ
140  || this->readOpt() == IOobject::MUST_READ_IF_MODIFIED
141  )
142  {
143 
144  if (readOpt() == IOobject::MUST_READ_IF_MODIFIED)
145  {
146  WarningIn
147  (
148  "polyBoundaryMesh::polyBoundaryMesh\n"
149  "(\n"
150  " const IOobject&,\n"
151  " const polyMesh&\n"
152  " const polyPatchList&\n"
153  ")"
154  ) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
155  << " does not support automatic rereading."
156  << endl;
157  }
158 
159  polyPatchList& patches = *this;
160 
161  // Read polyPatchList
162  Istream& is = readStream(typeName);
163 
164  PtrList<entry> patchEntries(is);
165  patches.setSize(patchEntries.size());
166 
167  forAll(patches, patchI)
168  {
169  patches.set
170  (
171  patchI,
173  (
174  patchEntries[patchI].keyword(),
175  patchEntries[patchI].dict(),
176  patchI,
177  *this
178  )
179  );
180  }
181 
182  // Check state of IOstream
183  is.check
184  (
185  "polyBoundaryMesh::polyBoundaryMesh"
186  "(const IOobject&, const polyMesh&, const polyPatchList&)"
187  );
188 
189  close();
190  }
191  else
192  {
193  polyPatchList& patches = *this;
194  patches.setSize(ppl.size());
195  forAll (patches, patchI)
196  {
197  patches.set(patchI, ppl[patchI].clone(*this).ptr());
198  }
199  }
200 }
201 
202 
203 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
204 
206 {}
207 
208 
210 {
211  forAll(*this, patchI)
212  {
213  operator[](patchI).clearGeom();
214  }
215 }
216 
217 
219 {
220  neighbourEdgesPtr_.clear();
221  patchIDPtr_.clear();
222  groupPatchIDsPtr_.clear();
223 
224  forAll(*this, patchI)
225  {
226  operator[](patchI).clearAddressing();
227  }
228 }
229 
230 
231 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
232 
233 void Foam::polyBoundaryMesh::calcGeometry()
234 {
236 
237  if
238  (
241  )
242  {
243  forAll(*this, patchI)
244  {
245  operator[](patchI).initGeometry(pBufs);
246  }
247 
248  pBufs.finishedSends();
249 
250  forAll(*this, patchI)
251  {
252  operator[](patchI).calcGeometry(pBufs);
253  }
254  }
256  {
257  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
258 
259  // Dummy.
260  pBufs.finishedSends();
261 
262  forAll(patchSchedule, patchEvali)
263  {
264  const label patchI = patchSchedule[patchEvali].patch;
265 
266  if (patchSchedule[patchEvali].init)
267  {
268  operator[](patchI).initGeometry(pBufs);
269  }
270  else
271  {
272  operator[](patchI).calcGeometry(pBufs);
273  }
274  }
275  }
276 }
277 
278 
281 {
282  if (Pstream::parRun())
283  {
284  WarningIn("polyBoundaryMesh::neighbourEdges() const")
285  << "Neighbour edge addressing not correct across parallel"
286  << " boundaries." << endl;
287  }
288 
289  if (!neighbourEdgesPtr_.valid())
290  {
291  neighbourEdgesPtr_.reset(new List<labelPairList>(size()));
292  List<labelPairList>& neighbourEdges = neighbourEdgesPtr_();
293 
294  // Initialize.
295  label nEdgePairs = 0;
296  forAll(*this, patchI)
297  {
298  const polyPatch& pp = operator[](patchI);
299 
300  neighbourEdges[patchI].setSize(pp.nEdges() - pp.nInternalEdges());
301 
302  forAll(neighbourEdges[patchI], i)
303  {
304  labelPair& edgeInfo = neighbourEdges[patchI][i];
305 
306  edgeInfo[0] = -1;
307  edgeInfo[1] = -1;
308  }
309 
310  nEdgePairs += pp.nEdges() - pp.nInternalEdges();
311  }
312 
313  // From mesh edge (expressed as a point pair so as not to construct
314  // point addressing) to patch + relative edge index.
315  HashTable<labelPair, edge, Hash<edge> > pointsToEdge(nEdgePairs);
316 
317  forAll(*this, patchI)
318  {
319  const polyPatch& pp = operator[](patchI);
320 
321  const edgeList& edges = pp.edges();
322 
323  for
324  (
325  label edgei = pp.nInternalEdges();
326  edgei < edges.size();
327  edgei++
328  )
329  {
330  // Edge in patch local points
331  const edge& e = edges[edgei];
332 
333  // Edge in mesh points.
334  edge meshEdge(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
335 
337  pointsToEdge.find(meshEdge);
338 
339  if (fnd == pointsToEdge.end())
340  {
341  // First occurrence of mesh edge. Store patch and my
342  // local index.
343  pointsToEdge.insert
344  (
345  meshEdge,
346  labelPair
347  (
348  patchI,
349  edgei - pp.nInternalEdges()
350  )
351  );
352  }
353  else
354  {
355  // Second occurrence. Store.
356  const labelPair& edgeInfo = fnd();
357 
358  neighbourEdges[patchI][edgei - pp.nInternalEdges()] =
359  edgeInfo;
360 
361  neighbourEdges[edgeInfo[0]][edgeInfo[1]]
362  = labelPair(patchI, edgei - pp.nInternalEdges());
363 
364  // Found all two occurrences of this edge so remove from
365  // hash to save space. Note that this will give lots of
366  // problems if the polyBoundaryMesh is multiply connected.
367  pointsToEdge.erase(meshEdge);
368  }
369  }
370  }
371 
372  if (pointsToEdge.size())
373  {
374  FatalErrorIn("polyBoundaryMesh::neighbourEdges() const")
375  << "Not all boundary edges of patches match up." << nl
376  << "Is the outside of your mesh multiply connected?"
377  << abort(FatalError);
378  }
379 
380  forAll(*this, patchI)
381  {
382  const polyPatch& pp = operator[](patchI);
383 
384  const labelPairList& nbrEdges = neighbourEdges[patchI];
385 
386  forAll(nbrEdges, i)
387  {
388  const labelPair& edgeInfo = nbrEdges[i];
389 
390  if (edgeInfo[0] == -1 || edgeInfo[1] == -1)
391  {
392  label edgeI = pp.nInternalEdges() + i;
393  const edge& e = pp.edges()[edgeI];
394 
395  FatalErrorIn("polyBoundaryMesh::neighbourEdges() const")
396  << "Not all boundary edges of patches match up." << nl
397  << "Edge " << edgeI << " on patch " << pp.name()
398  << " end points " << pp.localPoints()[e[0]] << ' '
399  << pp.localPoints()[e[1]] << " is not matched to an"
400  << " edge on any other patch." << nl
401  << "Is the outside of your mesh multiply connected?"
402  << abort(FatalError);
403  }
404  }
405  }
406  }
407 
408  return neighbourEdgesPtr_();
409 }
410 
411 
413 {
414  if (!patchIDPtr_.valid())
415  {
416  patchIDPtr_.reset
417  (
418  new labelList
419  (
420  mesh_.nFaces()
421  - mesh_.nInternalFaces()
422  )
423  );
424  labelList& patchID = patchIDPtr_();
425 
426  const polyBoundaryMesh& bm = *this;
427 
428  forAll(bm, patchI)
429  {
430  label bFaceI = bm[patchI].start() - mesh_.nInternalFaces();
431  forAll(bm[patchI], i)
432  {
433  patchID[bFaceI++] = patchI;
434  }
435  }
436  }
437  return patchIDPtr_();
438 }
439 
440 
443 {
444  if (!groupPatchIDsPtr_.valid())
445  {
446  groupPatchIDsPtr_.reset(new HashTable<labelList, word>(10));
447  HashTable<labelList, word>& groupPatchIDs = groupPatchIDsPtr_();
448 
449  const polyBoundaryMesh& bm = *this;
450 
451  forAll(bm, patchI)
452  {
453  const wordList& groups = bm[patchI].inGroups();
454 
455  forAll(groups, i)
456  {
457  const word& name = groups[i];
458 
459  if (findPatchID(name) != -1)
460  {
461  WarningIn("polyBoundaryMesh::groupPatchIDs() const")
462  << "Patch " << bm[patchI].name()
463  << " specifies a group " << name
464  << " which is also a patch name."
465  << " This might give problems later on." << endl;
466  }
467 
468 
469  HashTable<labelList, word>::iterator iter = groupPatchIDs.find
470  (
471  name
472  );
473 
474  if (iter != groupPatchIDs.end())
475  {
476  iter().append(patchI);
477  }
478  else
479  {
480  groupPatchIDs.insert(name, labelList(1, patchI));
481  }
482  }
483  }
484  }
485  return groupPatchIDsPtr_();
486 }
487 
488 
490 (
491  const word& groupName,
492  const labelList& patchIDs
493 )
494 {
495  groupPatchIDsPtr_.clear();
496 
497  polyPatchList& patches = *this;
498 
499  boolList donePatch(patches.size(), false);
500 
501  // Add to specified patches
502  forAll(patchIDs, i)
503  {
504  label patchI = patchIDs[i];
505  polyPatch& pp = patches[patchI];
506 
507  if (!pp.inGroup(groupName))
508  {
509  pp.inGroups().append(groupName);
510  }
511  donePatch[patchI] = true;
512  }
513 
514  // Remove from other patches
515  forAll(patches, patchI)
516  {
517  if (!donePatch[patchI])
518  {
519  polyPatch& pp = patches[patchI];
520 
521  label newI = 0;
522  if (pp.inGroup(groupName))
523  {
524  wordList& groups = pp.inGroups();
525 
526  forAll(groups, i)
527  {
528  if (groups[i] != groupName)
529  {
530  groups[newI++] = groups[i];
531  }
532  }
533  groups.setSize(newI);
534  }
535  }
536  }
537 }
538 
539 
541 {
542  const polyPatchList& patches = *this;
543 
544  wordList t(patches.size());
545 
546  forAll(patches, patchI)
547  {
548  t[patchI] = patches[patchI].name();
549  }
550 
551  return t;
552 }
553 
554 
556 {
557  const polyPatchList& patches = *this;
558 
559  wordList t(patches.size());
560 
561  forAll(patches, patchI)
562  {
563  t[patchI] = patches[patchI].type();
564  }
565 
566  return t;
567 }
568 
569 
571 {
572  const polyPatchList& patches = *this;
573 
574  wordList t(patches.size());
575 
576  forAll(patches, patchI)
577  {
578  t[patchI] = patches[patchI].physicalType();
579  }
580 
581  return t;
582 }
583 
584 
586 (
587  const keyType& key,
588  const bool usePatchGroups
589 ) const
590 {
591  DynamicList<label> indices;
592 
593  if (!key.empty())
594  {
595  if (key.isPattern())
596  {
597  indices = findStrings(key, this->names());
598 
599  if (usePatchGroups && groupPatchIDs().size())
600  {
601  labelHashSet indexSet(indices);
602 
603  const wordList allGroupNames = groupPatchIDs().toc();
604  labelList groupIDs = findStrings(key, allGroupNames);
605  forAll(groupIDs, i)
606  {
607  const word& grpName = allGroupNames[groupIDs[i]];
608  const labelList& patchIDs = groupPatchIDs()[grpName];
609  forAll(patchIDs, j)
610  {
611  if (indexSet.insert(patchIDs[j]))
612  {
613  indices.append(patchIDs[j]);
614  }
615  }
616  }
617  }
618  }
619  else
620  {
621  // Literal string. Special version of above to avoid
622  // unnecessary memory allocations
623 
624  indices.setCapacity(1);
625  forAll(*this, i)
626  {
627  if (key == operator[](i).name())
628  {
629  indices.append(i);
630  break;
631  }
632  }
633 
634  if (usePatchGroups && groupPatchIDs().size())
635  {
637  groupPatchIDs().find(key);
638 
639  if (iter != groupPatchIDs().end())
640  {
641  labelHashSet indexSet(indices);
642 
643  const labelList& patchIDs = iter();
644  forAll(patchIDs, j)
645  {
646  if (indexSet.insert(patchIDs[j]))
647  {
648  indices.append(patchIDs[j]);
649  }
650  }
651  }
652  }
653  }
654  }
655 
656  return indices;
657 }
658 
659 
661 {
662  if (!key.empty())
663  {
664  if (key.isPattern())
665  {
666  labelList indices = this->findIndices(key);
667 
668  // return first element
669  if (!indices.empty())
670  {
671  return indices[0];
672  }
673  }
674  else
675  {
676  forAll(*this, i)
677  {
678  if (key == operator[](i).name())
679  {
680  return i;
681  }
682  }
683  }
684  }
685 
686  // not found
687  return -1;
688 }
689 
690 
692 {
693  const polyPatchList& patches = *this;
694 
695  forAll(patches, patchI)
696  {
697  if (patches[patchI].name() == patchName)
698  {
699  return patchI;
700  }
701  }
702 
703  // Patch not found
704  if (debug)
705  {
706  Pout<< "label polyBoundaryMesh::findPatchID(const word&) const"
707  << "Patch named " << patchName << " not found. "
708  << "List of available patch names: " << names() << endl;
709  }
710 
711  // Not found, return -1
712  return -1;
713 }
714 
715 
717 {
718  // Find out which patch the current face belongs to by comparing label
719  // with patch start labels.
720  // If the face is internal, return -1;
721  // if it is off the end of the list, abort
722  if (faceIndex < mesh().nInternalFaces())
723  {
724  return -1;
725  }
726  else if (faceIndex >= mesh().nFaces())
727  {
729  (
730  "polyBoundaryMesh::whichPatch(const label faceIndex) const"
731  ) << "given label " << faceIndex
732  << " greater than the number of geometric faces " << mesh().nFaces()
733  << abort(FatalError);
734  }
735 
736 
737  forAll(*this, patchI)
738  {
739  const polyPatch& bp = operator[](patchI);
740 
741  if
742  (
743  faceIndex >= bp.start()
744  && faceIndex < bp.start() + bp.size()
745  )
746  {
747  return patchI;
748  }
749  }
750 
751  // If not in any of above, it is trouble!
753  (
754  "label polyBoundaryMesh::whichPatch(const label faceIndex) const"
755  ) << "Cannot find face " << faceIndex << " in any of the patches "
756  << names() << nl
757  << "It seems your patches are not consistent with the mesh :"
758  << " internalFaces:" << mesh().nInternalFaces()
759  << " total number of faces:" << mesh().nFaces()
760  << abort(FatalError);
761 
762  return -1;
763 }
764 
765 
767 (
768  const UList<wordRe>& patchNames,
769  const bool warnNotFound,
770  const bool usePatchGroups
771 ) const
772 {
773  const wordList allPatchNames(this->names());
774  labelHashSet ids(size());
775 
776  forAll(patchNames, i)
777  {
778  const wordRe& patchName = patchNames[i];
779 
780  // Treat the given patch names as wild-cards and search the set
781  // of all patch names for matches
782  labelList patchIDs = findStrings(patchName, allPatchNames);
783 
784  forAll(patchIDs, j)
785  {
786  ids.insert(patchIDs[j]);
787  }
788 
789  if (patchIDs.empty())
790  {
791  if (usePatchGroups)
792  {
793  const wordList allGroupNames = groupPatchIDs().toc();
794 
795  // Regard as group name
796  labelList groupIDs = findStrings(patchName, allGroupNames);
797 
798  forAll(groupIDs, i)
799  {
800  const word& name = allGroupNames[groupIDs[i]];
801  const labelList& extraPatchIDs = groupPatchIDs()[name];
802 
803  forAll(extraPatchIDs, extraI)
804  {
805  ids.insert(extraPatchIDs[extraI]);
806  }
807  }
808 
809  if (groupIDs.empty() && warnNotFound)
810  {
811  WarningIn
812  (
813  "polyBoundaryMesh::patchSet"
814  "(const wordReList&, const bool, const bool) const"
815  ) << "Cannot find any patch or group names matching "
816  << patchName
817  << endl;
818  }
819  }
820  else if (warnNotFound)
821  {
822  WarningIn
823  (
824  "polyBoundaryMesh::patchSet"
825  "(const wordReList&, const bool, const bool) const"
826  ) << "Cannot find any patch names matching " << patchName
827  << endl;
828  }
829  }
830  }
831 
832  return ids;
833 }
834 
835 
837 (
838  const labelUList& patchIDs,
839  wordList& groups,
840  labelHashSet& nonGroupPatches
841 ) const
842 {
843  // Current matched groups
844  DynamicList<word> matchedGroups(1);
845 
846  // Current set of unmatched patches
847  nonGroupPatches = labelHashSet(patchIDs);
848 
849  const HashTable<labelList, word>& groupPatchIDs = this->groupPatchIDs();
850  for
851  (
853  groupPatchIDs.begin();
854  iter != groupPatchIDs.end();
855  ++iter
856  )
857  {
858  // Store currently unmatched patches so we can restore
859  labelHashSet oldNonGroupPatches(nonGroupPatches);
860 
861  // Match by deleting patches in group from the current set and seeing
862  // if all have been deleted.
863  labelHashSet groupPatchSet(iter());
864 
865  label nMatch = nonGroupPatches.erase(groupPatchSet);
866 
867  if (nMatch == groupPatchSet.size())
868  {
869  matchedGroups.append(iter.key());
870  }
871  else if (nMatch != 0)
872  {
873  // No full match. Undo.
874  nonGroupPatches.transfer(oldNonGroupPatches);
875  }
876  }
877 
878  groups.transfer(matchedGroups);
879 }
880 
881 
882 bool Foam::polyBoundaryMesh::checkParallelSync(const bool report) const
883 {
884  if (!Pstream::parRun())
885  {
886  return false;
887  }
888 
889 
890  const polyBoundaryMesh& bm = *this;
891 
892  bool hasError = false;
893 
894  // Collect non-proc patches and check proc patches are last.
895  wordList names(bm.size());
896  wordList types(bm.size());
897 
898  label nonProcI = 0;
899 
900  forAll(bm, patchI)
901  {
902  if (!isA<processorPolyPatch>(bm[patchI]))
903  {
904  if (nonProcI != patchI)
905  {
906  // There is processor patch in between normal patches.
907  hasError = true;
908 
909  if (debug || report)
910  {
911  Pout<< " ***Problem with boundary patch " << patchI
912  << " named " << bm[patchI].name()
913  << " of type " << bm[patchI].type()
914  << ". The patch seems to be preceeded by processor"
915  << " patches. This is can give problems."
916  << endl;
917  }
918  }
919  else
920  {
921  names[nonProcI] = bm[patchI].name();
922  types[nonProcI] = bm[patchI].type();
923  nonProcI++;
924  }
925  }
926  }
927  names.setSize(nonProcI);
928  types.setSize(nonProcI);
929 
930  List<wordList> allNames(Pstream::nProcs());
931  allNames[Pstream::myProcNo()] = names;
932  Pstream::gatherList(allNames);
933  Pstream::scatterList(allNames);
934 
935  List<wordList> allTypes(Pstream::nProcs());
936  allTypes[Pstream::myProcNo()] = types;
937  Pstream::gatherList(allTypes);
938  Pstream::scatterList(allTypes);
939 
940  // Have every processor check but only master print error.
941 
942  for (label procI = 1; procI < allNames.size(); ++procI)
943  {
944  if
945  (
946  (allNames[procI] != allNames[0])
947  || (allTypes[procI] != allTypes[0])
948  )
949  {
950  hasError = true;
951 
952  if (debug || (report && Pstream::master()))
953  {
954  Info<< " ***Inconsistent patches across processors, "
955  "processor 0 has patch names:" << allNames[0]
956  << " patch types:" << allTypes[0]
957  << " processor " << procI << " has patch names:"
958  << allNames[procI]
959  << " patch types:" << allTypes[procI]
960  << endl;
961  }
962  }
963  }
964 
965  return hasError;
966 }
967 
968 
969 bool Foam::polyBoundaryMesh::checkDefinition(const bool report) const
970 {
971  label nextPatchStart = mesh().nInternalFaces();
972  const polyBoundaryMesh& bm = *this;
973 
974  bool hasError = false;
975 
976  HashSet<word> patchNames(2*size());
977 
978  forAll(bm, patchI)
979  {
980  if (bm[patchI].start() != nextPatchStart && !hasError)
981  {
982  hasError = true;
983 
984  Info<< " ****Problem with boundary patch " << patchI
985  << " named " << bm[patchI].name()
986  << " of type " << bm[patchI].type()
987  << ". The patch should start on face no " << nextPatchStart
988  << " and the patch specifies " << bm[patchI].start()
989  << "." << endl
990  << "Possibly consecutive patches have this same problem."
991  << " Suppressing future warnings." << endl;
992  }
993 
994  if (!patchNames.insert(bm[patchI].name()) && !hasError)
995  {
996  hasError = true;
997 
998  Info<< " ****Duplicate boundary patch " << patchI
999  << " named " << bm[patchI].name()
1000  << " of type " << bm[patchI].type()
1001  << "." << endl
1002  << "Suppressing future warnings." << endl;
1003  }
1004 
1005  nextPatchStart += bm[patchI].size();
1006  }
1007 
1008  reduce(hasError, orOp<bool>());
1009 
1010  if (debug || report)
1011  {
1012  if (hasError)
1013  {
1014  Pout<< " ***Boundary definition is in error." << endl;
1015  }
1016  else
1017  {
1018  Info<< " Boundary definition OK." << endl;
1019  }
1020  }
1021 
1022  return hasError;
1023 }
1024 
1025 
1027 {
1029 
1030  if
1031  (
1034  )
1035  {
1036  forAll(*this, patchI)
1037  {
1038  operator[](patchI).initMovePoints(pBufs, p);
1039  }
1040 
1041  pBufs.finishedSends();
1042 
1043  forAll(*this, patchI)
1044  {
1045  operator[](patchI).movePoints(pBufs, p);
1046  }
1047  }
1049  {
1050  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
1051 
1052  // Dummy.
1053  pBufs.finishedSends();
1054 
1055  forAll(patchSchedule, patchEvali)
1056  {
1057  const label patchI = patchSchedule[patchEvali].patch;
1058 
1059  if (patchSchedule[patchEvali].init)
1060  {
1061  operator[](patchI).initMovePoints(pBufs, p);
1062  }
1063  else
1064  {
1065  operator[](patchI).movePoints(pBufs, p);
1066  }
1067  }
1068  }
1069 }
1070 
1071 
1073 {
1074  neighbourEdgesPtr_.clear();
1075  patchIDPtr_.clear();
1076  groupPatchIDsPtr_.clear();
1077 
1079 
1080  if
1081  (
1084  )
1085  {
1086  forAll(*this, patchI)
1087  {
1088  operator[](patchI).initUpdateMesh(pBufs);
1089  }
1090 
1091  pBufs.finishedSends();
1092 
1093  forAll(*this, patchI)
1094  {
1095  operator[](patchI).updateMesh(pBufs);
1096  }
1097  }
1099  {
1100  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
1101 
1102  // Dummy.
1103  pBufs.finishedSends();
1104 
1105  forAll(patchSchedule, patchEvali)
1106  {
1107  const label patchI = patchSchedule[patchEvali].patch;
1108 
1109  if (patchSchedule[patchEvali].init)
1110  {
1111  operator[](patchI).initUpdateMesh(pBufs);
1112  }
1113  else
1114  {
1115  operator[](patchI).updateMesh(pBufs);
1116  }
1117  }
1118  }
1119 }
1120 
1121 
1124  const labelUList& oldToNew,
1125  const bool validBoundary
1126 )
1127 {
1128  // Change order of patches
1129  polyPatchList::reorder(oldToNew);
1130 
1131  // Adapt indices
1132  polyPatchList& patches = *this;
1133 
1134  forAll(patches, patchI)
1135  {
1136  patches[patchI].index() = patchI;
1137  }
1138 
1139  if (validBoundary)
1140  {
1141  updateMesh();
1142  }
1143 }
1144 
1145 
1147 {
1148  const polyPatchList& patches = *this;
1149 
1150  os << patches.size() << nl << token::BEGIN_LIST << incrIndent << nl;
1151 
1152  forAll(patches, patchI)
1153  {
1154  os << indent << patches[patchI].name() << nl
1155  << indent << token::BEGIN_BLOCK << nl
1156  << incrIndent << patches[patchI] << decrIndent
1157  << indent << token::END_BLOCK << endl;
1158  }
1159 
1160  os << decrIndent << token::END_LIST;
1161 
1162  // Check state of IOstream
1163  os.check("polyBoundaryMesh::writeData(Ostream& os) const");
1164 
1165  return os.good();
1166 }
1167 
1168 
1174 ) const
1175 {
1177 }
1178 
1179 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
1180 
1183  const word& patchName
1184 ) const
1185 {
1186  const label patchI = findPatchID(patchName);
1187 
1188  if (patchI < 0)
1189  {
1190  FatalErrorIn
1191  (
1192  "polyBoundaryMesh::operator[](const word&) const"
1193  ) << "Patch named " << patchName << " not found." << nl
1194  << "Available patch names: " << names() << endl
1195  << abort(FatalError);
1196  }
1197 
1198  return operator[](patchI);
1199 }
1200 
1201 
1204  const word& patchName
1205 )
1206 {
1207  const label patchI = findPatchID(patchName);
1208 
1209  if (patchI < 0)
1210  {
1211  FatalErrorIn
1212  (
1213  "polyBoundaryMesh::operator[](const word&)"
1214  ) << "Patch named " << patchName << " not found." << nl
1215  << "Available patch names: " << names() << endl
1216  << abort(FatalError);
1217  }
1218 
1219  return operator[](patchI);
1220 }
1221 
1222 
1223 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
1224 
1226 {
1227  pbm.writeData(os);
1228  return os;
1229 }
1230 
1231 
1232 // ************************************************************************* //
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:380
void setSize(const label)
Reset size of PtrList. If extending the PtrList, new entries are.
Definition: PtrList.C:142
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:109
~polyBoundaryMesh()
Destructor.
label size() const
Return the number of elements in the PtrList.
Definition: PtrListI.H:32
label nFaces() const
bool set(const label) const
Is element set.
Definition: PtrListI.H:107
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
const word & name() const
Return name.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:61
bool erase(const iterator &)
Erase a hashedEntry specified by given iterator.
Definition: HashTable.C:379
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:390
wordList patchNames(nPatches)
An STL-conforming const_iterator.
Definition: HashTable.H:470
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
virtual bool writeObject(IOstream::streamFormat, IOstream::versionNumber, IOstream::compressionType) const
Write using given format, version and compression.
bool empty() const
Return true if the UList is empty (ie, size() is zero).
Definition: UListI.H:313
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
An STL-conforming iterator.
Definition: HashTable.H:415
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:221
An STL-conforming hash table.
Definition: HashTable.H:61
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order. Return.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
A class for handling words, derived from string.
Definition: word.H:59
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
wordList physicalTypes() const
Return a list of physical types.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:310
bool isPattern() const
Should be treated as a match rather than a literal string.
Definition: keyTypeI.H:76
void updateMesh()
Correct polyBoundaryMesh after topology update.
const List< labelPairList > & neighbourEdges() const
Per patch the edges on the neighbouring patch. Is for every external.
An STL-conforming iterator.
Definition: PtrList.H:281
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
bool checkDefinition(const bool report=false) const
Check boundary definition. Return true if in error.
messageStream Info
dynamicFvMesh & mesh
friend Ostream & operator(Ostream &, const PtrList< T > &)
Ostream & operator<<(Ostream &, const edgeMesh &)
Definition: edgeMeshIO.C:133
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Namespace for OpenFOAM.
A class for handling keywords in dictionaries.
Definition: keyType.H:56
const HashTable< labelList, word > & groupPatchIDs() const
Per patch group the patch indices.
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
patches[0]
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:92
wordList names() const
Return a list of patch names.
PtrList< polyPatch > polyPatchList
container classes for polyPatch
Definition: polyPatchList.H:45
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:228
dictionary dict
const Field< PointType > & localPoints() const
Return pointField of points in patch.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
static const char nl
Definition: Ostream.H:260
const double e
Elementary charge.
Definition: doubleFloat.H:78
void setSize(const label)
Reset size of List.
Definition: List.C:318
wordList types() const
Return a list of patch types.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
void setGroup(const word &groupName, const labelList &patchIDs)
Set/add group with patches.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:235
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
#define WarningIn(functionName)
Report a warning using Foam::Warning.
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:86
Foam::polyBoundaryMesh.
volScalarField & p
Definition: createFields.H:51
bool findStrings(const wordReListMatcher &matcher, const std::string &str)
Return true if string matches one of the regular expressions.
Definition: stringListOps.H:52
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
#define forAll(list, i)
Definition: UList.H:421
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp) const
Write using given format, version and form uncompression.
void clearAddressing()
Clear addressing at this level and at patches.
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
label findIndex(const keyType &) const
Return patch index for the first match, return -1 if not found.
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const word & name() const
Return name.
Definition: IOobject.H:260
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:404
void matchGroups(const labelUList &patchIDs, wordList &groups, labelHashSet &nonGroupPatches) const
Match the patches to groups. Returns all the (fully matched) groups.
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return a pointer to a new patch created on freestore from.
Definition: polyPatchNew.C:32
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:210
labelHashSet patchSet(const UList< wordRe > &patchNames, const bool warnNotFound=true, const bool usePatchGroups=true) const
Return the set of patch IDs corresponding to the given names.
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:193
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:300
label nInternalFaces() const
const labelList & patchID() const
Per boundary face label the patch index.
void movePoints(const pointField &)
Correct polyBoundaryMesh after moving points.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
label nInternalEdges() const
Number of internal edges.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:60
error FatalError
labelList findIndices(const keyType &, const bool usePatchGroups=true) const
Return patch indices for all matches. Optionally matches patchGroups.
List< label > labelList
A List of labels.
Definition: labelList.H:56
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
Operations on lists of strings.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
void transfer(HashTable< T, Key, Hash > &)
Transfer the contents of the argument table into this table.
Definition: HashTable.C:518
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:398
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:106
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:97
bool inGroup(const word &) const
Test if in group.
void clearGeom()
Clear geometry at this level and at patches.
void reorder(const labelUList &)
Reorders elements. Ordering does not have to be done in.
Definition: PtrList.C:208
iterator begin()
Iterator set to the beginning of the HashTable.
Definition: HashTableI.H:419
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:139
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:255
const lduSchedule & patchSchedule() const
Order in which the patches should be initialised/evaluated.
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
void reorder(const labelUList &, const bool validBoundary)
Reorders patches. Ordering does not have to be done in.
label nEdges() const
Return number of edges in patch.
Version number type.
Definition: IOstream.H:96
A wordRe is a word, but can also have a regular expression for matching words.
Definition: wordRe.H:74
label findPatchID(const word &patchName) const
Find patch index given a name.
bool writeData(Ostream &) const
writeData member function required by regIOobject
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurences of given element. Linear search.
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1200
defineTypeNameAndDebug(combustionModel, 0)
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
const wordList & inGroups() const
Return the optional groups patch belongs to.
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116