ENH: snappyHexMesh: early exit of leak detection. See #2403

This commit is contained in:
mattijs
2022-06-01 15:25:14 +01:00
parent 11b0d70b2d
commit 903f45dcdc
6 changed files with 175 additions and 96 deletions

View File

@ -225,6 +225,11 @@ castellatedMeshControls
//- Optional removal of cells in thin gaps. Start removing cells //- Optional removal of cells in thin gaps. Start removing cells
// if at refinement level 10 we're detecting thin gaps. // if at refinement level 10 we're detecting thin gaps.
//blockLevel 10; //blockLevel 10;
//- Optional early detection of connections between inside and
// outside locations. Default is only after all refinement has
// been done.
//leakLevel 10;
} }
} }
@ -481,6 +486,9 @@ castellatedMeshControls
//minCellFraction 0.001; //minCellFraction 0.001;
// Optional: same but in absolute number of cells. Default is 0. // Optional: same but in absolute number of cells. Default is 0.
//nMinCells 100; //nMinCells 100;
// Optional: disable of automatic leak closure and exit immediately
//useLeakClosure false;
} }
// Settings for the snapping. // Settings for the snapping.

View File

@ -586,6 +586,7 @@ private:
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& regionsInMesh, const wordList& regionsInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter, const refPtr<coordSetWriter>& leakPathFormatter,
const labelList& neiLevel, const labelList& neiLevel,
@ -845,6 +846,7 @@ private:
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& zonesInMesh, const wordList& zonesInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter, const refPtr<coordSetWriter>& leakPathFormatter,
labelList& cellToZone, labelList& cellToZone,
@ -1302,6 +1304,7 @@ public:
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& regionsInMesh, const wordList& regionsInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter const refPtr<coordSetWriter>& leakPathFormatter
); );
@ -1333,6 +1336,7 @@ public:
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& regionsInMesh, const wordList& regionsInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter const refPtr<coordSetWriter>& leakPathFormatter
); );
@ -1435,6 +1439,7 @@ public:
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& regionsInMesh, const wordList& regionsInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter, const refPtr<coordSetWriter>& leakPathFormatter,
wordPairHashTable& zonesToFaceZone wordPairHashTable& zonesToFaceZone
); );

View File

