mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: use globalIndex gather for simpler code and less communication
- checkTools, PatchTools::gatherAndMerge, SprayCloud penetration
This commit is contained in:
committed by
Andrew Heather
parent
c178fe8ec1
commit
a6d1f47943
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user