Merge branch 'feature-particle-histogram' into 'develop'

ENH: ParticleHistogram: refactor PatchParticleHistogram function object

See merge request Development/openfoam!595
This commit is contained in:
Andrew Heather
2023-06-01 08:24:29 +00:00
20 changed files with 1138 additions and 791 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 "ParticlePostProcessing.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(ParticlePostProcessing, 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 "ParticlePostProcessing.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(ParticlePostProcessing, 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 "ParticlePostProcessing.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(ParticlePostProcessing, 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

@ -0,0 +1,269 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019-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 "ParticlePostProcessing.H"
#include "Pstream.H"
#include "stringListOps.H"
#include "ListOps.H"
#include "ListListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class CloudType>
void Foam::ParticlePostProcessing<CloudType>::writeFileHeader(Ostream& os) const
{
this->writeCommented(os, "Time");
os << ' ' << "currentProc";
if (!header_.empty())
{
os << ' ' << header_;
}
os << endl;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::ParticlePostProcessing<CloudType>::ParticlePostProcessing
(
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()),
maxStoredParcels_(this->coeffDict().getScalar("maxStoredParcels")),
header_(),
fields_(),
times_(),
data_()
{
writeFile::read(this->coeffDict());
this->coeffDict().readIfPresent("fields", fields_);
if (maxStoredParcels_ <= 0)
{
FatalIOErrorInFunction(this->coeffDict())
<< "maxStoredParcels = " << maxStoredParcels_
<< ", cannot be equal to or less than zero"
<< exit(FatalIOError);
}
const label sz = collector_.size();
times_.resize(sz);
data_.resize(sz);
}
template<class CloudType>
Foam::ParticlePostProcessing<CloudType>::ParticlePostProcessing
(
const ParticlePostProcessing<CloudType>& ppp
)
:
CloudFunctionObject<CloudType>(ppp),
writeFile(ppp),
collector_(ppp.collector_),
maxStoredParcels_(ppp.maxStoredParcels_),
header_(ppp.header_),
fields_(ppp.fields_),
times_(ppp.times_),
data_(ppp.data_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::ParticlePostProcessing<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 (header_.empty())
{
OStringStream data;
p.writeProperties(data, fields_, " ", true);
header_ = data.str();
}
if (localPatchi != -1 && data_[localPatchi].size() < maxStoredParcels_)
{
times_[localPatchi].append(this->owner().time().value());
OStringStream data;
data<< Pstream::myProcNo();
p.writeProperties(data, fields_, " ", false);
data_[localPatchi].append(data.str());
}
}
template<class CloudType>
void Foam::ParticlePostProcessing<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();
if (header_.empty())
{
OStringStream data;
p.writeProperties(data, fields_, " ", true);
header_ = data.str();
}
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 && data_[localFacei].size() < maxStoredParcels_)
{
times_[i].append(this->owner().time().value());
OStringStream data;
data<< Pstream::myProcNo();
p.writeProperties(data, fields_, " ", false);
data_[i].append(data.str());
}
}
}
template<class CloudType>
void Foam::ParticlePostProcessing<CloudType>::write()
{
const wordList& names = collector_.names();
forAll(names, i)
{
List<scalarList> procTimes(Pstream::nProcs());
procTimes[Pstream::myProcNo()] = times_[i];
Pstream::gatherList(procTimes);
List<List<string>> procData(Pstream::nProcs());
procData[Pstream::myProcNo()] = data_[i];
Pstream::gatherList(procData);
Pstream::combineReduce
(
header_,
[](string& x, const string& y)
{
if (y.size() > x.size())
{
x = y;
}
}
);
if (Pstream::master())
{
List<string> globalData;
globalData = ListListOps::combine<List<string>>
(
procData,
accessOp<List<string>>()
);
scalarList globalTimes;
globalTimes = ListListOps::combine<scalarList>
(
procTimes,
accessOp<scalarList>()
);
if (this->writeToFile())
{
autoPtr<OFstream> osPtr = this->newFileAtTime
(
names[i],
this->owner().time().value()
);
OFstream& os = osPtr.ref();
writeFileHeader(os);
const labelList indices(sortedOrder(globalTimes));
forAll(globalTimes, j)
{
const label datai = indices[j];
os << globalTimes[datai] << tab
<< globalData[datai].c_str()
<< nl;
}
}
}
times_[i].clearStorage();
data_[i].clearStorage();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,226 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019-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::ParticlePostProcessing
Description
Writes out various standard Lagrangian data elements of
particles hitting on a given list of patches or face zones.
Operands:
\table
Operand | Type | Location
input | - | -
output file | dat | \<case\>/postProcessing/\<FO\>/\<time\>/\<file\>
output field | - | -
\endtable
The output file contains columns depending on the \c fields entry.
Usage
Minimal example by using
\c constant/reactingCloud1Properties.cloudFunctions:
\verbatim
ParticlePostProcessing1
{
// Mandatory entries
type particlePostProcessing;
maxStoredParcels <scalar>;
// Optional entries
fields (<wordRes>);
// Conditional entries
// Option-1
patches (<wordRes>);
// Option-2
faceZones (<wordRes>);
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
type | Type name: particlePostProcessing | word | yes | -
maxStoredParcels | Maximum number of parcels to process | label | yes | -
fields | Names of standard Lagrangian fields | wordRes | no | all
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.
- Empty files indicate that no particles hit selected surfaces.
SourceFiles
ParticlePostProcessing.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_ParticlePostProcessing_H
#define Foam_ParticlePostProcessing_H
#include "CloudFunctionObject.H"
#include "writeFile.H"
#include "cloudFunctionObjectTools.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class ParticlePostProcessing Declaration
\*---------------------------------------------------------------------------*/
template<class CloudType>
class ParticlePostProcessing
:
public CloudFunctionObject<CloudType>,
public functionObjects::writeFile
{
// Private Data
// Typedefs
//- Convenience typedef for parcel type
typedef typename CloudType::particleType parcelType;
//- Collector surfaces
cloudFunctionObjectTools::collector collector_;
//- Maximum number of parcels to store - set as a scalar for I/O
scalar maxStoredParcels_;
//- Field header
string header_;
//- Field name filters
wordRes fields_;
//- List of times for each data record
List<DynamicList<scalar>> times_;
//- List of output data per surface
List<DynamicList<string>> data_;
// Private Member Functions
//- Write output file header
void writeFileHeader(Ostream& os) const;
public:
//- Runtime type information
TypeName("particlePostProcessing");
// Constructors
//- Construct from dictionary
ParticlePostProcessing
(
const dictionary& dict,
CloudType& owner,
const word& modelName
);
//- Copy construct
ParticlePostProcessing(const ParticlePostProcessing<CloudType>& ppp);
//- No copy assignment
void operator=(const ParticlePostProcessing<CloudType>&) = delete;
//- Construct and return a clone
virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
{
return autoPtr<CloudFunctionObject<CloudType>>
(
new ParticlePostProcessing<CloudType>(*this)
);
}
//- Destructor
virtual ~ParticlePostProcessing() = default;
// Member Functions
// Access
//- Return maximum number of parcels to store per surface
label maxStoredParcels() const noexcept { return maxStoredParcels_; }
// Evaluation
//- 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();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "ParticlePostProcessing.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

@ -1,216 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019 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 "PatchPostProcessing.H"
#include "Pstream.H"
#include "stringListOps.H"
#include "ListOps.H"
#include "ListListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class CloudType>
Foam::label Foam::PatchPostProcessing<CloudType>::applyToPatch
(
const label globalPatchi
) const
{
return patchIDs_.find(globalPatchi);
}
// * * * * * * * * * * * * * protected Member Functions * * * * * * * * * * //
template<class CloudType>
void Foam::PatchPostProcessing<CloudType>::write()
{
forAll(patchData_, i)
{
List<List<scalar>> procTimes(Pstream::nProcs());
procTimes[Pstream::myProcNo()] = times_[i];
Pstream::gatherList(procTimes);
List<List<string>> procData(Pstream::nProcs());
procData[Pstream::myProcNo()] = patchData_[i];
Pstream::gatherList(procData);
if (Pstream::master())
{
const fvMesh& mesh = this->owner().mesh();
// Create directory if it doesn't exist
mkDir(this->writeTimeDir());
const word& patchName = mesh.boundaryMesh()[patchIDs_[i]].name();
OFstream patchOutFile
(
this->writeTimeDir()/patchName + ".post",
IOstreamOption::ASCII,
mesh.time().writeCompression()
);
List<string> globalData;
globalData = ListListOps::combine<List<string>>
(
procData,
accessOp<List<string>>()
);
List<scalar> globalTimes;
globalTimes = ListListOps::combine<List<scalar>>
(
procTimes,
accessOp<List<scalar>>()
);
labelList indices(sortedOrder(globalTimes));
string header("# Time currentProc " + header_);
patchOutFile<< header.c_str() << nl;
forAll(globalTimes, i)
{
label dataI = indices[i];
patchOutFile
<< globalTimes[dataI] << ' '
<< globalData[dataI].c_str()
<< nl;
}
}
patchData_[i].clearStorage();
times_[i].clearStorage();
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::PatchPostProcessing<CloudType>::PatchPostProcessing
(
const dictionary& dict,
CloudType& owner,
const word& modelName
)
:
CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
maxStoredParcels_(this->coeffDict().getScalar("maxStoredParcels")),
fields_(),
patchIDs_(),
times_(),
patchData_(),
header_()
{
// The "fields" filter is optional
this->coeffDict().readIfPresent("fields", fields_);
// The "patches" are required
const wordRes patchMatcher(this->coeffDict().lookup("patches"));
patchIDs_ = patchMatcher.matching(owner.mesh().boundaryMesh().names());
if (patchIDs_.empty())
{
WarningInFunction
<< "No matching patches found: "
<< flatOutput(patchMatcher) << nl;
}
if (debug)
{
Info<< "Post-process fields "
<< flatOutput(fields_) << nl;
Info<< "On patches (";
for (const label patchi : patchIDs_)
{
Info<< ' ' << owner.mesh().boundaryMesh()[patchi].name();
}
Info<< " )" << nl;
}
patchData_.setSize(patchIDs_.size());
times_.setSize(patchIDs_.size());
}
template<class CloudType>
Foam::PatchPostProcessing<CloudType>::PatchPostProcessing
(
const PatchPostProcessing<CloudType>& ppm
)
:
CloudFunctionObject<CloudType>(ppm),
maxStoredParcels_(ppm.maxStoredParcels_),
fields_(ppm.fields_),
patchIDs_(ppm.patchIDs_),
times_(ppm.times_),
patchData_(ppm.patchData_),
header_(ppm.header_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::PatchPostProcessing<CloudType>::postPatch
(
const parcelType& p,
const polyPatch& pp,
bool&
)
{
const label patchi = pp.index();
const label localPatchi = applyToPatch(patchi);
if (header_.empty())
{
OStringStream data;
p.writeProperties(data, fields_, " ", true);
header_ = data.str();
}
if (localPatchi != -1 && patchData_[localPatchi].size() < maxStoredParcels_)
{
times_[localPatchi].append(this->owner().time().value());
OStringStream data;
data<< Pstream::myProcNo();
p.writeProperties(data, fields_, " ", false);
patchData_[localPatchi].append(data.str());
}
}
// ************************************************************************* //

View File

@ -1,171 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019 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::PatchPostProcessing
Group
grpLagrangianIntermediateFunctionObjects
Description
Standard post-processing
SourceFiles
PatchPostProcessing.C
\*---------------------------------------------------------------------------*/
#ifndef PatchPostProcessing_H
#define PatchPostProcessing_H
#include "CloudFunctionObject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class PatchPostProcessing Declaration
\*---------------------------------------------------------------------------*/
template<class CloudType>
class PatchPostProcessing
:
public CloudFunctionObject<CloudType>
{
// Private data
typedef typename CloudType::particleType parcelType;
//- Maximum number of parcels to store - set as a scalar for I/O
scalar maxStoredParcels_;
//- Field name filters
wordRes fields_;
//- List of patch indices to post-process
labelList patchIDs_;
//- List of time for each data record
List<DynamicList<scalar>> times_;
//- List of output data per patch
List<DynamicList<string>> patchData_;
//- Field header
string header_;
// Private Member Functions
//- Returns local patchi if patch is in patchIds_ list
label applyToPatch(const label globalPatchi) const;
protected:
// Protected Member Functions
//- Write post-processing info
void write();
public:
//- Runtime type information
TypeName("patchPostProcessing");
// Constructors
//- Construct from dictionary
PatchPostProcessing
(
const dictionary& dict,
CloudType& owner,
const word& modelName
);
//- Construct copy
PatchPostProcessing(const PatchPostProcessing<CloudType>& ppm);
//- Construct and return a clone
virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
{
return autoPtr<CloudFunctionObject<CloudType>>
(
new PatchPostProcessing<CloudType>(*this)
);
}
//- Destructor
virtual ~PatchPostProcessing() = default;
// Member Functions
// Access
//- Return maximum number of parcels to store per patch
inline label maxStoredParcels() const;
//- Return const mapping from local to global patch ids
inline const labelList& patchIDs() const;
// Evaluation
//- Post-patch hook
virtual void postPatch
(
const parcelType& p,
const polyPatch& pp,
bool& keepParticle
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "PatchPostProcessingI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "PatchPostProcessing.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,42 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
template<class CloudType>
Foam::label Foam::PatchPostProcessing<CloudType>::maxStoredParcels() const
{
return maxStoredParcels_;
}
template<class CloudType>
const Foam::labelList& Foam::PatchPostProcessing<CloudType>::patchIDs() const
{
return patchIDs_;
}
// ************************************************************************* //

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
@ -564,9 +564,9 @@ in this ways the particles hitting the patches will be classified in the followi
maxStoredParcels 100000000;
}
patchPostProcessing1
particlePostProcessing1
{
type patchPostProcessing;
type particlePostProcessing;
fields (position origId d);
maxStoredParcels 100000000;
patches

View File

@ -167,9 +167,9 @@ cloudFunctions
writer vtk;
}
patchParticleHistogram1
particleHistogram1
{
type patchParticleHistogram;
type particleHistogram;
patches
(
cycLeft_half0
@ -181,9 +181,9 @@ cloudFunctions
maxStoredParcels 20;
}
patchPostProcessing1
particlePostProcessing1
{
type patchPostProcessing;
type particlePostProcessing;
fields (position "U.*" d T nParticle);
maxStoredParcels 20;
patches

View File

@ -175,9 +175,9 @@ subModels
cloudFunctions
{
patchPostProcessing1
particlePostProcessing1
{
type patchPostProcessing;
type particlePostProcessing;
maxStoredParcels 100;
patches ( outlet );
}

View File

@ -177,9 +177,9 @@ subModels
cloudFunctions
{
patchPostProcessing1
particlePostProcessing1
{
type patchPostProcessing;
type particlePostProcessing;
maxStoredParcels 100;
patches ( outlet );
}

View File

@ -177,9 +177,9 @@ subModels
cloudFunctions
{
patchPostProcessing1
particlePostProcessing1
{
type patchPostProcessing;
type particlePostProcessing;
maxStoredParcels 100;
patches ( outlet );
}

View File

@ -158,9 +158,9 @@ subModels
cloudFunctions
{
patchPostProcessing1
particlePostProcessing1
{
type patchPostProcessing;
type particlePostProcessing;
maxStoredParcels 20;
patches
(