ENH: extractEulerianParticles - refactoring and robustness improvements

This commit is contained in:
Andrew Heather
2018-11-02 11:22:17 +00:00
parent 8bf7a522e7
commit f5af16d968
2 changed files with 133 additions and 189 deletions

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -264,24 +264,16 @@ void Foam::functionObjects::extractEulerianParticles::setBlockedFaces
} }
void Foam::functionObjects::extractEulerianParticles::collectParticles void Foam::functionObjects::extractEulerianParticles::collectParticle
( (
const scalar time, const scalar time,
const boolList& collectParticle const label regioni
) )
{ {
DebugInFunction << "collectParticle: " << collectParticle << endl; DebugInFunction << "collectParticle: " << regioni << endl;
// Collect particles on local processors that have passed through faceZone const label particlei = regionToParticleMap_[regioni];
forAll(collectParticle, regioni) eulerianParticle p = particles_[particlei];
{
if (!collectParticle[regioni])
{
continue;
}
Map<label>::const_iterator iter = regionToParticleMap_.find(regioni);
eulerianParticle p = particles_[iter()];
if (p.faceIHit != -1 && nInjectorLocations_) if (p.faceIHit != -1 && nInjectorLocations_)
{ {
@ -319,146 +311,100 @@ void Foam::functionObjects::extractEulerianParticles::collectParticles
); );
cloud_.addParticle(ip); cloud_.addParticle(ip);
collectedVolume_ += p.V;
} }
nCollectedParticles_++; ++nCollectedParticles_;
} }
else else
{ {
// Discard particles over/under diameter threshold // Discard particles over/under diameter threshold
nDiscardedParticles_++; ++nDiscardedParticles_;
discardedVolume_ += p.V; discardedVolume_ += p.V;
} }
}
} }
void Foam::functionObjects::extractEulerianParticles::calculateAddressing void Foam::functionObjects::extractEulerianParticles::calculateAddressing
( (
const label nRegionsOld, const label nNewRegions,
const label nRegionsNew,
const scalar time, const scalar time,
labelList& regionFaceIDs labelList& regionFaceIDs
) )
{ {
DebugInFunction << endl; DebugInFunction << endl;
// New region can only point to one old region // Determine mapping between old and new regions so that we can
// Old region can only point to one new region. If old region intersects // accumulate particle info
// multiple new regions, select max of new region indices. labelList oldToNewRegion(particles_.size(), -1);
labelList newToNewRegion(identity(nNewRegions));
labelList oldToNewRegion(nRegionsOld, -1);
labelList newToOldRegion(nRegionsNew, -1);
forAll(regionFaceIDs, facei) forAll(regionFaceIDs, facei)
{ {
label newRegioni = regionFaceIDs[facei]; label newRegioni = regionFaceIDs[facei];
label oldRegioni = regions0_[facei]; label oldRegioni = regions0_[facei];
if (newRegioni != -1) if (newRegioni != -1 && oldRegioni != -1)
{ {
newToOldRegion[newRegioni] = oldRegioni; // If old region has split into multiple regions we need to
// renumber new regions to maintain connectivity with old regions
if (oldRegioni != -1) newToNewRegion[newRegioni] =
{
// New region linked to old (so can accumulate particle data)
// Old region might already be mapped to a new region
oldToNewRegion[oldRegioni] =
max(newRegioni, oldToNewRegion[oldRegioni]); max(newRegioni, oldToNewRegion[oldRegioni]);
} oldToNewRegion[oldRegioni] = newRegioni;
} }
} }
// Need to re-number the new region indices based on knowledge of which // Create map from new regions to slots in particles list
// old region they intersect. After operations, there should be a // - filter through new-to-new addressing to identify new particles
// one-to-one match between the old and new regions. Pstream::listCombineGather(newToNewRegion, maxEqOp<label>());
Pstream::listCombineScatter(newToNewRegion);
// Ensure all old regions point to the same new regions (if present) label nParticle = -1;
labelHashSet newRegions;
Map<label> newRegionToParticleMap;
forAll(newToNewRegion, newRegioni0)
{
label newRegioni = newToNewRegion[newRegioni0];
if (newRegions.insert(newRegioni))
{
++nParticle;
}
// New particle slot
newRegionToParticleMap.insert(newRegioni0, nParticle);
}
// Accumulate old region data or create a new particle if there is no
// mapping from the old-to-new region
Pstream::listCombineGather(oldToNewRegion, maxEqOp<label>()); Pstream::listCombineGather(oldToNewRegion, maxEqOp<label>());
Pstream::listCombineScatter(oldToNewRegion); Pstream::listCombineScatter(oldToNewRegion);
List<eulerianParticle> newParticles(newRegionToParticleMap.size());
// Any new region that points to an old region should be renumbered to the
// new region specified by the oldToNewRegion index
if (oldToNewRegion.size())
{
// Create corrected new to new addressing
labelList newToNewRegionCorr(newToOldRegion.size(), -1);
forAll(newToOldRegion, newRegioni)
{
label oldRegioni = newToOldRegion[newRegioni];
if (oldRegioni != -1)
{
label newRegionICorr = oldToNewRegion[oldRegioni];
newToNewRegionCorr[newRegioni] = newRegionICorr;
newToOldRegion[newRegioni] = oldRegioni;
}
}
// Renumber the new (current) face region IDs
forAll(regionFaceIDs, facei)
{
label newRegioni = regionFaceIDs[facei];
if (newRegioni != -1)
{
label newRegionICorr = newToNewRegionCorr[newRegioni];
// Note: newRegionICorr can be -1 if the region is new, since
// the address corrections are based on inverting the
// old-to-new addressing
if (newRegionICorr != -1)
{
regionFaceIDs[facei] = newRegionICorr;
}
}
}
boolList collectParticleFlag(nRegionsOld, true);
forAll(oldToNewRegion, oldRegioni) forAll(oldToNewRegion, oldRegioni)
{ {
label newRegioni = oldToNewRegion[oldRegioni]; label newRegioni = oldToNewRegion[oldRegioni];
if (newRegioni != -1) if (newRegioni == -1)
{ {
collectParticleFlag[oldRegioni] = false; // No mapping from old-to-new - collect new particle
} DebugInfo
} << "Collecting particle from oldRegion:" << oldRegioni
<< endl;
// Collect particles whose IDs are no longer active collectParticle(time, oldRegioni);
collectParticles(time, collectParticleFlag);
}
// Re-order collection bins
Map<label> newRegionToParticleMap(nRegionsNew);
List<eulerianParticle> newParticles(nRegionsNew);
label particlei = 0;
forAll(newToOldRegion, newRegioni)
{
label oldRegioni = newToOldRegion[newRegioni];
if (oldRegioni == -1)
{
// No mapping from old to new - this is a new particle
newRegionToParticleMap.insert(newRegioni, particlei);
particlei++;
} }
else else
{ {
// Update addressing for old to new regions // Combine existing particle into new particle
label oldParticlei = regionToParticleMap_[oldRegioni];
if (newRegionToParticleMap.insert(newRegioni, particlei))
{
// First time this particle has been seen
newParticles[particlei] = particles_[oldParticlei];
particlei++;
}
else
{
// Combine with existing contribution
label newParticlei = newRegionToParticleMap[newRegioni]; label newParticlei = newRegionToParticleMap[newRegioni];
label oldParticlei = regionToParticleMap_[oldRegioni];
DebugInfo
<< "Combining newRegioni: " << newRegioni
<< "(p:" << newParticlei << ") and "
<< "oldRegioni: " << oldRegioni
<< "(p:" << oldParticlei << ")"
<< endl;
newParticles[newParticlei] = newParticles[newParticlei] =
sumParticleOp<eulerianParticle>() sumParticleOp<eulerianParticle>()
( (
@ -467,11 +413,14 @@ void Foam::functionObjects::extractEulerianParticles::calculateAddressing
); );
} }
} }
}
// Reset the particles list and addressing for latest available info // Reset the particles list and addressing for latest available info
particles_.transfer(newParticles); particles_.transfer(newParticles);
regionToParticleMap_ = newRegionToParticleMap; regionToParticleMap_ = newRegionToParticleMap;
// Reset the region IDs for the next integration step
// - these become the oldRegioni's
regions0_ = regionFaceIDs;
} }
@ -494,7 +443,6 @@ void Foam::functionObjects::extractEulerianParticles::accumulateParticleInfo
forAll(regionFaceIDs, localFacei) forAll(regionFaceIDs, localFacei)
{ {
const label newRegioni = regionFaceIDs[localFacei]; const label newRegioni = regionFaceIDs[localFacei];
if (newRegioni != -1) if (newRegioni != -1)
{ {
const label particlei = regionToParticleMap_[newRegioni]; const label particlei = regionToParticleMap_[newRegioni];
@ -547,14 +495,14 @@ Foam::functionObjects::extractEulerianParticles::extractEulerianParticles
fineToCoarseAddr_(), fineToCoarseAddr_(),
globalCoarseFaces_(), globalCoarseFaces_(),
regions0_(), regions0_(),
nRegions0_(0),
particles_(), particles_(),
regionToParticleMap_(), regionToParticleMap_(),
minDiameter_(ROOTVSMALL), minDiameter_(ROOTVSMALL),
maxDiameter_(GREAT), maxDiameter_(GREAT),
nCollectedParticles_(0), nCollectedParticles_(getProperty<label>("nCollectedParticles", 0)),
nDiscardedParticles_(0), collectedVolume_(getProperty<scalar>("collectedVolume", 0)),
discardedVolume_(0) nDiscardedParticles_(getProperty<label>("nDiscardedParticles", 0)),
discardedVolume_(getProperty<scalar>("discardedVolume", 0))
{ {
if (mesh_.nSolutionD() != 3) if (mesh_.nSolutionD() != 3)
{ {
@ -567,12 +515,6 @@ Foam::functionObjects::extractEulerianParticles::extractEulerianParticles
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::extractEulerianParticles::~extractEulerianParticles()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::functionObjects::extractEulerianParticles::read bool Foam::functionObjects::extractEulerianParticles::read
@ -644,9 +586,9 @@ bool Foam::functionObjects::extractEulerianParticles::execute()
// Calculate the addressing between the old and new region information // Calculate the addressing between the old and new region information
// Also collects particles that have traversed the faceZone // Also collects particles that have traversed the faceZone
// - Note: may also update regionFaceIDs
calculateAddressing calculateAddressing
( (
nRegions0_,
nRegionsNew, nRegionsNew,
mesh_.time().value(), mesh_.time().value(),
regionFaceIDs regionFaceIDs
@ -656,13 +598,11 @@ bool Foam::functionObjects::extractEulerianParticles::execute()
tmp<surfaceScalarField> tphi = phiU(); tmp<surfaceScalarField> tphi = phiU();
accumulateParticleInfo(alphaf, tphi(), regionFaceIDs, fz); accumulateParticleInfo(alphaf, tphi(), regionFaceIDs, fz);
// Reset the blocked faces for the next integration step Log << " Collected particles : " << nCollectedParticles_ << nl
nRegions0_ = nRegionsNew; << " Collected volume : " << collectedVolume_ << nl
regions0_ = regionFaceIDs; << " Discarded particles : " << nDiscardedParticles_ << nl
<< " Discarded volume : " << discardedVolume_ << nl
Log << " Collected particles: " << nCollectedParticles_ << nl << " Particles in progress : " << particles_.size() << nl
<< " Discarded particles: " << nDiscardedParticles_ << nl
<< " Discarded volume: " << discardedVolume_ << nl
<< endl; << endl;
return true; return true;
@ -675,6 +615,11 @@ bool Foam::functionObjects::extractEulerianParticles::write()
cloud_.write(); cloud_.write();
setProperty("nCollectedParticles", nCollectedParticles_);
setProperty("collectedVolume", collectedVolume_);
setProperty("nDiscardedParticles", nDiscardedParticles_);
setProperty("discardedVolume", discardedVolume_);
return true; return true;
} }

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -23,6 +23,7 @@ License
Class Class
Foam::functionObjects::extractEulerianParticles Foam::functionObjects::extractEulerianParticles
Group Group
grpFieldFunctionObjects grpFieldFunctionObjects
@ -73,10 +74,8 @@ SourceFiles
#include "runTimeSelectionTables.H" #include "runTimeSelectionTables.H"
#include "polyMesh.H" #include "polyMesh.H"
#include "surfaceFieldsFwd.H" #include "surfaceFieldsFwd.H"
#include "vectorList.H"
#include "globalIndex.H" #include "globalIndex.H"
#include "eulerianParticle.H" #include "eulerianParticle.H"
#include "IOdictionary.H"
#include "injectedParticleCloud.H" #include "injectedParticleCloud.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -153,9 +152,6 @@ protected:
//- Region indices in faceZone faces from last iteration //- Region indices in faceZone faces from last iteration
labelList regions0_; labelList regions0_;
//- Number of regions from last iteration
label nRegions0_;
//- Particle properties (partial, being accumulated) //- Particle properties (partial, being accumulated)
List<eulerianParticle> particles_; List<eulerianParticle> particles_;
@ -176,6 +172,9 @@ protected:
//- Total number of collected particles //- Total number of collected particles
label nCollectedParticles_; label nCollectedParticles_;
//- Total collected volume [m3]
scalar collectedVolume_;
//- Total number of discarded particles //- Total number of discarded particles
label nDiscardedParticles_; label nDiscardedParticles_;
@ -206,19 +205,19 @@ protected:
); );
//- Calculate the addressing between regions between iterations //- Calculate the addressing between regions between iterations
//- Returns the number of active regions (particles)
virtual void calculateAddressing virtual void calculateAddressing
( (
const label nRegionsOld,
const label nRegionsNew, const label nRegionsNew,
const scalar time, const scalar time,
labelList& regionFaceIDs labelList& regionFaceIDs
); );
//- Collect particles that have passed through the faceZone //- Collect particles that have passed through the faceZone
virtual void collectParticles virtual void collectParticle
( (
const scalar time, const scalar time,
const boolList& collectParticle const label regioni
); );
//- Process latest region information //- Process latest region information
@ -265,7 +264,7 @@ public:
//- Destructor //- Destructor
virtual ~extractEulerianParticles(); virtual ~extractEulerianParticles() = default;
// Member Functions // Member Functions