64 const word& coeffsName,
65 const bool allowDefault
69 if (!dictptr && allowDefault)
87 const label nDomainsGlobal = decompDict.
get<label>(
"numberOfSubdomains");
95 if (regionDict.
readIfPresent(
"numberOfSubdomains", nDomainsRegion))
97 if (nDomainsRegion >= 1 && nDomainsRegion <= nDomainsGlobal)
99 return nDomainsRegion;
103 <<
"ignoring out of range numberOfSubdomains "
104 << nDomainsRegion <<
" for region " <<
regionName
110 return nDomainsGlobal;
124 && (dictptr = decompDict.
findDict(
"regions")) !=
nullptr
135bool Foam::decompositionMethod::constraintCompat(
const word& modelType)
const
137 bool usable = decompDict_.found(modelType);
143 for (
const auto& item : constraints_)
145 if (modelType == item.type())
155 <<
nl <<
" Using '" << modelType
156 <<
"' constraint specification." <<
nl;
161 <<
nl <<
" Ignoring '" << modelType
162 <<
"' constraint specification - was already specified." <<
nl;
172void Foam::decompositionMethod::readConstraints()
174 constraints_.clear();
176 const dictionary* dictptr = decompDict_.
findDict(
"constraints");
180 for (
const entry& dEntry : *dictptr)
182 if (!dEntry.isDict())
188 const dictionary&
dict = dEntry.dict();
198 if (constraintCompat(
"preserveBaffles"))
202 new decompositionConstraints::preserveBaffles()
206 if (constraintCompat(
"preservePatches"))
210 new decompositionConstraints::preservePatches
212 decompDict_.get<wordRes>(
"preservePatches")
217 if (constraintCompat(
"preserveFaceZones"))
221 new decompositionConstraints::preserveFaceZones
223 decompDict_.get<
wordRes>(
"preserveFaceZones")
228 if (constraintCompat(
"singleProcessorFaceSets"))
234 decompDict_.lookup(
"singleProcessorFaceSets")
245 const word& coeffsName,
249 const bool allowDefault = !(select & selectionType::EXACT);
260 if (select & selectionType::MANDATORY)
263 <<
"'" << coeffsName <<
"' dictionary not found in dictionary "
268 if (select & selectionType::NULL_DICT)
279 const word& coeffsName,
283 const bool allowDefault = !(select & selectionType::EXACT);
287 if (!decompRegionDict_.empty())
290 dictptr =
cfindCoeffsDict(decompRegionDict_, coeffsName, allowDefault);
304 if (select & selectionType::MANDATORY)
307 <<
"'" << coeffsName <<
"' dictionary not found in dictionary "
308 << decompDict_.name() <<
endl
312 if (select & selectionType::NULL_DICT)
329 decompDict_(decompDict),
353 auto* ctorPtr = dictionaryConstructorTable(methodType);
360 "decompositionMethod",
362 *dictionaryConstructorTablePtr_
368 Info<<
"Decomposition method " << methodType
369 <<
" [" << (nDomains(decompDict,
regionName)) <<
']';
426 forAll(fineDistribution, i)
428 fineDistribution[i] = coarseDistribution[fineToCoarse[i]];
431 return fineDistribution;
462 return decompose(globalCellCells, cc, weights);
470 const label nLocalCoarse,
493 if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
495 label facei = pp.start();
500 globalNeighbour[bFacei] = globalAgglom.
toGlobal
502 agglom[faceOwner[facei]]
523 const label own = agglom[faceOwner[facei]];
524 const label nei = agglom[faceNeighbour[facei]];
526 nFacesPerCell[own]++;
527 nFacesPerCell[nei]++;
532 if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
534 label facei = pp.start();
539 const label own = agglom[faceOwner[facei]];
540 const label globalNei = globalNeighbour[bFacei];
544 !globalAgglom.
isLocal(globalNei)
545 || globalAgglom.
toLocal(globalNei) != own
548 nFacesPerCell[own]++;
561 cellCells.
setSize(nFacesPerCell);
571 const label own = agglom[faceOwner[facei]];
572 const label nei = agglom[faceNeighbour[facei]];
574 m[offsets[own] + nFacesPerCell[own]++] = globalAgglom.
toGlobal(nei);
575 m[offsets[nei] + nFacesPerCell[nei]++] = globalAgglom.
toGlobal(own);
581 if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
583 label facei = pp.start();
588 const label own = agglom[faceOwner[facei]];
589 const label globalNei = globalNeighbour[bFacei];
593 !globalAgglom.
isLocal(globalNei)
594 || globalAgglom.
toLocal(globalNei) != own
597 m[offsets[own] + nFacesPerCell[own]++] = globalNei;
611 if (cellCells.
size() == 0)
619 label startIndex = cellCells.
offsets()[0];
626 const label endIndex = cellCells.
offsets()[celli+1];
628 for (label i = startIndex; i < endIndex; ++i)
630 if (nbrCells.
insert(cellCells.
m()[i]))
632 cellCells.
m()[newIndex++] = cellCells.
m()[i];
635 startIndex = endIndex;
636 cellCells.
offsets()[celli+1] = newIndex;
639 cellCells.
m().setSize(newIndex);
662 const label nLocalCoarse,
686 if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
688 label facei = pp.start();
693 globalNeighbour[bFacei] = globalAgglom.
toGlobal
695 agglom[faceOwner[facei]]
716 const label own = agglom[faceOwner[facei]];
717 const label nei = agglom[faceNeighbour[facei]];
719 nFacesPerCell[own]++;
720 nFacesPerCell[nei]++;
725 if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
727 label facei = pp.start();
732 const label own = agglom[faceOwner[facei]];
733 const label globalNei = globalNeighbour[bFacei];
737 !globalAgglom.
isLocal(globalNei)
738 || globalAgglom.
toLocal(globalNei) != own
741 nFacesPerCell[own]++;
754 cellCells.
setSize(nFacesPerCell);
755 cellCellWeights.
setSize(nFacesPerCell);
766 const label own = agglom[faceOwner[facei]];
767 const label nei = agglom[faceNeighbour[facei]];
769 const label ownIndex = offsets[own] + nFacesPerCell[own]++;
770 const label neiIndex = offsets[nei] + nFacesPerCell[nei]++;
772 m[ownIndex] = globalAgglom.
toGlobal(nei);
774 m[neiIndex] = globalAgglom.
toGlobal(own);
781 if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
783 label facei = pp.start();
788 const label own = agglom[faceOwner[facei]];
789 const label globalNei = globalNeighbour[bFacei];
793 !globalAgglom.
isLocal(globalNei)
794 || globalAgglom.
toLocal(globalNei) != own
797 const label ownIndex = offsets[own] + nFacesPerCell[own]++;
798 m[ownIndex] = globalNei;
813 if (cellCells.
size() == 0)
821 label startIndex = cellCells.
offsets()[0];
828 const label endIndex = cellCells.
offsets()[celli+1];
830 for (label i = startIndex; i < endIndex; ++i)
832 if (nbrCells.
insert(cellCells.
m()[i]))
834 cellCells.
m()[newIndex] = cellCells.
m()[i];
835 cellCellWeights.
m()[newIndex] = cellCellWeights.
m()[i];
839 startIndex = endIndex;
840 cellCells.
offsets()[celli+1] = newIndex;
841 cellCellWeights.
offsets()[celli+1] = newIndex;
844 cellCells.
m().setSize(newIndex);
845 cellCellWeights.
m().setSize(newIndex);
877 <<
"Number of weights " << cellWeights.
size()
878 <<
" differs from number of cells " <<
mesh.
nCells()
883 const bool hasUnblocked =
894 explicitConnections.
size(),
901 for (
const labelList& procset : specifiedProcessorFaces)
903 nProcSets += procset.size();
910 if (!hasUnblocked && !nConnections && !nProcSets)
928 regionSplit localRegion(
mesh, blockedFace, explicitConnections,
false);
933 const label nUnblocked =
944 Info<<
"Constrained decomposition:" <<
nl
945 <<
" faces with same owner and neighbour processor : "
947 <<
" baffle faces with same owner processor : "
948 << nConnections <<
nl
949 <<
" faces all on same processor : "
970 forAll(localRegion, celli)
972 const label regioni = localRegion[celli];
974 regionWeights[regioni] += cellWeights[celli];
984 forAll(localRegion, celli)
986 const label regioni = localRegion[celli];
988 regionWeights[regioni] += 1.0;
1011 for (
const labelPair& baffle : explicitConnections)
1013 const label f0 = baffle.first();
1014 const label f1 = baffle.second();
1016 if (!blockedFace[f0] && !blockedFace[f1])
1030 else if (blockedFace[f0] != blockedFace[f1])
1033 <<
"On explicit connection between faces " << f0
1035 <<
" the two blockedFace status are not equal : "
1036 << blockedFace[f0] <<
" and " << blockedFace[f1]
1059 label nUnblocked = 0;
1060 forAll(blockedFace, facei)
1062 if (blockedFace[facei])
1064 faceData[facei] =
minData(-123);
1077 forAll(blockedFace, facei)
1079 if (!blockedFace[facei])
1082 seedFaces[nUnblocked] = facei;
1083 seedData[nUnblocked] =
minData(finalDecomp[own]);
1101 forAll(finalDecomp, celli)
1103 if (cellData[celli].valid(deltaCalc.
data()))
1105 finalDecomp[celli] = cellData[celli].
data();
1124 forAll(specifiedProcessorFaces, seti)
1126 const labelList& set = specifiedProcessorFaces[seti];
1128 label proci = specifiedProcessor[seti];
1143 for (
const label facei : set)
1146 for (
const label pointi :
f)
1149 for (
const label pFacei :
pFaces)
1174 const label facei = pp.start()+i;
1178 if (!blockedFace[facei])
1180 const label ownProc = finalDecomp[own];
1181 const label nbrProc = nbrDecomp[bFacei];
1183 if (ownProc != nbrProc)
1186 <<
"patch:" << pp.name()
1187 <<
" face:" << facei
1189 <<
" ownProc:" << ownProc
1190 <<
" nbrProc:" << nbrProc
1215 specifiedProcessorFaces.
clear();
1216 explicitConnections.
clear();
1220 decompConstraint.add
1224 specifiedProcessorFaces,
1244 decompConstraint.apply
1248 specifiedProcessorFaces,
1250 explicitConnections,
1273 specifiedProcessorFaces,
1287 specifiedProcessorFaces,
1299 specifiedProcessorFaces,
1301 explicitConnections,
A packed storage unstructured matrix of objects of type <T> using an offset table for access.
List< SubListType > unpack() const
Return non-compact list of lists.
const List< T > & m() const noexcept
Const access to the packed matrix of values.
label size() const noexcept
The primary size (the number of rows/sublists)
const labelList & offsets() const noexcept
Return the offset table (= size()+1)
void setSize(const label mRows)
Redimension - same as resize()
Wave propagation of information through grid. Every iteration information goes through one layer of c...
const TrackingData & data() const
Additional data to be passed into container.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
void clear()
Clear all entries from table.
void setSize(const label n)
Alias for resize()
void clear()
Clear the list, i.e. set size to zero.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
T * data() noexcept
Return pointer to the underlying array serving as data storage.
void size(const label n)
Older name for setAddressableSize.
static label worldComm
Default communicator (all processors)
static bool & parRun() noexcept
Test if this a parallel run.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Abstract class for handling decomposition constraints.
Constraint to keep all cells connected to face or point of faceSet on a single processor.
Abstract base class for domain decomposition.
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.
void setConstraints(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections) const
Helper: extract constraints:
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool global, CompactListList< label > &cellCells)
Helper: determine (local or global) cellCells from mesh.
static const dictionary & findCoeffsDict(const dictionary &dict, const word &coeffsName, int select=selectionType::DEFAULT)
static const dictionary & optionalRegionDict(const dictionary &decompDict, const word ®ionName)
label nDomains() const noexcept
Number of domains.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
const fileName & name() const noexcept
The dictionary name.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
A face is a list of labels corresponding to mesh vertices.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
label toGlobal(const label i) const
From local to global index.
label toLocal(const label i) const
From global to local on current processor.
bool isLocal(const label i) const
Is on local processor.
label nTotalCells() const noexcept
Return total number of cells in decomposed mesh.
For use with FaceCellWave. Transports minimum passive data.
static const complex max
complex (VGREAT,VGREAT)
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Mesh consisting of general polyhedral cells.
virtual const faceList & faces() const
Return raw faces.
virtual const labelList & faceOwner() const
Return face owner.
const globalMeshData & globalData() const
Return parallel info.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
virtual const labelList & faceNeighbour() const
Return face neighbour.
A patch is a list of labels that address the faces in the global face list.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
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
const vectorField & faceAreas() 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.
bool decompose() const noexcept
Query the decompose flag (normally off)
A List of wordRe with additional matching capabilities.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
const polyBoundaryMesh & patches
Foam::word regionName(Foam::polyMesh::defaultRegion)
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
#define WarningInFunction
Report a warning using Foam::Warning.
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
bool all(const UList< bool > &bools)
True if all entries are 'true' or if the set is empty.
static const dictionary * cfindCoeffsDict(const dictionary &dict, const word &coeffsName, const bool allowDefault)
List< label > labelList
A List of labels.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
errorManip< error > abort(error &err)
static constexpr const zero Zero
Global zero (0)
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a)
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];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } 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};const 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< SLList< face > > pFaces[nBCs]
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
#define forAll(list, i)
Loop across all elements in list.