Skip to content
Snippets Groups Projects
Commit b76178bd authored by andy's avatar andy
Browse files

ENH: Corrected cloud penetration for parallel cases

parent 6774f024
No related branches found
No related tags found
No related merge requests found
...@@ -24,6 +24,7 @@ License ...@@ -24,6 +24,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "fvmSup.H" #include "fvmSup.H"
#include "SortableList.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
...@@ -343,99 +344,123 @@ inline Foam::scalar Foam::KinematicCloud<CloudType>::Dmax() const ...@@ -343,99 +344,123 @@ inline Foam::scalar Foam::KinematicCloud<CloudType>::Dmax() const
template<class CloudType> template<class CloudType>
inline Foam::scalar Foam::KinematicCloud<CloudType>::penetration inline Foam::scalar Foam::KinematicCloud<CloudType>::penetration
( (
const scalar& prc const scalar& fraction
) const ) const
{ {
scalar distance = 0.0; if ((fraction < 0) || (fraction > 1))
scalar mTot = 0.0; {
FatalErrorIn
(
"inline Foam::scalar Foam::KinematicCloud<CloudType>::penetration"
"("
"const scalar&"
") const"
)
<< "fraction should be in the range 0 < fraction < 1"
<< exit(FatalError);
}
label np = this->size(); scalar distance = 0.0;
// arrays containing the parcels mass and const label nParcel = this->size();
// distance from injector in ascending order globalIndex globalParcels(nParcel);
scalarField mass(np); const label nParcelSum = globalParcels.size();
scalarField dist(np);
if (np > 0) if (nParcelSum == 0)
{ {
label n = 0; return distance;
}
// first arrange the parcels in ascending order // lists of parcels mass and distance from initial injection point
// the first parcel is closest to its injection position List<scalar> mass(nParcel, 0.0);
// and the last one is most far away. List<scalar> dist(nParcel, 0.0);
forAllConstIter(typename KinematicCloud<CloudType>, *this, iter)
{
const parcelType& p = iter();
scalar mi = p.nParticle()*p.mass();
scalar di = mag(p.position() - p.position0());
mTot += mi;
// insert at the last place label i = 0;
mass[n] = mi; scalar mSum = 0.0;
dist[n] = di; forAllConstIter(typename KinematicCloud<CloudType>, *this, iter)
{
const parcelType& p = iter();
scalar m = p.nParticle()*p.mass();
scalar d = mag(p.position() - p.position0());
mSum += m;
label i = 0; mass[i] = m;
bool found = false; dist[i] = d;
// insert the parcel in the correct place i++;
// and move the others
while ((i < n) && (!found))
{
if (di < dist[i])
{
found = true;
for (label j=n; j>i; j--)
{
mass[j] = mass[j-1];
dist[j] = dist[j-1];
}
mass[i] = mi;
dist[i] = di;
}
i++;
}
n++;
}
} }
reduce(mTot, sumOp<scalar>()); // calculate total mass across all processors
reduce(mSum, sumOp<scalar>());
// flatten the mass list
List<scalar> allMass(nParcelSum, 0.0);
SubList<scalar>
(
allMass,
globalParcels.localSize(Pstream::myProcNo()),
globalParcels.offset(Pstream::myProcNo())
).assign(mass);
// flatten the distance list
SortableList<scalar> allDist(nParcelSum, 0.0);
SubList<scalar>
(
allDist,
globalParcels.localSize(Pstream::myProcNo()),
globalParcels.offset(Pstream::myProcNo())
).assign(dist);
// sort allDist distances into ascending order
// note: allMass masses are left unsorted
allDist.sort();
if (np > 0) if (nParcelSum > 1)
{ {
scalar mLimit = prc*mTot; const scalar mLimit = fraction*mSum;
scalar mOff = (1.0 - prc)*mTot; const labelList& indices = allDist.indices();
if (np > 1) if (mLimit > (mSum - allMass[indices.last()]))
{ {
// 'prc' is large enough that the parcel most far distance = allDist.last();
// away will be used, no need to loop... }
if (mLimit > mTot - mass[np-1]) else
{ {
distance = dist[np-1]; // assuming that 'fraction' is generally closer to 1 than 0, loop
} // through in reverse distance order
else const scalar mThreshold = (1.0 - fraction)*mSum;
scalar mCurrent = 0.0;
label i0 = 0;
forAllReverse(indices, i)
{ {
scalar mOffSum = 0.0; label indI = indices[i];
label i = np;
mCurrent += allMass[indI];
while ((mOffSum < mOff) && (i>0)) if (mCurrent > mThreshold)
{ {
i--; i0 = i;
mOffSum += mass[i]; break;
} }
distance =
dist[i+1]
+ (dist[i] - dist[i+1])*(mOffSum - mOff)
/mass[i+1] ;
} }
}
else if (i0 == indices.size() - 1)
{ {
distance = dist[0]; distance = allDist.last();
}
else
{
// linearly interpolate to determine distance
scalar alpha = (mCurrent - mThreshold)/allMass[indices[i0]];
distance = allDist[i0] + alpha*(allDist[i0+1] - allDist[i0]);
}
} }
} }
else
reduce(distance, maxOp<scalar>()); {
distance = allDist.first();
}
return distance; return distance;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment