48 const List<label>& toProc
59 label proci = toProc[i];
70 sendMap[proci].setSize(nSend[proci]);
78 label proci = toProc[i];
80 sendMap[proci][nSend[proci]++] = i;
101 forAll(constructMap, proci)
105 label nRecv = recvSizes[proci];
107 constructMap[proci].setSize(nRecv);
109 for (
label i = 0; i < nRecv; i++)
111 constructMap[proci][i] = constructSize++;
116 return autoPtr<mapDistribute>
130 void Foam::backgroundMeshDecomposition::initialRefinement()
137 mesh_.time().timeName(),
144 zeroGradientFvPatchScalarField::typeName
147 const conformationSurfaces& geometry = geometryToConformTo_;
149 decompositionMethod& decomposer = decomposerPtr_();
155 List<volumeType> volumeStatus
166 forAll(volumeStatus, celli)
172 mesh_.cells()[celli].points
179 if (geometry.overlaps(cellBb))
183 else if (geometry.inside(cellBb.midpoint()))
195 labelList refCells = selectRefinementCells
204 meshCutter_.consistentRefinement
211 forAll(newCellsToRefine, nCTRI)
213 label celli = newCellsToRefine[nCTRI];
220 icellWeights[celli] =
max 223 icellWeights[celli]/8.0
227 if (
returnReduce(newCellsToRefine.size(), sumOp<label>()) == 0)
233 polyTopoChange meshMod(mesh_);
236 meshCutter_.setRefinement(newCellsToRefine, meshMod);
239 autoPtr<mapPolyMesh> map = meshMod.changeMesh
249 mesh_.updateMesh(map);
252 meshCutter_.updateMesh(map);
257 const labelList& cellMap = map().cellMap();
259 List<volumeType> newVolumeStatus(cellMap.size());
263 label oldCelli = cellMap[newCelli];
271 newVolumeStatus[newCelli] = volumeStatus[oldCelli];
275 volumeStatus.transfer(newVolumeStatus);
278 Info<<
" Background mesh refined from " 280 <<
" to " << mesh_.globalData().nTotalCells()
281 <<
" cells." <<
endl;
285 forAll(volumeStatus, celli)
291 mesh_.cells()[celli].points
298 if (geometry.overlaps(cellBb))
302 else if (geometry.inside(cellBb.midpoint()))
314 bool removeOutsideCells =
false;
316 if (removeOutsideCells)
318 DynamicList<label> cellsToRemove;
320 forAll(volumeStatus, celli)
324 cellsToRemove.append(celli);
328 removeCells cellRemover(mesh_);
331 polyTopoChange meshMod(mesh_);
333 labelList exposedFaces = cellRemover.getExposedFaces
339 cellRemover.setRefinement
348 autoPtr<mapPolyMesh> map = meshMod.changeMesh
358 mesh_.updateMesh(map);
361 meshCutter_.updateMesh(map);
362 cellRemover.updateMesh(map);
367 const labelList& cellMap = map().cellMap();
369 List<volumeType> newVolumeStatus(cellMap.size());
373 label oldCelli = cellMap[newCelli];
381 newVolumeStatus[newCelli] = volumeStatus[oldCelli];
385 volumeStatus.transfer(newVolumeStatus);
390 - mesh_.globalData().nTotalCells()
391 <<
" cells." <<
endl;
403 labelList newDecomp = decomposer.decompose
410 fvMeshDistribute distributor(mesh_, mergeDist_);
412 autoPtr<mapDistributePolyMesh> mapDist = distributor.distribute
417 meshCutter_.distribute(mapDist);
419 mapDist().distributeCellData(volumeStatus);
423 printMeshData(mesh_);
446 void Foam::backgroundMeshDecomposition::printMeshData
453 globalIndex globalCells(mesh.nCells());
478 Info<<
"Processor " << proci <<
" " 479 <<
"Number of cells = " << globalCells.localSize(proci)
503 bool Foam::backgroundMeshDecomposition::refineCell
507 scalar& weightEstimate
517 mesh_.cells()[celli].points
524 weightEstimate = 1.0;
628 Foam::labelList Foam::backgroundMeshDecomposition::selectRefinementCells
630 List<volumeType>& volumeStatus,
639 forAll(volumeStatus, celli)
643 if (meshCutter_.cellLevel()[celli] < minLevels_)
645 cellsToRefine.insert(celli);
661 cellsToRefine.insert(celli);
666 return cellsToRefine.toc();
670 void Foam::backgroundMeshDecomposition::buildPatchAndTree()
677 mesh_.nFaces() - mesh_.nInternalFaces(),
678 mesh_.nInternalFaces()
683 boundaryFacesPtr_.reset
687 tmpBoundaryFaces.localFaces(),
688 tmpBoundaryFaces.localPoints()
693 treeBoundBox overallBb(boundaryFacesPtr_().localPoints());
695 Random& rnd = rndGen_;
699 new indexedOctree<treeDataBPatch>
707 overallBb.extend(rnd, 1e-4),
720 point bbMin(GREAT, GREAT, GREAT);
721 point bbMax(-GREAT, -GREAT, -GREAT);
723 forAll(allBackgroundMeshBounds_, proci)
725 bbMin =
min(bbMin, allBackgroundMeshBounds_[proci].
min());
726 bbMax =
max(bbMax, allBackgroundMeshBounds_[proci].
max());
729 globalBackgroundBounds_ = treeBoundBox(bbMin, bbMax);
736 /
"backgroundMeshDecomposition_proc_" 738 +
"_boundaryFaces.obj" 741 const faceList& faces = boundaryFacesPtr_().localFaces();
742 const List<point>& points = boundaryFacesPtr_().localPoints();
744 Map<label> foamToObj(points.size());
750 const face&
f = faces[i];
754 if (foamToObj.insert(f[fPI], vertI))
765 fStr<<
' ' << foamToObj[f[fPI]] + 1;
776 Foam::backgroundMeshDecomposition::backgroundMeshDecomposition
780 const conformationSurfaces& geometryToConformTo,
781 const dictionary& coeffsDict
785 geometryToConformTo_(geometryToConformTo),
791 "backgroundMeshDecomposition",
795 IOobject::AUTO_WRITE,
807 allBackgroundMeshBounds_(Pstream::nProcs()),
808 globalBackgroundBounds_(),
816 IOobject::MUST_READ_IF_MODIFIED,
820 decomposerPtr_(decompositionMethod::
New(decomposeDict_)),
821 mergeDist_(1e-6*mesh_.bounds().
mag()),
825 coeffsDict.lookupOrDefault<scalar>(
"minCellSizeLimit", 0.0)
834 <<
"This cannot be used when not running in parallel." 838 if (!decomposerPtr_().parallelAware())
841 <<
"You have selected decomposition method " 842 << decomposerPtr_().typeName
843 <<
" which is not parallel aware." << endl
847 Info<<
nl <<
"Building initial background mesh decomposition" <<
endl;
881 label nOccupiedCells = 0;
885 if (icellWeights[cI] > 1 - SMALL)
895 scalar cellWeightLimit =
max 898 *
sum(cellWeights).value()
905 Info<<
" cellWeightLimit " << cellWeightLimit <<
endl;
907 Pout<<
" sum(cellWeights) " <<
sum(cellWeights.primitiveField())
908 <<
" max(cellWeights) " <<
max(cellWeights.primitiveField())
916 if (icellWeights[cWI] > cellWeightLimit)
918 cellsToRefine.insert(cWI);
922 if (
returnReduce(cellsToRefine.size(), sumOp<label>()) == 0)
930 meshCutter_.consistentRefinement
937 if (debug && !cellsToRefine.empty())
939 Pout<<
" cellWeights too large in " << cellsToRefine.size()
943 forAll(newCellsToRefine, nCTRI)
945 label celli = newCellsToRefine[nCTRI];
947 icellWeights[celli] /= 8.0;
951 polyTopoChange meshMod(mesh_);
954 meshCutter_.setRefinement(newCellsToRefine, meshMod);
957 autoPtr<mapPolyMesh> map = meshMod.changeMesh
967 mesh_.updateMesh(map);
970 meshCutter_.updateMesh(map);
972 Info<<
" Background mesh refined from " 974 <<
" to " << mesh_.globalData().nTotalCells()
975 <<
" cells." <<
endl;
988 printMeshData(mesh_);
990 Pout<<
" Pre distribute sum(cellWeights) " 992 <<
" max(cellWeights) " 997 labelList newDecomp = decomposerPtr_().decompose
1000 mesh_.cellCentres(),
1004 Info<<
" Redistributing background mesh cells" <<
endl;
1006 fvMeshDistribute distributor(mesh_, mergeDist_);
1008 autoPtr<mapDistributePolyMesh> mapDist = distributor.distribute(newDecomp);
1010 meshCutter_.distribute(mapDist);
1014 printMeshData(mesh_);
1016 Pout<<
" Post distribute sum(cellWeights) " 1017 <<
sum(icellWeights)
1018 <<
" max(cellWeights) " 1019 <<
max(icellWeights)
1025 cellWeights.
write();
1028 buildPatchAndTree();
1047 const List<point>& pts
1050 boolList posProc(pts.size(),
true);
1054 posProc[pI] = positionOnThisProcessor(pts[pI]);
1063 const treeBoundBox& box
1067 return !bFTreePtr_().findBox(box).empty();
1073 const point& centre,
1074 const scalar radiusSqr
1079 return bFTreePtr_().findNearest(centre, radiusSqr).hit();
1089 return bFTreePtr_().findLine(start, end);
1099 return bFTreePtr_().findLineAny(start, end);
1105 const List<point>& pts
1108 DynamicList<label> toCandidateProc;
1109 DynamicList<point> testPoints;
1113 label nTotalCandidates = 0;
1117 const point& pt = pts[pI];
1119 label nCandidates = 0;
1121 forAll(allBackgroundMeshBounds_, proci)
1125 if (allBackgroundMeshBounds_[proci].overlaps(pt,
sqr(SMALL*100)))
1127 toCandidateProc.append(proci);
1128 testPoints.append(pt);
1134 ptBlockStart[pI] = nTotalCandidates;
1135 ptBlockSize[pI] = nCandidates;
1137 nTotalCandidates += nCandidates;
1141 label preDistributionToCandidateProcSize = toCandidateProc.size();
1143 autoPtr<mapDistribute> map(buildMap(toCandidateProc));
1145 map().distribute(testPoints);
1147 List<scalar> distanceSqrToCandidate(testPoints.size(),
sqr(GREAT));
1160 distanceSqrToCandidate[tPI] =
magSqr 1162 testPoints[tPI] - info.hitPoint()
1167 map().reverseDistribute
1169 preDistributionToCandidateProcSize,
1170 distanceSqrToCandidate
1173 labelList ptNearestProc(pts.size(), -1);
1179 SubList<scalar> ptNearestProcResults
1181 distanceSqrToCandidate,
1186 scalar nearestProcDistSqr = GREAT;
1188 forAll(ptNearestProcResults, pPRI)
1190 if (ptNearestProcResults[pPRI] < nearestProcDistSqr)
1192 nearestProcDistSqr = ptNearestProcResults[pPRI];
1194 ptNearestProc[pI] = toCandidateProc[ptBlockStart[pI] + pPRI];
1200 Pout<< pts[pI] <<
" nearestProcDistSqr " << nearestProcDistSqr
1201 <<
" ptNearestProc[pI] " << ptNearestProc[pI] <<
endl;
1204 if (ptNearestProc[pI] < 0)
1207 <<
"The position " << pts[pI]
1208 <<
" did not find a nearest point on the background mesh." 1213 return ptNearestProc;
1221 const List<point>& starts,
1222 const List<point>& ends,
1223 bool includeOwnProcessor
1226 DynamicList<label> toCandidateProc;
1227 DynamicList<point> testStarts;
1228 DynamicList<point> testEnds;
1229 labelList segmentBlockStart(starts.size(), -1);
1230 labelList segmentBlockSize(starts.size(), -1);
1232 label nTotalCandidates = 0;
1236 const point& s = starts[sI];
1237 const point& e = ends[sI];
1242 label nCandidates = 0;
1244 forAll(allBackgroundMeshBounds_, proci)
1251 && allBackgroundMeshBounds_[proci].intersects(s, e,
p)
1254 toCandidateProc.append(proci);
1255 testStarts.append(s);
1262 segmentBlockStart[sI] = nTotalCandidates;
1263 segmentBlockSize[sI] = nCandidates;
1265 nTotalCandidates += nCandidates;
1269 label preDistributionToCandidateProcSize = toCandidateProc.size();
1271 autoPtr<mapDistribute> map(buildMap(toCandidateProc));
1273 map().distribute(testStarts);
1274 map().distribute(testEnds);
1276 List<pointIndexHit> segmentIntersectsCandidate(testStarts.size());
1281 const point& s = testStarts[sI];
1282 const point& e = testEnds[sI];
1285 segmentIntersectsCandidate[sI] = bFTreePtr_().findLine(s, e);
1288 map().reverseDistribute
1290 preDistributionToCandidateProcSize,
1291 segmentIntersectsCandidate
1294 List<List<pointIndexHit>> segmentHitProcs(starts.size());
1297 DynamicList<pointIndexHit> tmpProcHits;
1301 tmpProcHits.clear();
1305 SubList<pointIndexHit> segmentProcResults
1307 segmentIntersectsCandidate,
1308 segmentBlockSize[sI],
1309 segmentBlockStart[sI]
1312 forAll(segmentProcResults, sPRI)
1314 if (segmentProcResults[sPRI].hit())
1316 tmpProcHits.append(segmentProcResults[sPRI]);
1318 tmpProcHits.last().setIndex
1320 toCandidateProc[segmentBlockStart[sI] + sPRI]
1325 segmentHitProcs[sI] = tmpProcHits;
1328 return segmentHitProcs;
1334 const point& centre,
1335 const scalar& radiusSqr
1338 forAll(allBackgroundMeshBounds_, proci)
1340 if (bFTreePtr_().findNearest(centre, radiusSqr).hit())
1352 const point& centre,
1353 const scalar radiusSqr
1358 forAll(allBackgroundMeshBounds_, proci)
1364 && allBackgroundMeshBounds_[proci].overlaps(centre, radiusSqr)
1370 toProc.append(proci);
List< labelList > labelListList
A List of labelList.
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
#define forAll(list, i)
Loop across all elements in list.
labelList processorNearestPosition(const List< point > &pts) const
What is the nearest processor to the given position?
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Ostream & endl(Ostream &os)
Add newline and flush stream.
static scalar & perturbTol()
Get the perturbation tolerance.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
labelList overlapProcessors(const point ¢re, const scalar radiusSqr) const
bool positionOnThisProcessor(const point &pt) const
Is the given position inside the domain of this decomposition.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
PointIndexHit< point > pointIndexHit
DimensionedField< scalar, volMesh > Internal
Type of the internal field from which this GeometricField is derived.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
static autoPtr< mapDistribute > buildMap(const List< label > &toProc)
Build a mapDistribute for the supplied destination processor data.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
List< bool > boolList
Bool container classes.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
treeDataPrimitivePatch< bPatch > treeDataBPatch
static void exchangeSizes(const Container &sendData, labelList &sizes, const label comm=UPstream::worldComm)
Helper: exchange sizes of sendData. sendData is the data per.
stressControl lookup("compactNormalStress") >> compactNormalStress
List< label > labelList
A List of labels.
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
PrimitivePatch< face, List, const pointField > bPatch
label readLabel(Istream &is)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
prefixOSstream Pout(cout,"Pout")
defineTypeNameAndDebug(combustionModel, 0)
pointIndexHit findLine(const point &start, const point &end) const
Find nearest intersection of line between start and end, (exposing.
bool overlapsThisProcessor(const treeBoundBox &box) const
Does the given box overlap the faces of the boundary of this.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
PrimitivePatch< face, SubList, const pointField & > primitivePatch
Addressing for a faceList slice.
word name(const complex &)
Return a string representation of a complex.
bool overlapsOtherProcessors(const point ¢re, const scalar &radiusSqr) const
static bool & parRun()
Is this a parallel run?
static label nProcs(const label communicator=0)
Number of processes in parallel run.
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
vector point
Point is a vector.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
dimensioned< scalar > mag(const dimensioned< Type > &)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
autoPtr< mapDistributePolyMesh > distribute(volScalarField &cellWeights)
Redistribute the background mesh based on a supplied weight field,.
virtual Ostream & write(const token &)=0
Write next token to stream.
List< List< pointIndexHit > > intersectsProcessors(const List< point > &starts, const List< point > &ends, bool includeOwnProcessor=false) const
Which processors are intersected by the line segment, returns all.
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
~backgroundMeshDecomposition()
Destructor.
int system(const std::string &command)
Execute the specified command.
pointIndexHit findLineAny(const point &start, const point &end) const
Find any intersection of line between start and end, (exposing.