multicomponentThermo.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) 2023-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "multicomponentThermo.H"
27 
28 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
29 
30 namespace Foam
31 {
33 }
34 
35 
36 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
37 
39 (
40  const speciesTable& species
41 )
42 {
43  if (species.size())
44  {
46  (
48  (
49  IOobject::groupName("Yt", Y_[0].group()),
50  Y_[0],
52  )
53  );
54  volScalarField& Yt = tYt.ref();
55 
56  for (label i=1; i<Y_.size(); i++)
57  {
58  Yt += Y_[i];
59  }
60 
61  if (min(Yt).value() == 0 && max(Yt).value() == 0)
62  {
64  << "Sum of specie mass fractions = 0"
65  << exit(FatalError);
66  }
67 
68  if (min(Yt).value() < 0.999)
69  {
71  << "Min sum of specie mass fractions " << min(Yt).value()
72  << " < 0.999"
73  << exit(FatalError);
74  }
75 
76  if (max(Yt).value() > 1.001)
77  {
79  << "Max sum of specie mass fractions " << max(Yt).value()
80  << " > 1.001"
81  << exit(FatalError);
82  }
83 
84  forAll(Y_, i)
85  {
86  Y_[i] /= Yt;
87  }
88  }
89 }
90 
91 
92 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
93 
95 (
96  const dictionary& dict,
97  const speciesTable& species,
98  const fvMesh& mesh,
99  const word& phaseName,
100  const bool requiresDefaultSpecie
101 )
102 :
103  defaultSpecieName_
104  (
105  requiresDefaultSpecie && species.size()
106  ? dict.lookupBackwardsCompatible<word>
107  (
108  {"defaultSpecie", "inertSpecie"}
109  )
110  : word("undefined")
111  ),
112  defaultSpeciei_
113  (
114  requiresDefaultSpecie && species.size()
115  ? species[defaultSpecieName_]
116  : -1
117  ),
118  Y_(species.size())
119 {
120  if
121  (
122  species.size()
123  && defaultSpecieName_ != "undefined"
124  && defaultSpeciei_ == -1
125  )
126  {
128  << "default specie " << defaultSpecieName_
129  << " not found in available species " << species
130  << exit(FatalIOError);
131  }
132 
133  bool Yset = false;
134 
135  // Read the species' mass fractions
136  forAll(species, i)
137  {
139  (
141  mesh.time().name(),
142  mesh,
144  );
145 
146  if (header.headerOk())
147  {
148  // Read the mass fraction field
149  Y_.set
150  (
151  i,
152  new volScalarField
153  (
154  IOobject
155  (
157  mesh.time().name(),
158  mesh,
161  ),
162  mesh
163  )
164  );
165 
166  Yset = true;
167  }
168  else
169  {
170  // Read Ydefault if not already read
171  if (!Ydefault_.valid())
172  {
173  Ydefault_ = new volScalarField
174  (
175  IOobject
176  (
177  IOobject::groupName("Ydefault", phaseName),
178  mesh.time().name(),
179  mesh,
182  ),
183  mesh
184  );
185  }
186 
187  Y_.set
188  (
189  i,
190  new volScalarField
191  (
192  IOobject
193  (
195  mesh.time().name(),
196  mesh,
199  ),
200  Ydefault_()
201  )
202  );
203  }
204  }
205 
206  // If the mass fractions have been specified check and normalise
207  if (Yset && defaultSpeciei_ != -1)
208  {
209  correctMassFractions(species);
210  }
211 }
212 
213 
214 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
215 
217 {}
218 
219 
221 {}
222 
223 
224 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
225 
227 {
228  return defaultSpeciei_;
229 }
230 
231 
233 {
234  if (Pstream::parRun())
235  {
237  const_cast<boolList&>(this->speciesActive());
238 
239  Pstream::listCombineGather(speciesActive, orEqOp<bool>());
241 
243  const_cast<PtrList<volScalarField>&>(this->Y());
244 
245  forAll(Y, speciei)
246  {
247  if (speciesActive[speciei])
248  {
249  Y[speciei].writeOpt() = IOobject::AUTO_WRITE;
250  }
251  }
252  }
253 
254  if (Ydefault_.valid())
255  {
256  Ydefault_->writeOpt() = IOobject::AUTO_WRITE;
257  }
258 }
259 
260 
263 {
264  return Y_;
265 }
266 
267 
270 {
271  return Y_;
272 }
273 
274 
276 {
277  if (defaultSpeciei_ != -1)
278  {
279  if (species().size())
280  {
282  (
284  (
286  Y()[0].mesh(),
288  )
289  );
290  volScalarField& Yt = tYt.ref();
291 
292  forAll(Y(), i)
293  {
294  if (solveSpecie(i))
295  {
296  Y()[i].max(scalar(0));
297  Yt += Y()[i];
298  }
299  }
300 
301  Y()[defaultSpeciei_] = scalar(1) - Yt;
302  Y()[defaultSpeciei_].max(scalar(0));
303  }
304 
305  if (Ydefault_.valid() && Ydefault_->writeOpt() == IOobject::NO_WRITE)
306  {
307  Ydefault_.clear();
308  }
309  }
310 }
311 
312 
313 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Generic GeometricField class.
static tmp< GeometricField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Internal &, const PtrList< Patch > &, const HashPtrTable< Source > &=HashPtrTable< Source >())
Return a temporary field constructed from name,.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
static word groupName(Name name, const word &group)
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
virtual const fvMesh & mesh() const =0
Return const access to the mesh.
virtual const word & phaseName() const =0
Phase name.
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
const word & name() const
Return const reference to name.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:433
A wordList with hashed indices for faster lookup by name.
virtual label defaultSpecie() const
The index of the default specie.
virtual void normaliseY()
Normalise the mass fractions by clipping positive and deriving.
virtual void syncSpeciesActive() const
Synchronise the specie active flags.
virtual PtrList< volScalarField > & Y()
Access the mass-fraction fields.
void correctMassFractions(const speciesTable &species)
Scale the mass fractions to sum to 1.
implementation(const dictionary &, const speciesTable &, const fvMesh &, const word &, const bool requiresDefaultSpecie=true)
Construct from dictionary, specie names, mesh and phase name.
PtrList< volScalarField > Y_
Species mass fractions.
Base-class for multi-component thermodynamic properties.
virtual const speciesTable & species() const =0
Return the table of species.
bool solveSpecie(const label speciei) const
Should the given specie be solved for? I.e., is it active and.
virtual const boolList & speciesActive() const =0
Access the specie active flags.
virtual PtrList< volScalarField > & Y()=0
Access the mass-fraction fields.
virtual ~multicomponentThermo()
Destructor.
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Templated form of IOobject providing type information for file reading and header type checking.
Definition: IOobject.H:545
A class for handling words, derived from string.
Definition: word.H:63
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const char *const group
Group name for atomic constants.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const dimensionSet & dimless
Definition: dimensions.C:138
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
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
IOerror FatalIOError
error FatalError
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
dictionary dict