Commit 4421021e authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: support use of bitSet for regionSplit

parent 0b68f14f
......@@ -70,6 +70,36 @@ static labelList containerSizes(const UList<Container>& input)
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::regionSplit::checkBoundaryFaceSync
(
const boolList& blockedFace
) const
{
if (blockedFace.size())
{
// Check that blockedFace is synced.
boolList syncBlockedFace(blockedFace);
syncTools::swapFaceList(mesh(), syncBlockedFace);
forAll(syncBlockedFace, facei)
{
if
(
blockedFace.test(facei)
!= syncBlockedFace.test(facei)
)
{
FatalErrorInFunction
<< "Face " << facei << " not synchronised. My value:"
<< blockedFace.test(facei) << " coupled value:"
<< syncBlockedFace.test(facei) << nl
<< abort(FatalError);
}
}
}
}
void Foam::regionSplit::updateFacePair
(
const label face0,
......@@ -122,7 +152,7 @@ void Foam::regionSplit::updateFacePair
void Foam::regionSplit::fillSeedMask
(
const List<labelPair>& explicitConnections,
const UList<labelPair>& explicitConnections,
const label seedCellId,
const label markValue,
labelList& cellRegion,
......@@ -200,16 +230,12 @@ void Foam::regionSplit::fillSeedMask
for (const polyPatch& pp : patches)
{
if
(
isA<cyclicPolyPatch>(pp)
&& refCast<const cyclicPolyPatch>(pp).owner()
)
const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
if (bool(cpp) && cpp->owner())
{
// Transfer from neighbourPatch to here or vice versa.
const cyclicPolyPatch& cycPatch =
refCast<const cyclicPolyPatch>(pp);
const auto& cycPatch = *cpp;
label face0 = cycPatch.start();
......@@ -251,57 +277,19 @@ void Foam::regionSplit::fillSeedMask
}
Foam::label Foam::regionSplit::calcLocalRegionSplit
Foam::label Foam::regionSplit::localRegionSplit
(
const boolList& blockedFace,
const List<labelPair>& explicitConnections,
const UList<labelPair>& explicitConnections,
labelList& cellRegion
labelList& cellRegion,
labelList& faceRegion
) const
{
clockValue timing(debug);
if (debug)
{
if (blockedFace.size())
{
// Check that blockedFace is synced.
boolList syncBlockedFace(blockedFace);
syncTools::swapFaceList(mesh(), syncBlockedFace);
forAll(syncBlockedFace, facei)
{
if (syncBlockedFace[facei] != blockedFace[facei])
{
FatalErrorInFunction
<< "Face " << facei << " not synchronised. My value:"
<< blockedFace[facei] << " coupled value:"
<< syncBlockedFace[facei]
<< abort(FatalError);
}
}
}
}
changedCells_.reserve(mesh_.nCells());
changedFaces_.reserve(mesh_.nFaces());
// Region per face.
// -1 = unassigned
// -2 = blocked
labelList faceRegion(mesh().nFaces(), UNASSIGNED);
if (blockedFace.size())
{
forAll(blockedFace, facei)
{
if (blockedFace[facei])
{
faceRegion[facei] = BLOCKED;
}
}
}
// Assign local regions
// ~~~~~~~~~~~~~~~~~~~~
......@@ -371,31 +359,6 @@ Foam::label Foam::regionSplit::calcLocalRegionSplit
}
Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit
(
const bool doGlobalRegions,
const boolList& blockedFace,
const List<labelPair>& explicitConnections,
labelList& cellRegion
) const
{
const label nLocalRegions = calcLocalRegionSplit
(
blockedFace,
explicitConnections,
cellRegion
);
if (!doGlobalRegions)
{
return autoPtr<globalIndex>::New(nLocalRegions);
}
return reduceRegions(nLocalRegions, blockedFace, cellRegion);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::regionSplit::regionSplit
......@@ -404,36 +367,60 @@ Foam::regionSplit::regionSplit
const bool doGlobalRegions
)
:
MeshObject<polyMesh, Foam::TopologicalMeshObject, regionSplit>(mesh),
labelList(mesh.nCells(), -1)
{
globalNumberingPtr_ = calcRegionSplit
regionSplit
(
doGlobalRegions,
boolList(), // No blockedFace
mesh,
bitSet(), // No blockedFace
List<labelPair>(), // No explicitConnections
*this
);
}
doGlobalRegions
)
{}
Foam::regionSplit::regionSplit
(
const polyMesh& mesh,
const boolList& blockedFace,
const bitSet& blockedFace,
const List<labelPair>& explicitConnections,
const bool doGlobalRegions
)
:
MeshObject<polyMesh, Foam::TopologicalMeshObject, regionSplit>(mesh),
labelList(mesh.nCells(), -1)
labelList(mesh.nCells(), UNASSIGNED),
globalNumbering_()
{
globalNumberingPtr_ = calcRegionSplit
(
doGlobalRegions,
blockedFace,
List<labelPair>(), // No explicitConnections
*this
);
// if (debug)
// {
// checkBoundaryFaceSync(blockedFace);
// }
labelList& cellRegion = *this;
labelList faceRegion(mesh.nFaces(), UNASSIGNED);
for (const label facei : blockedFace)
{
faceRegion[facei] = BLOCKED;
}
const label numLocalRegions =
localRegionSplit(explicitConnections, cellRegion, faceRegion);
faceRegion.clear();
if (doGlobalRegions)
{
// Wrap bitset or bools
bitSetOrBoolList hasBlockedFace(blockedFace);
globalNumbering_ =
reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
}
else
{
globalNumbering_ = globalIndex(numLocalRegions);
}
}
......@@ -446,25 +433,54 @@ Foam::regionSplit::regionSplit
)
:
MeshObject<polyMesh, Foam::TopologicalMeshObject, regionSplit>(mesh),
labelList(mesh.nCells(), -1)
labelList(mesh.nCells(), UNASSIGNED),
globalNumbering_()
{
globalNumberingPtr_ = calcRegionSplit
(
doGlobalRegions,
blockedFace,
explicitConnections,
*this
);
if (debug)
{
checkBoundaryFaceSync(blockedFace);
}
labelList& cellRegion = *this;
labelList faceRegion(mesh.nFaces(), UNASSIGNED);
forAll(blockedFace, facei)
{
if (blockedFace.test(facei))
{
faceRegion[facei] = BLOCKED;
}
}
const label numLocalRegions =
localRegionSplit(explicitConnections, cellRegion, faceRegion);
faceRegion.clear();
if (doGlobalRegions)
{
// Wrap bitset or bools
bitSetOrBoolList hasBlockedFace(blockedFace);
globalNumbering_ =
reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
}
else
{
globalNumbering_ = globalIndex(numLocalRegions);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::reduceRegions
Foam::globalIndex
Foam::regionSplit::reduceRegionsImpl
(
const label numLocalRegions,
const boolList& blockedFace,
const bitSetOrBoolList& blockedFace,
labelList& cellRegion
) const
{
......@@ -474,8 +490,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::reduceRegions
{
FatalErrorInFunction
<< "The cellRegion size " << cellRegion.size()
<< " is not equal to the of number of cells "
<< mesh().nCells() << endl
<< " != number of cells " << mesh().nCells() << endl
<< abort(FatalError);
}
......@@ -549,22 +564,23 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::reduceRegions
{
if (pp.coupled())
{
const labelUList& faceCells = pp.faceCells();
SubList<label> patchNbrRegion
(
nbrRegion,
pp.size(),
pp.start()-mesh().nInternalFaces()
pp.offset()
);
const labelUList& faceCells = pp.faceCells();
forAll(faceCells, patchFacei)
{
const label celli = faceCells[patchFacei];
const label meshFacei = pp.start()+patchFacei;
if (!blockedFace[meshFacei])
if (!blockedFace.test(meshFacei))
{
// Send the most currently updated region Id
const label orig = cellRegion[faceCells[patchFacei]];
const label orig = cellRegion[celli];
patchNbrRegion[patchFacei] = localToGlobal[orig];
}
......@@ -578,23 +594,24 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::reduceRegions
{
if (pp.coupled())
{
const labelUList& faceCells = pp.faceCells();
SubList<label> patchNbrRegion
(
nbrRegion,
pp.size(),
pp.start()-mesh().nInternalFaces()
pp.offset()
);
const labelUList& faceCells = pp.faceCells();
forAll(faceCells, patchFacei)
{
const label celli = faceCells[patchFacei];
const label meshFacei = pp.start()+patchFacei;
if (!blockedFace[meshFacei])
if (!blockedFace.test(meshFacei))
{
// Reduction by retaining the min region id.
const label orig = cellRegion[faceCells[patchFacei]];
const label orig = cellRegion[celli];
const label sent = localToGlobal[orig];
const label recv = patchNbrRegion[patchFacei];
......@@ -689,8 +706,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::reduceRegions
// The new global numbering using compacted local regions
auto globalCompactPtr = autoPtr<globalIndex>::New(nCompact);
const auto& globalCompact = *globalCompactPtr;
globalIndex globalCompact(nCompact);
// Determine the following:
......@@ -817,7 +833,23 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::reduceRegions
DebugInfo
<<"regionSplit::reduceRegions = " << double(timing.elapsed()) << "s\n";
return globalCompactPtr;
return globalCompact;
}
Foam::globalIndex
Foam::regionSplit::reduceRegions
(
const label numLocalRegions,
const bitSet& blockedFace,
labelList& cellRegion
) const
{
// Wrap bitset or bools
bitSetOrBoolList hasBlockedFace(blockedFace);
return reduceRegionsImpl(numLocalRegions, hasBlockedFace, cellRegion);
}
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -122,6 +122,7 @@ SourceFiles
#include "globalIndex.H"
#include "labelPair.H"
#include "bitSet.H"
#include "boolList.H"
#include "MeshObject.H"
......@@ -130,8 +131,7 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class polyMesh;
/*---------------------------------------------------------------------------*\
......@@ -143,9 +143,10 @@ class regionSplit
public MeshObject<polyMesh, TopologicalMeshObject, regionSplit>,
public labelList
{
// Private data
// Private Data
autoPtr<globalIndex> globalNumberingPtr_;
//- Indexing into the regions
globalIndex globalNumbering_;
//- Temporary list of cells that have changed
mutable DynamicList<label> changedCells_;
......@@ -154,8 +155,43 @@ class regionSplit
mutable DynamicList<label> changedFaces_;
// Private Class
//- Simple wrapper for handling test() on bitSet or boolList
//- without a templating layer or lambda expresssion.
class bitSetOrBoolList
{
const bitSet& a_;
const boolList& b_;
public:
explicit bitSetOrBoolList(const bitSet& select)
:
a_(select),
b_(boolList::null())
{}
explicit bitSetOrBoolList(const boolList& select)
:
a_(bitSet::null()),
b_(select)
{}
//- Test function
bool test(const label i) const
{
return a_.test(i) || b_.test(i);
}
};
// Private Member Functions
//- Check that boundary faces are synchronised, or Fatal
void checkBoundaryFaceSync(const boolList& blockedFace) const;
//- Update faceRegion data between (non-processor) coupled faces.
void updateFacePair
(
......@@ -169,7 +205,7 @@ class regionSplit
//- for contiguous region around it
void fillSeedMask
(
const List<labelPair>& explicitConnections,
const UList<labelPair>& explicitConnections,
const label seedCellID,
const label markValue,
labelList& cellRegion,
......@@ -180,22 +216,21 @@ class regionSplit
//- Calculate the local region split.
// \return number of processor-local regions,
// without consolidation between procesors
label calcLocalRegionSplit
label localRegionSplit
(
const boolList& blockedFace,
const List<labelPair>& explicitConnections,
labelList& cellRegion
const UList<labelPair>& explicitConnections,
labelList& cellRegion,
labelList& faceRegion
) const;
//- Calculate the local region split.
// \return number of processor-local regions,
// without consolidation between procesors
autoPtr<globalIndex> calcRegionSplit
//- Manually consolidate regions globally by swapping information
// between processor domains and reducing the regions accordingly.
//
// \return globalIndex into the local regions after reduction.
globalIndex reduceRegionsImpl
(
const bool doGlobalRegions,
const boolList& blockedFace,
const List<labelPair>& explicitConnections,
const label numLocalRegions,
const bitSetOrBoolList& blockedFace,
labelList& cellRegion
) const;
......@@ -215,23 +250,29 @@ public:
const bool doGlobalRegions = Pstream::parRun()
);
//- Construct from mesh and whether face is blocked
//- Construct from mesh and whether face is blocked, optionally
//- with additional explicit connections between
//- normal boundary faces.
//
// \note blockedFace must be consistent across coupled faces!
regionSplit
(
const polyMesh& mesh,
const boolList& blockedFace,
const bitSet& blockedFace,
const List<labelPair>& explicitConnections = List<labelPair>(),
const bool doGlobalRegions = Pstream::parRun()
);
//- Construct from mesh and whether face is blocked, with additional
//- explicit connections between normal boundary faces.
//- Construct from mesh and whether face is blocked, optionally
//- with additional explicit connections between
//- normal boundary faces.
//
// \note blockedFace must be consistent across coupled faces!
regionSplit
(
const polyMesh& mesh,
const boolList& blockedFace,
const List<labelPair>& explicitConnections,
const List<labelPair>& explicitConnections = List<labelPair>(),
const bool doGlobalRegions = Pstream::parRun()
);
......@@ -239,9 +280,9 @@ public:
// Member Functions
//- Return global region numbering
const globalIndex& globalNumbering() const
const globalIndex& globalNumbering() const noexcept
{
return *globalNumberingPtr_;
return globalNumbering_;
}
//- Return local number of regions
......@@ -256,18 +297,16 @@ public:
return globalNumbering().size();
}
//- Manually consolidate the regions globally by swapping information
//- Manually consolidate regions globally by swapping information
// between processor domains and reducing the regions accordingly.
//
// \return number of local regions after reduction.
autoPtr<globalIndex> reduceRegions
// \return globalIndex into the local regions after reduction.
globalIndex reduceRegions
(
const label numLocalRegions,
const boolList& blockedFace,
const bitSet& blockedFace,
labelList& cellRegion
) const;
};
......
......@@ -30,6 +30,13 @@ License
#include "PatchEdgeFaceWave.H"
#include "edgeTopoDistanceData.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
static constexpr Foam::label UNASSIGNED = -1;
static constexpr Foam::label BLOCKED = -2;
// * * * * * * * * * * * * * * * * Constructor * * * * * * * * * * * * * * * //
Foam::regionSplit2D::regionSplit2D
......@@ -40,7 +47,7 @@ Foam::regionSplit2D::regionSplit2D
const label offset
)
:
labelList(patch.size(), -1),
labelList(patch.size(), UNASSIGNED),
nRegions_(0)
{
globalIndex globalFaces(blockedFaces.size());
......@@ -49,15 +56,15 @@ Foam::regionSplit2D::regionSplit2D
List<edgeTopoDistanceData<label>> allFaceInfo(patch.size());