From 31019383d28bdda2301314a10bc8dc02a3352a34 Mon Sep 17 00:00:00 2001 From: Vuko Vukcevic Date: Tue, 9 Apr 2019 17:16:26 +0200 Subject: [PATCH 01/17] Temporary commit donorBasedLayeredOverlap fringe algorithm. Work in progress. --- .../donorBasedLayeredOverlap.C | 392 ++++++++++++++++++ .../donorBasedLayeredOverlap.H | 164 ++++++++ .../oversetMesh/oversetRegion/oversetRegion.C | 14 + .../oversetMesh/oversetRegion/oversetRegion.H | 3 + 4 files changed, 573 insertions(+) create mode 100644 src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C create mode 100644 src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.H diff --git a/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C b/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C new file mode 100644 index 000000000..fbedea562 --- /dev/null +++ b/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.C @@ -0,0 +1,392 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 4.1 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + foam-extend is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with foam-extend. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "donorBasedLayeredOverlapFringe.H" +#include "faceCellsFringe.H" +#include "oversetRegion.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(donorBasedLayeredOverlapFringe, 0); + addToRunTimeSelectionTable + ( + oversetFringe, + donorBasedLayeredOverlapFringe, + dictionary + ); +} + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const +{ + if (acceptorsPtr_) + { + FatalErrorIn + ( + "void Foam::donorBasedLayeredOverlapFringe::calcAddressing() const" + ) << "Addressing already calculated" + << abort(FatalError); + } + + // Get reference to region cell zone + const cellZone& rcz = region().zone(); + + // 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) + { + const polyPatchID curFringePatch + ( + patchNames_[nameI], + mesh().boundaryMesh() + ); + + if (!curFringePatch.active()) + { + FatalErrorIn + ( + "void donorBasedLayeredOverlapFringe::calcAddressing() const" + ) << "Fringe patch " << patchNames_[nameI] + << " cannot be found" + << abort(FatalError); + } + + 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]); + } + } + } + + // Collect acceptors + acceptorsPtr_ = new labelList(acceptorSet.sortedToc()); + + // Holes are empty for this fringe + fringeHolesPtr_ = new labelList(); +} + + +void Foam::donorBasedLayeredOverlapFringe::clearAddressing() const +{ + deleteDemandDrivenData(fringeHolesPtr_); + deleteDemandDrivenData(acceptorsPtr_); + deleteDemandDrivenData(finalDonorAcceptorsPtr_); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from dictionary +Foam::donorBasedLayeredOverlapFringe::donorBasedLayeredOverlapFringe +( + const fvMesh& mesh, + const oversetRegion& region, + const dictionary& dict +) +: + oversetFringe(mesh, region, dict), + connectedRegionIDs_(), + regionCentrePoints_ + ( + dict.lookupOrDefault("regionCentrePoints", pointList(0)) + ), + nLayers_(readLabel(dict.lookup("nLayers"))), + fringeHolesPtr_(nullptr), + acceptorsPtr_(nullptr), + finalDonorAcceptorsPtr_(nullptr) +{ + // 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& 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 (connectedRegion_, crI) + { + // Get name of this connected region + const word& crName = connectedRegion_[crI]; + + // Find this region in the list of all regions + const label regionID = findIndex(allRegions, 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: number of (optionally) specified centre points must be + // equal to the number of connected regions + if + ( + regionCentrePoints_.size() + && (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); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::donorBasedLayeredOverlapFringe::~donorBasedLayeredOverlapFringe() +{ + clearAddressing(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::donorBasedLayeredOverlapFringe::updateIteration +( + donorAcceptorList& donorAcceptorRegionData +) const +{ + // If the donorAcceptor list has been allocated, something went wrong with + // the iteration procedure (not-updated flag): this function has been called + // more than once, which should not happen for donorBasedLayeredOverlapFringe + if (finalDonorAcceptorsPtr_) + { + FatalErrorIn + ( + "donorBasedLayeredOverlapFringe::updateIteration(donorAcceptorList&" + ) << "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& 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(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 + ( + donorAcceptorRegionData, + true + ); + + // 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(); +} + + +const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::fringeHoles() const +{ + if (!fringeHolesPtr_) + { + calcAddressing(); + } + + return *fringeHolesPtr_; +} + + +const Foam::labelList& Foam::donorBasedLayeredOverlapFringe::candidateAcceptors() const +{ + if (!acceptorsPtr_) + { + calcAddressing(); + } + + return *acceptorsPtr_; +} + + +Foam::donorAcceptorList& Foam::donorBasedLayeredOverlapFringe::finalDonorAcceptors() const +{ + if (!finalDonorAcceptorsPtr_) + { + FatalErrorIn("donorBasedLayeredOverlapFringe::finalDonorAcceptors()") + << "finalDonorAcceptorPtr_ not allocated. Make sure you have " + << "called donorBasedLayeredOverlapFringe::updateIteration() before asking for " + << "final set of donor/acceptor pairs." + << abort(FatalError); + } + + if (!foundSuitableOverlap()) + { + FatalErrorIn("donorBasedLayeredOverlapFringe::finalDonorAcceptors()") + << "Attemted to access finalDonorAcceptors but suitable overlap " + << "has not been found. This is not allowed. " + << abort(FatalError); + } + + return *finalDonorAcceptorsPtr_; +} + + +void Foam::donorBasedLayeredOverlapFringe::update() const +{ + if (updateFringe_) + { + Info<< "donorBasedLayeredOverlapFringe::update() const" << endl; + + // Clear out + clearAddressing(); + } + + // Set flag to false and clear final donor/acceptors only + deleteDemandDrivenData(finalDonorAcceptorsPtr_); +} + + +// ************************************************************************* // diff --git a/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.H b/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.H new file mode 100644 index 000000000..dd10a4e5c --- /dev/null +++ b/src/overset/oversetMesh/oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlap.H @@ -0,0 +1,164 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 4.1 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + foam-extend is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with foam-extend. If not, see . + +Class + donorBasedLayeredOverlapFringe + +Description + Fringe algorithm based on donors from different regions. The algorithm waits + 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. + + 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). + +Author + Vuko Vukcevic, Wikki Ltd. All rights reserved. + +SourceFiles + donorBasedLayeredOverlapFringe.C + +\*---------------------------------------------------------------------------*/ + +#ifndef donorBasedLayeredOverlapFringe_H +#define donorBasedLayeredOverlapFringe_H + +#include "oversetFringe.H" +#include "pointList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class donorBasedLayeredOverlapFringe Declaration +\*---------------------------------------------------------------------------*/ + +class donorBasedLayeredOverlapFringe +: + public oversetFringe +{ + // Private data + + //- Regions IDs from which the donors will be collected as a starting + // point + labelList connectedRegionsIDs_; + + //- 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 + pointList regionCentrePoints_; + + //- How many layers to move away from connected region donors to define + // acceptor (and holes) + label nLayers_; + + //- Fringe hole cells + mutable labelList* fringeHolesPtr_; + + //- Acceptor cells + mutable labelList* acceptorsPtr_; + + //- Final donor/acceptor pairs for this region (fringe) + mutable donorAcceptorList* finalDonorAcceptorsPtr_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + donorBasedLayeredOverlapFringe(const donorBasedLayeredOverlapFringe&); + + //- Disallow default bitwise assignment + void operator=(const donorBasedLayeredOverlapFringe&); + + + // Calculate hole and acceptor addressing + void calcAddressing() const; + + // Clear addressing + void clearAddressing() const; + + +public: + + //- Runtime type information + TypeName("donorBasedLayeredOverlap"); + + + // Constructors + + //- Construct from dictionary + donorBasedLayeredOverlapFringe + ( + const fvMesh& mesh, + const oversetRegion& region, + const dictionary& dict + ); + + + // Destructor + + virtual ~donorBasedLayeredOverlapFringe(); + + + // Member Functions + + //- Update iteration. Note: invalidates parameter + virtual bool updateIteration + ( + donorAcceptorList& donorAcceptorRegionData + ) const; + + //- Return list of deactivated (hole) cells + // Fringe hole cells are collected in addition to geometric hole + // cells, which fall outside of all donor regions + virtual const labelList& fringeHoles() const; + + //- Return list of acceptor cells + virtual const labelList& candidateAcceptors() const; + + //- Return list of final donor acceptor pairs. Note: caller may + // invalidate finalDonorAcceptorsPtr_ for optimisation purposes + virtual donorAcceptorList& finalDonorAcceptors() const; + + //- Update the fringe + virtual void update() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/overset/oversetMesh/oversetRegion/oversetRegion.C b/src/overset/oversetMesh/oversetRegion/oversetRegion.C index 009cf948b..573b8d4d7 100644 --- a/src/overset/oversetMesh/oversetRegion/oversetRegion.C +++ b/src/overset/oversetMesh/oversetRegion/oversetRegion.C @@ -1730,6 +1730,20 @@ Foam::oversetRegion::~oversetRegion() // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // +const Foam::oversetFringe& Foam::oversetRegion::fringe() const +{ + if (fringePtr_.empty()) + { + FatalErrorIn("const oversetFringe& oversetRegion::fringe() const") + << "Fringe pointer not allocated. It should have been initialized" + << " properly at construction. Something went wrong..." + << abort(FatalError); + } + + return fringePtr_(); +} + + const Foam::labelList& Foam::oversetRegion::donorRegions() const { if (!donorRegionsPtr_) diff --git a/src/overset/oversetMesh/oversetRegion/oversetRegion.H b/src/overset/oversetMesh/oversetRegion/oversetRegion.H index efdcb106a..346ef3c51 100644 --- a/src/overset/oversetMesh/oversetRegion/oversetRegion.H +++ b/src/overset/oversetMesh/oversetRegion/oversetRegion.H @@ -327,6 +327,9 @@ public: return zone(); } + //- Return overset fringe algorithm for this region + const oversetFringe& fringe() const; + //- Return list of donor region indices const labelList& donorRegions() const; From 6a5117ed5186f7212f804e5c2274f3052090ce43 Mon Sep 17 00:00:00 2001 From: Vuko Vukcevic Date: Wed, 10 Apr 2019 18:17:51 +0200 Subject: [PATCH 02/17] Finished writing first version of donorBasedLayeredOverlap fringe Note: did not attempt to compile yet, let alone test it --- .../donorBasedLayeredOverlap.C | 677 ++++++++++++++---- .../donorBasedLayeredOverlap.H | 19 +- 2 files changed, 565 insertions(+), 131 deletions(-) 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