@ -292,6 +292,7 @@ void Foam::meshRefinement::getBafflePatches
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& zonesInMesh, const wordList& zonesInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter, const refPtr<coordSetWriter>& leakPathFormatter,
const labelList& neiLevel, const labelList& neiLevel,
const pointField& neiCc, const pointField& neiCc,
@ -326,6 +327,7 @@ void Foam::meshRefinement::getBafflePatches
locationsInMesh, locationsInMesh,
zonesInMesh, zonesInMesh,
locationsOutsideMesh, locationsOutsideMesh,
exitIfLeakPath,
leakPathFormatter, leakPathFormatter,
cellToZone, cellToZone,
@ -2848,6 +2850,7 @@ void Foam::meshRefinement::zonify
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& zonesInMesh, const wordList& zonesInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter, const refPtr<coordSetWriter>& leakPathFormatter,
labelList& cellToZone, labelList& cellToZone,
@ -2961,11 +2964,6 @@ void Foam::meshRefinement::zonify
// Add to unnamedRegion1, unnamedRegion2 // Add to unnamedRegion1, unnamedRegion2
if (unnamedMapPtr.valid()) if (unnamedMapPtr.valid())
{ {
WarningInFunction
<< "Detected and closed leak path from "
<< locationsInMesh << " to " << locationsOutsideMesh
<< endl;
// Dump leak path // Dump leak path
if (leakPathFormatter) if (leakPathFormatter)
{ {
@ -2985,6 +2983,23 @@ void Foam::meshRefinement::zonify
Info<< "Dumped leak path to " << fName << endl; Info<< "Dumped leak path to " << fName << endl;
} }
auto& err =
(
exitIfLeakPath
? FatalErrorInFunction
: WarningInFunction
);
err << "Locations in mesh " << locationsInMesh
<< " connect to one of the locations outside mesh "
<< locationsOutsideMesh << endl;
if (exitIfLeakPath)
{
FatalError << exit(FatalError);
}
labelList packedRegion1 labelList packedRegion1
( (
UIndirectList<label>(unnamedRegion1, unnamedFaces) UIndirectList<label>(unnamedRegion1, unnamedFaces)
@ -3034,96 +3049,119 @@ void Foam::meshRefinement::zonify
posOrientation posOrientation
); );
if (locationsOutsideMesh.size()) // Ideally we'd like to close 'cellZone' surfaces. The problem is
{ // that we don't (easily) know which locationsInMesh should be inside
namedFaces = ListOps::findIndices // the surface and which aren't. With 'insidePoint' definition of
( // cellZone we have a location inside the cellZone but how do we
namedSurfaceRegion, // know where the locationsInMesh are? Are they inside the cellZone
[](const label x){return x != -1;} // as well? Only with the 'locationsInMesh' notation where we specify
); // the cellZone and the seedpoint could we make sure that we cannot
// walk from one to the other.
// For now disable hole closure on cellZones
const globalIndex globalNamedFaces(namedFaces.size()); //if (locationsOutsideMesh.size())
//{
namedMapPtr = holeToFace::calcClosure // namedFaces = ListOps::findIndices
( // (
mesh_, // namedSurfaceRegion,
allLocations, // [](const label x){return x != -1;}
namedFaces, // );
globalNamedFaces, //
true, // allow erosion // {
// OBJstream str(mesh_.time().timePath()/"namedFaces.obj");
namedClosureFaces, // Pout<< "Writing " << namedFaces.size() << " zone faces to "
namedToClosure // << str.name() << endl;
); // str.write
// (
if (debug) // UIndirectList<face>(mesh_.faces(), namedFaces)(),
{ // mesh_.points()
Pout<< "meshRefinement::zonify : found faceZone closure faces:" // );
<< namedClosureFaces.size() // }
<< " map:" << namedMapPtr.valid() << endl; //
} //
// const globalIndex globalNamedFaces(namedFaces.size());
// Add to namedSurfaceRegion, posOrientation //
if (namedMapPtr.valid()) // namedMapPtr = holeToFace::calcClosure
{ // (
WarningInFunction // mesh_,
<< "Detected and closed leak path" // allLocations,
<< " through zoned surfaces from " // namedFaces, // or also unnamedFaces?
<< locationsInMesh << " to " << locationsOutsideMesh // globalNamedFaces,
<< endl; // true, // allow erosion
//
// Dump leak path // namedClosureFaces,
if (leakPathFormatter) // namedToClosure
{ // );
boolList blockedFace(mesh_.nFaces(), false); //
UIndirectList<bool>(blockedFace, unnamedFaces) = true; // if (debug)
UIndirectList<bool>(blockedFace, namedFaces) = true; // {
const fileName fName // Pout<< "meshRefinement::zonify :"
( // << " found faceZone closure faces:"
writeLeakPath // << namedClosureFaces.size()
( // << " map:" << namedMapPtr.valid() << endl;
mesh_, // }
locationsInMesh, //
locationsOutsideMesh, // // Add to namedSurfaceRegion, posOrientation
blockedFace, // if (namedMapPtr.valid())
leakPathFormatter.constCast() // {
) // WarningInFunction
); // << "Detected and closed leak path"
Info<< "Dumped leak path to " << fName << endl; // << " through zoned surfaces from "
} // << locationsInMesh << " to " << locationsOutsideMesh
// << endl;
labelList packedSurfaceRegion //
( // // Dump leak path
UIndirectList<label>(namedSurfaceRegion, namedFaces) // if (leakPathFormatter)
); // {
namedMapPtr->distribute(packedSurfaceRegion); // boolList blockedFace(mesh_.nFaces(), false);
boolList packedOrientation(posOrientation.size()); // UIndirectList<bool>(blockedFace, unnamedFaces) = true;
forAll(namedFaces, i) // UIndirectList<bool>(blockedFace, namedFaces) = true;
{ // const fileName fName
const label facei = namedFaces[i]; // (
packedOrientation[i] = posOrientation[facei]; // writeLeakPath
} // (
namedMapPtr->distribute(packedOrientation); // mesh_,
forAll(namedClosureFaces, i) // locationsInMesh,
{ // locationsOutsideMesh,
const label sloti = namedToClosure[i]; // blockedFace,
if (sloti != -1) // leakPathFormatter.constCast()
{ // )
const label facei = namedClosureFaces[i]; // );
const label regioni = namedSurfaceRegion[facei]; // Info<< "Dumped leak path to " << fName << endl;
const label slotRegioni = packedSurfaceRegion[sloti]; // }
const bool orient = posOrientation[facei]; //
const bool slotOrient = packedOrientation[sloti]; // labelList packedSurfaceRegion
// (
if (slotRegioni != regioni || slotOrient != orient) // UIndirectList<label>(namedSurfaceRegion, namedFaces)
{ // );
namedSurfaceRegion[facei] = slotRegioni; // namedMapPtr->distribute(packedSurfaceRegion);
posOrientation[facei] = slotOrient; // boolList packedOrientation(posOrientation.size());
} // forAll(namedFaces, i)
} // {
} // const label facei = namedFaces[i];
} // packedOrientation[i] = posOrientation[facei];
} // }
// namedMapPtr->distribute(packedOrientation);
// forAll(namedClosureFaces, i)
// {
// const label sloti = namedToClosure[i];
// if (sloti != -1)
// {
// const label facei = namedClosureFaces[i];
// const label regioni = namedSurfaceRegion[facei];
// const label slotRegioni = packedSurfaceRegion[sloti];
// const bool orient = posOrientation[facei];
// const bool slotOrient = packedOrientation[sloti];
//
// if (slotRegioni != regioni || slotOrient != orient)
// {
// namedSurfaceRegion[facei] = slotRegioni;
// posOrientation[facei] = slotOrient;
// }
// }
// }
// }
//}
} }
@ -4505,6 +4543,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& zonesInMesh, const wordList& zonesInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter const refPtr<coordSetWriter>& leakPathFormatter
) )
{ {
@ -4532,6 +4571,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
locationsInMesh, locationsInMesh,
zonesInMesh, zonesInMesh,
locationsOutsideMesh, locationsOutsideMesh,
exitIfLeakPath,
refPtr<coordSetWriter>(nullptr), refPtr<coordSetWriter>(nullptr),
neiLevel, neiLevel,
@ -4606,6 +4646,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
locationsInMesh, locationsInMesh,
zonesInMesh, zonesInMesh,
locationsOutsideMesh, locationsOutsideMesh,
exitIfLeakPath,
refPtr<coordSetWriter>(nullptr), refPtr<coordSetWriter>(nullptr),
neiLevel, neiLevel,
@ -4781,12 +4822,14 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMesh
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& zonesInMesh, const wordList& zonesInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter const refPtr<coordSetWriter>& leakPathFormatter
) )
{ {
// Determine patches to put intersections into // Determine patches to put intersections into
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Swap neighbouring cell centres and cell level // Swap neighbouring cell centres and cell level
labelList neiLevel(mesh_.nBoundaryFaces()); labelList neiLevel(mesh_.nBoundaryFaces());
pointField neiCc(mesh_.nBoundaryFaces()); pointField neiCc(mesh_.nBoundaryFaces());
@ -4802,6 +4845,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMesh
locationsInMesh, locationsInMesh,
zonesInMesh, zonesInMesh,
locationsOutsideMesh, locationsOutsideMesh,
exitIfLeakPath,
leakPathFormatter, leakPathFormatter,
neiLevel, neiLevel,
@ -5269,6 +5313,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::removeLimitShells
locationsInMesh, locationsInMesh,
zonesInMesh, zonesInMesh,
locationsOutsideMesh, locationsOutsideMesh,
false, // do not exit. Use leak-closure instead.
refPtr<coordSetWriter>(nullptr), refPtr<coordSetWriter>(nullptr),
neiLevel, neiLevel,
@ -5579,6 +5624,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
const pointField& locationsInMesh, const pointField& locationsInMesh,
const wordList& zonesInMesh, const wordList& zonesInMesh,
const pointField& locationsOutsideMesh, const pointField& locationsOutsideMesh,
const bool exitIfLeakPath,
const refPtr<coordSetWriter>& leakPathFormatter, const refPtr<coordSetWriter>& leakPathFormatter,
wordPairHashTable& zonesToFaceZone wordPairHashTable& zonesToFaceZone
) )
@ -5660,6 +5706,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
locationsInMesh, locationsInMesh,
zonesInMesh, zonesInMesh,
locationsOutsideMesh, locationsOutsideMesh,
exitIfLeakPath,
leakPathFormatter, leakPathFormatter,
cellToZone, cellToZone,

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2015-2020 OpenCFD Ltd. Copyright (C) 2015-2020,2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -74,6 +74,7 @@ Foam::refinementParameters::refinementParameters
pointField(0) pointField(0)
) )
), ),
useLeakClosure_(dict.getOrDefault<bool>("useLeakClosure", true)),
faceZoneControls_(dict.subOrEmptyDict("faceZoneControls")), faceZoneControls_(dict.subOrEmptyDict("faceZoneControls")),
allowFreeStandingZoneFaces_ allowFreeStandingZoneFaces_
( (

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2014 OpenFOAM Foundation Copyright (C) 2011-2014 OpenFOAM Foundation
Copyright (C) 2015-2020 OpenCFD Ltd. Copyright (C) 2015-2020,2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -87,6 +87,9 @@ class refinementParameters
//- Areas to keep //- Areas to keep
pointField locationsInMesh_; pointField locationsInMesh_;
//- How to handle connections between inside and outside points
const bool useLeakClosure_;
//- Region for location //- Region for location
wordList zonesInMesh_; wordList zonesInMesh_;
@ -195,6 +198,16 @@ public:
return locationsOutsideMesh_; return locationsOutsideMesh_;
} }
//- Whether to attempt to close any 'leak' between
// locationsInsideMesh and locationsOutsideMesh or exit with
// error. Default is true.
// (see also refinementSurfaces::leakLevel to force surfaces to
// be checked for leaks early-on in the refinement)
bool useLeakClosure() const
{
return useLeakClosure_;
}
//- Are zone faces allowed only inbetween different cell zones //- Are zone faces allowed only inbetween different cell zones
// or also just free standing? // or also just free standing?
bool allowFreeStandingZoneFaces() const bool allowFreeStandingZoneFaces() const

