Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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 * * * * * * * * * * * * * //
38namespace Foam
39{
40 defineTypeNameAndDebug(regionSplit, 0);
41}
42
43static constexpr Foam::label UNASSIGNED = -1;
44static constexpr Foam::label BLOCKED = -2;
45
46
47// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
48
49namespace Foam
50{
51
52//- The sizes of a List of containers (eg, labelHashSet)
53template<class Container>
54static labelList containerSizes(const UList<Container>& input)
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
73void 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
103void 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
153void 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
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 {
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
280Foam::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;
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:
388 MeshObject_type(mesh),
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_type(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
479Foam::globalIndex
480Foam::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
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 {
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;
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)
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
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// ************************************************************************* //
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
label size() const noexcept
The number of elements in table.
Definition HashTable.H:358
label size() const noexcept
The number of elements in the list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
static void exchange(const UList< Container > &sendBufs, const labelUList &recvSizes, List< Container > &recvBufs, const int tag=UPstream::msgType(), const int comm=UPstream::worldComm, const bool wait=true)
Helper: exchange contiguous data. Sends sendBufs, receives into recvBufs using predetermined receive ...
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
bool test(const label i) const
Test bool value at specified position, always false for out-of-range access.
Definition UList.H:852
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
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:1697
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition bitSet.H:61
Access to high-resolution clock value with some basic operations. Used to calculate time durations,...
Definition clockValue.H:50
Cyclic plane patch.
Smooth ATC in cells next to a set of patches supplied by type.
Definition faceCells.H:55
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition polyMesh.C:1107
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
label nCells() const noexcept
Number of mesh cells.
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
globalIndex reduceRegions(const label numLocalRegions, const bitSet &blockedFace, labelList &cellRegion) const
Manually consolidate regions globally by swapping information.
regionSplit(const polyMesh &mesh, const bool doGlobalRegions=Pstream::parRun())
Construct from mesh.
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues, const bool parRun=UPstream::parRun())
Swap coupled face values. Uses eqOp.
Definition syncTools.H:567
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const bool parRun=UPstream::parRun())
Swap coupled boundary face values. Uses eqOp.
Definition syncTools.H:524
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const cellShapeList & cells
#define DebugInfo
Report an information message using Foam::Info.
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
Pair< label > labelPair
A pair of labels.
Definition Pair.H:54
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
label inplaceMapValue(const labelUList &oldToNew, Container &input)
Map values. Ignore negative values.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
errorManip< error > abort(error &err)
Definition errorManip.H:139
List< bool > boolList
A List of bools.
Definition List.H:60
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
UList< label > labelUList
A UList of labels.
Definition UList.H:75
static labelList containerSizes(const UList< Container > &input)
The sizes of a List of containers (eg, labelHashSet).
Definition regionSplit.C:49
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
static constexpr Foam::label UNASSIGNED
Definition regionSplit.C:36
static constexpr Foam::label BLOCKED
Definition regionSplit.C:37
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235