PatchParticleHistogram.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2020-2021 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
29#include "Pstream.H"
30#include "stringListOps.H"
31#include "ListOps.H"
32#include "ListListOps.H"
33
34// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35
36template<class CloudType>
38(
39 const label globalPatchi
40) const
41{
42 return patchIDs_.find(globalPatchi);
43}
44
45
46// * * * * * * * * * * * * * protected Member Functions * * * * * * * * * * //
47
48template<class CloudType>
50{
51 forAll(times_, i)
52 {
53 List<List<scalar>> procTimes(Pstream::nProcs());
54 procTimes[Pstream::myProcNo()] = times_[i];
55 Pstream::gatherList(procTimes);
56
57 List<List<scalar>> procDiameters(Pstream::nProcs());
58 procDiameters[Pstream::myProcNo()] = patchDiameters_[i];
59 Pstream::gatherList(procDiameters);
60
61 List<List<scalar>> procParticles(Pstream::nProcs());
62 procParticles[Pstream::myProcNo()] = patchParticles_[i];
63 Pstream::gatherList(procParticles);
64
65 if (Pstream::master())
66 {
67 const fvMesh& mesh = this->owner().mesh();
68
69 mkDir(this->writeTimeDir());
70
71 const word& patchName = mesh.boundaryMesh()[patchIDs_[i]].name();
72
73 OFstream patchOutFile
74 (
75 this->writeTimeDir()/patchName + ".post",
76 IOstream::ASCII,
77 IOstream::currentVersion,
78 mesh.time().writeCompression()
79 );
80
81 List<scalar> globalTimes;
82 globalTimes = ListListOps::combine<List<scalar>>
83 (
84 procTimes,
86 );
87
88 List<scalar> globalDiameters;
89 globalDiameters = ListListOps::combine<List<scalar>>
90 (
91 procDiameters,
93 );
94
95 List<scalar> globalParticles;
96 globalParticles = ListListOps::combine<List<scalar>>
97 (
98 procParticles,
100 );
101
102 // Compute histogram
103 List<scalar> nParticles(nBins_, Zero);
104 forAll(globalDiameters, j)
105 {
106 const label bini = (globalDiameters[j] - min_)/delta_;
107 if (bini >= 0 && bini < nBins_)
108 {
109 nParticles[bini] += globalParticles[j];
110 nParticlesCumulative_[i][bini] += globalParticles[j];
111 }
112 }
113
114 patchOutFile
115 << "# nBin=" << nBins_
116 << "; min=" << min_
117 << "; max=" << max_ << nl
118 << "# dEdge1 dEdge2 nParticles nParticlesCumulative"
119 << endl;
120
121 forAll(nParticles, j)
122 {
123 patchOutFile
124 << binEdges_[j]
125 << ' '
126 << binEdges_[j + 1]
127 << ' '
128 << nParticles[j]
129 << ' '
130 << nParticlesCumulative_[i][j]
131 << nl;
132 }
133 }
134
135 times_[i].clearStorage();
136 patchDiameters_[i].clearStorage();
137 patchParticles_[i].clearStorage();
138 }
139}
140
141
142// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
143
144template<class CloudType>
146(
147 const dictionary& dict,
148 CloudType& owner,
149 const word& modelName
150)
151:
152 CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
153 nBins_(dict.getCheck<label>("nBins", labelMinMax::ge(1))),
154 min_(dict.getScalar("min")),
155 max_(dict.getScalar("max")),
156 delta_((max_ - min_)/scalar(nBins_)),
157 maxStoredParcels_(dict.getScalar("maxStoredParcels")),
158 binEdges_(nBins_ + 1),
159 patchIDs_(),
160 nParticlesCumulative_(),
161 times_(),
162 patchDiameters_(),
163 patchParticles_()
164{
165 if (min_ >= max_)
166 {
168 << "Histogram minimum = " << min_
169 << ", cannot be larger than histogram maximum = " << max_
170 << exit(FatalIOError);
171 }
172
173 if (maxStoredParcels_ <= 0)
174 {
176 << "maxStoredParcels = " << maxStoredParcels_
177 << ", cannot be equal to or less than zero"
178 << exit(FatalIOError);
179 }
180
181 // Compute histogram-bin properties
182 binEdges_[0] = min_;
183 for (label i = 0; i < nBins_; ++i)
184 {
185 const scalar next = min_ + (i+1)*delta_;
186 binEdges_[i+1] = next;
187 }
188
189 // Compute histogram-patch properties
190 const wordRes patchMatcher(dict.get<wordRes>("patches"));
191
192 patchIDs_ = patchMatcher.matching(owner.mesh().boundaryMesh().names());
193
194 if (patchIDs_.empty())
195 {
197 << "No matching patches found: "
198 << flatOutput(patchMatcher) << nl
199 << exit(FatalIOError);
200 }
201
202 nParticlesCumulative_ =
203 List<List<scalar>>(patchIDs_.size(), List<scalar>(nBins_, Zero));
204
205 times_.setSize(patchIDs_.size());
206 patchDiameters_.setSize(patchIDs_.size());
207 patchParticles_.setSize(patchIDs_.size());
208}
209
210
211template<class CloudType>
213(
215)
216:
218 nBins_(ppm.nBins_),
219 min_(ppm.min_),
220 max_(ppm.max_),
221 delta_(ppm.delta_),
222 maxStoredParcels_(ppm.maxStoredParcels_),
223 binEdges_(ppm.binEdges_),
224 patchIDs_(ppm.patchIDs_),
225 nParticlesCumulative_(ppm.nParticlesCumulative_),
226 times_(ppm.times_),
227 patchDiameters_(ppm.patchDiameters_),
228 patchParticles_(ppm.patchParticles_)
229{}
230
231
232// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
233
234template<class CloudType>
236(
237 const parcelType& p,
238 const polyPatch& pp,
239 bool&
240)
241{
242 const label patchi = pp.index();
243 const label localPatchi = applyToPatch(patchi);
244
245 if (localPatchi != -1 && times_[localPatchi].size() < maxStoredParcels_)
246 {
247 times_[localPatchi].append(this->owner().time().value());
248 patchDiameters_[localPatchi].append(p.d());
249 patchParticles_[localPatchi].append(p.nParticle());
250 }
251}
252
253
254// ************************************************************************* //
Various functions to operate on Lists.
Templated cloud function object base class.
const CloudType & owner() const
Return const access to the owner cloud.
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:75
const fvMesh & mesh() const
Return reference to the mesh.
Definition: DSMCCloudI.H:44
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
A min/max value pair with additional methods. In addition to conveniently storing values,...
Definition: MinMax.H:128
Output to file stream, using an OSstream.
Definition: OFstream.H:57
Computes a histogram for the distribution of particle diameters and corresponding number of particles...
virtual void postPatch(const parcelType &p, const polyPatch &pp, bool &keepParticle)
Post-patch hook.
void write()
Write post-processing info.
PatchParticleHistogram()=delete
No default construct.
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
label index() const noexcept
The index of this patch in the boundaryMesh.
wordList names() const
Return a list of patch names.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
const dictionary & dict() const
Return const access to the cloud dictionary.
Definition: subModelBase.C:113
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:54
labelList matching(const UList< StringType > &input, const bool invert=false) const
Return list indices for all matches.
A class for handling words, derived from Foam::string.
Definition: word.H:68
volScalarField & p
dynamicFvMesh & mesh
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:215
IOerror FatalIOError
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Operations on lists of strings.
mkDir(pdfPath)