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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2018-2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "polyBoundaryMesh.H"
30 #include "polyMesh.H"
31 #include "primitiveMesh.H"
32 #include "processorPolyPatch.H"
33 #include "PstreamBuffers.H"
34 #include "lduSchedule.H"
35 #include "globalMeshData.H"
36 #include "wordRes.H"
37 #include "DynamicList.H"
38 #include "PtrListOps.H"
39 #include "edgeHashes.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(polyBoundaryMesh, 0);
46 }
47 
48 
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 
51 bool Foam::polyBoundaryMesh::hasGroupIDs() const
52 {
53  if (groupIDsPtr_)
54  {
55  // Use existing cache
56  return !groupIDsPtr_->empty();
57  }
58 
59  const polyPatchList& patches = *this;
60 
61  for (const polyPatch& p : patches)
62  {
63  if (!p.inGroups().empty())
64  {
65  return true;
66  }
67  }
68 
69  return false;
70 }
71 
72 
73 void Foam::polyBoundaryMesh::calcGroupIDs() const
74 {
75  if (groupIDsPtr_)
76  {
77  return; // Or FatalError
78  }
79 
80  groupIDsPtr_.emplace(16);
81  auto& groupLookup = *groupIDsPtr_;
82 
83  const polyPatchList& patches = *this;
84 
85  forAll(patches, patchi)
86  {
87  for (const word& groupName : patches[patchi].inGroups())
88  {
89  groupLookup(groupName).push_back(patchi);
90  }
91  }
92 
93  // Remove groups that clash with patch names
94  forAll(patches, patchi)
95  {
96  if (groupLookup.empty())
97  {
98  break; // Early termination
99  }
100  else if (groupLookup.erase(patches[patchi].name()))
101  {
103  << "Removed group '" << patches[patchi].name()
104  << "' which clashes with patch " << patchi
105  << " of the same name."
106  << endl;
107  }
108  }
109 }
110 
111 
112 void Foam::polyBoundaryMesh::populate(PtrList<entry>&& entries)
113 {
114  clearLocalAddressing();
115 
116  polyPatchList& patches = *this;
117 
118  patches.resize_null(entries.size());
119 
120  // Transcribe.
121  // Does not handle nullptr at all (what could possibly be done?)
122  forAll(patches, patchi)
123  {
124  patches.set
125  (
126  patchi,
128  (
129  entries[patchi].keyword(),
130  entries[patchi].dict(),
131  patchi,
132  *this
133  )
134  );
135  }
136 
137  entries.clear();
138 }
139 
140 
141 bool Foam::polyBoundaryMesh::readIOcontents(const bool allowOptionalRead)
142 {
143  bool updated = false;
144  PtrList<entry> entries;
145 
146  if
147  (
148  this->isReadRequired()
149  || (allowOptionalRead && this->isReadOptional() && this->headerOk())
150  )
151  {
152  // Warn for MUST_READ_IF_MODIFIED
153  warnNoRereading<polyBoundaryMesh>();
154 
155  // Read entries
156  Istream& is = readStream(typeName);
157 
158  is >> entries;
159 
160  is.check(FUNCTION_NAME);
161  close();
162  updated = true;
163  }
164  // Future: support master-only and broadcast?
165 
166  if (updated)
167  {
168  populate(std::move(entries));
169  }
170 
171  return updated;
172 }
173 
174 
175 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
176 
178 (
179  const IOobject& io,
180  const polyMesh& mesh
181 )
182 :
183  polyPatchList(),
184  regIOobject(io),
185  mesh_(mesh)
186 {
187  readIOcontents(false); // allowOptionalRead = false
188 }
189 
190 
192 (
193  const IOobject& io,
194  const polyMesh& pm,
195  Foam::zero
196 )
197 :
199  regIOobject(io),
200  mesh_(pm)
201 {}
202 
203 
205 (
206  const IOobject& io,
207  const polyMesh& pm,
208  const label size
209 )
210 :
212  regIOobject(io),
213  mesh_(pm)
214 {}
215 
216 
218 (
219  const IOobject& io,
220  const polyMesh& pm,
221  const polyPatchList& list
222 )
223 :
224  polyPatchList(),
225  regIOobject(io),
226  mesh_(pm)
227 {
228  if (!readIOcontents(true)) // allowOptionalRead = true
229  {
230  // Nothing read. Use supplied patches
231  polyPatchList& patches = *this;
232  patches.resize(list.size());
233 
234  forAll(patches, patchi)
235  {
236  patches.set(patchi, list[patchi].clone(*this));
237  }
238  }
239 }
240 
241 
243 (
244  const IOobject& io,
245  const polyMesh& pm,
246  PtrList<entry>&& entries
247 )
248 :
249  polyPatchList(),
250  regIOobject(io),
251  mesh_(pm)
252 {
253  if (!readIOcontents(true)) // allowOptionalRead = true
254  {
255  populate(std::move(entries));
256  }
257  entries.clear();
258 }
259 
260 
261 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
262 
264 {
266  clearAddressing();
267 }
268 
269 
271 {
272  polyPatchList& patches = *this;
273 
274  for (polyPatch& p : patches)
275  {
276  p.clearGeom();
277  }
278 }
279 
280 
281 // Private until it is more generally required (and gets a better name?)
282 void Foam::polyBoundaryMesh::clearLocalAddressing()
283 {
284  neighbourEdgesPtr_.reset(nullptr);
285  patchIDPtr_.reset(nullptr);
286  groupIDsPtr_.reset(nullptr);
287 }
288 
289 
291 {
292  clearLocalAddressing();
293 
294  polyPatchList& patches = *this;
295 
296  for (polyPatch& p : patches)
297  {
298  p.clearAddressing();
299  }
300 }
301 
302 
303 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
304 
305 void Foam::polyBoundaryMesh::calcGeometry()
306 {
307  // Make sure messages don't interact by having unique tag
308  const int oldTag = UPstream::incrMsgType();
309 
310  PstreamBuffers pBufs(Pstream::defaultCommsType);
311 
312  if
313  (
314  pBufs.commsType() == Pstream::commsTypes::buffered
315  || pBufs.commsType() == Pstream::commsTypes::nonBlocking
316  )
317  {
318  forAll(*this, patchi)
319  {
320  operator[](patchi).initGeometry(pBufs);
321  }
322 
323  pBufs.finishedSends();
324 
325  forAll(*this, patchi)
326  {
327  operator[](patchi).calcGeometry(pBufs);
328  }
329  }
330  else if (pBufs.commsType() == Pstream::commsTypes::scheduled)
331  {
332  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
333 
334  // Dummy.
335  pBufs.finishedSends();
336 
337  for (const auto& schedEval : patchSchedule)
338  {
339  const label patchi = schedEval.patch;
340 
341  if (schedEval.init)
342  {
343  operator[](patchi).initGeometry(pBufs);
344  }
345  else
346  {
347  operator[](patchi).calcGeometry(pBufs);
348  }
349  }
350  }
351 
352  // Reset tag
353  UPstream::msgType(oldTag);
354 }
355 
356 
358 {
359  return faceList::subList
360  (
361  mesh_.faces(),
362  mesh_.nBoundaryFaces(),
363  mesh_.nInternalFaces()
364  );
365 }
366 
367 
369 {
370  return labelList::subList
371  (
372  mesh_.faceOwner(),
373  mesh_.nBoundaryFaces(),
374  mesh_.nInternalFaces()
375  );
376 }
377 
378 // Potentially useful to simplify logic elsewhere?
379 // const Foam::labelList::subList Foam::polyBoundaryMesh::faceNeighbour() const
380 // {
381 // return labelList::subList();
382 // }
383 
384 
387 {
388  const polyPatchList& patches = *this;
389 
391 
392  forAll(patches, patchi)
393  {
394  list.set(patchi, &patches[patchi].faceCells());
395  }
396 
397  return list;
398 }
399 
400 
403 {
404  if (Pstream::parRun())
405  {
407  << "Neighbour edge addressing not correct across parallel"
408  << " boundaries." << endl;
409  }
410 
411  if (!neighbourEdgesPtr_)
412  {
413  neighbourEdgesPtr_.emplace(size());
414  auto& neighbourEdges = *neighbourEdgesPtr_;
415 
416  // Initialize.
417  label nEdgePairs = 0;
418  forAll(*this, patchi)
419  {
420  const polyPatch& pp = operator[](patchi);
421 
422  neighbourEdges[patchi].setSize(pp.nEdges() - pp.nInternalEdges());
423 
424  for (labelPair& edgeInfo : neighbourEdges[patchi])
425  {
426  edgeInfo[0] = -1;
427  edgeInfo[1] = -1;
428  }
429 
430  nEdgePairs += pp.nEdges() - pp.nInternalEdges();
431  }
432 
433  // From mesh edge (expressed as a point pair so as not to construct
434  // point addressing) to patch + relative edge index.
435  EdgeMap<labelPair> pointsToEdge(nEdgePairs);
436 
437  forAll(*this, patchi)
438  {
439  const polyPatch& pp = operator[](patchi);
440 
441  const edgeList& edges = pp.edges();
442 
443  for
444  (
445  label edgei = pp.nInternalEdges();
446  edgei < edges.size();
447  edgei++
448  )
449  {
450  // Edge in patch local points
451  const edge& e = edges[edgei];
452 
453  // Edge in mesh points.
454  edge meshEdge(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
455 
456  auto fnd = pointsToEdge.find(meshEdge);
457 
458  if (!fnd.good())
459  {
460  // First occurrence of mesh edge. Store patch and my
461  // local index.
462  pointsToEdge.insert
463  (
464  meshEdge,
465  labelPair
466  (
467  patchi,
468  edgei - pp.nInternalEdges()
469  )
470  );
471  }
472  else
473  {
474  // Second occurrence. Store.
475  const labelPair& edgeInfo = fnd.val();
476 
477  neighbourEdges[patchi][edgei - pp.nInternalEdges()] =
478  edgeInfo;
479 
480  neighbourEdges[edgeInfo[0]][edgeInfo[1]]
481  = labelPair(patchi, edgei - pp.nInternalEdges());
482 
483  // Found all two occurrences of this edge so remove from
484  // hash to save space. Note that this will give lots of
485  // problems if the polyBoundaryMesh is multiply connected.
486  pointsToEdge.erase(meshEdge);
487  }
488  }
489  }
490 
491  if (pointsToEdge.size())
492  {
494  << "Not all boundary edges of patches match up." << nl
495  << "Is the outside of your mesh multiply connected?"
496  << abort(FatalError);
497  }
498 
499  forAll(*this, patchi)
500  {
501  const polyPatch& pp = operator[](patchi);
502 
503  const labelPairList& nbrEdges = neighbourEdges[patchi];
504 
505  forAll(nbrEdges, i)
506  {
507  const labelPair& edgeInfo = nbrEdges[i];
508 
509  if (edgeInfo[0] == -1 || edgeInfo[1] == -1)
510  {
511  const label edgei = pp.nInternalEdges() + i;
512  const edge& e = pp.edges()[edgei];
513 
515  << "Not all boundary edges of patches match up." << nl
516  << "Edge " << edgei << " on patch " << pp.name()
517  << " end points " << pp.localPoints()[e[0]] << ' '
518  << pp.localPoints()[e[1]] << " is not matched to an"
519  << " edge on any other patch." << nl
520  << "Is the outside of your mesh multiply connected?"
521  << abort(FatalError);
522  }
523  }
524  }
525  }
526 
527  return *neighbourEdgesPtr_;
528 }
529 
530 
532 {
533  if (!patchIDPtr_)
534  {
535  patchIDPtr_.emplace(mesh_.nBoundaryFaces());
536  auto& list = *patchIDPtr_;
537 
538  const polyPatchList& patches = *this;
539 
540  forAll(patches, patchi)
541  {
542  SubList<label>
543  (
544  list,
545  patches[patchi].size(),
546  (patches[patchi].start() - mesh_.nInternalFaces())
547  ) = patchi;
548  }
549  }
550 
551  return *patchIDPtr_;
552 }
553 
554 
555 Foam::label Foam::polyBoundaryMesh::patchID(const label meshFacei) const
556 {
557  const label bndFacei = (meshFacei - mesh_.nInternalFaces());
558 
559  return
560  (
561  (bndFacei >= 0 && bndFacei < mesh_.nBoundaryFaces())
562  ? this->patchID()[bndFacei]
563  : -1
564  );
565 }
566 
567 
569 Foam::polyBoundaryMesh::patchID(const labelUList& meshFaceIndices) const
570 {
571  labelList output(meshFaceIndices.size());
572  forAll(meshFaceIndices, i)
573  {
574  output[i] = patchID(meshFaceIndices[i]);
575  }
576  return output;
577 }
578 
579 
582 {
583  if (!groupIDsPtr_)
584  {
585  calcGroupIDs();
586  }
587 
588  return *groupIDsPtr_;
589 }
590 
591 
593 (
594  const word& groupName,
595  const labelUList& patchIDs
596 )
597 {
598  groupIDsPtr_.reset(nullptr);
599 
600  polyPatchList& patches = *this;
601 
602  boolList pending(patches.size(), true);
603 
604  // Add to specified patches
605  for (const label patchi : patchIDs)
606  {
607  if (pending.test(patchi))
608  {
609  pending.unset(patchi);
610  patches[patchi].addGroup(groupName);
611  }
612  }
613 
614  // Remove from other patches
615  forAll(patches, patchi)
616  {
617  if (pending.test(patchi))
618  {
619  patches[patchi].removeGroup(groupName);
620  }
621  }
622 }
623 
624 
625 Foam::label Foam::polyBoundaryMesh::nNonProcessor() const
626 {
627  const polyPatchList& patches = *this;
628 
629  label count = 0;
630 
631  for (const polyPatch& p : patches)
632  {
633  if (isA<processorPolyPatch>(p))
634  {
635  break;
636  }
637 
638  ++count;
639  }
640 
641  return count;
642 }
643 
644 
646 {
647  const polyPatchList& patches = *this;
648 
649  label count = 0;
650 
651  for (const polyPatch& p : patches)
652  {
653  if (isA<processorPolyPatch>(p))
654  {
655  ++count;
656  }
657  }
658 
659  return count;
660 }
661 
662 
664 {
665  const polyPatchList& patches = *this;
666 
667  label count = 0;
668 
669  for (const polyPatch& p : patches)
670  {
671  if (isA<processorPolyPatch>(p))
672  {
673  break;
674  }
675 
676  count += p.nFaces();
677  }
678 
679  return count;
680 }
681 
684 {
685  return PtrListOps::get<word>(*this, nameOp<polyPatch>());
686 }
687 
690 {
691  return PtrListOps::get<word>(*this, typeOp<polyPatch>());
692 }
693 
694 
696 {
697  return
698  PtrListOps::get<word>
699  (
700  *this,
701  [](const polyPatch& p) { return p.physicalType(); }
702  );
703 }
704 
705 
707 {
708  return
709  PtrListOps::get<label>
710  (
711  *this,
712  [](const polyPatch& p) { return p.start(); }
713  );
714 }
715 
716 
718 {
719  return
720  PtrListOps::get<label>
721  (
722  *this,
723  [](const polyPatch& p) { return p.size(); }
724  );
725 }
726 
727 
729 {
730  return
731  PtrListOps::get<labelRange>
732  (
733  *this,
734  [](const polyPatch& p) { return p.range(); }
735  );
736 }
737 
740 {
741  return this->groupPatchIDs().sortedToc();
742 }
743 
745 Foam::label Foam::polyBoundaryMesh::start() const noexcept
746 {
747  return mesh_.nInternalFaces();
748 }
749 
751 Foam::label Foam::polyBoundaryMesh::nFaces() const noexcept
752 {
753  return mesh_.nBoundaryFaces();
754 }
755 
758 {
759  return labelRange(mesh_.nInternalFaces(), mesh_.nBoundaryFaces());
760 }
761 
762 
763 Foam::labelRange Foam::polyBoundaryMesh::range(const label patchi) const
764 {
765  if (patchi < 0)
766  {
767  return labelRange(mesh_.nInternalFaces(), 0);
768  }
770  // Will fail if patchi >= size()
771  return (*this)[patchi].range();
772 }
773 
774 
776 (
777  const wordRe& matcher,
778  const bool useGroups
779 ) const
780 {
781  if (matcher.empty())
782  {
783  return labelList();
784  }
785 
786  // Only check groups if requested and they exist
787  const bool checkGroups = (useGroups && this->hasGroupIDs());
788 
789  labelHashSet ids;
790 
791  if (matcher.isPattern())
792  {
793  if (checkGroups)
794  {
795  const auto& groupLookup = groupPatchIDs();
796  forAllConstIters(groupLookup, iter)
797  {
798  if (matcher(iter.key()))
799  {
800  // Add patch ids associated with the group
801  ids.insert(iter.val());
802  }
803  }
804  }
805 
806  if (ids.empty())
807  {
808  return PtrListOps::findMatching(*this, matcher);
809  }
810  else
811  {
812  ids.insert(PtrListOps::findMatching(*this, matcher));
813  }
814  }
815  else
816  {
817  // Literal string.
818  // Special version of above for reduced memory footprint.
819 
820  const label patchId = PtrListOps::firstMatching(*this, matcher);
821 
822  if (patchId >= 0)
823  {
824  return labelList(one{}, patchId);
825  }
826  else if (checkGroups)
827  {
828  const auto iter = groupPatchIDs().cfind(matcher);
829 
830  if (iter.good())
831  {
832  // Hash ids associated with the group
833  ids.insert(iter.val());
834  }
835  }
836  }
837 
838  return ids.sortedToc();
839 }
840 
841 
843 (
844  const wordRes& matcher,
845  const bool useGroups
846 ) const
847 {
848  if (matcher.empty())
849  {
850  return labelList();
851  }
852  else if (matcher.size() == 1)
853  {
854  return this->indices(matcher.front(), useGroups);
855  }
856 
857  labelHashSet ids;
858 
859  // Only check groups if requested and they exist
860  if (useGroups && this->hasGroupIDs())
861  {
862  ids.reserve(this->size());
863 
864  const auto& groupLookup = groupPatchIDs();
865  forAllConstIters(groupLookup, iter)
866  {
867  if (matcher(iter.key()))
868  {
869  // Add patch ids associated with the group
870  ids.insert(iter.val());
871  }
872  }
873  }
874 
875  if (ids.empty())
876  {
877  return PtrListOps::findMatching(*this, matcher);
878  }
879  else
880  {
881  ids.insert(PtrListOps::findMatching(*this, matcher));
882  }
883 
884  return ids.sortedToc();
885 }
886 
887 
889 (
890  const wordRes& allow,
891  const wordRes& deny,
892  const bool useGroups
893 ) const
894 {
895  if (allow.empty() && deny.empty())
896  {
897  // Fast-path: select all
898  return identity(this->size());
899  }
900 
901  const wordRes::filter matcher(allow, deny);
902 
903  labelHashSet ids;
904 
905  // Only check groups if requested and they exist
906  if (useGroups && this->hasGroupIDs())
907  {
908  ids.reserve(this->size());
909 
910  const auto& groupLookup = groupPatchIDs();
911  forAllConstIters(groupLookup, iter)
912  {
913  if (matcher(iter.key()))
914  {
915  // Add patch ids associated with the group
916  ids.insert(iter.val());
917  }
918  }
919  }
920 
921  if (ids.empty())
922  {
923  return PtrListOps::findMatching(*this, matcher);
924  }
925  else
926  {
927  ids.insert(PtrListOps::findMatching(*this, matcher));
928  }
929 
930  return ids.sortedToc();
931 }
932 
933 
934 Foam::label Foam::polyBoundaryMesh::findIndex(const wordRe& key) const
935 {
936  if (key.empty())
937  {
938  return -1;
939  }
940  return PtrListOps::firstMatching(*this, key);
941 }
942 
943 
945 (
946  const word& patchName,
947  bool allowNotFound
948 ) const
949 {
950  if (patchName.empty())
951  {
952  return -1;
953  }
954 
955  const label patchId = PtrListOps::firstMatching(*this, patchName);
956 
957  if (patchId >= 0)
958  {
959  return patchId;
960  }
961 
962  if (!allowNotFound)
963  {
965  << "Patch '" << patchName << "' not found. "
966  << "Available patch names";
967 
968  if (polyMesh::defaultRegion != mesh_.name())
969  {
970  FatalError
971  << " in region '" << mesh_.name() << "'";
972  }
973 
974  FatalError
975  << " include: " << names() << endl
976  << exit(FatalError);
977  }
978 
979  // Patch not found
980  if (debug)
981  {
982  Pout<< "label polyBoundaryMesh::findPatchID(const word&) const"
983  << "Patch named " << patchName << " not found. "
984  << "Available patch names: " << names() << endl;
985  }
987  // Not found, return -1
988  return -1;
989 }
990 
991 
993 Foam::polyBoundaryMesh::whichPatchFace(const label meshFacei) const
994 {
995  if (meshFacei < mesh().nInternalFaces())
996  {
997  // Internal face: return (-1, meshFace)
998  return labelPair(-1, meshFacei);
999  }
1000  else if (meshFacei >= mesh().nFaces())
1001  {
1002  // Bounds error: abort
1004  << "Face " << meshFacei
1005  << " out of bounds. Number of geometric faces " << mesh().nFaces()
1006  << abort(FatalError);
1007 
1008  return labelPair(-1, meshFacei);
1009  }
1010 
1011 
1012  const polyPatchList& patches = *this;
1013 
1014  // Do we have cached patch info?
1015  if (patchIDPtr_)
1016  {
1017  const label patchi =
1018  this->patchID()[meshFacei - mesh().nInternalFaces()];
1019 
1020  // (patch, local face index)
1021  return labelPair(patchi, meshFacei - patches[patchi].start());
1022  }
1023 
1024 
1025  // Patches are ordered, use binary search
1026  // Find out which patch index and local patch face the specified
1027  // mesh face belongs to by comparing label with patch start labels.
1028 
1029  const label patchi =
1030  findLower
1031  (
1032  patches,
1033  meshFacei,
1034  0,
1035  // Must include the start in the comparison
1036  [](const polyPatch& p, label val) { return (p.start() <= val); }
1037  );
1038 
1039  if (patchi < 0 || !patches[patchi].range().contains(meshFacei))
1040  {
1041  // If not in any of above, it is trouble!
1043  << "Face " << meshFacei << " not found in any of the patches "
1044  << flatOutput(names()) << nl
1045  << "The patches appear to be inconsistent with the mesh :"
1046  << " internalFaces:" << mesh().nInternalFaces()
1047  << " total number of faces:" << mesh().nFaces()
1048  << abort(FatalError);
1049 
1050  return labelPair(-1, meshFacei);
1051  }
1053  // (patch, local face index)
1054  return labelPair(patchi, meshFacei - patches[patchi].start());
1055 }
1056 
1057 
1059 Foam::polyBoundaryMesh::whichPatchFace(const labelUList& meshFaceIndices) const
1060 {
1061  labelPairList output(meshFaceIndices.size());
1062  forAll(meshFaceIndices, i)
1063  {
1064  output[i] = whichPatchFace(meshFaceIndices[i]);
1065  }
1066  return output;
1067 }
1068 
1069 
1071 (
1072  const UList<wordRe>& select,
1073  const bool warnNotFound,
1074  const bool useGroups
1075 ) const
1076 {
1077  labelHashSet ids;
1078  if (select.empty())
1079  {
1080  return ids;
1081  }
1082 
1083  const polyPatchList& patches = *this;
1084 
1085  const label len = patches.size();
1086 
1087  ids.reserve(len);
1088 
1089  // Only check groups if requested and they exist
1090  const bool checkGroups = (useGroups && this->hasGroupIDs());
1091 
1092  for (const wordRe& matcher : select)
1093  {
1094  bool missed = true;
1095 
1096  for (label i = 0; i < len; ++i)
1097  {
1098  if (matcher(patches[i].name()))
1099  {
1100  ids.insert(i);
1101  missed = false;
1102  }
1103  }
1104 
1105  if (missed && checkGroups)
1106  {
1107  // Check group names
1108  if (matcher.isPattern())
1109  {
1110  forAllConstIters(groupPatchIDs(), iter)
1111  {
1112  if (matcher.match(iter.key()))
1113  {
1114  // Hash ids associated with the group
1115  ids.insert(iter.val());
1116  missed = false;
1117  }
1118  }
1119  }
1120  else
1121  {
1122  const auto iter = groupPatchIDs().cfind(matcher);
1123 
1124  if (iter.good())
1125  {
1126  // Hash ids associated with the group
1127  ids.insert(iter.val());
1128  missed = false;
1129  }
1130  }
1131  }
1132 
1133  if (missed && warnNotFound)
1134  {
1135  if (checkGroups)
1136  {
1138  << "Cannot find any patch or group names matching "
1139  << matcher << endl;
1140  }
1141  else
1142  {
1144  << "Cannot find any patch names matching "
1145  << matcher << endl;
1146  }
1147  }
1148  }
1149 
1150  return ids;
1151 }
1152 
1153 
1155 (
1156  const labelUList& patchIDs,
1157  wordList& groups,
1158  labelHashSet& nonGroupPatches
1159 ) const
1160 {
1161  // Current matched groups
1162  DynamicList<word> matchedGroups(1);
1163 
1164  // Current set of unmatched patches
1165  nonGroupPatches = labelHashSet(patchIDs);
1166 
1167  const HashTable<labelList>& groupLookup = this->groupPatchIDs();
1168  forAllConstIters(groupLookup, iter)
1169  {
1170  // Store currently unmatched patches so we can restore
1171  labelHashSet oldNonGroupPatches(nonGroupPatches);
1172 
1173  // Match by deleting patches in group from the current set and seeing
1174  // if all have been deleted.
1175  labelHashSet groupPatchSet(iter.val());
1176 
1177  label nMatch = nonGroupPatches.erase(groupPatchSet);
1178 
1179  if (nMatch == groupPatchSet.size())
1180  {
1181  matchedGroups.push_back(iter.key());
1182  }
1183  else if (nMatch != 0)
1184  {
1185  // No full match. Undo.
1186  nonGroupPatches.transfer(oldNonGroupPatches);
1187  }
1188  }
1189 
1190  groups.transfer(matchedGroups);
1191 }
1192 
1193 
1194 bool Foam::polyBoundaryMesh::checkParallelSync(const bool report) const
1195 {
1196  if (!Pstream::parRun())
1197  {
1198  return false;
1199  }
1200 
1201  const polyBoundaryMesh& bm = *this;
1202 
1203  bool hasError = false;
1204 
1205  // Collect non-proc patches and check proc patches are last.
1206  wordList localNames(bm.size());
1207  wordList localTypes(bm.size());
1208 
1209  label nonProci = 0;
1210 
1211  forAll(bm, patchi)
1212  {
1213  if (!isA<processorPolyPatch>(bm[patchi]))
1214  {
1215  if (nonProci != patchi)
1216  {
1217  // A processor patch in between normal patches!
1218  hasError = true;
1219 
1220  if (debug || report)
1221  {
1222  Pout<< " ***Problem with boundary patch " << patchi
1223  << " name:" << bm[patchi].name()
1224  << " type:" << bm[patchi].type()
1225  << " - seems to be preceeded by processor patches."
1226  << " This is usually a problem." << endl;
1227  }
1228  }
1229  else
1230  {
1231  localNames[nonProci] = bm[patchi].name();
1232  localTypes[nonProci] = bm[patchi].type();
1233  ++nonProci;
1234  }
1235  }
1236  }
1237  localNames.resize(nonProci);
1238  localTypes.resize(nonProci);
1239 
1240  // Check and report error(s) on master
1241  // - don't need indexing on master itself
1242 
1243  const globalIndex procAddr(globalIndex::gatherNonLocal{}, nonProci);
1244 
1245  const wordList allNames(procAddr.gather(localNames));
1246  const wordList allTypes(procAddr.gather(localTypes));
1247 
1248  // Automatically restricted to master
1249  for (const int proci : procAddr.subProcs())
1250  {
1251  const auto procNames(allNames.slice(procAddr.range(proci)));
1252  const auto procTypes(allTypes.slice(procAddr.range(proci)));
1253 
1254  if (procNames != localNames || procTypes != localTypes)
1255  {
1256  hasError = true;
1257 
1258  if (debug || report)
1259  {
1260  Info<< " ***Inconsistent patches across processors, "
1261  "processor0 has patch names:" << localNames
1262  << " patch types:" << localTypes
1263  << " processor" << proci
1264  << " has patch names:" << procNames
1265  << " patch types:" << procTypes
1266  << endl;
1267  }
1268  }
1269  }
1270 
1271  // Reduce (not broadcast) to respect local out-of-order errors (first loop)
1272  return returnReduceOr(hasError);
1273 }
1274 
1275 
1276 bool Foam::polyBoundaryMesh::checkDefinition(const bool report) const
1277 {
1278  label nextPatchStart = mesh().nInternalFaces();
1279  const polyBoundaryMesh& bm = *this;
1280 
1281  bool hasError = false;
1282 
1283  wordHashSet patchNames(2*this->size());
1284 
1285  forAll(bm, patchi)
1286  {
1287  if (bm[patchi].start() != nextPatchStart && !hasError)
1288  {
1289  hasError = true;
1290 
1291  Info<< " ****Problem with boundary patch " << patchi
1292  << " named " << bm[patchi].name()
1293  << " of type " << bm[patchi].type()
1294  << ". The patch should start on face no " << nextPatchStart
1295  << " and the patch specifies " << bm[patchi].start()
1296  << "." << endl
1297  << "Possibly consecutive patches have this same problem."
1298  << " Suppressing future warnings." << endl;
1299  }
1300 
1301  if (!patchNames.insert(bm[patchi].name()) && !hasError)
1302  {
1303  hasError = true;
1304 
1305  Info<< " ****Duplicate boundary patch " << patchi
1306  << " named " << bm[patchi].name()
1307  << " of type " << bm[patchi].type()
1308  << "." << endl
1309  << "Suppressing future warnings." << endl;
1310  }
1311 
1312  nextPatchStart += bm[patchi].size();
1313  }
1314 
1315  Pstream::reduceOr(hasError);
1316 
1317  if (debug || report)
1318  {
1319  if (hasError)
1320  {
1321  Pout<< " ***Boundary definition is in error." << endl;
1322  }
1323  else
1324  {
1325  Info<< " Boundary definition OK." << endl;
1326  }
1327  }
1328 
1329  return hasError;
1330 }
1331 
1332 
1334 {
1335  PstreamBuffers pBufs(Pstream::defaultCommsType);
1336 
1337  if
1338  (
1339  pBufs.commsType() == Pstream::commsTypes::buffered
1340  || pBufs.commsType() == Pstream::commsTypes::nonBlocking
1341  )
1342  {
1343  forAll(*this, patchi)
1344  {
1345  operator[](patchi).initMovePoints(pBufs, p);
1346  }
1347 
1348  pBufs.finishedSends();
1349 
1350  forAll(*this, patchi)
1351  {
1352  operator[](patchi).movePoints(pBufs, p);
1353  }
1354  }
1355  else if (pBufs.commsType() == Pstream::commsTypes::scheduled)
1356  {
1357  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
1358 
1359  // Dummy.
1360  pBufs.finishedSends();
1361 
1362  for (const auto& schedEval : patchSchedule)
1363  {
1364  const label patchi = schedEval.patch;
1365 
1366  if (schedEval.init)
1367  {
1368  operator[](patchi).initMovePoints(pBufs, p);
1369  }
1370  else
1371  {
1372  operator[](patchi).movePoints(pBufs, p);
1373  }
1374  }
1375  }
1376 }
1377 
1378 
1380 {
1381  neighbourEdgesPtr_.reset(nullptr);
1382  patchIDPtr_.reset(nullptr);
1383  groupIDsPtr_.reset(nullptr);
1384 
1385  PstreamBuffers pBufs(Pstream::defaultCommsType);
1386 
1387  if
1388  (
1389  pBufs.commsType() == Pstream::commsTypes::buffered
1390  || pBufs.commsType() == Pstream::commsTypes::nonBlocking
1391  )
1392  {
1393  forAll(*this, patchi)
1394  {
1395  operator[](patchi).initUpdateMesh(pBufs);
1396  }
1397 
1398  pBufs.finishedSends();
1399 
1400  forAll(*this, patchi)
1401  {
1402  operator[](patchi).updateMesh(pBufs);
1403  }
1404  }
1405  else if (pBufs.commsType() == Pstream::commsTypes::scheduled)
1406  {
1407  const lduSchedule& patchSchedule = mesh().globalData().patchSchedule();
1408 
1409  // Dummy.
1410  pBufs.finishedSends();
1411 
1412  for (const auto& schedEval : patchSchedule)
1413  {
1414  const label patchi = schedEval.patch;
1415 
1416  if (schedEval.init)
1417  {
1418  operator[](patchi).initUpdateMesh(pBufs);
1419  }
1420  else
1421  {
1422  operator[](patchi).updateMesh(pBufs);
1423  }
1424  }
1425  }
1426 }
1427 
1428 
1430 (
1431  const labelUList& oldToNew,
1432  const bool validBoundary
1433 )
1434 {
1435  // Change order of patches
1436  polyPatchList::reorder(oldToNew);
1437 
1438  // Adapt indices
1439  polyPatchList& patches = *this;
1440 
1441  forAll(patches, patchi)
1442  {
1443  patches[patchi].index() = patchi;
1444  }
1445 
1446  // Clear group-to-patch addressing. Note: could re-calculate
1447  groupIDsPtr_.reset(nullptr);
1448 
1449  if (validBoundary)
1450  {
1451  updateMesh();
1452  }
1453 }
1454 
1455 
1456 void Foam::polyBoundaryMesh::writeEntry(Ostream& os) const
1457 {
1458  const polyPatchList& entries = *this;
1459 
1460  os << entries.size();
1461 
1462  if (entries.empty())
1463  {
1464  // 0-sized : can write with less vertical space
1466  }
1467  else
1468  {
1469  os << nl << token::BEGIN_LIST << incrIndent << nl;
1470 
1471  for (const auto& pp : entries)
1472  {
1473  os.beginBlock(pp.name());
1474  os << pp;
1475  os.endBlock();
1476  }
1478  }
1480 }
1481 
1482 
1484 (
1485  const word& keyword,
1486  Ostream& os
1487 ) const
1488 {
1489  const polyPatchList& entries = *this;
1490 
1491  if (!keyword.empty())
1492  {
1493  os.write(keyword);
1494  os << (entries.empty() ? token::SPACE : token::NL);
1495  }
1497  writeEntry(os);
1498 
1499  if (!keyword.empty()) os.endEntry();
1500 }
1501 
1502 
1505  writeEntry(os);
1506  return os.good();
1507 }
1508 
1509 
1511 (
1512  IOstreamOption streamOpt,
1513  const bool writeOnProc
1514 ) const
1515 {
1517  return regIOobject::writeObject(streamOpt, writeOnProc);
1518 }
1519 
1520 
1521 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
1522 
1524 (
1525  const word& patchName
1526 ) const
1527 {
1528  const label patchi = findPatchID(patchName);
1529 
1530  if (patchi < 0)
1531  {
1533  << "Patch named " << patchName << " not found." << nl
1534  << "Available patch names: " << names() << endl
1535  << abort(FatalError);
1536  }
1537 
1538  return operator[](patchi);
1539 }
1540 
1541 
1543 (
1544  const word& patchName
1545 )
1546 {
1547  const label patchi = findPatchID(patchName);
1548 
1549  if (patchi < 0)
1550  {
1552  << "Patch named " << patchName << " not found." << nl
1553  << "Available patch names: " << names() << endl
1554  << abort(FatalError);
1555  }
1557  return operator[](patchi);
1558 }
1559 
1560 
1561 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
1562 
1563 Foam::Ostream& Foam::operator<<(Ostream& os, const polyBoundaryMesh& pbm)
1564 {
1565  pbm.writeData(os);
1566  return os;
1567 }
1568 
1569 
1570 // ************************************************************************* //
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
label nNonProcessorFaces() const
The number of boundary faces before the first processor patch.
labelRange range(const label proci) const
Return start/size range of proci data.
Definition: globalIndexI.H:282
label patchId(-1)
const labelList patchIDs(pbm.indices(polyPatchNames, true))
const polyBoundaryMesh & pbm
labelList patchSizes() const
Return a list of patch sizes.
dictionary dict
const List< labelPairList > & neighbourEdges() const
Per patch the edges on the neighbouring patch.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
autoPtr< IOobject > clone() const
Clone.
Definition: IOobject.H:629
labelList findMatching(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Extract list indices for all items with &#39;name()&#39; that matches.
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Binary search to find the index of the last element in a sorted list that is less than value...
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
virtual const fileName & name() const
The name of the stream.
Definition: IOstream.C:33
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
static int incrMsgType(int val=1) noexcept
Increment the message tag for standard messages.
Definition: UPstream.H:1809
const Field< point_type > & localPoints() const
Return pointField of points in patch.
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:45
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
void setGroup(const word &groupName, const labelUList &patchIDs)
Set/add group with patches.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
labelHashSet patchSet(const UList< wordRe > &select, const bool warnNotFound=true, const bool useGroups=true) const
Return the set of patch IDs corresponding to the given names.
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
polyBoundaryMesh(const polyBoundaryMesh &)=delete
No copy construct.
List< bool > select(const label n, const labelUList &locations)
Construct a selection list of bools (all false) with the given pre-size, subsequently add specified l...
Definition: BitOps.C:134
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:697
Type type(bool followLink=true, bool checkGzip=false) const
Return the directory entry type: UNDEFINED, FILE, DIRECTORY (or SYMLINK).
Definition: fileName.C:353
virtual bool writeData(Ostream &os) const
The writeData member function required by regIOobject.
Newline [isspace].
Definition: token.H:130
void reorder(const labelUList &oldToNew, const bool validBoundary)
Reorders patches. Ordering does not have to be done in.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
labelPair whichPatchFace(const label meshFacei) const
Lookup mesh face index and return (patchi, patchFacei) tuple or (-1, meshFacei) for internal faces...
const labelList & patchID() const
Per boundary face label the patch index.
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
void reorder(const labelUList &oldToNew, const bool check=false)
Reorder elements. Reordering must be unique (ie, shuffle).
Definition: UPtrList.C:79
wordList groupNames() const
A list of the group names (if any)
label nInternalEdges() const
Number of internal edges.
void clearGeom()
Clear geometry at this level and at patches.
Begin list [isseparator].
Definition: token.H:161
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1787
labelRange range() const noexcept
The face range for all boundary faces.
List< lduScheduleEntry > lduSchedule
A List of lduSchedule entries.
Definition: lduSchedule.H:46
List< labelPair > labelPairList
List of labelPair.
Definition: labelPair.H:33
Functions to operate on Pointer Lists.
A simple container for options an IOstream can normally have.
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, UList< Type > &allFld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
SubList< face > subList
Declare type of subList.
Definition: List.H:149
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:52
wordList types() const
Return a list of patch types.
label nFaces() const noexcept
Number of mesh faces.
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:134
void movePoints(const pointField &p)
Correct polyBoundaryMesh after moving points.
scalar range
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Extract name (as a word) from an object, typically using its name() method.
Definition: word.H:340
label nProcessorPatches() const
The number of processorPolyPatch patches.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
labelList indices(const wordRe &matcher, const bool useGroups=true) const
The (sorted) patch indices for all matches, optionally matching patch groups.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
Definition: polyPatch.H:56
void matchGroups(const labelUList &patchIDs, wordList &groups, labelHashSet &nonGroupPatches) const
Match the patches to groups.
void resize_null(const label newLen)
Set the addressed list to the given size, deleting all existing entries. Afterwards the list contains...
Definition: PtrListI.H:96
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
A non-owning sub-view of a List (allocated or unallocated storage).
Definition: SubList.H:46
UPtrList< const labelUList > faceCells() const
Return a list of faceCells for each patch.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
A class for handling words, derived from Foam::string.
Definition: word.H:63
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:406
bool checkDefinition(const bool report=false) const
Check boundary definition.
wordList names() const
Return a list of patch names.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:108
Space [isspace].
Definition: token.H:131
wordList patchNames(nPatches)
const globalMeshData & globalData() const
Return parallel info (demand-driven)
Definition: polyMesh.C:1296
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
label nInternalFaces() const noexcept
Number of internal faces.
End list [isseparator].
Definition: token.H:162
auto key(const Type &t) -> std::enable_if_t< std::is_enum_v< Type >, std::underlying_type_t< Type > >
Definition: foamGltfBase.H:103
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
wordList physicalTypes() const
Return a list of physical types.
friend Ostream & operator(Ostream &os, const UPtrList< T > &list)
Write UPtrList to Ostream.
A HashTable similar to std::unordered_map.
Definition: HashTable.H:108
const HashTable< labelList > & groupPatchIDs() const
The patch indices per patch group.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:106
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:159
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings...
Definition: wordRe.H:78
const faceList::subList faces() const
Return mesh faces for the entire boundary.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: scalarImpl.H:255
void clear()
Clear the patch list and all demand-driven data.
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
label nEdges() const
Number of edges in patch.
void writeEntry(Ostream &os) const
Write as a plain list of entries.
int debug
Static debugging option.
void updateMesh()
Correct polyBoundaryMesh after topology update.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
std::enable_if_t< std::is_same_v< bool, TypeT >, bool > unset(const label i)
Unset the bool entry at specified position, always false for out-of-range access. ...
Definition: UList.H:827
defineTypeNameAndDebug(combustionModel, 0)
compressionType compression() const noexcept
Get the stream compression.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:509
labelList patchStarts() const
Return a list of patch start face indices.
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes)
Definition: globalIndexI.H:197
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:489
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:77
List< word > wordList
List of word.
Definition: fileName.H:59
label nFaces() const noexcept
The number of boundary faces in the underlying mesh.
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:963
#define WarningInFunction
Report a warning using Foam::Warning.
globalIndex procAddr(aMesh.nFaces())
List< labelRange > patchRanges() const
Return a list of patch ranges.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:54
void clearAddressing()
Clear addressing at this level and at patches.
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
void reserve(label numEntries)
Reserve space for at least the specified number of elements (not the number of buckets) and regenerat...
Definition: HashTable.C:729
const lduSchedule & patchSchedule() const noexcept
Order in which the patches should be initialised/evaluated corresponding to the schedule.
const polyBoundaryMesh & patches
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:68
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:81
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:90
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:44
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return pointer to a new patch created on freestore from components.
Definition: polyPatchNew.C:28
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
List< label > labelList
A List of labels.
Definition: List.H:61
volScalarField & p
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc=true) const
Write using stream options, but always UNCOMPRESSED.
virtual Ostream & endEntry()
Write end entry (&#39;;&#39;) followed by newline.
Definition: Ostream.C:117
"buffered" : (MPI_Bsend, MPI_Recv)
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
label nNonProcessor() const
The number of patches before the first processor patch.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:500
static void reduceOr(bool &value, const int communicator=worldComm)
Logical (or) reduction (MPI_AllReduce)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
List< bool > boolList
A List of bools.
Definition: List.H:59
bool isPattern() const noexcept
The wordRe is a pattern, not a literal string.
Definition: wordReI.H:104
label findIndex(const wordRe &key) const
Return patch index for the first match, return -1 if not found.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Extract type (as a word) from an object, typically using its type() method.
Definition: word.H:361
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label firstMatching(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Find first list item with &#39;name()&#39; that matches, -1 on failure.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
const labelList::subList faceOwner() const
Return face owner for the entire boundary.