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-2023 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>
48 
49 template<>
51 {
52  return f;
53 }
54 
55 template<>
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(identityMap(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().name(),
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()
850  /functionObjects::writeFile::outputPrefix
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,
870  IOstream::ASCII,
871  IOstream::UNCOMPRESSED
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,
886  IOstream::ASCII,
887  IOstream::UNCOMPRESSED
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 (
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()
938  .PtrList<phaseModel>::convert<const volScalarField>(),
939  fG, f1D2, f2D1, fS,
940  fGD, f1D2D, f2D1D, fSD,
941  subtract
942  );
943 
944  // Construct the result
947  (
948  ModelType::typeName + ":"
949  + IOobject::groupName(name, interface_.name()),
950  interface_.mesh(),
951  dimensioned<Type>(dims, Zero)
952  );
953 
954  // Add the model contributions to the result
955  if (modelGeneral_.valid())
956  {
957  x.ref() += fG*(modelGeneral_().*method)(args ...);
958  }
959  if (model1DispersedIn2_.valid())
960  {
961  x.ref() += f1D2*(model1DispersedIn2_().*method)(args ...);
962  }
963  if (model2DispersedIn1_.valid())
964  {
965  x.ref() += f2D1*(model2DispersedIn1_().*method)(args ...);
966  }
967  if (model1SegregatedWith2_.valid())
968  {
969  x.ref() += fS*(model1SegregatedWith2_().*method)(args ...);
970  }
971  forAll(interface_.fluid().phases(), phasei)
972  {
973  if (modelsGeneralDisplaced_.set(phasei))
974  {
975  x.ref() +=
976  fGD[phasei]
977  *(modelsGeneralDisplaced_[phasei].*method)(args ...);
978  }
979  if (models1DispersedIn2Displaced_.set(phasei))
980  {
981  x.ref() +=
982  f1D2D[phasei]
983  *(models1DispersedIn2Displaced_[phasei].*method)(args ...);
984  }
985  if (models2DispersedIn1Displaced_.set(phasei))
986  {
987  x.ref() +=
988  f2D1D[phasei]
989  *(models2DispersedIn1Displaced_[phasei].*method)(args ...);
990  }
991  if (models1SegregatedWith2Displaced_.set(phasei))
992  {
993  x.ref() +=
994  fSD[phasei]
995  *(models1SegregatedWith2Displaced_[phasei].*method)(args ...);
996  }
997  }
998 
999  // Correct boundary conditions if necessary
1000  if (ModelType::correctFixedFluxBCs)
1001  {
1002  correctFixedFluxBCs(x.ref());
1003  }
1004 
1005  return x;
1006 }
1007 
1008 
1009 template<class ModelType>
1010 template
1011 <
1012  class Type,
1013  template<class> class PatchField,
1014  class GeoMesh,
1015  class ... Args
1016 >
1019 (
1021  (ModelType::*method)(Args ...) const,
1022  const word& name,
1023  const dimensionSet& dims,
1024  const bool subtract,
1025  Args ... args
1026 ) const
1027 {
1028  check();
1029 
1030  typedef GeometricField<scalar, PatchField, GeoMesh> scalarGeoField;
1031  typedef GeometricField<Type, PatchField, GeoMesh> typeGeoField;
1032 
1033  // Get the blending coefficients
1034  const label nPhases = interface_.fluid().phases().size();
1035  tmp<scalarGeoField> fG, f1D2, f2D1, fS;
1036  PtrList<scalarGeoField> fGD(nPhases);
1037  PtrList<scalarGeoField> f1D2D(nPhases);
1038  PtrList<scalarGeoField> f2D1D(nPhases);
1039  PtrList<scalarGeoField> fSD(nPhases);
1040  calculateBlendingCoeffs
1041  (
1042  interface_.fluid().phases()
1043  .PtrList<phaseModel>::convert<const volScalarField>(),
1044  fG, f1D2, f2D1, fS,
1045  fGD, f1D2D, f2D1D, fSD,
1046  subtract
1047  );
1048 
1049  // Construct the result
1051 
1052  // Add the model contributions to the result
1053  auto addToXs = [&]
1054  (
1055  const scalarGeoField& f,
1056  const HashPtrTable<typeGeoField>& dxs
1057  )
1058  {
1059  forAllConstIter(typename HashPtrTable<typeGeoField>, dxs, dxIter)
1060  {
1061  if (xs.found(dxIter.key()))
1062  {
1063  *xs[dxIter.key()] += f**dxIter();
1064  }
1065  else
1066  {
1067  xs.insert
1068  (
1069  dxIter.key(),
1071  (
1072  ModelType::typeName + ':'
1073  + IOobject::groupName
1074  (
1075  IOobject::groupName(name, dxIter.key()),
1076  interface_.name()
1077  ),
1078  f**dxIter()
1079  ).ptr()
1080  );
1081  }
1082  }
1083  };
1084  if (modelGeneral_.valid())
1085  {
1086  addToXs(fG, (modelGeneral_().*method)(args ...));
1087  }
1088  if (model1DispersedIn2_.valid())
1089  {
1090  addToXs(f1D2, (model1DispersedIn2_().*method)(args ...));
1091  }
1092  if (model2DispersedIn1_.valid())
1093  {
1094  addToXs(f2D1, (model2DispersedIn1_().*method)(args ...));
1095  }
1096  if (model1SegregatedWith2_.valid())
1097  {
1098  addToXs(fS, (model1SegregatedWith2_().*method)(args ...));
1099  }
1100  forAll(interface_.fluid().phases(), phasei)
1101  {
1102  if (modelsGeneralDisplaced_.set(phasei))
1103  {
1104  addToXs
1105  (
1106  fGD[phasei],
1107  (modelsGeneralDisplaced_[phasei].*method)(args ...)
1108  );
1109  }
1110  if (models1DispersedIn2Displaced_.set(phasei))
1111  {
1112  addToXs
1113  (
1114  f1D2D[phasei],
1115  (models1DispersedIn2Displaced_[phasei].*method)(args ...)
1116  );
1117  }
1118  if (models2DispersedIn1Displaced_.set(phasei))
1119  {
1120  addToXs
1121  (
1122  f2D1D[phasei],
1123  (models2DispersedIn1Displaced_[phasei].*method)(args ...)
1124  );
1125  }
1126  if (models1SegregatedWith2Displaced_.set(phasei))
1127  {
1128  addToXs
1129  (
1130  fSD[phasei],
1131  (models1SegregatedWith2Displaced_[phasei].*method)(args ...)
1132  );
1133  }
1134  }
1135 
1136  // Correct boundary conditions if necessary
1137  if (ModelType::correctFixedFluxBCs)
1138  {
1139  forAllIter(typename HashPtrTable<typeGeoField>, xs, xIter)
1140  {
1141  correctFixedFluxBCs(*xIter());
1142  }
1143  }
1144 
1145  return xs;
1146 }
1147 
1148 
1149 template<class ModelType>
1150 template<class ... Args>
1152 (
1153  bool (ModelType::*method)(Args ...) const,
1154  Args ... args
1155 ) const
1156 {
1157  check();
1158 
1159  bool result = false;
1160 
1161  if (modelGeneral_.valid())
1162  {
1163  result = result || (modelGeneral_().*method)(args ...);
1164  }
1165  if (model1DispersedIn2_.valid())
1166  {
1167  result = result || (model1DispersedIn2_().*method)(args ...);
1168  }
1169  if (model2DispersedIn1_.valid())
1170  {
1171  result = result || (model2DispersedIn1_().*method)(args ...);
1172  }
1173  if (model1SegregatedWith2_.valid())
1174  {
1175  result = result || (model1SegregatedWith2_().*method)(args ...);
1176  }
1177 
1178  forAll(interface_.fluid().phases(), phasei)
1179  {
1180  if (modelsGeneralDisplaced_.set(phasei))
1181  {
1182  result =
1183  result
1184  || (modelsGeneralDisplaced_[phasei].*method)(args ...);
1185  }
1186  if (models1DispersedIn2Displaced_.set(phasei))
1187  {
1188  result =
1189  result
1190  || (models1DispersedIn2Displaced_[phasei].*method)(args ...);
1191  }
1192  if (models2DispersedIn1Displaced_.set(phasei))
1193  {
1194  result =
1195  result
1196  || (models2DispersedIn1Displaced_[phasei].*method)(args ...);
1197  }
1198  if (models1SegregatedWith2Displaced_.set(phasei))
1199  {
1200  result =
1201  result
1202  || (models1SegregatedWith2Displaced_[phasei].*method)(args ...);
1203  }
1204  }
1205 
1206  return result;
1207 }
1208 
1209 
1210 template<class ModelType>
1211 template<class ... Args>
1213 (
1214  const hashedWordList& (ModelType::*method)(Args ...) const,
1215  Args ... args
1216 ) const
1217 {
1218  check();
1219 
1220  wordList result;
1221 
1222  if (modelGeneral_.valid())
1223  {
1224  result.append((modelGeneral_().*method)(args ...));
1225  }
1226  if (model1DispersedIn2_.valid())
1227  {
1228  result.append((model1DispersedIn2_().*method)(args ...));
1229  }
1230  if (model2DispersedIn1_.valid())
1231  {
1232  result.append((model2DispersedIn1_().*method)(args ...));
1233  }
1234  if (model1SegregatedWith2_.valid())
1235  {
1236  result.append((model1SegregatedWith2_().*method)(args ...));
1237  }
1238 
1239  forAll(interface_.fluid().phases(), phasei)
1240  {
1241  if (modelsGeneralDisplaced_.set(phasei))
1242  {
1243  result.append
1244  (
1245  (modelsGeneralDisplaced_[phasei].*method)(args ...)
1246  );
1247  }
1248  if (models1DispersedIn2Displaced_.set(phasei))
1249  {
1250  result.append
1251  (
1252  (models1DispersedIn2Displaced_[phasei].*method)(args ...)
1253  );
1254  }
1255  if (models2DispersedIn1Displaced_.set(phasei))
1256  {
1257  result.append
1258  (
1259  (models2DispersedIn1Displaced_[phasei].*method)(args ...)
1260  );
1261  }
1262  if (models1SegregatedWith2Displaced_.set(phasei))
1263  {
1264  result.append
1265  (
1266  (models1SegregatedWith2Displaced_[phasei].*method)(args ...)
1267  );
1268  }
1269  }
1270 
1271  return hashedWordList(move(result));
1272 }
1273 
1274 
1275 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1276 
1277 template<class ModelType>
1279 (
1280  const dictionary& dict,
1281  const phaseInterface& interface
1282 )
1283 :
1284  regIOobject
1285  (
1286  IOobject
1287  (
1288  IOobject::groupName(typeName, interface.name()),
1289  interface.fluid().mesh().time().name(),
1290  interface.fluid().mesh()
1291  )
1292  ),
1293  interface_(interface),
1294  blending_(),
1295  modelGeneral_(),
1296  model1DispersedIn2_(),
1297  model2DispersedIn1_(),
1298  model1SegregatedWith2_(),
1299  modelsGeneralDisplaced_(interface.fluid().phases().size()),
1300  models1DispersedIn2Displaced_(interface.fluid().phases().size()),
1301  models2DispersedIn1Displaced_(interface.fluid().phases().size()),
1302  models1SegregatedWith2Displaced_(interface.fluid().phases().size()),
1303  checkTimeIndex_(-1)
1304 {
1305  // Construct blending functions
1306  const dictionary& blendingDict = interface.fluid().subDict("blending");
1307  blending_ =
1309  (
1310  ModelType::typeName,
1311  blendingDict.found(interface.fluid().modelName<ModelType>())
1312  ? blendingDict.subDict(interface.fluid().modelName<ModelType>())
1313  : blendingDict.subDict("default"),
1314  interface
1315  );
1316 
1317  // Construct the models
1318  PtrList<phaseInterface> interfaces;
1319  PtrList<ModelType> models;
1321  <
1322  ModelType,
1329  >
1330  (
1331  dict,
1332  interface,
1333  interfaces,
1334  models
1335  );
1336 
1337  // Unpack the interface and model lists to populate the models used for the
1338  // different parts of the blending space
1339  forAll(interfaces, i)
1340  {
1341  const phaseInterface& interface = interfaces[i];
1342 
1343  autoPtr<ModelType>* modelPtrPtr;
1344  PtrList<ModelType>* modelPtrsPtr;
1345 
1346  if (isA<dispersedPhaseInterface>(interface))
1347  {
1348  const phaseModel& dispersed =
1349  refCast<const dispersedPhaseInterface>(interface).dispersed();
1350 
1351  modelPtrPtr =
1352  interface_.index(dispersed) == 0
1353  ? &model1DispersedIn2_
1354  : &model2DispersedIn1_;
1355  modelPtrsPtr =
1356  interface_.index(dispersed) == 0
1357  ? &models1DispersedIn2Displaced_
1358  : &models2DispersedIn1Displaced_;
1359  }
1360  else if (isA<segregatedPhaseInterface>(interface))
1361  {
1362  modelPtrPtr = &model1SegregatedWith2_;
1363  modelPtrsPtr = &models1SegregatedWith2Displaced_;
1364  }
1365  else
1366  {
1367  modelPtrPtr = &modelGeneral_;
1368  modelPtrsPtr = &modelsGeneralDisplaced_;
1369  }
1370 
1371  if (!isA<displacedPhaseInterface>(interface))
1372  {
1373  *modelPtrPtr = models.set(i, nullptr);
1374  }
1375  else
1376  {
1377  const phaseModel& displacing =
1378  refCast<const displacedPhaseInterface>(interface).displacing();
1379 
1380  modelPtrsPtr->set(displacing.index(), models.set(i, nullptr));
1381  }
1382  }
1383 
1384  // Write out the blending space if needed
1385  if (blendingDict.found("format"))
1386  {
1387  const word format = blendingDict.lookup<word>("format");
1388 
1389  const label nPhases = interface_.fluid().phases().size();
1390 
1391  if
1392  (
1393  (nPhases <= 2 && format != noSetWriter::typeName)
1394  || (nPhases > 2 && format != noSurfaceWriter::typeName)
1395  )
1396  {
1397  postProcessBlendingCoefficients(format);
1398  }
1399  }
1400 }
1401 
1402 
1403 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1404 
1405 template<class ModelType>
1407 {}
1408 
1409 
1410 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
1411 
1412 template<class ModelType>
1413 const Foam::phaseInterface&
1415 {
1416  return interface_;
1417 }
1418 
1419 
1420 template<class ModelType>
1422 {
1423  return os.good();
1424 }
1425 
1426 
1427 // ************************************************************************* //
static const Foam::dimensionedScalar A("A", Foam::dimPressure, 611.21)
label k
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
const phaseInterface & interface() const
Access the interface.
BlendedInterfacialModel(const dictionary &dict, const phaseInterface &interface)
Construct from a dictionary and an interface.
bool writeData(Ostream &os) const
Dummy write for regIOobject.
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.
Generic mesh wrapper used by volMesh, surfaceMesh, pointMesh etc.
Definition: GeoMesh.H:47
Generic GeometricField class.
A HashTable specialisation for hashing pointers.
Definition: HashPtrTable.H:67
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:113
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:330
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
bool set(const label) const
Is element set.
Definition: PtrListI.H:65
static autoPtr< blendingMethod > New(const word &modelTypeName, const dictionary &dict, const phaseInterface &interface)
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:860
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:998
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:659
Dimension set for the base types.
Definition: dimensionSet.H:122
Generic dimensioned Type class.
Class to represent a interface between phases where one phase is considered dispersed within the othe...
Class to represent a interface between phases where one phase is considered dispersed within the othe...
virtual word name() const
Name.
Class to represent an interface between phases which has been displaced to some extent by a third pha...
virtual word name() const
Name.
A wordList with hashed indices for faster lookup by name.
Class to represent an interface between phases. Derivations can further specify the configuration of ...
const phaseSystem & fluid() const
Return the phase system.
virtual word name() const
Name.
label index(const phaseModel &phase) const
Return the index of the given phase. Generates a FatalError if.
label index() const
Return the index of the phase.
Definition: phaseModel.C:121
void generateInterfacialModels(const dictionary &dict, const phaseInterface &interface, PtrList< phaseInterface > &interfaces, PtrList< ModelType > &models) const
Generate interfacial-model lists.
const phaseModelList & phases() const
Return the phase models.
Definition: phaseSystemI.H:41
word modelName() const
Return the model name. This is the same as the model's typename.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
Class to represent a interface between phases where the two phases are considered to be segregated,...
Class to represent a interface between phases where the two phases are considered to be segregated; t...
A class for managing temporary objects.
Definition: tmp.H:55
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
volScalarField scalarField(fieldObject, mesh)
label patchi
static List< word > fieldNames
Definition: globalFoam.H:46
const pointField & points
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.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Info<< "Calculating turbulent flame speed field St\n"<< endl;volScalarField St(IOobject("St", runTime.name(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), flameWrinkling->Xi() *Su);multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:230
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
#define WarningInFunction
Report a warning using Foam::Warning.
bool valid(const PtrList< ModelType > &l)
tmp< GeoField > interpolate(tmp< volScalarField > f)
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
Namespace for OpenFOAM.
void addField(const Group &group, const word &name, tmp< GeoField > field, PtrList< GeoField > &fieldList)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
static const zero Zero
Definition: zero.H:97
List< word > wordList
A List of words.
Definition: fileName.H:54
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
void subtract(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
const dimensionSet dimless
dimensionedScalar sin(const dimensionedScalar &ds)
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< scalar > scalarList
A List of scalars.
Definition: scalarList.H:50
vector point
Point is a vector.
Definition: point.H:41
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:61
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
error FatalError
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
fvMesh zeroDimensionalFvMesh(const objectRegistry &db)
Construct a zero-dimensional unit-cube FV mesh.
List< face > faceList
Definition: faceListFwd.H:43
dimensionedScalar cos(const dimensionedScalar &ds)
label timeIndex
Definition: getTimeIndex.H:4
word format(conversionProperties.lookup("format"))
face triFace(3)
labelList f(nPoints)
dictionary dict
Foam::argList args(argc, argv)