basicThermo.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "basicThermo.H"
30 #include "stringOps.H"
31 #include "wordIOList.H"
36 #include "fixedJumpFvPatchFields.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(basicThermo, 0);
46  defineRunTimeSelectionTable(basicThermo, fvMesh);
47  defineRunTimeSelectionTable(basicThermo, fvMeshDictPhase);
48 }
49 
50 const Foam::word Foam::basicThermo::dictName("thermophysicalProperties");
51 
52 const Foam::wordList Foam::basicThermo::componentHeader4
53 ({
54  "type",
55  "mixture",
56  "properties",
57  "energy"
58 });
59 
60 const Foam::wordList Foam::basicThermo::componentHeader7
61 ({
62  "type",
63  "mixture",
64  "transport",
65  "thermo",
66  "equationOfState",
67  "specie",
68  "energy"
69 });
70 
71 
72 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
73 
75 (
76  Ostream& os,
77  const wordList& cmptNames,
78  const wordList& thermoNames
79 )
80 {
81  const int nCmpt = cmptNames.size();
82 
83  // Build a table of constituent parts by split name into constituent parts
84  // - remove incompatible entries from the list
85  // - note: row-0 contains the names of constituent parts (ie, the header)
86 
87  DynamicList<wordList> outputTbl;
88  outputTbl.resize(thermoNames.size()+1);
89 
90  label rowi = 0;
91 
92  // Header
93  outputTbl[rowi] = cmptNames;
94  if (!outputTbl[rowi].empty())
95  {
96  ++rowi;
97  }
98 
99  for (const word& thermoName : thermoNames)
100  {
101  outputTbl[rowi] = basicThermo::splitThermoName(thermoName, nCmpt);
102  if (!outputTbl[rowi].empty())
103  {
104  ++rowi;
105  }
106  }
107 
108  if (rowi > 1)
109  {
110  outputTbl.resize(rowi);
111  Foam::printTable(outputTbl, os);
112  }
113 
114  return os;
115 }
116 
117 
118 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
119 
120 Foam::word Foam::basicThermo::makeThermoName
121 (
122  const dictionary& thermoTypeDict,
123  const wordList*& cmptHeaderPtr
124 )
125 {
126  if (thermoTypeDict.found("properties"))
127  {
128  if (cmptHeaderPtr)
129  {
130  cmptHeaderPtr = &(componentHeader4);
131  }
132 
133  return word
134  (
135  thermoTypeDict.get<word>("type") + '<'
136  + thermoTypeDict.get<word>("mixture") + '<'
137  + thermoTypeDict.get<word>("properties") + ','
138  + thermoTypeDict.get<word>("energy") + ">>"
139  );
140  }
141  else
142  {
143  if (cmptHeaderPtr)
144  {
145  cmptHeaderPtr = &(componentHeader7);
146  }
147 
148  return word
149  (
150  thermoTypeDict.get<word>("type") + '<'
151  + thermoTypeDict.get<word>("mixture") + '<'
152  + thermoTypeDict.get<word>("transport") + '<'
153  + thermoTypeDict.get<word>("thermo") + '<'
154  + thermoTypeDict.get<word>("equationOfState") + '<'
155  + thermoTypeDict.get<word>("specie") + ">>,"
156  + thermoTypeDict.get<word>("energy") + ">>>"
157  );
158  }
159 }
160 
161 
162 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
163 
165 {
166  const volScalarField::Boundary& tbf = this->T_.boundaryField();
167 
168  wordList hbt(tbf.size());
169 
170  forAll(tbf, patchi)
171  {
172  if (isA<fixedJumpFvPatchScalarField>(tbf[patchi]))
173  {
174  const auto& pf =
175  dynamic_cast<const fixedJumpFvPatchScalarField&>
176  (
177  tbf[patchi]
178  );
179 
180  hbt[patchi] = pf.interfaceFieldType();
181  }
182  else if (isA<fixedJumpAMIFvPatchScalarField>(tbf[patchi]))
183  {
184  const auto& pf =
185  dynamic_cast<const fixedJumpAMIFvPatchScalarField&>
186  (
187  tbf[patchi]
188  );
189 
190  hbt[patchi] = pf.interfaceFieldType();
191  }
192  }
193 
194  return hbt;
195 }
196 
197 
199 {
200  const volScalarField::Boundary& tbf = this->T_.boundaryField();
201 
202  wordList hbt(tbf.types());
203 
204  forAll(tbf, patchi)
205  {
206  if (isA<fixedValueFvPatchScalarField>(tbf[patchi]))
207  {
208  hbt[patchi] = fixedEnergyFvPatchScalarField::typeName;
209  }
210  else if
211  (
212  isA<zeroGradientFvPatchScalarField>(tbf[patchi])
213  || isA<fixedGradientFvPatchScalarField>(tbf[patchi])
214  )
215  {
216  hbt[patchi] = gradientEnergyFvPatchScalarField::typeName;
217  }
218  else if (isA<mixedFvPatchScalarField>(tbf[patchi]))
219  {
220  hbt[patchi] = mixedEnergyFvPatchScalarField::typeName;
221  }
222  else if (isA<fixedJumpFvPatchScalarField>(tbf[patchi]))
223  {
225  }
226  else if (isA<fixedJumpAMIFvPatchScalarField>(tbf[patchi]))
227  {
229  }
230  }
231 
232  return hbt;
233 }
234 
235 
236 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
237 
238 Foam::volScalarField& Foam::basicThermo::lookupOrConstruct
239 (
240  const fvMesh& mesh,
241  const word& fieldName,
242  bool& isOwner
243 )
244 {
245  auto* ptr = mesh.objectRegistry::getObjectPtr<volScalarField>(fieldName);
246 
247  isOwner = !ptr;
248 
249  if (!ptr)
250  {
251  ptr = new volScalarField
252  (
253  IOobject
254  (
255  fieldName,
256  mesh.time().timeName(),
257  mesh,
261  ),
262  mesh
263  );
264 
265  // Transfer ownership of this object to the objectRegistry
266  ptr->store();
267  }
268 
269  return *ptr;
270 }
271 
272 
273 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
274 
276 (
277  const fvMesh& mesh,
278  const word& phaseName
279 )
280 :
282  (
283  IOobject
284  (
285  phasePropertyName(dictName, phaseName),
286  mesh.time().constant(),
287  mesh,
288  IOobject::MUST_READ_IF_MODIFIED,
289  IOobject::NO_WRITE
290  )
291  ),
292 
293  phaseName_(phaseName),
294 
295  pOwner_(false),
296  TOwner_(false),
297  dpdt_(getOrDefault<bool>("dpdt", true)),
298 
299  p_(lookupOrConstruct(mesh, "p", pOwner_)),
300  T_(lookupOrConstruct(mesh, phasePropertyName("T"), TOwner_)),
301 
302  alpha_
303  (
304  IOobject
305  (
306  phasePropertyName("thermo:alpha"),
307  mesh.time().timeName(),
308  mesh,
309  IOobject::READ_IF_PRESENT,
310  IOobject::NO_WRITE
311  ),
312  mesh,
313  dimensionedScalar(dimensionSet(1, -1, -1, 0, 0), Zero)
314  )
315 {
316  this->readIfPresent("updateT", TOwner_); // Manual override
317 }
318 
319 
321 (
322  const fvMesh& mesh,
323  const dictionary& dict,
324  const word& phaseName
325 )
326 :
328  (
329  IOobject
330  (
331  phasePropertyName(dictName, phaseName),
332  mesh.time().constant(),
333  mesh,
334  IOobject::NO_READ,
335  IOobject::NO_WRITE
336  ),
337  dict
338  ),
339 
340  phaseName_(phaseName),
341 
342  pOwner_(false),
343  TOwner_(false),
344  dpdt_(getOrDefault<bool>("dpdt", true)),
345 
346  p_(lookupOrConstruct(mesh, "p", pOwner_)),
347  T_(lookupOrConstruct(mesh, phasePropertyName("T"), TOwner_)),
348 
349  alpha_
350  (
351  IOobject
352  (
353  phasePropertyName("thermo:alpha"),
354  mesh.time().timeName(),
355  mesh,
356  IOobject::NO_READ,
357  IOobject::NO_WRITE
358  ),
359  mesh,
360  dimensionedScalar(dimensionSet(1, -1, -1, 0, 0), Zero)
361  )
362 {
363  this->readIfPresent("updateT", TOwner_); // Manual override
364 }
365 
366 
368 (
369  const fvMesh& mesh,
370  const word& phaseName,
371  const word& dictionaryName
372 )
373 :
375  (
376  IOobject
377  (
378  dictionaryName,
379  mesh.time().constant(),
380  mesh,
381  IOobject::MUST_READ_IF_MODIFIED,
382  IOobject::NO_WRITE
383  )
384  ),
385 
386  phaseName_(phaseName),
387 
388  pOwner_(false),
389  TOwner_(false),
390  dpdt_(getOrDefault<bool>("dpdt", true)),
391 
392  p_(lookupOrConstruct(mesh, "p", pOwner_)),
393  T_(lookupOrConstruct(mesh, "T", TOwner_)),
394 
395  alpha_
396  (
397  IOobject
398  (
399  phasePropertyName("thermo:alpha"),
400  mesh.time().timeName(),
401  mesh,
402  IOobject::READ_IF_PRESENT,
403  IOobject::NO_WRITE
404  ),
405  mesh,
406  dimensionedScalar(dimensionSet(1, -1, -1, 0, 0), Zero)
407  )
408 {
409  this->readIfPresent("updateT", TOwner_); // Manual override
410 
411  if (debug)
412  {
413  Pout<< "Constructed shared thermo : mesh:" << mesh.name()
414  << " phase:" << phaseName
415  << " dictionary:" << dictionaryName
416  << " T:" << T_.name()
417  << " updateT:" << TOwner_
418  << " alphaName:" << alpha_.name()
419  << endl;
420  }
421 }
422 
423 
424 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
425 
427 (
428  const fvMesh& mesh,
429  const word& phaseName
430 )
431 {
432  return New<basicThermo>(mesh, phaseName);
433 }
434 
435 
436 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
437 
439 {
440  if (pOwner_)
441  {
442  db().checkOut(p_.name());
443  }
444 
445  if (TOwner_)
446  {
447  db().checkOut(T_.name());
448  }
449 }
450 
451 
452 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
453 
455 (
456  const fvPatchScalarField& pf
457 )
458 {
459  const basicThermo* thermoPtr = pf.db().cfindObject<basicThermo>(dictName);
460 
461  if (thermoPtr)
462  {
463  return *thermoPtr;
464  }
465 
466  for (const basicThermo& thermo : pf.db().cobjects<basicThermo>())
467  {
468  if
469  (
470  &(thermo.he().internalField())
471  == &(pf.internalField())
472  )
473  {
474  return thermo;
475  }
476  }
478  // Failure
479  return pf.db().lookupObject<basicThermo>(dictName);
480 }
481 
482 
484 (
485  const string& app,
486  const word& a
487 ) const
488 {
489  if (!(he().name() == phasePropertyName(a)))
490  {
492  << "Supported energy type is " << phasePropertyName(a)
493  << ", thermodynamics package provides " << he().name()
494  << exit(FatalError);
495  }
496 }
497 
499 (
500  const string& app,
501  const word& a,
502  const word& b
503 ) const
504 {
505  if
506  (
507  !(
508  he().name() == phasePropertyName(a)
509  || he().name() == phasePropertyName(b)
510  )
511  )
512  {
514  << "Supported energy types: " << phasePropertyName(a)
515  << " and " << phasePropertyName(b)
516  << ", thermodynamics package provides " << he().name()
517  << exit(FatalError);
518  }
519 }
520 
522 (
523  const string& app,
524  const word& a,
525  const word& b,
526  const word& c
527 ) const
528 {
529  if
530  (
531  !(
532  he().name() == phasePropertyName(a)
533  || he().name() == phasePropertyName(b)
534  || he().name() == phasePropertyName(c)
535  )
536  )
537  {
539  << "Supported energy types: " << phasePropertyName(a)
540  << ", " << phasePropertyName(b)
541  << " and " << phasePropertyName(c)
542  << ", thermodynamics package provides " << he().name()
543  << exit(FatalError);
544  }
545 }
546 
548 (
549  const string& app,
550  const word& a,
551  const word& b,
552  const word& c,
553  const word& d
554 ) const
555 {
556  if
557  (
558  !(
559  he().name() == phasePropertyName(a)
560  || he().name() == phasePropertyName(b)
561  || he().name() == phasePropertyName(c)
562  || he().name() == phasePropertyName(d)
563  )
564  )
565  {
567  << "Supported energy types: " << phasePropertyName(a)
568  << ", " << phasePropertyName(b)
569  << ", " << phasePropertyName(c)
570  << " and " << phasePropertyName(d)
571  << ", thermodynamics package provides " << he().name()
572  << exit(FatalError);
573  }
574 }
575 
576 
578 (
579  const std::string& thermoName,
580  const int nExpectedCmpts
581 )
582 {
583  // Split on ",<>" but include space for good measure.
584  // Splits things like
585  // "hePsiThermo<pureMixture<const<hConst<perfectGas<specie>>,enthalpy>>>"
586 
587  const auto parsed = stringOps::splitAny<std::string>(thermoName, " ,<>");
588  const int nParsed(parsed.size());
589 
590  wordList cmpts;
591 
592  if (!nExpectedCmpts || nParsed == nExpectedCmpts)
593  {
594  cmpts.resize(nParsed);
595 
596  auto iter = cmpts.begin();
597  for (const auto& sub : parsed)
598  {
599  *iter = word(sub.str());
600  ++iter;
601  }
602  }
603 
604  return cmpts;
605 }
606 
609 {
610  return p_;
611 }
612 
615 {
616  return p_;
617 }
618 
621 {
622  return T_;
623 }
624 
627 {
628  return T_;
629 }
630 
633 {
634  return alpha_;
635 }
636 
638 const Foam::scalarField& Foam::basicThermo::alpha(const label patchi) const
639 {
640  return alpha_.boundaryField()[patchi];
641 }
642 
643 
645 {
646  return regIOobject::read();
647 }
648 
649 
650 // ************************************************************************* //
volScalarField & he
Definition: YEEqn.H:52
word dictName() const
The local dictionary name (final part of scoped name)
Definition: dictionaryI.H:53
virtual ~basicThermo()
Destructor.
Definition: basicThermo.C:431
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
const Type & lookupObject(const word &name, const bool recursive=false) const
Lookup and return const reference to the object of the given Type. Fatal if not found or the wrong ty...
Abstract base-class for fluid and solid thermodynamic properties.
Definition: basicThermo.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
virtual bool read()
Read object.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
static Ostream & printThermoNames(Ostream &os, const wordList &cmptNames, const wordList &thermoNames)
Print (filtered) table of thermo names, splits on " ,<>".
Definition: basicThermo.C:68
Ostream & printTable(const UList< wordList > &tbl, List< std::string::size_type > &columnWidths, Ostream &os, bool headerSeparator=true)
Print a List of wordList as a table.
Definition: wordIOList.C:40
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
virtual word thermoName() const =0
Return the name of the thermo physics.
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:353
const word dictName("faMeshDefinition")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
virtual const volScalarField & alpha() const
Thermal diffusivity for enthalpy of mixture [kg/m/s].
Definition: basicThermo.C:625
virtual const volScalarField & T() const
Temperature [K].
Definition: basicThermo.C:613
GeometricBoundaryField< scalar, fvPatchField, volMesh > Boundary
Type of boundary fields.
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:360
const Type * cfindObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
static autoPtr< Thermo > New(const fvMesh &, const word &phaseName=word::null)
Generic New for each of the related thermodynamics packages.
virtual volScalarField & he()=0
Enthalpy/Internal energy [J/kg].
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
virtual volScalarField & p()
Pressure [Pa].
Definition: basicThermo.C:601
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
psiReactionThermo & thermo
Definition: createFields.H:28
static const char *const typeName
Typename for Field.
Definition: Field.H:86
word timeName
Definition: getTimeIndex.H:3
Dimension set for the base types, which can be used to implement rigorous dimension checking for alge...
Definition: dimensionSet.H:105
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
wordList heBoundaryBaseTypes()
Return the enthalpy/internal energy field boundary base types by interrogating the temperature field ...
Definition: basicThermo.C:157
basicThermo(const basicThermo &)=delete
No copy construct.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
static wordList splitThermoName(const std::string &thermoName, const int nExpectedCmpts)
Split thermo package name into a list of components names.
Definition: basicThermo.C:571
fvPatchField< scalar > fvPatchScalarField
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
A class for handling words, derived from Foam::string.
Definition: word.H:63
wordList heBoundaryTypes()
Return the enthalpy/internal energy field boundary types by interrogating the temperature field bound...
Definition: basicThermo.C:191
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:450
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
int debug
Static debugging option.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
UPtrList< const Type > cobjects() const
Return unsorted list of objects with a class satisfying isA<Type> or isType<Type> (with Strict) ...
List< word > wordList
List of word.
Definition: fileName.H:59
volScalarField alpha_
Laminar thermal diffusivity [kg/m/s].
Definition: basicThermo.H:166
bool TOwner_
Temperature created and stored by this instance.
Definition: basicThermo.H:143
const word & name() const
Return reference to name.
Definition: fvMesh.H:387
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
const dimensionedScalar c
Speed of light in a vacuum.
Automatically write from objectRegistry::writeObject()
virtual bool read()
Read thermophysical properties dictionary.
Definition: basicThermo.C:637
static const basicThermo & lookupThermo(const fvPatchScalarField &pf)
Definition: basicThermo.C:448
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
void validate(const string &app, const word &) const
Check that the thermodynamics package is consistent.
Definition: basicThermo.C:477
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
Request registration (bool: true)
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
volScalarField & T_
Temperature [K].
Definition: basicThermo.H:161
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127