solidificationMelting.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) 2014-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 "solidificationMelting.H"
27 #include "fvcDdt.H"
28 #include "fvMatrices.H"
29 #include "basicThermo.H"
34 #include "geometricOneField.H"
35 
36 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace fv
41 {
43 
46  (
47  fvModel,
49  dictionary,
50  solidificationMeltingSource,
51  "solidificationMeltingSource"
52  );
53 }
54 }
55 
56 
59 {
60  "thermo",
61  "lookup"
62 };
63 
64 
65 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
66 
67 void Foam::fv::solidificationMelting::readCoeffs(const dictionary& dict)
68 {
69  Tsol_ = dict.lookup<scalar>("Tsol");
70  Tliq_ = dict.lookupOrDefault<scalar>("Tliq", Tsol_);
71  alpha1e_ = dict.lookupOrDefault<scalar>("alpha1e", 0.0);
72  L_ = dict.lookup<scalar>("L");
73 
74  relax_ = dict.lookupOrDefault("relax", 0.9);
75 
76  mode_ = thermoModeTypeNames_.read(dict.lookup("thermoMode"));
77 
78  rhoRef_ = dict.lookup<scalar>("rhoRef");
79  TName_ = dict.lookupOrDefault<word>("T", "T");
80  CpName_ = dict.lookupOrDefault<word>("Cp", "Cp");
81  UName_ = dict.lookupOrDefault<word>("U", "U");
82  phiName_ = dict.lookupOrDefault<word>("phi", "phi");
83 
84  Cu_ = dict.lookupOrDefault<scalar>("Cu", 100000);
85  q_ = dict.lookupOrDefault("q", 0.001);
86 
87  beta_ = dict.lookup<scalar>("beta");
88 
89  if (mode_ == thermoMode::lookup)
90  {
91  CpRef_ = dict.lookup<scalar>("CpRef");
92  }
93 
94  if (!mesh().foundObject<uniformDimensionedVectorField>("g"))
95  {
96  g_ = dict.lookup("g");
97  }
98 }
99 
100 
102 Foam::fv::solidificationMelting::Cp() const
103 {
104  switch (mode_)
105  {
106  case thermoMode::thermo:
107  {
108  const basicThermo& thermo =
110 
111  return thermo.Cp();
112  break;
113  }
114  case thermoMode::lookup:
115  {
116  if (CpName_ == "CpRef")
117  {
118  return volScalarField::New
119  (
120  name() + ":Cp",
121  mesh(),
123  (
125  CpRef_
126  ),
128  );
129  }
130  else
131  {
132  return mesh().lookupObject<volScalarField>(CpName_);
133  }
134 
135  break;
136  }
137  default:
138  {
140  << "Unhandled thermo mode: " << thermoModeTypeNames_[mode_]
141  << abort(FatalError);
142  }
143  }
144 
145  return tmp<volScalarField>(nullptr);
146 }
147 
148 
149 Foam::vector Foam::fv::solidificationMelting::g() const
150 {
151  if (mesh().foundObject<uniformDimensionedVectorField>("g"))
152  {
153  const uniformDimensionedVectorField& value =
154  mesh().lookupObject<uniformDimensionedVectorField>("g");
155  return value.value();
156  }
157  else
158  {
159  return g_;
160  }
161 }
162 
163 
164 void Foam::fv::solidificationMelting::update
165 (
166  const volScalarField& Cp
167 ) const
168 {
169  if (curTimeIndex_ == mesh().time().timeIndex())
170  {
171  return;
172  }
173 
174  if (debug)
175  {
176  Info<< indent
177  << type() << ": " << name()
178  << " - updating phase indicator" << endl;
179  }
180 
181  // update old time alpha1 field
182  alpha1_.oldTime();
183 
184  const volScalarField& T = mesh().lookupObject<volScalarField>(TName_);
185 
186  zone_.regenerate();
187  const labelList& cells = zone_.zone();
188 
189  forAll(cells, i)
190  {
191  const label celli = cells[i];
192 
193  const scalar Tc = T[celli];
194  const scalar Cpc = Cp[celli];
195  const scalar alpha1New =
196  alpha1_[celli]
197  + relax_*Cpc
198  *(
199  Tc
200  - max
201  (
202  Tsol_,
203  Tsol_
204  + (Tliq_ - Tsol_)*(alpha1_[celli] - alpha1e_)/(1 - alpha1e_)
205  )
206  )/L_;
207 
208  alpha1_[celli] = max(0, min(alpha1New, 1));
209  deltaT_[i] =
210  Tc
211  - max
212  (
213  Tsol_,
214  Tsol_
215  + (Tliq_ - Tsol_)*(alpha1_[celli] - alpha1e_)/(1 - alpha1e_)
216  );
217  }
218 
219  alpha1_.correctBoundaryConditions();
220 
221  curTimeIndex_ = mesh().time().timeIndex();
222 }
223 
224 
225 template<class RhoFieldType>
226 void Foam::fv::solidificationMelting::apply
227 (
228  const RhoFieldType& rho,
229  fvMatrix<scalar>& eqn
230 ) const
231 {
232  if (debug)
233  {
234  Info<< indent
235  << type() << ": applying source to " << eqn.psi().name() << endl;
236  }
237 
238  const volScalarField Cp(this->Cp());
239 
240  update(Cp);
241 
242  dimensionedScalar L("L", dimEnergy/dimMass, L_);
243 
244  // Contributions added to rhs of solver equation
245  if (eqn.psi().dimensions() == dimTemperature)
246  {
247  eqn -= L/Cp*(fvc::ddt(rho, alpha1_));
248  }
249  else
250  {
251  eqn -= L*(fvc::ddt(rho, alpha1_));
252  }
253 }
254 
255 
256 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
257 
259 (
260  const word& name,
261  const word& modelType,
262  const fvMesh& mesh,
263  const dictionary& dict
264 )
265 :
266  fvModel(name, modelType, mesh, dict),
267  zone_(mesh, coeffs(dict)),
268  Tsol_(NaN),
269  Tliq_(NaN),
270  alpha1e_(NaN),
271  L_(NaN),
272  relax_(NaN),
273  mode_(thermoMode::thermo),
274  rhoRef_(NaN),
275  TName_(word::null),
276  CpName_(word::null),
277  UName_(word::null),
278  phiName_(word::null),
279  Cu_(NaN),
280  q_(NaN),
281  beta_(NaN),
282  alpha1_
283  (
284  IOobject
285  (
286  this->name() + ":alpha1",
287  mesh.time().name(),
288  mesh,
289  IOobject::READ_IF_PRESENT,
290  IOobject::AUTO_WRITE
291  ),
292  mesh,
294  zeroGradientFvPatchScalarField::typeName
295  ),
296  curTimeIndex_(-1),
297  deltaT_(zone_.nCells(), 0)
298 {
299  readCoeffs(coeffs(dict));
300 }
301 
302 
303 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
304 
306 {
307  switch (mode_)
308  {
309  case thermoMode::thermo:
310  {
311  const basicThermo& thermo =
313 
314  return wordList({UName_, thermo.he().name()});
315  }
316  case thermoMode::lookup:
317  {
318  return wordList({UName_, TName_});
319  }
320  }
321 
322  return wordList::null();
323 }
324 
325 
327 (
328  const volScalarField& he,
329  fvMatrix<scalar>& eqn
330 ) const
331 {
332  apply(geometricOneField(), eqn);
333 }
334 
335 
337 (
338  const volScalarField& rho,
339  const volScalarField& he,
340  fvMatrix<scalar>& eqn
341 ) const
342 {
343  apply(rho, eqn);
344 }
345 
346 
348 (
349  const volVectorField& U,
350  fvMatrix<vector>& eqn
351 ) const
352 {
353  if (debug)
354  {
355  Info<< indent
356  << type() << ": applying source to " << eqn.psi().name() << endl;
357  }
358 
359  const volScalarField Cp(this->Cp());
360 
361  update(Cp);
362 
363  const vector g = this->g();
364 
365  scalarField& Sp = eqn.diag();
366  vectorField& Su = eqn.source();
367  const scalarField& V = mesh().V();
368 
369  const labelList& cells = zone_.zone();
370 
371  forAll(cells, i)
372  {
373  const label celli = cells[i];
374 
375  const scalar Vc = V[celli];
376  const scalar alpha1c = alpha1_[celli];
377 
378  const scalar S = -Cu_*sqr(1.0 - alpha1c)/(pow3(alpha1c) + q_);
379  const vector Sb = rhoRef_*g*beta_*deltaT_[i];
380 
381  Sp[celli] += Vc*S;
382  Su[celli] += Vc*Sb;
383  }
384 }
385 
386 
388 (
389  const volScalarField& rho,
390  const volVectorField& U,
391  fvMatrix<vector>& eqn
392 ) const
393 {
394  addSup(U, eqn);
395 }
396 
397 
399 {
400  zone_.movePoints();
401  return true;
402 }
403 
404 
406 (
407  const polyTopoChangeMap& map
408 )
409 {
410  zone_.topoChange(map);
411 }
412 
413 
415 {
416  zone_.mapMesh(map);
417 }
418 
419 
421 (
422  const polyDistributionMap& map
423 )
424 {
425  zone_.distribute(map);
426 }
427 
428 
430 {
431  if (fvModel::read(dict))
432  {
433  zone_.read(coeffs(dict));
434  readCoeffs(coeffs(dict));
435  return true;
436  }
437  else
438  {
439  return false;
440  }
441 
442  return false;
443 }
444 
445 
446 // ************************************************************************* //
scalar Cp(const scalar p, const scalar T) const
Definition: EtoHthermo.H:2
#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.
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,.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
static const List< word > & null()
Return a null List.
Definition: ListI.H:118
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:55
Enum read(Istream &) const
Read a word from Istream and return the corresponding.
Definition: NamedEnum.C:55
label timeIndex() const
Return current time index.
Definition: TimeStateI.H:28
Base-class for fluid and solid thermodynamic properties.
Definition: basicThermo.H:78
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
Field< Type > & source()
Definition: fvMatrix.H:307
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
const DimensionedField< scalar, fvMesh > & V() const
Return cell volumes.
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
virtual bool read(const dictionary &dict)
Read source dictionary.
Definition: fvModel.C:196
const fvMesh & mesh() const
Return const access to the mesh database.
Definition: fvModelI.H:69
This source is designed to model the effect of solidification and melting processes,...
virtual bool movePoints()
Update for mesh motion.
virtual wordList addSupFields() const
Return the list of fields for which the fvModel adds source term.
virtual void addSup(const volScalarField &he, fvMatrix< scalar > &eqn) const
Add explicit contribution to enthalpy equation.
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
virtual bool read(const dictionary &dict)
Read source dictionary.
static const NamedEnum< thermoMode, 2 > thermoModeTypeNames_
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
solidificationMelting(const word &name, const word &modelType, const fvMesh &mesh, const dictionary &dict)
Construct from explicit source name and mesh.
A class representing the concept of a GeometricField of 1 used to avoid unnecessary manipulations for...
scalarField & diag()
Definition: lduMatrix.C:186
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type and name.
bool foundObject(const word &name) const
Is the named Type in registry.
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
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)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
A special matrix type and solver, designed for finite volume solutions of scalar equations.
Calculate the first temporal derivative.
const cellShapeList & cells
U
Definition: pEqn.H:72
rho
Definition: pEqn.H:1
const dimensionSet time
addToRunTimeSelectionTable(fvConstraint, bound, dictionary)
defineTypeNameAndDebug(bound, 0)
addBackwardCompatibleToRunTimeSelectionTable(fvConstraint, fixedTemperature, dictionary, fixedTemperatureConstraint, "fixedTemperatureConstraint")
tmp< VolField< Type > > ddt(const dimensioned< Type > dt, const fvMesh &mesh)
Definition: fvcDdt.C:45
tmp< VolField< Type > > Su(const VolField< Type > &su, const VolField< Type > &vf)
Definition: fvcSup.C:44
tmp< VolField< Type > > Sp(const volScalarField &sp, const VolField< Type > &vf)
Definition: fvcSup.C:67
tmp< fvMatrix< Type > > S(const Pair< tmp< volScalarField::Internal >> &, const VolField< Type > &)
const unitSet & lookup(const word &unitName)
Lookup and return the named unit from the table.
Definition: units.C:346
Namespace for OpenFOAM.
List< word > wordList
A List of words.
Definition: fileName.H:54
const dimensionSet & dimless
Definition: dimensions.C:138
List< label > labelList
A List of labels.
Definition: labelList.H:56
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 & dimMass
Definition: dimensions.C:140
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void pow3(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
const dimensionSet & dimEnergy
Definition: dimensions.C:160
error FatalError
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:243
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
label timeIndex
Definition: getTimeIndex.H:4
labelList fv(nPoints)
dictionary dict
fluidMulticomponentThermo & thermo
Definition: createFields.H:15
Typedefs for UniformDimensionedField.