solidificationMeltingSource.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-2023 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 "fvMatrices.H"
28 #include "basicThermo.H"
33 #include "geometricOneField.H"
34 
35 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  template<>
40  const char* NamedEnum
41  <
43  2
44  >::names[] =
45  {
46  "thermo",
47  "lookup"
48  };
49 
50  namespace fv
51  {
53 
55  (
56  fvModel,
59  );
60  }
61 }
62 
65 
66 
67 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
68 
69 void Foam::fv::solidificationMeltingSource::readCoeffs()
70 {
71  Tsol_ = coeffs().lookup<scalar>("Tsol");
72  Tliq_ = coeffs().lookupOrDefault<scalar>("Tliq", Tsol_);
73  alpha1e_ = coeffs().lookupOrDefault<scalar>("alpha1e", 0.0);
74  L_ = coeffs().lookup<scalar>("L");
75 
76  relax_ = coeffs().lookupOrDefault("relax", 0.9);
77 
78  mode_ = thermoModeTypeNames_.read(coeffs().lookup("thermoMode"));
79 
80  rhoRef_ = coeffs().lookup<scalar>("rhoRef");
81  TName_ = coeffs().lookupOrDefault<word>("T", "T");
82  CpName_ = coeffs().lookupOrDefault<word>("Cp", "Cp");
83  UName_ = coeffs().lookupOrDefault<word>("U", "U");
84  phiName_ = coeffs().lookupOrDefault<word>("phi", "phi");
85 
86  Cu_ = coeffs().lookupOrDefault<scalar>("Cu", 100000);
87  q_ = coeffs().lookupOrDefault("q", 0.001);
88 
89  beta_ = coeffs().lookup<scalar>("beta");
90 }
91 
92 
94 Foam::fv::solidificationMeltingSource::Cp() const
95 {
96  switch (mode_)
97  {
98  case thermoMode::thermo:
99  {
100  const basicThermo& thermo =
101  mesh().lookupObject<basicThermo>(physicalProperties::typeName);
102 
103  return thermo.Cp();
104  break;
105  }
106  case thermoMode::lookup:
107  {
108  if (CpName_ == "CpRef")
109  {
110  scalar CpRef = coeffs().lookup<scalar>("CpRef");
111 
112  return volScalarField::New
113  (
114  name() + ":Cp",
115  mesh(),
117  (
119  CpRef
120  ),
121  extrapolatedCalculatedFvPatchScalarField::typeName
122  );
123  }
124  else
125  {
126  return mesh().lookupObject<volScalarField>(CpName_);
127  }
128 
129  break;
130  }
131  default:
132  {
134  << "Unhandled thermo mode: " << thermoModeTypeNames_[mode_]
135  << abort(FatalError);
136  }
137  }
138 
139  return tmp<volScalarField>(nullptr);
140 }
141 
142 
143 Foam::vector Foam::fv::solidificationMeltingSource::g() const
144 {
145  if (mesh().foundObject<uniformDimensionedVectorField>("g"))
146  {
147  const uniformDimensionedVectorField& value =
148  mesh().lookupObject<uniformDimensionedVectorField>("g");
149  return value.value();
150  }
151  else
152  {
153  return coeffs().lookup("g");
154  }
155 }
156 
157 
158 void Foam::fv::solidificationMeltingSource::update
159 (
160  const volScalarField& Cp
161 ) const
162 {
163  if (curTimeIndex_ == mesh().time().timeIndex())
164  {
165  return;
166  }
167 
168  if (debug)
169  {
170  Info<< type() << ": " << name()
171  << " - updating phase indicator" << endl;
172  }
173 
174  // update old time alpha1 field
175  alpha1_.oldTime();
176 
177  const volScalarField& T = mesh().lookupObject<volScalarField>(TName_);
178 
179  const labelUList cells = set_.cells();
180 
181  forAll(cells, i)
182  {
183  const label celli = cells[i];
184 
185  const scalar Tc = T[celli];
186  const scalar Cpc = Cp[celli];
187  const scalar alpha1New =
188  alpha1_[celli]
189  + relax_*Cpc
190  *(
191  Tc
192  - max
193  (
194  Tsol_,
195  Tsol_
196  + (Tliq_ - Tsol_)*(alpha1_[celli] - alpha1e_)/(1 - alpha1e_)
197  )
198  )/L_;
199 
200  alpha1_[celli] = max(0, min(alpha1New, 1));
201  deltaT_[i] =
202  Tc
203  - max
204  (
205  Tsol_,
206  Tsol_
207  + (Tliq_ - Tsol_)*(alpha1_[celli] - alpha1e_)/(1 - alpha1e_)
208  );
209  }
210 
211  alpha1_.correctBoundaryConditions();
212 
213  curTimeIndex_ = mesh().time().timeIndex();
214 }
215 
216 
217 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
218 
220 (
221  const word& name,
222  const word& modelType,
223  const fvMesh& mesh,
224  const dictionary& dict
225 )
226 :
227  fvModel(name, modelType, mesh, dict),
228  set_(mesh, coeffs()),
229  Tsol_(NaN),
230  Tliq_(NaN),
231  alpha1e_(NaN),
232  L_(NaN),
233  relax_(NaN),
234  mode_(thermoMode::thermo),
235  rhoRef_(NaN),
236  TName_(word::null),
237  CpName_(word::null),
238  UName_(word::null),
239  phiName_(word::null),
240  Cu_(NaN),
241  q_(NaN),
242  beta_(NaN),
243  alpha1_
244  (
245  IOobject
246  (
247  this->name() + ":alpha1",
248  mesh.time().name(),
249  mesh,
250  IOobject::READ_IF_PRESENT,
251  IOobject::AUTO_WRITE
252  ),
253  mesh,
255  zeroGradientFvPatchScalarField::typeName
256  ),
257  curTimeIndex_(-1),
258  deltaT_(set_.nCells(), 0)
259 {
260  readCoeffs();
261 }
262 
263 
264 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
265 
267 {
268  switch (mode_)
269  {
270  case thermoMode::thermo:
271  {
272  const basicThermo& thermo =
273  mesh().lookupObject<basicThermo>(physicalProperties::typeName);
274 
275  return wordList({UName_, thermo.he().name()});
276  }
277  case thermoMode::lookup:
278  {
279  return wordList({UName_, TName_});
280  }
281  }
282 
283  return wordList::null();
284 }
285 
286 
288 (
289  fvMatrix<scalar>& eqn,
290  const word& fieldName
291 ) const
292 {
293  apply(geometricOneField(), eqn);
294 }
295 
296 
298 (
299  const volScalarField& rho,
300  fvMatrix<scalar>& eqn,
301  const word& fieldName
302 ) const
303 {
304  apply(rho, eqn);
305 }
306 
307 
309 (
310  fvMatrix<vector>& eqn,
311  const word& fieldName
312 ) const
313 {
314  if (debug)
315  {
316  Info<< type() << ": applying source to " << eqn.psi().name() << endl;
317  }
318 
319  const volScalarField Cp(this->Cp());
320 
321  update(Cp);
322 
323  vector g = this->g();
324 
325  scalarField& Sp = eqn.diag();
326  vectorField& Su = eqn.source();
327  const scalarField& V = mesh().V();
328 
329  const labelUList cells = set_.cells();
330 
331  forAll(cells, i)
332  {
333  const label celli = cells[i];
334 
335  const scalar Vc = V[celli];
336  const scalar alpha1c = alpha1_[celli];
337 
338  const scalar S = -Cu_*sqr(1.0 - alpha1c)/(pow3(alpha1c) + q_);
339  const vector Sb = rhoRef_*g*beta_*deltaT_[i];
340 
341  Sp[celli] += Vc*S;
342  Su[celli] += Vc*Sb;
343  }
344 }
345 
346 
348 (
349  const volScalarField& rho,
350  fvMatrix<vector>& eqn,
351  const word& fieldName
352 ) const
353 {
354  // Momentum source uses a Boussinesq approximation - redirect
355  addSup(eqn, fieldName);
356 }
357 
358 
360 {
361  set_.movePoints();
362  return true;
363 }
364 
365 
367 (
368  const polyTopoChangeMap& map
369 )
370 {
371  set_.topoChange(map);
372 }
373 
374 
376 {
377  set_.mapMesh(map);
378 }
379 
380 
382 (
383  const polyDistributionMap& map
384 )
385 {
386  set_.distribute(map);
387 }
388 
389 
391 {
392  if (fvModel::read(dict))
393  {
394  set_.read(coeffs());
395  readCoeffs();
396  return true;
397  }
398  else
399  {
400  return false;
401  }
402 
403  return false;
404 }
405 
406 
407 // ************************************************************************* //
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:434
Macros for easy insertion into run-time selection tables.
Generic GeometricField class.
static tmp< GeometricField< Type, PatchField, GeoMesh > > New(const word &name, const Internal &, const PtrList< PatchField< Type >> &)
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:54
Enum read(Istream &) const
Read a word from Istream and return the corresponding.
Definition: NamedEnum.C:61
Base-class for fluid and solid thermodynamic properties.
Definition: basicThermo.H:78
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:860
const Type & value() const
Return const reference to value.
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:101
Finite volume model abstract base class.
Definition: fvModel.H:59
const dictionary & coeffs() const
Return dictionary.
Definition: fvModelI.H:40
virtual bool read(const dictionary &dict)
Read source dictionary.
Definition: fvModel.C:187
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(fvMatrix< scalar > &eqn, const word &fieldName) 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.
solidificationMeltingSource(const word &name, const word &modelType, const fvMesh &mesh, const dictionary &dict)
Construct from explicit source name and mesh.
virtual bool read(const dictionary &dict)
Read source dictionary.
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
static const NamedEnum< thermoMode, 2 > thermoModeTypeNames_
A class representing the concept of a GeometricField of 1 used to avoid unnecessary manipulations for...
scalarField & diag()
Definition: lduMatrix.C:186
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
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
A special matrix type and solver, designed for finite volume solutions of scalar equations.
const cellShapeList & cells
addToRunTimeSelectionTable(fvConstraint, bound, dictionary)
defineTypeNameAndDebug(bound, 0)
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 > &)
static Type NaN()
Return a primitive with all components set to NaN.
Namespace for OpenFOAM.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
List< word > wordList
A List of words.
Definition: fileName.H:54
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 dimEnergy
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
dimensionedScalar pow3(const dimensionedScalar &ds)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const dimensionSet dimless
messageStream Info
const dimensionSet dimTemperature
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
UniformDimensionedField< vector > uniformDimensionedVectorField
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:61
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
const dimensionSet dimMass
error FatalError
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
UList< label > labelUList
Definition: UList.H:65
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
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:31