ENH: ParticleHistogram: refactor PatchParticleHistogram function object

- enable 'faceZone' support.
- introduce 'cloudFunctionObjectTools' to simplify collection of particle info
  on patches or face zones.
- enable 'writeFile' support to better control file output.
- rename 'PatchParticleHistogram' as 'ParticleHistogram' for better clarity.
This commit is contained in:
Kutalmis Bercin 2023-01-17 16:43:02 +00:00 committed by Andrew Heather
parent f0fca75726
commit c177637db2
11 changed files with 625 additions and 344 deletions

View File

@ -120,7 +120,7 @@ phaseProperties/phasePropertiesList/phasePropertiesList.C
/* additional helper classes */
clouds/Templates/KinematicCloud/cloudSolution/cloudSolution.C
submodels/CloudFunctionObjects/CloudFunctionObject/cloudFunctionObjectTools.C
/* averaging methods */
submodels/MPPIC/AveragingMethods/makeAveragingMethods.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2018 OpenFOAM Foundation
Copyright (C) 2020-2022 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,10 +38,10 @@ License
#include "ParticleTracks.H"
#include "ParticleTrap.H"
#include "ParticleZoneInfo.H"
#include "ParticleHistogram.H"
#include "PatchCollisionDensity.H"
#include "PatchInteractionFields.H"
#include "PatchPostProcessing.H"
#include "PatchParticleHistogram.H"
#include "RemoveParcels.H"
#include "VoidFraction.H"
#include "KinematicReynoldsNumber.H"
@ -60,10 +60,10 @@ License
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \
makeCloudFunctionObjectType(ParticleHistogram, CloudType); \
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
makeCloudFunctionObjectType(PatchParticleHistogram, CloudType); \
makeCloudFunctionObjectType(RemoveParcels, CloudType); \
makeCloudFunctionObjectType(VoidFraction, CloudType); \
makeCloudFunctionObjectType(KinematicReynoldsNumber, CloudType); \

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2018 OpenFOAM Foundation
Copyright (C) 2020-2022 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,10 +38,10 @@ License
#include "ParticleTracks.H"
#include "ParticleTrap.H"
#include "ParticleZoneInfo.H"
#include "ParticleHistogram.H"
#include "PatchCollisionDensity.H"
#include "PatchInteractionFields.H"
#include "PatchPostProcessing.H"
#include "PatchParticleHistogram.H"
#include "RemoveParcels.H"
#include "VoidFraction.H"
#include "NusseltNumber.H"
@ -63,10 +63,10 @@ License
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \
makeCloudFunctionObjectType(ParticleHistogram, CloudType); \
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
makeCloudFunctionObjectType(PatchParticleHistogram, CloudType); \
makeCloudFunctionObjectType(RemoveParcels, CloudType); \
makeCloudFunctionObjectType(VoidFraction, CloudType); \
makeCloudFunctionObjectType(NusseltNumber, CloudType); \

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2022 OpenCFD Ltd.
Copyright (C) 2021-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,10 +37,10 @@ License
#include "ParticleTracks.H"
#include "ParticleTrap.H"
#include "ParticleZoneInfo.H"
#include "ParticleHistogram.H"
#include "PatchCollisionDensity.H"
#include "PatchInteractionFields.H"
#include "PatchPostProcessing.H"
#include "PatchParticleHistogram.H"
#include "RemoveParcels.H"
#include "VoidFraction.H"
#include "NusseltNumber.H"
@ -61,10 +61,10 @@ License
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
makeCloudFunctionObjectType(ParticleZoneInfo, CloudType); \
makeCloudFunctionObjectType(ParticleHistogram, CloudType); \
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
makeCloudFunctionObjectType(PatchInteractionFields, CloudType); \
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
makeCloudFunctionObjectType(PatchParticleHistogram, CloudType); \
makeCloudFunctionObjectType(RemoveParcels, CloudType); \
makeCloudFunctionObjectType(VoidFraction, CloudType); \
makeCloudFunctionObjectType(NusseltNumber, CloudType); \

View File

