heatTransferSystem.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) 2015-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 "heatTransferSystem.H"
27 
28 #include "fvmSup.H"
29 
30 #include "heatTransferModel.H"
32 
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
40 }
41 
42 
44 (
45  "heatTransfer"
46 );
47 
48 
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 
51 Foam::IOobject Foam::heatTransferSystem::io(const phaseSystem& fluid) const
52 {
53  typeIOobject<IOdictionary> result
54  (
56  fluid.mesh().time().constant(),
57  fluid.mesh(),
60  );
61 
62  // Check for and warn about heat transfer models being in the old
63  // location in constant/phaseProperties
64  if (!result.headerOk())
65  {
66  result.readOpt() = IOobject::NO_READ;
67 
68  if
69  (
70  fluid.found(modelName<heatTransferModel>())
71  || !fluid.thermalPhases().empty()
72  )
73  {
75  << "Specifying a heat transfer model entry - "
76  << modelName<heatTransferModel>() << " - in "
77  << fluid.relativeObjectPath() << " is deprecated. The contents "
78  << "of this entry should now be specified in "
79  << result.relativeObjectPath() << "." << endl;
80  }
81  }
82  else
83  {
84  if (fluid.found(modelName<heatTransferModel>()))
85  {
87  << "Heat transfer model entry - "
88  << modelName<heatTransferModel>() << " - in "
89  << fluid.relativeObjectPath() << " is no longer used. The "
90  << "contents of this entry are now read from "
91  << result.relativeObjectPath() << "." << endl;
92  }
93  }
94 
95  return result;
96 }
97 
98 
99 const Foam::dictionary& Foam::heatTransferSystem::modelsDict() const
100 {
101  const word key = modelName<heatTransferModel>();
102 
103  return
104  readOpt() == IOobject::NO_READ && fluid_.found(key)
105  ? fluid_.subDict(key)
106  : *this;
107 }
108 
109 
110 void Foam::heatTransferSystem::readModels()
111 {
112  models_ =
113  generateBlendedInterfacialModels<blendedHeatTransferModel>
114  (
115  fluid_,
116  modelsDict(),
117  wordHashSet(),
118  true
119  );
120 
121  sidedModels_ =
122  generateBlendedInterfacialModels<blendedSidedHeatTransferModel>
123  (
124  fluid_,
125  modelsDict(),
126  wordHashSet(),
127  true
128  );
129 
130  forAllConstIter(modelsTable, models_, modelIter)
131  {
132  if (sidedModels_.found(modelIter.key()))
133  {
134  const phaseInterface interface(fluid_, modelIter.key());
135 
136  FatalIOErrorInFunction(modelsDict())
137  << "One-resistance and two-resistance heat transfer models "
138  << "both specified between phases "
139  << interface.phase1().name() << " and "
140  << interface.phase2().name() << exit(FatalIOError);
141  }
142  }
143 }
144 
145 
146 template<class ... Args>
147 Foam::Pair<Foam::tmp<Foam::volScalarField>> Foam::heatTransferSystem::Hs
148 (
149  const phaseModel& phase1,
150  const phaseModel& phase2,
151  Args ... args
152 ) const
153 {
154  auto error = [&](const word& why)
155  {
157  << why << " two-resistance heat transfer models found that "
158  << "provide a heat transfer coefficient between phases "
159  << phase1.name() << " and " << phase2.name() << exit(FatalError);
160  };
161 
163 
164  const phaseInterface interface(phase1, phase2);
165 
166  auto iter = sidedModels_.find(interface);
167 
168  if (iter != sidedModels_.end())
169  {
170  HsPtr.set
171  (
173  (
174  iter()->KinThe(phase1, args ...),
175  iter()->KinThe(phase2, args ...)
176  )
177  );
178  }
179 
180  const Foam::fvModels& fvModels = Foam::fvModels::New(fluid_.mesh());
181 
182  forAll(fvModels, i)
183  {
184  if (!isA<fv::twoResistanceHeatTransfer>(fvModels[i])) continue;
185 
186  const fv::twoResistanceHeatTransfer& heatTransferFvModel =
187  refCast<const fv::twoResistanceHeatTransfer>(fvModels[i]);
188 
190  heatTransferFvModel.Ks(phase1, phase2, args ...);
191 
192  if (!Hs.first().valid() || !Hs.second().valid()) continue;
193 
194  if (HsPtr.valid()) error("Multiple");
195 
196  HsPtr.set(new Pair<tmp<volScalarField>>(Hs.first(), Hs.second()));
197  }
198 
199  if (!HsPtr.valid()) error("No");
200 
201  return HsPtr();
202 }
203 
204 
205 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
206 
208 (
209  const phaseSystem& fluid
210 )
211 :
212  IOdictionary(io(fluid)),
213  fluid_(fluid),
214  models_(),
215  sidedModels_()
216 {
217  // If we have no entries and there are no thermal phases then this case
218  // does not need any heat transfer modelling and we can just quit without
219  // trying to construct anything
220  if
221  (
223  && !fluid_.found(modelName<heatTransferModel>())
224  && fluid.thermalPhases().empty()
225  ) return;
226 
227  Info<< indentOrNl << "Constructing " << typeName << " from "
228  << relativeObjectPath().c_str() << endl;
229 
230  printDictionary print(*this);
231 
232  readModels();
233 }
234 
235 
236 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
237 
239 {}
240 
241 
242 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
243 
244 Foam::Pair<Foam::tmp<Foam::volScalarField>> Foam::heatTransferSystem::Hs
245 (
246  const phaseModel& phase1,
247  const phaseModel& phase2
248 ) const
249 {
250  return Hs<>(phase1, phase2);
251 }
252 
253 
254 Foam::Pair<Foam::tmp<Foam::volScalarField>> Foam::heatTransferSystem::Hs
255 (
256  const phaseModel& phase1,
257  const phaseModel& phase2,
258  const scalar residualAlpha
259 ) const
260 {
261  return Hs<scalar>(phase1, phase2, residualAlpha);
262 }
263 
264 
267 {
269  (
271  );
272  HashPtrTable<fvScalarMatrix>& eqns = eqnsPtr();
273 
274  forAll(fluid_.phases(), phasei)
275  {
276  const phaseModel& phase = fluid_.phases()[phasei];
277 
278  eqns.insert
279  (
280  phase.name(),
281  new fvScalarMatrix(phase.thermo().he(), dimEnergy/dimTime)
282  );
283  }
284 
285  forAllConstIter(modelsTable, models_, modelIter)
286  {
287  const phaseInterface interface(fluid_, modelIter.key());
288 
289  const volScalarField::Internal H(modelIter()->K());
290 
291  forAllConstIter(phaseInterface, interface, iter)
292  {
293  const phaseModel& phase = iter();
294  const phaseModel& otherPhase = iter.otherPhase();
295 
296  const volScalarField& he = phase.thermo().he();
297  const volScalarField::Internal& Cpv(phase.thermo().Cpv());
298 
299  const volScalarField::Internal Hstabilised
300  (
301  iter.otherPhase()()
302  /max(iter.otherPhase()(), iter.otherPhase().residualAlpha())
303  *H
304  );
305 
306  eqns[phase.name()] +=
307  Hstabilised*(otherPhase.thermo().T()() - phase.thermo().T()())
308  + Hstabilised/Cpv*he - fvm::Sp(Hstabilised/Cpv, he);
309  }
310  }
311 
312  forAllConstIter(sidedModelsTable, sidedModels_, sidedModelIter)
313  {
314  const phaseInterface interface(fluid_, sidedModelIter.key());
315 
317  (
318  sidedModelIter()->KinThe(interface.phase1()),
319  sidedModelIter()->KinThe(interface.phase2())
320  );
321 
322  const volScalarField::Internal HEff
323  (
324  Hs.first()()*Hs.second()()/(Hs.first()() + Hs.second()())
325  );
326 
327  forAllConstIter(phaseInterface, interface, iter)
328  {
329  const phaseModel& phase = iter();
330  const phaseModel& otherPhase = iter.otherPhase();
331 
332  const volScalarField& he = phase.thermo().he();
333  const volScalarField::Internal& Cpv(phase.thermo().Cpv());
334 
335  const volScalarField::Internal& H = Hs[iter.index()];
336 
337  eqns[phase.name()] +=
338  HEff*(otherPhase.thermo().T()() - phase.thermo().T()())
339  + H/Cpv*he - fvm::Sp(H/Cpv, he);
340  }
341  }
342 
343  return eqnsPtr;
344 }
345 
346 
348 {
349  if (regIOobject::read())
350  {
351  readModels();
352 
353  return true;
354  }
355  else
356  {
357  return false;
358  }
359 }
360 
361 
362 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
static fvModels & New(const word &name, const fvMesh &mesh)
Construct and return the named DemandDrivenMeshObject.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Generic GeometricField class.
A HashTable specialisation for hashing pointers.
Definition: HashPtrTable.H:68
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:57
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:119
fileName relativeObjectPath() const
Return complete relativePath + object name.
Definition: IOobject.H:420
readOption readOpt() const
Definition: IOobject.H:357
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
bool empty() const
Return true if the UPtrList is empty (ie, size() is zero)
Definition: UPtrListI.H:36
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
void set(T *)
Set pointer to that given.
Definition: autoPtrI.H:99
virtual const volScalarField & T() const =0
Temperature [K].
virtual const volScalarField & Cpv() const =0
Heat capacity at constant pressure/volume [J/kg/K].
virtual const volScalarField & he() const =0
Enthalpy/Internal energy [J/kg].
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:468
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:71
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:118
Finite volume models.
Definition: fvModels.H:69
Model for heat transfer between two phases. Two heat transfer coefficients are used to calculate the ...
Class which provides interfacial momentum transfer between a number of phases. Drag,...
static const word propertiesName
Default name of the phase properties dictionary.
heatTransferSystem(const phaseSystem &)
Construct from a phase system.
virtual ~heatTransferSystem()
Destructor.
autoPtr< HashPtrTable< fvScalarMatrix > > heatTransfer() const
Return the heat transfer matrices.
virtual bool read()
Read base phaseProperties dictionary.
Class to represent an interface between phases. Derivations can further specify the configuration of ...
const phaseModel & phase1() const
Return phase 1.
const phaseModel & phase2() const
Return phase 2.
virtual const rhoThermo & thermo() const =0
Return the thermophysical model.
const word & name() const
Return the name of this phase.
Definition: phaseModel.C:92
Class to represent a system of phases.
Definition: phaseSystem.H:74
const phaseModelPartialList & thermalPhases() const
Return the models for phases that have variable temperature.
Definition: phaseSystemI.H:146
Enables the printing of a dictionary and subsequently looked-up defaulted entries.
virtual bool read()
Read object.
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
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
Calculate the matrix for implicit and explicit sources.
K
Definition: pEqn.H:75
#define WarningInFunction
Report a warning using Foam::Warning.
tmp< fvMatrix< Type > > Sp(const volScalarField::Internal &, const VolField< Type > &)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
const dimensionSet & dimTime
Definition: dimensions.C:142
IOerror FatalIOError
HashSet wordHashSet
A HashSet with word keys.
Definition: HashSet.H:210
Ostream & indentOrNl(Ostream &os)
Indent stream or add newline if indent level == 0.
Definition: Ostream.H:250
const dimensionSet & dimEnergy
Definition: dimensions.C:160
error FatalError
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Foam::argList args(argc, argv)