Loading...
Searching...
No Matches
ParticleHistogram.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-2023 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
28#include "ParticleHistogram.H"
29#include "Pstream.H"
30#include "ListOps.H"
31#include "ListListOps.H"
32
33// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34
35template<class CloudType>
36void Foam::ParticleHistogram<CloudType>::writeFileHeader(Ostream& os) const
37{
38 this->writeHeaderValue(os, "nBin", nBins_);
39 this->writeHeaderValue(os, "min", range_.min());
40 this->writeHeaderValue(os, "max", range_.max());
41 this->writeHeader(os, "");
42 this->writeCommented(os, "dEdge1");
43 os << tab << "dEdge2"
44 << tab << "nParticles"
45 << tab << "nParticlesCumulative"
46 << endl;
47}
48
49
50// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
51
52template<class CloudType>
54(
55 const dictionary& dict,
56 CloudType& owner,
57 const word& modelName
58)
59:
60 CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
61 functionObjects::writeFile
62 (
63 owner,
64 this->localPath(),
66 ),
67 collector_(this->coeffDict(), owner.mesh()),
68 nBins_
69 (
70 this->coeffDict().template getCheck<label>("nBins", labelMinMax::ge(1))
71 ),
72 maxStoredParcels_(this->coeffDict().getScalar("maxStoredParcels")),
73 range_
74 (
75 this->coeffDict().getScalar("min"),
76 this->coeffDict().getScalar("max")
77 ),
78 binEdges_(nBins_ + 1),
79 nParticlesCumulative_(),
80 dParticles_(),
81 nParticles_()
82{
83 writeFile::read(this->coeffDict());
84
85 if (!range_.good())
86 {
88 << "Invalid histogram range: " << range_
90 }
91
92 if (maxStoredParcels_ <= 0)
93 {
95 << "maxStoredParcels = " << maxStoredParcels_
96 << ", cannot be equal to or less than zero"
98 }
99
100 // Compute histogram-bin properties
101 binEdges_[0] = range_.min();
102 const scalar delta = range_.span()/scalar(nBins_);
103 for (label i = 0; i < nBins_; ++i)
104 {
105 const scalar next = range_.min() + (i+1)*delta;
106 binEdges_[i+1] = next;
107 }
108
109 const label sz = collector_.size();
110 nParticlesCumulative_ = List<scalarList>(sz, scalarList(nBins_, Zero));
111 dParticles_.resize(sz);
112 nParticles_.resize(sz);
113}
114
115
116template<class CloudType>
118(
120)
121:
123 writeFile(ph),
124 collector_(ph.collector_),
125 nBins_(ph.nBins_),
126 maxStoredParcels_(ph.maxStoredParcels_),
127 range_(ph.range_),
128 binEdges_(ph.binEdges_),
129 nParticlesCumulative_(ph.nParticlesCumulative_),
130 dParticles_(ph.dParticles_),
131 nParticles_(ph.nParticles_)
132{}
133
134
135// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
136
137template<class CloudType>
139(
140 const parcelType& p,
141 const polyPatch& pp,
142 const typename parcelType::trackingData& td
143)
144{
145 if (!collector_.isPatch())
146 {
147 return true;
148 }
149
150 const label patchi = pp.index();
151 const label localPatchi = collector_.IDs().find(patchi);
152
153 if
154 (
155 localPatchi != -1
156 && dParticles_[localPatchi].size() < maxStoredParcels_
157 )
158 {
159 dParticles_[localPatchi].append(p.d());
160 nParticles_[localPatchi].append(p.nParticle());
162
163 return true;
164}
165
166
167template<class CloudType>
169(
170 const parcelType& p,
171 const typename parcelType::trackingData& td
172)
173{
174 if (collector_.isPatch())
175 {
176 return true;
177 }
178
179 const labelList& IDs = collector_.IDs();
180 const List<boundBox>& BBs = collector_.BBs();
181 const faceZoneMesh& fzm = this->owner().mesh().faceZones();
182
183 forAll(IDs, i)
184 {
185 if (!BBs[i].contains(p.position()))
186 {
187 // Quick reject if the particle is not in the face zone bound box
188 continue;
189 }
190
191 const label zonei = IDs[i];
192 const label localFacei = fzm[zonei].find(p.face());
193
194 if
195 (
196 localFacei != -1
197 && dParticles_[i].size() < maxStoredParcels_
198 )
199 {
200 dParticles_[i].append(p.d());
201 nParticles_[i].append(p.nParticle());
202 }
204
205 return true;
206}
207
208
209template<class CloudType>
211{
212 const wordList& names = collector_.names();
213
214 forAll(names, i)
215 {
216 List<scalarList> procDiameters(Pstream::nProcs());
217 procDiameters[Pstream::myProcNo()] = dParticles_[i];
218 Pstream::gatherList(procDiameters);
219
220 List<scalarList> procParticles(Pstream::nProcs());
221 procParticles[Pstream::myProcNo()] = nParticles_[i];
222 Pstream::gatherList(procParticles);
223
224 if (Pstream::master())
225 {
226 scalarList globalDiameters;
227 globalDiameters = ListListOps::combine<scalarList>
228 (
229 procDiameters,
230 accessOp<scalarList>()
231 );
232
233 scalarList globalParticles;
234 globalParticles = ListListOps::combine<scalarList>
235 (
236 procParticles,
237 accessOp<scalarList>()
238 );
239
240 // Compute histogram
241 scalarList nParticles(nBins_, Zero);
242 const scalar delta = range_.span()/scalar(nBins_);
243 forAll(globalDiameters, j)
244 {
245 const label bini = (globalDiameters[j] - range_.min())/delta;
246 if (bini >= 0 && bini < nBins_)
247 {
248 nParticles[bini] += globalParticles[j];
249 nParticlesCumulative_[i][bini] += globalParticles[j];
250 }
251 }
252
253 if (this->writeToFile())
254 {
255 autoPtr<OFstream> osPtr = this->newFileAtTime
256 (
257 names[i],
258 this->owner().time().value()
259 );
260 OFstream& os = osPtr.ref();
261
262 writeFileHeader(os);
263
264 forAll(nParticles, j)
265 {
266 os << binEdges_[j] << tab
267 << binEdges_[j + 1] << tab
268 << nParticles[j] << tab
269 << nParticlesCumulative_[i][j]
270 << nl;
271 }
272 }
273 }
274
275 dParticles_[i].clearStorage();
276 nParticles_[i].clearStorage();
277 }
278}
279
280
281// ************************************************************************* //
scalar delta
Various functions to operate on Lists.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Templated cloud function object base class.
CloudFunctionObject(CloudType &owner)
Construct null from owner.
virtual fileName localPath() const
Output directory.
const CloudType & owner() const
Return const access to the owner cloud.
const fvMesh & mesh() const
Return reference to the mesh.
Definition DSMCCloudI.H:37
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
bool good() const
Range is non-inverted.
Definition MinMaxI.H:153
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
Computes a histogram for the distribution of particle diameters and corresponding number of particles...
ParticleHistogram(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
virtual void write()
Write post-processing info.
virtual bool postFace(const parcelType &p, const typename parcelType::trackingData &td)
Post-face hook.
virtual bool postPatch(const parcelType &p, const polyPatch &pp, const typename parcelType::trackingData &td)
Post-patch hook.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run.
Definition UPstream.H:1697
@ gatherList
gatherList [manual algorithm]
Definition UPstream.H:194
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
T & ref()
Return reference to the managed object without nullptr checking.
Definition autoPtr.H:231
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
writeFile(const objectRegistry &obr, const fileName &prefix, const word &name="undefined", const bool writeToFile=true, const string &ext=".dat")
Construct from objectRegistry, prefix, fileName.
Definition writeFile.C:200
virtual bool writeToFile() const
Flag to allow writing to file.
Definition writeFile.C:286
virtual autoPtr< OFstream > newFileAtTime(const word &name, scalar timeValue) const
Return autoPtr to a new file for a given time.
Definition writeFile.C:110
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition polyMesh.H:671
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
const dictionary & dict() const
Return const access to the cloud dictionary.
const word & modelName() const
Return const access to the name of the sub-model.
A class for handling words, derived from Foam::string.
Definition word.H:66
volScalarField & p
dynamicFvMesh & mesh
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
OBJstream os(runTime.globalPath()/outputName)
auto & names
wallPoints::trackData td(isBlockedFace, regionToBlockSize)
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition ListListOps.C:62
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
List< word > wordList
List of word.
Definition fileName.H:60
DSMCCloud< dsmcParcel > CloudType
List< label > labelList
A List of labels.
Definition List.H:62
MinMax< label > labelMinMax
A label min/max range.
Definition MinMax.H:96
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with faceZone content on a polyMesh.
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
List< scalar > scalarList
List of scalar.
Definition scalarList.H:32
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
constexpr char tab
The tab '\t' character(0x09).
Definition Ostream.H:49
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
Object access operator or list access operator (default is pass-through).
Definition UList.H:1120