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