diff --git a/src/overset/oversetMesh/Make/files b/src/overset/oversetMesh/Make/files
index 2a7175cc0..d21982f92 100644
--- a/src/overset/oversetMesh/Make/files
+++ b/src/overset/oversetMesh/Make/files
@@ -5,6 +5,7 @@ oversetFringe/oversetFringe/newOversetFringe.C
oversetFringe/manualFringe/manualFringe.C
oversetFringe/faceCellsFringe/faceCellsFringe.C
oversetFringe/donorBasedLayeredOverlapFringe/donorBasedLayeredOverlapFringe.C
+oversetFringe/cuttingPatchFringe/cuttingPatchFringe.C
oversetFringe/overlapFringe/overlapFringe/overlapFringe.C
oversetFringe/overlapFringe/layeredOverlapFringe/layeredOverlapFringe.C
oversetFringe/overlapFringe/adaptiveOverlapFringe/adaptiveOverlapFringe.C
diff --git a/src/overset/oversetMesh/oversetFringe/cuttingPatchFringe/cuttingPatchFringe.C b/src/overset/oversetMesh/oversetFringe/cuttingPatchFringe/cuttingPatchFringe.C
new file mode 100644
index 000000000..f3b49587e
--- /dev/null
+++ b/src/overset/oversetMesh/oversetFringe/cuttingPatchFringe/cuttingPatchFringe.C
@@ -0,0 +1,772 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 "cuttingPatchFringe.H"
+#include "oversetMesh.H"
+#include "oversetRegion.H"
+#include "faceCellsFringe.H"
+#include "oversetRegion.H"
+#include "polyPatchID.H"
+#include "addToRunTimeSelectionTable.H"
+#include "syncTools.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+ defineTypeNameAndDebug(cuttingPatchFringe, 0);
+ addToRunTimeSelectionTable
+ (
+ oversetFringe,
+ cuttingPatchFringe,
+ dictionary
+ );
+}
+
+
+// * * * * * * * * * * * * * 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& 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 cuttingPatchFringe::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 for. 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
+{
+ // Make sure that either acceptorsPtr is unnalocated or if it is allocated,
+ // that it is empty
+ if (acceptorsPtr_ && !acceptorsPtr_->empty())
+ {
+ FatalErrorIn
+ (
+ "void Foam::cuttingPatchFringe::calcAddressing() const"
+ ) << "Addressing already calculated"
+ << 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
+ const PtrList& allRegions =
+ this->region().overset().regions();
+
+ // Sets containing all acceptors and all holes for all connected regions
+ const polyMesh& mesh = this->mesh();
+ labelHashSet allAcceptors(0.02*mesh.nCells());
+ labelHashSet allFringeHoles(0.02*mesh.nCells());
+
+ if (debug)
+ {
+ Info<< "All dependent fringes are ready."
+ << " Starting face cells cut patch fringe assembly..." << endl;
+ }
+
+ // 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();
+
+ // 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(fringe))
+ {
+ FatalErrorIn
+ (
+ "void Foam::cuttingPatchFringe::"
+ "updateIteration(donorAcceptorList&) const"
+ ) << "cuttingPatch fringe is designed to work"
+ << " 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);
+ }
+ const faceCellsFringe& fcFringe =
+ refCast(fringe);
+
+ // Get patch names from faceCells fringe
+ const wordList& fcPatchNames = fcFringe.patchNames();
+
+ // Find the patches
+ labelHashSet patchIDs;
+
+ forAll (fcPatchNames, nameI)
+ {
+ // Get polyPatchID and check if valid
+ const polyPatchID fringePatch
+ (
+ fcPatchNames[nameI],
+ mesh.boundaryMesh()
+ );
+
+ if (!fringePatch.active())
+ {
+ FatalErrorIn
+ (
+ "void cuttingPatchFringe::calcAddressing const"
+ ) << "Fringe patch " << fcPatchNames[nameI]
+ << " for region " << allRegions[regionID].name()
+ << " cannot be found."
+ << abort(FatalError);
+ }
+
+ // Store patch ID in the set
+ patchIDs.insert(fringePatch.index());
+ }
+
+ // Note: same 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)
+ {
+ triFaces[tsI] = ts[tsI].reverseFace();
+ }
+ }
+
+ if (Pstream::parRun())
+ {
+ // Combine all faces and points into a single list
+
+ List allTriFaces(Pstream::nProcs());
+ List 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();
+ }
+
+ // Pack points
+ triPoints.setSize(nPoints);
+
+ // Prepare point renumbering array
+ 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];
+ procRenumberPoints[ptpI] = nPoints;
+
+ nPoints++;
+ }
+ }
+
+ // Pack triangles and renumber into complete points on the fly
+ 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
+ triSurface patchTriMesh(triFaces, triPoints);
+
+ // Clean up duplicate points and zero sized triangles
+ patchTriMesh.cleanup(false);
+
+ // Get this region
+ const oversetRegion& myRegion = this->region();
+
+ // Debug: write down the tri mesh
+ if (Pstream::master())
+ {
+ patchTriMesh.write
+ (
+ word
+ (
+ "patchTriSurface_region" + myRegion.name() +
+ "_connectedRegion" + allRegions[regionID].name() + ".vtk"
+ )
+ );
+ }
+
+ // Create the tri surface search object
+ triSurfaceSearch patchTriSearch(patchTriMesh);
+
+ // Get cells in this region
+ const labelList& myRegionCells = myRegion.regionCells();
+
+ // Get cell centres for inside-outside search using search object
+ vectorField myCC(myRegionCells.size());
+
+ // Cell centres from polyMesh
+ const vectorField& cc = mesh.cellCentres();
+
+ 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];
+ }
+
+ // Get necessary mesh data (from polyMesh/primitiveMesh)
+ const cellList& meshCells = mesh.cells();
+ const unallocLabelList& owner = mesh.faceOwner();
+ const unallocLabelList& neighbour = mesh.faceNeighbour();
+
+ // Collect all inside cells either as hole cells or acceptor
+ // cells. For the first iteration, acceptor cells are the cells that
+ // have at least one neighbour cell that is not marked
+ labelHashSet acceptors(myRegionCells.size()/10);
+
+ // 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
+ // its faces and set the flag
+ const cell& cFaces = meshCells[cellI];
+
+ forAll (cFaces, i)
+ {
+ // Set the mark for this global face and break out
+ hasUnmarkedCell[cFaces[i]] = true;
+ break;
+ }
+ }
+ }
+
+ // Sync the face list across processor boundaries
+ syncTools::syncFaceList
+ (
+ mesh,
+ hasUnmarkedCell,
+ orOp(),
+ false
+ );
+
+ // Mark-up for all hole faces
+ boolList holeFaceMask(mesh.nFaces(), false);
+
+ // 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];
+
+ // Helper variable to determine whether this marked cell
+ // should be collected as a hole
+ bool isHole = true;
+
+ 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, set isHole to false and break
+ acceptors.insert(cellI);
+ isHole = false;
+ break;
+ }
+ }
+
+ // If this is a hole, collect it and mark its faces
+ if (isHole)
+ {
+ holeCellMask[cellI] = true;
+
+ // Loop through cell faces and mark them
+ const cell& cFaces = meshCells[cellI];
+
+ forAll (cFaces, i)
+ {
+ holeFaceMask[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 donors 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 (holeFaceMask[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(),
+ 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 (holeCellMask[own])
+ {
+ // Owner cell is a hole, insert it
+ newAcceptors.insert(own);
+
+ // Update hole mask
+ holeCellMask[own] = false;
+ }
+ else if (holeCellMask[nei])
+ {
+ // Neighbour cell is a hole, insert it
+ newAcceptors.insert(nei);
+
+ // Update hole mask
+ holeCellMask[nei] = false;
+ }
+
+ // Also update hole face mask for next iteration
+ holeFaceMask[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 (holeCellMask[own])
+ {
+ // Face cell is a hole, insert it
+ newAcceptors.insert(own);
+
+ // Update hole mask
+ holeCellMask[own] = false;
+ }
+
+ // Also update hole face mask for next iteration
+ holeFaceMask[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 (holeCellMask, cellI)
+ {
+ if (holeCellMask[cellI])
+ {
+ fringeHoles.insert(cellI);
+ }
+ }
+
+ // Finally, we have fringe holes and acceptors and we need to add them
+ // to the list containing all acceptors and holes (for all connected
+ // regions)
+ allAcceptors += acceptors;
+ allFringeHoles += fringeHoles;
+ }
+
+ // Set acceptors and holes from the data for all regions
+ acceptorsPtr_ = new labelList(allAcceptors.sortedToc());
+ fringeHolesPtr_ = new labelList(allFringeHoles.sortedToc());
+
+ if (debug)
+ {
+ Info<< "In cuttingPatchFringe::calcAddressing() const" << nl
+ << "Found " << acceptorsPtr_->size() << " acceptors." << nl
+ << "Found " << fringeHolesPtr_->size() << " fringe holes." << endl;
+ }
+}
+
+
+void Foam::cuttingPatchFringe::clearAddressing() const
+{
+ deleteDemandDrivenData(fringeHolesPtr_);
+ deleteDemandDrivenData(acceptorsPtr_);
+ deleteDemandDrivenData(finalDonorAcceptorsPtr_);
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+// Construct from dictionary
+Foam::cuttingPatchFringe::cuttingPatchFringe
+(
+ const fvMesh& mesh,
+ const oversetRegion& region,
+ const dictionary& dict
+)
+:
+ oversetFringe(mesh, region, dict),
+ connectedRegionNames_(dict.lookup("connectedRegions")),
+ connectedRegionIDs_(),
+ nLayers_(readLabel(dict.lookup("nLayers"))),
+ fringeHolesPtr_(nullptr),
+ acceptorsPtr_(nullptr),
+ finalDonorAcceptorsPtr_(nullptr),
+ isInitialized_(false)
+{
+ // Sanity check number of layers: must be greater than 0
+ if (nLayers_ < 1)
+ {
+ FatalIOErrorIn
+ (
+ "cuttingPatchFringe::"
+ "cuttingPatchFringe\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);
+ }
+
+ // Preferably, the number of layers should be at least 2
+ if (nLayers_ == 1)
+ {
+ WarningIn
+ (
+ "cuttingPatchFringe::"
+ "cuttingPatchFringe\n"
+ "(\n"
+ " const fvMesh& mesh,\n"
+ " const oversetRegion& region,\n"
+ " const dictionary& dict\n"
+ ")"
+ ) << "You have specified nLayers = " << nLayers_
+ << nl
+ << "We strongly advise to use at least 2 layers to avoid"
+ << " possibility of having acceptors that cannot find decent"
+ << " donors on the other side."
+ << abort(FatalError);
+ }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+
+Foam::cuttingPatchFringe::~cuttingPatchFringe()
+{
+ clearAddressing();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+bool Foam::cuttingPatchFringe::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 cuttingPatchFringe
+ if (finalDonorAcceptorsPtr_)
+ {
+ FatalErrorIn
+ (
+ "cuttingPatchFringe::"
+ "updateIteration(donorAcceptorList&) const"
+ ) << "finalDonorAcceptorPtr_ already allocated. Something went "
+ << "wrong with the iteration procedure (flag was not updated)."
+ << nl
+ << "This should not happen for cuttingPatchFringe."
+ << abort(FatalError);
+ }
+
+ // Allocate the list by reusing the argument list
+ finalDonorAcceptorsPtr_ = new donorAcceptorList
+ (
+ donorAcceptorRegionData,
+ true
+ );
+
+ // Set the flag to true and return
+ updateSuitableOverlapFlag(true);
+
+ return foundSuitableOverlap();
+}
+
+
+const Foam::labelList& Foam::cuttingPatchFringe::fringeHoles() const
+{
+ if (!fringeHolesPtr_)
+ {
+ calcAddressing();
+ }
+
+ return *fringeHolesPtr_;
+}
+
+
+const Foam::labelList& Foam::cuttingPatchFringe::candidateAcceptors() const
+{
+ if (!acceptorsPtr_)
+ {
+ calcAddressing();
+ }
+
+ return *acceptorsPtr_;
+}
+
+
+Foam::donorAcceptorList&
+Foam::cuttingPatchFringe::finalDonorAcceptors() const
+{
+ if (!finalDonorAcceptorsPtr_)
+ {
+ FatalErrorIn("cuttingPatchFringe::finalDonorAcceptors()")
+ << "finalDonorAcceptorPtr_ not allocated. Make sure you have"
+ << " called cuttingPatchFringe::updateIteration() before"
+ << " asking for final set of donor/acceptor pairs."
+ << abort(FatalError);
+ }
+
+ if (!foundSuitableOverlap())
+ {
+ FatalErrorIn("cuttingPatchFringe::finalDonorAcceptors()")
+ << "Attemted to access finalDonorAcceptors but suitable overlap "
+ << "has not been found. This is not allowed. "
+ << abort(FatalError);
+ }
+
+ return *finalDonorAcceptorsPtr_;
+}
+
+
+void Foam::cuttingPatchFringe::update() const
+{
+ Info<< "cuttingPatchFringe::update() const" << endl;
+
+ // Clear out
+ clearAddressing();
+
+ // Set flag to false and clear final donor/acceptors only
+ deleteDemandDrivenData(finalDonorAcceptorsPtr_);
+ updateSuitableOverlapFlag(false);
+}
+
+
+// ************************************************************************* //
diff --git a/src/overset/oversetMesh/oversetFringe/cuttingPatchFringe/cuttingPatchFringe.H b/src/overset/oversetMesh/oversetFringe/cuttingPatchFringe/cuttingPatchFringe.H
new file mode 100644
index 000000000..cc885c303
--- /dev/null
+++ b/src/overset/oversetMesh/oversetFringe/cuttingPatchFringe/cuttingPatchFringe.H
@@ -0,0 +1,163 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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
+ cuttingPatchFringe
+
+Description
+ Fringe algorithm based on collecting all the cells cut by its donor region
+ patch (assuming faceCells algorithm is used). Inside cells are marked and
+ moved nLayers towards the interior to define the acceptors as robustly as
+ possible.
+
+Author
+ Vuko Vukcevic, Wikki Ltd. All rights reserved.
+
+SourceFiles
+ cuttingPatchFringe.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cuttingPatchFringe_H
+#define cuttingPatchFringe_H
+
+#include "oversetFringe.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+ Class cuttingPatchFringe Declaration
+\*---------------------------------------------------------------------------*/
+
+class cuttingPatchFringe
+:
+ public oversetFringe
+{
+ // Private data
+
+ //- Names of connected regions. Looked up on construction
+ wordList connectedRegionNames_;
+
+ //- 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
+ // 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_;
+
+ //- Initialization helper
+ mutable bool isInitialized_;
+
+
+ // Private Member Functions
+
+ //- Initialization
+ void init() const;
+
+ //- Calculate hole and acceptor addressing
+ void calcAddressing() const;
+
+ //- Clear addressing
+ void clearAddressing() const;
+
+
+public:
+
+ //- Runtime type information
+ TypeName("cuttingPatch");
+
+
+ // Constructors
+
+ //- Construct from dictionary
+ cuttingPatchFringe
+ (
+ const fvMesh& mesh,
+ const oversetRegion& region,
+ const dictionary& dict
+ );
+
+ //- Disallow default bitwise copy construct
+ cuttingPatchFringe
+ (
+ const cuttingPatchFringe&
+ ) = delete;
+
+ //- Disallow default bitwise assignment
+ void operator=(const cuttingPatchFringe&) = delete;
+
+
+ // Destructor
+
+ virtual ~cuttingPatchFringe();
+
+
+ // 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
+
+// ************************************************************************* //