Loading...
Searching...
No Matches
decompositionMethod.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-2016 OpenFOAM Foundation
9 Copyright (C) 2015-2023 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 "decompositionMethod.H"
30#include "globalIndex.H"
31#include "globalMeshData.H"
32#include "syncTools.H"
33#include "faceSet.H"
34#include "regionSplit.H"
35#include "localPointRegion.H"
36#include "minData.H"
37#include "BitOps.H"
38#include "FaceCellWave.H"
39
40// Compatibility (MAY-2014)
45
46// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47
48namespace Foam
49{
52
53} // End namespace Foam
54
56// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
57
58namespace Foam
59{
60
61// Find named coefficents dictionary, or use default "coeffs"
62static inline const dictionary* cfindCoeffsDict
63(
64 const dictionary& dict,
65 const word& coeffsName,
66 const bool allowDefault
67)
68{
69 const dictionary* dictptr = dict.findDict(coeffsName);
70 if (!dictptr && allowDefault)
71 {
72 dictptr = dict.findDict("coeffs");
73 }
74 return dictptr;
76
77} // End namespace Foam
78
79
80// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
81
83(
84 const dictionary& decompDict,
85 const word& regionName
86)
87{
88 label nDomainsRegion = 0;
89 label nDomainsGlobal = UPstream::nProcs();
90
91 // Allow numberOfSubdomains to be optional in parallel, which allows
92 // for missing files on directories that have not yet been created.
93
94 decompDict.readEntry<label>
95 (
96 "numberOfSubdomains",
97 nDomainsGlobal,
98 keyType::REGEX, // keyType::LITERAL?
100 );
101
102 if (!regionName.empty())
103 {
104 const dictionary& regionDict =
105 optionalRegionDict(decompDict, regionName);
106
107 if (regionDict.readIfPresent("numberOfSubdomains", nDomainsRegion))
108 {
109 if (nDomainsRegion >= 1 && nDomainsRegion <= nDomainsGlobal)
110 {
111 return nDomainsRegion;
112 }
113
115 << "Ignoring region [" << regionName
116 << "] numberOfSubdomains: " << nDomainsRegion
117 << ", using global: " << nDomainsGlobal << nl
118 << endl;
120 }
121
122 return nDomainsGlobal;
123}
124
125
127(
128 const dictionary& decompDict,
129 const word& regionName
130)
131{
132 const dictionary* dictptr = nullptr;
133 if
134 (
135 !regionName.empty()
136 && (dictptr = decompDict.findDict("regions")) != nullptr
137 )
138 {
139 dictptr = dictptr->findDict(regionName);
140 }
141 return (dictptr ? *dictptr : dictionary::null);
142}
143
144
145// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
146
147bool Foam::decompositionMethod::constraintCompat(const word& modelType) const
148{
149 bool usable = decompDict_.found(modelType);
150 if (!usable)
151 {
152 return false;
153 }
154
155 for (const auto& item : constraints_)
156 {
157 if (modelType == item.type())
158 {
159 usable = false;
160 break;
161 }
162 }
163
164 if (usable)
165 {
166 Warning
167 << nl << " Using '" << modelType
168 << "' constraint specification." << nl;
169 }
170 else
171 {
172 Warning
173 << nl << " Ignoring '" << modelType
174 << "' constraint specification - was already specified." << nl;
175 }
176
177 // The syntax changed MAY-2014
178 error::warnAboutAge("constraint keyword", 1406);
179
180 return usable;
181}
182
183
184void Foam::decompositionMethod::readConstraints()
185{
186 constraints_.clear();
187
188 const dictionary* dictptr = decompDict_.findDict("constraints");
189
190 if (dictptr)
191 {
192 for (const entry& dEntry : *dictptr)
193 {
194 if (!dEntry.isDict()) // safety
195 {
196 // Ignore or warn
197 continue;
198 }
199
200 const dictionary& dict = dEntry.dict();
201
202 if (dict.getOrDefault("enabled", true))
203 {
204 constraints_.append(decompositionConstraint::New(dict));
205 }
206 }
207 }
208
209 // Backwards compatibility (MAY-2014)
210 if (constraintCompat("preserveBaffles"))
211 {
212 constraints_.append
213 (
215 );
216 }
217
218 if (constraintCompat("preservePatches"))
219 {
220 constraints_.append
221 (
223 (
224 decompDict_.get<wordRes>("preservePatches")
225 )
226 );
227 }
228
229 if (constraintCompat("preserveFaceZones"))
230 {
231 constraints_.append
232 (
234 (
235 decompDict_.get<wordRes>("preserveFaceZones")
236 )
237 );
238 }
239
240 if (constraintCompat("singleProcessorFaceSets"))
241 {
242 constraints_.append
243 (
245 (
246 decompDict_.lookup("singleProcessorFaceSets")
248 );
249 }
250}
251
252// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
253
255(
256 const dictionary& dict,
257 const word& coeffsName,
258 int select
259)
260{
261 const bool allowDefault = !(select & selectionType::EXACT);
262
263 const dictionary* dictptr =
264 cfindCoeffsDict(dict, coeffsName, allowDefault);
265
266 if (dictptr)
267 {
268 return *dictptr;
269 }
270
271 // Not found
272 if (select & selectionType::MANDATORY)
273 {
275 << "'" << coeffsName << "' dictionary not found in dictionary "
276 << dict.name() << endl
278 }
279
280 if (select & selectionType::NULL_DICT)
281 {
283 }
284
285 return dict; // Return original dictionary
286}
287
288
290(
291 const word& coeffsName,
292 int select
293) const
294{
295 const bool allowDefault = !(select & selectionType::EXACT);
296
297 const dictionary* dictptr = nullptr;
299 if (!decompRegionDict_.empty())
300 {
301 // Region-specific dictionary
302 dictptr = cfindCoeffsDict(decompRegionDict_, coeffsName, allowDefault);
303 }
304 if (!dictptr)
305 {
306 // General
307 dictptr = cfindCoeffsDict(decompDict_, coeffsName, allowDefault);
308 }
309
310 if (dictptr)
311 {
312 return *dictptr;
313 }
314
315 // Not found
316 if (select & selectionType::MANDATORY)
317 {
319 << "'" << coeffsName << "' dictionary not found in dictionary "
320 << decompDict_.name() << endl
322 }
323
324 if (select & selectionType::NULL_DICT)
325 {
326 return dictionary::null;
327 }
329 return decompDict_; // Return general dictionary
331
332
333// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
334
337 decompDict_(dictionary::null),
339 nDomains_(numDomains)
340{}
341
342
344(
345 const dictionary& decompDict,
346 const word& regionName
347)
348:
349 decompDict_(decompDict),
350 decompRegionDict_
351 (
352 optionalRegionDict(decompDict_, regionName)
353 ),
354 nDomains_(nDomains(decompDict, regionName))
356 readConstraints();
357}
358
359
360// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
361
363(
364 const dictionary& decompDict,
365 const word& regionName
366)
367{
368 word methodType(decompDict.get<word>("method"));
369
370 const dictionary& regionDict = optionalRegionDict(decompDict, regionName);
371 regionDict.readIfPresent("method", methodType);
372
373 auto* ctorPtr = dictionaryConstructorTable(methodType);
374
375 if (!ctorPtr)
376 {
378 (
379 decompDict,
380 "decompositionMethod",
381 methodType,
382 *dictionaryConstructorTablePtr_
383 ) << exit(FatalIOError);
384 }
385
386 // verbose
387 {
388 Info<< "Decomposition method " << methodType
389 << " [" << (nDomains(decompDict, regionName)) << ']';
390
391 if (!regionName.empty())
392 {
393 Info<< " (region " << regionName << ')';
394 }
396 }
397
398 return autoPtr<decompositionMethod>(ctorPtr(decompDict, regionName));
399}
400
401
403(
404 const polyMesh& mesh,
405 const labelList& fineToCoarse,
406 const pointField& coarsePoints,
407 const scalarField& coarseWeights
408) const
409{
410 CompactListList<label> coarseCellCells;
412 (
413 mesh,
414 fineToCoarse,
415 coarsePoints.size(),
416 true, // Global mesh connectivity
417 coarseCellCells
418 );
419
420 // Decompose based on agglomerated points
421 labelList decomp
424 (
425 coarseCellCells,
426 coarsePoints,
427 coarseWeights
428 )
429 );
430
431 // From coarse back to fine for original mesh
432 return labelList(decomp, fineToCoarse);
433}
434
435
437(
438 const polyMesh& mesh,
439 const labelList& agglom,
440 const label nLocalCoarse,
441 const bool parallel,
442 CompactListList<label>& cellCells
443)
444{
446 (
447 mesh,
448 agglom,
449 nLocalCoarse,
450 parallel,
451 cellCells
452 );
453}
454
455
457(
458 const polyMesh& mesh,
459 const labelList& agglom,
460 const label nLocalCoarse,
461 const bool parallel,
462 CompactListList<label>& cellCells,
463 CompactListList<scalar>& cellCellWeights
464)
465{
467 (
468 mesh,
469 agglom,
470 nLocalCoarse,
471 parallel,
472 cellCells,
473 cellCellWeights
474 );
476
477
478// NOTE:
479// - alternative calcCellCells that handled explicitConnections was
480// deactivated (2014 or earlier) and finally removed APR-2018.
481
483(
484 const polyMesh& mesh,
485 const scalarField& cellWeights,
486
487 //- Whether owner and neighbour should be on same processor
488 // (takes priority over explicitConnections)
489 const boolList& blockedFace,
490
491 //- Whether whole sets of faces (and point neighbours) need to be kept
492 // on single processor
493 const PtrList<labelList>& specifiedProcessorFaces,
494 const labelList& specifiedProcessor,
495
496 //- Additional connections between boundary faces
497 const List<labelPair>& explicitConnections
498) const
499{
500 // Any weights specified?
501 const bool hasWeights = returnReduceOr(cellWeights.size());
502
503 if (hasWeights && (cellWeights.size() != mesh.nCells()))
504 {
506 << "Number of weights (" << cellWeights.size()
507 << ") != number of cells (" << mesh.nCells() << ")"
508 << exit(FatalError);
509 }
510
511 // Any faces not blocked?
512 const bool hasUnblocked =
514 (
515 !blockedFace.empty() && !blockedFace.all()
516 );
517
518
519 // Any non-mesh connections?
520 const label nConnections = returnReduce
521 (
522 explicitConnections.size(),
523 sumOp<label>()
524 );
525
526
527 // Any processor sets?
528 label nProcSets = 0;
529 for (const labelList& procset : specifiedProcessorFaces)
530 {
531 nProcSets += procset.size();
532 }
533 reduce(nProcSets, sumOp<label>());
534
535
536 // Either do decomposition on cell centres or on agglomeration
537
538 if (!hasUnblocked && !nConnections && !nProcSets)
539 {
540 // No constraints, possibly weights
541
542 return
543 (
544 hasWeights
545 ? decompose(mesh, mesh.cellCentres(), cellWeights)
546 : decompose(mesh, mesh.cellCentres())
547 );
548 }
549
550
551 // The harder work.
552 // When we have processor sets, connections, or blocked faces.
553
554
555 // Determine local regions, separated by blockedFaces
556 regionSplit localRegion(mesh, blockedFace, explicitConnections, false);
557
558 if (debug)
559 {
560 // Only need to count unblocked faces for debugging
561 const label nUnblocked =
562 (
563 hasUnblocked
565 (
566 label(BitOps::count(blockedFace, false)),
568 )
569 : 0
570 );
571
572 Info<< "Constrained decomposition:" << nl
573 << " faces with same owner and neighbour processor : "
574 << nUnblocked << nl
575 << " baffle faces with same owner processor : "
576 << nConnections << nl
577 << " faces all on same processor : "
578 << nProcSets << nl
579 << " split into " << localRegion.nLocalRegions()
580 << " regions."
581 << endl;
582 }
583
584
585 // Gather region weights and determine region cell centres
586 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
587
588 // For the region centre, just take the first cell in the region.
589 // If we average the region centre instead, cyclics could cause
590 // the average domain centre to be outside of domain.
591
592 scalarField regionWeights(localRegion.nLocalRegions(), Foam::zero{});
593
594 pointField regionCentres(localRegion.nLocalRegions(), point::max);
595
596 if (hasWeights)
597 {
598 forAll(localRegion, celli)
599 {
600 const label regioni = localRegion[celli];
601
602 regionWeights[regioni] += cellWeights[celli];
603
604 if (regionCentres[regioni] == point::max)
605 {
606 regionCentres[regioni] = mesh.cellCentres()[celli];
607 }
608 }
609 }
610 else
611 {
612 forAll(localRegion, celli)
613 {
614 const label regioni = localRegion[celli];
615
616 regionWeights[regioni] += 1.0;
617
618 if (regionCentres[regioni] == point::max)
619 {
620 regionCentres[regioni] = mesh.cellCentres()[celli];
621 }
622 }
623 }
624
625 // Do decomposition on agglomeration
626 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
627
628 labelList finalDecomp =
629 decompose
630 (
631 mesh,
632 localRegion,
633 regionCentres,
634 regionWeights
635 );
636
637
638 // Apply explicitConnections since decompose did not know about them
639 for (const labelPair& baffle : explicitConnections)
640 {
641 const label f0 = baffle.first();
642 const label f1 = baffle.second();
643
644 if (!blockedFace[f0] && !blockedFace[f1])
645 {
646 // Note: what if internal faces and owner and neighbour on
647 // different processor?
648 // So for now just push owner side proc
649
650 const label proci = finalDecomp[mesh.faceOwner()[f0]];
651
652 finalDecomp[mesh.faceOwner()[f1]] = proci;
653 if (mesh.isInternalFace(f1))
654 {
655 finalDecomp[mesh.faceNeighbour()[f1]] = proci;
656 }
657 }
658 else if (blockedFace[f0] != blockedFace[f1])
659 {
661 << "On explicit connection between faces " << f0
662 << " and " << f1
663 << " the two blockedFace status are not equal : "
664 << blockedFace[f0] << " and " << blockedFace[f1]
665 << exit(FatalError);
666 }
667 }
668
669
670 // blockedFaces corresponding to processor faces need to be handled
671 // separately since not handled by local regionSplit. We need to
672 // walk now across coupled faces and make sure to move a whole
673 // global region across
674
675 // This additionally consolidates/compacts the regions numbers globally,
676 // since that was skipped in the previous regionSplit.
677 if (Pstream::parRun())
678 {
679 // Re-do regionSplit
680
681 // Field on cells and faces.
682 List<minData> cellData(mesh.nCells());
683 List<minData> faceData(mesh.nFaces());
684
685 // Take over blockedFaces by seeding a negative number
686 // (so is always less than the decomposition)
687 label nUnblocked = 0;
688 forAll(blockedFace, facei)
689 {
690 if (blockedFace[facei])
691 {
692 faceData[facei] = minData(-123);
693 }
694 else
695 {
696 ++nUnblocked;
697 }
698 }
699
700 // Seed unblocked faces with destination processor
701 labelList seedFaces(nUnblocked);
702 List<minData> seedData(nUnblocked);
703 nUnblocked = 0;
704
705 forAll(blockedFace, facei)
706 {
707 if (!blockedFace[facei])
708 {
709 const label own = mesh.faceOwner()[facei];
710 seedFaces[nUnblocked] = facei;
711 seedData[nUnblocked] = minData(finalDecomp[own]);
712 nUnblocked++;
713 }
714 }
715
716
717 // Propagate information inwards
718 FaceCellWave<minData> deltaCalc
719 (
720 mesh,
721 seedFaces,
722 seedData,
723 faceData,
724 cellData,
726 );
727
728 // And extract
729 forAll(finalDecomp, celli)
730 {
731 if (cellData[celli].valid(deltaCalc.data()))
732 {
733 finalDecomp[celli] = cellData[celli].data();
734 }
735 }
736 }
737
738
739 // For specifiedProcessorFaces rework the cellToProc to enforce
740 // all on one processor since we can't guarantee that the input
741 // to regionSplit was a single region.
742 // E.g. faceSet 'a' with the cells split into two regions
743 // by a notch formed by two walls
744 //
745 // \ /
746 // \ /
747 // ---a----+-----a-----
748 //
749 //
750 // Note that reworking the cellToProc might make the decomposition
751 // unbalanced.
752 forAll(specifiedProcessorFaces, seti)
753 {
754 const labelList& set = specifiedProcessorFaces[seti];
755
756 label proci = specifiedProcessor[seti];
757 if (proci == -1)
758 {
759 // If no processor specified - use the one from the 0th element
760 if (set.size())
761 {
762 proci = finalDecomp[mesh.faceOwner()[set[0]]];
763 }
764 else
765 {
766 // Zero-sized processor (e.g. from redistributePar)
767 proci = 0;
768 }
769 }
770
771 for (const label facei : set)
772 {
773 const face& f = mesh.faces()[facei];
774 for (const label pointi : f)
775 {
776 const labelList& pFaces = mesh.pointFaces()[pointi];
777 for (const label pFacei : pFaces)
778 {
779 finalDecomp[mesh.faceOwner()[pFacei]] = proci;
780 if (mesh.isInternalFace(pFacei))
781 {
782 finalDecomp[mesh.faceNeighbour()[pFacei]] = proci;
783 }
784 }
785 }
786 }
787 }
788
789
790 if (debug && Pstream::parRun())
791 {
792 labelList nbrDecomp;
793 syncTools::swapBoundaryCellList(mesh, finalDecomp, nbrDecomp);
794
796 for (const polyPatch& pp : patches)
797 {
798 if (pp.coupled())
799 {
800 forAll(pp, i)
801 {
802 const label facei = pp.start()+i;
803 const label own = mesh.faceOwner()[facei];
804 const label bFacei = facei-mesh.nInternalFaces();
805
806 if (!blockedFace[facei])
807 {
808 const label ownProc = finalDecomp[own];
809 const label nbrProc = nbrDecomp[bFacei];
810
811 if (ownProc != nbrProc)
812 {
814 << "patch:" << pp.name()
815 << " face:" << facei
816 << " at:" << mesh.faceCentres()[facei]
817 << " ownProc:" << ownProc
818 << " nbrProc:" << nbrProc
819 << exit(FatalError);
820 }
821 }
822 }
823 }
824 }
825 }
826
827 return finalDecomp;
828}
829
830
833 const polyMesh& mesh,
834 boolList& blockedFace,
835 PtrList<labelList>& specifiedProcessorFaces,
836 labelList& specifiedProcessor,
837 List<labelPair>& explicitConnections
838) const
839{
840 blockedFace.resize_nocopy(mesh.nFaces());
841 blockedFace = true;
842
843 specifiedProcessorFaces.clear();
844 explicitConnections.clear();
845
846 for (const decompositionConstraint& decompConstraint : constraints_)
847 {
848 decompConstraint.add
849 (
850 mesh,
851 blockedFace,
852 specifiedProcessorFaces,
853 specifiedProcessor,
854 explicitConnections
855 );
856 }
857}
858
859
862 const polyMesh& mesh,
863 const boolList& blockedFace,
864 const PtrList<labelList>& specifiedProcessorFaces,
865 const labelList& specifiedProcessor,
866 const List<labelPair>& explicitConnections,
867 labelList& decomposition
868) const
869{
870 for (const decompositionConstraint& decompConstraint : constraints_)
871 {
872 decompConstraint.apply
873 (
874 mesh,
875 blockedFace,
876 specifiedProcessorFaces,
877 specifiedProcessor,
878 explicitConnections,
879 decomposition
880 );
881 }
882}
883
884
887 const polyMesh& mesh,
888 const scalarField& cellWeights
889) const
890{
891 // Collect all constraints
892
893 boolList blockedFace;
894 PtrList<labelList> specifiedProcessorFaces;
895 labelList specifiedProcessor;
896 List<labelPair> explicitConnections;
898 (
899 mesh,
900 blockedFace,
901 specifiedProcessorFaces,
902 specifiedProcessor,
903 explicitConnections
904 );
905
906
907 // Construct decomposition method and either do decomposition on
908 // cell centres or on agglomeration
909
910 labelList finalDecomp = decompose
911 (
912 mesh,
913 cellWeights, // optional weights
914 blockedFace, // any cells to be combined
915 specifiedProcessorFaces,// any whole cluster of cells to be kept
916 specifiedProcessor,
917 explicitConnections // baffles
918 );
919
920
921 // Give any constraint the option of modifying the decomposition
922
924 (
925 mesh,
926 blockedFace,
927 specifiedProcessorFaces,
928 specifiedProcessor,
929 explicitConnections,
930 finalDecomp
931 );
932
933 return finalDecomp;
934}
935
936
937// * * * * * * * * * * * * * * * Stub Functions * * * * * * * * * * * * * * //
938
941 const pointField& points,
942 const scalarField& pointWeights
943) const
944{
946 return labelList();
947}
948
949
950// ************************************************************************* //
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
A packed storage of objects of type <T> using an offset table for access.
Wave propagation of information through grid. Every iteration information goes through one layer of c...
const TrackingData & data() const noexcept
Additional data to be passed into container.
@ MUST_READ
Reading required.
@ LAZY_READ
Reading is optional [identical to READ_IF_PRESENT].
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 resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition PtrList.H:67
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition PtrListI.H:98
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
bool all() const
True if all entries are 'true' or if the list is empty.
Definition UList.H:806
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition UListI.H:274
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
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
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
static const Form max
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
Abstract class for handling decomposition constraints.
static autoPtr< decompositionConstraint > New(const dictionary &constraintDict)
Return a reference to the selected decompositionConstraint.
Detects baffles and keeps owner and neighbour on same processor.
Constraint to keep/move owner and neighbour of faceZone onto same processor.
Constraint to keep owner and neighbour of (cyclic) patch on same processor.
Constraint to keep all cells connected to face or point of faceSet on a single processor.
Abstract base class for domain decomposition.
@ EXACT
No fallback to "coeffs" if main name not found.
@ MANDATORY
Fatal if dictionary could not be found.
const dictionary & decompRegionDict_
Region-specific decomposition dictionary information.
label nDomains_
Number of domains for the decomposition.
PtrList< decompositionConstraint > constraints_
Optional constraints.
void applyConstraints(const polyMesh &mesh, const boolList &blockedFace, const PtrList< labelList > &specifiedProcessorFaces, const labelList &specifiedProcessor, const List< labelPair > &explicitConnections, labelList &finalDecomp) const
Helper: apply constraints to a decomposition.
const dictionary & decompDict_
Top-level decomposition dictionary (eg, decomposeParDict).
static label nDomains(const dictionary &decompDict, const word &regionName="")
Return region-specific or top-level numberOfSubdomains entry.
void setConstraints(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections) const
Helper: extract constraints:
decompositionMethod(const label numDomains)
Construct with specified number of domains, no coefficients or constraints.
static autoPtr< decompositionMethod > New(const dictionary &decompDict, const word &regionName="")
Return a reference to the selected decomposition method, optionally region-specific.
virtual labelList decompose(const pointField &points, const scalarField &pointWeights=scalarField::null()) const
Return the wanted processor number for every coordinate, using uniform or specified point weights.
static FOAM_NO_DANGLING_REFERENCE const dictionary & findCoeffsDict(const dictionary &dict, const word &coeffsName, int select=selectionType::DEFAULT)
Locate coeffsName dictionary or the fallback "coeffs" dictionary within an enclosing dictionary.
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
static const dictionary & optionalRegionDict(const dictionary &decompDict, const word &regionName)
Return an optional region-specific dictionary from "regions" sub-dictionary, or dictionary::null on f...
label nDomains() const noexcept
Number of domains.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
const fileName & name() const noexcept
The dictionary name.
Definition dictionaryI.H:41
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and it is a dictionary) otherwise return nullptr...
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect,...
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition dictionary.H:487
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition error.C:67
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
static void calcCellCells(const polyMesh &mesh, const labelUList &agglom, const label nLocalCoarse, const bool parallel, CompactListList< label > &cellCells)
Determine (local or global) cellCells from mesh agglomeration.
label nTotalCells() const noexcept
Total global number of mesh cells.
@ REGEX
Regular expression.
Definition keyType.H:83
virtual labelList decompose(const polyMesh &mesh, const pointField &points=pointField::null(), const scalarField &pointWeights=scalarField::null()) const
Return for every coordinate the wanted processor number.
For use with FaceCellWave. Transports minimum passive data.
Definition minData.H:57
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
virtual const faceList & faces() const
Return raw faces.
Definition polyMesh.C:1088
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
const globalMeshData & globalData() const
Return parallel info (demand-driven).
Definition polyMesh.C:1296
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
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
const vectorField & faceCentres() const
label nInternalFaces() const noexcept
Number of internal faces.
const vectorField & cellCentres() const
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
const labelListList & pointFaces() const
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
label nLocalRegions() const
Return local number of regions.
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData, const bool parRun=UPstream::parRun())
Extract and swap to obtain neighbour cell values for all boundary faces.
A List of wordRe with additional matching capabilities.
Definition wordRes.H:56
A class for handling words, derived from Foam::string.
Definition word.H:66
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition error.H:637
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition error.H:688
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const pointField & points
#define WarningInFunction
Report a warning using Foam::Warning.
void set(List< bool > &bools, const labelUList &locations)
Set the listed locations (assign 'true').
Definition BitOps.C:35
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition BitOps.H:73
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.
static const dictionary * cfindCoeffsDict(const dictionary &dict, const word &coeffsName, const bool allowDefault)
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
errorManip< error > abort(error &err)
Definition errorManip.H:139
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
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...
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional 'FOAM Warning' header text.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} pointMap[start]=pointMap[end]=Foam::min(start, end);} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};constexpr label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< DynamicList< face > > pFaces[nBCs]
labelList f(nPoints)
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299