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  )
228  : nullptr
229  ),
230  haveEmissivity_(ptf.haveEmissivity_),
231  emissivity_(ptf.emissivity_),
232  Ta_(ptf.Ta_, false),
233  relax_(ptf.relax_),
234  qrName_(ptf.qrName_),
235  qrRelax_(ptf.qrRelax_),
236  qrPrevious_
237  (
238  qrName_ != word::null
239  ? mapper(ptf.qrPrevious_)()
240  : scalarField()
241  )
242 {}
243 
244 
247 (
250 )
251 :
252  mixedFvPatchScalarField(ptf, iF),
253  haveQ_(ptf.haveQ_),
254  Q_(ptf.Q_, false),
255  haveq_(ptf.haveq_),
256  q_(ptf.q_, false),
257  h_
258  (
259  ptf.h_.valid()
260  ? new FunctionalDimensionedField<scalar, fvPatch>
261  (
262  ptf.h_()
263  )
264  : nullptr
265  ),
266  haveEmissivity_(ptf.haveEmissivity_),
267  emissivity_(ptf.emissivity_),
268  Ta_(ptf.Ta_, false),
269  relax_(ptf.relax_),
270  qrName_(ptf.qrName_),
271  qrRelax_(ptf.qrRelax_),
272  qrPrevious_(ptf.qrPrevious_)
273 {}
274 
275 
278 (
280 ) const
281 {
283  (
285  );
286 }
287 
288 
289 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
290 
293 {}
294 
295 
296 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
297 
299 (
300  const fvPatchScalarField& ptf,
301  const fieldMapper& mapper
302 )
303 {
304  mixedFvPatchScalarField::map(ptf, mapper);
305 
306  if (h_.valid())
307  {
308  h_->map(!mapper.direct());
309  }
310 
312  refCast<const externalTemperatureFvPatchScalarField>(ptf);
313 
314  if (qrName_ != word::null)
315  {
316  mapper(qrPrevious_, tiptf.qrPrevious_);
317  }
318 }
319 
320 
322 (
323  const fvPatchScalarField& ptf
324 )
325 {
326  mixedFvPatchScalarField::reset(ptf);
327 
328  if (h_.valid())
329  {
330  h_->reset();
331  }
332 
334  refCast<const externalTemperatureFvPatchScalarField>(ptf);
335 
336  if (qrName_ != word::null)
337  {
338  qrPrevious_.reset(tiptf.qrPrevious_);
339  }
340 }
341 
342 
343 
345 {
346  if (updated())
347  {
348  return;
349  }
350 
351  const scalar t = time().value();
352 
353  // Get thermal conductivities, the patch temperature and any explicit
354  // correction heat flux
356  tmp<scalarField> sumKappaTcByDelta, sumKappaByDelta;
358  tmp<scalarField> sumq;
359  getKappa(kappa, sumKappaTcByDelta, sumKappaByDelta, T, sumq);
360 
361  // Add any user specified heat fluxes
362  if (haveQ_)
363  {
364  plusEqOp(sumq, Q_->value(t)/gSum(patch().magSf()));
365  }
366  if (haveq_)
367  {
368  plusEqOp(sumq, q_->value(t));
369  }
370 
371  // Add the (relaxed) radiative heat flux
372  if (qrName_ != word::null)
373  {
374  const fvPatchScalarField& qrCurrent =
375  patch().lookupPatchField<volScalarField, scalar>(qrName_);
376 
377  const scalarField qr(qrRelax_*qrCurrent + (1 - qrRelax_)*qrPrevious_);
378 
379  qrPrevious_ = qr;
380 
381  plusEqOp(sumq, qr);
382  }
383 
384  // Evaluate the ambient temperature
385  const scalar Ta = h_.valid() || haveEmissivity_ ? Ta_->value(t) : NaN;
386 
387  // Evaluate the combined convective and radiative heat transfer coefficient
388  tmp<scalarField> hEff;
389  if (h_.valid())
390  {
391  h_->update();
392  plusEqOp(hEff, h_());
393  }
394  if (haveEmissivity_)
395  {
396  plusEqOp
397  (
398  hEff,
399  emissivity_
401  *(sqr(Ta) + sqr(T()))
402  *(Ta + T())
403  );
404  }
405 
406  // If we have a heat transfer coefficient then add it to the kappa sums
407  if (hEff.valid())
408  {
409  plusEqOp(sumKappaByDelta, hEff());
410  plusEqOp(sumKappaTcByDelta, hEff*Ta);
411  }
412 
413  // Set the mixed parameters
414  const scalarField kappaByDelta(kappa*patch().deltaCoeffs());
415  tmp<scalarField> kappaPlusSumKappaByDelta
416  (
417  sumKappaByDelta.valid()
418  ? kappaByDelta + sumKappaByDelta()
419  : tmp<scalarField>(kappaByDelta)
420  );
421 
422  // ... value fraction
423  if (sumKappaByDelta.valid())
424  {
425  valueFraction() = sumKappaByDelta()/kappaPlusSumKappaByDelta();
426  }
427  else
428  {
429  valueFraction() = Zero;
430  }
431 
432  // ... reference value
433  tmp<scalarField> trefValue;
434  if (sumKappaByDelta.valid())
435  {
436  plusEqOp
437  (
438  trefValue,
439  max(sumKappaTcByDelta, small*kappaByDelta*patchInternalField())
440  /max(sumKappaByDelta, small*kappaByDelta)
441  );
442  }
443  if (sumq.valid())
444  {
445  plusEqOp(trefValue, sumq()/kappaPlusSumKappaByDelta());
446  }
447  if (trefValue.valid())
448  {
449  refValue() = trefValue;
450  }
451  else
452  {
453  refValue() = Zero;
454  }
455 
456  // ... and reference gradient
457  if (sumq.valid())
458  {
459  refGrad() = sumq*patch().deltaCoeffs()/kappaPlusSumKappaByDelta();
460  }
461  else
462  {
463  refGrad() = Zero;
464  }
465 
466  // Modify the mixed parameters for under-relaxation
467  if (relax_ != 1)
468  {
469  const scalarField f(valueFraction());
470  valueFraction() = 1 - relax_*(1 - f);
471  refValue() = (f*relax_*refValue() + (1 - relax_)*T)/valueFraction();
472  }
473 
474  mixedFvPatchScalarField::updateCoeffs();
475 
476  if (debug)
477  {
478  const scalar Q = gSum(kappa*patch().magSf()*snGrad());
479 
480  Info<< patch().mesh().name() << ':'
481  << patch().name() << ':'
482  << this->internalField().name() << " :"
483  << " heat transfer rate:" << Q
484  << " walltemperature "
485  << " min:" << gMin(*this)
486  << " max:" << gMax(*this)
487  << " avg:" << gAverage(*this)
488  << endl;
489  }
490 }
491 
492 
494 (
495  Ostream& os
496 ) const
497 {
499 
500  if (haveQ_)
501  {
502  writeEntry(os, time().userUnits(), dimPower, Q_());
503  }
504 
505  if (haveq_)
506  {
507  writeEntry(os, time().userUnits(), dimPower/dimArea, q_());
508  }
509 
510  if (h_.valid())
511  {
512  writeEntry(os, h_());
513  }
514 
515  if (haveEmissivity_)
516  {
517  writeEntry(os, "emissivity", emissivity_);
518  }
519 
520  if (h_.valid() || haveEmissivity_)
521  {
522  writeEntry(os, time().userUnits(), dimTemperature, Ta_());
523  }
524 
525  writeEntryIfDifferent(os, "relaxation", scalar(1), relax_);
526 
527  if (qrName_ != word::null)
528  {
529  writeEntry(os, "qr", qrName_);
530  writeEntry(os, "qrRelaxation", qrRelax_);
531  writeEntry(os, "qrPrevious", qrPrevious_);
532  }
533 
534  writeEntry(os, "refValue", refValue());
535  writeEntry(os, "refGradient", refGrad());
536  writeEntry(os, "valueFraction", valueFraction());
537  writeEntry(os, "value", *this);
538 }
539 
540 
541 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
542 
543 namespace Foam
544 {
546  (
549  );
550 
552  (
555  patchMapper,
556  externalWallHeatFluxTemperature,
557  "externalWallHeatFluxTemperature"
558  );
559 
561  (
564  dictionary,
565  externalWallHeatFluxTemperature,
566  "externalWallHeatFluxTemperature"
567  );
568 }
569 
570 
571 // ************************************************************************* //
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
virtual bool direct() const
Is the mapper direct?
Definition: fieldMapper.H:132
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:141
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:161
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:149
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:143
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
labelList f(nPoints)
dictionary dict
volScalarField & p