clouds.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) 2021-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 "clouds.H"
27 #include "multicomponentThermo.H"
28 #include "fvMatrix.H"
30 
31 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35  namespace fv
36  {
38 
40  (
41  fvModel,
42  clouds,
44  );
45  }
46 }
47 
48 
49 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
50 
52 (
53  const word& sourceName,
54  const word& modelType,
55  const fvMesh& mesh,
56  const dictionary& dict
57 )
58 :
59  fvModel(sourceName, modelType, mesh, dict),
60  g_
61  (
62  IOobject
63  (
64  "g",
65  mesh.time().constant(),
66  mesh,
67  IOobject::READ_IF_PRESENT,
68  IOobject::NO_WRITE
69  ),
71  ),
72  carrierHasThermo_
73  (
75  ),
76  tCarrierThermo_
77  (
78  carrierHasThermo_
80  (
82  )
83  : tmpNrc<fluidThermo>(nullptr)
84  ),
85  tCarrierViscosity_
86  (
87  carrierHasThermo_
88  ? tmpNrc<viscosityModel>(nullptr)
90  (
92  )
93  ),
94  tRho_
95  (
96  carrierHasThermo_
97  ? tmp<volScalarField>(nullptr)
99  (
100  new volScalarField
101  (
102  IOobject
103  (
104  "rho",
105  mesh.time().name(),
106  mesh
107  ),
108  mesh,
109  dimensionedScalar("rho", dimDensity, tCarrierViscosity_())
110  )
111  )
112  ),
113  tMu_
114  (
115  carrierHasThermo_
116  ? tmp<volScalarField>(nullptr)
118  (
119  new volScalarField("mu", tRho_()*tCarrierViscosity_().nu())
120  )
121  ),
122  cloudNames_
123  (
124  dict.lookupOrDefault<wordList>
125  (
126  "clouds",
127  parcelCloudList::defaultCloudNames
128  )
129  ),
130  rhoName_(dict.lookupOrDefault<word>("rho", "rho")),
131  UName_(dict.lookupOrDefault<word>("U", "U")),
132  cloudsPtr_
133  (
134  carrierHasThermo_
135  ? new parcelCloudList
136  (
137  cloudNames_,
138  mesh.lookupObject<volScalarField>(rhoName_),
139  mesh.lookupObject<volVectorField>(UName_),
140  g_,
141  tCarrierThermo_()
142  )
143  : new parcelCloudList
144  (
145  cloudNames_,
146  tRho_(),
147  mesh.lookupObject<volVectorField>(UName_),
148  tMu_(),
149  g_
150  )
151  ),
152  curTimeIndex_(-1)
153 {}
154 
155 
156 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
157 
159 {
160  if (!cloudsPtr_->coupled())
161  {
162  return wordList();
163  }
164 
165  wordList fieldNames(1, UName_);
166 
167  if (carrierHasThermo_)
168  {
169  const fluidThermo& carrierThermo = tCarrierThermo_();
170 
171  fieldNames.append(rhoName_);
172 
173  fieldNames.append(carrierThermo.he().name());
174 
175  if (isA<multicomponentThermo>(carrierThermo))
176  {
177  const multicomponentThermo& carrierMcThermo =
178  refCast<const multicomponentThermo>(carrierThermo);
179 
180  forAll(carrierMcThermo.Y(), i)
181  {
182  if (carrierMcThermo.solveSpecie(i))
183  {
184  fieldNames.append(carrierMcThermo.Y()[i].name());
185  }
186  }
187  }
188  }
189 
190  return fieldNames;
191 }
192 
193 
195 {
196  if (curTimeIndex_ == mesh().time().timeIndex())
197  {
198  return;
199  }
200 
201  if (!carrierHasThermo_)
202  {
203  tMu_.ref() = tRho_()*tCarrierViscosity_().nu();
204  }
205 
206  cloudsPtr_().evolve();
207 
208  curTimeIndex_ = mesh().time().timeIndex();
209 }
210 
211 
213 (
214  const volScalarField& rho,
215  fvMatrix<scalar>& eqn
216 ) const
217 {
218  if (debug)
219  {
220  Info<< type() << ": applying source to " << eqn.psi().name() << endl;
221  }
222 
223  if (!carrierHasThermo_)
224  {
226  << "Applying source to compressible equation when carrier thermo "
227  << "is not available"
228  << exit(FatalError);
229  }
230 
231  if (rho.name() == rhoName_)
232  {
233  eqn += cloudsPtr_().Srho(eqn.psi());
234  }
235  else
236  {
238  << "Support for field " << rho.name() << " is not implemented"
239  << exit(FatalError);
240  }
241 }
242 
243 
245 (
246  const volScalarField& rho,
247  const volScalarField& field,
248  fvMatrix<scalar>& eqn
249 ) const
250 {
251  if (debug)
252  {
253  Info<< type() << ": applying source to " << eqn.psi().name() << endl;
254  }
255 
256  if (!carrierHasThermo_)
257  {
259  << "Applying source to compressible equation when carrier thermo "
260  << "is not available"
261  << exit(FatalError);
262  }
263 
264  const fluidThermo& carrierThermo = tCarrierThermo_();
265 
266  if (&field == &carrierThermo.he())
267  {
268  eqn += cloudsPtr_().Sh(eqn.psi());
269  return;
270  }
271 
272  if (isA<multicomponentThermo>(carrierThermo))
273  {
274  const multicomponentThermo& carrierMcThermo =
275  refCast<const multicomponentThermo>(carrierThermo);
276 
277  if (carrierMcThermo.containsSpecie(field.name()))
278  {
279  eqn +=
280  cloudsPtr_().SYi
281  (
282  carrierMcThermo.specieIndex(field),
283  field
284  );
285  return;
286  }
287  }
288 
289  {
291  << "Support for field " << field.name() << " is not implemented"
292  << exit(FatalError);
293  }
294 }
295 
296 
298 (
299  const volVectorField& U,
300  fvMatrix<vector>& eqn
301 ) const
302 {
303  if (debug)
304  {
305  Info<< type() << ": applying source to " << eqn.psi().name() << endl;
306  }
307 
308  if (carrierHasThermo_)
309  {
311  << "Applying source to incompressible equation when carrier thermo "
312  << "is available"
313  << exit(FatalError);
314  }
315 
316  if (U.name() == UName_)
317  {
318  eqn += cloudsPtr_().SU(eqn.psi())/tRho_();
319  }
320  else
321  {
323  << "Support for field " << U.name() << " is not implemented"
324  << exit(FatalError);
325  }
326 }
327 
328 
330 (
331  const volScalarField& rho,
332  const volVectorField& U,
333  fvMatrix<vector>& eqn
334 ) const
335 {
336  if (debug)
337  {
338  Info<< type() << ": applying source to " << eqn.psi().name() << endl;
339  }
340 
341  if (!carrierHasThermo_)
342  {
344  << "Applying source to compressible equation when carrier thermo "
345  << "is not available"
346  << exit(FatalError);
347  }
348 
349  if (U.name() == UName_)
350  {
351  eqn += cloudsPtr_().SU(eqn.psi());
352  }
353  else
354  {
356  << "Support for field " << U.name() << " is not implemented"
357  << exit(FatalError);
358  }
359 }
360 
361 
363 {
364  // Store the particle positions
365  cloudsPtr_().storeGlobalPositions();
366 }
367 
368 
370 {
371  cloudsPtr_().topoChange(map);
372 }
373 
374 
376 {
377  cloudsPtr_().mapMesh(map);
378 }
379 
380 
382 {
383  cloudsPtr_().distribute(map);
384 }
385 
386 
388 {
389  return true;
390 }
391 
392 
393 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
Generic GeometricField class.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const word & name() const
Return name.
Definition: IOobject.H:307
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
label timeIndex() const
Return current time index.
Definition: TimeStateI.H:28
virtual const volScalarField & he() const =0
Enthalpy/Internal energy [J/kg].
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Base-class for fluid thermodynamic properties.
Definition: fluidThermo.H:56
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:118
VolField< Type > & psi()
Definition: fvMatrix.H:289
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
Finite volume model abstract base class.
Definition: fvModel.H:60
This fvModel adds any number of Lagrangian clouds to any single-phase solver. The particles are track...
Definition: clouds.H:131
virtual bool movePoints()
Update for mesh motion.
Definition: clouds.C:387
virtual wordList addSupFields() const
Return the list of fields for which the option adds source term.
Definition: clouds.C:158
virtual void correct()
Solve the Lagrangian clouds and update the sources.
Definition: clouds.C:194
virtual void addSup(const volScalarField &rho, fvMatrix< scalar > &eqn) const
Add source to continuity equation.
Definition: clouds.C:213
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
Definition: clouds.C:369
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
Definition: clouds.C:381
virtual void preUpdateMesh()
Prepare for mesh update.
Definition: clouds.C:362
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
Definition: clouds.C:375
clouds(const word &sourceName, const word &modelType, const fvMesh &mesh, const dictionary &dict)
Construct from explicit source name and mesh.
Definition: clouds.C:52
Base-class for multi-component thermodynamic properties.
bool solveSpecie(const label speciei) const
Should the given specie be solved for? I.e., is it active and.
virtual PtrList< volScalarField > & Y()=0
Access the mass-fraction fields.
bool containsSpecie(const word &specieName) const
Does the mixture include this specie?
label specieIndex(const volScalarField &Yi) const
Access the specie index of the given mass-fraction field.
List of parcel clouds, with the same interface as an individual parcel cloud. This is the object that...
A base class for physical properties.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
A class for managing temporary objects without reference counting.
Definition: tmpNrc.H:53
A class for managing temporary objects.
Definition: tmp.H:55
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
An abstract base class for Newtonian viscosity models.
A class for handling words, derived from string.
Definition: word.H:63
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
static List< word > fieldNames
Definition: globalFoam.H:46
U
Definition: pEqn.H:72
rho
Definition: pEqn.H:1
const dimensionSet time
addToRunTimeSelectionTable(fvConstraint, bound, dictionary)
defineTypeNameAndDebug(bound, 0)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
List< word > wordList
A List of words.
Definition: fileName.H:54
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
const dimensionSet & dimAcceleration
Definition: dimensions.C:156
const dimensionSet & dimDensity
Definition: dimensions.C:158
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
label timeIndex
Definition: getTimeIndex.H:4
labelList fv(nPoints)
dictionary dict