Merge branch 'feature/donorBasedOverlapFringe' of ssh://git.code.sf.net/u/vvukcevic/foam-extend-4.0-vv into feature/donorBasedOverlapFringe

This commit is contained in:
Vuko Vukcevic 2019-07-11 14:36:18 +02:00
commit 4203848450
2 changed files with 337 additions and 482 deletions

View file

@ -26,8 +26,6 @@ License
#include "cuttingPatchFringe.H" #include "cuttingPatchFringe.H"
#include "oversetMesh.H" #include "oversetMesh.H"
#include "oversetRegion.H" #include "oversetRegion.H"
#include "faceCellsFringe.H"
#include "oversetRegion.H"
#include "polyPatchID.H" #include "polyPatchID.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "syncTools.H" #include "syncTools.H"
@ -48,80 +46,6 @@ namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::cuttingPatchFringe::init() const
{
// Set size of the list containing IDs
connectedRegionIDs_.setSize(connectedRegionNames_.size());
// Get list of all overset regions
const PtrList<oversetRegion>& allRegions =
this->region().overset().regions();
// Create list of all region names for easy lookup
wordList allRegionNames(allRegions.size());
forAll (allRegionNames, arI)
{
allRegionNames[arI] = allRegions[arI].name();
}
// Loop through all regions, collect region IDs and do sanity checks
forAll (connectedRegionNames_, crI)
{
// Get name of this connected region
const word& crName = connectedRegionNames_[crI];
// Find this region in the list of all regions
const label regionID = findIndex(allRegionNames, crName);
if (regionID == -1)
{
FatalErrorIn("void cuttingPatchFringe::init() const")
<< "Region " << crName << " not found in list of regions."
<< "List of overset regions: " << allRegionNames
<< abort(FatalError);
}
// Check whether the region is already present in the list
if (findIndex(connectedRegionIDs_, regionID) != -1)
{
// Duplicate found. Issue an error
FatalErrorIn("void cuttingPatchFringe::init() const")
<< "Region " << crName << " found in the list of regions"
<< " more than once." << nl
<< " This is not allowed." << nl
<< "Make sure that you don't have duplicate entries."
<< abort(FatalError);
}
// Collect the region index in the list
connectedRegionIDs_[crI] = regionID;
// Sanity check: if the specified connected donor region has more than 1
// donor regions, this fringe algorithm is attempted to be used for
// something that's not intended. Issue an error
if (allRegions[regionID].donorRegions().size() != 1)
{
FatalErrorIn("void cuttingPatchFringe::init() const")
<< "Region " << crName << " specified as connected region, but"
<< " that region has "
<< allRegions[regionID].donorRegions().size()
<< " donor regions."
<< abort(FatalError);
}
// Sanity check whether the donor region of connected region is actually
// this region
if (allRegions[regionID].donorRegions()[0] != this->region().index())
{
FatalErrorIn("void cuttingPatchFringe::init() const")
<< "The donor region of region " << crName
<< " should be only region " << this->region().name()
<< abort(FatalError);
}
}
}
void Foam::cuttingPatchFringe::calcAddressing() const void Foam::cuttingPatchFringe::calcAddressing() const
{ {
// Make sure that either acceptorsPtr is unnalocated or if it is allocated, // Make sure that either acceptorsPtr is unnalocated or if it is allocated,
@ -135,468 +59,413 @@ void Foam::cuttingPatchFringe::calcAddressing() const
<< abort(FatalError); << abort(FatalError);
} }
if (!isInitialized_) // Get polyMesh
{
// This is the first call, initialize the data and set flag to true
init();
isInitialized_ = true;
}
// Get list of all overset regions
const PtrList<oversetRegion>& allRegions =
this->region().overset().regions();
// Sets containing all acceptors and all holes for all connected regions
const polyMesh& mesh = this->mesh(); const polyMesh& mesh = this->mesh();
labelHashSet allAcceptors(0.02*mesh.nCells());
labelHashSet allFringeHoles(0.02*mesh.nCells());
if (debug) // Collect all cutting patches
labelHashSet patchIDs(cuttingPatchNames_.size());
forAll (cuttingPatchNames_, nameI)
{ {
Info<< "All dependent fringes are ready." // Get polyPatchID and check if valid
<< " Starting face cells cut patch fringe assembly..." << endl; const polyPatchID cutPatch
} (
cuttingPatchNames_[nameI],
mesh.boundaryMesh()
);
// Loop through connected regions if (!cutPatch.active())
forAll (connectedRegionIDs_, crI)
{
// Get ID of this region
const label& regionID = connectedRegionIDs_[crI];
// Get fringe of the connected region
const oversetFringe& fringe = allRegions[regionID].fringe();
// If this is not faceCells fringe, issue an Error. This fringe
// selection algorithm is intended to work only with faceCells fringe on
// the other side. VV, 9/Apr/2019
if (!isA<faceCellsFringe>(fringe))
{ {
FatalErrorIn FatalErrorIn
( (
"void Foam::cuttingPatchFringe::" "void cuttingPatchFringe::calcAddressing const"
"updateIteration(donorAcceptorList&) const" ) << "Cutting patch " << cuttingPatchNames_[nameI]
) << "cuttingPatch fringe is designed to work" << " cannot be found."
<< " with faceCells fringe as a connected region fringe."
<< nl
<< "Connected overset region " << allRegions[regionID].name()
<< " has " << fringe.type() << " fringe type. "
<< nl
<< "Proceed with care!"
<< abort(FatalError); << abort(FatalError);
} }
const faceCellsFringe& fcFringe =
refCast<const faceCellsFringe>(fringe);
// Get patch names from faceCells fringe // Store patch ID in the set
const wordList& fcPatchNames = fcFringe.patchNames(); patchIDs.insert(cutPatch.index());
}
// Find the patches if (debug)
labelHashSet patchIDs; {
Info<< "Starting cutting patch fringe assembly..." << endl;
}
forAll (fcPatchNames, nameI) // Note: similar code as in oversetRegion::calcHoleTriMesh. Consider
// refactoring. VV, 20/May/2019
// Make and invert local triSurface
triFaceList triFaces;
pointField triPoints;
// Memory management
{
triSurface ts = triSurfaceTools::triangulate
(
mesh.boundaryMesh(),
patchIDs
);
// Clean mutiple points and zero-sized triangles
ts.cleanup(false);
triFaces.setSize(ts.size());
triPoints = ts.points();
forAll (ts, tsI)
{ {
// Get polyPatchID and check if valid // Bugfix: no need to reverse the face because the normals point in
const polyPatchID fringePatch // the correct direction already. VV, 20/May/2019.
( triFaces[tsI] = ts[tsI];
fcPatchNames[nameI], }
mesh.boundaryMesh() }
);
if (!fringePatch.active()) if (Pstream::parRun())
{ {
FatalErrorIn // Combine all faces and points into a single list
(
"void cuttingPatchFringe::calcAddressing const"
) << "Fringe patch " << fcPatchNames[nameI]
<< " for region " << allRegions[regionID].name()
<< " cannot be found."
<< abort(FatalError);
}
// Store patch ID in the set List<triFaceList> allTriFaces(Pstream::nProcs());
patchIDs.insert(fringePatch.index()); List<pointField> allTriPoints(Pstream::nProcs());
allTriFaces[Pstream::myProcNo()] = triFaces;
allTriPoints[Pstream::myProcNo()] = triPoints;
Pstream::gatherList(allTriFaces);
Pstream::scatterList(allTriFaces);
Pstream::gatherList(allTriPoints);
Pstream::scatterList(allTriPoints);
// Re-pack points and faces
label nTris = 0;
label nPoints = 0;
forAll (allTriFaces, procI)
{
nTris += allTriFaces[procI].size();
nPoints += allTriPoints[procI].size();
} }
// Note: same code as in oversetRegion::calcHoleTriMesh. Consider // Pack points
// refactoring. VV, 20/May/2019 triPoints.setSize(nPoints);
// Make and invert local triSurface // Prepare point renumbering array
triFaceList triFaces; labelListList renumberPoints(Pstream::nProcs());
pointField triPoints;
// Memory management nPoints = 0;
forAll (allTriPoints, procI)
{ {
triSurface ts = triSurfaceTools::triangulate const pointField& ptp = allTriPoints[procI];
(
mesh.boundaryMesh(),
patchIDs
);
// Clean mutiple points and zero-sized triangles renumberPoints[procI].setSize(ptp.size());
ts.cleanup(false);
triFaces.setSize(ts.size()); labelList& procRenumberPoints = renumberPoints[procI];
triPoints = ts.points();
forAll (ts, tsI) forAll (ptp, ptpI)
{ {
// Bugfix: no need to reverse face because the normals point in triPoints[nPoints] = ptp[ptpI];
// the correct direction already. VV, 20/May/2019. procRenumberPoints[ptpI] = nPoints;
triFaces[tsI] = ts[tsI];
nPoints++;
} }
} }
if (Pstream::parRun()) // Pack triangles and renumber into complete points on the fly
triFaces.setSize(nTris);
nTris = 0;
forAll (allTriFaces, procI)
{ {
// Combine all faces and points into a single list const triFaceList& ptf = allTriFaces[procI];
List<triFaceList> allTriFaces(Pstream::nProcs()); const labelList& procRenumberPoints = renumberPoints[procI];
List<pointField> allTriPoints(Pstream::nProcs());
allTriFaces[Pstream::myProcNo()] = triFaces; forAll (ptf, ptfI)
allTriPoints[Pstream::myProcNo()] = triPoints;
Pstream::gatherList(allTriFaces);
Pstream::scatterList(allTriFaces);
Pstream::gatherList(allTriPoints);
Pstream::scatterList(allTriPoints);
// Re-pack points and faces
label nTris = 0;
label nPoints = 0;
forAll (allTriFaces, procI)
{ {
nTris += allTriFaces[procI].size(); const triFace& procFace = ptf[ptfI];
nPoints += allTriPoints[procI].size();
}
// Pack points triFace& renumberFace = triFaces[nTris];
triPoints.setSize(nPoints);
// Prepare point renumbering array forAll (renumberFace, rfI)
labelListList renumberPoints(Pstream::nProcs());
nPoints = 0;
forAll (allTriPoints, procI)
{
const pointField& ptp = allTriPoints[procI];
renumberPoints[procI].setSize(ptp.size());
labelList& procRenumberPoints = renumberPoints[procI];
forAll (ptp, ptpI)
{ {
triPoints[nPoints] = ptp[ptpI]; renumberFace[rfI] =
procRenumberPoints[ptpI] = nPoints; procRenumberPoints[procFace[rfI]];
nPoints++;
} }
}
// Pack triangles and renumber into complete points on the fly nTris++;
triFaces.setSize(nTris);
nTris = 0;
forAll (allTriFaces, procI)
{
const triFaceList& ptf = allTriFaces[procI];
const labelList& procRenumberPoints = renumberPoints[procI];
forAll (ptf, ptfI)
{
const triFace& procFace = ptf[ptfI];
triFace& renumberFace = triFaces[nTris];
forAll (renumberFace, rfI)
{
renumberFace[rfI] =
procRenumberPoints[procFace[rfI]];
}
nTris++;
}
} }
} }
}
// Make a complete triSurface from local data // Make a complete triSurface from local data
triSurface patchTriMesh(triFaces, triPoints); triSurface patchTriMesh(triFaces, triPoints);
// Clean up duplicate points and zero sized triangles // Clean up duplicate points and zero sized triangles
patchTriMesh.cleanup(false); patchTriMesh.cleanup(false);
// Get this region // Get this region
const oversetRegion& myRegion = this->region(); const oversetRegion& myRegion = this->region();
// Debug: write down the tri mesh // Debug: write down the tri mesh
if (Pstream::master()) if (Pstream::master())
{ {
patchTriMesh.write patchTriMesh.write
(
word
( (
word "patchTriSurface_region" + myRegion.name() + ".vtk"
( )
"patchTriSurface_region" + myRegion.name() + );
"_connectedRegion" + allRegions[regionID].name() + ".vtk" }
)
);
}
// Create the tri surface search object // Create the tri surface search object
triSurfaceSearch patchTriSearch(patchTriMesh); triSurfaceSearch patchTriSearch(patchTriMesh);
// Get cells in this region // Get cells in this region
const labelList& myRegionCells = myRegion.regionCells(); const labelList& myRegionCells = myRegion.regionCells();
// Get cell centres for inside-outside search using search object // Get cell centres for inside-outside search using search object
vectorField myCC(myRegionCells.size()); vectorField myCC(myRegionCells.size());
// Cell centres from polyMesh // Cell centres from polyMesh
const vectorField& cc = mesh.cellCentres(); const vectorField& cc = mesh.cellCentres();
forAll (myCC, i) forAll (myCC, i)
{
myCC[i] = cc[myRegionCells[i]];
}
// Inside mask: all cells within search object will be marked
boolList insideMask(mesh.nCells(), false);
// Get inside cells for cells in my region only
boolList myRegionInsideMask = patchTriSearch.calcInside(myCC);
// Note: insideMask has the size of all mesh cells and
// myRegionInsideMask has the size of cells in this region
forAll (myRegionInsideMask, i)
{
insideMask[myRegionCells[i]] = myRegionInsideMask[i];
}
// Make sure that the cut holes for this region are also properly marked as
// "inside". This may not be the case automatically for e.g. simulations
// with appendages
const labelList& cutRegionHoles = myRegion.cutHoles();
forAll (cutRegionHoles, i)
{
insideMask[cutRegionHoles[i]] = true;
}
// Get necessary mesh data (from polyMesh/primitiveMesh)
const cellList& meshCells = mesh.cells();
const unallocLabelList& owner = mesh.faceOwner();
const unallocLabelList& neighbour = mesh.faceNeighbour();
// Bool list for collecting faces with at least one unmarked
// cell (to determine the acceptors for the first iteration)
boolList hasUnmarkedCell(mesh.nFaces(), false);
// Loop through all cells
forAll (insideMask, cellI)
{
if (!insideMask[cellI])
{ {
myCC[i] = cc[myRegionCells[i]]; // This cell is not inside (it is unmarked). Loop through
} // its faces and set the flag
const cell& cFaces = meshCells[cellI];
// Inside mask: all cells within search object will be marked forAll (cFaces, i)
boolList insideMask(mesh.nCells(), false);
// Get inside cells for cells in my region only
boolList myRegionInsideMask = patchTriSearch.calcInside(myCC);
// Note: insideMask has the size of all mesh cells and
// myRegionInsideMask has the size of cells in this region
forAll (myRegionInsideMask, i)
{
insideMask[myRegionCells[i]] = myRegionInsideMask[i];
}
// Get necessary mesh data (from polyMesh/primitiveMesh)
const cellList& meshCells = mesh.cells();
const unallocLabelList& owner = mesh.faceOwner();
const unallocLabelList& neighbour = mesh.faceNeighbour();
// Bool list for collecting faces with at least one unmarked
// cell (to determine the acceptors for the first iteration)
boolList hasUnmarkedCell(mesh.nFaces(), false);
// Loop through all cells
forAll (insideMask, cellI)
{
if (!insideMask[cellI])
{ {
// This cell is not inside (it is unmarked). Loop through // Set the mark for this global face
// its faces and set the flag hasUnmarkedCell[cFaces[i]] = true;
const cell& cFaces = meshCells[cellI];
forAll (cFaces, i)
{
// Set the mark for this global face and break out
hasUnmarkedCell[cFaces[i]] = true;
}
} }
} }
}
// Sync the face list across processor boundaries
syncTools::syncFaceList
(
mesh,
hasUnmarkedCell,
orEqOp<bool>(),
true
);
// Mark-up for all inside faces
boolList insideFaceMask(mesh.nFaces(), false);
// Collect all acceptors for the first iteration (the cells that
// have at least one neighbour cell that is not marked)
labelHashSet acceptors(myRegionCells.size()/10);
// Loop again through all cells and collect marked ones into
// acceptors or holes, depending on whether they have unmarked cell
// as a neighbour (indicating an acceptor)
forAll (insideMask, cellI)
{
if (insideMask[cellI])
{
// This cell is inside the covered region
const cell& cFaces = meshCells[cellI];
forAll (cFaces, i)
{
// Get global face index
const label& faceI = cFaces[i];
// Check whether this neighbour is unmarked
if (hasUnmarkedCell[faceI])
{
// This cell has unmarked neighbour, collect it into
// the acceptor list
acceptors.insert(cellI);
// This cell is no longer "inside cell"
insideMask[cellI] = false;
}
else
{
// This is an "inside" face, mark it
insideFaceMask[faceI] = true;
}
} // End for all faces
} // End if cell is inside
} // End for all cells
// Note: insideFaceMask already synced across processors because it relies
// on hasUnmarkedCell list, which has been synced just above
// Hash set containing new acceptors (for successive iterations)
labelHashSet newAcceptors(acceptors.size());
// Now that we have the initial set of acceptors (and holes), loop
// nLayers away from initial donors
for (label i = 0; i < nLayers_; ++i)
{
// Face markup for propagation
boolList propagateFace(mesh.nFaces(), false);
// Loop through all acceptors and mark faces that are around hole
// cells. This way, we make sure that we go towards the correct,
// inside direction
forAllConstIter (labelHashSet, acceptors, iter)
{
// Get the cell index and the cell
const label& cellI = iter.key();
const cell& cFaces = meshCells[cellI];
// Loop through all faces of the cell
forAll (cFaces, i)
{
// Get face index (global)
const label& faceI = cFaces[i];
if (insideFaceMask[faceI])
{
// This is a hole face, we are moving in the right
// direction. Mark the face for propagation
propagateFace[faceI] = true;
}
} // End for all faces of the cell
} // End for all donor cells
// Sync the face list across processor boundaries // Sync the face list across processor boundaries
syncTools::syncFaceList syncTools::syncFaceList
( (
mesh, mesh,
hasUnmarkedCell, propagateFace,
orOp<bool>(), orEqOp<bool>(),
false false
); );
// Mark-up for all inside faces // Loop through all internal faces and append acceptors
boolList insideFaceMask(mesh.nFaces(), false); for (label faceI = 0; faceI < mesh.nInternalFaces(); ++faceI)
// Collect all acceptors for the first iteration (the cells that
// have at least one neighbour cell that is not marked)
labelHashSet acceptors(myRegionCells.size()/10);
// Loop again through all cells and collect marked ones into
// acceptors or holes, depending on whether they have unmarked cell
// as a neighbour (indicating an acceptor)
forAll (insideMask, cellI)
{ {
if (insideMask[cellI]) if (propagateFace[faceI])
{ {
// This cell is inside the covered region // Face is marked, select owner or neighbour
const cell& cFaces = meshCells[cellI]; const label& own = owner[faceI];
const label& nei = neighbour[faceI];
forAll (cFaces, i) // Either owner or neighbour may be hole, not both
if (insideMask[own])
{ {
// Get global face index // Owner cell is a hole, insert it
const label& faceI = cFaces[i]; newAcceptors.insert(own);
// Check whether this neighbour is unmarked // Update hole mask
if (hasUnmarkedCell[faceI]) insideMask[own] = false;
{ }
// This cell has unmarked neighbour, collect it into else if (insideMask[nei])
// the acceptor list {
acceptors.insert(cellI); // Neighbour cell is a hole, insert it
newAcceptors.insert(nei);
// This cell is no longer "inside cell" // Update hole mask
insideMask[cellI] = false;; insideMask[nei] = false;
// Break out since there's nothing to do for this cell
break;
}
} }
// If this is still inside cell, collect it and mark its faces // Also update hole face mask for next iteration
if (insideMask[cellI]) insideFaceMask[faceI] = false;
{
// Loop through cell faces and mark them
const cell& cFaces = meshCells[cellI];
forAll (cFaces, i)
{
insideFaceMask[cFaces[i]] = true;
}
}
} // End if cell is inside
} // End for all cells
// Hash set containing new acceptors (for successive iterations)
labelHashSet newAcceptors(acceptors.size());
// Now that we have the initial set of acceptors (and holes), loop
// nLayers away from initial donors
for (label i = 0; i < nLayers_; ++i)
{
// Face markup for propagation
boolList propagateFace(mesh.nFaces(), false);
// Loop through all acceptors and mark faces that are around hole
// cells. This way, we make sure that we go towards the correct,
// inside direction
forAllConstIter (labelHashSet, acceptors, iter)
{
// Get the cell index and the cell
const label& cellI = iter.key();
const cell& cFaces = meshCells[cellI];
// Loop through all faces of the cell
forAll (cFaces, i)
{
// Get face index (global)
const label& faceI = cFaces[i];
if (insideFaceMask[faceI])
{
// This is a hole face, we are moving in the right
// direction. Mark the face for propagation
propagateFace[faceI] = true;
}
} // End for all faces of the cell
} // End for all donor cells
// Sync the face list across processor boundaries
syncTools::syncFaceList
(
mesh,
propagateFace,
orOp<bool>(),
false
);
// Loop through all faces and append acceptors
for (label faceI = 0; faceI < mesh.nInternalFaces(); ++faceI)
{
if (propagateFace[faceI])
{
// Face is marked, select owner or neighbour
const label& own = owner[faceI];
const label& nei = neighbour[faceI];
// Either owner or neighbour may be hole, not both
if (insideMask[own])
{
// Owner cell is a hole, insert it
newAcceptors.insert(own);
// Update hole mask
insideMask[own] = false;
}
else if (insideMask[nei])
{
// Neighbour cell is a hole, insert it
newAcceptors.insert(nei);
// Update hole mask
insideMask[nei] = false;
}
// Also update hole face mask for next iteration
insideFaceMask[faceI] = false;
}
}
// Loop through boundary faces
for
(
label faceI = mesh.nInternalFaces();
faceI < mesh.nFaces();
++faceI
)
{
if (propagateFace[faceI])
{
// Face is marked, select owner if this is the right
// side. Neighbour handled on the other side
const label& own = owner[faceI];
if (insideMask[own])
{
// Face cell is a hole, insert it
newAcceptors.insert(own);
// Update hole mask
insideMask[own] = false;
}
// Also update hole face mask for next iteration
insideFaceMask[faceI] = false;
}
}
// Transfer newAcceptors into acceptors for next iteration or
// for final assembly. Resize newAcceptors accordingly
acceptors.transfer(newAcceptors);
newAcceptors.resize(acceptors.size());
} // End for specified number of layers
// At this point, we have the final set of acceptors and we marked
// all cells that should be holes. Collect holes into hash set (could be
// optimized by using dynamic lists)
labelHashSet fringeHoles(myRegionCells.size()/10);
forAll (insideMask, cellI)
{
if (insideMask[cellI])
{
fringeHoles.insert(cellI);
} }
} }
// Finally, we have fringe holes and acceptors and we need to add them // Loop through boundary faces
// to the list containing all acceptors and holes (for all connected for
// regions) (
allAcceptors += acceptors; label faceI = mesh.nInternalFaces();
allFringeHoles += fringeHoles; faceI < mesh.nFaces();
++faceI
)
{
if (propagateFace[faceI])
{
// Face is marked, select owner if this is the right
// side. Neighbour handled on the other side
const label& own = owner[faceI];
if (insideMask[own])
{
// Face cell is a hole, insert it
newAcceptors.insert(own);
// Update hole mask
insideMask[own] = false;
}
// Also update hole face mask for next iteration
insideFaceMask[faceI] = false;
}
}
// Transfer newAcceptors into acceptors for next iteration or
// for final assembly. Resize newAcceptors accordingly
acceptors.transfer(newAcceptors);
newAcceptors.resize(acceptors.size());
} // End for specified number of layers
// At this point, we have the final set of acceptors and we marked
// all cells that should be holes. Collect them into the list
dynamicLabelList fringeHoles(myRegionCells.size()/10);
forAll (insideMask, cellI)
{
if (insideMask[cellI])
{
fringeHoles.append(cellI);
}
} }
// Set acceptors and holes from the data for all regions // Set acceptors and holes from the data for all regions
acceptorsPtr_ = new labelList(allAcceptors.sortedToc()); acceptorsPtr_ = new labelList(acceptors.sortedToc());
fringeHolesPtr_ = new labelList(allFringeHoles.sortedToc()); fringeHolesPtr_ = new labelList(fringeHoles.xfer());
if (debug) if (debug)
{ {
@ -626,13 +495,11 @@ Foam::cuttingPatchFringe::cuttingPatchFringe
) )
: :
oversetFringe(mesh, region, dict), oversetFringe(mesh, region, dict),
connectedRegionNames_(dict.lookup("connectedRegions")), cuttingPatchNames_(dict.lookup("cuttingPatches")),
connectedRegionIDs_(),
nLayers_(readLabel(dict.lookup("nLayers"))), nLayers_(readLabel(dict.lookup("nLayers"))),
fringeHolesPtr_(nullptr), fringeHolesPtr_(nullptr),
acceptorsPtr_(nullptr), acceptorsPtr_(nullptr),
finalDonorAcceptorsPtr_(nullptr), finalDonorAcceptorsPtr_(nullptr)
isInitialized_(false)
{ {
// Sanity check number of layers: must be greater than 0 // Sanity check number of layers: must be greater than 0
if (nLayers_ < 1) if (nLayers_ < 1)
@ -650,7 +517,7 @@ Foam::cuttingPatchFringe::cuttingPatchFringe
) << "Invalid number of layers specified, nLayers = " << nLayers_ ) << "Invalid number of layers specified, nLayers = " << nLayers_
<< nl << nl
<< "The number should be greater than 0." << "The number should be greater than 0."
<< abort(FatalError); << exit(FatalError);
} }
// Preferably, the number of layers should be at least 2 // Preferably, the number of layers should be at least 2

View file

@ -58,14 +58,8 @@ class cuttingPatchFringe
{ {
// Private data // Private data
//- Names of connected regions. Looked up on construction //- Names of the cuttingPatches
wordList connectedRegionNames_; wordList cuttingPatchNames_;
//- Regions IDs from which the donors will be collected as a starting
// point. Note: initialized in init private member function because we
// cannot initialize it in constructor. This is because certain overset
// regions (and their fringes) may not be initialized at this point.
mutable labelList connectedRegionIDs_;
//- How many layers to move away from connected region donors to define //- How many layers to move away from connected region donors to define
// acceptor (and holes) // acceptor (and holes)
@ -80,15 +74,9 @@ class cuttingPatchFringe
//- Final donor/acceptor pairs for this region (fringe) //- Final donor/acceptor pairs for this region (fringe)
mutable donorAcceptorList* finalDonorAcceptorsPtr_; mutable donorAcceptorList* finalDonorAcceptorsPtr_;
//- Initialization helper
mutable bool isInitialized_;
// Private Member Functions // Private Member Functions
//- Initialization
void init() const;
//- Calculate hole and acceptor addressing //- Calculate hole and acceptor addressing
void calcAddressing() const; void calcAddressing() const;