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-2018 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 "sizeGroup.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34 namespace functionObjects
35 {
36  defineTypeNameAndDebug(sizeDistribution, 0);
37  addToRunTimeSelectionTable(functionObject, sizeDistribution, dictionary);
38 }
39 }
40 
41 template<>
42 const char*
44 <
46  2
47 >::names[] = {"cellZone", "all"};
48 
49 template<>
50 const char*
52 <
54  4
55 >::names[] =
56  {
57  "numberDensity",
58  "volumeDensity",
59  "numberConcentration",
60  "moments"
61  };
62 
63 template<>
64 const char*
66 <
68  2
69 >::names[] = {"diameter", "volume"};
70 
71 const Foam::NamedEnum
72 <
74  2
76 
77 const Foam::NamedEnum
78 <
80  4
82 
83 const Foam::NamedEnum
84 <
86  2
88 
89 
90 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
91 
93 (
94  const dictionary& dict
95 )
96 {
97  switch (functionType_)
98  {
99  case ftNdf:
100  {
101  break;
102  }
103 
104  case ftVdf:
105  {
106  break;
107  }
108 
109  case ftNc:
110  {
111  break;
112  }
113 
114  case ftMom:
115  {
116  break;
117  }
118 
119  default:
120  {
122  << "Unknown function type. Valid function types are:"
123  << functionTypeNames_ << nl << exit(FatalError);
124  }
125  }
126 
127  switch (abszissaType_)
128  {
129  case atDiameter:
130  {
131  break;
132  }
133 
134  case atVolume:
135  {
136  break;
137  }
138 
139  default:
140  {
142  << "Unknown abszissa type. Valid abszissa types are:"
143  << abszissaTypeNames_ << nl << exit(FatalError);
144  }
145  }
146 
147  setCellZoneCells();
148 
149  if (nCells_ == 0)
150  {
152  << type() << " " << name() << ": "
153  << regionTypeNames_[regionType_] << "(" << regionName_ << "):" << nl
154  << " Region has no cells" << exit(FatalError);
155  }
156 
157  volume_ = volume();
158 
159  Info<< type() << " " << name() << ":"
160  << regionTypeNames_[regionType_] << "(" << regionName_ << "):" << nl
161  << " total cells = " << nCells_ << nl
162  << " total volume = " << volume_
163  << nl << endl;
164 
165  Info<< nl << endl;
166 }
167 
168 
170 {
171  switch (regionType_)
172  {
173  case rtCellZone:
174  {
175  dict().lookup("name") >> regionName_;
176 
177  label zoneId = mesh().cellZones().findZoneID(regionName_);
178 
179  if (zoneId < 0)
180  {
182  << "Unknown cell zone name: " << regionName_
183  << ". Valid cell zones are: " << mesh().cellZones().names()
184  << nl << exit(FatalError);
185  }
186 
187  cellId_ = mesh().cellZones()[zoneId];
188  nCells_ = returnReduce(cellId_.size(), sumOp<label>());
189  break;
190  }
191 
192  case rtAll:
193  {
194  cellId_ = identity(mesh().nCells());
195  nCells_ = returnReduce(cellId_.size(), sumOp<label>());
196  break;
197  }
198 
199  default:
200  {
202  << "Unknown region type. Valid region types are:"
203  << regionTypeNames_ << nl << exit(FatalError);
204  }
205  }
206 
207  if (debug)
208  {
209  Pout<< "Selected region size = " << cellId_.size() << endl;
210  }
211 }
212 
213 
215 {
216  return gSum(filterField(mesh().V()));
217 }
218 
219 
221 {
222  List<scalarField> allValues(Pstream::nProcs());
223 
224  allValues[Pstream::myProcNo()] = field;
225 
226  Pstream::gatherList(allValues);
227 
228  if (Pstream::master())
229  {
230  field =
231  ListListOps::combine<scalarField>
232  (
233  allValues,
234  accessOp<scalarField>()
235  );
236  }
237 }
238 
239 
242 (
243  const scalarField& field
244 ) const
245 {
246  return tmp<scalarField>(new scalarField(field, cellId_));
247 }
248 
249 
251 (
252  const label i
253 )
254 {
255  OFstream& file = this->file();
256 
257  switch (functionType_)
258  {
259  case ftNdf:
260  {
261  writeHeader(file, "Number density function");
262  break;
263  }
264 
265  case ftVdf:
266  {
267  writeHeader(file, "Volume density function");
268  break;
269  }
270 
271  case ftNc:
272  {
273  writeHeader(file, "Number concentration");
274  break;
275  }
276 
277  case ftMom:
278  {
279  writeHeader(file, "Moments");
280  break;
281  }
282  }
283 
284  switch (abszissaType_)
285  {
286  case atVolume:
287  {
288  writeCommented(file, "Time/volume");
289  break;
290  }
291 
292  case atDiameter:
293  {
294  writeCommented(file, "Time/diameter");
295  break;
296  }
297  }
298 
299  switch (functionType_)
300  {
301  case ftMom:
302  {
303  for (label i = 0; i <= momentOrder_; i++)
304  {
305  file() << tab << i;
306  }
307 
308  break;
309  }
310  default:
311  {
312  forAll(popBal_.sizeGroups(), sizeGroupi)
313  {
314  const diameterModels::sizeGroup& fi =
315  *popBal_.sizeGroups()[sizeGroupi];
316 
317  switch (abszissaType_)
318  {
319  case atDiameter:
320  {
321  file() << tab << fi.d().value();
322 
323  break;
324  }
325 
326  case atVolume:
327  {
328  file() << tab << fi.x().value();
329 
330  break;
331  }
332  }
333  }
334 
335  break;
336  }
337  }
338 
339  file << endl;
340 }
341 
342 
343 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
344 
346 (
347  const word& name,
348  const Time& runTime,
349  const dictionary& dict
350 )
351 :
352  fvMeshFunctionObject(name, runTime, dict),
353  logFiles(obr_, name),
354  dict_(dict),
355  regionType_(regionTypeNames_.read(dict.lookup("regionType"))),
356  regionName_(word::null),
357  functionType_(functionTypeNames_.read(dict.lookup("functionType"))),
358  abszissaType_(abszissaTypeNames_.read(dict.lookup("abszissaType"))),
359  nCells_(0),
360  cellId_(),
361  volume_(0.0),
362  writeVolume_(dict.lookupOrDefault("writeVolume", false)),
363  popBal_
364  (
365  obr_.lookupObject<Foam::diameterModels::populationBalanceModel>
366  (
367  dict.lookup("populationBalance")
368  )
369  ),
370  N_(popBal_.sizeGroups().size()),
371  momentOrder_(dict.lookupOrDefault<label>("momentOrder", 0)),
372  normalize_(dict.lookupOrDefault("normalize", false)),
373  sumN_(0.0),
374  sumV_(0.0)
375 {
376  read(dict);
377  resetName(name);
378 }
379 
380 
381 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
382 
384 {}
385 
386 
387 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
388 
389 bool Foam::functionObjects::sizeDistribution::read(const dictionary& dict)
390 {
391  if (dict != dict_)
392  {
393  dict_ = dict;
394  }
395 
397 
398  initialise(dict);
399 
400  return true;
401 }
402 
403 
405 {
406  return true;
407 }
408 
409 
411 {
412  logFiles::write();
413 
414  if (Pstream::master())
415  {
416  writeTime(file());
417  }
418 
419  Log << type() << " " << name() << " write" << nl;
420 
421  scalarField V(filterField(mesh().V()));
422  combineFields(V);
423 
424  sumN_ *= 0.0;
425  sumV_ *= 0.0;
426 
427  forAll(N_, i)
428  {
430  *popBal_.sizeGroups()[i];
431 
432  const volScalarField& alpha = fi.VelocityGroup().phase();
433 
434  scalarField Ni(fi*alpha/fi.x());
435  scalarField values(filterField(Ni));
436  scalarField V(filterField(mesh().V()));
437 
438  // Combine onto master
439  combineFields(values);
440  combineFields(V);
441 
442  if (Pstream::master())
443  {
444  // Calculate volume-averaged number concentration
445  N_[i] = sum(V*values)/sum(V);
446  }
447 
448  sumN_ += N_[i];
449 
450  sumV_ += N_[i]*fi.x().value();
451  }
452 
453  if (Pstream::master())
454  {
455  switch (functionType_)
456  {
457  case ftMom:
458  {
459  for (label m = 0; m <= momentOrder_; m++)
460  {
461  scalar result(0.0);
462 
463  forAll(N_, i)
464  {
466  *popBal_.sizeGroups()[i];
467 
468  switch (abszissaType_)
469  {
470  case atVolume:
471  {
472  result += pow(fi.x().value(), m)*N_[i];
473 
474  break;
475  }
476 
477  case atDiameter:
478  {
479  result += pow(fi.d().value(), m)*N_[i];
480 
481  break;
482  }
483  }
484  }
485 
486  file() << tab << result;
487  }
488 
489  break;
490  }
491 
492  default:
493  {
494  forAll(popBal_.sizeGroups(), i)
495  {
497  *popBal_.sizeGroups()[i];
498 
499  scalar result(0.0);
500  scalar delta(0.0);
501 
502  switch (abszissaType_)
503  {
504  case atVolume:
505  {
506  delta = popBal_.v()[i+1].value()
507  - popBal_.v()[i].value();
508 
509  break;
510  }
511 
512  case atDiameter:
513  {
514  const scalar& formFactor =
515  fi.VelocityGroup().formFactor().value();
516 
517  delta =
518  pow
519  (
520  popBal_.v()[i+1].value()
521  /formFactor,
522  1.0/3.0
523  )
524  - pow
525  (
526  popBal_.v()[i].value()
527  /formFactor,
528  1.0/3.0
529  );
530 
531  break;
532  }
533  }
534 
535  switch (functionType_)
536  {
537  case ftNdf:
538  {
539  if (normalize_ == true)
540  {
541  result = N_[i]/delta/sumN_;
542  }
543  else
544  {
545  result = N_[i]/delta;
546  }
547 
548  break;
549  }
550 
551  case ftVdf:
552  {
553  if (normalize_ == true)
554  {
555  result = N_[i]*fi.x().value()/delta/sumV_;
556  }
557  else
558  {
559  result = N_[i]*fi.x().value()/delta;
560  }
561 
562  break;
563  }
564 
565  case ftNc:
566  {
567  if (normalize_ == true)
568  {
569  result = N_[i]/sumN_;
570  }
571  else
572  {
573  result = N_[i];
574  }
575 
576  break;
577  }
578 
579  default:
580  {
581  break;
582  }
583  }
584 
585  file()<< tab << result;
586  }
587  }
588  }
589  }
590 
591  if (Pstream::master())
592  {
593  file()<< endl;
594  }
595 
596  Log << endl;
597 
598  return true;
599 }
600 
601 
602 // ************************************************************************* //
scalar delta
tmp< scalarField > filterField(const scalarField &field) const
Filter field according to cellIds.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
virtual bool read(const dictionary &dict)
Read the input data.
const dimensionedScalar & x() const
Return representative volume of the sizeGroup.
Definition: sizeGroupI.H:57
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const word & name() const
Return the name of this functionObject.
static const NamedEnum< regionTypes, 2 > regionTypeNames_
Region type names.
static const char tab
Definition: Ostream.H:264
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
virtual ~sizeDistribution()
Destructor.
static const NamedEnum< functionTypes, 4 > functionTypeNames_
Function type names.
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:427
void combineFields(scalarField &field)
Combine fields from all processor domains into single field.
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:421
static const NamedEnum< abszissaTypes, 2 > abszissaTypeNames_
Abszissa type names.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
virtual bool read(const dictionary &dict)
Read from dictionary.
void initialise(const dictionary &dict)
Initialise, e.g. cell addressing.
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:51
Macros for easy insertion into run-time selection tables.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:52
virtual bool read(const dictionary &)
Read optional controls.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
stressControl lookup("compactNormalStress") >> compactNormalStress
const phaseModel & phase() const
Return the phase.
dynamicFvMesh & mesh
Type gSum(const FieldField< Field, Type > &f)
This class represents a single sizeGroup belonging to a velocityGroup. The main property of a sizeGro...
Definition: sizeGroup.H:94
virtual void writeFileHeader(const label i)
Output file header information.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
scalar volume() const
Calculate and return volume of the evaluated cell zone.
virtual const word & type() const =0
Runtime type information.
const Type & value() const
Return const reference to value.
static const char nl
Definition: Ostream.H:265
const dimensionedScalar & formFactor() const
Return the form factor.
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
fileName::Type type(const fileName &, const bool followLink=true)
Return the file type: DIRECTORY or FILE.
Definition: POSIX.C:481
sizeDistribution(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
void setCellZoneCells()
Set cells to evaluate based on a cell zone.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:409
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
#define Log
Report write to Foam::Info if the local log switch is true.
abszissaTypes
abszissa type enumeration
messageStream Info
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
const dimensionedScalar & d() const
Return representative diameter of the sizeGroup.
Definition: sizeGroupI.H:50
defineTypeNameAndDebug(fvMeshFunctionObject, 0)
A class for managing temporary objects.
Definition: PtrList.H:53
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
functionTypes
Function type enumeration.
const velocityGroup & VelocityGroup() const
Return const-reference to the velocityGroup.
Definition: sizeGroupI.H:43
addToRunTimeSelectionTable(functionObject, add, dictionary)
Namespace for OpenFOAM.