ENH: use globalIndex gather for simpler code and less communication

- checkTools, PatchTools::gatherAndMerge, SprayCloud penetration
This commit is contained in:
Mark Olesen
2022-02-23 15:31:31 +01:00
committed by Andrew Heather
parent c178fe8ec1
commit a6d1f47943
4 changed files with 69 additions and 178 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2015-2017 OpenFOAM Foundation Copyright (C) 2015-2017 OpenFOAM Foundation
Copyright (C) 2015-2021 OpenCFD Ltd. Copyright (C) 2015-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -423,8 +423,8 @@ void Foam::mergeAndWrite
{ {
const polyMesh& mesh = refCast<const polyMesh>(set.db()); const polyMesh& mesh = refCast<const polyMesh>(set.db());
pointField mergedPts; labelField mergedIDs(set.sortedToc());
labelList mergedIDs; pointField mergedPts(mesh.points(), mergedIDs);
if (Pstream::parRun()) if (Pstream::parRun())
{ {
@ -432,55 +432,12 @@ void Foam::mergeAndWrite
// (mesh.globalData().mergePoints etc) since this might // (mesh.globalData().mergePoints etc) since this might
// hide any synchronisation problem // hide any synchronisation problem
globalIndex globalNumbering(mesh.nPoints()); // Renumber local ids -> global ids
globalIndex(mesh.nPoints()).inplaceToGlobal(mergedIDs);
mergedPts.setSize(returnReduce(set.size(), sumOp<label>())); globalIndex gatherer(mergedIDs.size(), globalIndex::gatherOnly{});
mergedIDs.setSize(mergedPts.size()); gatherer.gatherInplace(mergedIDs);
gatherer.gatherInplace(mergedPts);
labelList setPointIDs(set.sortedToc());
// Get renumbered local data
pointField myPoints(mesh.points(), setPointIDs);
labelList myIDs(globalNumbering.toGlobal(setPointIDs));
if (Pstream::master())
{
// Insert master data first
label pOffset = 0;
SubList<point>(mergedPts, myPoints.size(), pOffset) = myPoints;
SubList<label>(mergedIDs, myIDs.size(), pOffset) = myIDs;
pOffset += myPoints.size();
// Receive slave ones
for (const int slave : Pstream::subProcs())
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
pointField slavePts(fromSlave);
labelList slaveIDs(fromSlave);
SubList<point>(mergedPts, slavePts.size(), pOffset) = slavePts;
SubList<label>(mergedIDs, slaveIDs.size(), pOffset) = slaveIDs;
pOffset += slaveIDs.size();
}
}
else
{
// Construct processor stream with estimate of size. Could
// be improved.
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo(),
myPoints.byteSize() + myIDs.byteSize()
);
toMaster << myPoints << myIDs;
}
}
else
{
mergedIDs = set.sortedToc();
mergedPts = pointField(mesh.points(), mergedIDs);
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2012-2017 OpenFOAM Foundation Copyright (C) 2012-2017 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -136,7 +136,7 @@ void Foam::PatchTools::gatherAndMerge
if (Pstream::parRun()) if (Pstream::parRun())
{ {
// Renumber the setPatch points/faces into unique points // Renumber the points/faces into unique points
globalPointsPtr = mesh.globalData().mergePoints globalPointsPtr = mesh.globalData().mergePoints
( (
meshPoints, meshPoints,
@ -147,65 +147,22 @@ void Foam::PatchTools::gatherAndMerge
globalFacesPtr.reset(new globalIndex(localFaces.size())); globalFacesPtr.reset(new globalIndex(localFaces.size()));
if (Pstream::master()) // Renumber faces locally
List<FaceType> myFaces(localFaces);
for (auto& f : myFaces)
{ {
// Get renumbered local data inplaceRenumber(pointToGlobal, f);
pointField myPoints(mesh.points(), uniqueMeshPointLabels);
List<FaceType> myFaces(localFaces);
for (auto& f : myFaces)
{
inplaceRenumber(pointToGlobal, f);
}
mergedFaces.setSize(globalFacesPtr().totalSize());
mergedPoints.setSize(globalPointsPtr().totalSize());
// Insert master data first
label pOffset = globalPointsPtr().localStart(Pstream::masterNo());
SubList<point>(mergedPoints, myPoints.size(), pOffset) = myPoints;
label fOffset = globalFacesPtr().localStart(Pstream::masterNo());
SubList<FaceType>(mergedFaces, myFaces.size(), fOffset) = myFaces;
// Receive slave ones
for (const int slave : Pstream::subProcs())
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
pointField slavePoints(fromSlave);
List<FaceType> slaveFaces(fromSlave);
label pOffset = globalPointsPtr().localStart(slave);
SubList<point>(mergedPoints, slavePoints.size(), pOffset) =
slavePoints;
label fOffset = globalFacesPtr().localStart(slave);
SubList<FaceType>(mergedFaces, slaveFaces.size(), fOffset) =
slaveFaces;
}
} }
else
{
// Get renumbered local data
pointField myPoints(mesh.points(), uniqueMeshPointLabels);
List<FaceType> myFaces(localFaces);
for (auto& f : myFaces)
{
inplaceRenumber(pointToGlobal, f);
}
// Construct processor stream with estimate of size. Could // Can also use
// be improved. // UIndirectList<point>(mesh.points(), uniqueMeshPointLabels)
OPstream toMaster // but favour communication over local memory use
( globalPointsPtr().gather
Pstream::commsTypes::scheduled, (
Pstream::masterNo(), pointField(mesh.points(), uniqueMeshPointLabels),
myPoints.byteSize() + 4*sizeof(label)*myFaces.size() mergedPoints
); );
toMaster << myPoints << myFaces; globalFacesPtr().gather(myFaces, mergedFaces);
}
} }
else else
{ {

View File

@ -35,11 +35,11 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef SprayCloud_H #ifndef Foam_SprayCloud_H
#define SprayCloud_H #define Foam_SprayCloud_H
#include "sprayCloud.H" #include "sprayCloud.H"
#include "SortableList.H" #include "SortList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -88,95 +88,73 @@ inline Foam::scalar Foam::SprayCloud<CloudType>::penetration
<< exit(FatalError); << exit(FatalError);
} }
scalar distance = 0.0;
const label nParcel = this->size(); const label nParcel = this->size();
globalIndex globalParcels(nParcel); const globalIndex globalParcels(nParcel);
const label nParcelSum = globalParcels.totalSize(); const label nTotParcel = globalParcels.totalSize();
if (nParcelSum == 0) if (nTotParcel == 0)
{ {
return distance; return 0;
} }
// lists of parcels mass and distance from initial injection point // lists of parcels mass and distance from initial injection point
List<List<scalar>> procMass(Pstream::nProcs()); List<scalar> mass(nParcel);
List<List<scalar>> procDist(Pstream::nProcs()); List<scalar> dist(nParcel);
List<scalar>& mass = procMass[Pstream::myProcNo()]; scalar mTotal = 0;
List<scalar>& dist = procDist[Pstream::myProcNo()];
mass.setSize(nParcel);
dist.setSize(nParcel);
label i = 0;
scalar mSum = 0.0;
for (const parcelType& p : *this)
{ {
scalar m = p.nParticle()*p.mass(); label i = 0;
scalar d = mag(p.position() - p.position0()); for (const parcelType& p : *this)
mSum += m; {
scalar m = p.nParticle()*p.mass();
scalar d = mag(p.position() - p.position0());
mTotal += m;
mass[i] = m; mass[i] = m;
dist[i] = d; dist[i] = d;
++i;
++i; }
} }
// Total mass across all processors
reduce(mTotal, sumOp<scalar>());
// calculate total mass across all processors scalar distance = 0;
reduce(mSum, sumOp<scalar>()); globalParcels.gatherInplace(mass);
Pstream::gatherList(procMass); globalParcels.gatherInplace(dist);
Pstream::gatherList(procDist);
if (Pstream::master()) if (Pstream::master())
{ {
// flatten the mass lists if (nTotParcel == 1)
List<scalar> allMass(nParcelSum, Zero);
SortableList<scalar> allDist(nParcelSum, Zero);
for (const int proci : Pstream::allProcs())
{ {
SubList<scalar> distance = dist[0];
(
allMass,
globalParcels.localSize(proci),
globalParcels.localStart(proci)
) = procMass[proci];
// flatten the distance list
SubList<scalar>
(
allDist,
globalParcels.localSize(proci),
globalParcels.localStart(proci)
) = procDist[proci];
} }
else
// sort allDist distances into ascending order
// note: allMass masses are left unsorted
allDist.sort();
if (nParcelSum > 1)
{ {
const scalar mLimit = fraction*mSum; // Distances - sored into ascending order
const labelList& indices = allDist.indices(); // Masses - leave unsorted
if (mLimit > (mSum - allMass[indices.last()])) const SortList<scalar> sortedDist(dist);
const scalar mLimit = fraction*mTotal;
const labelList& indices = sortedDist.indices();
if (mLimit > (mTotal - mass[indices.last()]))
{ {
distance = allDist.last(); distance = sortedDist.last();
} }
else else
{ {
// assuming that 'fraction' is generally closer to 1 than 0, // assuming that 'fraction' is generally closer to 1 than 0,
// loop through in reverse distance order // loop through in reverse distance order
const scalar mThreshold = (1.0 - fraction)*mSum; const scalar mThreshold = (1.0 - fraction)*mTotal;
scalar mCurrent = 0.0; scalar mCurrent = 0;
label i0 = 0; label i0 = 0;
forAllReverse(indices, i) forAllReverse(indices, i)
{ {
label indI = indices[i]; label indI = indices[i];
mCurrent += allMass[indI]; mCurrent += mass[indI];
if (mCurrent > mThreshold) if (mCurrent > mThreshold)
{ {
@ -187,21 +165,20 @@ inline Foam::scalar Foam::SprayCloud<CloudType>::penetration
if (i0 == indices.size() - 1) if (i0 == indices.size() - 1)
{ {
distance = allDist.last(); distance = sortedDist.last();
} }
else else
{ {
// linearly interpolate to determine distance // linearly interpolate to determine distance
scalar alpha = (mCurrent - mThreshold)/allMass[indices[i0]]; scalar alpha = (mCurrent - mThreshold)/mass[indices[i0]];
distance = distance =
allDist[i0] + alpha*(allDist[i0+1] - allDist[i0]); (
sortedDist[i0]
+ alpha*(sortedDist[i0+1] - sortedDist[i0])
);
} }
} }
} }
else
{
distance = allDist.first();
}
} }
Pstream::scatter(distance); Pstream::scatter(distance);