ENH: globalIndex gather for PatchTools::gatherAndMerge (#2402)

- lower memory overhead, simpler code and eliminates need for
  ListListOps::combineOffset()

- optional handling of local faces/points for re-using in different
  contexts

STYLE: labelUList instead of labelList for globalMesh mergePoints

STYLE: adjust verbose information from mergePoints

- also report the current new-point location
This commit is contained in:
Mark Olesen
2022-03-10 14:32:19 +01:00
parent 6e509c10fc
commit f7cbb0672b
7 changed files with 129 additions and 151 deletions

View File

@ -89,12 +89,12 @@ Foam::label Foam::mergePoints
Field<scalar> sortedTol(nPoints); Field<scalar> sortedTol(nPoints);
forAll(order, sortI) forAll(order, sorti)
{ {
const point_type& pt = points[order[sortI]]; const point_type& pt = points[order[sorti]];
// Use scalar precision // Use scalar precision
sortedTol[sortI] = sortedTol[sorti] =
2*mergeTol* 2*mergeTol*
( (
mag(scalar(pt.x() - compareOrigin.x())) mag(scalar(pt.x() - compareOrigin.x()))
@ -109,11 +109,16 @@ Foam::label Foam::mergePoints
label pointi = order[0]; label pointi = order[0];
pointMap[pointi] = newPointi++; pointMap[pointi] = newPointi++;
for (label sortI = 1; sortI < order.size(); ++sortI) /// if (verbose)
/// {
/// Pout<< "Foam::mergePoints : [0] Uniq point " << pointi << endl;
/// }
for (label sorti = 1; sorti < order.size(); ++sorti)
{ {
// Get original point index // Get original point index
const label pointi = order[sortI]; const label pointi = order[sorti];
const scalar mag2 = magSqrDist[order[sortI]]; const scalar mag2 = magSqrDist[order[sorti]];
// Convert to scalar precision // Convert to scalar precision
// NOTE: not yet using point_type template parameter // NOTE: not yet using point_type template parameter
@ -130,13 +135,13 @@ Foam::label Foam::mergePoints
for for
( (
label prevSortI = sortI - 1; label prevSorti = sorti - 1;
prevSortI >= 0 prevSorti >= 0
&& (mag(magSqrDist[order[prevSortI]] - mag2) <= sortedTol[sortI]); && (mag(magSqrDist[order[prevSorti]] - mag2) <= sortedTol[sorti]);
--prevSortI --prevSorti
) )
{ {
const label prevPointi = order[prevSortI]; const label prevPointi = order[prevSorti];
// Convert to scalar precision // Convert to scalar precision
// NOTE: not yet using point_type template parameter // NOTE: not yet using point_type template parameter
@ -164,16 +169,22 @@ Foam::label Foam::mergePoints
if (verbose) if (verbose)
{ {
Pout<< "Foam::mergePoints : Merging points " Pout<< "Foam::mergePoints : [" << pointMap[pointi]
<< pointi << " and " << equalPointi << "] Point " << pointi << " duplicate of " << equalPointi
<< " with coordinates:" << points[pointi] << " : coordinates:" << points[pointi]
<< " and " << points[equalPointi] << " and " << points[equalPointi] << endl;
<< endl;
} }
} }
else else
{ {
// Differs. Store new point. // Differs. Store new point.
/// if (verbose)
/// {
/// Pout<< "Foam::mergePoints : [" << newPointi
/// << "] Uniq point " << pointi << endl;
/// }
pointMap[pointi] = newPointi++; pointMap[pointi] = newPointi++;
} }
} }
@ -200,7 +211,7 @@ bool Foam::mergePoints
typename PointList::const_reference origin typename PointList::const_reference origin
) )
{ {
const label nUnique = mergePoints const label nUnique = Foam::mergePoints
( (
points, points,
mergeTol, mergeTol,
@ -209,7 +220,7 @@ bool Foam::mergePoints
origin origin
); );
newPoints.setSize(nUnique); newPoints.resize_nocopy(nUnique);
forAll(pointMap, pointi) forAll(pointMap, pointi)
{ {
newPoints[pointMap[pointi]] = points[pointi]; newPoints[pointMap[pointi]] = points[pointi];

View File

@ -138,7 +138,7 @@ void Foam::globalMeshData::calcSharedPoints() const
// Calculate all shared points (exclude points that are only // Calculate all shared points (exclude points that are only
// on two coupled patches). This does all the hard work. // on two coupled patches). This does all the hard work.
globalPoints parallelPoints(mesh_, false, true); const globalPoints parallelPoints(mesh_, false, true);
// Count the number of master points // Count the number of master points
label nMaster = 0; label nMaster = 0;
@ -155,7 +155,7 @@ void Foam::globalMeshData::calcSharedPoints() const
} }
// Allocate global numbers // Allocate global numbers
globalIndex masterNumbering(nMaster); const globalIndex masterNumbering(nMaster);
nGlobalPoints_ = masterNumbering.totalSize(); nGlobalPoints_ = masterNumbering.totalSize();
@ -2472,7 +2472,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
( (
const labelList& meshPoints, const labelUList& meshPoints,
const Map<label>& /* unused: meshPointMap */, const Map<label>& /* unused: meshPointMap */,
labelList& pointToGlobal, labelList& pointToGlobal,
labelList& uniqueMeshPoints labelList& uniqueMeshPoints
@ -2498,7 +2498,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
// - from coupled point to global patch point // - from coupled point to global patch point
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
globalIndex globalPPoints(meshPoints.size()); const globalIndex globalPPoints(meshPoints.size());
labelList patchToCoupled(meshPoints.size(), -1); labelList patchToCoupled(meshPoints.size(), -1);
label nCoupled = 0; label nCoupled = 0;

View File

@ -576,7 +576,7 @@ public:
// - the global number for all local points. // - the global number for all local points.
autoPtr<globalIndex> mergePoints autoPtr<globalIndex> mergePoints
( (
const labelList& meshPoints, const labelUList& meshPoints,
const Map<label>& meshPointMap, //!< currently unused const Map<label>& meshPointMap, //!< currently unused
labelList& pointToGlobal, labelList& pointToGlobal,
labelList& uniqueMeshPoints labelList& uniqueMeshPoints

View File

@ -218,12 +218,20 @@ public:
//- Gather points and faces onto master and merge into single patch. //- Gather points and faces onto master and merge into single patch.
// Note: uses faces/points, not localFaces/localPoints. // Note: Normally uses faces/points (not localFaces/localPoints)
//
// \param[in] mergeDist Geometric merge tolerance for Foam::mergePoints
// \param[in] pp The patch to merge
// \param[out] mergedPoints
// \param[out] mergedFaces
// \param[out] pointMergeMap
// \param[in] useLocal gather/merge the localFaces/localPoints
// instead of (global) faces/points
template<class FaceList, class PointField> template<class FaceList, class PointField>
static void gatherAndMerge static void gatherAndMerge
( (
const scalar mergeDist, const scalar mergeDist,
const PrimitivePatch<FaceList, PointField>& p, const PrimitivePatch<FaceList, PointField>& pp,
Field Field
< <
typename PrimitivePatch<FaceList, PointField>::point_type typename PrimitivePatch<FaceList, PointField>::point_type
@ -232,7 +240,8 @@ public:
< <
typename PrimitivePatch<FaceList, PointField>::face_type typename PrimitivePatch<FaceList, PointField>::face_type
>& mergedFaces, >& mergedFaces,
labelList& pointMergeMap labelList& pointMergeMap,
const bool useLocal = false
); );
//- Gather (mesh!) points and faces onto master and merge collocated //- Gather (mesh!) points and faces onto master and merge collocated

View File

@ -37,7 +37,7 @@ template<class FaceList, class PointField>
void Foam::PatchTools::gatherAndMerge void Foam::PatchTools::gatherAndMerge
( (
const scalar mergeDist, const scalar mergeDist,
const PrimitivePatch<FaceList, PointField>& p, const PrimitivePatch<FaceList, PointField>& pp,
Field Field
< <
typename PrimitivePatch<FaceList, PointField>::point_type typename PrimitivePatch<FaceList, PointField>::point_type
@ -46,50 +46,54 @@ void Foam::PatchTools::gatherAndMerge
< <
typename PrimitivePatch<FaceList, PointField>::face_type typename PrimitivePatch<FaceList, PointField>::face_type
>& mergedFaces, >& mergedFaces,
labelList& pointMergeMap labelList& pointMergeMap,
const bool useLocal
) )
{ {
typedef typename PrimitivePatch<FaceList,PointField>::face_type FaceType; typedef typename PrimitivePatch<FaceList,PointField>::face_type FaceType;
typedef typename PrimitivePatch<FaceList,PointField>::point_type PointType; typedef typename PrimitivePatch<FaceList,PointField>::point_type PointType;
// Collect points from all processors // Faces from all ranks
labelList pointSizes; const globalIndex faceAddr(pp.size(), globalIndex::gatherOnly{});
{
const globalIndex gi(p.points().size());
gi.gather(p.points(), mergedPoints); // Points from all ranks
const globalIndex pointAddr
pointSizes = gi.sizes();
}
// Collect faces from all processors and renumber using sizes of
// gathered points
{
List<List<FaceType>> gatheredFaces(Pstream::nProcs());
gatheredFaces[Pstream::myProcNo()] = p;
Pstream::gatherList(gatheredFaces);
if (Pstream::master())
{
mergedFaces = static_cast<const List<FaceType>&>
( (
ListListOps::combineOffset<List<FaceType>> (useLocal ? pp.localPoints().size() : pp.points().size()),
( globalIndex::gatherOnly{}
gatheredFaces,
pointSizes,
accessOp<List<FaceType>>(),
offsetOp<FaceType>()
)
); );
if (useLocal)
{
faceAddr.gather(pp.localFaces(), mergedFaces);
pointAddr.gather(pp.localPoints(), mergedPoints);
}
else
{
faceAddr.gather(pp, mergedFaces);
pointAddr.gather(pp.points(), mergedPoints);
}
// Relabel faces according to global point offsets
for (const label proci : faceAddr.subProcs())
{
SubList<FaceType> slot(mergedFaces, faceAddr.range(proci));
for (auto& f : slot)
{
pointAddr.inplaceToGlobal(proci, f);
} }
} }
if (Pstream::master()) // Merging points
bool hasMerged = false;
if (Pstream::parRun() && Pstream::master())
{ {
Field<PointType> newPoints; Field<PointType> newPoints;
labelList oldToNew; labelList oldToNew;
bool hasMerged = mergePoints hasMerged = Foam::mergePoints
( (
mergedPoints, mergedPoints,
mergeDist, mergeDist,
@ -100,19 +104,28 @@ void Foam::PatchTools::gatherAndMerge
if (hasMerged) if (hasMerged)
{ {
// Store point mapping
pointMergeMap.transfer(oldToNew);
// Copy points
mergedPoints.transfer(newPoints);
// Relabel faces // Relabel faces
for (auto& f : mergedFaces) for (auto& f : mergedFaces)
{ {
inplaceRenumber(pointMergeMap, f); inplaceRenumber(oldToNew, f);
}
// Store newly merged points
mergedPoints.transfer(newPoints);
// Store point mapping
if (notNull(pointMergeMap))
{
pointMergeMap.transfer(oldToNew);
} }
} }
} }
// TDB:
// if (!hasMerged && notNull(pointMergeMap))
// {
// pointMergeMap.clear();
// }
} }

View File

@ -468,9 +468,15 @@ public:
bool hasPointNormals() const { return bool(pointNormalsPtr_); } bool hasPointNormals() const { return bool(pointNormalsPtr_); }
bool hasBoundaryPoints() const { return bool(boundaryPointsPtr_); } bool hasBoundaryPoints() const { return bool(boundaryPointsPtr_); }
// These ones are currently all calculated together:
// - edges(), faceFaces(), edgeFaces(), faceEdges()
bool hasEdges() const { return bool(edgesPtr_); }
bool hasFaceFaces() const { return bool(faceFacesPtr_); } bool hasFaceFaces() const { return bool(faceFacesPtr_); }
bool hasEdgeFaces() const { return bool(edgeFacesPtr_); } bool hasEdgeFaces() const { return bool(edgeFacesPtr_); }
bool hasFaceEdges() const { return bool(faceEdgesPtr_); } bool hasFaceEdges() const { return bool(faceEdgesPtr_); }
bool hasPointEdges() const { return bool(pointEdgesPtr_); } bool hasPointEdges() const { return bool(pointEdgesPtr_); }
bool hasPointFaces() const { return bool(pointFacesPtr_); } bool hasPointFaces() const { return bool(pointFacesPtr_); }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd. Copyright (C) 2017-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -32,7 +32,7 @@ License
#include "coupledPolyPatch.H" #include "coupledPolyPatch.H"
#include "sampledSurface.H" #include "sampledSurface.H"
#include "mergePoints.H" #include "mergePoints.H"
#include "uindirectPrimitivePatch.H" #include "indirectPrimitivePatch.H"
#include "PatchTools.H" #include "PatchTools.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
@ -353,104 +353,43 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
pointField& points pointField& points
) const ) const
{ {
List<faceList> allFaces(Pstream::nProcs()); labelList whichFaces(faceId_);
List<pointField> allPoints(Pstream::nProcs());
{ // Remap patch-face ids to mesh face ids
IndirectList<face> selectedFaces(mesh_.faces(), labelList(faceId_)); forAll(whichFaces, i)
labelList& meshFaceIds = selectedFaces.addressing();
forAll(meshFaceIds, i)
{ {
const label patchi = facePatchId_[i]; const label patchi = facePatchId_[i];
if (patchi != -1) if (patchi != -1)
{ {
meshFaceIds[i] += mesh_.boundaryMesh()[patchi].start(); whichFaces[i] += mesh_.boundaryMesh()[patchi].start();
} }
} }
// Add local faces and points to the all* lists indirectPrimitivePatch pp
uindirectPrimitivePatch pp(selectedFaces, mesh_.points());
allFaces[Pstream::myProcNo()] = pp.localFaces();
allPoints[Pstream::myProcNo()] = pp.localPoints();
}
Pstream::gatherList(allFaces);
Pstream::gatherList(allPoints);
// Renumber and flatten
label nFaces = 0;
label nPoints = 0;
forAll(allFaces, proci)
{
nFaces += allFaces[proci].size();
nPoints += allPoints[proci].size();
}
faces.resize(nFaces);
points.resize(nPoints);
nFaces = 0;
nPoints = 0;
// My data first
{
for (const face& f : allFaces[Pstream::myProcNo()])
{
faces[nFaces++] = offsetOp<face>()(f, nPoints);
}
for (const point& p : allPoints[Pstream::myProcNo()])
{
points[nPoints++] = p;
}
}
// Other proc data follows
forAll(allFaces, proci)
{
if (proci == Pstream::myProcNo())
{
continue;
}
for (const face& f : allFaces[proci])
{
faces[nFaces++] = offsetOp<face>()(f, nPoints);
}
for (const point& p : allPoints[proci])
{
points[nPoints++] = p;
}
}
// Merge
labelList oldToNew;
pointField newPoints;
bool hasMerged = mergePoints
( (
points, IndirectList<face>(mesh_.faces(), std::move(whichFaces)),
SMALL, mesh_.points()
false,
oldToNew,
newPoints
); );
if (hasMerged)
{
if (debug)
{
Pout<< "Merged from " << points.size()
<< " down to " << newPoints.size() << " points" << endl;
}
points.transfer(newPoints); if (Pstream::parRun())
for (face& f : faces)
{ {
inplaceRenumber(oldToNew, f); labelList pointsMap;
PatchTools::gatherAndMerge
(
SMALL, // mergeDist
pp,
points,
faces,
pointsMap,
true // useLocal=true
);
} }
else
{
faces = pp.localFaces();
points = pp.localPoints();
} }
} }