@ -0,0 +1,113 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 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 "cloudFunctionObjectTools.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::cloudFunctionObjectTools::collector::collector
(
const dictionary& dict,
const polyMesh& mesh
)
:
isPatch_(false),
IDs_(),
names_(),
BBs_()
{
wordRes matcher;
if (dict.readIfPresent("patches", matcher) && !matcher.empty())
{
isPatch_ = true;
IDs_ = mesh.boundaryMesh().indices(matcher);
names_.resize(IDs_.size());
label count = 0;
for (const label patchi : IDs_)
{
names_[count] = mesh.boundaryMesh()[patchi].name();
++count;
}
}
else if (dict.readIfPresent("faceZones", matcher))
{
const faceZoneMesh& fzm = mesh.faceZones();
IDs_ = fzm.indices(matcher);
BBs_.resize(IDs_.size());
names_.resize(IDs_.size());
label count = 0;
for (const label zonei : IDs_)
{
const faceZone& fz = fzm[zonei];
names_[count] = fz.name();
auto& bb = BBs_[count];
++count;
bb.reset();
const auto& faces = mesh.faces();
const auto& points = mesh.points();
for (const label facei : fz)
{
bb.add(points, faces[facei]);
}
bb.reduce();
bb.inflate(0.05);
}
}
if (matcher.empty() || IDs_.size() < 1)
{
FatalIOErrorInFunction(dict)
<< "No matching patches or face zones found: "
<< flatOutput(matcher) << nl
<< exit(FatalIOError);
}
}
Foam::cloudFunctionObjectTools::collector::collector
(
const collector& phc
)
:
isPatch_(phc.isPatch_),
IDs_(phc.IDs_),
names_(phc.names_),
BBs_(phc.BBs_)
{}
// ************************************************************************* //

View File

