Loading...
Searching...
No Matches
ParticleZoneInfo.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) 2022 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 "ParticleZoneInfo.H"
30
31// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32
33namespace Foam
34{
35
37{
38 void operator()(particleInfo& p1, const particleInfo& p2) const
39 {
40 // p2 not set
41 if (p2.origID == -1)
42 {
43 return;
44 }
45
46 // p1 not set - initialise with p2
47 if (p1.origID == -1)
48 {
49 p1 = p2;
50 return;
51 }
52
53 // Set initial values
54 if (p2.time0 < p1.time0)
55 {
56 p1.time0 = p2.time0;
57 p1.d0 = p2.d0;
58 p1.mass0 = p2.mass0;
59 }
60
61 // Accumulate age
62 p1.age += p2.age;
63
64 // Set latest available values
65 if (p2.isOlderThan(p1))
66 {
67 p1.position = p2.position;
68 p1.d = p2.d;
69 p1.mass = p2.mass;
70 }
71 }
72};
73
74template<class Type>
76(
77 const Foam::UList<Foam::particleInfo>& data,
78 Type Foam::particleInfo::* field
79)
80{
81 Field<Type> result(data.size());
82
83 forAll(data, i)
84 {
85 result[i] = data[i].*field;
86 }
87
88 return result;
89}
90
91} // End namespace Foam
92
93
94// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
95
96template<class CloudType>
97void Foam::ParticleZoneInfo<CloudType>::writeWriter
98(
99 const UList<particleInfo>& data
100)
101{
102 coordSet coords
103 (
104 "zoneParticles",
105 "xyz",
106 getData(data, &particleInfo::position),
107 scalarList(data.size(), Zero)
108 );
109
110 writerPtr_->open(coords, this->baseTimeDir() / "zoneParticles");
111 writerPtr_->beginTime(this->owner().time());
112
113#undef writeLocal
114#define writeLocal(field) \
115 writerPtr_->write(#field, getData(data, &particleInfo::field));
116
117 writeLocal(origID);
118 writeLocal(origProc);
119 writeLocal(time0);
120 writeLocal(age);
121 writeLocal(d0);
122 writeLocal(d);
123 writeLocal(mass0);
124 writeLocal(mass);
125#undef writeLocal
126
127 writerPtr_->endTime();
128 writerPtr_->close();
129}
130
131
132template<class CloudType>
133void Foam::ParticleZoneInfo<CloudType>::writeFileHeader(Ostream& os) const
134{
135 this->writeHeaderValue(os, "cellZone", cellZoneName_);
136 this->writeHeaderValue(os, "time", this->owner().time().timeOutputValue());
137 this->writeHeader(os, "");
138 this->writeCommented(os, "origID");
139 os << tab << "origProc"
140 << tab << "(x y z)"
141 << tab << "time0"
142 << tab << "age"
143 << tab << "d0"
144 << tab << "d"
145 << tab << "mass0"
146 << tab << "mass"
147 << endl;
148}
149
150
151template<class CloudType>
152bool Foam::ParticleZoneInfo<CloudType>::inZone(const label celli) const
153{
154 return this->owner().mesh().cellZones()[cellZoneId_].whichCell(celli) != -1;
155}
156
157
158template<class CloudType>
159Foam::label Foam::ParticleZoneInfo<CloudType>::getParticleID
160(
161 const particleInfo& p
162) const
163{
164 forAll(data_, i)
165 {
166 const auto& d = data_[i];
167 if ((d.origProc == p.origProc) && (d.origID == p.origID))
168 {
169 return i;
170 }
171 }
172
173 return -1;
174}
175
176
177// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
178
179template<class CloudType>
181(
182 const dictionary& dict,
183 CloudType& owner,
184 const word& modelName
185)
186:
187 CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
188 functionObjects::writeFile
189 (
190 owner,
191 this->localPath(),
193 ),
194 cellZoneName_(this->coeffDict().getWord("cellZone")),
195 cellZoneId_(-1),
196 data_(),
197 movedParticles_(),
198 maxIDs_(Pstream::nProcs(), Zero),
199 writerPtr_(nullptr)
200{
201 if (Pstream::master())
202 {
203 const word writerType = this->coeffDict().getWord("writer");
204
205 writerPtr_ = coordSetWriter::New
206 (
207 writerType,
208 coordSetWriter::formatOptions(this->coeffDict(), writerType)
209 );
210 }
211
212 writeFile::read(this->coeffDict());
213
214 const auto& cellZones = owner.mesh().cellZones();
215
216 cellZoneId_ = cellZones.findZoneID(cellZoneName_);
217 if (cellZoneId_ == -1)
218 {
220 << "Unable to find cellZone " << cellZoneName_
221 << ". Available cellZones are:" << cellZones.names()
222 << exit(FatalIOError);
223 }
224
225 Info<< " Processing cellZone" << cellZoneName_ << " with id "
226 << cellZoneId_ << endl;
227
228 if (Pstream::master())
229 {
230 // Data was reduced on write
231 labelList maxIDs;
232
233 if (this->getModelProperty("maxIDs", maxIDs))
234 {
235 if (maxIDs.size() == Pstream::nProcs())
236 {
237 maxIDs_ = maxIDs;
238 this->getModelProperty("data", data_);
239
240 Info<< " Restarting with " << data_.size()
241 << " particles" << endl;
242 }
243 else
244 {
246 << "Case restarted with a different number of processors."
247 << " Restarting particle statistics." << endl;
248
249 // TODO
250 // - use Cloud for base storage instead of local particle list?
252 }
253 }
254}
255
256
257template<class CloudType>
259(
261)
262:
264 writeFile(pzi),
265 cellZoneName_(pzi.cellZoneName_),
266 cellZoneId_(pzi.cellZoneId_),
267 data_(pzi.data_),
268 movedParticles_(pzi.movedParticles_),
269 maxIDs_(Pstream::nProcs()),
270 writerPtr_(nullptr)
271{}
272
273
274// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
275
276template<class CloudType>
279 const typename parcelType::trackingData& td
280)
281{}
282
283
284template<class CloudType>
286(
287 const typename parcelType::trackingData& td
288)
289{
290 Log_<< this->type() << ":" << nl
291 << " Cell zone = " << cellZoneName_ << nl
292 << " Contributions = "
293 << returnReduce(movedParticles_.size(), sumOp<label>())
294 << endl;
295
296 if (!this->writeTime())
297 {
298 Log_<< endl;
299 }
300
301 for (const auto& p : movedParticles_)
302 {
303 const label id = getParticleID(p);
304
305 if (id == -1)
306 {
307 // New particle
308 data_.append(p);
309 maxIDs_[p.origProc] = max(maxIDs_[p.origProc], p.origID);
310 }
311 else
312 {
313 // Add to existing particle
314 data_[id] += p;
315 }
316 }
317
318 movedParticles_.clear();
320 // Calls write
322}
323
324
325template<class CloudType>
327(
328 parcelType& p,
329 const scalar dt,
330 const point&,
331 const typename parcelType::trackingData& td
332)
333{
334 if (inZone(p.cell()))
335 {
336 particleInfo newData;
337 newData.origID = p.origId();
338 newData.origProc = p.origProc();
339 newData.position = p.position();
340 newData.time0 = this->owner().time().value() + dt;
341 newData.age = dt;
342 newData.d0 = p.d();
343 newData.d = p.d();
344 newData.mass0 = p.mass();
345 newData.mass = newData.mass0;
346
347 movedParticles_.append(newData);
349
350 return true;
351}
352
353
354template<class CloudType>
356{
357 autoPtr<OFstream> osPtr =
358 this->newFileAtTime
359 (
360 "particles",
361 this->owner().time().timeOutputValue()
362 );
363
364 if (Pstream::parRun())
365 {
366 // Find number of particles per proc
367 labelList allMaxIDs(maxIDs_);
368 Pstream::listReduce(allMaxIDs, maxOp<label>());
369
370 // Combine into single list
371 label n = returnReduce(data_.size(), sumOp<label>());
372 DynamicList<particleInfo> globalParticles(n);
373 {
374 List<List<particleInfo>> procParticles(Pstream::nProcs());
375 forAll(procParticles, proci)
376 {
377 procParticles[proci].resize(allMaxIDs[proci] + 1);
378 }
379
380 // Insert into bins for accumulation
381 for (const auto& d : data_)
382 {
383 procParticles[d.origProc][d.origID] = d;
384 }
385
386 for (auto& particles : procParticles)
387 {
388 Pstream::listCombineGather(particles, particleInfoCombineOp());
389 for (const auto& p : particles)
390 {
391 if (p.origID != -1)
392 {
393 globalParticles.append(p);
394 }
395 }
396 }
397 }
398
399 if (Pstream::master())
400 {
401 writeWriter(globalParticles);
402
403 auto& os = osPtr();
404 writeFileHeader(os);
405
406 label nData = 0;
407
408 for (const auto& p : globalParticles)
409 {
410 if (p.origID != -1)
411 {
412 os << p << endl;
413 ++nData;
414 }
415 }
416
417 Log_<< " Number of particles = " << nData << nl
418 << " Written data to " << os.name() << endl;
419
420 this->setModelProperty("data", globalParticles);
421 this->setModelProperty("maxIDs", allMaxIDs);
422 }
423 else
424 {
425 // Data only present on master
426 this->setModelProperty("data", List<particleInfo>());
427 this->setModelProperty("maxIDs", labelList());
428 }
429 }
430 else
431 {
432 writeWriter(data_);
433
434 auto& os = osPtr();
435 writeFileHeader(os);
436
437 for (const auto& p : data_)
438 {
439 os << p << nl;
440 }
441
442 Log_<< " Number of particles = " << data_.size() << nl
443 << " Written data to " << os.name() << endl;
444
445 this->setModelProperty("data", data_);
446 this->setModelProperty("maxIDs", maxIDs_);
447 }
448
449 Log_<< endl;
450}
451
452
453// ************************************************************************* //
#define writeLocal(field)
label n
Templated cloud function object base class.
CloudFunctionObject(CloudType &owner)
Construct null from owner.
virtual void postEvolve(const typename parcelType::trackingData &td)
Post-evolve hook.
virtual fileName localPath() const
Output directory.
const CloudType & owner() const
Return const access to the owner cloud.
virtual bool writeTime() const
Flag to indicate when to write a property.
const fvMesh & mesh() const
Return reference to the mesh.
Definition DSMCCloudI.H:37
particle::trackingData trackingData
Definition DSMCParcel.H:155
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void append(const T &val)
Copy append an element to the end of this list.
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
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
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition OSstream.H:134
Reports cloud information for particles passing through a specified cell zone.
virtual void postEvolve(const typename parcelType::trackingData &td)
Post-evolve hook.
virtual void write()
Write.
ParticleZoneInfo(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
virtual void preEvolve(const typename parcelType::trackingData &td)
Pre-evolve hook.
virtual bool postMove(parcelType &p, const scalar dt, const point &position0, const typename parcelType::trackingData &td)
Post-move hook.
Inter-processor communications stream.
Definition Pstream.H:59
static void listCombineGather(UList< T > &values, CombineOp cop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Forwards to Pstream::listGather with an in-place cop.
static void listReduce(UList< T > &values, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce list elements (list must be equal size on all ranks), applying bop to each list element.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
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
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
static autoPtr< coordSetWriter > New(const word &writeFormat)
Return a reference to the selected writer.
static dictionary formatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Same as fileFormats::getFormatOptions.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
word getWord(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Same as get<word>(const word&, keyType::option).
const Type & value() const noexcept
Return const reference to value.
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 autoPtr< OFstream > newFileAtTime(const word &name, scalar timeValue) const
Return autoPtr to a new file for a given time.
Definition writeFile.C:110
const Time & time() const noexcept
Return time registry.
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition polyMesh.H:679
bool getModelProperty(const word &entryName, Type &value) const
Retrieve generic property from the sub-model.
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.
void setModelProperty(const word &entryName, const Type &value)
Add generic property to the sub-model.
A class for handling words, derived from Foam::string.
Definition word.H:66
volScalarField & p
rDeltaTY field()
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
OBJstream os(runTime.globalPath()/outputName)
wallPoints::trackData td(isBlockedFace, regionToBlockSize)
#define Log_
Report write to Foam::Info if the class log switch is true.
#define WarningInFunction
Report a warning using Foam::Warning.
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
DSMCCloud< dsmcParcel > CloudType
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< Type > getData(const Foam::UList< Foam::particleInfo > &data, Type Foam::particleInfo::*field)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition POSIX.C:801
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
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 ...
vector point
Point is a vector.
Definition point.H:37
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
void operator()(particleInfo &p1, const particleInfo &p2) const
scalar isOlderThan(const particleInfo &p) const