ParticlePostProcessing.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) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "ParticlePostProcessing.H"
30 #include "Pstream.H"
31 #include "stringListOps.H"
32 #include "ListOps.H"
33 #include "ListListOps.H"
34 
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 
37 template<class CloudType>
39 {
40  this->writeCommented(os, "Time");
41  os << ' ' << "currentProc";
42 
43  if (!header_.empty())
44  {
45  os << ' ' << header_;
46  }
47 
48  os << endl;
49 }
50 
51 
52 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
53 
54 template<class CloudType>
56 (
57  const dictionary& dict,
58  CloudType& owner,
59  const word& modelName
60 )
61 :
62  CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
63  functionObjects::writeFile
64  (
65  owner,
66  this->localPath(),
67  typeName
68  ),
69  collector_(this->coeffDict(), owner.mesh()),
70  maxStoredParcels_(this->coeffDict().getScalar("maxStoredParcels")),
71  header_(),
72  fields_(),
73  times_(),
74  data_()
75 {
76  writeFile::read(this->coeffDict());
77 
78  this->coeffDict().readIfPresent("fields", fields_);
79 
80  if (maxStoredParcels_ <= 0)
81  {
83  << "maxStoredParcels = " << maxStoredParcels_
84  << ", cannot be equal to or less than zero"
85  << exit(FatalIOError);
86  }
87 
88  const label sz = collector_.size();
89  times_.resize(sz);
90  data_.resize(sz);
91 }
92 
93 
94 template<class CloudType>
96 (
98 )
99 :
101  writeFile(ppp),
102  collector_(ppp.collector_),
103  maxStoredParcels_(ppp.maxStoredParcels_),
104  header_(ppp.header_),
105  fields_(ppp.fields_),
106  times_(ppp.times_),
107  data_(ppp.data_)
108 {}
109 
110 
111 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
112 
113 template<class CloudType>
115 (
116  const parcelType& p,
117  const polyPatch& pp,
118  const typename parcelType::trackingData& td
119 )
120 {
121  if (!collector_.isPatch())
122  {
123  return true;
124  }
125 
126  const label patchi = pp.index();
127  const label localPatchi = collector_.IDs().find(patchi);
128 
129  if (header_.empty())
130  {
131  OStringStream data;
132  p.writeProperties(data, fields_, " ", true);
133  header_ = data.str();
134  }
135 
136  if (localPatchi != -1 && data_[localPatchi].size() < maxStoredParcels_)
137  {
138  times_[localPatchi].append(this->owner().time().value());
139 
140  OStringStream data;
141  data<< Pstream::myProcNo();
142  p.writeProperties(data, fields_, " ", false);
143 
144  data_[localPatchi].append(data.str());
145  }
147  return true;
148 }
149 
150 
151 template<class CloudType>
153 (
154  const parcelType& p,
155  const typename parcelType::trackingData& td
156 )
157 {
158  if (collector_.isPatch())
159  {
160  return true;
161  }
162 
163  const labelList& IDs = collector_.IDs();
164  const List<boundBox>& BBs = collector_.BBs();
165  const faceZoneMesh& fzm = this->owner().mesh().faceZones();
166 
167  if (header_.empty())
168  {
169  OStringStream data;
170  p.writeProperties(data, fields_, " ", true);
171  header_ = data.str();
172  }
173 
174  forAll(IDs, i)
175  {
176  if (!BBs[i].contains(p.position()))
177  {
178  // Quick reject if the particle is not in the face zone bound box
179  continue;
180  }
181 
182  const label zonei = IDs[i];
183  const label localFacei = fzm[zonei].find(p.face());
184 
185  if (localFacei != -1 && data_[localFacei].size() < maxStoredParcels_)
186  {
187  times_[i].append(this->owner().time().value());
188 
189  OStringStream data;
190  data<< Pstream::myProcNo();
191  p.writeProperties(data, fields_, " ", false);
192 
193  data_[i].append(data.str());
194  }
195  }
196 
197  return true;
198 }
199 
200 
201 template<class CloudType>
203 {
204  const wordList& names = collector_.names();
205 
206  forAll(names, i)
207  {
208  List<scalarList> procTimes(Pstream::nProcs());
209  procTimes[Pstream::myProcNo()] = times_[i];
210  Pstream::gatherList(procTimes);
211 
212  List<List<string>> procData(Pstream::nProcs());
213  procData[Pstream::myProcNo()] = data_[i];
214  Pstream::gatherList(procData);
215 
217  (
218  header_,
219  [](string& x, const string& y)
220  {
221  if (y.size() > x.size())
222  {
223  x = y;
224  }
225  }
226  );
227 
228  if (Pstream::master())
229  {
230  List<string> globalData;
231  globalData = ListListOps::combine<List<string>>
232  (
233  procData,
234  accessOp<List<string>>()
235  );
236 
237  scalarList globalTimes;
238  globalTimes = ListListOps::combine<scalarList>
239  (
240  procTimes,
241  accessOp<scalarList>()
242  );
243 
244  if (this->writeToFile())
245  {
246  autoPtr<OFstream> osPtr = this->newFileAtTime
247  (
248  names[i],
249  this->owner().time().value()
250  );
251  OFstream& os = osPtr.ref();
252 
253  writeFileHeader(os);
254 
255  const labelList indices(sortedOrder(globalTimes));
256  forAll(globalTimes, j)
257  {
258  const label datai = indices[j];
259 
260  os << globalTimes[datai] << tab
261  << globalData[datai].c_str()
262  << nl;
263  }
264  }
265  }
266 
267  times_[i].clearStorage();
268  data_[i].clearStorage();
269  }
270 }
271 
272 
273 // ************************************************************************* //
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
dictionary dict
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
constexpr char tab
The tab &#39;\t&#39; character(0x09)
Definition: Ostream.H:49
Operations on lists of strings.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
ParticlePostProcessing(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
scalar y
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:1065
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
Gather data, but keep individual values separate. Uses the specified communication schedule...
virtual bool postPatch(const parcelType &p, const polyPatch &pp, const typename parcelType::trackingData &td)
Post-patch hook.
dynamicFvMesh & mesh
A class for handling words, derived from Foam::string.
Definition: word.H:63
label size() const noexcept
Return number of collectors (zones or patches)
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
Definition: subModelBase.C:122
static void combineReduce(const List< commsStruct > &comms, T &value, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) applying cop to inplace combine value from different processors...
Writes out various standard Lagrangian data elements of particles hitting on a given list of patches ...
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
OBJstream os(runTime.globalPath()/outputName)
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:670
virtual void write()
Write post-processing info.
virtual bool postFace(const parcelType &p, const typename parcelType::trackingData &td)
Post-face hook.
List< word > wordList
List of word.
Definition: fileName.H:59
const fvMesh & mesh() const
Return reference to the mesh.
Definition: DSMCCloudI.H:37
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:67
Templated cloud function object base class.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...