@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 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::cloudFunctionObjectTools::collector
Description
Implementation of template-invariant tools for
various function objects such as Foam::ParticleHistogram.
SourceFiles
cloudFunctionObjectTools.C
\*---------------------------------------------------------------------------*/
#ifndef cloudFunctionObjectTools_collector_H
#define cloudFunctionObjectTools_collector_H
#include "polyMesh.H"
#include "boundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Namespace cloudFunctionObjectTools Declaration
\*---------------------------------------------------------------------------*/
namespace cloudFunctionObjectTools
{
/*---------------------------------------------------------------------------*\
Class collector Declaration
\*---------------------------------------------------------------------------*/
class collector
{
// Private Data
//- Flag to decide if the collector is patch based
bool isPatch_;
//- List of indices of collectors (zones or patches)
labelList IDs_;
//- List of names of collectors
wordList names_;
//- List of bounding-boxes of collectors
List<boundBox> BBs_;
public:
// Constructors
//- Construct from dictionary
collector
(
const dictionary& dict,
const polyMesh& mesh
);
//- Copy construct
collector(const collector& phc);
//- No copy assignment
void operator=(const collector&) = delete;
//- Destructor
virtual ~collector() = default;
// Member Functions
// Access
//- Return the flag if the collector is patch based
bool isPatch() const noexcept { return isPatch_; }
//- Return number of collectors (zones or patches)
label size() const noexcept { return IDs_.size(); }
//- Return const reference to the indices of collectors
const labelList& IDs() const noexcept { return IDs_; }
//- Return const reference to the names of collectors
const wordList& names() const noexcept { return names_; }
//- Return const reference to the bounding-boxes of collectors
const List<boundBox>& BBs() const noexcept { return BBs_; }
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace cloudFunctionObjectTools
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,278 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2023 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 "ParticleHistogram.H"
#include "Pstream.H"
#include "stringListOps.H"
#include "ListOps.H"
#include "ListListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class CloudType>
void Foam::ParticleHistogram<CloudType>::writeFileHeader(Ostream& os) const
{
this->writeHeaderValue(os, "nBin", nBins_);
this->writeHeaderValue(os, "min", range_.min());
this->writeHeaderValue(os, "max", range_.max());
this->writeHeader(os, "");
this->writeCommented(os, "dEdge1");
os << tab << "dEdge2"
<< tab << "nParticles"
<< tab << "nParticlesCumulative"
<< endl;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::ParticleHistogram<CloudType>::ParticleHistogram
(
const dictionary& dict,
CloudType& owner,
const word& modelName
)
:
CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
functionObjects::writeFile
(
owner,
this->localPath(),
typeName
),
collector_(this->coeffDict(), owner.mesh()),
nBins_
(
this->coeffDict().template getCheck<label>("nBins", labelMinMax::ge(1))
),
maxStoredParcels_(this->coeffDict().getScalar("maxStoredParcels")),
range_
(
this->coeffDict().getScalar("min"),
this->coeffDict().getScalar("max")
),
binEdges_(nBins_ + 1),
nParticlesCumulative_(),
dParticles_(),
nParticles_()
{
writeFile::read(this->coeffDict());
if (!range_.good())
{
FatalIOErrorInFunction(this->coeffDict())
<< "Invalid histogram range: " << range_
<< exit(FatalIOError);
}
if (maxStoredParcels_ <= 0)
{
FatalIOErrorInFunction(this->coeffDict())
<< "maxStoredParcels = " << maxStoredParcels_
<< ", cannot be equal to or less than zero"
<< exit(FatalIOError);
}
// Compute histogram-bin properties
binEdges_[0] = range_.min();
const scalar delta = range_.span()/scalar(nBins_);
for (label i = 0; i < nBins_; ++i)
{
const scalar next = range_.min() + (i+1)*delta;
binEdges_[i+1] = next;
}
const label sz = collector_.size();
nParticlesCumulative_ = List<scalarList>(sz, scalarList(nBins_, Zero));
dParticles_.resize(sz);
nParticles_.resize(sz);
}
template<class CloudType>
Foam::ParticleHistogram<CloudType>::ParticleHistogram
(
const ParticleHistogram<CloudType>& ph
)
:
CloudFunctionObject<CloudType>(ph),
writeFile(ph),
collector_(ph.collector_),
nBins_(ph.nBins_),
maxStoredParcels_(ph.maxStoredParcels_),
range_(ph.range_),
binEdges_(ph.binEdges_),
nParticlesCumulative_(ph.nParticlesCumulative_),
dParticles_(ph.dParticles_),
nParticles_(ph.nParticles_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::ParticleHistogram<CloudType>::postPatch
(
const parcelType& p,
const polyPatch& pp,
bool&
)
{
if (!collector_.isPatch())
{
return;
}
const label patchi = pp.index();
const label localPatchi = collector_.IDs().find(patchi);
if
(
localPatchi != -1
&& dParticles_[localPatchi].size() < maxStoredParcels_
)
{
dParticles_[localPatchi].append(p.d());
nParticles_[localPatchi].append(p.nParticle());
}
}
template<class CloudType>
void Foam::ParticleHistogram<CloudType>::postFace
(
const parcelType& p,
bool&
)
{
if (collector_.isPatch())
{
return;
}
const labelList& IDs = collector_.IDs();
const List<boundBox>& BBs = collector_.BBs();
const faceZoneMesh& fzm = this->owner().mesh().faceZones();
forAll(IDs, i)
{
if (!BBs[i].contains(p.position()))
{
// Quick reject if the particle is not in the face zone bound box
continue;
}
const label zonei = IDs[i];
const label localFacei = fzm[zonei].find(p.face());
if
(
localFacei != -1
&& dParticles_[i].size() < maxStoredParcels_
)
{
dParticles_[i].append(p.d());
nParticles_[i].append(p.nParticle());
}
}
}
template<class CloudType>
void Foam::ParticleHistogram<CloudType>::write()
{
const wordList& names = collector_.names();
forAll(names, i)
{
List<scalarList> procDiameters(Pstream::nProcs());
procDiameters[Pstream::myProcNo()] = dParticles_[i];
Pstream::gatherList(procDiameters);
List<scalarList> procParticles(Pstream::nProcs());
procParticles[Pstream::myProcNo()] = nParticles_[i];
Pstream::gatherList(procParticles);
if (Pstream::master())
{
scalarList globalDiameters;
globalDiameters = ListListOps::combine<scalarList>
(
procDiameters,
accessOp<scalarList>()
);
scalarList globalParticles;
globalParticles = ListListOps::combine<scalarList>
(
procParticles,
accessOp<scalarList>()
);
// Compute histogram
scalarList nParticles(nBins_, Zero);
const scalar delta = range_.span()/scalar(nBins_);
forAll(globalDiameters, j)
{
const label bini = (globalDiameters[j] - range_.min())/delta;
if (bini >= 0 && bini < nBins_)
{
nParticles[bini] += globalParticles[j];
nParticlesCumulative_[i][bini] += globalParticles[j];
}
}
if (this->writeToFile())
{
autoPtr<OFstream> osPtr = this->newFileAtTime
(
names[i],
this->owner().time().value()
);
OFstream& os = osPtr.ref();
writeFileHeader(os);
forAll(nParticles, j)
{
os << binEdges_[j] << tab
<< binEdges_[j + 1] << tab
<< nParticles[j] << tab
<< nParticlesCumulative_[i][j]
<< nl;
}
}
}
dParticles_[i].clearStorage();
nParticles_[i].clearStorage();
}
}
// ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -24,64 +24,86 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::PatchParticleHistogram
Foam::ParticleHistogram
Description
Computes a histogram for the distribution of particle diameters
and corresponding number of particles hitting on a given list of patches.
and corresponding number of particles hitting on a given list of
patches or face zones.
Operands:
\table
Operand | Type | Location
input | - | -
output file | dat | $FOAM_CASE/postProcessing/\<FO\>/\<time\>/\<file\>
output file | dat | \<case\>/postProcessing/\<FO\>/\<time\>/\<file\>
output field | - | -
\endtable
The output file contains two columns, the first is the bin edges of
the particle diameter (i.e. \c d), and the second is the number of
particles whose diameter falling into the corresponding bin
(i.e. \c nParticles).
The output file contains four columns, from the first to the last:
\vartable
dEdge1 | Left bin-edge of particle diameter
dEdge2 | Right bin-edge of particle diameter
nParticles | Number of particles falling into the corresponding bin
nParticlesCumulative | Cumulative number of binned particles
\endvartable
Usage
Minimal example by using
\c constant/reactingCloud1Properties.cloudFunctions:
\verbatim
patchParticleHistogram1
particleHistogram1
{
// Mandatory entries (unmodifiable)
type patchParticleHistogram;
patches (<patch1> <patch2> ... <patchN>);
nBins 10;
min 0.1;
max 10.0;
maxStoredParcels 20;
// Mandatory entries
type particleHistogram;
nBins <label>;
min <scalar>;
max <scalar>;
maxStoredParcels <scalar>;
// Conditional entries
// Option-1
patches (<wordRes>);
// Option-2
faceZones (<wordRes>);
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Dflt
type | Type name: patchParticleHistogram | word | yes | -
patches | Names of operand patches | wordList | yes | -
Property | Description | Type | Reqd | Deflt
type | Type name: particleHistogram | word | yes | -
nBins | Number of histogram bins | label | yes | -
max | Maximum value of histogram data | scalar | yes | -
min | Minimum value of histogram data | scalar | yes | -
maxStoredParcels | Maximum number of parcels to process | label | yes | -
patches | Names of operand patches | wordRes | choice | -
faceZones | Names of operand face zones | wordRes | choice | -
\endtable
The inherited entries are elaborated in:
- \link CloudFunctionObject.H \endlink
- \link writeFile.H \endlink
Note
- The underlying type of \c maxStoredParcels is set as a scalar for I/O.
SourceFiles
PatchParticleHistogram.C
ParticleHistogram.C
\*---------------------------------------------------------------------------*/
#ifndef PatchParticleHistogram_H
#define PatchParticleHistogram_H
#ifndef Foam_ParticleHistogram_H
#define Foam_ParticleHistogram_H
#include "CloudFunctionObject.H"
#include "writeFile.H"
#include "MinMax.H"
#include "cloudFunctionObjectTools.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -89,81 +111,64 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class PatchParticleHistogram Declaration
Class ParticleHistogram Declaration
\*---------------------------------------------------------------------------*/
template<class CloudType>
class PatchParticleHistogram
class ParticleHistogram
:
public CloudFunctionObject<CloudType>
public CloudFunctionObject<CloudType>,
public functionObjects::writeFile
{
// Private Data
//- Convenience typedef for parcel type
typedef typename CloudType::particleType parcelType;
// Typedefs
//- Convenience typedef for parcel type
typedef typename CloudType::particleType parcelType;
//- Collector surfaces
cloudFunctionObjectTools::collector collector_;
//- Number of data bins
const label nBins_;
//- Minimum value of histogram data
const scalar min_;
//- Maximum value of histogram data
const scalar max_;
//- Bin width of histogram
const scalar delta_;
//- Maximum number of parcels to store - set as a scalar for I/O
const scalar maxStoredParcels_;
//- Min/Max value of histogram data
const scalarMinMax range_;
//- Bin edges of histogram
scalarField binEdges_;
//- List of patch indices to post-process
labelList patchIDs_;
//- Accumulated number of particles per patch
//- Accumulated number of particles per surface
//- binned according to the histogram settings
List<List<scalar>> nParticlesCumulative_;
List<scalarList> nParticlesCumulative_;
//- List of time for each data record
List<DynamicList<scalar>> times_;
// List of surface-hit particle diameters
List<DynamicList<scalar>> dParticles_;
// List of patch-hit particle diameters
List<DynamicList<scalar>> patchDiameters_;
// List of number of patch-hit particles
List<DynamicList<scalar>> patchParticles_;
// List of number of surface-hit particles
List<DynamicList<scalar>> nParticles_;
// Private Member Functions
//- Return local patchi if patch is in patchIds_ list
label applyToPatch(const label globalPatchi) const;
protected:
// Protected Member Functions
//- Write post-processing info
void write();
//- Write output file header
void writeFileHeader(Ostream& os) const;
public:
//- Runtime type information
TypeName("patchParticleHistogram");
TypeName("particleHistogram");
// Constructors
//- No default construct
PatchParticleHistogram() = delete;
//- Construct from dictionary
PatchParticleHistogram
ParticleHistogram
(
const dictionary& dict,
CloudType& owner,
@ -171,36 +176,45 @@ public:
);
//- Copy construct
PatchParticleHistogram(const PatchParticleHistogram<CloudType>& ppm);
ParticleHistogram(const ParticleHistogram<CloudType>& ph);
//- No copy assignment
void operator=(const PatchParticleHistogram<CloudType>&) = delete;
void operator=(const ParticleHistogram<CloudType>&) = delete;
//- Construct and return a clone
virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
{
return autoPtr<CloudFunctionObject<CloudType>>
(
new PatchParticleHistogram<CloudType>(*this)
new ParticleHistogram<CloudType>(*this)
);
}
//- Destructor
virtual ~PatchParticleHistogram() = default;
virtual ~ParticleHistogram() = default;
// Member Functions
// Evaluation
// Evaluation
//- Post-patch hook
virtual void postPatch
(
const parcelType& p,
const polyPatch& pp,
bool& keepParticle
);
//- Post-patch hook
virtual void postPatch
(
const parcelType& p,
const polyPatch& pp,
bool& keepParticle
);
//- Post-face hook
virtual void postFace(const parcelType& p, bool& keepParticle);
// I-O
//- Write post-processing info
virtual void write();
};
@ -212,7 +226,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "PatchParticleHistogram.C"
#include "ParticleHistogram.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -1,253 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2021 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 "PatchParticleHistogram.H"
#include "Pstream.H"
#include "stringListOps.H"
#include "ListOps.H"
#include "ListListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class CloudType>
Foam::label Foam::PatchParticleHistogram<CloudType>::applyToPatch
(
const label globalPatchi
) const
{
return patchIDs_.find(globalPatchi);
}
// * * * * * * * * * * * * * protected Member Functions * * * * * * * * * * //
template<class CloudType>
void Foam::PatchParticleHistogram<CloudType>::write()
{
forAll(times_, i)
{
List<List<scalar>> procTimes(Pstream::nProcs());
procTimes[Pstream::myProcNo()] = times_[i];
Pstream::gatherList(procTimes);
List<List<scalar>> procDiameters(Pstream::nProcs());
procDiameters[Pstream::myProcNo()] = patchDiameters_[i];
Pstream::gatherList(procDiameters);
List<List<scalar>> procParticles(Pstream::nProcs());
procParticles[Pstream::myProcNo()] = patchParticles_[i];
Pstream::gatherList(procParticles);
if (Pstream::master())
{
const fvMesh& mesh = this->owner().mesh();
mkDir(this->writeTimeDir());
const word& patchName = mesh.boundaryMesh()[patchIDs_[i]].name();
OFstream patchOutFile
(
this->writeTimeDir()/patchName + ".post",
IOstreamOption::ASCII,
mesh.time().writeCompression()
);
List<scalar> globalTimes;
globalTimes = ListListOps::combine<List<scalar>>
(
procTimes,
accessOp<List<scalar>>()
);
List<scalar> globalDiameters;
globalDiameters = ListListOps::combine<List<scalar>>
(
procDiameters,
accessOp<List<scalar>>()
);
List<scalar> globalParticles;
globalParticles = ListListOps::combine<List<scalar>>
(
procParticles,
accessOp<List<scalar>>()
);
// Compute histogram
List<scalar> nParticles(nBins_, Zero);
forAll(globalDiameters, j)
{
const label bini = (globalDiameters[j] - min_)/delta_;
if (bini >= 0 && bini < nBins_)
{
nParticles[bini] += globalParticles[j];
nParticlesCumulative_[i][bini] += globalParticles[j];
}
}
patchOutFile
<< "# nBin=" << nBins_
<< "; min=" << min_
<< "; max=" << max_ << nl
<< "# dEdge1 dEdge2 nParticles nParticlesCumulative"
<< endl;
forAll(nParticles, j)
{
patchOutFile
<< binEdges_[j]
<< ' '
<< binEdges_[j + 1]
<< ' '
<< nParticles[j]
<< ' '
<< nParticlesCumulative_[i][j]
<< nl;
}
}
times_[i].clearStorage();
patchDiameters_[i].clearStorage();
patchParticles_[i].clearStorage();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::PatchParticleHistogram<CloudType>::PatchParticleHistogram
(
const dictionary& dict,
CloudType& owner,
const word& modelName
)
:
CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
nBins_(dict.getCheck<label>("nBins", labelMinMax::ge(1))),
min_(dict.getScalar("min")),
max_(dict.getScalar("max")),
delta_((max_ - min_)/scalar(nBins_)),
maxStoredParcels_(dict.getScalar("maxStoredParcels")),
binEdges_(nBins_ + 1),
patchIDs_(),
nParticlesCumulative_(),
times_(),
patchDiameters_(),
patchParticles_()
{
if (min_ >= max_)
{
FatalIOErrorInFunction(dict)
<< "Histogram minimum = " << min_
<< ", cannot be larger than histogram maximum = " << max_
<< exit(FatalIOError);
}
if (maxStoredParcels_ <= 0)
{
FatalIOErrorInFunction(dict)
<< "maxStoredParcels = " << maxStoredParcels_
<< ", cannot be equal to or less than zero"
<< exit(FatalIOError);
}
// Compute histogram-bin properties
binEdges_[0] = min_;
for (label i = 0; i < nBins_; ++i)
{
const scalar next = min_ + (i+1)*delta_;
binEdges_[i+1] = next;
}
// Compute histogram-patch properties
const wordRes patchMatcher(dict.get<wordRes>("patches"));
patchIDs_ = patchMatcher.matching(owner.mesh().boundaryMesh().names());
if (patchIDs_.empty())
{
FatalIOErrorInFunction(dict)
<< "No matching patches found: "
<< flatOutput(patchMatcher) << nl
<< exit(FatalIOError);
}
nParticlesCumulative_ =
List<List<scalar>>(patchIDs_.size(), List<scalar>(nBins_, Zero));
times_.setSize(patchIDs_.size());
patchDiameters_.setSize(patchIDs_.size());
patchParticles_.setSize(patchIDs_.size());
}
template<class CloudType>
Foam::PatchParticleHistogram<CloudType>::PatchParticleHistogram
(
const PatchParticleHistogram<CloudType>& ppm
)
:
CloudFunctionObject<CloudType>(ppm),
nBins_(ppm.nBins_),
min_(ppm.min_),
max_(ppm.max_),
delta_(ppm.delta_),
maxStoredParcels_(ppm.maxStoredParcels_),
binEdges_(ppm.binEdges_),
patchIDs_(ppm.patchIDs_),
nParticlesCumulative_(ppm.nParticlesCumulative_),
times_(ppm.times_),
patchDiameters_(ppm.patchDiameters_),
patchParticles_(ppm.patchParticles_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::PatchParticleHistogram<CloudType>::postPatch
(
const parcelType& p,
const polyPatch& pp,
bool&
)
{
const label patchi = pp.index();
const label localPatchi = applyToPatch(patchi);
if (localPatchi != -1 && times_[localPatchi].size() < maxStoredParcels_)
{
times_[localPatchi].append(this->owner().time().value());
patchDiameters_[localPatchi].append(p.d());
patchParticles_[localPatchi].append(p.nParticle());
}
}
// ************************************************************************* //

View File

@ -531,7 +531,7 @@ in the injection models set above we have
36 μm -> 2 parcels per second
45 μm -> 2 parcels per second
therefore in the following "patchParticleHistogram1" we can set
therefore in the following "particleHistogram1" we can set
nBins = 9
min = 0μm
max = 45μm
@ -547,9 +547,9 @@ in this ways the particles hitting the patches will be classified in the followi
9) 40.01μm to 45.01μm <- the 45μm particles will be counted in this range
*/
patchParticleHistogram1
particleHistogram1
{
type patchParticleHistogram;
type particleHistogram;
patches
(
roof

View File

@ -167,9 +167,9 @@ cloudFunctions
writer vtk;
}
patchParticleHistogram1
particleHistogram1
{
type patchParticleHistogram;
type particleHistogram;
patches
(
cycLeft_half0