View File

@ -1824,6 +1824,7 @@ void Foam::snappyRefineDriver::removeInsideCells
); );
} }
// Fix any additional (e.g. locationsOutsideMesh). Note: probably not // Fix any additional (e.g. locationsOutsideMesh). Note: probably not
// necessary. // necessary.
meshRefiner_.splitMesh meshRefiner_.splitMesh
@ -1835,6 +1836,7 @@ void Foam::snappyRefineDriver::removeInsideCells
refineParams.locationsInMesh(), refineParams.locationsInMesh(),
refineParams.zonesInMesh(), refineParams.zonesInMesh(),
refineParams.locationsOutsideMesh(), refineParams.locationsOutsideMesh(),
!refineParams.useLeakClosure(),
setFormatter_ setFormatter_
); );
@ -2822,6 +2824,7 @@ void Foam::snappyRefineDriver::baffleAndSplitMesh
refineParams.locationsInMesh(), refineParams.locationsInMesh(),
refineParams.zonesInMesh(), refineParams.zonesInMesh(),
refineParams.locationsOutsideMesh(), refineParams.locationsOutsideMesh(),
!refineParams.useLeakClosure(),
setFormatter_ setFormatter_
); );
@ -2886,6 +2889,7 @@ void Foam::snappyRefineDriver::zonify
refineParams.locationsInMesh(), refineParams.locationsInMesh(),
refineParams.zonesInMesh(), refineParams.zonesInMesh(),
refineParams.locationsOutsideMesh(), refineParams.locationsOutsideMesh(),
!refineParams.useLeakClosure(),
setFormatter_, setFormatter_,
zonesToFaceZone zonesToFaceZone
); );
@ -2958,6 +2962,7 @@ void Foam::snappyRefineDriver::splitAndMergeBaffles
refineParams.locationsInMesh(), refineParams.locationsInMesh(),
refineParams.zonesInMesh(), refineParams.zonesInMesh(),
refineParams.locationsOutsideMesh(), refineParams.locationsOutsideMesh(),
!refineParams.useLeakClosure(),
setFormatter_ setFormatter_
); );