Finished writing first version of donorBasedLayeredOverlap fringe
Note: did not attempt to compile yet, let alone test it
This commit is contained in:
parent
31019383d2
commit
6a5117ed51
2 changed files with 565 additions and 131 deletions
|
@ -27,6 +27,7 @@ License
|
|||
#include "faceCellsFringe.H"
|
||||
#include "oversetRegion.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "syncTools.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
|
@ -41,11 +42,22 @@ namespace Foam
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
const Foam::debug::tolerancesSwitch
|
||||
Foam::donorBasedLayeredOverlapFringe::distTol_
|
||||
(
|
||||
"donorBasedLayeredOverlapDistanceTolerance"
|
||||
0.0
|
||||
);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
|
||||
{
|
||||
if (acceptorsPtr_)
|
||||
// Make sure that either acceptorsPtr is unnalocated or if it is allocated,
|
||||
// that it is empty
|
||||
if (acceptorsPtr_ && !acceptorsPtr_->empty())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
|
@ -54,52 +66,438 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
|
|||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Get reference to region cell zone
|
||||
const cellZone& rcz = region().zone();
|
||||
// Get list of all overset regions
|
||||
const PtrList<oversetRegion>& allRegions =
|
||||
this->region().overset().regions();
|
||||
|
||||
// Make a hash set to collect acceptor points
|
||||
// Note: 2 patches connecting at the corner may create a duplicate,
|
||||
// which is filtered on insertion
|
||||
labelHashSet acceptorSet;
|
||||
|
||||
// Find patches and mark cells
|
||||
forAll (patchNames_, nameI)
|
||||
// Loop through all connected regions and check whether the fringe overlap
|
||||
// has been found for all of them
|
||||
bool allFringesReady = true;
|
||||
forAll (connectedRegionIDs_, crI)
|
||||
{
|
||||
const polyPatchID curFringePatch
|
||||
(
|
||||
patchNames_[nameI],
|
||||
mesh().boundaryMesh()
|
||||
);
|
||||
// Get ID of this region
|
||||
const label& regionID = connectedRegionIDs_[crI];
|
||||
|
||||
if (!curFringePatch.active())
|
||||
// Get the overset region
|
||||
const oversetRegion& region = allRegions[regionID];
|
||||
|
||||
// Get the fringe algorithm from the region
|
||||
const oversetFringe& fringe = region.fringe();
|
||||
|
||||
// If this is not faceCells fringe, issue a Warning. This fringe
|
||||
// selection algorithm is intended to work only with faceCells fringe on
|
||||
// the other side. VV, 9/Apr/2019
|
||||
if (!isA<faceCellsFringe>(fringe))
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"void Foam::donorBasedLayeredOverlapFringe::"
|
||||
"updateIteration(donorAcceptorList&) const"
|
||||
) << "donorBasedLayeredOverlap fringe is designed to work"
|
||||
<< " with faceCells fringe as a connected region fringe."
|
||||
<< nl
|
||||
<< "Connected overset region " << region.name()
|
||||
<< " has " << fringe.type() " fringe type. "
|
||||
<< nl
|
||||
<< "Proceed with care!"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Update flag collecting whether all connected regions found the
|
||||
// overlap
|
||||
allFringesReady &= fringe.foundSuitableOverlap();
|
||||
}
|
||||
|
||||
// Sets containing all acceptors and all holes for all connected regions
|
||||
labelHashSet allAcceptors(0.02*mesh.nCells());
|
||||
labelHashSet allFringeHoles(0.02*mesh.nCells());
|
||||
|
||||
if (allFringesReady)
|
||||
{
|
||||
// Loop through connected regions
|
||||
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();
|
||||
|
||||
// The fringe should be finalized, which means we may take a const
|
||||
// reference to its final donor acceptors
|
||||
const donorAcceptorList& crDonorAcceptorPairs =
|
||||
fringe.finalDonorAcceptors();
|
||||
|
||||
// Hash set containing donors
|
||||
labelHashSet donors(6*crDonorAcceptorPairs.size());
|
||||
|
||||
// Initialize centre of the donors of this connected region in order
|
||||
// to search in a given direction
|
||||
vector centrePoint(vector::zero);
|
||||
|
||||
// Loop through all donor/acceptors
|
||||
forAll (crDonorAcceptorPairs, daI)
|
||||
{
|
||||
// Get this donor/acceptor pair
|
||||
const donorAcceptor& daPair = crDonorAcceptorPairs[daI];
|
||||
|
||||
// Check whether all donors have been found
|
||||
if (!daPair.donorFound())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"void donorBasedLayeredOverlapFringe::calcAddressing() const"
|
||||
) << "Fringe patch " << patchNames_[nameI]
|
||||
<< " cannot be found"
|
||||
"donorBasedLayeredOverlapFringe::"
|
||||
"updateIteration(donorAcceptorList&) const"
|
||||
) << "Donor not found for donor/acceptor pair " << daI
|
||||
<< nl
|
||||
<< "Donor/acceptor data: " << daPair
|
||||
<< nl
|
||||
<< "In connected region: " << allRegions[regionID].name()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const unallocLabelList& curFaceCells =
|
||||
mesh().boundaryMesh()[curFringePatch.index()].donorBasedLayeredOverlap();
|
||||
|
||||
forAll (curFaceCells, fcI)
|
||||
// Mark donors on my processor from this connected region. Note
|
||||
// that the check has been made in constructor to make sure that
|
||||
// this region is the only donor region for the connected region
|
||||
if (daPair.donorProcNo() == Pstream::myProcNo())
|
||||
{
|
||||
// Check if cell is in region zone
|
||||
if (rcz.whichCell(curFaceCells[fcI]) > -1)
|
||||
// Get donor index
|
||||
const label& dI = daPair.donorCell();
|
||||
|
||||
// Insert donor into the hash set
|
||||
if (donors.insert(dI))
|
||||
{
|
||||
// Found acceptor
|
||||
acceptorSet.insert(curFaceCells[fcI]);
|
||||
// Donor has been inserted (not previously found in the
|
||||
// hash set), add donor point to centre point (the
|
||||
// centre point will be calculated later on as
|
||||
// arithmetic mean)
|
||||
centrePoint += daPair.donorPoint();
|
||||
}
|
||||
|
||||
// Loop through extended donor cells
|
||||
donorAcceptor::DynamicLabelList& extDonors =
|
||||
daPair.extendedDonorCells();
|
||||
donorAcceptor::DynamicPointList& extDonorPoints =
|
||||
daPair.extendedDonorPoints();
|
||||
|
||||
forAll (extDonors, i)
|
||||
{
|
||||
// Get donor index
|
||||
const label& edI = extDonors[i];
|
||||
|
||||
// Inser extended donor into the hash set
|
||||
if (donors.insert(edI))
|
||||
{
|
||||
// Donor has been inserted (not previously found in
|
||||
// the hash set), add extended donor point as well
|
||||
centrePoint += extDonorPoints[i];
|
||||
}
|
||||
} // End for all extended donors
|
||||
} // End if this donor is on my processor
|
||||
} // End for all (master) donor cells
|
||||
|
||||
// Use the centre point as specified by the user if it was specified
|
||||
// (if the regionCentrePoints_ list is not empty). This avoids
|
||||
// parallel communication as well.
|
||||
if (!regionCentrePoints_.empty())
|
||||
{
|
||||
// Use specified centre point, discarding the data we calculated
|
||||
// above
|
||||
centrePoint = regionCentrePoints_[crI];
|
||||
}
|
||||
else
|
||||
{
|
||||
// User did not specify centre points and the centre point holds
|
||||
// the sum of all the points. Reduce the data
|
||||
reduce(centrePoint, sumOp<vector>());
|
||||
nUniqueDonors = returnReduce(donors.size(), sumOp<label>());
|
||||
|
||||
// Calculate the final centre point by finding the arithmetic mean
|
||||
centrePoint /= nUniqueDonors;
|
||||
}
|
||||
|
||||
// We now have a collection of all donors for this connected region
|
||||
// and the centre point to move to. Let's collect the acceptors
|
||||
labelHashSet acceptors(donors.size()); // Reasonable size estimate
|
||||
|
||||
// Get necessary mesh data (from polyMesh/primitiveMesh)
|
||||
const polyMesh& mesh = this->mesh();
|
||||
const vectorField& cc = mesh.cellCentres();
|
||||
const vectorField& fc = mesh.faceCentres();
|
||||
const cellList& meshCells = mesh.cells();
|
||||
const unallocLabelList& owner = mesh.faceOwner();
|
||||
const unallocLabelList& neighbour = mesh.faceNeighbour();
|
||||
|
||||
// Mark cells that are eligible to be acceptors (not donors)
|
||||
boolList eligibleCells(mesh.nCells(), true);
|
||||
forAllConstIter (labelHashSet, donors, iter)
|
||||
{
|
||||
eligibleCells[iter.key()] = false;
|
||||
}
|
||||
|
||||
// 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 donors and mark faces that are pointing
|
||||
// towards the centre point and have an eligible neighbour
|
||||
forAllConstIter (labelHashSet, donors, iter)
|
||||
{
|
||||
// Get the cell index and the cell
|
||||
const label& cellI = iter.key();
|
||||
const label& cell = meshCells[cellI];
|
||||
|
||||
// Get cell centre of this donor and calculate distance to
|
||||
// centre point
|
||||
const vector& donorCentre = cc[cellI];
|
||||
const scalar donorCentreToRegionCentreDist =
|
||||
mag(donorCentre - centrePoint);
|
||||
|
||||
// Loop through all faces of the cell
|
||||
forAll (cFaces, i)
|
||||
{
|
||||
// Get face index (global)
|
||||
const label& faceI = cFaces[i];
|
||||
|
||||
// Get face centre and calculate distance to centre
|
||||
// point
|
||||
const vector& faceCentre = fc[faceI];
|
||||
const scalar faceCentreToRegionCentreDist =
|
||||
mag(faceCentre - centrePoint);
|
||||
|
||||
if
|
||||
(
|
||||
faceCentreToRegionCentreDist
|
||||
- donorCentreToRegionCentreDist
|
||||
< distTol_
|
||||
)
|
||||
{
|
||||
// Face is closer to the centre point than cell: we
|
||||
// are moving in the right direction. Mark the face
|
||||
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 eligible, not both
|
||||
if (eligibleCells[own])
|
||||
{
|
||||
// Owner cell is not a donor, insert it
|
||||
acceptors.insert(own);
|
||||
|
||||
// Mark as ineligible
|
||||
eligibleCells[own] = false;
|
||||
}
|
||||
else if (eligibleCells[nei])
|
||||
{
|
||||
// Neighbour cell is not a donor, insert it
|
||||
acceptors.insert(nei);
|
||||
|
||||
// Mark as ineligible
|
||||
eligibleCells[nei] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect acceptors
|
||||
acceptorsPtr_ = new labelList(acceptorSet.sortedToc());
|
||||
// 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];
|
||||
|
||||
// Holes are empty for this fringe
|
||||
fringeHolesPtr_ = new labelList();
|
||||
if (eligibleCells[own])
|
||||
{
|
||||
// Face cell is not a donor, insert it
|
||||
acceptors.insert(own);
|
||||
|
||||
// Mark as ineligible
|
||||
eligibleCells[own] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special treatment for last iteration
|
||||
if (i == nLayers_ - 1)
|
||||
{
|
||||
// This is not the last iteration, transfer acceptors into
|
||||
// donors
|
||||
donors.transfer(acceptors);
|
||||
|
||||
// Resize acceptors list
|
||||
acceptors.resize(donors.size());
|
||||
}
|
||||
} // End for specified number of layers
|
||||
|
||||
// At this point, we have the final set of acceptors and we marked
|
||||
// all cells that are ineligible (either donor or acceptor). The
|
||||
// remaining thing to do is to mark the interior holes
|
||||
|
||||
// Create a hash set containing fringe holes, initialized with
|
||||
// acceptors in order to avoid having special conditions in the loop
|
||||
// below for the first pass
|
||||
labelHashSet fringeHoles(10*acceptors.size());
|
||||
|
||||
// Collect holes until there are no holes to collect
|
||||
label nAddedHoles;
|
||||
do
|
||||
{
|
||||
// Reset number of newly added holes
|
||||
nAddedHoles = 0;
|
||||
|
||||
// Face markup for propagation
|
||||
boolList propagateFace(mesh.nFaces(), false);
|
||||
|
||||
// Loop through all acceptors and mark faces that are pointing
|
||||
// towards the centre point and have eligible neighbour (not an
|
||||
// acceptor or donor)
|
||||
forAllConstIter (labelHashSet, fringeHoles, iter)
|
||||
{
|
||||
// Get the cell index and the cell
|
||||
const label& cellI = iter.key();
|
||||
const label& cell = meshCells[cellI];
|
||||
|
||||
// Note: there's no need to check for the distance here
|
||||
// because there's always at least one "buffer" layer
|
||||
// towards the outer side that consists of donors, which are
|
||||
// marked as ineligible at the beginning
|
||||
|
||||
// Loop through all faces of the cell and mark all of them
|
||||
// for propagation
|
||||
forAll (cFaces, i)
|
||||
{
|
||||
propagateFace[cFaces[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Sync the face list across processor boundaries
|
||||
syncTools::syncFaceList
|
||||
(
|
||||
mesh,
|
||||
propagateFace,
|
||||
orOp<bool>(),
|
||||
false
|
||||
);
|
||||
|
||||
// Loop through all faces and append interior holes
|
||||
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 eligible, not both
|
||||
if (eligibleCells[own])
|
||||
{
|
||||
// Owner cell is not a hole (or an acceptor in the
|
||||
// first iteration), insert it
|
||||
if (fringeHoles.insert(own))
|
||||
{
|
||||
// Count number of added holes in this iteration
|
||||
++nAddedHoles;
|
||||
}
|
||||
|
||||
// Mark as ineligible
|
||||
eligibleCells[own] = false;
|
||||
}
|
||||
else if (eligibleCells[nei])
|
||||
{
|
||||
// Neighbour cell is not a hole (or an acceptor in
|
||||
// the first iteration), insert it
|
||||
if (fringeHoles.insert(nei))
|
||||
{
|
||||
// Count number of added holes in this iteration
|
||||
++nAddedHoles;
|
||||
}
|
||||
|
||||
// Mark as ineligible
|
||||
eligibleCells[nei] = 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 (eligibleCells[own])
|
||||
{
|
||||
// Face cell is not a hole (or an acceptor in the
|
||||
// first iteration), inser it
|
||||
if (fringeHoles.insert(own))
|
||||
{
|
||||
++nAddedHoles;
|
||||
}
|
||||
|
||||
// Mark as ineligible
|
||||
eligibleCells[own] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We moved one layer "inside" the fringe. Keep going until
|
||||
// there are no more holes to add
|
||||
|
||||
} while (nAddedHoles != 0);
|
||||
|
||||
// Finally, we have collected all the fringe holes and acceptors
|
||||
// from this connected region. Append them to the global sets
|
||||
allAcceptors += acceptors;
|
||||
allFringeHoles += fringeHoles;
|
||||
|
||||
} // End for all connected regions
|
||||
|
||||
// Set acceptors and holes from the data for all regions
|
||||
acceptorsPtr_ = new labelList(allAcceptors.sortedToc());
|
||||
fringeHolesPtr_ = new labelList(allFringeHoles.sortedToc());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connected fringes are not ready, allocate empty lists for acceptors
|
||||
// and holes, which will be deleted when asked for again from the
|
||||
// iterative procedure (see candidateAcceptors() and fringeHoles())
|
||||
acceptorsPtr_ = new labelList(0);
|
||||
holesPtr_ = new labelList(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,6 +530,25 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
|
|||
acceptorsPtr_(nullptr),
|
||||
finalDonorAcceptorsPtr_(nullptr)
|
||||
{
|
||||
// Sanity check number of layers: must be greater than 0
|
||||
if (nLayers_ < 1)
|
||||
{
|
||||
FatalIOErrorIn
|
||||
(
|
||||
"donorBasedLayeredOverlapFringe::"
|
||||
"donorBasedLayeredOverlapFringe\n"
|
||||
"(\n"
|
||||
" const fvMesh& mesh,\n"
|
||||
" const oversetRegion& region,\n"
|
||||
" const dictionary& dict\n"
|
||||
")",
|
||||
dict
|
||||
) << "Invalid number of layers specified, nLayers = " nLayers_
|
||||
<< nl
|
||||
<< "The number should be greater than 0."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Read names of connected regions
|
||||
const wordList connectedRegionNames(dict.lookup("connectedRegions"));
|
||||
|
||||
|
@ -150,10 +567,10 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
|
|||
}
|
||||
|
||||
// Loop through all regions and check whether the overlap has been found
|
||||
forAll (connectedRegion_, crI)
|
||||
forAll (connectedRegionNames, crI)
|
||||
{
|
||||
// Get name of this connected region
|
||||
const word& crName = connectedRegion_[crI];
|
||||
const word& crName = connectedRegionNames[crI];
|
||||
|
||||
// Find this region in the list of all regions
|
||||
const label regionID = findIndex(allRegions, crName);
|
||||
|
@ -176,13 +593,51 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
|
|||
|
||||
// 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
|
||||
(
|
||||
"donorBasedLayeredOverlapFringe::"
|
||||
"donorBasedLayeredOverlapFringe\n"
|
||||
"(\n"
|
||||
" const fvMesh& mesh,\n"
|
||||
" const oversetRegion& region,\n"
|
||||
" const dictionary& dict\n"
|
||||
")"
|
||||
) << "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 (regionID != this->region().index())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"donorBasedLayeredOverlapFringe::"
|
||||
"donorBasedLayeredOverlapFringe\n"
|
||||
"(\n"
|
||||
" const fvMesh& mesh,\n"
|
||||
" const oversetRegion& region,\n"
|
||||
" const dictionary& dict\n"
|
||||
")"
|
||||
) << "The donor region of region " << crName
|
||||
<< " should be only region " << this->region().name()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check: number of (optionally) specified centre points must be
|
||||
// equal to the number of connected regions
|
||||
if
|
||||
(
|
||||
regionCentrePoints_.size()
|
||||
!regionCentrePoints_.empty()
|
||||
&& (regionCentrePoints_.size() != connectedRegionIDs_.size())
|
||||
)
|
||||
{
|
||||
|
@ -207,6 +662,33 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
|
|||
<< " make sure to specify centre points for all connected regions."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Sanity check: if the user has specified centre points, dynamic mesh
|
||||
// simulations may be problematic. Issue a warning
|
||||
if
|
||||
(
|
||||
!regionCentrePoints_.empty()
|
||||
&& isA<dynamicFvMesh>(this->mesh())
|
||||
)
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"donorBasedLayeredOverlapFringe::"
|
||||
"donorBasedLayeredOverlapFringe\n"
|
||||
"(\n"
|
||||
" const fvMesh& mesh,\n"
|
||||
" const oversetRegion& region,\n"
|
||||
" const dictionary& dict\n"
|
||||
")"
|
||||
) << "You have specified regionCentrePoints for a dynamic mesh"
|
||||
<< " simulation."
|
||||
<< nl
|
||||
<< "Make sure that the centre points always remain in/near the"
|
||||
<< " centre of donors in connected regions!"
|
||||
<< nl
|
||||
<< "Proceed with care!"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,85 +714,14 @@ bool Foam::donorBasedLayeredOverlapFringe::updateIteration
|
|||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"donorBasedLayeredOverlapFringe::updateIteration(donorAcceptorList&"
|
||||
"donorBasedLayeredOverlapFringe::"
|
||||
"updateIteration(donorAcceptorList&) const"
|
||||
) << "finalDonorAcceptorPtr_ already allocated. Something went "
|
||||
<< "wrong with the iteration procedure (flag was not updated)."
|
||||
<< nl << "This should not happen for donorBasedLayeredOverlapFringe."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Get list of all overset regions
|
||||
const PtrList<oversetRegion>& allRegions =
|
||||
this->region().overset().regions();
|
||||
|
||||
// Loop through all connected regions and check whether the fringe overlap
|
||||
// has been found for all of them
|
||||
bool allFringesReady = true;
|
||||
forAll (connectedRegionIDs_, crI)
|
||||
{
|
||||
// Get ID of this region
|
||||
const label& regionID = connectedRegionIDs_[crI];
|
||||
|
||||
// Get the overset region
|
||||
const oversetRegion& region = allRegions[regionID];
|
||||
|
||||
// Get the fringe algorithm from the region
|
||||
const oversetFringe& fringe = region.fringe();
|
||||
|
||||
// If this is not faceCells fringe, issue a Warning. This fringe
|
||||
// selection algorithm is intended to work only with faceCells fringe on
|
||||
// the other side. VV, 9/Apr/2019
|
||||
if (!isA<faceCellsFringe>(fringe))
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"void Foam::donorBasedLayeredOverlapFringe::"
|
||||
"calcAddressing() const"
|
||||
) << "donorBasedLayeredOverlap fringe is designed to work"
|
||||
<< " with faceCells fringe as a connected region fringe."
|
||||
<< nl
|
||||
<< "Connected overset region " << region.name()
|
||||
<< " has " << fringe.type() " fringe type. "
|
||||
<< nl
|
||||
<< "Proceed with care!"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Update flag collecting whether all connected regions found the
|
||||
// overlap
|
||||
allFringesReady &= fringe.foundSuitableOverlap();
|
||||
}
|
||||
|
||||
if (allFringesReady)
|
||||
{
|
||||
// Loop through connected regions
|
||||
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();
|
||||
|
||||
// The fringe should be finalized, which means we may take a const
|
||||
// reference to its final donor acceptors
|
||||
const donorAcceptorList& crDonorAcceptorPairs =
|
||||
fringe.finalDonorAcceptors();
|
||||
|
||||
// Sanity check the validity of donor
|
||||
|
||||
// Mark donors on my processor from this connected region
|
||||
|
||||
// Calculate the centre for this connected region if it isn't
|
||||
// specified
|
||||
|
||||
// Mark all future acceptors by moving towards the centre using
|
||||
// face-neighbour walk nLayers times
|
||||
|
||||
// Now that the acceptors are marked, mark all remaining holes
|
||||
|
||||
}
|
||||
|
||||
// Allocate the list by reusing the argument list
|
||||
finalDonorAcceptorsPtr_ = new donorAcceptorList
|
||||
(
|
||||
|
@ -321,10 +732,6 @@ bool Foam::donorBasedLayeredOverlapFringe::updateIteration
|
|||
// Set the flag to true and return
|
||||
updateSuitableOverlapFlag(true);
|
||||
|
||||
return foundSuitableOverlap();
|
||||
} // else connected fringes are not ready yet, foundSuitableOverlap flag is
|
||||
// alraedy false, so there's nothing to do
|
||||
|
||||
return foundSuitablaOverlap();
|
||||
}
|
||||
|
||||
|
@ -335,6 +742,16 @@ const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::fringeHoles() const
|
|||
{
|
||||
calcAddressing();
|
||||
}
|
||||
else if (fringeHolesPtr_->empty())
|
||||
{
|
||||
// Fringe holes pointer is empty, delete both acceptorPtr_ and
|
||||
// fringeHolesPtr_ and calculate addressing. Since this fringe strategy
|
||||
// depends on other fringes, we need to have a special control in the
|
||||
// iterative algorithm that will start only when all the others are done
|
||||
// See calcAddressing() for details
|
||||
deleteDemandDrivenData(fringeHolesPtr_);
|
||||
deleteDemandDrivenData(acceptorsPtr_);
|
||||
}
|
||||
|
||||
return *fringeHolesPtr_;
|
||||
}
|
||||
|
@ -346,6 +763,16 @@ const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::candidateAcceptors(
|
|||
{
|
||||
calcAddressing();
|
||||
}
|
||||
else if (acceptorsPtr_->empty())
|
||||
{
|
||||
// Acceptors pointer is empty, delete both acceptorPtr_ and
|
||||
// fringeHolesPtr_ and calculate addressing. Since this fringe strategy
|
||||
// depends on other fringes, we need to have a special control in the
|
||||
// iterative algorithm that will start only when all the others are done
|
||||
// See calcAddressing() for details
|
||||
deleteDemandDrivenData(fringeHolesPtr_);
|
||||
deleteDemandDrivenData(acceptorsPtr_);
|
||||
}
|
||||
|
||||
return *acceptorsPtr_;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ Description
|
|||
until the final donor/acceptor assembly has been performed for all regions
|
||||
whose donor region is this region. Then, all donors are collected and the
|
||||
acceptors are cells neighbouring the donors nLayers towards the interior.
|
||||
Interior is defined either by a user-specified point or as a centre of
|
||||
volume of the donor cells.
|
||||
Interior is defined either by user-specified points for each region or as a
|
||||
centre of volume of the donor cells in particular region.
|
||||
|
||||
This fringe algorithm is intended to be used along with the faceCells fringe
|
||||
on the other side, where the cell sizes are not significantly different from
|
||||
each other (e.g. 10:1 cell ratio will probably be problematic to correctly
|
||||
set-up).
|
||||
each other (e.g. 10:1 cell ratio, where the finer cells are found on the
|
||||
background mesh will probably be problematic to correctly set-up).
|
||||
|
||||
Author
|
||||
Vuko Vukcevic, Wikki Ltd. All rights reserved.
|
||||
|
@ -72,8 +72,8 @@ class donorBasedLayeredOverlapFringe
|
|||
|
||||
//- Optional list of points representing a rough estimate of the centre
|
||||
// for each underlying connected region. If these are not provided, the
|
||||
// centre is calculated as the centre of volume of all donors for a
|
||||
// given connected region
|
||||
// centre is calculated as the centre of all donors for a given
|
||||
// connected region
|
||||
pointList regionCentrePoints_;
|
||||
|
||||
//- How many layers to move away from connected region donors to define
|
||||
|
@ -90,6 +90,13 @@ class donorBasedLayeredOverlapFringe
|
|||
mutable donorAcceptorList* finalDonorAcceptorsPtr_;
|
||||
|
||||
|
||||
// Private static data
|
||||
|
||||
//- Distance tolerance to determine propagation direction. Note:
|
||||
// absolute value, default = 0. Might be useful is some strange cases
|
||||
static const debug::tolerancesSwitch distTol_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
|
|
Reference in a new issue