Run-time bugfixes in donorBasedLayeredOverlapFringe

Note: still need to thoroughly test in parallel and with multiple donor regions
for a single background region
This commit is contained in:
Vuko Vukcevic 2019-04-11 17:27:01 +02:00
parent 805c942ac4
commit 02f459fc91
3 changed files with 197 additions and 185 deletions

View file

@ -2,14 +2,10 @@ EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \ -I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \ -I$(LIB_SRC)/sampling/lnInclude
-I$(LIB_SRC)/dynamicMesh/dynamicMesh/lnInclude \
-I$(LIB_SRC)/dynamicMesh/dynamicFvMesh/lnInclude
EXE_LIBS = \ EXE_LIBS = \
-lfiniteVolume \ -lfiniteVolume \
-lmeshTools \ -lmeshTools \
-lsurfMesh \ -lsurfMesh \
-lsampling \ -lsampling
-ldynamicMesh \
-ldynamicFvMesh

View file

@ -30,7 +30,6 @@ License
#include "oversetRegion.H" #include "oversetRegion.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "syncTools.H" #include "syncTools.H"
#include "dynamicFvMesh.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -56,6 +55,88 @@ Foam::donorBasedLayeredOverlapFringe::distTol_
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::donorBasedLayeredOverlapFringe::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 and check whether the overlap has been found
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 donorBasedLayeredOverlapFringe::init() const")
<< "Region " << crName << " not found in list of regions."
<< "List of overset regions: " << allRegionNames
<< 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 donorBasedLayeredOverlapFringe::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 donorBasedLayeredOverlapFringe::init() const")
<< "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_.empty()
&& (regionCentrePoints_.size() != connectedRegionIDs_.size())
)
{
FatalErrorIn("void donorBasedLayeredOverlapFringe::init() const")
<< "You have specified "
<< regionCentrePoints_.size()
<< " regionCentrePoints, while specifying "
<< connectedRegionIDs_.size()
<< " connectedRegions."
<< nl
<< "If you'd like to avoid using automatic centre point detection,"
<< " make sure to specify centre points for all connected regions."
<< abort(FatalError);
}
}
void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const void Foam::donorBasedLayeredOverlapFringe::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,
@ -69,6 +150,13 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
<< abort(FatalError); << abort(FatalError);
} }
if (!isInitialized_)
{
// This is the first call, initialize the data and set flag to true
init();
isInitialized_ = true;
}
// Get list of all overset regions // Get list of all overset regions
const PtrList<oversetRegion>& allRegions = const PtrList<oversetRegion>& allRegions =
this->region().overset().regions(); this->region().overset().regions();
@ -118,6 +206,9 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
if (allFringesReady) if (allFringesReady)
{ {
Info<< "All dependent fringes are ready. Starting donor based layered"
<< " overlap assembly..." << endl;
// Loop through connected regions // Loop through connected regions
forAll (connectedRegionIDs_, crI) forAll (connectedRegionIDs_, crI)
{ {
@ -217,10 +308,18 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
const label nUniqueDonors = const label nUniqueDonors =
returnReduce(donors.size(), sumOp<label>()); returnReduce(donors.size(), sumOp<label>());
// Calculate the final centre point by finding the arithmetic mean // Calculate the final centre point by finding the arithmetic
// mean
centrePoint /= nUniqueDonors; centrePoint /= nUniqueDonors;
} }
if (debug)
{
Info<< "Centre point for donors for region "
<< allRegions[regionID].name() << " is : " << centrePoint
<< endl;
}
// We now have a collection of all donors for this connected region // We now have a collection of all donors for this connected region
// and the centre point to move to. Let's collect the acceptors // and the centre point to move to. Let's collect the acceptors
labelHashSet acceptors(donors.size()); // Reasonable size estimate labelHashSet acceptors(donors.size()); // Reasonable size estimate
@ -348,8 +447,8 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
} }
} }
// Special treatment for last iteration // Special treatment for all non-final iterations
if (i == nLayers_ - 1) if (i < nLayers_ - 1)
{ {
// This is not the last iteration, transfer acceptors into // This is not the last iteration, transfer acceptors into
// donors // donors
@ -364,13 +463,14 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
// all cells that are ineligible (either donor or acceptor). The // all cells that are ineligible (either donor or acceptor). The
// remaining thing to do is to mark the interior holes // remaining thing to do is to mark the interior holes
// Create a hash set containing fringe holes, initialized with // Create a hash set that will contain fringe holes
// acceptors in order to avoid having special conditions in the loop
// below for the first pass
labelHashSet fringeHoles(10*acceptors.size()); labelHashSet fringeHoles(10*acceptors.size());
// Collect holes until there are no holes to collect // Collect holes until there are no holes to collect. Note: for the
// first iteration, we will start with acceptors, otherwise, we will
// start from all fringe holes
label nAddedHoles; label nAddedHoles;
bool firstIteration = true;
do do
{ {
// Reset number of newly added holes // Reset number of newly added holes
@ -379,10 +479,26 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
// Face markup for propagation // Face markup for propagation
boolList propagateFace(mesh.nFaces(), false); boolList propagateFace(mesh.nFaces(), false);
// Loop through all acceptors and mark faces that are pointing // Get collection of cells from which to start the search:
// towards the centre point and have eligible neighbour (not an // acceptors for the first iteration and fringe holes otherwise
// acceptor or donor) labelHashSet* curSetPtr = nullptr;
forAllConstIter (labelHashSet, fringeHoles, iter) if (firstIteration)
{
// Point current set to acceptors and switch off the flag
curSetPtr = &acceptors;
firstIteration = false;
}
else
{
// Point current set to fringe holes
curSetPtr = &fringeHoles;
}
const labelHashSet& curSet = *curSetPtr;
// Loop through all cells in the set and mark faces that are
// pointing towards the centre point and have eligible neighbour
// (not an acceptor or donor).
forAllConstIter (labelHashSet, curSet, iter)
{ {
// Get the cell index and the cell // Get the cell index and the cell
const label& cellI = iter.key(); const label& cellI = iter.key();
@ -499,8 +615,15 @@ void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const
// Connected fringes are not ready, allocate empty lists for acceptors // Connected fringes are not ready, allocate empty lists for acceptors
// and holes, which will be deleted when asked for again from the // and holes, which will be deleted when asked for again from the
// iterative procedure (see candidateAcceptors() and fringeHoles()) // iterative procedure (see candidateAcceptors() and fringeHoles())
acceptorsPtr_ = new labelList(0); acceptorsPtr_ = new labelList;
fringeHolesPtr_ = new labelList(0); fringeHolesPtr_ = new labelList;
}
if (debug)
{
Info<< "In donorBasedLayeredOverlapFringe::calcAddressing() const" << nl
<< "Found " << acceptorsPtr_->size() << " acceptors." << nl
<< "Found " << fringeHolesPtr_->size() << " fringe holes." << endl;
} }
} }
@ -524,6 +647,7 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
) )
: :
oversetFringe(mesh, region, dict), oversetFringe(mesh, region, dict),
connectedRegionNames_(dict.lookup("connectedRegions")),
connectedRegionIDs_(), connectedRegionIDs_(),
regionCentrePoints_ regionCentrePoints_
( (
@ -536,7 +660,8 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
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)
@ -556,147 +681,6 @@ Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe
<< "The number should be greater than 0." << "The number should be greater than 0."
<< abort(FatalError); << abort(FatalError);
} }
// Read names of connected regions
const wordList connectedRegionNames(dict.lookup("connectedRegions"));
// 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 and check whether the overlap has been found
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
(
"donorBasedLayeredOverlapFringe::"
"donorBasedLayeredOverlapFringe\n"
"(\n"
" const fvMesh& mesh,\n"
" const oversetRegion& region,\n"
" const dictionary& dict\n"
")"
) << "Region " << crName << " not found in list of regions."
<< "List of overset regions: " << allRegionNames
<< 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
(
"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_.empty()
&& (regionCentrePoints_.size() != connectedRegionIDs_.size())
)
{
// The list is not empty and the size of the list is not the same as the
// size of the connected regions. This is a problem
FatalErrorIn
(
"donorBasedLayeredOverlapFringe::"
"donorBasedLayeredOverlapFringe\n"
"(\n"
" const fvMesh& mesh,\n"
" const oversetRegion& region,\n"
" const dictionary& dict\n"
")"
) << "You have specified "
<< regionCentrePoints_.size()
<< " regionCentrePoints, while specifying "
<< connectedRegionIDs_.size()
<< " connectedRegions."
<< nl
<< "If you'd like to avoid using automatic centre point detection,"
<< " 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;
}
} }
@ -730,15 +714,28 @@ bool Foam::donorBasedLayeredOverlapFringe::updateIteration
<< abort(FatalError); << abort(FatalError);
} }
// Allocate the list by reusing the argument list if
finalDonorAcceptorsPtr_ = new donorAcceptorList
( (
donorAcceptorRegionData, fringeHolesPtr_ && acceptorsPtr_
true && !fringeHolesPtr_->empty() && !acceptorsPtr_->empty()
); )
{
// Set the flag to true and return // Allocate the list by reusing the argument list
updateSuitableOverlapFlag(true); finalDonorAcceptorsPtr_ = new donorAcceptorList
(
donorAcceptorRegionData,
true
);
// Set the flag to true
updateSuitableOverlapFlag(true);
}
else
{
// Delete fringeHolesPtr and acceptorsPtr to trigger calculation of
// addressing, this time with other fringes up-to-date
}
// else suitable overlap has not been found and there's nothing to do
return foundSuitableOverlap(); return foundSuitableOverlap();
} }
@ -759,13 +756,16 @@ const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::fringeHoles() const
// See calcAddressing() for details // See calcAddressing() for details
deleteDemandDrivenData(fringeHolesPtr_); deleteDemandDrivenData(fringeHolesPtr_);
deleteDemandDrivenData(acceptorsPtr_); deleteDemandDrivenData(acceptorsPtr_);
calcAddressing();
} }
return *fringeHolesPtr_; return *fringeHolesPtr_;
} }
const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::candidateAcceptors() const const Foam::labelList&
Foam::donorBasedLayeredOverlapFringe::candidateAcceptors() const
{ {
if (!acceptorsPtr_) if (!acceptorsPtr_)
{ {
@ -780,20 +780,23 @@ const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::candidateAcceptors(
// See calcAddressing() for details // See calcAddressing() for details
deleteDemandDrivenData(fringeHolesPtr_); deleteDemandDrivenData(fringeHolesPtr_);
deleteDemandDrivenData(acceptorsPtr_); deleteDemandDrivenData(acceptorsPtr_);
calcAddressing();
} }
return *acceptorsPtr_; return *acceptorsPtr_;
} }
Foam::donorAcceptorList& Foam::donorBasedLayeredOverlapFringe::finalDonorAcceptors() const Foam::donorAcceptorList&
Foam::donorBasedLayeredOverlapFringe::finalDonorAcceptors() const
{ {
if (!finalDonorAcceptorsPtr_) if (!finalDonorAcceptorsPtr_)
{ {
FatalErrorIn("donorBasedLayeredOverlapFringe::finalDonorAcceptors()") FatalErrorIn("donorBasedLayeredOverlapFringe::finalDonorAcceptors()")
<< "finalDonorAcceptorPtr_ not allocated. Make sure you have " << "finalDonorAcceptorPtr_ not allocated. Make sure you have"
<< "called donorBasedLayeredOverlapFringe::updateIteration() before asking for " << " called donorBasedLayeredOverlapFringe::updateIteration() before"
<< "final set of donor/acceptor pairs." << " asking for final set of donor/acceptor pairs."
<< abort(FatalError); << abort(FatalError);
} }

View file

@ -65,9 +65,14 @@ class donorBasedLayeredOverlapFringe
{ {
// Private data // Private data
//- Names of connected regions. Looked up on construction
wordList connectedRegionNames_;
//- Regions IDs from which the donors will be collected as a starting //- Regions IDs from which the donors will be collected as a starting
// point // point. Note: initialized in init private member function because we
labelList connectedRegionIDs_; // cannot initialize it in constructor. This is because certain overset
// regions (and their fringes) may not be initialized at this point.
mutable labelList connectedRegionIDs_;
//- Optional list of points representing a rough estimate of the centre //- Optional list of points representing a rough estimate of the centre
// for each underlying connected region. If these are not provided, the // for each underlying connected region. If these are not provided, the
@ -88,6 +93,9 @@ class donorBasedLayeredOverlapFringe
//- 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 static data // Private static data
@ -98,17 +106,13 @@ class donorBasedLayeredOverlapFringe
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Initialization
donorBasedLayeredOverlapFringe(const donorBasedLayeredOverlapFringe&); void init() const;
//- Disallow default bitwise assignment //- Calculate hole and acceptor addressing
void operator=(const donorBasedLayeredOverlapFringe&);
// Calculate hole and acceptor addressing
void calcAddressing() const; void calcAddressing() const;
// Clear addressing //- Clear addressing
void clearAddressing() const; void clearAddressing() const;
@ -128,6 +132,15 @@ public:
const dictionary& dict const dictionary& dict
); );
//- Disallow default bitwise copy construct
donorBasedLayeredOverlapFringe
(
const donorBasedLayeredOverlapFringe&
) = delete;
//- Disallow default bitwise assignment
void operator=(const donorBasedLayeredOverlapFringe&) = delete;
// Destructor // Destructor