heatTransferLimitedPhaseChange.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) 2024-2025 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 
27 #include "fvmSup.H"
28 #include "multiphaseEuler.H"
31 
32 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 namespace fv
37 {
40  (
41  fvModel,
44  );
45 }
46 }
47 
48 
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 
51 void Foam::fv::heatTransferLimitedPhaseChange::readCoeffs
52 (
53  const dictionary& dict
54 )
55 {
56  saturationModelPtr_.reset
57  (
59  (
60  "saturationTemperature",
61  dict
62  ).ptr()
63  );
64 
65  pressureImplicit_ = dict.lookup<bool>("pressureImplicit");
66 
67  if (pressureImplicit_ && !dmDotdpPtr_.valid())
68  {
69  dmDotdpPtr_.set
70  (
72  (
73  IOobject
74  (
75  name() + ":dmDotdp",
76  mesh().time().name(),
77  mesh(),
80  ),
81  mesh(),
83  )
84  );
85  }
86 
87  if (!pressureImplicit_ && dmDotdpPtr_.valid())
88  {
89  dmDotdpPtr_.clear();
90  }
91 }
92 
93 
94 void Foam::fv::heatTransferLimitedPhaseChange::correctMDot() const
95 {
96  Info<< type() << ": " << name() << endl << incrIndent;
97 
98  const volScalarField::Internal& p = this->p();
99  const volScalarField::Internal& T1 = phase1_.thermo().T();
100  const volScalarField::Internal& T2 = phase2_.thermo().T();
101 
102  // Saturation temperature
103  const volScalarField::Internal Tsat(saturationModelPtr_->Tsat(p));
104  infoField("Tsat", Tsat);
105 
106  // Latent heat
107  const volScalarField::Internal L(this->L(Tsat));
108 
109  // Heat transfer coefficients
110  const Pair<tmp<volScalarField>> Hs =
111  solver_.heatTransfer.Hs(phase1_, phase2_, scalar(0));
112  const volScalarField::Internal& H1 = Hs.first();
113  const volScalarField::Internal& H2 = Hs.second();
114 
115  // Relaxation factor
116  const scalar f = mesh().solution().fieldRelaxationFactor(mDot_.member());
117 
118  // Recalculate the phase change rate
119  mDot_ = (1 - f)*mDot_ + f*(H1*(T1 - Tsat) + H2*(T2 - Tsat))/L;
120  infoField("mDot", mDot_);
121 
122  // Recalculate the phase change rate derivative w.r.t. pressure
123  if (pressureImplicit_)
124  {
125  // Saturation temperature derivative w.r.t. pressure
126  const volScalarField::Internal TsatPrime
127  (
128  saturationModelPtr_->TsatPrime(p)
129  );
130 
131  dmDotdpPtr_() = (1 - f)*dmDotdpPtr_() - f*(H1 + H2)*TsatPrime/L;
132  }
133 
134  Info<< decrIndent;
135 }
136 
137 
138 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
139 
141 (
142  const word& name,
143  const word& modelType,
144  const fvMesh& mesh,
145  const dictionary& dict
146 )
147 :
148  phaseChange(name, modelType, mesh, dict, wordList()),
149  solver_(mesh().lookupObject<solvers::multiphaseEuler>(solver::typeName)),
150  fluid_(solver_.fluid),
151  phase1_(fluid_.phases()[phaseNames().first()]),
152  phase2_(fluid_.phases()[phaseNames().second()]),
153  saturationModelPtr_(nullptr),
154  pressureImplicit_(false),
155  pressureEquationIndex_(-1),
156  mDot_
157  (
158  IOobject
159  (
160  name + ":mDot",
161  mesh.time().name(),
162  mesh,
163  IOobject::READ_IF_PRESENT,
164  IOobject::AUTO_WRITE
165  ),
166  mesh,
168  ),
169  dmDotdpPtr_(nullptr)
170 {
171  readCoeffs(coeffs(dict));
172 }
173 
174 
175 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
176 
179 {
180  // Heat transfer coefficients
181  const Pair<tmp<volScalarField>> Hs =
182  solver_.heatTransfer.Hs(phase1_, phase2_);
183  const volScalarField::Internal& H1 = Hs.first();
184  const volScalarField::Internal& H2 = Hs.second();
185 
186  return H2/(H1 + H2);
187 }
188 
189 
192 {
193  return mDot_;
194 }
195 
196 
198 (
199  const volScalarField& alpha,
200  const volScalarField& rho,
201  fvMatrix<scalar>& eqn
202 ) const
203 {
204  // Pressure equation (i.e., continuity, linearised in the pressure)
205  if
206  (
207  (&alpha == &phase1_ || &alpha == &phase2_)
208  && (&rho == &phase1_.rho() || &rho == &phase2_.rho())
209  && &eqn.psi() == &solver_.p_rgh
210  )
211  {
212  // Ensure that the source is up-to date if this is the first call in
213  // the current phase loop
214  if (pressureEquationIndex_ % 2 == 0) correctMDot();
215  pressureEquationIndex_ ++;
216 
217  // Add linearisation if necessary
218  if (pressureImplicit_)
219  {
220  const label s = &alpha == &phase1_ ? -1 : +1;
221 
222  eqn += correction(fvm::Sp(s*dmDotdpPtr_(), eqn.psi()));
223  }
224  }
225 
226  // Let the base class add the actual source
228 }
229 
230 
232 {
233  // Reset the p_rgh equation solution counter
234  pressureEquationIndex_ = 0;
235 
236  // Correct the total phase change rate
237  correctMDot();
238 }
239 
240 
242 {
243  if (phaseChange::read(dict))
244  {
245  readCoeffs(coeffs(dict));
246  return true;
247  }
248  else
249  {
250  return false;
251  }
252 }
253 
254 
255 // ************************************************************************* //
Macros for easy insertion into run-time selection tables.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Generic GeometricField class.
DimensionedField< Type, GeoMesh, PrimitiveField > Internal
Type of the internal field from which this GeometricField is derived.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
An ordered pair of two objects of type <Type> with first() and second() elements.
Definition: Pair.H:67
const Type & second() const
Return second.
Definition: PairI.H:121
const Type & first() const
Return first.
Definition: PairI.H:107
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
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 fvSolution & solution() const
Return the fvSolution.
Definition: fvMesh.C:1803
Finite volume model abstract base class.
Definition: fvModel.H:60
static const dictionary & coeffs(const word &modelType, const dictionary &)
Return the coefficients sub-dictionary for a given model type.
Definition: fvModelI.H:31
const fvMesh & mesh() const
Return const access to the mesh database.
Definition: fvModelI.H:69
const word & name() const
Return const access to the source name.
Definition: fvModelI.H:57
Model for heat transfer rate limited phase change between two phases.
virtual tmp< DimensionedField< scalar, fvMesh > > Lfraction() const
Return the fraction of the latent heat that is transferred into.
virtual tmp< DimensionedField< scalar, fvMesh > > mDot() const
Return the mass transfer rate.
virtual bool read(const dictionary &dict)
Read source dictionary.
void addSup(const volScalarField &alpha, const volScalarField &rho, const volScalarField &heOrYi, fvMatrix< scalar > &eqn) const
Use phaseChange's source functions.
Definition: phaseChange.C:529
heatTransferLimitedPhaseChange(const word &name, const word &modelType, const fvMesh &mesh, const dictionary &dict)
Construct from explicit source name and mesh.
virtual void addSup(fvMatrix< scalar > &eqn) const
Add a source term to a field-less proxy equation.
Definition: massTransfer.C:223
Base class for phase change models.
Definition: phaseChange.H:61
virtual bool read(const dictionary &dict)
Read source dictionary.
Definition: phaseChange.C:602
static autoPtr< saturationTemperatureModel > New(const word &name, const dictionary &dict)
Select with name within a dictionary.
scalar fieldRelaxationFactor(const word &name) const
Return the relaxation factor for the given field.
Definition: solution.C:174
Abstract base class for run-time selectable region solvers.
Definition: solver.H:56
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...
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)
Calculate the matrix for implicit and explicit sources.
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
rho
Definition: pEqn.H:1
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
const dimensionSet time
addToRunTimeSelectionTable(fvConstraint, bound, dictionary)
defineTypeNameAndDebug(bound, 0)
tmp< fvMatrix< Type > > Sp(const volScalarField::Internal &, const VolField< Type > &)
Namespace for OpenFOAM.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:272
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
labelList second(const UList< labelPair > &p)
Definition: patchToPatch.C:49
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:265
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
const dimensionSet & dimTime
Definition: dimensions.C:142
const dimensionSet & dimDensity
Definition: dimensions.C:158
const dimensionSet & dimPressure
Definition: dimensions.C:163
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
Return the correction form of the given matrix.
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
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
labelList f(nPoints)
labelList fv(nPoints)
dictionary dict
volScalarField & p