54Foam::label Foam::shortestPathSet::findMinFace
59 const bitSet& isLeakPoint,
60 const bool distanceMode,
64 const cell& cFaces2 =
mesh.cells()[cellI];
73 label faceI = cFaces2[i];
74 const topoDistanceData<label>& info =
allFaceInfo[faceI];
75 if (info.distance() < minDist)
77 minDist = info.distance();
81 else if (info.distance() == minDist)
93 scalar minDist2 = ROOTVGREAT;
96 label faceI = cFaces2[i];
99 scalar d2 =
magSqr(
mesh.faceCentres()[faceI]-origin);
114 label faceI = cFaces2[i];
120 const face&
f =
mesh.faces()[faceI];
123 if (isLeakPoint[
f[fp]])
130 if (nLeak < minLeakPoints)
132 minLeakPoints = nLeak;
144void Foam::shortestPathSet::calculateDistance
154 int dummyTrackData = 0;
163 faceDist.reserve(cFaces.size());
164 cFaces1.reserve(cFaces.size());
166 for (label facei : cFaces)
170 cFaces1.append(facei);
204 fm.time().timeName(),
223 pfld[i] = 1.0*
p[i].distance();
229 Pout<<
"Writing distance field for initial cell " << cellI
230 <<
" to " <<
fld.objectPath() <<
endl;
236void Foam::shortestPathSet::sync
243 bool& findMinDistance
271 [](ProcData&
x,
const ProcData&
y)
279 origin = searchData.second().first();
280 findMinDistance = searchData.second().second();
285bool Foam::shortestPathSet::touchesWall
300 if (isLeakPoint[
f[fp]] && isLeakPoint[
f[nextFp]])
303 if (isLeakFace.set(facei))
314Foam::bitSet Foam::shortestPathSet::pathFaces
341 nbrLeakCell[bFacei] = isLeakCell[celli];
360 if (isLeakCell[own[facei]] && isLeakCell[nbr[facei]])
362 isLeakFace.set(facei);
370 isLeakFace.set(facei);
377bool Foam::shortestPathSet::genSingleLeakPath
379 const bool markLeakPath,
383 const point& insidePoint,
384 const label insideCelli,
385 const point& outsidePoint,
386 const label outsideCelli,
389 const scalar trackLength,
431 if (celli != insideCelli && celli != outsideCelli)
433 if (isLeakCell[celli])
447 bitSet isLeakCellWithout(isLeakCell);
448 if (insideCelli != -1)
450 isLeakCellWithout.unset(insideCelli);
452 if (outsideCelli != -1)
454 isLeakCellWithout.unset(outsideCelli);
456 const bitSet isPathFace(pathFaces(
mesh, isLeakCellWithout));
459 if (isPathFace[facei])
470 if (isLeakFace[facei])
489 bool targetFound =
false;
490 if (outsideCelli != -1)
493 targetFound =
allCellInfo[outsideCelli].valid(dummyTrackData);
500 if (iter == 0 && !globalTargetFound)
503 <<
"Point " << outsidePoint
504 <<
" not reachable by walk from " << insidePoint
505 <<
". Probably mesh has island/regions."
506 <<
" Inside cell found: " << (insideCelli != -1 ?
"yes" :
"no")
507 <<
", Outside cell found: " << (outsideCelli != -1 ?
"yes" :
"no")
508 <<
". Skipped route detection." <<
endl;
511 if (!globalTargetFound)
529 label frontCellI = outsideCelli;
530 point origin(outsidePoint);
531 bool findMinDistance =
true;
536 scalar minDist = GREAT;
538 int dummyTrackData = 0;
540 if (frontCellI == -1)
566 if (frontCellI == -1)
569 if (globalMin.first() < searchRadius && globalMin.second() ==
Pstream::myProcNo() && minCellI != -1)
571 frontCellI = minCellI;
580 label frontFaceI = -1;
583 if (frontCellI != -1)
602 frontFaceI = findMinFace
614 bitSet isNewLeakPoint(isLeakPoint);
628 if (nbrCellI == frontCellI)
633 if (nbrCellI == insideCelli)
640 frontCellI = nbrCellI;
643 frontFaceI = findMinFace
656 if (fInfo.distance() <= cInfo.distance())
660 samplingCells.append(frontCellI);
661 samplingFaces.append(-1);
662 samplingSegments.append(iter);
663 samplingCurveDist.append
665 trackLength+cInfo.distance()
667 isLeakCell.set(frontCellI);
683 isNewLeakPoint.set(
mesh.
faces()[frontFaceI]);
685 findMinDistance =
false;
689 isLeakPoint.transfer(isNewLeakPoint);
713 if (frontFaceI != -1)
720 if (frontCellI != -1)
722 minCellDistance =
allCellInfo[frontCellI].distance();
743 const label oldFrontFaceI = frontFaceI;
751 label faceI =
pp.start()+i;
760 frontCellI =
pp.faceCells()[i];
774 samplingCells.append(frontCellI);
775 samplingFaces.append(-1);
776 samplingSegments.append(iter);
777 samplingCurveDist.append
779 trackLength+cInfo.distance()
781 isLeakCell.set(frontCellI);
797 isLeakPoint.set(
mesh.
faces()[frontFaceI]);
799 findMinDistance =
false;
806 if (insideCelli != -1 && frontCellI == insideCelli)
833Foam::label Foam::shortestPathSet::erodeFaceSet
836 const bitSet& isBlockedPoint,
847 <<
" isBlockedPoint:" << isBlockedPoint.size()
848 <<
" isLeakFace:" << isLeakFace.size()
857 label nTotalEroded = 0;
861 bitSet newIsLeakFace(isLeakFace);
865 const labelList meshFaceIDs(isLeakFace.toc());
877 nEdgeFaces[edgei] = edgeFaces[edgei].size();
883 bitSet sameEdgeOrientation;
903 globalData.globalEdgeSlaves(),
904 globalData.globalEdgeTransformedSlaves(),
917 if (nEdgeFaces[edgei] == 1)
923 if (!isBlockedPoint[mp0] || !isBlockedPoint[mp1])
926 const label patchFacei = edgeFaces[edgei][0];
933 if (newIsLeakFace.unset(meshFacei))
942 nTotalEroded += nEroded;
957 isLeakFace = std::move(newIsLeakFace);
964void Foam::shortestPathSet::genSamples
966 const bool addLeakPath,
969 const bitSet& isBoundaryFace,
970 const point& insidePoint,
971 const label insideCelli,
972 const point& outsidePoint,
999 label globalOutsideCelli = -1;
1000 if (localOutsideCelli != -1)
1002 globalOutsideCelli = globalCells.toGlobal(localOutsideCelli);
1007 if (globalOutsideCelli == -1)
1010 localOutsideCelli =
mesh.
findCell(outsidePoint + perturbVec);
1011 if (localOutsideCelli != -1)
1013 globalOutsideCelli = globalCells.toGlobal(localOutsideCelli);
1019 label outsideCelli = -1;
1020 label outsideProcI = -1;
1021 if (globalOutsideCelli != -1)
1023 outsideProcI = globalCells.whichProcID(globalOutsideCelli);
1026 outsideCelli = globalCells.toLocal(outsideProcI, globalOutsideCelli);
1033 Pout<<
"Outside point " << outsidePoint
1034 <<
" -> global cell " << globalOutsideCelli
1035 <<
" on proc " << outsideProcI
1040 scalar trackLength = 0;
1051 bool markLeakPath =
false;
1052 bool gaveUp =
false;
1055 for (iter = 0; iter < maxIter; iter++)
1062 const label oldNSamplingPts(samplingPts.size());
1064 bool foundPath = genSingleLeakPath
1097 samplingCurveDist.size()
1098 ? samplingCurveDist.last()
1110 if (!foundPath && !markLeakPath)
1118 if (nLeakFaces > nOldLeakFaces)
1124 markLeakPath =
false;
1133 if (markLeakPath && !foundPath)
1152 markLeakPath =
true;
1164 Pout<<
"Writing new isLeakCell to " << str.name() <<
endl;
1174 Pout<<
"Writing new leak-path to " << str.name() <<
endl;
1177 label samplei = oldNSamplingPts+1;
1178 samplei < samplingPts.size();
1182 Pout<<
" passing through cell "
1183 << samplingCells[samplei]
1185 <<
" distance:" << samplingCurveDist[samplei]
1190 samplingPts[samplei-1],
1191 samplingPts[samplei]
1202 const_cast<fvMesh&
>(fm).setInstance(fm.time().timeName());
1208 fm.time().timeName(),
1216 for (
const label celli : isLeakCell)
1218 fld[celli] = scalar(1);
1220 fld.correctBoundaryConditions();
1226 const bool shouldWarn =
returnReduceOr(maxIter > 1 && (iter == maxIter || gaveUp));
1230 <<
" leak paths" <<
nl <<
"This can cause problems when using the"
1231 <<
" paths to close leaks" <<
endl;
1236void Foam::shortestPathSet::genSamples
1238 const bool markLeakPath,
1239 const label maxIter,
1257 for (label patchi : wallPatches)
1262 isBlockedPoint.
set(
pp[i]);
1271 isBlockedPoint.set(
mesh.
faces()[facei]);
1287 for (
const auto& pointi : isBlockedPoint)
1291 Pout<<
"Writing " << str.nVertices()
1292 <<
" points to " << str.name() <<
endl;
1297 bitSet isLeakPoint(isBlockedPoint);
1303 label prevSegmenti = 0;
1304 scalar prevDistance = 0.0;
1311 for (
auto insidePoint : insidePoints_)
1315 label globalInsideCelli = -1;
1316 if (localInsideCelli != -1)
1318 globalInsideCelli = globalCells.toGlobal(localInsideCelli);
1323 if (globalInsideCelli == -1)
1326 localInsideCelli =
mesh.
findCell(insidePoint + perturbVec);
1327 if (localInsideCelli != -1)
1329 globalInsideCelli = globalCells.toGlobal(localInsideCelli);
1338 label insideCelli = -1;
1339 label insideProcI = -1;
1340 if (globalInsideCelli != -1)
1342 insideProcI = globalCells.whichProcID(globalInsideCelli);
1345 insideCelli = globalCells.toLocal(insideProcI, globalInsideCelli);
1352 Pout<<
"Inside point " << insidePoint
1353 <<
" -> global cell " << globalInsideCelli
1354 <<
" on proc " << insideProcI
1358 for (
auto outsidePoint : outsidePoints_)
1360 const label nOldSamples = samplingSegments.size();
1384 label maxSegment = 0;
1385 scalar maxDistance = 0.0;
1386 for (label i = nOldSamples; i < samplingSegments.size(); ++i)
1388 samplingSegments[i] += prevSegmenti;
1389 maxSegment =
max(maxSegment, samplingSegments[i]);
1390 samplingCurveDist[i] += prevDistance;
1391 maxDistance =
max(maxDistance, samplingCurveDist[i]);
1400 erodeFaceSet(
mesh, isBlockedPoint, isLeakFace);
1402 leakFaces_ = isLeakFace.sortedToc();
1412 Pout<<
"Writing " << leakFaces.size()
1413 <<
" faces to " << str.name() <<
endl;
1417 samplingPts.shrink();
1418 samplingCells.shrink();
1419 samplingFaces.shrink();
1420 samplingSegments.shrink();
1421 samplingCurveDist.shrink();
1426 std::move(samplingPts),
1427 std::move(samplingCells),
1428 std::move(samplingFaces),
1429 std::move(samplingSegments),
1430 std::move(samplingCurveDist)
1448 const bool markLeakPath,
1449 const label maxIter,
1458 outsidePoints_(outsidePoints)
1464 mesh.time().globalPath()
1466 /
mesh.pointsInstance()
1470 Info<<
"shortestPathSet : Writing blocked faces to "
1471 << outputDir <<
endl;
1500 uniqueMeshPointLabels,
1515 (outputDir /
"blockedFace"),
1528 (outputDir /
"blockedFace"),
1559 const label maxIter(
dict.getOrDefault<label>(
"maxIter", 50));
1560 const bool markLeakPath(
dict.getOrDefault(
"markLeakPath",
true));
1570 wallPatches.
append(patchi);
1574 genSamples(markLeakPath, maxIter,
mesh, wallPatches,
bitSet());
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
vtk::lineWriter writer(edgeCentres, edgeList::null(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edgesCentres")))
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const polyBoundaryMesh & pbm
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
void append(const T &val)
Copy append an element to the end of this list.
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
@ NO_READ
Nothing to be read.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
const Addr & addressing() const noexcept
The addressing used for the list.
A List with indirect addressing.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files.
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
label size() const noexcept
Number of entries.
void reset()
Clear all bits but do not adjust the addressable size.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const Map< label > & meshPointMap() const
Mesh point map.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const Field< point_type > & localPoints() const
Return pointField of points in patch.
const labelListList & edgeFaces() const
Return edge-face addressing.
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
static void combineReduce(T &value, CombineOp cop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) applying cop to inplace combine value from different processors.
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
A non-owning sub-view of a List (allocated or unallocated storage).
fileName timePath() const
Return current time path = path/timeName.
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
A List with indirect addressing. Like IndirectList but does not store addressing.
bool get(const label i) const
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
const point & max() const noexcept
Maximum describing the bounding box.
const point & min() const noexcept
Minimum describing the bounding box.
const word & axis() const
The sort axis name.
const scalarList & distance() const noexcept
Return the cumulative distance.
const word & name() const noexcept
The coord-set name.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
Smooth ATC in cells next to a set of patches supplied by type.
A face is a list of labels corresponding to mesh vertices.
A class for handling file names.
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
static word outputPrefix
Directory prefix.
Mesh data needed to do the Finite Volume discretisation.
const Time & time() const
Return the top-level database.
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
const globalIndex & globalMeshCellAddr() const noexcept
Global numbering for mesh cells.
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
label nTotalCells() const noexcept
Total global number of mesh cells.
Calculates points shared by more than two processor patches or cyclic patches.
LocalMin-mean differencing scheme class.
Class containing processor-to-processor mapping information.
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Mesh consisting of general polyhedral cells.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
virtual const faceList & faces() const
Return raw faces.
label findCell(const point &p, const cellDecomposition=CELL_TETS) const
Find cell enclosing this location and return index.
virtual const labelList & faceOwner() const
Return face owner.
const labelIOList & tetBasePtIs() const
Return the tetBasePtIs.
const globalMeshData & globalData() const
Return parallel info (demand-driven).
virtual const labelList & faceNeighbour() const
Return face neighbour.
const boundBox & bounds() const noexcept
Return mesh bounding box.
virtual const pointField & points() const
Return raw points.
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 nPoints() const noexcept
Number of mesh points.
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
const cellList & cells() const
Holds list of sampling points which is filled at construction time. Various implementations of this b...
const meshSearch & searchEngine() const noexcept
sampledSet(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const coordSet::coordFormat axisType)
Construct from components.
const polyMesh & mesh() const noexcept
Finds shortest path (in terms of cell centres) to walk on mesh from any point in insidePoints to any ...
shortestPathSet(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const word &axis, const bool markLeakPath, const label maxIter, const labelUList &wallPatches, const pointField &insidePoints, const pointField &outsidePoints, const boolList &blockedFace)
Construct from components. blockedFace is an optional specification.
For use with FaceCellWave. Determines topological distance to starting faces. Templated on passive tr...
Write faces/points (optionally with fields) as a vtp file or a legacy vtk file.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
const polyBoundaryMesh & patches
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
List< wallPoints > allFaceInfo(mesh_.nFaces())
const bitSet isBlockedFace(intersectedFaces())
FaceCellWave< wallPoints, wallPoints::trackData > wallDistCalc(mesh_, changedFaces, faceDist, allFaceInfo, allCellInfo, 0, td)
List< wallPoints > allCellInfo(mesh_.nCells())
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for handling debugging switches.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
scalar distance(const vector &p1, const vector &p2)
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
const dimensionSet dimless
Dimensionless.
List< labelList > labelListList
List of labelList.
List< label > labelList
A List of labels.
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
messageStream Info
Information stream (stdout output on master, null elsewhere).
List< face > faceList
List of faces.
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.
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
vector point
Point is a vector.
List< bool > boolList
A List of bools.
static constexpr const zero Zero
Global zero (0).
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
PrimitivePatch< UIndirectList< face >, const pointField & > uindirectPrimitivePatch
A PrimitivePatch with UIndirectList for the faces, const reference for the point field.
vectorField pointField
pointField is a vectorField.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
labelList findIndices(const ListType &input, typename ListType::const_reference val, label start=0)
Linear search to find all occurrences of given element.
errorManipArg< error, int > exit(error &err, const int errNo=1)
UList< label > labelUList
A UList of labels.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.
Assign tuple-like container to use the one with the smaller value of first.