mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Added new particleZoneInfo cloud function object.
Reports cloud information for particles passing through a specified cell
zone.
Example usage:
cloudFunctions
{
particleZoneInfo1
{
type particleZoneInfo;
cellZone leftFluid;
// Optional entries
//writer vtk;
}
}
Results are written to file:
- \<case\>/postProcessing/lagrangian/\<cloudName\>/\<functionName\>/\<time\>
\# cellZone : leftFluid
\# time : 1.0000000000e+00
\#
\# origID origProc (x y z) time0 age d0 d mass0 mass
Where
- origID : particle ID
- origProc : processor ID
- (x y z) : Cartesian co-ordinates
- time0 : time particle enters the cellZone
- age : time spent in the cellZone
- d0 : diameter on entry to the cellZone
- d : current diameter
- mass0 : mass on entry to the cellZone
- mass : current mass
If the optional \c writer entry is supplied, cloud data is written in the
specified format.
During the run, output statistics are reported after the cloud solution,
e.g.:
particleZoneInfo:
Cell zone = leftFluid
Contributions = 257
Here, 'Contributions' refers to the number of incremental particle-move
contributions recorded during this time step. At write times, the output
is extended, e.g.:
particleZoneInfo:
Cell zone = leftFluid
Contributions = 822
Number of particles = 199
Written data to "postProcessing/lagrangian/reactingCloud1/
TUT: filter: add an example for the particleZoneInfo function object
This commit is contained in:
committed by
Sergio Ferraris
parent
8d90b16518
commit
5cb0dc9d8a
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2018 OpenFOAM Foundation
|
Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||||
Copyright (C) 2020-2021 OpenCFD Ltd.
|
Copyright (C) 2020-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -37,6 +37,7 @@ License
|
|||||||
#include "ParticleErosion.H"
|
#include "ParticleErosion.H"
|
||||||
#include "ParticleTracks.H"
|
#include "ParticleTracks.H"
|
||||||
#include "ParticleTrap.H"
|
#include "ParticleTrap.H"
|
||||||
|
#include "ParticleZoneInfo.H"
|
||||||
#include "PatchCollisionDensity.H"
|
#include "PatchCollisionDensity.H"
|
||||||
#include "PatchInteractionFields.H"
|
#include "PatchInteractionFields.H"
|
||||||
#include "PatchPostProcessing.H"
|
#include "PatchPostProcessing.H"
|
||||||
@ -57,6 +58,7 @@ License
|
|||||||
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
||||||
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
||||||
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
||||||
|
makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
|
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2018 OpenFOAM Foundation
|
Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||||
Copyright (C) 2020-2021 OpenCFD Ltd.
|
Copyright (C) 2020-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -37,6 +37,7 @@ License
|
|||||||
#include "ParticleErosion.H"
|
#include "ParticleErosion.H"
|
||||||
#include "ParticleTracks.H"
|
#include "ParticleTracks.H"
|
||||||
#include "ParticleTrap.H"
|
#include "ParticleTrap.H"
|
||||||
|
#include "ParticleZoneInfo.H"
|
||||||
#include "PatchCollisionDensity.H"
|
#include "PatchCollisionDensity.H"
|
||||||
#include "PatchInteractionFields.H"
|
#include "PatchInteractionFields.H"
|
||||||
#include "PatchPostProcessing.H"
|
#include "PatchPostProcessing.H"
|
||||||
@ -60,6 +61,7 @@ License
|
|||||||
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
||||||
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
||||||
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
||||||
|
makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
|
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -36,6 +36,7 @@ License
|
|||||||
#include "ParticleErosion.H"
|
#include "ParticleErosion.H"
|
||||||
#include "ParticleTracks.H"
|
#include "ParticleTracks.H"
|
||||||
#include "ParticleTrap.H"
|
#include "ParticleTrap.H"
|
||||||
|
#include "ParticleZoneInfo.H"
|
||||||
#include "PatchCollisionDensity.H"
|
#include "PatchCollisionDensity.H"
|
||||||
#include "PatchInteractionFields.H"
|
#include "PatchInteractionFields.H"
|
||||||
#include "PatchPostProcessing.H"
|
#include "PatchPostProcessing.H"
|
||||||
@ -58,6 +59,7 @@ License
|
|||||||
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
||||||
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
||||||
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
||||||
|
makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
|
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
|
||||||
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
||||||
|
|||||||
@ -0,0 +1,458 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "ParticleZoneInfo.H"
|
||||||
|
#include "DynamicField.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
struct particleInfoCombineOp
|
||||||
|
{
|
||||||
|
void operator()(particleInfo& p1, const particleInfo& p2) const
|
||||||
|
{
|
||||||
|
// p2 not set
|
||||||
|
if (p2.origID == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// p1 not set - initialise with p2
|
||||||
|
if (p1.origID == -1)
|
||||||
|
{
|
||||||
|
p1 = p2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set initial values
|
||||||
|
if (p2.time0 < p1.time0)
|
||||||
|
{
|
||||||
|
p1.time0 = p2.time0;
|
||||||
|
p1.d0 = p2.d0;
|
||||||
|
p1.mass0 = p2.mass0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulate age
|
||||||
|
p1.age += p2.age;
|
||||||
|
|
||||||
|
// Set latest available values
|
||||||
|
if (p2.isOlderThan(p1))
|
||||||
|
{
|
||||||
|
p1.position = p2.position;
|
||||||
|
p1.d = p2.d;
|
||||||
|
p1.mass = p2.mass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Foam::Field<Type> getData
|
||||||
|
(
|
||||||
|
const Foam::UList<Foam::particleInfo>& data,
|
||||||
|
Type Foam::particleInfo::* field
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Field<Type> result(data.size());
|
||||||
|
|
||||||
|
forAll(data, i)
|
||||||
|
{
|
||||||
|
result[i] = data[i].*field;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Foam::Field<Type> getParData
|
||||||
|
(
|
||||||
|
const Foam::List<Foam::List<Foam::particleInfo>>& parData,
|
||||||
|
Type Foam::particleInfo::* field
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DynamicField<Type> result;
|
||||||
|
|
||||||
|
for (const auto& particles : parData)
|
||||||
|
{
|
||||||
|
for (const auto& p : particles)
|
||||||
|
{
|
||||||
|
if (p.origID != -1)
|
||||||
|
{
|
||||||
|
result.append(p.*field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::writeWriter
|
||||||
|
(
|
||||||
|
const DynamicList<particleInfo>& data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
coordSet coords
|
||||||
|
(
|
||||||
|
"zoneParticles",
|
||||||
|
"xyz",
|
||||||
|
getData(data_, &particleInfo::position),
|
||||||
|
scalarList(data.size(), Zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
writerPtr_->open(coords, this->baseTimeDir() / "zoneParticles");
|
||||||
|
writerPtr_->beginTime(this->owner().time());
|
||||||
|
|
||||||
|
#undef writeLocal
|
||||||
|
#define writeLocal(field) \
|
||||||
|
writerPtr_->write(#field, getData(data, &particleInfo::field));
|
||||||
|
|
||||||
|
writeLocal(origID);
|
||||||
|
writeLocal(origProc);
|
||||||
|
writeLocal(time0);
|
||||||
|
writeLocal(age);
|
||||||
|
writeLocal(d0);
|
||||||
|
writeLocal(d);
|
||||||
|
writeLocal(mass0);
|
||||||
|
writeLocal(mass);
|
||||||
|
#undef writeLocal
|
||||||
|
|
||||||
|
writerPtr_->endTime();
|
||||||
|
writerPtr_->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::writeWriter
|
||||||
|
(
|
||||||
|
const List<List<particleInfo>>& procData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
vectorField points(getParData(procData, &particleInfo::position));
|
||||||
|
|
||||||
|
coordSet coords
|
||||||
|
(
|
||||||
|
"zoneParticles",
|
||||||
|
"xyz",
|
||||||
|
std::move(points),
|
||||||
|
scalarList(points.size(), Zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
writerPtr_->open(coords, this->baseTimeDir() / "zoneParticles");
|
||||||
|
writerPtr_->beginTime(this->owner().time());
|
||||||
|
|
||||||
|
#undef writeLocal
|
||||||
|
#define writeLocal(field) \
|
||||||
|
writerPtr_->write(#field, getParData(procData, &particleInfo::field));
|
||||||
|
|
||||||
|
writeLocal(origID);
|
||||||
|
writeLocal(origProc);
|
||||||
|
writeLocal(time0);
|
||||||
|
writeLocal(age);
|
||||||
|
writeLocal(d0);
|
||||||
|
writeLocal(d);
|
||||||
|
writeLocal(mass0);
|
||||||
|
writeLocal(mass);
|
||||||
|
#undef writeLocal
|
||||||
|
|
||||||
|
writerPtr_->endTime();
|
||||||
|
writerPtr_->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::writeFileHeader(Ostream& os) const
|
||||||
|
{
|
||||||
|
this->writeHeaderValue(os, "cellZone", cellZoneName_);
|
||||||
|
this->writeHeaderValue(os, "time", this->owner().time().timeOutputValue());
|
||||||
|
this->writeHeader(os, "");
|
||||||
|
this->writeCommented(os, "origID");
|
||||||
|
os << tab << "origProc"
|
||||||
|
<< tab << "(x y z)"
|
||||||
|
<< tab << "time0"
|
||||||
|
<< tab << "age"
|
||||||
|
<< tab << "d0"
|
||||||
|
<< tab << "d"
|
||||||
|
<< tab << "mass0"
|
||||||
|
<< tab << "mass"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
bool Foam::ParticleZoneInfo<CloudType>::inZone(const label celli) const
|
||||||
|
{
|
||||||
|
return this->owner().mesh().cellZones()[cellZoneId_].whichCell(celli) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
Foam::label Foam::ParticleZoneInfo<CloudType>::getParticleID
|
||||||
|
(
|
||||||
|
const particleInfo& p
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
forAll(data_, i)
|
||||||
|
{
|
||||||
|
const auto& d = data_[i];
|
||||||
|
if ((d.origProc == p.origProc) && (d.origID == p.origID))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
Foam::ParticleZoneInfo<CloudType>::ParticleZoneInfo
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
CloudType& owner,
|
||||||
|
const word& modelName
|
||||||
|
)
|
||||||
|
:
|
||||||
|
CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
|
||||||
|
functionObjects::writeFile
|
||||||
|
(
|
||||||
|
owner,
|
||||||
|
this->localPath(),
|
||||||
|
typeName,
|
||||||
|
this->coeffDict()
|
||||||
|
),
|
||||||
|
cellZoneName_(this->coeffDict().getWord("cellZone")),
|
||||||
|
cellZoneId_(-1),
|
||||||
|
data_(),
|
||||||
|
movedParticles_(),
|
||||||
|
maxIDs_(Pstream::nProcs(), Zero),
|
||||||
|
writerPtr_
|
||||||
|
(
|
||||||
|
Pstream::master()
|
||||||
|
? coordSetWriter::New
|
||||||
|
(
|
||||||
|
this->coeffDict().getWord("writer"),
|
||||||
|
this->coeffDict().subOrEmptyDict("formatOptions")
|
||||||
|
)
|
||||||
|
: nullptr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto& cellZones = owner.mesh().cellZones();
|
||||||
|
|
||||||
|
cellZoneId_ = cellZones.findZoneID(cellZoneName_);
|
||||||
|
if (cellZoneId_ == -1)
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(this->coeffDict())
|
||||||
|
<< "Unable to find cellZone " << cellZoneName_
|
||||||
|
<< ". Available cellZones are:" << cellZones.names()
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< " Processing cellZone" << cellZoneName_ << " with id "
|
||||||
|
<< cellZoneId_ << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
Foam::ParticleZoneInfo<CloudType>::ParticleZoneInfo
|
||||||
|
(
|
||||||
|
const ParticleZoneInfo<CloudType>& pzi
|
||||||
|
)
|
||||||
|
:
|
||||||
|
CloudFunctionObject<CloudType>(pzi),
|
||||||
|
writeFile(pzi),
|
||||||
|
cellZoneName_(pzi.cellZoneName_),
|
||||||
|
cellZoneId_(pzi.cellZoneId_),
|
||||||
|
data_(pzi.data_),
|
||||||
|
movedParticles_(pzi.movedParticles_),
|
||||||
|
maxIDs_(Pstream::nProcs()),
|
||||||
|
writerPtr_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::preEvolve
|
||||||
|
(
|
||||||
|
const typename parcelType::trackingData& td
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::postEvolve
|
||||||
|
(
|
||||||
|
const typename parcelType::trackingData& td
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Info<< this->type() << ":" << nl
|
||||||
|
<< " Cell zone = " << cellZoneName_ << nl
|
||||||
|
<< " Contributions = "
|
||||||
|
<< returnReduce(movedParticles_.size(), sumOp<label>())
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
if (!this->writeTime())
|
||||||
|
{
|
||||||
|
Info<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& p : movedParticles_)
|
||||||
|
{
|
||||||
|
const label id = getParticleID(p);
|
||||||
|
|
||||||
|
if (id == -1)
|
||||||
|
{
|
||||||
|
// New particle
|
||||||
|
data_.append(p);
|
||||||
|
maxIDs_[p.origProc] = max(maxIDs_[p.origProc], p.origID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add to existing particle
|
||||||
|
data_[id] += p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
movedParticles_.clear();
|
||||||
|
|
||||||
|
// Calls write
|
||||||
|
CloudFunctionObject<CloudType>::postEvolve(td);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::postMove
|
||||||
|
(
|
||||||
|
parcelType& p,
|
||||||
|
const scalar dt,
|
||||||
|
const point&,
|
||||||
|
bool&
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (inZone(p.cell()))
|
||||||
|
{
|
||||||
|
particleInfo newData;
|
||||||
|
newData.origID = p.origId();
|
||||||
|
newData.origProc = p.origProc();
|
||||||
|
newData.position = p.position();
|
||||||
|
newData.time0 = this->owner().time().value() + dt;
|
||||||
|
newData.age = dt;
|
||||||
|
newData.d0 = p.d();
|
||||||
|
newData.d = p.d();
|
||||||
|
newData.mass0 = p.mass();
|
||||||
|
newData.mass = newData.mass0;
|
||||||
|
|
||||||
|
movedParticles_.append(newData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
void Foam::ParticleZoneInfo<CloudType>::write()
|
||||||
|
{
|
||||||
|
autoPtr<OFstream> osPtr =
|
||||||
|
this->createFile("particles", this->owner().time().timeOutputValue());
|
||||||
|
|
||||||
|
if (Pstream::parRun())
|
||||||
|
{
|
||||||
|
// Find number of particles per proc
|
||||||
|
labelList allMaxIDs(maxIDs_);
|
||||||
|
Pstream::listCombineGather(allMaxIDs, maxEqOp<label>());
|
||||||
|
Pstream::scatterList(allMaxIDs);
|
||||||
|
|
||||||
|
List<List<particleInfo>> procParticles(Pstream::nProcs());
|
||||||
|
forAll(procParticles, proci)
|
||||||
|
{
|
||||||
|
procParticles[proci].resize(allMaxIDs[proci] + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert into bins for accumulation
|
||||||
|
for (const auto& d : data_)
|
||||||
|
{
|
||||||
|
procParticles[d.origProc][d.origID] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& particles : procParticles)
|
||||||
|
{
|
||||||
|
Pstream::listCombineGather(particles, particleInfoCombineOp());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
writeWriter(procParticles);
|
||||||
|
|
||||||
|
auto& os = osPtr();
|
||||||
|
writeFileHeader(os);
|
||||||
|
|
||||||
|
label nData = 0;
|
||||||
|
for (const auto& particles : procParticles)
|
||||||
|
{
|
||||||
|
for (const auto& p : particles)
|
||||||
|
{
|
||||||
|
if (p.origID != -1)
|
||||||
|
{
|
||||||
|
os << p << endl;
|
||||||
|
++nData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< " Number of particles = " << nData << nl
|
||||||
|
<< " Written data to " << os.name() << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeWriter(data_);
|
||||||
|
|
||||||
|
auto& os = osPtr();
|
||||||
|
writeFileHeader(os);
|
||||||
|
|
||||||
|
for (const auto& p : data_)
|
||||||
|
{
|
||||||
|
os << p << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< " Number of particles = " << data_.size() << nl
|
||||||
|
<< " Written data to " << os.name() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,334 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::ParticleZoneInfo
|
||||||
|
|
||||||
|
Group
|
||||||
|
grpLagrangianIntermediateFunctionObjects
|
||||||
|
|
||||||
|
Description
|
||||||
|
Reports cloud information for particles passing through a specified cell
|
||||||
|
zone.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
Example usage:
|
||||||
|
\verbatim
|
||||||
|
cloudFunctions
|
||||||
|
{
|
||||||
|
particleZoneInfo1
|
||||||
|
{
|
||||||
|
// Mandatory entries
|
||||||
|
type particleZoneInfo;
|
||||||
|
cellZone leftFluid;
|
||||||
|
|
||||||
|
// Optional entries
|
||||||
|
writer vtk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Results are written to file:
|
||||||
|
- \<case\>/postProcessing/lagrangian/\<cloudName\>/\<functionName\>/\<time\>
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
# cellZone : leftFluid
|
||||||
|
# time : 1.0000000000e+00
|
||||||
|
#
|
||||||
|
# origID origProc (x y z) time0 age d0 d mass0 mass
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Where
|
||||||
|
- origID : particle ID
|
||||||
|
- origProc : processor ID
|
||||||
|
- (x y z) : Cartesian co-ordinates
|
||||||
|
- time0 : time particle enters the cellZone
|
||||||
|
- age : time spent in the cellZone
|
||||||
|
- d0 : diameter on entry to the cellZone
|
||||||
|
- d : current diameter
|
||||||
|
- mass0 : mass on entry to the cellZone
|
||||||
|
- mass : current mass
|
||||||
|
|
||||||
|
If the optional \c writer entry is supplied, cloud data is written in the
|
||||||
|
specified format.
|
||||||
|
|
||||||
|
During the run, output statistics are reported after the cloud solution,
|
||||||
|
e.g.:
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
particleZoneInfo:
|
||||||
|
Cell zone = leftFluid
|
||||||
|
Contributions = 257
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Here, 'Contributions' refers to the number of incremental particle-move
|
||||||
|
contributions recorded during this time step. At write times, the output
|
||||||
|
is extended, e.g.:
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
particleZoneInfo:
|
||||||
|
Cell zone = leftFluid
|
||||||
|
Contributions = 822
|
||||||
|
Number of particles = 199
|
||||||
|
Written data to "postProcessing/lagrangian/reactingCloud1/
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
ParticleZoneInfo.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef ParticleZoneInfo_H
|
||||||
|
#define ParticleZoneInfo_H
|
||||||
|
|
||||||
|
#include "CloudFunctionObject.H"
|
||||||
|
#include "writeFile.H"
|
||||||
|
#include "coordSetWriter.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
struct particleInfo Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct particleInfo
|
||||||
|
{
|
||||||
|
label origID = -1;
|
||||||
|
label origProc = -1;
|
||||||
|
vector position = Zero;
|
||||||
|
scalar time0 = 0;
|
||||||
|
scalar age = 0;
|
||||||
|
scalar d0 = 0;
|
||||||
|
scalar d = 0;
|
||||||
|
scalar mass0 = 0;
|
||||||
|
scalar mass = 0;
|
||||||
|
|
||||||
|
void operator+=(const particleInfo& p)
|
||||||
|
{
|
||||||
|
// Increment age
|
||||||
|
age += p.age;
|
||||||
|
|
||||||
|
// Set current values
|
||||||
|
position = p.position;
|
||||||
|
d = p.d;
|
||||||
|
mass = p.mass;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar isOlderThan(const particleInfo& p) const
|
||||||
|
{
|
||||||
|
// Cannot just use time0 - particle may leave/re-enter and
|
||||||
|
// so age is decoupled
|
||||||
|
return (p.time0 + p.age) < (time0 + age);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const particleInfo& a, const particleInfo& b)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
a.origID == b.origID
|
||||||
|
&& a.origProc == b.origProc
|
||||||
|
&& a.position == b.position
|
||||||
|
&& a.time0 == b.time0
|
||||||
|
&& a.age == b.age
|
||||||
|
&& a.d0 == b.d0
|
||||||
|
&& a.d == b.d
|
||||||
|
&& a.mass0 == b.mass0
|
||||||
|
&& a.mass == b.mass;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const particleInfo& a, const particleInfo& b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// IOstream Operators
|
||||||
|
|
||||||
|
friend Istream& operator>>(Istream& is, particleInfo& pi)
|
||||||
|
{
|
||||||
|
is >> pi.origID
|
||||||
|
>> pi.origProc
|
||||||
|
>> pi.position
|
||||||
|
>> pi.time0
|
||||||
|
>> pi.age
|
||||||
|
>> pi.d0
|
||||||
|
>> pi.d
|
||||||
|
>> pi.mass0
|
||||||
|
>> pi.mass;
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Ostream& operator<<(Ostream& os, const particleInfo& pi)
|
||||||
|
{
|
||||||
|
os << pi.origID
|
||||||
|
<< " " << pi.origProc
|
||||||
|
<< " " << pi.position
|
||||||
|
<< " " << pi.time0
|
||||||
|
<< " " << pi.age
|
||||||
|
<< " " << pi.d0
|
||||||
|
<< " " << pi.d
|
||||||
|
<< " " << pi.mass0
|
||||||
|
<< " " << pi.mass;
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class ParticleZoneInfo Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
class ParticleZoneInfo
|
||||||
|
:
|
||||||
|
public CloudFunctionObject<CloudType>,
|
||||||
|
public functionObjects::writeFile
|
||||||
|
|
||||||
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
// Typedefs
|
||||||
|
|
||||||
|
//- Convenience typedef for parcel type
|
||||||
|
typedef typename CloudType::parcelType parcelType;
|
||||||
|
|
||||||
|
|
||||||
|
//- Cell zone name
|
||||||
|
word cellZoneName_;
|
||||||
|
|
||||||
|
//- Cell zone index
|
||||||
|
label cellZoneId_;
|
||||||
|
|
||||||
|
//- Stored data
|
||||||
|
DynamicList<particleInfo> data_;
|
||||||
|
|
||||||
|
//- Work storage
|
||||||
|
DynamicList<particleInfo> movedParticles_;
|
||||||
|
|
||||||
|
//- Maximum particle ID per processor
|
||||||
|
labelList maxIDs_;
|
||||||
|
|
||||||
|
//- Set writer
|
||||||
|
autoPtr<coordSetWriter> writerPtr_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Write output file header
|
||||||
|
void writeFileHeader(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Return true if celli is in the cellZone
|
||||||
|
bool inZone(const label celli) const;
|
||||||
|
|
||||||
|
//- Return the index of the particle in the storage (data_)
|
||||||
|
//- Returns -1 if not found
|
||||||
|
label getParticleID(const particleInfo& p) const;
|
||||||
|
|
||||||
|
//- Write fields using writerPtr_ for serial runs
|
||||||
|
void writeWriter(const DynamicList<particleInfo>& data);
|
||||||
|
|
||||||
|
//- Write fields using writerPtr_ for parallel runs
|
||||||
|
void writeWriter(const List<List<particleInfo>>& procData);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("particleZoneInfo");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from dictionary
|
||||||
|
ParticleZoneInfo
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
CloudType& owner,
|
||||||
|
const word& modelName
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct copy
|
||||||
|
ParticleZoneInfo(const ParticleZoneInfo<CloudType>& pe);
|
||||||
|
|
||||||
|
//- Construct and return a clone
|
||||||
|
virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
|
||||||
|
{
|
||||||
|
return autoPtr<CloudFunctionObject<CloudType>>
|
||||||
|
(
|
||||||
|
new ParticleZoneInfo<CloudType>(*this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~ParticleZoneInfo() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Pre-evolve hook
|
||||||
|
virtual void preEvolve
|
||||||
|
(
|
||||||
|
const typename parcelType::trackingData& td
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Post-evolve hook
|
||||||
|
virtual void postEvolve
|
||||||
|
(
|
||||||
|
const typename parcelType::trackingData& td
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Post-move hook
|
||||||
|
virtual void postMove
|
||||||
|
(
|
||||||
|
parcelType& p,
|
||||||
|
const scalar dt,
|
||||||
|
const point& position0,
|
||||||
|
bool& keepParticle
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Write
|
||||||
|
virtual void write();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "ParticleZoneInfo.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -160,6 +160,13 @@ subModels
|
|||||||
|
|
||||||
cloudFunctions
|
cloudFunctions
|
||||||
{
|
{
|
||||||
|
particleZoneInfo1
|
||||||
|
{
|
||||||
|
type particleZoneInfo;
|
||||||
|
cellZone leftFluid;
|
||||||
|
writer vtk;
|
||||||
|
}
|
||||||
|
|
||||||
patchParticleHistogram1
|
patchParticleHistogram1
|
||||||
{
|
{
|
||||||
type patchParticleHistogram;
|
type patchParticleHistogram;
|
||||||
|
|||||||
Reference in New Issue
Block a user