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-2020 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 (bool(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 }
360 
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 :
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 :
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.found())
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 (returnReduce(!updateLookup.empty(), orOp<bool>()));
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(), labelHashSet(0));
725 
726  // Use estimate of sizing for non-local regions
727  forAll(nonLocal, proci)
728  {
729  if (proci != Pstream::myProcNo())
730  {
731  nonLocal[proci].resize
732  (
733  2*((nLocalRegions-nCompact)/Pstream::nProcs())
734  );
735  }
736  }
737 
738 
739  forAllConstIters(localToGlobal, iter)
740  {
741  const label regioni = iter.val();
742 
743  if (globalRegions.isLocal(regioni))
744  {
745  updateLookup.insert
746  (
747  regioni,
748  globalCompact.toGlobal(updateLookup.size())
749  );
750  }
751  else
752  {
753  nonLocal[globalRegions.whichProcID(regioni)].insert(regioni);
754  }
755  }
756 
757  if (debug)
758  {
759  Pout<< " per processor nonLocal regions: "
760  << flatOutput(containerSizes(nonLocal)) << endl;
761  }
762 
763 
764  // Convert to label list
765  forAll(sendNonLocal, proci)
766  {
767  sendNonLocal[proci] = nonLocal[proci].toc();
768  }
769  }
770 
771 
772  // Get the wanted region labels into recvNonLocal
773  labelListList recvNonLocal;
774  Pstream::exchange<labelList, label>
775  (
776  sendNonLocal,
777  recvNonLocal
778  );
779 
780 
781  // The recvNonLocal[proci] region labels are what proci requires.
782  // Transcribe into their compacted number.
783 
784  {
785  labelListList sendLocal(std::move(recvNonLocal));
786 
787  for (labelList& send : sendLocal)
788  {
789  for (label& regioni : send)
790  {
791  regioni = updateLookup[regioni];
792  }
793  }
794 
795  // Send back (into recvNonLocal)
796  Pstream::exchange<labelList, label>
797  (
798  sendLocal,
799  recvNonLocal
800  );
801  }
802 
803 
804  // Now recvNonLocal and sendNonLocal contain matched pairs with
805  // sendNonLocal being the non-compact region and recvNonLocal being
806  // the compact region.
807  //
808  // Insert these into the local compaction map.
809 
810  forAll(recvNonLocal, proci)
811  {
812  const labelList& send = sendNonLocal[proci];
813  const labelList& recv = recvNonLocal[proci];
814 
815  forAll(send, i)
816  {
817  updateLookup.insert(send[i], recv[i]);
818  }
819  }
820 
821 
822  // Now renumber the localToGlobal to use the final compact global values
823  inplaceMapValue(updateLookup, localToGlobal);
824 
825 
826  // Can now finally use localToGlobal to renumber cellRegion
827 
828  forAll(cellRegion, celli)
829  {
830  cellRegion[celli] = localToGlobal[cellRegion[celli]];
831  }
832 
833  DebugInfo
834  <<"regionSplit::reduceRegions = " << double(timing.elapsed()) << "s\n";
835 
836  return globalCompact;
837 }
838 
839 
842 (
843  const label numLocalRegions,
844  const bitSet& blockedFace,
845 
846  labelList& cellRegion
847 ) const
848 {
849  // Wrap bitset or bools
850  bitSetOrBoolList hasBlockedFace(blockedFace);
851 
852  return reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
853 }
854 
855 
856 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
Foam::HashTable::size
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
UNASSIGNED
static constexpr Foam::label UNASSIGNED
Definition: regionSplit.C:43
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
cyclicPolyPatch.H
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
globalIndex.H
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:439
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:69
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:182
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::regionSplit::regionSplit
regionSplit(const polyMesh &mesh, const bool doGlobalRegions=Pstream::parRun())
Construct from mesh.
Definition: regionSplit.C:365
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::labelPair
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:54
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
clockValue.H
Foam::MeshObject< polyMesh, TopologicalMeshObject, regionSplit >::mesh
const polyMesh & mesh() const
Definition: MeshObject.H:122
Foam::OSstream::name
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:107
Foam::containerSizes
static labelList containerSizes(const UList< Container > &input)
The sizes of a List of containers (eg, labelHashSet)
Definition: regionSplit.C:54
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
regionSplit.H
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Definition: polyBoundaryMesh.C:810
Foam::regionSplit
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:140
Foam::inplaceMapValue
label inplaceMapValue(const labelUList &oldToNew, Container &input)
Map values. Ignore negative values.
Foam::clockValue
Access to high-resolution clock value with some basic operations. Used to calculate time durations,...
Definition: clockValue.H:53
Foam::FatalError
error FatalError
processorPolyPatch.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::PtrList::clear
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:97
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:217
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
BLOCKED
static constexpr Foam::label BLOCKED
Definition: regionSplit.C:44
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::regionSplit::reduceRegions
globalIndex reduceRegions(const label numLocalRegions, const bitSet &blockedFace, labelList &cellRegion) const
Manually consolidate regions globally by swapping information.
Definition: regionSplit.C:842
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:359
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:464
Foam::nl
constexpr char nl
Definition: Ostream.H:385
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::syncTools::swapFaceList
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled face values. Uses eqOp.
Definition: syncTools.H:472
Foam::List< label >
Foam::UList
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:103
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::input
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:55
Foam::MeshObject
Templated abstract base-class for optional mesh objects used to automate their allocation to the mesh...
Definition: MeshObject.H:88
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::labelUList
UList< label > labelUList
A UList of labels.
Definition: UList.H:80
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys and label hasher.
Definition: HashSet.H:409
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Number of processes in parallel run, and 1 for serial run.
Definition: UPstream.H:446