regionSplit.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-2013 OpenFOAM Foundation
9  Copyright (C) 2018-2022 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 "regionSplit.H"
30 #include "cyclicPolyPatch.H"
31 #include "processorPolyPatch.H"
32 #include "globalIndex.H"
33 #include "syncTools.H"
34 #include "clockValue.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40  defineTypeNameAndDebug(regionSplit, 0);
41 }
42 
43 static constexpr Foam::label UNASSIGNED = -1;
44 static constexpr Foam::label BLOCKED = -2;
45 
46 
47 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
48 
49 namespace Foam
50 {
51 
52 //- The sizes of a List of containers (eg, labelHashSet)
53 template<class Container>
55 {
56  const label len = input.size();
57 
58  labelList output(len);
59 
60  for (label i = 0; i < len; ++i)
61  {
62  output[i] = input[i].size();
63  }
64 
65  return output;
66 }
67 
68 } // End namespace Foam
69 
70 
71 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
72 
73 void Foam::regionSplit::checkBoundaryFaceSync
74 (
75  const boolList& blockedFace
76 ) const
77 {
78  if (blockedFace.size())
79  {
80  // Check that blockedFace is synced.
81  boolList syncBlockedFace(blockedFace);
82  syncTools::swapFaceList(mesh(), syncBlockedFace);
83 
84  forAll(syncBlockedFace, facei)
85  {
86  if
87  (
88  blockedFace.test(facei)
89  != syncBlockedFace.test(facei)
90  )
91  {
93  << "Face " << facei << " not synchronised. My value:"
94  << blockedFace.test(facei) << " coupled value:"
95  << syncBlockedFace.test(facei) << nl
96  << abort(FatalError);
97  }
98  }
99  }
100 }
101 
102 
103 void Foam::regionSplit::updateFacePair
104 (
105  const label face0,
106  const label face1,
107 
108  labelList& faceRegion,
109  DynamicList<label>& facesChanged
110 ) const
111 {
112  if (faceRegion[face0] == UNASSIGNED)
113  {
114  if (faceRegion[face1] >= 0)
115  {
116  faceRegion[face0] = faceRegion[face1];
117  facesChanged.append(face0);
118  }
119  else if (faceRegion[face1] == BLOCKED)
120  {
121  // face1 blocked but not face0.
122  // - illegal for coupled faces, OK for explicit connections.
123  }
124  }
125  else if (faceRegion[face0] >= 0)
126  {
127  if (faceRegion[face1] == UNASSIGNED)
128  {
129  faceRegion[face1] = faceRegion[face0];
130  facesChanged.append(face1);
131  }
132  else if (faceRegion[face1] == BLOCKED)
133  {
134  // face1 blocked but not face0.
135  // - illegal for coupled faces, OK for explicit connections.
136  }
137  else if (faceRegion[face1] != faceRegion[face0])
138  {
140  << "Problem : coupled face " << face0
141  << " on patch " << mesh().boundaryMesh().whichPatch(face0)
142  << " has region " << faceRegion[face0]
143  << " but coupled face " << face1
144  << " has region " << faceRegion[face1] << nl
145  << "Is your blocked faces specification"
146  << " synchronized across coupled boundaries?" << endl
147  << abort(FatalError);
148  }
149  }
150 }
151 
152 
153 void Foam::regionSplit::fillSeedMask
154 (
155  const UList<labelPair>& explicitConnections,
156  const label seedCellId,
157  const label markValue,
158  labelList& cellRegion,
159  labelList& faceRegion
160 ) const
161 {
162  // Seed cell
163  cellRegion[seedCellId] = markValue;
164 
165  // Faces on seed cell
166  changedFaces_.clear();
167  for (const label facei : mesh().cells()[seedCellId])
168  {
169  if (faceRegion[facei] == UNASSIGNED)
170  {
171  faceRegion[facei] = markValue;
172  changedFaces_.append(facei);
173  }
174  }
175 
176  const polyBoundaryMesh& patches = mesh().boundaryMesh();
177 
178  // Loop over changed faces. FaceCellWave in small.
179 
180  while (changedFaces_.size())
181  {
182  changedCells_.clear();
183 
184  for (const label facei : changedFaces_)
185  {
186  const label own = mesh().faceOwner()[facei];
187 
188  if (cellRegion[own] == UNASSIGNED)
189  {
190  cellRegion[own] = markValue;
191  changedCells_.append(own);
192  }
193 
194  if (mesh().isInternalFace(facei))
195  {
196  const label nei = mesh().faceNeighbour()[facei];
197 
198  if (cellRegion[nei] == UNASSIGNED)
199  {
200  cellRegion[nei] = markValue;
201  changedCells_.append(nei);
202  }
203  }
204  }
205 
206  if (debug & 2)
207  {
208  Pout<< " Changed cells / faces : "
209  << changedCells_.size() << " / " << changedFaces_.size()
210  << " before sync" << endl;
211  }
212 
213  // Loop over changedCells and collect faces
214  changedFaces_.clear();
215  for (const label celli : changedCells_)
216  {
217  for (const label facei : mesh().cells()[celli])
218  {
219  if (faceRegion[facei] == UNASSIGNED)
220  {
221  faceRegion[facei] = markValue;
222  changedFaces_.append(facei);
223  }
224  }
225  }
226 
227 
228  // Update locally coupled faces
229  // Global connections are done later.
230 
231  for (const polyPatch& pp : patches)
232  {
233  const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
234 
235  if (cpp && cpp->owner())
236  {
237  // Transfer from neighbourPatch to here or vice versa.
238  const auto& cycPatch = *cpp;
239 
240  label face0 = cycPatch.start();
241 
242  forAll(cycPatch, i)
243  {
244  const label face1 = cycPatch.transformGlobalFace(face0);
245 
246  updateFacePair
247  (
248  face0,
249  face1,
250  faceRegion,
251  changedFaces_
252  );
253 
254  ++face0;
255  }
256  }
257  }
258 
259  for (const labelPair& pr : explicitConnections)
260  {
261  updateFacePair
262  (
263  pr.first(),
264  pr.second(),
265  faceRegion,
266  changedFaces_
267  );
268  }
269 
270  if (debug & 2)
271  {
272  Pout<< " Changed faces : "
273  << changedFaces_.size()
274  << " after sync" << endl;
275  }
276  }
277 }
278 
279 
280 Foam::label Foam::regionSplit::localRegionSplit
281 (
282  const UList<labelPair>& explicitConnections,
283 
284  labelList& cellRegion,
285  labelList& faceRegion
286 ) const
287 {
288  clockValue timing(debug);
289 
290  changedCells_.reserve(mesh_.nCells());
291  changedFaces_.reserve(mesh_.nFaces());
292 
293 
294  // Assign local regions
295  // ~~~~~~~~~~~~~~~~~~~~
296 
297  // Start with region 0
298  label nLocalRegions = 0;
299 
300  for (label seedCellId = 0; seedCellId < cellRegion.size(); ++seedCellId)
301  {
302  // Find next unset cell - use as seed
303 
304  for (; seedCellId < cellRegion.size(); ++seedCellId)
305  {
306  if (cellRegion[seedCellId] == UNASSIGNED)
307  {
308  break;
309  }
310  }
311 
312  if (seedCellId >= cellRegion.size())
313  {
314  break;
315  }
316 
317  fillSeedMask
318  (
319  explicitConnections,
320  seedCellId,
321  nLocalRegions,
322  cellRegion,
323  faceRegion
324  );
325 
326  ++nLocalRegions; // Next region
327  }
328 
329  // Discard temporary working data
330  changedCells_.clearStorage();
331  changedFaces_.clearStorage();
332 
333  if (debug)
334  {
335  forAll(cellRegion, celli)
336  {
337  if (cellRegion[celli] < 0)
338  {
340  << "cell:" << celli << " region:" << cellRegion[celli]
341  << abort(FatalError);
342  }
343  }
344 
345  forAll(faceRegion, facei)
346  {
347  if (faceRegion[facei] == UNASSIGNED)
348  {
350  << "face:" << facei << " region:" << faceRegion[facei]
351  << abort(FatalError);
352  }
353  }
354  }
355 
356  DebugInfo << "regionSplit = " << double(timing.elapsed()) << "s\n";
357 
358  return nLocalRegions;
359 }
361 
362 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
363 
365 (
366  const polyMesh& mesh,
367  const bool doGlobalRegions
368 )
369 :
371  (
372  mesh,
373  bitSet(), // No blockedFace
374  List<labelPair>(), // No explicitConnections
375  doGlobalRegions
376  )
377 {}
378 
379 
381 (
382  const polyMesh& mesh,
383  const bitSet& blockedFace,
384  const List<labelPair>& explicitConnections,
385  const bool doGlobalRegions
386 )
387 :
389  labelList(mesh.nCells(), UNASSIGNED),
390  globalNumbering_()
391 {
392  // if (debug)
393  // {
394  // checkBoundaryFaceSync(blockedFace);
395  // }
396 
397  labelList& cellRegion = *this;
398 
399  labelList faceRegion(mesh.nFaces(), UNASSIGNED);
400 
401  for (const label facei : blockedFace)
402  {
403  faceRegion[facei] = BLOCKED;
404  }
405 
406  const label numLocalRegions =
407  localRegionSplit(explicitConnections, cellRegion, faceRegion);
408 
409  faceRegion.clear();
410 
411  if (doGlobalRegions)
412  {
413  // Wrap bitset or bools
414  bitSetOrBoolList hasBlockedFace(blockedFace);
415 
416  globalNumbering_ =
417  reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
418 
419  }
420  else
421  {
422  globalNumbering_ = globalIndex(numLocalRegions);
423  }
424 }
425 
426 
428 (
429  const polyMesh& mesh,
430  const boolList& blockedFace,
431  const List<labelPair>& explicitConnections,
432  const bool doGlobalRegions
433 )
434 :
435  MeshObject<polyMesh, Foam::TopologicalMeshObject, regionSplit>(mesh),
436  labelList(mesh.nCells(), UNASSIGNED),
437  globalNumbering_()
438 {
439  if (debug)
440  {
441  checkBoundaryFaceSync(blockedFace);
442  }
443 
444  labelList& cellRegion = *this;
445 
446  labelList faceRegion(mesh.nFaces(), UNASSIGNED);
447 
448  forAll(blockedFace, facei)
449  {
450  if (blockedFace.test(facei))
451  {
452  faceRegion[facei] = BLOCKED;
453  }
454  }
455 
456 
457  const label numLocalRegions =
458  localRegionSplit(explicitConnections, cellRegion, faceRegion);
459 
460  faceRegion.clear();
461 
462  if (doGlobalRegions)
463  {
464  // Wrap bitset or bools
465  bitSetOrBoolList hasBlockedFace(blockedFace);
466 
467  globalNumbering_ =
468  reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
469  }
470  else
471  {
472  globalNumbering_ = globalIndex(numLocalRegions);
473  }
474 }
475 
476 
477 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
478 
480 Foam::regionSplit::reduceRegionsImpl
481 (
482  const label numLocalRegions,
483  const bitSetOrBoolList& blockedFace,
484  labelList& cellRegion
485 ) const
486 {
487  clockValue timing(debug);
488 
489  if (cellRegion.size() != mesh().nCells())
490  {
492  << "The cellRegion size " << cellRegion.size()
493  << " != number of cells " << mesh().nCells() << endl
494  << abort(FatalError);
495  }
496 
497 
498  // (numLocalRegions < 0) to signal that region information should be
499  // determined ourselves. This is not really efficient, but can be useful
500 
501  const label nLocalRegions =
502  (
503  numLocalRegions < 0
504  ? labelHashSet(cellRegion).size()
505  : numLocalRegions
506  );
507 
508 
509  // Preliminary global region numbers
510  const globalIndex globalRegions(nLocalRegions);
511 
512 
513  // Lookup table of local region to global region.
514  // Initially an identity mapping of the uncombined global values.
515 
516  Map<label> localToGlobal(2*nLocalRegions);
517  for (const label regioni : cellRegion)
518  {
519  localToGlobal.insert(regioni, globalRegions.toGlobal(regioni));
520  }
521 
522  // To update the localToGlobal mapping during traversal of the boundaries
523  // and later when finalizing things.
524  Map<label> updateLookup(2*nLocalRegions);
525 
526 
527  // Note that we use two separate maps during the process.
528  // The localToGlobal is used to map the local to global regions.
529  // Merging across processors will normally make this a many->few mapping.
530  // However, we may need to walk up and down processor boundaries several
531  // times before all the information propagates through.
532  // During these traversals, it will normally be more efficient to just
533  // update the mapping without updating the cellRegion immediately.
534  // Only after everything is finalized do we renumber all of the cell
535  // regions.
536 
537 
538  // Merge global regions
539  // ~~~~~~~~~~~~~~~~~~~~
540  // Regions across non-blocked proc patches get merged.
541  // This will set merged global regions to be the min of both.
542  // (this will create gaps in the global region list so they will get
543  // merged later on)
544 
545  const polyBoundaryMesh& patches = mesh().boundaryMesh();
546 
547  // Buffer for swapping boundary information
548  labelList nbrRegion(mesh().nBoundaryFaces());
549 
550  bool emitWarning = true;
551 
552  do
553  {
554  if (debug)
555  {
556  Pout<< nl << "-- Starting Iteration --" << endl;
557  }
558 
559  updateLookup.clear();
560  nbrRegion = UNASSIGNED;
561 
562  // Region information to send
563  for (const polyPatch& pp : patches)
564  {
565  if (pp.coupled())
566  {
567  SubList<label> patchNbrRegion
568  (
569  nbrRegion,
570  pp.size(),
571  pp.offset()
572  );
573 
574  const labelUList& faceCells = pp.faceCells();
575  forAll(faceCells, patchFacei)
576  {
577  const label celli = faceCells[patchFacei];
578  const label meshFacei = pp.start()+patchFacei;
579 
580  if (!blockedFace.test(meshFacei))
581  {
582  // Send the most currently updated region Id
583  const label orig = cellRegion[celli];
584 
585  patchNbrRegion[patchFacei] = localToGlobal[orig];
586  }
587  }
588  }
589  }
591 
592  // Receive and reduce region information
593  for (const polyPatch& pp : patches)
594  {
595  if (pp.coupled())
596  {
597  SubList<label> patchNbrRegion
598  (
599  nbrRegion,
600  pp.size(),
601  pp.offset()
602  );
603 
604  const labelUList& faceCells = pp.faceCells();
605  forAll(faceCells, patchFacei)
606  {
607  const label celli = faceCells[patchFacei];
608  const label meshFacei = pp.start()+patchFacei;
609 
610  if (!blockedFace.test(meshFacei))
611  {
612  // Reduction by retaining the min region id.
613 
614  const label orig = cellRegion[celli];
615 
616  const label sent = localToGlobal[orig];
617  const label recv = patchNbrRegion[patchFacei];
618 
619  if (recv == UNASSIGNED)
620  {
621  if (emitWarning)
622  {
623  Pout<<"Warning in regionSplit:"
624  " received unassigned on "
625  << pp.name() << " at patchFace "
626  << patchFacei
627  << ". Check synchronisation in caller"
628  << nl;
629  }
630  }
631  else if (recv < sent)
632  {
633  // Record the minimum value seen
634 
635  auto fnd = updateLookup.find(sent);
636  if (!fnd.good())
637  {
638  updateLookup.insert(sent, recv);
639  }
640  else if (recv < *fnd)
641  {
642  *fnd = recv;
643  }
644  }
645  }
646  }
647  }
648  }
649 
650 
651  // Note: by always using the minimum region number across the
652  // processor faces, we effect a consolidation of connected regions
653  // and converge to a unique number for each distinct region.
654 
655 
656  // Update localToGlobal according to newly exchanged information
657 
658  inplaceMapValue(updateLookup, localToGlobal);
659 
660  if (debug & 2)
661  {
662  labelList keys(localToGlobal.sortedToc());
663  labelList vals(keys.size());
664  forAll(keys, i)
665  {
666  vals[i] = localToGlobal[keys[i]];
667  }
668 
669  Pout<< "Updated local regions:" << nl
670  << "old: " << flatOutput(keys) << nl
671  << "new: " << flatOutput(vals) << endl;
672  }
673  else if (debug)
674  {
675  Pout<< "Updated " << localToGlobal.size()
676  << " local regions" << endl;
677  }
678 
679  emitWarning = false;
680  // Continue until there are no further changes
681  }
682  while (returnReduceOr(updateLookup.size()));
683 
684 
685  //
686  // We will need compact numbers locally and non-locally
687  //
688 
689  // Determine the local compact numbering
690  label nCompact = 0;
691  {
692  labelHashSet localRegion(2*localToGlobal.size());
693 
694  forAllConstIters(localToGlobal, iter)
695  {
696  const label regioni = iter.val();
697 
698  if (globalRegions.isLocal(regioni))
699  {
700  localRegion.insert(regioni);
701  }
702  }
703 
704  nCompact = localRegion.size();
705  }
706 
707 
708  // The new global numbering using compacted local regions
709  globalIndex globalCompact(nCompact);
710 
711 
712  // Determine the following:
713  // - the local compact regions (store as updateLookup)
714  // - the non-local regions, ordered according to the processor on which
715  // they are local.
716 
717 
718  // The local compaction map (updated local to compact local numbering)
719  updateLookup.clear();
720 
721  labelListList sendNonLocal(Pstream::nProcs());
722 
723  {
724  List<labelHashSet> nonLocal(Pstream::nProcs());
725 
726  // Use estimate of sizing for non-local regions
727  label estimatedCount((nLocalRegions-nCompact)/Pstream::nProcs());
728 
729  forAll(nonLocal, proci)
730  {
731  if (proci != Pstream::myProcNo())
732  {
733  nonLocal[proci].reserve(estimatedCount);
734  }
735  }
736 
737 
738  forAllConstIters(localToGlobal, iter)
739  {
740  const label regioni = iter.val();
741 
742  if (globalRegions.isLocal(regioni))
743  {
744  updateLookup.insert
745  (
746  regioni,
747  globalCompact.toGlobal(updateLookup.size())
748  );
749  }
750  else
751  {
752  nonLocal[globalRegions.whichProcID(regioni)].insert(regioni);
753  }
754  }
755 
756  if (debug)
757  {
758  Pout<< " per processor nonLocal regions: "
759  << flatOutput(containerSizes(nonLocal)) << endl;
760  }
761 
762 
763  // Convert to label list
764  forAll(sendNonLocal, proci)
765  {
766  sendNonLocal[proci] = nonLocal[proci].toc();
767  }
768  }
769 
770 
771  // Get the wanted region labels into recvNonLocal
772  labelListList recvNonLocal;
773  Pstream::exchange<labelList, label>
774  (
775  sendNonLocal,
776  recvNonLocal
777  );
778 
779 
780  // The recvNonLocal[proci] region labels are what proci requires.
781  // Transcribe into their compacted number.
782 
783  {
784  labelListList sendLocal(std::move(recvNonLocal));
785 
786  for (labelList& send : sendLocal)
787  {
788  for (label& regioni : send)
789  {
790  regioni = updateLookup[regioni];
791  }
792  }
793 
794  // Send back (into recvNonLocal)
795  Pstream::exchange<labelList, label>
796  (
797  sendLocal,
798  recvNonLocal
799  );
800  }
801 
802 
803  // Now recvNonLocal and sendNonLocal contain matched pairs with
804  // sendNonLocal being the non-compact region and recvNonLocal being
805  // the compact region.
806  //
807  // Insert these into the local compaction map.
808 
809  forAll(recvNonLocal, proci)
810  {
811  const labelList& send = sendNonLocal[proci];
812  const labelList& recv = recvNonLocal[proci];
813 
814  forAll(send, i)
815  {
816  updateLookup.insert(send[i], recv[i]);
817  }
818  }
819 
820 
821  // Now renumber the localToGlobal to use the final compact global values
822  inplaceMapValue(updateLookup, localToGlobal);
823 
824 
825  // Can now finally use localToGlobal to renumber cellRegion
826 
827  forAll(cellRegion, celli)
828  {
829  cellRegion[celli] = localToGlobal[cellRegion[celli]];
830  }
831 
832  DebugInfo
833  <<"regionSplit::reduceRegions = " << double(timing.elapsed()) << "s\n";
834 
835  return globalCompact;
836 }
837 
838 
841 (
842  const label numLocalRegions,
843  const bitSet& blockedFace,
844 
845  labelList& cellRegion
846 ) const
847 {
848  // Wrap bitset or bools
849  bitSetOrBoolList hasBlockedFace(blockedFace);
850 
851  return reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
852 }
853 
854 
855 // ************************************************************************* //
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:136
regionSplit(const polyMesh &mesh, const bool doGlobalRegions=Pstream::parRun())
Construct from mesh.
Definition: regionSplit.C:360
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:598
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
label inplaceMapValue(const labelUList &oldToNew, Container &input)
Map values. Ignore negative values.
static constexpr Foam::label UNASSIGNED
Definition: regionSplit.C:36
static labelList containerSizes(const UList< Container > &input)
The sizes of a List of containers (eg, labelHashSet)
Definition: regionSplit.C:49
label nFaces() const noexcept
Number of mesh faces.
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
Templated abstract base-class for optional mesh objects used to automate their allocation to the mesh...
Definition: MeshObject.H:85
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
globalIndex reduceRegions(const label numLocalRegions, const bitSet &blockedFace, labelList &cellRegion) const
Manually consolidate regions globally by swapping information.
Definition: regionSplit.C:836
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
dynamicFvMesh & mesh
const cellShapeList & cells
const polyMesh & mesh() const noexcept
Reference to the mesh.
Definition: MeshObject.H:157
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:608
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:33
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
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:105
#define DebugInfo
Report an information message using Foam::Info.
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled face values. Uses eqOp.
Definition: syncTools.H:522
void clear()
Clear the patch list and all demand-driven data.
int debug
Static debugging option.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
defineTypeNameAndDebug(combustionModel, 0)
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
label nCells() const noexcept
Number of mesh cells.
static constexpr Foam::label BLOCKED
Definition: regionSplit.C:37
const polyBoundaryMesh & patches
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:44
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:485
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225