All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
waxSolventEvaporation.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) 2017-2019 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 "waxSolventEvaporation.H"
28 #include "thermoSingleLayer.H"
29 #include "zeroField.H"
30 
31 #include "fvmDdt.H"
32 #include "fvmDiv.H"
33 #include "fvcDiv.H"
34 #include "fvmSup.H"
35 
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace regionModels
41 {
42 namespace surfaceFilmModels
43 {
44 
45 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
46 
47 defineTypeNameAndDebug(waxSolventEvaporation, 0);
48 
50 (
51  phaseChangeModel,
52  waxSolventEvaporation,
53  dictionary
54 );
55 
56 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
57 
59 (
60  const scalar Re,
61  const scalar Sc
62 ) const
63 {
64  if (Re < 5.0E+05)
65  {
66  return 0.664*sqrt(Re)*cbrt(Sc);
67  }
68  else
69  {
70  return 0.037*pow(Re, 0.8)*cbrt(Sc);
71  }
72 }
73 
74 
75 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
76 
78 (
80  const dictionary& dict
81 )
82 :
83  phaseChangeModel(typeName, film, dict),
84  Wwax_
85  (
86  IOobject
87  (
88  IOobject::modelName("Wwax", typeName),
89  film.regionMesh().time().constant(),
90  film.regionMesh()
91  ),
92  coeffDict_.lookup<scalar>("Wwax")
93  ),
94  Wsolvent_
95  (
96  IOobject
97  (
98  IOobject::modelName("Wsolvent", typeName),
99  film.regionMesh().time().constant(),
100  film.regionMesh()
101  ),
102  coeffDict_.lookup<scalar>("Wsolvent")
103  ),
104  Ysolvent0_
105  (
106  IOobject
107  (
108  IOobject::modelName("Ysolvent0", typeName),
109  film.regionMesh().time().constant(),
110  film.regionMesh(),
113  )
114  ),
115  Ysolvent_
116  (
117  IOobject
118  (
119  IOobject::modelName("Ysolvent", typeName),
120  film.regionMesh().time().timeName(),
121  film.regionMesh(),
124  ),
125  film.regionMesh()
126  ),
127  deltaMin_(coeffDict_.lookup<scalar>("deltaMin")),
128  L_(coeffDict_.lookup<scalar>("L")),
129  TbFactor_(coeffDict_.lookupOrDefault<scalar>("TbFactor", 1.1)),
130  YInfZero_(coeffDict_.lookupOrDefault<Switch>("YInfZero", false)),
131  activityCoeff_
132  (
133  Function1<scalar>::New("activityCoeff", coeffDict_)
134  )
135 {}
136 
137 
138 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
139 
141 {}
142 
143 
144 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
145 
146 template<class YInfType>
148 (
149  const scalar dt,
150  scalarField& availableMass,
151  scalarField& dMass,
152  scalarField& dEnergy,
153  YInfType YInf
154 )
155 {
156  const thermoSingleLayer& film = filmType<thermoSingleLayer>();
157 
158  const volScalarField& alpha = film.alpha();
159  const volScalarField& delta = film.delta();
160  const volScalarField& rho = film.rho();
161  const surfaceScalarField& phi = film.phi();
162 
163  // Set local thermo properties
164  const SLGThermo& thermo = film.thermo();
165  const filmThermoModel& filmThermo = film.filmThermo();
166  const label vapId = thermo.carrierId(filmThermo.name());
167 
168  // Retrieve fields from film model
169  const scalarField& pInf = film.pPrimary();
170  const scalarField& T = film.T();
171  const scalarField& h = film.h();
172  const scalarField& rhoInf = film.rhoPrimary();
173  const scalarField& muInf = film.muPrimary();
174  const scalarField& V = film.regionMesh().V();
175  const scalarField& magSf = film.magSf();
176  const scalarField& VbyA = film.VbyA();
177  const vectorField dU(film.UPrimary() - film.Us());
178  const scalarField limMass
179  (
180  max(scalar(0), availableMass - deltaMin_*rho*magSf)
181  );
182 
183  // Molecular weight of vapour [kg/kmol]
184  const scalar Wvap = thermo.carrier().Wi(vapId);
185 
186  const scalar Wwax = Wwax_.value();
187  const scalar Wsolvent = Wsolvent_.value();
188 
189  volScalarField::Internal evapRateCoeff
190  (
191  IOobject
192  (
193  IOobject::modelName("evapRateCoeff", typeName),
194  film.regionMesh().time().timeName(),
195  film.regionMesh(),
198  false
199  ),
200  film.regionMesh(),
202  );
203 
204  volScalarField::Internal evapRateInf
205  (
206  IOobject
207  (
208  IOobject::modelName("evapRateInf", typeName),
209  film.regionMesh().time().timeName(),
210  film.regionMesh(),
213  false
214  ),
215  film.regionMesh(),
216  dimensionedScalar(evapRateCoeff.dimensions(), 0)
217  );
218 
219  bool filmPresent = false;
220 
221  forAll(dMass, celli)
222  {
223  if (delta[celli] > deltaMin_)
224  {
225  filmPresent = true;
226 
227  const scalar Ysolvent = Ysolvent_[celli];
228 
229  // Molefraction of solvent in liquid film
230  const scalar Xsolvent
231  (
232  Ysolvent*Wsolvent/((1 - Ysolvent)*Wwax + Ysolvent*Wsolvent)
233  );
234 
235  // Primary region density [kg/m^3]
236  const scalar rhoInfc = rhoInf[celli];
237 
238  // Cell pressure [Pa]
239  const scalar pc = pInf[celli];
240 
241  // Calculate the boiling temperature
242  const scalar Tb = filmThermo.Tb(pc);
243 
244  // Local temperature - impose lower limit of 200 K for stability
245  const scalar Tloc = min(TbFactor_*Tb, max(200.0, T[celli]));
246 
247  const scalar pPartialCoeff
248  (
249  filmThermo.pv(pc, Tloc)*activityCoeff_->value(Xsolvent)
250  );
251 
252  scalar XsCoeff = pPartialCoeff/pc;
253 
254  // Vapour phase mole fraction of solvent at interface
255  scalar Xs = XsCoeff*Xsolvent;
256 
257  if (Xs > 1)
258  {
260  << "Solvent vapour pressure > ambient pressure"
261  << endl;
262 
263  XsCoeff /= Xs;
264  Xs = 1;
265  }
266 
267  // Vapour phase mass fraction of solvent at the interface
268  const scalar YsCoeff
269  (
270  XsCoeff/(XsCoeff*Xsolvent*Wsolvent + (1 - Xs)*Wvap)
271  );
272 
273  // Primary region viscosity [Pa.s]
274  const scalar muInfc = muInf[celli];
275 
276  // Reynolds number
277  const scalar Re = rhoInfc*mag(dU[celli])*L_/muInfc;
278 
279  // Vapour diffusivity [m^2/s]
280  const scalar Dab = filmThermo.D(pc, Tloc);
281 
282  // Schmidt number
283  const scalar Sc = muInfc/(rhoInfc*(Dab + rootVSmall));
284 
285  // Sherwood number
286  const scalar Sh = this->Sh(Re, Sc);
287 
288  // Mass transfer coefficient [kg/m^3 s]
289  evapRateCoeff[celli] =
290  rhoInfc*Sh*Dab/(VbyA[celli]*(L_ + rootVSmall));
291 
292  // Solvent mass transfer
293  const scalar dm
294  (
295  max
296  (
297  dt*V[celli]
298  *evapRateCoeff[celli]*(YsCoeff*Ysolvent - YInf[celli]),
299  0
300  )
301  );
302 
303  if (dm > limMass[celli])
304  {
305  evapRateCoeff[celli] *= limMass[celli]/dm;
306  }
307 
308  evapRateInf[celli] = evapRateCoeff[celli]*YInf[celli];
309  evapRateCoeff[celli] *= YsCoeff;
310 
311  // hVap[celli] = filmThermo.hl(pc, Tloc);
312  }
313  }
314 
315  const dimensionedScalar rho0Bydt
316  (
317  "rho0Bydt",
319  rootVSmall/dt
320  );
321 
322  volScalarField::Internal impingementRate
323  (
324  max
325  (
326  -film.rhoSp(),
327  dimensionedScalar(film.rhoSp().dimensions(), 0)
328  )
329  );
330 
331  if (filmPresent)
332  {
333  // Solve for the solvent mass fraction
334  fvScalarMatrix YsolventEqn
335  (
336  fvm::ddt(alpha, rho, Ysolvent_) + fvm::div(phi, Ysolvent_)
337  - fvm::Sp(film.continuityErr(), Ysolvent_)
338  ==
339  rho0Bydt*Ysolvent_()
340 
341  + evapRateInf
342 
343  // Include the effect of the impinging droplets
344  // added with Ysolvent = Ysolvent0
345  + impingementRate*Ysolvent0_
346 
347  - fvm::Sp
348  (
349  rho0Bydt
350  + evapRateCoeff
351  + film.rhoSp()
352  + impingementRate,
353  Ysolvent_
354  )
355  );
356 
357  YsolventEqn.relax();
358  YsolventEqn.solve();
359 
360  Ysolvent_.min(1);
361  Ysolvent_.max(0);
362 
363  scalarField dm
364  (
365  dt*V*rhoInf*(evapRateCoeff*Ysolvent_ + evapRateInf)
366  );
367 
368  dMass += dm;
369 
370  // Heat is assumed to be removed by heat-transfer to the wall
371  // so the energy remains unchanged by the phase-change.
372  dEnergy += dm*h;
373 
374  // Latent heat [J/kg]
375  // dEnergy += dm*(h[celli] + hVap);
376  }
377 }
378 
379 
381 (
382  const scalar dt,
383  scalarField& availableMass,
384  scalarField& dMass,
385  scalarField& dEnergy
386 )
387 {
388  if (YInfZero_)
389  {
390  correctModel(dt, availableMass, dMass, dEnergy, zeroField());
391  }
392  else
393  {
394  const thermoSingleLayer& film = filmType<thermoSingleLayer>();
395  const label vapId = film.thermo().carrierId(film.filmThermo().name());
396  const scalarField& YInf = film.YPrimary()[vapId];
397 
398  correctModel(dt, availableMass, dMass, dEnergy, YInf);
399  }
400 }
401 
402 
403 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
404 
405 } // End namespace surfaceFilmModels
406 } // End namespace regionModels
407 } // End namespace Foam
408 
409 // ************************************************************************* //
scalar delta
Top level data entry class for use in dictionaries. Provides a mechanism to specify a variable as a c...
Definition: Function1.H:52
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
const volScalarField & VbyA() const
Return the cell layer volume/area [m].
virtual const word & name() const =0
Return the specie name.
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
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
autoPtr< Function1< scalar > > activityCoeff_
Activity coefficient as a function of solvent mole fraction.
uniformDimensionedScalarField Wwax_
Molecular weight of wax [kg/kmol].
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none/any.
Definition: Switch.H:60
virtual scalar Wi(const label speciei) const =0
Molecular weight of the given specie [kg/kmol].
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:622
const volScalarField & rhoPrimary() const
Density [kg/m^3].
tmp< fvMatrix< Type > > Sp(const volScalarField::Internal &, const GeometricField< Type, fvPatchField, volMesh > &)
rhoReactionThermo & thermo
Definition: createFields.H:28
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:239
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
const scalar deltaMin_
Minimum film height for model to be active.
volScalarField::Internal & rhoSp()
Mass [kg/m^2/s].
addToRunTimeSelectionTable(surfaceFilmRegionModel, kinematicSingleLayer, mesh)
Macros for easy insertion into run-time selection tables.
phi
Definition: pEqn.H:104
Base class for surface film phase change models.
const volScalarField & muPrimary() const
Viscosity [Pa.s].
const filmThermoModel & filmThermo() const
Film thermo.
const dimensionSet & dimensions() const
Return dimensions.
const volVectorField & UPrimary() const
Velocity [m/s].
virtual Type value(const scalar x) const =0
Return value as a function of (scalar) independent variable.
A class representing the concept of a field of 0 used to avoid unnecessary manipulations for objects ...
Definition: zeroField.H:50
dimensionedScalar cbrt(const dimensionedScalar &ds)
tmp< fvMatrix< Type > > ddt(const GeometricField< Type, fvPatchField, volMesh > &vf)
Definition: fvmDdt.C:46
Calculate the matrix for the first temporal derivative.
const word & constant() const
Return constant name.
Definition: TimePaths.H:124
const Type & value() const
Return const reference to value.
const surfaceScalarField & phi() const
Return the film flux [kg m/s].
const fvMesh & regionMesh() const
Return the region mesh database.
Definition: regionModelI.H:61
const PtrList< volScalarField > & YPrimary() const
Specie mass fractions [0-1].
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:72
const volScalarField::Internal & continuityErr() const
Return the current continuity error.
void min(const dimensioned< Type > &)
Thermo package for (S)olids (L)iquids and (G)ases Takes reference to thermo package, and provides:
Definition: SLGThermo.H:62
virtual scalar D(const scalar p, const scalar T) const =0
Return diffusivity [m^2/s].
virtual scalar Tb(const scalar p) const =0
Return boiling temperature [K].
const volScalarField & pPrimary() const
Pressure [Pa].
Calculate the divergence of the given field.
SolverPerformance< Type > solve(const dictionary &)
Solve segregated or coupled returning the solution statistics.
Definition: fvMatrixSolve.C:58
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmDiv.C:46
uniformDimensionedScalarField Wsolvent_
Molecular weight of liquid [kg/kmol].
void relax(const scalar alpha)
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:521
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const volScalarField & delta() const
Return const access to the film thickness [m].
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
const dimensionSet dimDensity
const basicSpecieMixture & carrier() const
Return reference to the gaseous components.
Definition: SLGThermo.C:108
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Calculate the matrix for the divergence of the given field and flux.
label carrierId(const word &cmptName, bool allowNotFound=false) const
Index of carrier component.
Definition: SLGThermo.C:148
const volScalarField::Internal & magSf() const
Return the face area magnitudes [m^2].
#define WarningInFunction
Report a warning using Foam::Warning.
const volVectorField::Internal & Us() const
Return the film surface velocity [m/s].
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
void max(const dimensioned< Type > &)
virtual const volScalarField & h() const
Return the film sensible enthalpy [J/kg].
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
dimensioned< scalar > mag(const dimensioned< Type > &)
const dimensionedScalar & h
Planck constant.
scalar Sh(const scalar Re, const scalar Sc) const
Return Sherwood number as a function of Reynolds and Schmidt numbers.
const volScalarField & rho() const
Return the film density [kg/m^3].
static word modelName(Name name, const word &model)
Return the name of the object within the given model.
volScalarField alpha(IOobject("alpha", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
uniformDimensionedScalarField Ysolvent0_
Initial solvent mass-fraction.
waxSolventEvaporation(surfaceFilmRegionModel &film, const dictionary &dict)
Construct from surface film model.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
defineTypeNameAndDebug(kinematicSingleLayer, 0)
const SLGThermo & thermo() const
Return const reference to the SLGThermo object.
void correctModel(const scalar dt, scalarField &availableMass, scalarField &dMass, scalarField &dEnergy, YInfType YInf)
Calculate the matrix for implicit and explicit sources.
virtual scalar pv(const scalar p, const scalar T) const =0
Return vapour pressure [Pa].
Thermodynamic form of single-cell layer surface film model.
const volScalarField & alpha() const
Return const access to the film volume fraction [].
Namespace for OpenFOAM.
virtual const volScalarField & T() const
Return the film mean temperature [K].