scalarTransport.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) 2012-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2023 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 "scalarTransport.H"
30 #include "surfaceFields.H"
31 #include "fvmDdt.H"
32 #include "fvmDiv.H"
33 #include "fvmLaplacian.H"
34 #include "fvmSup.H"
35 #include "CMULES.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 namespace functionObjects
45 {
46  defineTypeNameAndDebug(scalarTransport, 0);
47 
49  (
50  functionObject,
51  scalarTransport,
52  dictionary
53  );
54 }
55 }
56 
57 
58 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
59 
60 Foam::volScalarField& Foam::functionObjects::scalarTransport::transportedField()
61 {
62  if (!foundObject<volScalarField>(fieldName_))
63  {
64  auto tfldPtr = tmp<volScalarField>::New
65  (
66  IOobject
67  (
68  fieldName_,
69  mesh_.time().timeName(),
70  mesh_,
74  ),
75  mesh_
76  );
77  store(fieldName_, tfldPtr);
78 
79  if (phaseName_ != "none")
80  {
81  mesh_.setFluxRequired(fieldName_);
82  }
83  }
84 
85  return lookupObjectRef<volScalarField>(fieldName_);
86 }
87 
88 
89 Foam::tmp<Foam::volScalarField> Foam::functionObjects::scalarTransport::D
90 (
91  const volScalarField& s,
92  const surfaceScalarField& phi
93 ) const
94 {
95  const word Dname("D" + s.name());
96 
97  if (constantD_)
98  {
100  (
101  IOobject
102  (
103  Dname,
104  mesh_.time().timeName(),
105  mesh_.time(),
108  ),
109  mesh_,
110  dimensionedScalar(Dname, phi.dimensions()/dimLength, D_)
111  );
112  }
113 
114  if (nutName_ != "none")
115  {
116  const volScalarField& nutMean =
117  mesh_.lookupObject<volScalarField>(nutName_);
118 
119  return tmp<volScalarField>::New(Dname, nutMean);
120  }
121 
122  // Incompressible
123  {
124  const auto* turb =
125  findObject<incompressible::turbulenceModel>
126  (
128  );
129 
130  if (turb)
131  {
133  (
134  Dname,
135  alphaD_ * turb->nu() + alphaDt_ * turb->nut()
136  );
137  }
138  }
139 
140  // Compressible
141  {
142  const auto* turb =
143  findObject<compressible::turbulenceModel>
144  (
146  );
147 
148  if (turb)
149  {
151  (
152  Dname,
153  alphaD_ * turb->mu() + alphaDt_ * turb->mut()
154  );
155  }
156  }
157 
158 
160  (
161  IOobject
162  (
163  Dname,
164  mesh_.time().timeName(),
165  mesh_.time(),
168  ),
169  mesh_,
170  dimensionedScalar(phi.dimensions()/dimLength, Zero)
171  );
172 }
173 
174 
175 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
176 
177 Foam::functionObjects::scalarTransport::scalarTransport
178 (
179  const word& name,
180  const Time& runTime,
181  const dictionary& dict
182 )
183 :
185  fieldName_(dict.getOrDefault<word>("field", "s")),
186  phiName_(dict.getOrDefault<word>("phi", "phi")),
187  rhoName_(dict.getOrDefault<word>("rho", "rho")),
188  nutName_(dict.getOrDefault<word>("nut", "none")),
189  phaseName_(dict.getOrDefault<word>("phase", "none")),
190  phasePhiCompressedName_
191  (
192  dict.getOrDefault<word>("phasePhiCompressed", "alphaPhiUn")
193  ),
194  D_(0),
195  constantD_(false),
196  nCorr_(0),
197  resetOnStartUp_(false),
198  schemesField_("unknown-schemesField"),
199  fvOptions_(mesh_),
200  bounded01_(dict.getOrDefault("bounded01", true))
201 {
202  read(dict);
203 
204  // Force creation of transported field so any BCs using it can
205  // look it up
206  volScalarField& s = transportedField();
207 
208  if (resetOnStartUp_)
209  {
211  }
212 }
213 
214 
215 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
218 {}
219 
220 
221 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
222 
224 {
226 
227  dict.readIfPresent("phi", phiName_);
228  dict.readIfPresent("rho", rhoName_);
229  dict.readIfPresent("nut", nutName_);
230  dict.readIfPresent("phase", phaseName_);
231  dict.readIfPresent("bounded01", bounded01_);
232 
233  schemesField_ = dict.getOrDefault("schemesField", fieldName_);
234  constantD_ = dict.readIfPresent("D", D_);
235  alphaD_ = dict.getOrDefault<scalar>("alphaD", 1);
236  alphaDt_ = dict.getOrDefault<scalar>("alphaDt", 1);
237 
238  dict.readIfPresent("nCorr", nCorr_);
239  dict.readIfPresent("resetOnStartUp", resetOnStartUp_);
240 
241  if (dict.found("fvOptions"))
242  {
243  fvOptions_.reset(dict.subDict("fvOptions"));
244  }
245 
246  return true;
247 }
248 
249 
251 {
252  volScalarField& s = transportedField();
253 
254  Log << type() << " execute: " << s.name() << endl;
255 
256  const surfaceScalarField& phi =
257  mesh_.lookupObject<surfaceScalarField>(phiName_);
258 
259  // Calculate the diffusivity
260  volScalarField D(this->D(s, phi));
261 
262  word divScheme("div(phi," + schemesField_ + ")");
263  word laplacianScheme("laplacian(" + D.name() + "," + schemesField_ + ")");
264 
265  // Set under-relaxation coeff
266  scalar relaxCoeff = 0;
267  mesh_.relaxEquation(schemesField_, relaxCoeff);
268 
269  // Two phase scalar transport
270  if (phaseName_ != "none")
271  {
272  const volScalarField& alpha =
273  mesh_.lookupObject<volScalarField>(phaseName_);
274 
275  const surfaceScalarField& limitedPhiAlpha =
276  mesh_.lookupObject<surfaceScalarField>(phasePhiCompressedName_);
277 
278  D *= pos(alpha - 0.99);
279 
280  // Reset D dimensions consistent with limitedPhiAlpha
281  D.dimensions().reset(limitedPhiAlpha.dimensions()/dimLength);
282 
283  // Solve
284  tmp<surfaceScalarField> tTPhiUD;
285  for (label i = 0; i <= nCorr_; i++)
286  {
287  fvScalarMatrix sEqn
288  (
289  fvm::ddt(s)
290  + fvm::div(limitedPhiAlpha, s, divScheme)
291  - fvm::laplacian(D, s, laplacianScheme)
292  ==
293  alpha*fvOptions_(s)
294  );
295 
296  sEqn.relax(relaxCoeff);
297  fvOptions_.constrain(sEqn);
298  sEqn.solve(schemesField_);
299 
300  tTPhiUD = sEqn.flux();
301  }
302 
303  if (bounded01_)
304  {
306  (
307  geometricOneField(),
308  s,
309  phi,
310  tTPhiUD.ref(),
311  oneField(),
312  zeroField()
313  );
314  }
315  }
316  else if (phi.dimensions() == dimMass/dimTime)
317  {
318  const volScalarField& rho = lookupObject<volScalarField>(rhoName_);
319 
320  for (label i = 0; i <= nCorr_; i++)
321  {
322 
323  fvScalarMatrix sEqn
324  (
325  fvm::ddt(rho, s)
326  + fvm::div(phi, s, divScheme)
327  - fvm::laplacian(D, s, laplacianScheme)
328  ==
329  fvOptions_(rho, s)
330  );
331 
332  sEqn.relax(relaxCoeff);
333 
334  fvOptions_.constrain(sEqn);
335 
336  sEqn.solve(schemesField_);
337  }
338  }
339  else if (phi.dimensions() == dimVolume/dimTime)
340  {
341  for (label i = 0; i <= nCorr_; i++)
342  {
343  fvScalarMatrix sEqn
344  (
345  fvm::ddt(s)
346  + fvm::div(phi, s, divScheme)
347  - fvm::laplacian(D, s, laplacianScheme)
348  ==
349  fvOptions_(s)
350  );
351 
352  sEqn.relax(relaxCoeff);
353 
354  fvOptions_.constrain(sEqn);
355 
356  sEqn.solve(schemesField_);
357  }
358  }
359  else
360  {
362  << "Incompatible dimensions for phi: " << phi.dimensions() << nl
363  << "Dimensions should be " << dimMass/dimTime << " or "
365  }
367  Log << endl;
368 
369  return true;
370 }
371 
372 
374 {
375  Log << type() << " write: " << name() << nl
376  << tab << fieldName_ << nl
377  << endl;
378 
379  volScalarField& s = transportedField();
380 
381  s.write();
382 
383  return true;
384 }
385 
386 
387 // ************************************************************************* //
Foam::surfaceFields.
dictionary dict
defineTypeNameAndDebug(ObukhovLength, 0)
fvMatrix< scalar > fvScalarMatrix
Definition: fvMatricesFwd.H:37
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
compressible::turbulenceModel & turb
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Calculate the matrix for the laplacian of the field.
vtkSmartPointer< vtkFloatArray > zeroField(const word &name, const label size)
Create named field initialized to zero.
constexpr char tab
The tab &#39;\t&#39; character(0x09)
Definition: Ostream.H:49
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:360
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Macros for easy insertion into run-time selection tables.
void setFluxRequired(const word &name) const
Set flux-required for given name (mutable)
virtual bool execute()
Calculate the scalarTransport.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
dimensionedScalar pos(const dimensionedScalar &ds)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:58
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
static const word propertiesName
Default name of the turbulence properties dictionary.
A class for handling words, derived from Foam::string.
Definition: word.H:63
tmp< fvMatrix< Type > > ddt(const GeometricField< Type, fvPatchField, volMesh > &vf)
Definition: fvmDdt.C:41
bool store(word &fieldName, const tmp< ObjectType > &tfield, bool cacheable=false)
Store the field in the (sub) objectRegistry under the given name.
Calculate the matrix for the first temporal derivative.
virtual bool read(const dictionary &)
Read the scalarTransport data.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:206
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: fvPatchField.H:64
SolverPerformance< Type > solve(const dictionary &)
Solve returning the solution statistics.
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
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmDiv.C:41
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
void relax(const scalar alpha)
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:1101
Calculate the matrix for the divergence of the given field and flux.
virtual bool write()
Do nothing.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:41
Nothing to be read.
#define Log
Definition: PDRblock.C:28
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
virtual bool read(const dictionary &dict)
Read optional controls.
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > flux() const
Return the face-flux field from the matrix.
Definition: fvMatrix.C:1422
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
const dimensionedScalar & D
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
A class for managing temporary objects.
Definition: HashPtrTable.H:50
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
void explicitSolve(const RdeltaTType &rDeltaT, const RhoType &rho, volScalarField &psi, const surfaceScalarField &phiPsi, const SpType &Sp, const SuType &Su)
Request registration (bool: true)
const fvMesh & mesh_
Reference to the fvMesh.
CMULES: Multidimensional universal limiter for explicit corrected implicit solution.
Calculate the finiteVolume matrix for implicit and explicit sources.
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127