sizeDistribution.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2017-2020 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "sizeDistribution.H"
27 #include "Time.H"
28 #include "fvMesh.H"
30 #include "mathematicalConstants.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 namespace functionObjects
37 {
38  defineTypeNameAndDebug(sizeDistribution, 0);
39  addToRunTimeSelectionTable(functionObject, sizeDistribution, dictionary);
40 }
41 }
42 
43 template<>
44 const char*
46 <
48  4
49 >::names[] =
50 {
51  "moments",
52  "standardDeviation",
53  "number",
54  "volume"
55 };
56 
57 const Foam::NamedEnum
58 <
60  4
62 
63 template<>
64 const char*
66 <
68  4
69 >::names[] =
70 {
71  "volume",
72  "area",
73  "diameter",
74  "projectedAreaDiameter"
75 };
76 
77 const Foam::NamedEnum
78 <
80  4
82 
84 
85 
86 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
87 
90 (
91  const scalarField& field
92 ) const
93 {
94  if (isNull(cellIDs()))
95  {
96  return field;
97  }
98  else
99  {
100  return tmp<scalarField>(new scalarField(field, cellIDs()));
101  }
102 }
103 
104 
106 {
107  forAll(N_, i)
108  {
109  const Foam::diameterModels::sizeGroup& fi = popBal_.sizeGroups()[i];
110 
111  scalarField Ni(filterField(fi*fi.phase()/fi.x()));
112  scalarField V(filterField(mesh_.V()));
113  scalarField ai(filterField(fi.a()));
114  scalarField di(Ni.size());
115 
116  switch (coordinateType_)
117  {
118  case ctProjectedAreaDiameter:
119  {
120  di = sqrt(ai/pi);
121 
122  break;
123  }
124  default:
125  {
126  di = fi.d();
127 
128  break;
129  }
130  }
131 
132  N_[i] = gSum(V*Ni)/this->V();
133  a_[i] = gSum(V*ai)/this->V();
134  d_[i] = gSum(V*di)/this->V();
135  }
136 
137  forAll(bins_, i)
138  {
139  const Foam::diameterModels::sizeGroup& fi = popBal_.sizeGroups()[i];
140 
141  bins_[i] = point(fi.x().value(), a_[i], d_[i]);
142  }
143 }
144 
145 
147 {
148  logFiles::write();
149 
150  Log << " writing moments of size distribution." << endl;
151 
152  if (Pstream::master())
153  {
154  writeTime(file());
155  }
156 
157  for (label k = 0; k <= maxOrder_; k++)
158  {
159  scalar result = 0;
160 
161  forAll(N_, i)
162  {
163  result += pow(bins_[i][binCmpt_], k)*N_[i];
164  }
165 
166  if (Pstream::master())
167  {
168  file() << tab << result;
169  }
170  }
171 
172  if (Pstream::master())
173  {
174  file() << endl;
175  }
176 }
177 
178 
180 {
181  logFiles::write();
182 
183  Log << " writing standard deviation of size distribution."
184  << endl;
185 
186  if (Pstream::master())
187  {
188  writeTime(file());
189  }
190 
191  scalar stdDev = 0;
192  scalar mean = 0;
193  scalar var = 0;
194 
195  if(sum(N_) != 0)
196  {
197  if (geometric_)
198  {
199  mean = exp(sum(Foam::log(bins_.component(binCmpt_))*N_/sum(N_)));
200 
201  var =
202  sum(sqr(Foam::log(bins_.component(binCmpt_)) - Foam::log(mean))
203  *N_/sum(N_));
204 
205  stdDev = exp(sqrt(var));
206  }
207  else
208  {
209  mean = sum(bins_.component(binCmpt_)*N_/sum(N_));
210 
211  var = sum(sqr(bins_.component(binCmpt_) - mean)*N_/sum(N_));
212 
213  stdDev = sqrt(var);
214  }
215  }
216 
217  if (Pstream::master())
218  {
219  file() << tab << stdDev << tab << mean << tab << var << endl;
220  }
221 }
222 
223 
225 {
226  scalarField result(N_);
227 
228  switch (functionType_)
229  {
230  case ftNumber:
231  {
232  Log << " writing number distribution. "
233  << endl;
234 
235  break;
236  }
237  case ftVolume:
238  {
239  Log << " writing volume distribution. "
240  << endl;
241 
242  result *= bins_.component(0);
243 
244  break;
245  }
246  default:
247  {
248  break;
249  }
250 
251  }
252 
253  if (normalize_)
254  {
255  if(sum(result) != 0)
256  {
257  result /= sum(result);
258  }
259 
260  }
261 
262  if (densityFunction_)
263  {
264  List<scalar> bndrs(N_.size() + 1);
265 
266  bndrs.first() = bins_.first()[binCmpt_];
267  bndrs.last() = bins_.last()[binCmpt_];
268 
269  for (label i = 1; i < N_.size(); i++)
270  {
271  bndrs[i] = (bins_[i][binCmpt_] + bins_[i-1][binCmpt_])/2.0;
272  }
273 
274  forAll(result, i)
275  {
276  if (geometric_)
277  {
278  result[i] /=
279  (Foam::log(bndrs[i+1]) - Foam::log(bndrs[i]));
280  }
281  else
282  {
283  result[i] /= (bndrs[i+1] - bndrs[i]);
284  }
285  }
286  }
287 
288  if (Pstream::master())
289  {
290  const coordSet coords
291  (
292  "sizeDistribution",
293  "xyz",
294  bins_,
295  mag(bins_)
296  );
297 
298  writeGraph(coords, functionTypeNames_[functionType_], result);
299  }
300 }
301 
302 
304 (
305  const label i
306 )
307 {
309 
310  writeHeaderValue
311  (
312  file(),
313  "Coordinate",
314  word(coordinateTypeNames_[coordinateType_])
315  );
316 
317  word str("Time");
318 
319  switch (functionType_)
320  {
321  case ftMoments:
322  {
323  for (label k = 0; k <= maxOrder_; k++)
324  {
325  str += (" k=" + std::to_string(k));
326  }
327 
328  break;
329  }
330 
331  case ftStdDev:
332  {
333  str += " standardDeviation mean variance";
334 
335  break;
336  }
337 
338  default:
339  {
340  break;
341  }
342  }
343 
344  writeCommented(file(), str);
345 
346  file() << endl;
347 }
348 
349 
351 (
352  const coordSet& coords,
353  const word& functionTypeName,
354  const scalarField& values
355 )
356 {
357  const wordList functionTypeNames(1, functionTypeName);
358 
359  fileName outputPath = file_.baseTimeDir();
360 
361  mkDir(outputPath);
362  OFstream graphFile
363  (
364  outputPath/(this->name() + ".dat")
365  );
366 
367  volRegion::writeFileHeader(file_, graphFile);
368 
369  file_.writeCommented(graphFile, "Volume area diameter " + functionTypeName);
370 
371  if (densityFunction_)
372  {
373  graphFile << "Density";
374  }
375  else
376  {
377  graphFile << "Concentration";
378  }
379 
380  graphFile << endl;
381 
382  List<const scalarField*> yPtrs(1);
383  yPtrs[0] = &values;
384  scalarFormatter_().write(coords, functionTypeNames, yPtrs, graphFile);
385 }
386 
387 
388 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
389 
391 (
392  const word& name,
393  const Time& runTime,
394  const dictionary& dict
395 )
396 :
397  fvMeshFunctionObject(name, runTime, dict),
398  volRegion(fvMeshFunctionObject::mesh_, dict),
399  logFiles(obr_, name),
400  mesh_(fvMeshFunctionObject::mesh_),
401  file_(obr_, name),
402  popBal_
403  (
404  obr_.lookupObject<Foam::diameterModels::populationBalanceModel>
405  (
406  dict.lookup("populationBalance")
407  )
408  ),
409  functionType_(functionTypeNames_.read(dict.lookup("functionType"))),
410  coordinateType_(coordinateTypeNames_.read(dict.lookup("coordinateType"))),
411  N_(popBal_.sizeGroups().size(), 0),
412  a_(popBal_.sizeGroups().size(), 0),
413  d_(popBal_.sizeGroups().size(), 0),
414  bins_(N_.size()),
415  binCmpt_(0)
416 {
417  read(dict);
418  resetName(name);
419 
420  switch (coordinateType_)
421  {
422  case ctVolume:
423  {
424  binCmpt_ = 0;
425 
426  break;
427  }
428  case ctArea:
429  {
430  binCmpt_ = 1;
431 
432  break;
433  }
434  case ctDiameter:
435  {
436  binCmpt_ = 2;
437 
438  break;
439  }
440  case ctProjectedAreaDiameter:
441  {
442  binCmpt_ = 2;
443 
444  break;
445  }
446  }
447 
448  scalarFormatter_ = writer<scalar>::New("raw");
449 }
450 
451 
452 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
453 
455 {}
456 
457 
458 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
459 
460 bool Foam::functionObjects::sizeDistribution::read(const dictionary& dict)
461 {
463 
464  normalize_ = dict.lookupOrDefault<Switch>("normalize", false);
465  densityFunction_ = dict.lookupOrDefault<Switch>("densityFunction", false);
466  geometric_ = dict.lookupOrDefault<Switch>("geometric", false);
467  maxOrder_ = dict.lookupOrDefault("maxOrder", 3);
468 
469  return false;
470 }
471 
472 
474 {
475  return true;
476 }
477 
478 
480 {
481  return true;
482 }
483 
484 
486 {
487  Log << type() << " " << name() << " write:" << nl;
488 
489  correctVolAverages();
490 
491  switch (functionType_)
492  {
493  case ftMoments:
494  {
495  writeMoments();
496 
497  break;
498  }
499 
500  case ftStdDev:
501  {
502  writeStdDev();
503 
504  break;
505  }
506 
507  default:
508  {
509  writeDistribution();
510 
511  break;
512  }
513  }
514 
515  Log << endl;
516 
517  return true;
518 }
519 
520 
521 // ************************************************************************* //
tmp< scalarField > filterField(const scalarField &field) const
Filter field according to cellIds.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
virtual bool write()
Write function.
Definition: logFiles.C:180
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
const dimensionedScalar & x() const
Return representative volume of the sizeGroup.
Definition: sizeGroupI.H:57
functionType
Function type enumeration.
dimensionedScalar log(const dimensionedScalar &ds)
const word & name() const
Return the name of this functionObject.
static const char tab
Definition: Ostream.H:259
dimensionedSymmTensor sqr(const dimensionedVector &dv)
virtual ~sizeDistribution()
Destructor.
void writeGraph(const coordSet &coords, const word &functionTypeName, const scalarField &values)
Output function for all functionType number/volume.
addToRunTimeSelectionTable(functionObject, Qdot, dictionary)
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
const tmp< volScalarField > d() const
Return representative diameter of the sizeGroup.
label k
Boltzmann constant.
virtual bool read(const dictionary &)
Read the sizeDistribution data.
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:51
const phaseModel & phase() const
Return const-reference to the phase.
Definition: sizeGroupI.H:36
Macros for easy insertion into run-time selection tables.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
void writeStdDev()
Write standard deviation.
const tmp< volScalarField > a() const
Return representative surface area of the sizeGroup.
virtual bool read(const dictionary &)
Read optional controls.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
stressControl lookup("compactNormalStress") >> compactNormalStress
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
Definition: nullObjectI.H:46
Type gSum(const FieldField< Field, Type > &f)
dimensionedScalar exp(const dimensionedScalar &ds)
This class represents a single sizeGroup belonging to a velocityGroup. The main property of a sizeGro...
Definition: sizeGroup.H:100
virtual void writeFileHeader(const label i)
Output file header information for functionType moments.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual const word & type() const =0
Runtime type information.
const Type & value() const
Return const reference to value.
virtual bool execute()
Execute, currently does nothing.
static autoPtr< writer > New(const word &writeFormat)
Return a reference to the selected writer.
Definition: writer.C:35
static const char nl
Definition: Ostream.H:260
coordinateType
Coordinate type enumeration.
virtual bool write()
Calculate and write the size distribution.
static const NamedEnum< coordinateType, 4 > coordinateTypeNames_
Coordinate type names.
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
defineTypeNameAndDebug(Qdot, 0)
sizeDistribution(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
void writeFileHeader(const writeFile &wf, Ostream &file)
Output file header information.
Definition: volRegion.C:58
List< word > wordList
A List of words.
Definition: fileName.H:54
void writeDistribution()
Write distribution.
void correctVolAverages()
Correct volume averages.
vector point
Point is a vector.
Definition: point.H:41
#define Log
Report write to Foam::Info if the local log switch is true.
dimensioned< scalar > mag(const dimensioned< Type > &)
static const NamedEnum< functionType, 4 > functionTypeNames_
Ordinate type names.
rDeltaTY field()
A class for managing temporary objects.
Definition: PtrList.H:53
virtual bool end()
Execute at the final time-loop, currently does nothing.
Namespace for OpenFOAM.