diff --git a/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C b/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C index fbedea562..cf55bf4a2 100644 --- a/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C +++ b/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C @@ -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& 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(fringe)) { - FatalErrorIn + WarningIn ( - "void donorBasedLayeredOverlapFringe::calcAddressing() const" - ) << "Fringe patch " << patchNames_[nameI] - << " cannot be found" - << abort(FatalError); + "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; } - const unallocLabelList& curFaceCells = - mesh().boundaryMesh()[curFringePatch.index()].donorBasedLayeredOverlap(); - - forAll (curFaceCells, fcI) - { - // Check if cell is in region zone - if (rcz.whichCell(curFaceCells[fcI]) > -1) - { - // Found acceptor - acceptorSet.insert(curFaceCells[fcI]); - } - } + // Update flag collecting whether all connected regions found the + // overlap + allFringesReady &= fringe.foundSuitableOverlap(); } - // Collect acceptors - acceptorsPtr_ = new labelList(acceptorSet.sortedToc()); + // Sets containing all acceptors and all holes for all connected regions + labelHashSet allAcceptors(0.02*mesh.nCells()); + labelHashSet allFringeHoles(0.02*mesh.nCells()); - // Holes are empty for this fringe - fringeHolesPtr_ = new labelList(); + 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 + ( + "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); + } + + // 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()) + { + // Get donor index + const label& dI = daPair.donorCell(); + + // Insert donor into the hash set + if (donors.insert(dI)) + { + // 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()); + nUniqueDonors = returnReduce(donors.size(), sumOp