externalTemperatureFvPatchScalarField.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) 2011-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 
31 
32 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
33 
35 (
37  const scalar d
38 ) const
39 {
40  if (!tf.valid())
41  {
42  tf = new scalarField(size(), d);
43  }
44  else
45  {
46  tf.ref() += d;
47  }
48 }
49 
50 
52 (
54  const tmp<scalarField>& tdf
55 ) const
56 {
57  if (!tdf.valid())
58  {
59  return;
60  }
61 
62  if (!tf.valid())
63  {
64  tf = tdf.ptr();
65  }
66  else
67  {
68  tf.ref() += tdf;
69  }
70 }
71 
72 
74 (
76  tmp<scalarField>& sumKappaTcByDelta,
77  tmp<scalarField>& sumKappaByDelta,
79  tmp<scalarField>& sumq
80 ) const
81 {
82  const thermophysicalTransportModel& ttm =
83  patch().mesh()
84  .lookupType<thermophysicalTransportModel>();
85 
86  kappa = ttm.kappaEff(patch().index());
87 
88  T = tmp<scalarField>(*this);
89 
90  plusEqOp(sumq, ttm.qCorr(patch().index()));
91 }
92 
93 
94 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
95 
98 (
99  const fvPatch& p,
101  const dictionary& dict
102 )
103 :
104  mixedFvPatchScalarField(p, iF, dict, false),
105  haveQ_(dict.found("Q")),
106  Q_
107  (
108  haveQ_
109  ? Function1<scalar>::New("Q", time().userUnits(), dimPower, dict)
110  : autoPtr<Function1<scalar>>()
111  ),
112  haveq_(dict.found("q")),
113  q_
114  (
115  haveq_
116  ? Function1<scalar>::New
117  (
118  "q",
119  time().userUnits(),
121  dict
122  )
123  : autoPtr<Function1<scalar>>()
124  ),
125  h_
126  (
127  dict.found("h")
128  ? new FunctionalDimensionedField<scalar, fvPatch>
129  (
130  iF.name(),
131  "h",
132  p,
134  dict
135  )
136  : nullptr
137  ),
138  haveEmissivity_(dict.found("emissivity")),
139  emissivity_
140  (
141  haveEmissivity_
142  ? dict.lookup<scalar>("emissivity", units::fraction)
143  : NaN
144  ),
145  Ta_
146  (
147  h_.valid() || haveEmissivity_
148  ? Function1<scalar>::New
149  (
150  "Ta",
151  time().userUnits(),
153  dict
154  ).ptr()
155  : nullptr
156  ),
157  relax_(dict.lookupOrDefault<scalar>("relaxation", units::fraction, 1)),
158  qrName_(dict.lookupOrDefault<word>("qr", word::null)),
159  qrRelax_(dict.lookupOrDefault<scalar>("qrRelaxation", units::fraction, 1)),
160  qrPrevious_
161  (
162  qrName_ != word::null
163  ? dict.found("qrPrevious")
164  ? scalarField("qrPrevious", dimPower/dimArea, dict, p.size())
165  : scalarField(p.size(), 0)
166  : scalarField()
167  )
168 {
170  (
171  scalarField("value", iF.dimensions(), dict, p.size())
172  );
173 
174  if (haveEmissivity_ && (emissivity_ < 0 || emissivity_ > 1))
175  {
177  << "Emissivity must be in the range 0 to 1"
178  << exit(FatalIOError);
179  }
180 
181  if (dict.found("refValue"))
182  {
183  // Full restart
184  refValue() = scalarField("refValue", iF.dimensions(), dict, p.size());
185  refGrad() =
187  (
188  "refGradient",
189  iF.dimensions()/dimLength,
190  dict,
191  p.size()
192  );
193  valueFraction() =
194  scalarField("valueFraction", units::fraction, dict, p.size());
195  }
196  else
197  {
198  // Start from user entered data. Assume fixedValue.
199  refValue() = *this;
200  refGrad() = 0;
201  valueFraction() = 1;
202  }
203 }
204 
205 
208 (
210  const fvPatch& p,
212  const fieldMapper& mapper
213 )
214 :
215  mixedFvPatchScalarField(ptf, p, iF, mapper),
216  haveQ_(ptf.haveQ_),
217  Q_(ptf.Q_, false),
218  haveq_(ptf.haveq_),
219  q_(ptf.q_, false),
220  h_
221  (
222  ptf.h_.valid()
223  ? new FunctionalDimensionedField<scalar, fvPatch>
224  (
225  ptf.h_(),
226  p,
227  mapper
228  )
229  : nullptr
230  ),
231  haveEmissivity_(ptf.haveEmissivity_),
232  emissivity_(ptf.emissivity_),
233  Ta_(ptf.Ta_, false),
234  relax_(ptf.relax_),
235  qrName_(ptf.qrName_),
236  qrRelax_(ptf.qrRelax_),
237  qrPrevious_
238  (
239  qrName_ != word::null
240  ? mapper(ptf.qrPrevious_)()
241  : scalarField()
242  )
243 {}
244 
245 
248 (
251 )
252 :
253  mixedFvPatchScalarField(ptf, iF),
254  haveQ_(ptf.haveQ_),
255  Q_(ptf.Q_, false),
256  haveq_(ptf.haveq_),
257  q_(ptf.q_, false),
258  h_
259  (
260  ptf.h_.valid()
261  ? new FunctionalDimensionedField<scalar, fvPatch>
262  (
263  ptf.h_()
264  )
265  : nullptr
266  ),
267  haveEmissivity_(ptf.haveEmissivity_),
268  emissivity_(ptf.emissivity_),
269  Ta_(ptf.Ta_, false),
270  relax_(ptf.relax_),
271  qrName_(ptf.qrName_),
272  qrRelax_(ptf.qrRelax_),
273  qrPrevious_(ptf.qrPrevious_)
274 {}
275 
276 
279 (
281 ) const
282 {
284  (
286  );
287 }
288 
289 
290 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
291 
294 {}
295 
296 
297 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
298 
300 (
301  const fvPatchScalarField& ptf,
302  const fieldMapper& mapper
303 )
304 {
305  mixedFvPatchScalarField::map(ptf, mapper);
306 
308  refCast<const externalTemperatureFvPatchScalarField>(ptf);
309 
310  if (h_.valid())
311  {
312  h_->map(etptf.h_(), mapper);
313  }
314 
315  if (qrName_ != word::null)
316  {
317  mapper(qrPrevious_, etptf.qrPrevious_);
318  }
319 }
320 
321 
323 (
324  const fvPatchScalarField& ptf
325 )
326 {
327  mixedFvPatchScalarField::reset(ptf);
328 
329  if (h_.valid())
330  {
331  h_->reset();
332  }
333 
335  refCast<const externalTemperatureFvPatchScalarField>(ptf);
336 
337  if (qrName_ != word::null)
338  {
339  qrPrevious_.reset(tiptf.qrPrevious_);
340  }
341 }
342 
343 
344 
346 {
347  if (updated())
348  {
349  return;
350  }
351 
352  const scalar t = time().value();
353 
354  // Get thermal conductivities, the patch temperature and any explicit
355  // correction heat flux
357  tmp<scalarField> sumKappaTcByDelta, sumKappaByDelta;
359  tmp<scalarField> sumq;
360  getKappa(kappa, sumKappaTcByDelta, sumKappaByDelta, T, sumq);
361 
362  // Add any user specified heat fluxes
363  if (haveQ_)
364  {
365  plusEqOp(sumq, Q_->value(t)/gSum(patch().magSf()));
366  }
367  if (haveq_)
368  {
369  plusEqOp(sumq, q_->value(t));
370  }
371 
372  // Add the (relaxed) radiative heat flux
373  if (qrName_ != word::null)
374  {
375  const fvPatchScalarField& qrCurrent =
376  patch().lookupPatchField<volScalarField, scalar>(qrName_);
377 
378  const scalarField qr(qrRelax_*qrCurrent + (1 - qrRelax_)*qrPrevious_);
379 
380  qrPrevious_ = qr;
381 
382  plusEqOp(sumq, qr);
383  }
384 
385  // Evaluate the ambient temperature
386  const scalar Ta = h_.valid() || haveEmissivity_ ? Ta_->value(t) : NaN;
387 
388  // Evaluate the combined convective and radiative heat transfer coefficient
389  tmp<scalarField> hEff;
390  if (h_.valid())
391  {
392  h_->update();
393  plusEqOp(hEff, h_());
394  }
395  if (haveEmissivity_)
396  {
397  plusEqOp
398  (
399  hEff,
400  emissivity_
402  *(sqr(Ta) + sqr(T()))
403  *(Ta + T())
404  );
405  }
406 
407  // If we have a heat transfer coefficient then add it to the kappa sums
408  if (hEff.valid())
409  {
410  plusEqOp(sumKappaByDelta, hEff());
411  plusEqOp(sumKappaTcByDelta, hEff*Ta);
412  }
413 
414  // Set the mixed parameters
415  const scalarField kappaByDelta(kappa*patch().deltaCoeffs());
416  tmp<scalarField> kappaPlusSumKappaByDelta
417  (
418  sumKappaByDelta.valid()
419  ? kappaByDelta + sumKappaByDelta()
420  : tmp<scalarField>(kappaByDelta)
421  );
422 
423  // ... value fraction
424  if (sumKappaByDelta.valid())
425  {
426  valueFraction() = sumKappaByDelta()/kappaPlusSumKappaByDelta();
427  }
428  else
429  {
430  valueFraction() = Zero;
431  }
432 
433  // ... reference value
434  tmp<scalarField> trefValue;
435  if (sumKappaByDelta.valid())
436  {
437  plusEqOp
438  (
439  trefValue,
440  max(sumKappaTcByDelta, small*kappaByDelta*patchInternalField())
441  /max(sumKappaByDelta, small*kappaByDelta)
442  );
443  }
444  if (sumq.valid())
445  {
446  plusEqOp(trefValue, sumq()/kappaPlusSumKappaByDelta());
447  }
448  if (trefValue.valid())
449  {
450  refValue() = trefValue;
451  }
452  else
453  {
454  refValue() = Zero;
455  }
456 
457  // ... and reference gradient
458  if (sumq.valid())
459  {
460  refGrad() = sumq*patch().deltaCoeffs()/kappaPlusSumKappaByDelta();
461  }
462  else
463  {
464  refGrad() = Zero;
465  }
466 
467  // Modify the mixed parameters for under-relaxation
468  if (relax_ != 1)
469  {
470  const scalarField f(valueFraction());
471  valueFraction() = 1 - relax_*(1 - f);
472  refValue() = (f*relax_*refValue() + (1 - relax_)*T)/valueFraction();
473  }
474 
475  mixedFvPatchScalarField::updateCoeffs();
476 
477  if (debug)
478  {
479  const scalar Q = gSum(kappa*patch().magSf()*snGrad());
480 
481  Info<< patch().mesh().name() << ':'
482  << patch().name() << ':'
483  << this->internalField().name() << " :"
484  << " heat transfer rate:" << Q
485  << " walltemperature "
486  << " min:" << gMin(*this)
487  << " max:" << gMax(*this)
488  << " avg:" << gAverage(*this)
489  << endl;
490  }
491 }
492 
493 
495 (
496  Ostream& os
497 ) const
498 {
500 
501  if (haveQ_)
502  {
503  writeEntry(os, time().userUnits(), dimPower, Q_());
504  }
505 
506  if (haveq_)
507  {
508  writeEntry(os, time().userUnits(), dimPower/dimArea, q_());
509  }
510 
511  if (h_.valid())
512  {
513  writeEntry(os, h_());
514  }
515 
516  if (haveEmissivity_)
517  {
518  writeEntry(os, "emissivity", emissivity_);
519  }
520 
521  if (h_.valid() || haveEmissivity_)
522  {
523  writeEntry(os, time().userUnits(), dimTemperature, Ta_());
524  }
525 
526  writeEntryIfDifferent(os, "relaxation", scalar(1), relax_);
527 
528  if (qrName_ != word::null)
529  {
530  writeEntry(os, "qr", qrName_);
531  writeEntry(os, "qrRelaxation", qrRelax_);
532  writeEntry(os, "qrPrevious", qrPrevious_);
533  }
534 
535  writeEntry(os, "refValue", refValue());
536  writeEntry(os, "refGradient", refGrad());
537  writeEntry(os, "valueFraction", valueFraction());
538  writeEntry(os, "value", *this);
539 }
540 
541 
542 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
543 
544 namespace Foam
545 {
547  (
550  );
551 
553  (
556  patchMapper,
557  externalWallHeatFluxTemperature,
558  "externalWallHeatFluxTemperature"
559  );
560 
562  (
565  dictionary,
566  externalWallHeatFluxTemperature,
567  "externalWallHeatFluxTemperature"
568  );
569 }
570 
571 
572 // ************************************************************************* //
bool found
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...
const dimensionSet & dimensions() const
Return dimensions.
Run-time selectable general function of one variable.
Definition: Function1.H:62
DimensionedField with a corresponding run-time selected function to evaluate and update the field.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
This boundary condition applies a heat flux condition to temperature on an external wall....
virtual void getKappa(scalarField &kappa, tmp< scalarField > &sumKappaTcByDelta, tmp< scalarField > &sumKappaByDelta, tmp< scalarField > &T, tmp< scalarField > &sumq) const
Get the patch kappa, kappa*Tc/delta, kappa/delta,.
void plusEqOp(tmp< scalarField > &tf, const scalar d) const
Plus-equals op for a tmp field. Will initialise the tmp if empty.
virtual tmp< fvPatchScalarField > clone(const DimensionedField< scalar, fvMesh > &iF) const
Construct and return a clone setting internal field reference.
virtual void reset(const fvPatchScalarField &)
Reset the fvPatchField to the given fvPatchField.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
virtual void map(const fvPatchScalarField &, const fieldMapper &)
Map the given fvPatchField onto this fvPatchField.
externalTemperatureFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, fvMesh > &, const dictionary &)
Construct from patch, internal field and dictionary.
Abstract base class for field mapping.
Definition: fieldMapper.H:48
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:90
virtual void write(Ostream &) const
Write.
Definition: fvPatchField.C:235
friend Ostream & operator(Ostream &, const fvPatchField< Type > &)
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:58
Abstract base class for all fluid and solid thermophysical transport models.
virtual tmp< scalarField > qCorr(const label patchi) const =0
Return the patch heat flux correction [W/m^2].
virtual tmp< volScalarField > kappaEff() const =0
Effective thermal turbulent conductivity.
A class for managing temporary objects.
Definition: tmp.H:55
bool valid() const
Is this temporary object valid,.
Definition: tmpI.H:183
T * ptr() const
Return tmp pointer for reuse.
Definition: tmpI.H:221
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
const tensorField & tf
bool valid(const PtrList< ModelType > &l)
const dimensionedScalar kappa
Coulomb constant: default SI units: [N.m2/C2].
const dimensionedScalar sigma
Stefan-Boltzmann constant: default SI units: [W/m^2/K^4].
const dimensionSet time
tmp< SurfaceField< Type > > snGrad(const VolField< Type > &vf, const word &name)
Definition: fvcSnGrad.C:45
const unitSet fraction
const unitSet & lookup(const word &unitName)
Lookup and return the named unit from the table.
Definition: units.C:346
Namespace for OpenFOAM.
Type gMin(const UList< Type > &f, const label comm)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
void writeEntryIfDifferent(Ostream &os, const word &entryName, const EntryType &value1, const EntryType &value2)
Helper function to write the keyword and entry only if the.
Type gAverage(const UList< Type > &f, const label comm)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
const dimensionSet & dimLength
Definition: dimensions.C:276
makePatchTypeField(fvPatchScalarField, atmosphericBoundaryLayerTurbulentEpsilonFvPatchScalarField)
messageStream Info
Type gSum(const UList< Type > &f, const label comm)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
addBackwardCompatibleToRunTimeSelectionTable(fvPatchScalarField, coupledTemperatureFvPatchScalarField, patchMapper, turbulentTemperatureCoupledBaffleMixed, "compressible::turbulentTemperatureCoupledBaffleMixed")
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
const dimensionSet & dimPower
Definition: dimensions.C:292
IOerror FatalIOError
Type gMax(const UList< Type > &f, const label comm)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
const dimensionSet & dimArea
Definition: dimensions.C:281
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
void T(GeometricField< Type, GeoMesh, PrimitiveField1 > &gf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf1)
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
const dimensionSet & dimTemperature
Definition: dimensions.C:278
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
labelList f(nPoints)
dictionary dict
volScalarField & p