All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BlendedInterfacialModel.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) 2014-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 
27 #include "phaseSystem.H"
31 #include "surfaceInterpolate.H"
32 #include "zeroDimensionalFvMesh.H"
33 #include "mathematicalConstants.H"
34 #include "writeFile.H"
35 #include "triFace.H"
36 #include "noSetWriter.H"
37 #include "noSurfaceWriter.H"
38 
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 namespace blendedInterfacialModel
44 {
45 
46 template<class GeoField>
47 inline tmp<GeoField> interpolate(tmp<volScalarField> f);
48 
49 template<>
50 inline tmp<Foam::volScalarField> interpolate(tmp<volScalarField> f)
51 {
52  return f;
53 }
54 
55 template<>
56 inline tmp<Foam::surfaceScalarField> interpolate(tmp<volScalarField> f)
57 {
58  return fvc::interpolate(f);
59 }
60 
61 template<class ModelType>
62 inline bool valid(const PtrList<ModelType>& l)
63 {
64  forAll(l, i)
65  {
66  if (l.set(i))
67  {
68  return true;
69  }
70  }
71  return false;
72 }
73 
74 } // End namespace blendedInterfacialModel
75 } // End namespace Foam
76 
77 
78 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
79 
80 template<class ModelType>
82 {
83  // Only generate warnings once per timestep
84  const label timeIndex = interface_.mesh().time().timeIndex();
85  if (checkTimeIndex_ == timeIndex) return;
86  checkTimeIndex_ = timeIndex;
87 
88  const phaseModel& phase1 = interface_.phase1();
89  const phaseModel& phase2 = interface_.phase2();
90 
91  const bool can1In2 = blending_->canBeContinuous(1);
92  const bool can2In1 = blending_->canBeContinuous(0);
93  const bool canS = blending_->canSegregate();
94 
95  // Warnings associated with redundant model specification
96 
97  if
98  (
99  !can1In2
100  && (
101  model1DispersedIn2_.valid()
102  || blendedInterfacialModel::valid(models1DispersedIn2Displaced_)
103  )
104  )
105  {
107  << "A " << ModelType::typeName << " was provided for "
108  << dispersedPhaseInterface(phase1, phase2).name()
109  << " but the associated blending does not permit " << phase2.name()
110  << " to be continuous so this model will not be used" << endl;
111  }
112 
113  if
114  (
115  !can2In1
116  && (
117  model2DispersedIn1_.valid()
118  || blendedInterfacialModel::valid(models2DispersedIn1Displaced_)
119  )
120  )
121  {
123  << "A " << ModelType::typeName << " was provided for "
124  << dispersedPhaseInterface(phase2, phase1).name()
125  << " but the associated blending does not permit " << phase1.name()
126  << " to be continuous so this model will not be used" << endl;
127  }
128 
129  if
130  (
131  !canS
132  && (
133  model1SegregatedWith2_.valid()
134  || blendedInterfacialModel::valid(models1SegregatedWith2Displaced_)
135  )
136  )
137  {
139  << "A " << ModelType::typeName << " was provided for "
140  << segregatedPhaseInterface(phase1, phase2).name()
141  << " but the associated blending does not permit segregation"
142  << " so this model will not be used" << endl;
143  }
144 
145  if
146  (
147  modelGeneral_.valid()
148  && (can1In2 || can2In1 || canS)
149  && (!can1In2 || model1DispersedIn2_.valid())
150  && (!can2In1 || model2DispersedIn1_.valid())
151  && (!canS || model1SegregatedWith2_.valid())
152  )
153  {
155  << "A " << ModelType::typeName << " was provided for "
156  << phaseInterface(phase1, phase2).name()
157  << " but other displaced and/or segregated models apply"
158  << " across the entire phase fraction space so this model"
159  << " will not be used" << endl;
160  }
161 
162  forAll(interface_.fluid().phases(), phasei)
163  {
164  const phaseModel& phaseD = interface_.fluid().phases()[phasei];
165 
166  if
167  (
168  modelsGeneralDisplaced_.set(phasei)
169  && (can1In2 || can2In1 || canS)
170  && (!can1In2 || models1DispersedIn2Displaced_.set(phasei))
171  && (!can2In1 || models2DispersedIn1Displaced_.set(phasei))
172  && (!canS || models1SegregatedWith2Displaced_.set(phasei))
173  )
174  {
176  << "A " << ModelType::typeName << " was provided for "
177  << displacedPhaseInterface(phase1, phase2, phaseD).name()
178  << " but other displaced and/or segregated models apply"
179  << " across the entire phase fraction space so this model"
180  << " will not be used" << endl;
181  }
182  }
183 
184  // Warnings associated with gaps in the blending space
185 
186  if (can1In2 && !modelGeneral_.valid() && !model1DispersedIn2_.valid())
187  {
189  << "Blending for " << ModelType::typeName << "s permits "
190  << phase2.name() << " to become continuous, but no model was "
191  << "provided for " << dispersedPhaseInterface(phase1, phase2).name()
192  << ". Consider adding a model for this configuration (or for "
193  << phaseInterface(phase1, phase2).name() << "), or if no model is "
194  << "needed then add a \"none\" model to suppress this warning."
195  << endl;
196  }
197 
198  if (can2In1 && !modelGeneral_.valid() && !model2DispersedIn1_.valid())
199  {
201  << "Blending for " << ModelType::typeName << "s permits "
202  << phase1.name() << " to become continuous, but no model was "
203  << "provided for " << dispersedPhaseInterface(phase2, phase1).name()
204  << ". Consider adding a model for this configuration (or for "
205  << phaseInterface(phase1, phase2).name() << "), or if no model is "
206  << "needed then add a \"none\" model to suppress this warning."
207  << endl;
208  }
209 
210  if (canS && !modelGeneral_.valid() && !model1SegregatedWith2_.valid())
211  {
213  << "Blending for " << ModelType::typeName << "s permits "
214  << "segregation but no model was provided for "
215  << segregatedPhaseInterface(phase2, phase1).name()
216  << ". Consider adding a model for this configuration (or for "
217  << phaseInterface(phase1, phase2).name() << "), or if no model is "
218  << "needed then add a \"none\" model to suppress this warning."
219  << endl;
220  }
221 }
222 
223 
224 template<class ModelType>
225 template<template<class> class PatchField, class GeoMesh>
227 (
228  const UPtrList<const volScalarField>& alphas,
229  tmp<GeometricField<scalar, PatchField, GeoMesh>>& fG,
230  tmp<GeometricField<scalar, PatchField, GeoMesh>>& f1D2,
231  tmp<GeometricField<scalar, PatchField, GeoMesh>>& f2D1,
232  tmp<GeometricField<scalar, PatchField, GeoMesh>>& fS,
233  PtrList<GeometricField<scalar, PatchField, GeoMesh>>& fGD,
234  PtrList<GeometricField<scalar, PatchField, GeoMesh>>& f1D2D,
235  PtrList<GeometricField<scalar, PatchField, GeoMesh>>& f2D1D,
236  PtrList<GeometricField<scalar, PatchField, GeoMesh>>& fSD,
237  const bool subtract
238 ) const
239 {
240  typedef GeometricField<scalar, PatchField, GeoMesh> scalarGeoField;
241 
242  // Create a constant field
243  auto constant = [&](const scalar k)
244  {
245  return
247  (
248  Foam::name(k),
249  alphas.first().mesh(),
251  );
252  };
253 
254  // Get the dispersed blending functions
255  tmp<scalarGeoField> F1D2, F2D1;
256  if
257  (
258  model1DispersedIn2_.valid()
259  || model1SegregatedWith2_.valid()
260  || blendedInterfacialModel::valid(models1DispersedIn2Displaced_)
261  || blendedInterfacialModel::valid(models1SegregatedWith2Displaced_)
262  )
263  {
264  F1D2 =
265  blendedInterfacialModel::interpolate<scalarGeoField>
266  (
267  blending_->f1DispersedIn2(alphas)
268  );
269  }
270  if
271  (
272  model2DispersedIn1_.valid()
273  || model1SegregatedWith2_.valid()
274  || blendedInterfacialModel::valid(models2DispersedIn1Displaced_)
275  || blendedInterfacialModel::valid(models1SegregatedWith2Displaced_)
276  )
277  {
278  F2D1 =
279  blendedInterfacialModel::interpolate<scalarGeoField>
280  (
281  blending_->f2DispersedIn1(alphas)
282  );
283  }
284 
285  // Construct non-displaced coefficients
286  {
287  if (model1DispersedIn2_.valid())
288  {
289  f1D2 = F1D2().clone();
290  }
291 
292  if (model2DispersedIn1_.valid())
293  {
294  f2D1 = F2D1().clone();
295  }
296 
297  if (model1SegregatedWith2_.valid())
298  {
299  fS = constant(1);
300  if (f1D2.valid()) { fS.ref() -= f1D2(); }
301  if (f2D1.valid()) { fS.ref() -= f2D1(); }
302  }
303 
304  if (modelGeneral_.valid())
305  {
306  fG = constant(1);
307  if (f1D2.valid()) { fG.ref() -= f1D2(); }
308  if (f2D1.valid()) { fG.ref() -= f2D1(); }
309  if (fS.valid()) { fG.ref() -= fS(); }
310  }
311  }
312 
313  // Get the displaced blending function
314  tmp<scalarGeoField> FD;
315  if
316  (
317  blendedInterfacialModel::valid(modelsGeneralDisplaced_)
318  || blendedInterfacialModel::valid(models1DispersedIn2Displaced_)
319  || blendedInterfacialModel::valid(models2DispersedIn1Displaced_)
320  || blendedInterfacialModel::valid(models1SegregatedWith2Displaced_)
321  )
322  {
323  FD =
324  blendedInterfacialModel::interpolate<scalarGeoField>
325  (
326  blending_->fDisplaced(alphas)
327  );
328  }
329 
330  // Construct displaced coefficients
331  tmp<scalarGeoField> fDSum;
332  if
333  (
334  blendedInterfacialModel::valid(modelsGeneralDisplaced_)
335  || blendedInterfacialModel::valid(models1DispersedIn2Displaced_)
336  || blendedInterfacialModel::valid(models2DispersedIn1Displaced_)
337  || blendedInterfacialModel::valid(models1SegregatedWith2Displaced_)
338  )
339  {
340  fDSum = constant(0);
341 
342  forAll(alphas, phasei)
343  {
344  const phaseModel& phaseD = interface_.fluid().phases()[phasei];
345 
346  if (interface_.contains(phaseD)) continue;
347 
348  // Weight the contribution of a dispersed model for this phase
349  // according to the phase fraction in the subset of phases that are
350  // not part of this interface. This seems like a reasonable
351  // assumption if a stochastic viewpoint is taken. However, it is
352  // possible that other forms may be desired in which case this
353  // could be abstracted and controlled by the blending method.
354  tmp<scalarGeoField> alpha;
355  if
356  (
357  models1DispersedIn2Displaced_.set(phasei)
358  || models2DispersedIn1Displaced_.set(phasei)
359  || models1SegregatedWith2Displaced_.set(phasei)
360  || modelsGeneralDisplaced_.set(phasei)
361  )
362  {
363  alpha =
364  blendedInterfacialModel::interpolate<scalarGeoField>
365  (
366  alphas[phasei]
367  /max
368  (
369  1
370  - alphas[interface_.phase1().index()]
371  - alphas[interface_.phase2().index()],
372  phaseD.residualAlpha()
373  )
374  );
375  }
376 
377  if (models1DispersedIn2Displaced_.set(phasei))
378  {
379  f1D2D.set(phasei, alpha()*FD()*F1D2());
380  fDSum.ref() += f1D2D[phasei];
381  }
382 
383  if (models2DispersedIn1Displaced_.set(phasei))
384  {
385  f2D1D.set(phasei, alpha()*FD()*F2D1());
386  fDSum.ref() += f2D1D[phasei];
387  }
388 
389  if (models1SegregatedWith2Displaced_.set(phasei))
390  {
391  fSD.set(phasei, alpha()*FD());
392  if (f1D2D.set(phasei)) fSD[phasei] -= f1D2D[phasei];
393  if (f2D1D.set(phasei)) fSD[phasei] -= f2D1D[phasei];
394  fDSum.ref() += fSD[phasei];
395  }
396 
397  if (modelsGeneralDisplaced_.set(phasei))
398  {
399  fGD.set(phasei, alpha()*FD());
400  if (f1D2D.set(phasei)) fGD[phasei] -= f1D2D[phasei];
401  if (f2D1D.set(phasei)) fGD[phasei] -= f2D1D[phasei];
402  if (fSD.set(phasei)) fGD[phasei] -= fSD[phasei];
403  fDSum.ref() += fGD[phasei];
404  }
405  }
406  }
407 
408  // Remove the displaced part from the non-displaced coefficients
409  if (fDSum.valid())
410  {
411  if (f1D2.valid()) f1D2.ref() *= 1 - fDSum();
412  if (f2D1.valid()) f2D1.ref() *= 1 - fDSum();
413  if (fS.valid()) fS.ref() *= 1 - fDSum();
414  if (fG.valid()) fG.ref() *= 1 - fDSum();
415  }
416 
417  // Flip the sign of the 2 dispersed in 1 models if necessary
418  if (subtract)
419  {
420  auto signedError = [this](const phaseInterface& interface)
421  {
423  << "A signed quantity was evaluated from the blended "
424  << ModelType::typeName << " for " << interface_.name()
425  << " but a model was provided for " << interface.name()
426  << ". Signed quantities are only possible to evaluate for"
427  << " dispersed configurations" << exit(FatalError);
428  };
429 
430  const phaseModel& phase1 = interface_.phase1();
431  const phaseModel& phase2 = interface_.phase2();
432 
433  if (fG.valid())
434  {
435  signedError(phaseInterface(phase1, phase2));
436  }
437  if (f1D2.valid())
438  {
439  // Do nothing
440  }
441  if (f2D1.valid())
442  {
443  f2D1.ref() *= -1;
444  }
445  if (fS.valid())
446  {
447  signedError(segregatedPhaseInterface(phase1, phase2));
448  }
449 
450  forAll(alphas, phasei)
451  {
452  const phaseModel& phaseD = interface_.fluid().phases()[phasei];
453 
454  if (fGD.set(phasei))
455  {
456  signedError
457  (
458  displacedPhaseInterface(phase1, phase2, phaseD)
459  );
460  }
461  if (f1D2D.set(phasei))
462  {
463  // Do nothing
464  }
465  if (f2D1D.set(phasei))
466  {
467  f2D1.ref() *= -1;
468  }
469  if (fSD.set(phasei))
470  {
471  signedError
472  (
473  segregatedDisplacedPhaseInterface(phase1, phase2, phaseD)
474  );
475  }
476  }
477  }
478 }
479 
480 
481 template<class ModelType>
482 template<class Type, template<class> class PatchField, class GeoMesh>
484 (
485  GeometricField<Type, PatchField, GeoMesh>& field
486 ) const
487 {
488  typedef GeometricField<Type, PatchField, GeoMesh> typeGeoField;
489 
490  typename typeGeoField::Boundary& fieldBf = field.boundaryFieldRef();
491 
492  forAll(fieldBf, patchi)
493  {
494  if
495  (
496  (
497  !interface_.phase1().stationary()
498  && isA<fixedValueFvsPatchScalarField>
499  (
500  interface_.phase1().phi()().boundaryField()[patchi]
501  )
502  )
503  || (
504  !interface_.phase2().stationary()
505  && isA<fixedValueFvsPatchScalarField>
506  (
507  interface_.phase2().phi()().boundaryField()[patchi]
508  )
509  )
510  )
511  {
512  fieldBf[patchi] = Zero;
513  }
514  }
515 }
516 
517 
518 template<class ModelType>
520 (
521  const word& format
522 ) const
523 {
524  using namespace constant::mathematical;
525 
526  const phaseSystem& fluid = interface_.fluid();
527  const label nPhases = fluid.phases().size();
528 
529  // Construct geometry and phase fraction values
531  faceList faces;
532  wordList fieldNames(nPhases);
533  PtrList<scalarField> fields(nPhases);
534  if (nPhases == 1)
535  {
536  // Single value
537  fieldNames[0] = fluid.phases()[0].volScalarField::name();
538  fields.set(0, new scalarField(1, 1));
539  }
540  else if (nPhases == 2)
541  {
542  // Single axis, using the first phase as the x-coordinate
543  static const label nDivisions = 128;
544  const scalarField divisionis(scalarList(identity(nDivisions)));
545  fieldNames[0] = fluid.phases()[0].volScalarField::name();
546  fieldNames[1] = fluid.phases()[1].volScalarField::name();
547  fields.set(0, new scalarField(divisionis/(nDivisions - 1)));
548  fields.set(1, new scalarField(1 - fields[0]));
549  }
550  else
551  {
552  // Polygon with as many vertices as there are phases. Each phase
553  // fraction equals one at a unique vertex, they vary linearly between
554  // vertices, and vary smoothly in the interior of the polygon. The sum
555  // of phase fractions is always one throughout the polygon (partition
556  // of unity). This is done using Wachspress coordinates. This does not
557  // cover the entire N-dimensional phase fraction space for N >= 4 (it's
558  // hard to imagine how that could be visualised) but it provides enough
559  // to give a good indication of what is going on.
560 
561  // Create the nodes of the blending space polygon
562  List<point> phaseNodes(nPhases);
563  forAll(phaseNodes, phasei)
564  {
565  const scalar theta = 2*pi*phasei/nPhases;
566  phaseNodes[phasei] = point(cos(theta), sin(theta), 0);
567  }
568 
569  // Create points within the polygon
570  static const label nDivisions = 32;
571  points.append(point::zero);
572  for (label divi = 0; divi < nDivisions; ++ divi)
573  {
574  const scalar s = scalar(divi + 1)/nDivisions;
575 
576  forAll(phaseNodes, phasei)
577  {
578  for (label i = 0; i < divi + 1; ++ i)
579  {
580  const scalar t = scalar(i)/(divi + 1);
581 
582  points.append
583  (
584  s*(1 - t)*phaseNodes[phasei]
585  + s*t*phaseNodes[(phasei + 1) % nPhases]
586  );
587  }
588  }
589  }
590 
591  // Create triangles within the polygon
592  forAll(phaseNodes, phasei)
593  {
594  faces.append(triFace(0, phasei + 1, (phasei + 1) % nPhases + 1));
595  }
596  for (label divi = 1; divi < nDivisions; ++ divi)
597  {
598  const label pointi0 = nPhases*(divi - 1)*divi/2 + 1;
599  const label pointi1 = nPhases*divi*(divi + 1)/2 + 1;
600 
601  forAll(phaseNodes, phasei)
602  {
603  for (label i = 0; i < divi + 1; ++ i)
604  {
605  const label pi00 =
606  pointi0
607  + ((phasei*divi + i) % (nPhases*divi));
608  const label pi01 =
609  pointi0
610  + ((phasei*divi + i + 1) % (nPhases*divi));
611  const label pi10 =
612  pointi1
613  + ((phasei*(divi + 1) + i) % (nPhases*(divi + 1)));
614  const label pi11 =
615  pointi1
616  + ((phasei*(divi + 1) + i + 1) % (nPhases*(divi + 1)));
617 
618  faces.append(triFace({pi00, pi10, pi11}));
619  if (i < divi) faces.append(triFace({pi00, pi11, pi01}));
620  }
621  }
622  }
623 
624  // Create phase fraction fields
625  forAll(fluid.phases(), phasei)
626  {
627  fieldNames[phasei] = fluid.phases()[phasei].volScalarField::name();
628  fields.set(phasei, new scalarField(points.size(), 0));
629 
630  const label phasei0 = (phasei + nPhases - 1) % nPhases;
631  const label phasei1 = (phasei + 1) % nPhases;
632 
633  const point& node0 = phaseNodes[phasei0];
634  const point& node = phaseNodes[phasei];
635  const point& node1 = phaseNodes[phasei1];
636 
637  forAll(points, i)
638  {
639  const scalar A = mag((node - node0) ^ (node1 - node0));
640  const scalar A0 = mag((node - node0) ^ (points[i] - node0));
641  const scalar A1 = mag((node1 - node) ^ (points[i] - node));
642 
643  if (A0 < rootSmall)
644  {
645  fields[phasei][i] =
646  great*mag(points[i] - node0)/mag(node - node0);
647  }
648  else if (A1 < rootSmall)
649  {
650  fields[phasei][i] =
651  great*mag(points[i] - node1)/mag(node - node1);
652  }
653  else
654  {
655  fields[phasei][i] = A/A0/A1;
656  }
657  }
658  }
659  forAll(points, i)
660  {
661  scalar s = 0;
662  forAll(fluid.phases(), phasei)
663  {
664  s += fields[phasei][i];
665  }
666  forAll(fluid.phases(), phasei)
667  {
668  fields[phasei][i] /= s;
669  }
670  }
671  }
672 
673  // Add the model coefficient fields
674  {
675  // Create alpha fields on a zero-dimensional one-cell mesh
676  const fvMesh mesh(zeroDimensionalFvMesh(fluid.mesh()));
677  PtrList<volScalarField> alphas(nPhases);
678  forAll(fluid.phases(), phasei)
679  {
680  alphas.set
681  (
682  phasei,
683  new volScalarField
684  (
685  IOobject
686  (
687  fluid.phases()[phasei].volScalarField::name(),
688  mesh.time().timeName(),
689  mesh
690  ),
691  mesh,
692  dimensionedScalar(dimless, fields[phasei][0])
693  )
694  );
695  }
696 
697  // Construct blending coefficient fields
698  {
699  tmp<volScalarField> fG, f1D2, f2D1, fS;
700  PtrList<volScalarField> fGD(nPhases);
701  PtrList<volScalarField> f1D2D(nPhases);
702  PtrList<volScalarField> f2D1D(nPhases);
703  PtrList<volScalarField> fSD(nPhases);
704  calculateBlendingCoeffs
705  (
706  alphas.convert<const volScalarField>(),
707  fG, f1D2, f2D1, fS,
708  fGD, f1D2D, f2D1D, fSD,
709  false
710  );
711 
712  const phaseModel& phase1 = interface_.phase1();
713  const phaseModel& phase2 = interface_.phase2();
714 
715  auto addField = [&](const phaseInterface& interface)
716  {
717  fieldNames.append(interface.name());
718  fields.append(new scalarField(fields.first().size()));
719  };
720 
721  if (fG.valid())
722  {
723  addField(phaseInterface(phase1, phase2));
724  }
725  if (f1D2.valid())
726  {
727  addField(dispersedPhaseInterface(phase1, phase2));
728  }
729  if (f2D1.valid())
730  {
731  addField(dispersedPhaseInterface(phase2, phase1));
732  }
733  if (fS.valid())
734  {
735  addField(segregatedPhaseInterface(phase2, phase1));
736  }
737 
738  forAll(fluid.phases(), phasei)
739  {
740  const phaseModel& phaseD = fluid.phases()[phasei];
741 
742  if (fGD.set(phasei))
743  {
744  addField(displacedPhaseInterface(phase1, phase2, phaseD));
745  }
746  if (f1D2D.set(phasei))
747  {
748  addField
749  (
750  dispersedDisplacedPhaseInterface
751  (
752  phase1,
753  phase2,
754  phaseD
755  )
756  );
757  }
758  if (f2D1D.set(phasei))
759  {
760  addField
761  (
762  dispersedDisplacedPhaseInterface
763  (
764  phase2,
765  phase1,
766  phaseD
767  )
768  );
769  }
770  if (fSD.set(phasei))
771  {
772  addField
773  (
774  segregatedDisplacedPhaseInterface
775  (
776  phase1,
777  phase2,
778  phaseD
779  )
780  );
781  }
782  }
783  }
784 
785  // Populate blending coefficient fields
786  forAll(fields.first(), i)
787  {
788  forAll(fluid.phases(), phasei)
789  {
790  alphas[phasei] = fields[phasei][i];
791  }
792 
793  tmp<volScalarField> fG, f1D2, f2D1, fS;
794  PtrList<volScalarField> fGD(nPhases);
795  PtrList<volScalarField> f1D2D(nPhases);
796  PtrList<volScalarField> f2D1D(nPhases);
797  PtrList<volScalarField> fSD(nPhases);
798  calculateBlendingCoeffs
799  (
800  alphas.convert<const volScalarField>(),
801  fG, f1D2, f2D1, fS,
802  fGD, f1D2D, f2D1D, fSD,
803  false
804  );
805 
806  label fieldi = nPhases;
807 
808  if (fG.valid())
809  {
810  fields[fieldi ++][i] = fG()[0];
811  }
812  if (f1D2.valid())
813  {
814  fields[fieldi ++][i] = f1D2()[0];
815  }
816  if (f2D1.valid())
817  {
818  fields[fieldi ++][i] = f2D1()[0];
819  }
820  if (fS.valid())
821  {
822  fields[fieldi ++][i] = fS()[0];
823  }
824 
825  forAll(fluid.phases(), phasei)
826  {
827  if (fGD.set(phasei))
828  {
829  fields[fieldi ++][i] = fGD[phasei][0];
830  }
831  if (f1D2D.set(phasei))
832  {
833  fields[fieldi ++][i] = f1D2D[phasei][0];
834  }
835  if (f2D1D.set(phasei))
836  {
837  fields[fieldi ++][i] = f2D1D[phasei][0];
838  }
839  if (fSD.set(phasei))
840  {
841  fields[fieldi ++][i] = fSD[phasei][0];
842  }
843  }
844  }
845  }
846 
847  // Write
848  const fileName path =
849  fluid.mesh().time().globalPath()
851  /ModelType::typeName;
852  Info<< "Writing blending coefficients to " << path/interface_.name()
853  << endl;
854  if (nPhases <= 2)
855  {
856  // Strip out the first field and shuffle everything else up
857  const autoPtr<scalarField> field0 = fields.set(0, nullptr);
858  const word field0Name = fieldNames[0];
859  for (label fieldi = 1; fieldi < fields.size(); ++ fieldi)
860  {
861  fields.set(fieldi - 1, fields.set(fieldi, nullptr).ptr());
862  fieldNames[fieldi - 1] = fieldNames[fieldi];
863  }
864  fields.resize(fields.size() - 1);
866 
868  (
869  format,
872  )->write
873  (
874  path,
875  interface_.name(),
876  coordSet(true, field0Name, field0),
877  fieldNames,
878  fields
879  );
880  }
881  else
882  {
884  (
885  format,
888  )->write
889  (
890  path,
891  interface_.name(),
892  points,
893  faces,
894  true,
895  fieldNames,
896  fields
897  );
898  }
899 }
900 
901 
902 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
903 
904 template<class ModelType>
905 template
906 <
907  class Type,
908  template<class> class PatchField,
909  class GeoMesh,
910  class ... Args
911 >
914 (
915  tmp<GeometricField<Type, PatchField, GeoMesh>>
916  (ModelType::*method)(Args ...) const,
917  const word& name,
918  const dimensionSet& dims,
919  const bool subtract,
920  Args ... args
921 ) const
922 {
923  check();
924 
925  typedef GeometricField<scalar, PatchField, GeoMesh> scalarGeoField;
926  typedef GeometricField<Type, PatchField, GeoMesh> typeGeoField;
927 
928  // Get the blending coefficients
929  const label nPhases = interface_.fluid().phases().size();
930  tmp<scalarGeoField> fG, f1D2, f2D1, fS;
931  PtrList<scalarGeoField> fGD(nPhases);
932  PtrList<scalarGeoField> f1D2D(nPhases);
933  PtrList<scalarGeoField> f2D1D(nPhases);
934  PtrList<scalarGeoField> fSD(nPhases);
935  calculateBlendingCoeffs
936  (
937  interface_.fluid().phases().template convert<const volScalarField>(),
938  fG, f1D2, f2D1, fS,
939  fGD, f1D2D, f2D1D, fSD,
940  subtract
941  );
942 
943  // Construct the result
944  tmp<typeGeoField> x =
946  (
947  ModelType::typeName + ":"
948  + IOobject::groupName(name, interface_.name()),
949  interface_.mesh(),
950  dimensioned<Type>(dims, Zero)
951  );
952 
953  // Add the model contributions to the result
954  if (modelGeneral_.valid())
955  {
956  x.ref() += fG*(modelGeneral_().*method)(args ...);
957  }
958  if (model1DispersedIn2_.valid())
959  {
960  x.ref() += f1D2*(model1DispersedIn2_().*method)(args ...);
961  }
962  if (model2DispersedIn1_.valid())
963  {
964  x.ref() += f2D1*(model2DispersedIn1_().*method)(args ...);
965  }
966  if (model1SegregatedWith2_.valid())
967  {
968  x.ref() += fS*(model1SegregatedWith2_().*method)(args ...);
969  }
970  forAll(interface_.fluid().phases(), phasei)
971  {
972  if (modelsGeneralDisplaced_.set(phasei))
973  {
974  x.ref() +=
975  fGD[phasei]
976  *(modelsGeneralDisplaced_[phasei].*method)(args ...);
977  }
978  if (models1DispersedIn2Displaced_.set(phasei))
979  {
980  x.ref() +=
981  f1D2D[phasei]
982  *(models1DispersedIn2Displaced_[phasei].*method)(args ...);
983  }
984  if (models2DispersedIn1Displaced_.set(phasei))
985  {
986  x.ref() +=
987  f2D1D[phasei]
988  *(models2DispersedIn1Displaced_[phasei].*method)(args ...);
989  }
990  if (models1SegregatedWith2Displaced_.set(phasei))
991  {
992  x.ref() +=
993  fSD[phasei]
994  *(models1SegregatedWith2Displaced_[phasei].*method)(args ...);
995  }
996  }
997 
998  // Correct boundary conditions if necessary
999  if (ModelType::correctFixedFluxBCs)
1000  {
1001  correctFixedFluxBCs(x.ref());
1002  }
1003 
1004  return x;
1005 }
1006 
1007 
1008 template<class ModelType>
1009 template
1010 <
1011  class Type,
1012  template<class> class PatchField,
1013  class GeoMesh,
1014  class ... Args
1015 >
1018 (
1019  HashPtrTable<GeometricField<Type, PatchField, GeoMesh>>
1020  (ModelType::*method)(Args ...) const,
1021  const word& name,
1022  const dimensionSet& dims,
1023  const bool subtract,
1024  Args ... args
1025 ) const
1026 {
1027  check();
1028 
1029  typedef GeometricField<scalar, PatchField, GeoMesh> scalarGeoField;
1030  typedef GeometricField<Type, PatchField, GeoMesh> typeGeoField;
1031 
1032  // Get the blending coefficients
1033  const label nPhases = interface_.fluid().phases().size();
1034  tmp<scalarGeoField> fG, f1D2, f2D1, fS;
1035  PtrList<scalarGeoField> fGD(nPhases);
1036  PtrList<scalarGeoField> f1D2D(nPhases);
1037  PtrList<scalarGeoField> f2D1D(nPhases);
1038  PtrList<scalarGeoField> fSD(nPhases);
1039  calculateBlendingCoeffs
1040  (
1041  interface_.fluid().phases().template convert<const volScalarField>(),
1042  fG, f1D2, f2D1, fS,
1043  fGD, f1D2D, f2D1D, fSD,
1044  subtract
1045  );
1046 
1047  // Construct the result
1048  HashPtrTable<typeGeoField> xs;
1049 
1050  // Add the model contributions to the result
1051  auto addToXs = [&]
1052  (
1053  const scalarGeoField& f,
1054  const HashPtrTable<typeGeoField>& dxs
1055  )
1056  {
1057  forAllConstIter(typename HashPtrTable<typeGeoField>, dxs, dxIter)
1058  {
1059  if (xs.found(dxIter.key()))
1060  {
1061  *xs[dxIter.key()] += f**dxIter();
1062  }
1063  else
1064  {
1065  xs.insert
1066  (
1067  dxIter.key(),
1069  (
1070  ModelType::typeName + ':'
1072  (
1073  IOobject::groupName(name, dxIter.key()),
1074  interface_.name()
1075  ),
1076  f**dxIter()
1077  ).ptr()
1078  );
1079  }
1080  }
1081  };
1082  if (modelGeneral_.valid())
1083  {
1084  addToXs(fG, (modelGeneral_().*method)(args ...));
1085  }
1086  if (model1DispersedIn2_.valid())
1087  {
1088  addToXs(f1D2, (model1DispersedIn2_().*method)(args ...));
1089  }
1090  if (model2DispersedIn1_.valid())
1091  {
1092  addToXs(f2D1, (model2DispersedIn1_().*method)(args ...));
1093  }
1094  if (model1SegregatedWith2_.valid())
1095  {
1096  addToXs(fS, (model1SegregatedWith2_().*method)(args ...));
1097  }
1098  forAll(interface_.fluid().phases(), phasei)
1099  {
1100  if (modelsGeneralDisplaced_.set(phasei))
1101  {
1102  addToXs
1103  (
1104  fGD[phasei],
1105  (modelsGeneralDisplaced_[phasei].*method)(args ...)
1106  );
1107  }
1108  if (models1DispersedIn2Displaced_.set(phasei))
1109  {
1110  addToXs
1111  (
1112  f1D2D[phasei],
1113  (models1DispersedIn2Displaced_[phasei].*method)(args ...)
1114  );
1115  }
1116  if (models2DispersedIn1Displaced_.set(phasei))
1117  {
1118  addToXs
1119  (
1120  f2D1D[phasei],
1121  (models2DispersedIn1Displaced_[phasei].*method)(args ...)
1122  );
1123  }
1124  if (models1SegregatedWith2Displaced_.set(phasei))
1125  {
1126  addToXs
1127  (
1128  fSD[phasei],
1129  (models1SegregatedWith2Displaced_[phasei].*method)(args ...)
1130  );
1131  }
1132  }
1133 
1134  // Correct boundary conditions if necessary
1135  if (ModelType::correctFixedFluxBCs)
1136  {
1137  forAllIter(typename HashPtrTable<typeGeoField>, xs, xIter)
1138  {
1139  correctFixedFluxBCs(*xIter());
1140  }
1141  }
1142 
1143  return xs;
1144 }
1145 
1146 
1147 template<class ModelType>
1148 template<class ... Args>
1150 (
1151  bool (ModelType::*method)(Args ...) const,
1152  Args ... args
1153 ) const
1154 {
1155  check();
1156 
1157  bool result = false;
1158 
1159  if (modelGeneral_.valid())
1160  {
1161  result = result || (modelGeneral_().*method)(args ...);
1162  }
1163  if (model1DispersedIn2_.valid())
1164  {
1165  result = result || (model1DispersedIn2_().*method)(args ...);
1166  }
1167  if (model2DispersedIn1_.valid())
1168  {
1169  result = result || (model2DispersedIn1_().*method)(args ...);
1170  }
1171  if (model1SegregatedWith2_.valid())
1172  {
1173  result = result || (model1SegregatedWith2_().*method)(args ...);
1174  }
1175 
1176  forAll(interface_.fluid().phases(), phasei)
1177  {
1178  if (modelsGeneralDisplaced_.set(phasei))
1179  {
1180  result =
1181  result
1182  || (modelsGeneralDisplaced_[phasei].*method)(args ...);
1183  }
1184  if (models1DispersedIn2Displaced_.set(phasei))
1185  {
1186  result =
1187  result
1188  || (models1DispersedIn2Displaced_[phasei].*method)(args ...);
1189  }
1190  if (models2DispersedIn1Displaced_.set(phasei))
1191  {
1192  result =
1193  result
1194  || (models2DispersedIn1Displaced_[phasei].*method)(args ...);
1195  }
1196  if (models1SegregatedWith2Displaced_.set(phasei))
1197  {
1198  result =
1199  result
1200  || (models1SegregatedWith2Displaced_[phasei].*method)(args ...);
1201  }
1202  }
1203 
1204  return result;
1205 }
1206 
1207 
1208 template<class ModelType>
1209 template<class ... Args>
1211 (
1212  const hashedWordList& (ModelType::*method)(Args ...) const,
1213  Args ... args
1214 ) const
1215 {
1216  check();
1217 
1218  wordList result;
1219 
1220  if (modelGeneral_.valid())
1221  {
1222  result.append((modelGeneral_().*method)(args ...));
1223  }
1224  if (model1DispersedIn2_.valid())
1225  {
1226  result.append((model1DispersedIn2_().*method)(args ...));
1227  }
1228  if (model2DispersedIn1_.valid())
1229  {
1230  result.append((model2DispersedIn1_().*method)(args ...));
1231  }
1232  if (model1SegregatedWith2_.valid())
1233  {
1234  result.append((model1SegregatedWith2_().*method)(args ...));
1235  }
1236 
1237  forAll(interface_.fluid().phases(), phasei)
1238  {
1239  if (modelsGeneralDisplaced_.set(phasei))
1240  {
1241  result.append
1242  (
1243  (modelsGeneralDisplaced_[phasei].*method)(args ...)
1244  );
1245  }
1246  if (models1DispersedIn2Displaced_.set(phasei))
1247  {
1248  result.append
1249  (
1250  (models1DispersedIn2Displaced_[phasei].*method)(args ...)
1251  );
1252  }
1253  if (models2DispersedIn1Displaced_.set(phasei))
1254  {
1255  result.append
1256  (
1257  (models2DispersedIn1Displaced_[phasei].*method)(args ...)
1258  );
1259  }
1260  if (models1SegregatedWith2Displaced_.set(phasei))
1261  {
1262  result.append
1263  (
1264  (models1SegregatedWith2Displaced_[phasei].*method)(args ...)
1265  );
1266  }
1267  }
1268 
1269  return hashedWordList(move(result));
1270 }
1271 
1272 
1273 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1274 
1275 template<class ModelType>
1277 (
1278  const dictionary& dict,
1279  const phaseInterface& interface
1280 )
1281 :
1282  regIOobject
1283  (
1284  IOobject
1285  (
1286  IOobject::groupName(typeName, interface.name()),
1287  interface.fluid().mesh().time().timeName(),
1288  interface.fluid().mesh()
1289  )
1290  ),
1291  interface_(interface),
1292  blending_(),
1293  modelGeneral_(),
1294  model1DispersedIn2_(),
1295  model2DispersedIn1_(),
1296  model1SegregatedWith2_(),
1297  modelsGeneralDisplaced_(interface.fluid().phases().size()),
1298  models1DispersedIn2Displaced_(interface.fluid().phases().size()),
1299  models2DispersedIn1Displaced_(interface.fluid().phases().size()),
1300  models1SegregatedWith2Displaced_(interface.fluid().phases().size()),
1301  checkTimeIndex_(-1)
1302 {
1303  // Construct blending functions
1304  const dictionary& blendingDict = interface.fluid().subDict("blending");
1305  blending_ =
1307  (
1308  ModelType::typeName,
1309  blendingDict.found(interface.fluid().modelName<ModelType>())
1310  ? blendingDict.subDict(interface.fluid().modelName<ModelType>())
1311  : blendingDict.subDict("default"),
1312  interface
1313  );
1314 
1315  // Construct the models
1316  PtrList<phaseInterface> interfaces;
1317  PtrList<ModelType> models;
1318  interface.fluid().generateInterfacialModels
1319  <
1320  ModelType,
1321  dispersedDisplacedPhaseInterface,
1322  segregatedDisplacedPhaseInterface,
1323  displacedPhaseInterface,
1324  dispersedPhaseInterface,
1325  segregatedPhaseInterface,
1326  phaseInterface
1327  >
1328  (
1329  dict,
1330  interface,
1331  interfaces,
1332  models
1333  );
1334 
1335  // Unpack the interface and model lists to populate the models used for the
1336  // different parts of the blending space
1337  forAll(interfaces, i)
1338  {
1339  const phaseInterface& interface = interfaces[i];
1340 
1341  autoPtr<ModelType>* modelPtrPtr;
1342  PtrList<ModelType>* modelPtrsPtr;
1343 
1344  if (isA<dispersedPhaseInterface>(interface))
1345  {
1346  const phaseModel& dispersed =
1347  refCast<const dispersedPhaseInterface>(interface).dispersed();
1348 
1349  modelPtrPtr =
1350  interface_.index(dispersed) == 0
1351  ? &model1DispersedIn2_
1352  : &model2DispersedIn1_;
1353  modelPtrsPtr =
1354  interface_.index(dispersed) == 0
1355  ? &models1DispersedIn2Displaced_
1356  : &models2DispersedIn1Displaced_;
1357  }
1358  else if (isA<segregatedPhaseInterface>(interface))
1359  {
1360  modelPtrPtr = &model1SegregatedWith2_;
1361  modelPtrsPtr = &models1SegregatedWith2Displaced_;
1362  }
1363  else
1364  {
1365  modelPtrPtr = &modelGeneral_;
1366  modelPtrsPtr = &modelsGeneralDisplaced_;
1367  }
1368 
1369  if (!isA<displacedPhaseInterface>(interface))
1370  {
1371  *modelPtrPtr = models.set(i, nullptr);
1372  }
1373  else
1374  {
1375  const phaseModel& displacing =
1376  refCast<const displacedPhaseInterface>(interface).displacing();
1377 
1378  modelPtrsPtr->set(displacing.index(), models.set(i, nullptr));
1379  }
1380  }
1381 
1382  // Write out the blending space if needed
1383  if (blendingDict.found("format"))
1384  {
1385  const word format = blendingDict.lookup<word>("format");
1386 
1387  const label nPhases = interface_.fluid().phases().size();
1388 
1389  if
1390  (
1391  (nPhases <= 2 && format != noSetWriter::typeName)
1392  || (nPhases > 2 && format != noSurfaceWriter::typeName)
1393  )
1394  {
1395  postProcessBlendingCoefficients(format);
1396  }
1397  }
1398 }
1399 
1400 
1401 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1402 
1403 template<class ModelType>
1405 {}
1406 
1407 
1408 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
1409 
1410 template<class ModelType>
1411 const Foam::phaseInterface&
1413 {
1414  return interface_;
1415 }
1416 
1417 
1418 template<class ModelType>
1420 {
1421  return os.good();
1422 }
1423 
1424 
1425 // ************************************************************************* //
static autoPtr< setWriter > New(const word &writeType, const IOstream::streamFormat writeFormat=IOstream::ASCII, const IOstream::compressionType writeCompression=IOstream::UNCOMPRESSED)
Select given write options.
Definition: setWriter.C:279
fvMesh zeroDimensionalFvMesh(const objectRegistry &db)
Construct a zero-dimensional unit-cube FV mesh.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
FvWallInfoData< WallInfo, label > label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
label phasei
Definition: pEqn.H:27
bool writeData(Ostream &os) const
Dummy write for regIOobject.
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition: curveTools.C:75
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
volScalarField alpha(IOobject("alpha", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
List< face > faceList
Definition: faceListFwd.H:43
~BlendedInterfacialModel()
Destructor.
static autoPtr< blendingMethod > New(const word &modelTypeName, const dictionary &dict, const phaseInterface &interface)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
const dimensionSet dimless
label k
Boltzmann constant.
A HashTable specialisation for hashing pointers.
Definition: HashPtrTable.H:50
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
fvMesh & mesh
Class to represent an interface between phases. Derivations can further specify the configuration of ...
static List< word > fieldNames
Definition: globalFoam.H:46
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:58
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
dimensionedScalar cos(const dimensionedScalar &ds)
const pointField & points
static const word outputPrefix
Directory prefix.
Definition: writeFile.H:72
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
static word groupName(Name name, const word &group)
face triFace(3)
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
List< scalar > scalarList
A List of scalars.
Definition: scalarList.H:50
word timeName
Definition: getTimeIndex.H:3
static const zero Zero
Definition: zero.H:97
static autoPtr< surfaceWriter > New(const word &writeType, const IOstream::streamFormat writeFormat, const IOstream::compressionType writeCompression)
Select given write options.
Definition: surfaceWriter.C:75
BlendedInterfacialModel(const dictionary &dict, const phaseInterface &interface)
Construct from a dictionary and an interface.
tmp< GeometricField< Type, PatchField, GeoMesh > > evaluate(tmp< GeometricField< Type, PatchField, GeoMesh >>(ModelType::*method)(Args ...) const, const word &name, const dimensionSet &dims, const bool subtract, Args ... args) const
Return a blended field.
dimensionedScalar sin(const dimensionedScalar &ds)
labelList f(nPoints)
const phaseInterface & interface() const
Access the interface.
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
List< word > wordList
A List of words.
Definition: fileName.H:54
Info<< "Reading field p_rgh\"<< endl;volScalarField p_rgh(IOobject("p_rgh", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE), mesh);pressureReference pressureReference(p, p_rgh, pimple.dict(), thermo.incompressible());mesh.schemes().setFluxRequired(p_rgh.name());hydrostaticInitialisation(p_rgh, p, rho, U, gh, ghf, pRef, thermo, pimple.dict());Info<< "Creating field dpdt\"<< endl;volScalarField dpdt(IOobject("dpdt", runTime.timeName(), mesh), mesh, dimensionedScalar(p.dimensions()/dimTime, 0));Info<< "Creating field kinetic energy K\"<< endl;volScalarField K("K", 0.5 *magSqr(U));dimensionedScalar initialMass=fvc::domainIntegrate(rho);multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:131
label patchi
vector point
Point is a vector.
Definition: point.H:41
#define WarningInFunction
Report a warning using Foam::Warning.
A wordList with hashed indices for faster lookup by name.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
label timeIndex
Definition: getTimeIndex.H:4
phaseSystem::phaseModelList & phases
Definition: createFields.H:12
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
A class for managing temporary objects.
Definition: PtrList.H:53
Namespace for OpenFOAM.