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  dimless
164  )
165  );
166 
167  Yset = true;
168  }
169  else
170  {
171  // Read Ydefault if not already read
172  if (!Ydefault_.valid())
173  {
174  Ydefault_ = new volScalarField
175  (
176  IOobject
177  (
178  IOobject::groupName("Ydefault", phaseName),
179  mesh.time().name(),
180  mesh,
183  ),
184  mesh,
185  dimless
186  );
187  }
188 
189  Y_.set
190  (
191  i,
192  new volScalarField
193  (
194  IOobject
195  (
197  mesh.time().name(),
198  mesh,
201  ),
202  Ydefault_()
203  )
204  );
205  }
206  }
207 
208  // If the mass fractions have been specified check and normalise
209  if (Yset && defaultSpeciei_ != -1)
210  {
211  correctMassFractions(species);
212  }
213 }
214 
215 
216 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
217 
219 {}
220 
221 
223 {}
224 
225 
226 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
227 
229 {
230  return defaultSpeciei_;
231 }
232 
233 
235 {
236  if (Pstream::parRun())
237  {
239  const_cast<boolList&>(this->speciesActive());
240 
241  Pstream::listCombineGather(speciesActive, orEqOp<bool>());
243 
245  const_cast<PtrList<volScalarField>&>(this->Y());
246 
247  forAll(Y, speciei)
248  {
249  if (speciesActive[speciei])
250  {
251  Y[speciei].writeOpt() = IOobject::AUTO_WRITE;
252  }
253  }
254  }
255 
256  if (Ydefault_.valid())
257  {
258  Ydefault_->writeOpt() = IOobject::AUTO_WRITE;
259  }
260 }
261 
262 
265 {
266  return Y_;
267 }
268 
269 
272 {
273  return Y_;
274 }
275 
276 
278 {
279  if (defaultSpeciei_ != -1)
280  {
281  if (species().size())
282  {
284  (
286  (
288  Y()[0].mesh(),
290  )
291  );
292  volScalarField& Yt = tYt.ref();
293 
294  forAll(Y(), i)
295  {
296  if (solveSpecie(i))
297  {
298  Y()[i].max(scalar(0));
299  Yt += Y()[i];
300  }
301  }
302 
303  Y()[defaultSpeciei_] = scalar(1) - Yt;
304  Y()[defaultSpeciei_].max(scalar(0));
305  }
306 
307  if (Ydefault_.valid() && Ydefault_->writeOpt() == IOobject::NO_WRITE)
308  {
309  Ydefault_.clear();
310  }
311  }
312 }
313 
314 
315 // ************************************************************************* //
#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.
const dimensionSet dimless
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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