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 */ /* additional helper classes */
clouds/Templates/KinematicCloud/cloudSolution/cloudSolution.C clouds/Templates/KinematicCloud/cloudSolution/cloudSolution.C
submodels/CloudFunctionObjects/CloudFunctionObject/cloudFunctionObjectTools.C
/* averaging methods */ /* averaging methods */
submodels/MPPIC/AveragingMethods/makeAveragingMethods.C submodels/MPPIC/AveragingMethods/makeAveragingMethods.C

View File

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

View File

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

View File

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

View File

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