All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
populationBalanceMoments.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) 2022 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 
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33 namespace functionObjects
34 {
35  defineTypeNameAndDebug(populationBalanceMoments, 0);
37  (
38  functionObject,
39  populationBalanceMoments,
40  dictionary
41  );
42 }
43 }
44 
45 
46 namespace Foam
47 {
48  template<>
49  const char* NamedEnum
50  <
52  4
53  >::names[] = {"integerMoment", "mean", "variance", "stdDev"};
54 }
55 
56 
57 const Foam::NamedEnum
58 <
60  4
61 >
63 
64 
65 namespace Foam
66 {
67  template<>
68  const char* NamedEnum
69  <
71  3
72  >::names[] = {"volume", "area", "diameter"};
73 }
74 
75 
76 const Foam::NamedEnum
77 <
79  3
80 >
82 
83 
84 namespace Foam
85 {
86  template<>
87  const char* NamedEnum
88  <
90  3
91  >::names[] =
92  {
93  "numberConcentration",
94  "volumeConcentration",
95  "areaConcentration"
96  };
97 }
98 
99 
100 const Foam::NamedEnum
101 <
103  3
104 >
106 
107 
108 namespace Foam
109 {
110  template<>
111  const char* NamedEnum
112  <
114  3
115  >::names[] = {"arithmetic", "geometric", "notApplicable"};
116 }
117 
118 
119 const Foam::NamedEnum
120 <
122  3
123 >
125 
126 
127 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
128 
130 Foam::functionObjects::populationBalanceMoments::coordinateTypeSymbolicName()
131 {
132  word coordinateTypeSymbolicName(word::null);
133 
134  switch (coordinateType_)
135  {
136  case coordinateType::volume:
137  {
138  coordinateTypeSymbolicName = "v";
139 
140  break;
141  }
142  case coordinateType::area:
143  {
144  coordinateTypeSymbolicName = "a";
145 
146  break;
147  }
148  case coordinateType::diameter:
149  {
150  coordinateTypeSymbolicName = "d";
151 
152  break;
153  }
154  }
155 
156  return coordinateTypeSymbolicName;
157 }
158 
159 
161 Foam::functionObjects::populationBalanceMoments::weightTypeSymbolicName()
162 {
163  word weightTypeSymbolicName(word::null);
164 
165  switch (weightType_)
166  {
167  case weightType::numberConcentration:
168  {
169  weightTypeSymbolicName = "N";
170 
171  break;
172  }
173  case weightType::volumeConcentration:
174  {
175  weightTypeSymbolicName = "V";
176 
177  break;
178  }
179  case weightType::areaConcentration:
180  {
181  weightTypeSymbolicName = "A";
182 
183  break;
184  }
185  }
186 
187  return weightTypeSymbolicName;
188 }
189 
190 
191 Foam::word Foam::functionObjects::populationBalanceMoments::defaultFldName()
192 {
193  word meanName
194  (
195  meanType_ == meanType::geometric
196  ? word(meanTypeNames_[meanType_]).capitalise()
197  : word("")
198  );
199 
200  return
201  word
202  (
204  (
205  "weighted"
206  + meanName
207  + word(momentTypeNames_[momentType_]).capitalise()
208  + "("
209  + weightTypeSymbolicName()
210  + ","
211  + coordinateTypeSymbolicName()
212  + ")",
213  popBal_.name()
214  )
215  );
216 }
217 
218 
220 Foam::functionObjects::populationBalanceMoments::integerMomentFldName()
221 {
222  return
223  word
224  (
226  (
227  word(momentTypeNames_[momentType_])
228  + Foam::name(order_)
229  + "("
230  + weightTypeSymbolicName()
231  + ","
232  + coordinateTypeSymbolicName()
233  + ")",
234  popBal_.name()
235  )
236  );
237 }
238 
239 
240 void Foam::functionObjects::populationBalanceMoments::setDimensions
241 (
242  volScalarField& fld,
243  momentType momType
244 )
245 {
246  switch (momType)
247  {
248  case momentType::integerMoment:
249  {
250  switch (coordinateType_)
251  {
252  case coordinateType::volume:
253  {
254  fld.dimensions().reset
255  (
256  pow(dimVolume, order_)/dimVolume
257  );
258 
259  break;
260  }
261  case coordinateType::area:
262  {
263  fld.dimensions().reset
264  (
265  pow(dimArea, order_)/dimVolume
266  );
267 
268  break;
269  }
270  case coordinateType::diameter:
271  {
272  fld.dimensions().reset
273  (
274  pow(dimLength, order_)/dimVolume
275  );
276 
277  break;
278  }
279  }
280 
281  switch (weightType_)
282  {
283  case weightType::volumeConcentration:
284  {
285  fld.dimensions().reset(fld.dimensions()*dimVolume);
286 
287  break;
288  }
289  case weightType::areaConcentration:
290  {
291  fld.dimensions().reset(fld.dimensions()*dimArea);
292 
293  break;
294  }
295  default:
296  {
297  break;
298  }
299  }
300 
301  break;
302  }
303  case momentType::mean:
304  {
305  switch (coordinateType_)
306  {
307  case coordinateType::volume:
308  {
309  fld.dimensions().reset(dimVolume);
310 
311  break;
312  }
313  case coordinateType::area:
314  {
315  fld.dimensions().reset(dimArea);
316 
317  break;
318  }
319  case coordinateType::diameter:
320  {
321  fld.dimensions().reset(dimLength);
322 
323  break;
324  }
325  }
326 
327  break;
328  }
329  case momentType::variance:
330  {
331  switch (coordinateType_)
332  {
333  case coordinateType::volume:
334  {
335  fld.dimensions().reset(sqr(dimVolume));
336 
337  break;
338  }
339  case coordinateType::area:
340  {
341  fld.dimensions().reset(sqr(dimArea));
342 
343  break;
344  }
345  case coordinateType::diameter:
346  {
347  fld.dimensions().reset(sqr(dimLength));
348 
349  break;
350  }
351  }
352 
353  if (meanType_ == meanType::geometric)
354  {
355  fld.dimensions().reset(dimless);
356  }
357 
358  break;
359  }
360  case momentType::stdDev:
361  {
362  switch (coordinateType_)
363  {
364  case coordinateType::volume:
365  {
366  fld.dimensions().reset(dimVolume);
367 
368  break;
369  }
370  case coordinateType::area:
371  {
372  fld.dimensions().reset(dimArea);
373 
374  break;
375  }
376  case coordinateType::diameter:
377  {
378  fld.dimensions().reset(dimLength);
379 
380  break;
381  }
382  }
383 
384  if (meanType_ == meanType::geometric)
385  {
386  fld.dimensions().reset(dimless);
387  }
388 
389  break;
390  }
391  }
392 }
393 
394 
396 Foam::functionObjects::populationBalanceMoments::totalConcentration()
397 {
398  tmp<volScalarField> tTotalConcentration
399  (
401  (
402  "totalConcentration",
403  mesh_,
405  )
406  );
407 
408  volScalarField& totalConcentration = tTotalConcentration.ref();
409 
410  switch (weightType_)
411  {
412  case weightType::volumeConcentration:
413  {
414  totalConcentration.dimensions().reset
415  (
416  totalConcentration.dimensions()*dimVolume
417  );
418 
419  break;
420  }
421  case weightType::areaConcentration:
422  {
423  totalConcentration.dimensions().reset
424  (
425  totalConcentration.dimensions()*dimArea
426  );
427 
428  break;
429  }
430  default:
431  {
432  break;
433  }
434  }
435 
436  forAll(popBal_.sizeGroups(), i)
437  {
438  const Foam::diameterModels::sizeGroup& fi = popBal_.sizeGroups()[i];
439 
440  switch (weightType_)
441  {
442  case weightType::numberConcentration:
443  {
444  totalConcentration += fi*fi.phase()/fi.x();
445 
446  break;
447  }
448  case weightType::volumeConcentration:
449  {
450  totalConcentration += fi*fi.phase();
451 
452  break;
453  }
454  case weightType::areaConcentration:
455  {
456  totalConcentration += fi.a()*fi*fi.phase()/fi.x();
457 
458  break;
459  }
460  }
461  }
462 
463  return tTotalConcentration;
464 }
465 
466 
468 Foam::functionObjects::populationBalanceMoments::mean()
469 {
470  tmp<volScalarField> tMean
471  (
473  (
474  "mean",
475  mesh_,
477  )
478  );
479 
480  volScalarField& mean = tMean.ref();
481 
482  setDimensions(mean, momentType::mean);
483 
484  volScalarField totalConcentration(this->totalConcentration());
485 
486  forAll(popBal_.sizeGroups(), i)
487  {
488  const Foam::diameterModels::sizeGroup& fi = popBal_.sizeGroups()[i];
489 
490  volScalarField concentration(fi*fi.phase()/fi.x());
491 
492  switch (weightType_)
493  {
494  case weightType::volumeConcentration:
495  {
496  concentration *= fi.x();
497 
498  break;
499  }
500  case weightType::areaConcentration:
501  {
502  concentration *= fi.a();
503 
504  break;
505  }
506  default:
507  {
508  break;
509  }
510  }
511 
512  switch (meanType_)
513  {
514  case meanType::geometric:
515  {
516  mean.dimensions().reset(dimless);
517 
518  switch (coordinateType_)
519  {
520  case coordinateType::volume:
521  {
522  dimensionedScalar unitVolume(dimVolume, 1);
523 
524  mean +=
525  Foam::log(fi.x()/unitVolume)
526  *concentration/totalConcentration;
527 
528  break;
529  }
530  case coordinateType::area:
531  {
532  dimensionedScalar unitArea(dimArea, 1);
533 
534  mean +=
535  Foam::log(fi.a()/unitArea)
536  *concentration/totalConcentration;
537 
538  break;
539  }
540  case coordinateType::diameter:
541  {
542  dimensionedScalar unitLength(dimLength, 1);
543 
544  mean +=
545  Foam::log(fi.d()/unitLength)
546  *concentration/totalConcentration;
547 
548  break;
549  }
550  }
551 
552  break;
553  }
554  default:
555  {
556  switch (coordinateType_)
557  {
558  case coordinateType::volume:
559  {
560  mean += fi.x()*concentration/totalConcentration;
561 
562  break;
563  }
564  case coordinateType::area:
565  {
566  mean += fi.a()*concentration/totalConcentration;
567 
568  break;
569  }
570  case coordinateType::diameter:
571  {
572  mean += fi.d()*concentration/totalConcentration;
573 
574  break;
575  }
576  }
577 
578  break;
579  }
580  }
581  }
582 
583  if (meanType_ == meanType::geometric)
584  {
585  mean = exp(mean);
586 
587  setDimensions(mean, momentType::mean);
588  }
589 
590  return tMean;
591 }
592 
593 
595 Foam::functionObjects::populationBalanceMoments::variance()
596 {
597  tmp<volScalarField> tVariance
598  (
600  (
601  "variance",
602  mesh_,
604  )
605  );
606 
607  volScalarField& variance = tVariance.ref();
608 
609  setDimensions(variance, momentType::variance);
610 
611  volScalarField totalConcentration(this->totalConcentration());
612  volScalarField mean(this->mean());
613 
614  forAll(popBal_.sizeGroups(), i)
615  {
616  const Foam::diameterModels::sizeGroup& fi = popBal_.sizeGroups()[i];
617 
618  volScalarField concentration(fi*fi.phase()/fi.x());
619 
620  switch (weightType_)
621  {
622  case weightType::volumeConcentration:
623  {
624  concentration *= fi.x();
625 
626  break;
627  }
628  case weightType::areaConcentration:
629  {
630  concentration *= fi.a();
631 
632  break;
633  }
634  default:
635  {
636  break;
637  }
638  }
639 
640  switch (meanType_)
641  {
642  case meanType::geometric:
643  {
644  switch (coordinateType_)
645  {
646  case coordinateType::volume:
647  {
648  variance +=
649  sqr(Foam::log(fi.x()/mean))
650  *concentration/totalConcentration;
651 
652  break;
653  }
654  case coordinateType::area:
655  {
656  variance +=
657  sqr(Foam::log(fi.a()/mean))
658  *concentration/totalConcentration;
659 
660  break;
661  }
662  case coordinateType::diameter:
663  {
664  variance +=
665  sqr(Foam::log(fi.d()/mean))
666  *concentration/totalConcentration;
667 
668  break;
669  }
670  }
671 
672  break;
673  }
674  default:
675  {
676  switch (coordinateType_)
677  {
678  case coordinateType::volume:
679  {
680  variance +=
681  sqr(fi.x() - mean)*concentration/totalConcentration;
682 
683 
684  break;
685  }
686  case coordinateType::area:
687  {
688  variance +=
689  sqr(fi.a() - mean)*concentration/totalConcentration;
690 
691  break;
692  }
693  case coordinateType::diameter:
694  {
695  variance +=
696  sqr(fi.d() - mean)*concentration/totalConcentration;
697 
698  break;
699  }
700  }
701 
702  break;
703  }
704  }
705  }
706 
707  return tVariance;
708 }
709 
710 
712 Foam::functionObjects::populationBalanceMoments::stdDev()
713 {
714  switch (meanType_)
715  {
716  case meanType::geometric:
717  {
718  return exp(sqrt(this->variance()));
719  }
720  default:
721  {
722  return sqrt(this->variance());
723  }
724  }
725 }
726 
727 
728 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
729 
731 (
732  const word& name,
733  const Time& runTime,
734  const dictionary& dict
735 )
736 :
737  fvMeshFunctionObject(name, runTime, dict),
738  popBal_
739  (
740  obr_.lookupObject<Foam::diameterModels::populationBalanceModel>
741  (
742  dict.lookup("populationBalance")
743  )
744  ),
745  momentType_(momentTypeNames_.read(dict.lookup("momentType"))),
746  coordinateType_(coordinateTypeNames_.read(dict.lookup("coordinateType"))),
747  weightType_
748  (
749  dict.found("weightType")
750  ? weightTypeNames_.read(dict.lookup("weightType"))
751  : weightType::numberConcentration
752  ),
753  meanType_(meanType::notApplicable),
754  order_(-1),
755  fldPtr_(nullptr)
756 {
757  read(dict);
758 }
759 
760 
761 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
762 
764 {}
765 
766 
767 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
768 
769 bool
771 {
773 
774  switch (momentType_)
775  {
776  case momentType::integerMoment:
777  {
778  order_ = dict.lookup<int>("order");
779 
780  break;
781  }
782  default:
783  {
784  meanType_ =
785  dict.found("meanType")
786  ? meanTypeNames_.read(dict.lookup("meanType"))
787  : meanType::arithmetic;
788 
789  break;
790  }
791  }
792 
793  switch (momentType_)
794  {
795  case momentType::integerMoment:
796  {
797  fldPtr_.set
798  (
799  new volScalarField
800  (
801  IOobject
802  (
803  this->integerMomentFldName(),
804  mesh_.time().timeName(),
805  mesh_,
808  ),
809  mesh_,
811  )
812  );
813 
814  volScalarField& integerMoment = fldPtr_();
815 
816  setDimensions(integerMoment, momentType::integerMoment);
817 
818  break;
819  }
820  case momentType::mean:
821  {
822  fldPtr_.set
823  (
824  new volScalarField
825  (
826  IOobject
827  (
828  this->defaultFldName(),
829  mesh_.time().timeName(),
830  mesh_,
833  ),
834  this->mean()
835  )
836  );
837 
838  break;
839  }
840  case momentType::variance:
841  {
842  fldPtr_.set
843  (
844  new volScalarField
845  (
846  IOobject
847  (
848  this->defaultFldName(),
849  mesh_.time().timeName(),
850  mesh_,
853  ),
854  this->variance()
855  )
856  );
857 
858  break;
859  }
860  case momentType::stdDev:
861  {
862  fldPtr_.set
863  (
864  new volScalarField
865  (
866  IOobject
867  (
868  this->defaultFldName(),
869  mesh_.time().timeName(),
870  mesh_,
873  ),
874  this->stdDev()
875  )
876  );
877 
878  break;
879  }
880  }
881 
882  return true;
883 }
884 
885 
887 {
888  switch (momentType_)
889  {
890  case momentType::integerMoment:
891  {
892  volScalarField& integerMoment = fldPtr_();
893 
894  integerMoment = Zero;
895 
896  forAll(popBal_.sizeGroups(), i)
897  {
899  popBal_.sizeGroups()[i];
900 
901  volScalarField concentration(fi*fi.phase()/fi.x());
902 
903  switch (weightType_)
904  {
905  case weightType::volumeConcentration:
906  {
907  concentration *= fi.x();
908 
909  break;
910  }
911  case weightType::areaConcentration:
912  {
913  concentration *= fi.a();
914 
915  break;
916  }
917  default:
918  {
919  break;
920  }
921  }
922 
923  switch (coordinateType_)
924  {
925  case coordinateType::volume:
926  {
927  integerMoment +=
928  pow(fi.x(), order_)*concentration;
929 
930  break;
931  }
932  case coordinateType::area:
933  {
934  integerMoment +=
935  pow(fi.a(), order_)*concentration;
936 
937  break;
938  }
939  case coordinateType::diameter:
940  {
941  integerMoment +=
942  pow(fi.d(), order_)*concentration;
943 
944  break;
945  }
946  }
947  }
948 
949  break;
950  }
951  case momentType::mean:
952  {
953  fldPtr_() = this->mean();
954 
955  break;
956  }
957  case momentType::variance:
958  {
959  fldPtr_() = this->variance();
960 
961  break;
962  }
963  case momentType::stdDev:
964  {
965  fldPtr_() = sqrt(this->variance());
966 
967  break;
968  }
969  }
970 
971  return true;
972 }
973 
974 
976 {
977  writeObject(fldPtr_->name());
978 
979  return true;
980 }
981 
982 
983 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
const dimensionSet dimArea
const dimensionedScalar & x() const
Return representative volume of the sizeGroup.
Definition: sizeGroupI.H:57
virtual bool read(const dictionary &)
Read the data.
dimensionedScalar log(const dimensionedScalar &ds)
bool writeObject(const word &fieldName)
Write field if present in objectRegistry.
virtual bool write()
Write the moment fields.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
addToRunTimeSelectionTable(functionObject, Qdot, dictionary)
populationBalanceMoments(const word &name, const Time &runTime, const dictionary &)
Construct from Time and dictionary.
static tmp< GeometricField< scalar, fvPatchField, volMesh > > New(const word &name, const Internal &, const PtrList< fvPatchField< scalar >> &)
Return a temporary field constructed from name,.
dimensionedScalar sqrt(const dimensionedScalar &ds)
static const NamedEnum< momentType, 4 > momentTypeNames_
Names of the moment types.
const tmp< volScalarField > d() const
Return representative diameter of the sizeGroup.
const dimensionSet dimless
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:372
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.
const dimensionSet dimLength
static const NamedEnum< coordinateType, 3 > coordinateTypeNames_
Names of the coordinate types.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:58
const tmp< volScalarField > a() const
Return representative surface area of the sizeGroup.
static const NamedEnum< meanType, 3 > meanTypeNames_
Names of the mean types.
const dimensionSet & dimensions() const
Return dimensions.
virtual bool read(const dictionary &)
Read optional controls.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
stressControl lookup("compactNormalStress") >> compactNormalStress
dimensionedScalar exp(const dimensionedScalar &ds)
Single size class fraction field representing a fixed particle volume as defined by the user through ...
Definition: sizeGroup.H:99
static word timeName(const scalar, const int precision=curPrecision_)
Return time name of given scalar time.
Definition: Time.C:666
A class for handling words, derived from string.
Definition: word.H:59
static word groupName(Name name, const word &group)
static const NamedEnum< weightType, 3 > weightTypeNames_
Names of the weight types.
static const word null
An empty word.
Definition: word.H:77
static const zero Zero
Definition: zero.H:97
coordinateType
Enumeration for the coordinate types.
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
defineTypeNameAndDebug(Qdot, 0)
Internal & ref()
Return a reference to the dimensioned internal field.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
void reset(const dimensionSet &)
Definition: dimensionSet.C:108
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const dimensionSet dimVolume
A class for managing temporary objects.
Definition: PtrList.H:53
bool found
const fvMesh & mesh_
Reference to the fvMesh.
virtual bool execute()
Calculate the moment fields.
Namespace for OpenFOAM.