Fickian.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 "Fickian.H"
27 #include "fvcDiv.H"
28 #include "fvcLaplacian.H"
29 #include "fvcSnGrad.H"
30 #include "fvmSup.H"
31 #include "surfaceInterpolate.H"
32 #include "Function2Evaluate.H"
33 
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 
41 template<class BasicThermophysicalTransportModel>
43 {
44  const PtrList<volScalarField>& Y = this->thermo().Y();
45  const volScalarField& p = this->thermo().p();
46  const volScalarField& T = this->thermo().T();
47 
48  Dm_.setSize(Y.size());
49 
50  if (mixtureDiffusionCoefficients_)
51  {
52  forAll(Y, i)
53  {
54  Dm_.set(i, evaluate(DmFuncs_[i], dimKinematicViscosity, p, T));
55  }
56  }
57  else
58  {
59  const volScalarField Wm(this->thermo().W());
60  volScalarField sumXbyD
61  (
63  (
64  "sumXbyD",
65  T.mesh(),
66  dimless/dimKinematicViscosity/Wm.dimensions()
67  )
68  );
69 
70  forAll(Dm_, i)
71  {
72  sumXbyD = Zero;
73 
74  forAll(Y, j)
75  {
76  if (j != i)
77  {
78  sumXbyD +=
79  Y[j]
80  /(
81  this->thermo().Wi(j)
82  *(
83  i < j
84  ? evaluate
85  (
86  DFuncs_[i][j],
88  p,
89  T
90  )
91  : evaluate
92  (
93  DFuncs_[j][i],
95  p,
96  T
97  )
98  )
99  );
100  }
101  }
102 
103  Dm_.set
104  (
105  i,
106  (1/Wm - Y[i]/this->thermo().Wi(i))
107  /max(sumXbyD, dimensionedScalar(sumXbyD.dimensions(), small))
108  );
109  }
110  }
111 }
112 
113 
114 template<class BasicThermophysicalTransportModel>
117 {
118  if (!Dm_.size())
119  {
120  updateDm();
121  }
122 
123  return Dm_;
124 }
125 
126 
127 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
128 
129 template<class BasicThermophysicalTransportModel>
131 (
132  const word& type,
133  const momentumTransportModel& momentumTransport,
134  const thermoModel& thermo
135 )
136 :
137  BasicThermophysicalTransportModel
138  (
139  type,
140  momentumTransport,
141  thermo
142  ),
143 
145 
146  mixtureDiffusionCoefficients_(true),
147 
148  DFuncs_(this->thermo().species().size()),
149 
150  DmFuncs_(this->thermo().species().size()),
151 
152  DTFuncs_
153  (
154  this->typeDict(type).found("DT")
155  ? this->thermo().species().size()
156  : 0
157  )
158 {}
159 
160 
161 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
162 
163 template<class BasicThermophysicalTransportModel>
165 {
167  {
168  const speciesTable& species = this->thermo().species();
169 
170  const dictionary& coeffDict = this->typeDict();
171 
172  coeffDict.lookup("mixtureDiffusionCoefficients")
173  >> mixtureDiffusionCoefficients_;
174 
175  if (mixtureDiffusionCoefficients_)
176  {
177  const dictionary& Ddict = coeffDict.subDict("Dm");
178 
179  forAll(species, i)
180  {
181  DmFuncs_.set
182  (
183  i,
185  (
186  species[i],
187  dimPressure,
190  Ddict
191  ).ptr()
192  );
193  }
194  }
195  else
196  {
197  const dictionary& Ddict = coeffDict.subDict("D");
198 
199  // Read the array of specie binary mass diffusion coefficient
200  // functions
201  forAll(species, i)
202  {
203  DFuncs_[i].setSize(species.size());
204 
205  forAll(species, j)
206  {
207  if (j >= i)
208  {
209  const word nameij(species[i] + '-' + species[j]);
210  const word nameji(species[j] + '-' + species[i]);
211 
212  word Dname;
213 
214  if (Ddict.found(nameij) && Ddict.found(nameji))
215  {
216  if (i != j)
217  {
219  << "Binary mass diffusion coefficients "
220  "for Both " << nameij
221  << " and " << nameji << " provided, using "
222  << nameij << endl;
223  }
224 
225  Dname = nameij;
226  }
227  else if (Ddict.found(nameij))
228  {
229  Dname = nameij;
230  }
231  else if (Ddict.found(nameji))
232  {
233  Dname = nameji;
234  }
235  else
236  {
238  << "Binary mass diffusion coefficient for pair "
239  << nameij << " or " << nameji << " not provided"
240  << exit(FatalIOError);
241  }
242 
243  DFuncs_[i].set
244  (
245  j,
247  (
248  Dname,
249  dimPressure,
252  Ddict
253  ).ptr()
254  );
255  }
256  }
257  }
258  }
259 
260  // Optionally read the List of specie Soret thermal diffusion
261  // coefficient functions
262  if (coeffDict.found("DT"))
263  {
264  const dictionary& DTdict = coeffDict.subDict("DT");
265 
266  forAll(species, i)
267  {
268  DTFuncs_.set
269  (
270  i,
272  (
273  species[i],
274  dimPressure,
277  DTdict
278  ).ptr()
279  );
280  }
281  }
282 
283  return true;
284  }
285  else
286  {
287  return false;
288  }
289 }
290 
291 
292 template<class BasicThermophysicalTransportModel>
294 (
295  const volScalarField& Yi
296 ) const
297 {
298  return volScalarField::New
299  (
300  "D",
301  this->momentumTransport().rho()
302  *Dm()[this->thermo().specieIndex(Yi)]
303  );
304 }
305 
306 
307 template<class BasicThermophysicalTransportModel>
309 (
310  const volScalarField& Yi,
311  const label patchi
312 ) const
313 {
314  return
315  this->momentumTransport().rho().boundaryField()[patchi]
316  *Dm()[this->thermo().specieIndex(Yi)].boundaryField()[patchi];
317 }
318 
319 
320 template<class BasicThermophysicalTransportModel>
322 (
323  const volScalarField& Yi
324 ) const
325 {
326  return volScalarField::New
327  (
328  "DEff",
329  this->momentumTransport().rho()
330  *Dm()[this->thermo().specieIndex(Yi)]
331  );
332 }
333 
334 
335 template<class BasicThermophysicalTransportModel>
337 (
338  const volScalarField& Yi,
339  const label patchi
340 ) const
341 {
342  return
343  this->momentumTransport().rho().boundaryField()[patchi]
344  *Dm()[this->thermo().specieIndex(Yi)].boundaryField()[patchi];
345 }
346 
347 
348 template<class BasicThermophysicalTransportModel>
350 {
352  (
354  (
356  (
357  "q",
358  this->thermo().phaseName()
359  ),
360  -fvc::interpolate(this->alpha()*this->kappaEff())
361  *fvc::snGrad(this->thermo().T())
362  )
363  );
364 
365  const PtrList<volScalarField>& Y = this->thermo().Y();
366  const volScalarField& p = this->thermo().p();
367  const volScalarField& T = this->thermo().T();
368 
369  if (Y.size())
370  {
371  surfaceScalarField sumJ
372  (
374  (
375  "sumJ",
376  Y[0].mesh(),
378  )
379  );
380 
381  surfaceScalarField sumJh
382  (
384  (
385  "sumJh",
386  Y[0].mesh(),
388  )
389  );
390 
391  forAll(Y, i)
392  {
393  if (i != this->thermo().defaultSpecie())
394  {
395  const volScalarField hi(this->thermo().hsi(i, p, T));
396 
397  const surfaceScalarField ji(this->j(Y[i]));
398 
399  sumJ += ji;
400 
401  sumJh += ji*fvc::interpolate(hi);
402  }
403  }
404 
405  {
406  const label i = this->thermo().defaultSpecie();
407 
408  const volScalarField hi(this->thermo().hsi(i, p, T));
409 
410  sumJh -= sumJ*fvc::interpolate(hi);
411  }
412 
413  tmpq.ref() += sumJh;
414  }
415 
416  return tmpq;
417 }
418 
419 
420 template<class BasicThermophysicalTransportModel>
422 (
423  const label patchi
424 ) const
425 {
426  tmp<scalarField> tmpq
427  (
428  - (
429  this->alpha().boundaryField()[patchi]
430  *this->kappaEff(patchi)
431  *this->thermo().T().boundaryField()[patchi].snGrad()
432  )
433  );
434 
435  const PtrList<volScalarField>& Y = this->thermo().Y();
436  const scalarField& p = this->thermo().p().boundaryField()[patchi];
437  const scalarField& T = this->thermo().T().boundaryField()[patchi];
438 
439  if (Y.size())
440  {
441  scalarField sumJ(tmpq->size(), scalar(0));
442  scalarField sumJh(tmpq->size(), scalar(0));
443 
444  forAll(Y, i)
445  {
446  if (i != this->thermo().defaultSpecie())
447  {
448  const scalarField hi(this->thermo().hsi(i, p, T));
449 
450  const scalarField ji(this->j(Y[i], patchi));
451 
452  sumJ += ji;
453 
454  sumJh += ji*hi;
455  }
456  }
457 
458  {
459  const label i = this->thermo().defaultSpecie();
460 
461  const scalarField hi(this->thermo().hsi(i, p, T));
462 
463  sumJh -= sumJ*hi;
464  }
465 
466  tmpq.ref() += sumJh;
467  }
468 
469  return tmpq;
470 }
471 
472 
473 template<class BasicThermophysicalTransportModel>
475 (
476  volScalarField& he
477 ) const
478 {
479  tmp<fvScalarMatrix> tmpDivq
480  (
481  fvm::Su
482  (
483  -fvc::laplacian(this->alpha()*this->kappaEff(), this->thermo().T()),
484  he
485  )
486  );
487 
488  const PtrList<volScalarField>& Y = this->thermo().Y();
489  const volScalarField& p = this->thermo().p();
490  const volScalarField& T = this->thermo().T();
491 
492  tmpDivq.ref() -=
493  fvm::laplacianCorrection(this->alpha()*this->alphaEff(), he);
494 
495  surfaceScalarField sumJ
496  (
498  (
499  "sumJ",
500  he.mesh(),
502  )
503  );
504 
505  surfaceScalarField sumJh
506  (
508  (
509  "sumJh",
510  he.mesh(),
511  dimensionedScalar(sumJ.dimensions()*he.dimensions(), 0)
512  )
513  );
514 
515  forAll(Y, i)
516  {
517  if (i != this->thermo().defaultSpecie())
518  {
519  const volScalarField hi(this->thermo().hsi(i, p, T));
520 
521  const surfaceScalarField ji(this->j(Y[i]));
522 
523  sumJ += ji;
524 
525  sumJh += ji*fvc::interpolate(hi);
526  }
527  }
528 
529  {
530  const label i = this->thermo().defaultSpecie();
531 
532  const volScalarField hi(this->thermo().hsi(i, p, T));
533 
534  sumJh -= sumJ*fvc::interpolate(hi);
535  }
536 
537  tmpDivq.ref() += fvc::div(sumJh*he.mesh().magSf());
538 
539  return tmpDivq;
540 }
541 
542 
543 template<class BasicThermophysicalTransportModel>
545 (
546  const volScalarField& Yi
547 ) const
548 {
549  if (DTFuncs_.size())
550  {
551  const volScalarField& p = this->thermo().p();
552  const volScalarField& T = this->thermo().T();
553 
554  return
555  BasicThermophysicalTransportModel::j(Yi)
557  (
558  evaluate
559  (
560  DTFuncs_[this->thermo().specieIndex(Yi)],
562  p,
563  T
564  )
565  )
567  }
568  else
569  {
570  return BasicThermophysicalTransportModel::j(Yi);
571  }
572 }
573 
574 
575 template<class BasicThermophysicalTransportModel>
577 (
578  const volScalarField& Yi,
579  const label patchi
580 ) const
581 {
582  if (DTFuncs_.size())
583  {
584  const scalarField& p = this->thermo().p().boundaryField()[patchi];
585  const scalarField& T = this->thermo().T().boundaryField()[patchi];
586 
587  return
588  BasicThermophysicalTransportModel::j(Yi, patchi)
589  - DTFuncs_[this->thermo().specieIndex(Yi)].value(p, T)
590  *this->thermo().T().boundaryField()[patchi].snGrad()/T;
591  }
592  else
593  {
594  return BasicThermophysicalTransportModel::j(Yi, patchi);
595  }
596 }
597 
598 
599 template<class BasicThermophysicalTransportModel>
601 (
602  volScalarField& Yi
603 ) const
604 {
605  if (DTFuncs_.size())
606  {
607  const volScalarField& p = this->thermo().p();
608  const volScalarField& T = this->thermo().T();
609 
610  return
611  BasicThermophysicalTransportModel::divj(Yi)
612  - fvc::div
613  (
615  (
616  evaluate
617  (
618  DTFuncs_[this->thermo().specieIndex(Yi)],
620  p,
621  T
622  )
623  )
625  *T.mesh().magSf()
626  );
627  }
628  else
629  {
630  return BasicThermophysicalTransportModel::divj(Yi);
631  }
632 }
633 
634 
635 template<class BasicThermophysicalTransportModel>
637 {
638  BasicThermophysicalTransportModel::predict();
639  updateDm();
640 }
641 
642 
643 template<class BasicThermophysicalTransportModel>
645 {
646  return true;
647 }
648 
649 
650 template<class BasicThermophysicalTransportModel>
652 (
653  const polyTopoChangeMap& map
654 )
655 {
656  // Delete the cached Dm, will be re-created in predict
657  Dm_.clear();
658 }
659 
660 
661 template<class BasicThermophysicalTransportModel>
663 (
664  const polyMeshMap& map
665 )
666 {
667  // Delete the cached Dm, will be re-created in predict
668  Dm_.clear();
669 }
670 
671 
672 template<class BasicThermophysicalTransportModel>
674 (
675  const polyDistributionMap& map
676 )
677 {
678  // Delete the cached Dm, will be re-created in predict
679  Dm_.clear();
680 }
681 
682 
683 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
684 
685 } // End namespace Foam
686 
687 // ************************************************************************* //
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
const dimensionSet & dimensions() const
Return dimensions.
const GeoMesh & mesh() const
Return mesh.
virtual bool movePoints()
Update for mesh motion.
Definition: Fickian.C:644
virtual tmp< volScalarField > DEff(const volScalarField &Yi) const
Effective mass diffusion coefficient.
Definition: Fickian.C:322
virtual tmp< fvScalarMatrix > divq(volScalarField &he) const
Return the source term for the energy equation.
Definition: Fickian.C:475
virtual tmp< fvScalarMatrix > divj(volScalarField &Yi) const
Return the source term for the given specie mass-fraction equation.
Definition: Fickian.C:601
virtual void predict()
Update the diffusion coefficients.
Definition: Fickian.C:636
virtual void mapMesh(const polyMeshMap &map)
Update from another mesh using the given map.
Definition: Fickian.C:663
virtual tmp< surfaceScalarField > j(const volScalarField &Yi) const
Return the specie flux for the given specie mass-fraction [kg/m^2/s].
Definition: Fickian.C:545
virtual tmp< surfaceScalarField > q() const
Return the heat flux [W/m^2].
Definition: Fickian.C:349
virtual void distribute(const polyDistributionMap &map)
Redistribute or update using the given distribution map.
Definition: Fickian.C:674
BasicThermophysicalTransportModel::thermoModel thermoModel
Definition: Fickian.H:105
virtual tmp< volScalarField > D(const volScalarField &Yi) const
Mass diffusivity.
Definition: Fickian.C:294
BasicThermophysicalTransportModel::momentumTransportModel momentumTransportModel
Definition: Fickian.H:102
Fickian(const word &type, const momentumTransportModel &momentumTransport, const thermoModel &thermo)
Construct from a momentum transport model and a thermo model.
Definition: Fickian.C:131
virtual void topoChange(const polyTopoChangeMap &map)
Update topology using the given map.
Definition: Fickian.C:652
virtual bool read()
Read thermophysicalTransport dictionary.
Definition: Fickian.C:164
Run-time selectable function of two variables.
Definition: Function2.H:62
static autoPtr< Function2< Type > > New(const word &name, const Function2s::unitSets &units, const dictionary &dict)
Select from dictionary.
Definition: Function2New.C:32
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
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,.
static word groupName(Name name, const word &group)
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
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
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
virtual const volScalarField & T() const =0
Temperature [K].
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:669
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:778
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:468
virtual const volScalarField & p() const =0
Pressure [Pa].
A wordList with hashed indices for faster lookup by name.
virtual const speciesTable & species() const =0
Return the table of species.
virtual PtrList< volScalarField > & Y()=0
Access the mass-fraction fields.
virtual dimensionedScalar Wi(const label speciei) const =0
Molecular weight [kg/kmol].
virtual label defaultSpecie() const =0
The index of the default specie.
label specieIndex(const volScalarField &Yi) const
Access the specie index of the given mass-fraction field.
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.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Base class for multi-component Fickian based temperature gradient heat flux models with optional Sore...
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 FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
Calculate the divergence of the given field.
Calculate the laplacian of the given field.
Calculate the snGrad of the given volField.
Calculate the matrix for implicit and explicit sources.
label patchi
rho
Definition: pEqn.H:1
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
#define WarningInFunction
Report a warning using Foam::Warning.
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
tmp< VolField< Type > > laplacian(const VolField< Type > &vf, const word &name)
Definition: fvcLaplacian.C:45
tmp< VolField< Type > > div(const SurfaceField< Type > &ssf)
Definition: fvcDiv.C:47
tmp< SurfaceField< Type > > snGrad(const VolField< Type > &vf, const word &name)
Definition: fvcSnGrad.C:45
tmp< fvMatrix< Type > > laplacianCorrection(const VolField< scalar > &gamma, const VolField< Type > &vf)
Definition: fvmLaplacian.C:340
tmp< fvMatrix< Type > > Su(const DimensionedField< Type, fvMesh > &, const VolField< Type > &)
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
const dimensionSet & dimless
Definition: dimensions.C:138
const dimensionSet & dimKinematicViscosity
Definition: dimensions.C:171
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
const dimensionSet & dimDynamicViscosity
Definition: dimensions.C:173
const dimensionSet & dimMass
Definition: dimensions.C:140
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
scalarList W(const fluidMulticomponentThermo &thermo)
void evaluate(GeometricField< Type, GeoMesh > &result, const Function1< Type > &func, const GeometricField< Type, GeoMesh > &x)
const dimensionSet & dimTime
Definition: dimensions.C:142
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
const dimensionSet & dimPressure
Definition: dimensions.C:163
IOerror FatalIOError
const dimensionSet & dimEnergy
Definition: dimensions.C:160
const dimensionSet & dimArea
Definition: dimensions.C:149
void T(GeometricField< Type, GeoMesh, PrimitiveField1 > &gf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf1)
const dimensionSet & dimTemperature
Definition: dimensions.C:143
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
volScalarField & p
PtrList< volScalarField > & Y
fluidMulticomponentThermo & thermo
Definition: createFields.H:15