coupledTemperatureFvPatchScalarField.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 
29 #include "mappedFvPatchBaseBase.H"
31 
32 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
33 
35 (
37  tmp<scalarField>& sumKappaTByDelta,
38  tmp<scalarField>& sumKappaByDeltaNbr,
39  scalarField& sumq,
40  tmp<scalarField>& qByKappa
41 ) const
42 {
43  const thermophysicalTransportModel& ttm =
44  patch().mesh()
45  .lookupType<thermophysicalTransportModel>();
46 
47  kappa = ttm.kappaEff(patch().index());
48 
49  qByKappa = sumq/kappa();
50 
51  sumq = 0;
52 
53  tmp<scalarField> qCorr(ttm.qCorr(patch().index()));
54 
55  if (qCorr.valid())
56  {
57  sumq += qCorr;
58  }
59 }
60 
61 
63 (
64  tmp<scalarField>& sumKappaTByDeltaNbr,
65  tmp<scalarField>& sumKappaByDeltaNbr,
66  tmp<scalarField>& qNbr
67 ) const
68 {
69  const thermophysicalTransportModel& ttm =
70  patch().mesh()
71  .lookupType<thermophysicalTransportModel>();
72 
73  sumKappaByDeltaNbr = ttm.kappaEff(patch().index())*patch().deltaCoeffs();
74 
75  sumKappaTByDeltaNbr = sumKappaByDeltaNbr()*patchInternalField();
76 
77  qNbr = ttm.qCorr(patch().index());
78 }
79 
80 
82 (
83  tmp<scalarField>& result,
84  const tmp<scalarField>& field
85 ) const
86 {
87  if (result.valid())
88  {
89  result.ref() += field;
90  }
91  else
92  {
93  if (field.isTmp())
94  {
95  result = field;
96  }
97  else
98  {
99  result = field().clone();
100  }
101  }
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
106 
109 (
110  const fvPatch& p,
112  const dictionary& dict
113 )
114 :
115  mixedFvPatchScalarField(p, iF, dict, false),
116  TnbrName_(dict.lookupOrDefault<word>("Tnbr", "T")),
117  qrNbrName_(dict.lookupOrDefault<word>("qrNbr", "none")),
118  qrName_(dict.lookupOrDefault<word>("qr", "none")),
119  qrRelax_(dict.lookupOrDefault<scalar>("qrRelaxation", units::fraction, 1)),
120  qrPrevious_
121  (
122  qrName_ != word::null
123  ? dict.found("qrPrevious")
124  ? scalarField("qrPrevious", dimPower/dimArea, dict, p.size())
125  : scalarField(p.size(), 0)
126  : scalarField()
127  ),
128  h_
129  (
130  dict.found("h")
131  ? new FunctionalDimensionedField<scalar, fvPatch>
132  (
133  iF.name(),
134  "h",
135  p,
137  dict
138  )
139  : nullptr
140  ),
141  qs_(),
142  Qs_(0)
143 {
145  (
146  *this,
147  iF,
148  dict,
150  );
151 
152  if (dict.found("qs"))
153  {
154  if (dict.found("Qs"))
155  {
157  << "Either qs or Qs should be specified, not both"
158  << exit(FatalIOError);
159  }
160 
161  qs_ = new scalarField("qs", dimPower/dimTime, dict, p.size());
162  }
163  else if (dict.found("Qs"))
164  {
165  Qs_ = dict.lookup<scalar>("Qs");
166  qs_ = new scalarField(p.size(), Qs_/gSum(patch().magSf()));
167  }
168 
170  (
171  scalarField("value", iF.dimensions(), dict, p.size())
172  );
173 
174  if (dict.found("refValue"))
175  {
176  // Full restart
177  refValue() = scalarField("refValue", iF.dimensions(), dict, p.size());
178  refGrad() =
180  (
181  "refGradient",
182  iF.dimensions()/dimLength,
183  dict,
184  p.size()
185  );
186  valueFraction() =
187  scalarField("valueFraction", units::fraction, dict, p.size());
188  }
189  else
190  {
191  // Start from user entered data. Assume fixedValue.
192  refValue() = *this;
193  refGrad() = 0;
194  valueFraction() = 1;
195  }
196 }
197 
198 
201 (
203  const fvPatch& p,
205  const fieldMapper& mapper
206 )
207 :
208  mixedFvPatchScalarField(psf, p, iF, mapper),
209  TnbrName_(psf.TnbrName_),
210  qrNbrName_(psf.qrNbrName_),
211  qrName_(psf.qrName_),
212  qrRelax_(psf.qrRelax_),
213  qrPrevious_
214  (
215  qrName_ != word::null
216  ? mapper(psf.qrPrevious_)()
217  : scalarField()
218  ),
219  h_
220  (
221  psf.h_.valid()
222  ? new FunctionalDimensionedField<scalar, fvPatch>
223  (
224  psf.h_(),
225  p,
226  mapper
227  )
228  : nullptr
229  ),
230  qs_(psf.qs_.valid() ? new scalarField(p.size()) : nullptr),
231  Qs_(psf.Qs_)
232 {
233  map(psf, mapper);
234 }
235 
236 
239 (
242 )
243 :
244  mixedFvPatchScalarField(psf, iF),
245  TnbrName_(psf.TnbrName_),
246  qrNbrName_(psf.qrNbrName_),
247  qrName_(psf.qrName_),
248  qrRelax_(psf.qrRelax_),
249  qrPrevious_(psf.qrPrevious_),
250  h_
251  (
252  psf.h_.valid()
253  ? new FunctionalDimensionedField<scalar, fvPatch>
254  (
255  psf.h_()
256  )
257  : nullptr
258  ),
259  qs_(psf.qs_, false),
260  Qs_(psf.Qs_)
261 {}
262 
263 
266 (
268 ) const
269 {
271  (
273  );
274 }
275 
276 
277 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
278 
281 {}
282 
283 
284 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
285 
287 (
289  const fieldMapper& mapper
290 )
291 {
292  // Unmapped faces are considered zero-gradient/adiabatic
293  mapper(*this, ptf, [&](){ return patchInternalField(); });
294  mapper(refValue(), ptf.refValue(), [&](){ return patchInternalField(); });
295  mapper(refGrad(), ptf.refGrad(), scalar(0));
296  mapper(valueFraction(), ptf.valueFraction(), scalar(0));
297 
298  // Map the heat flux, if present
299  if (ptf.qs_.valid())
300  {
301  mapper(qs_(), ptf.qs_());
302  }
303 }
304 
305 
307 (
308  const fvPatchScalarField& ptf,
309  const fieldMapper& mapper
310 )
311 {
313  refCast<const coupledTemperatureFvPatchScalarField>(ptf);
314 
315  map(ctptf, mapper);
316 
317  if (h_.valid())
318  {
319  h_->map(ctptf.h_(), mapper);
320  }
321 }
322 
323 
325 (
326  const fvPatchScalarField& ptf
327 )
328 {
329  mixedFvPatchScalarField::reset(ptf);
330 
332  refCast<const coupledTemperatureFvPatchScalarField>(ptf);
333 
334  if (tiptf.qs_.valid())
335  {
336  qs_().reset(tiptf.qs_());
337  }
338 
339  if (h_.valid())
340  {
341  h_->reset();
342  }
343 }
344 
345 
347 {
348  if (updated())
349  {
350  return;
351  }
352 
353  // Since we're inside initEvaluate/evaluate there might be processor
354  // comms underway. Change the tag we use.
355  int oldTag = UPstream::msgType();
356  UPstream::msgType() = oldTag + 1;
357 
358  // Get the mapper and the neighbouring patch
359  const mappedFvPatchBaseBase& mapper =
361  const fvPatch& patchNbr = mapper.nbrFvPatch();
362 
363  const fvPatchScalarField& TpNbr =
364  patchNbr.lookupPatchField<volScalarField, scalar>(TnbrName_);
365 
366  if (!isA<coupledTemperatureFvPatchScalarField>(TpNbr))
367  {
369  << "Patch field for " << internalField().name() << " on "
370  << this->patch().name() << " is of type "
372  << endl << "The neighbouring patch field "
373  << internalField().name() << " on "
374  << patchNbr.name() << " is required to be the same, but is "
375  << "currently of type " << TpNbr.type() << exit(FatalError);
376  }
377 
378  const coupledTemperatureFvPatchScalarField& coupledTemperatureNbr =
379  refCast<const coupledTemperatureFvPatchScalarField>(TpNbr);
380 
381  scalarField sumq(size(), 0);
382 
383  if (qrName_ != "none")
384  {
385  sumq += patch().lookupPatchField<volScalarField, scalar>(qrName_);
386  }
387 
388  if (qrNbrName_ != "none")
389  {
390  sumq += mapper.fromNeighbour
391  (
392  patchNbr.lookupPatchField<volScalarField, scalar>(qrNbrName_)
393  );
394  }
395 
396  if (qrName_ != "none" || qrNbrName_ != "none")
397  {
398  sumq = qrRelax_*sumq + (1 - qrRelax_)*qrPrevious_;
399  qrPrevious_ = sumq;
400  }
401 
402  if (qs_.valid())
403  {
404  sumq += qs_();
405  }
406 
408  tmp<scalarField> sumKappaTByDelta;
409  tmp<scalarField> sumKappaByDelta;
410  tmp<scalarField> qByKappa;
411 
412  // q = alpha.this*sumq
413  getThis(kappa, sumKappaTByDelta, sumKappaByDelta, sumq, qByKappa);
414 
415  // Add neighbour contributions
416  {
417  tmp<scalarField> sumKappaTByDeltaNbr;
418  tmp<scalarField> sumKappaByDeltaNbr;
419  tmp<scalarField> qNbr;
420 
421  coupledTemperatureNbr.getNbr
422  (
423  sumKappaTByDeltaNbr,
424  sumKappaByDeltaNbr,
425  qNbr
426  );
427 
428  // Include the effect of the optional neighbour insulation layer
429  if (coupledTemperatureNbr.h_.valid())
430  {
432  (
433  coupledTemperatureNbr
434  ).h_->update();
435 
436  const scalarField hFactor
437  (
438  coupledTemperatureNbr.h_()
439  /(coupledTemperatureNbr.h_() + sumKappaByDeltaNbr())
440  );
441  sumKappaTByDeltaNbr.ref() *= hFactor;
442  sumKappaByDeltaNbr.ref() *= hFactor;
443  }
444 
445  tmp<scalarField> sumKappaTByDeltaNbrMapped
446  (
447  mapper.fromNeighbour(sumKappaTByDeltaNbr)
448  );
449 
450  tmp<scalarField> sumKappaByDeltaNbrMapped
451  (
452  mapper.fromNeighbour(sumKappaByDeltaNbr)
453  );
454 
455  // Include the effect of the optional insulation layer
456  if (h_.valid())
457  {
458  h_->update();
459 
460  const scalarField hFactor(h_()/(h_() + sumKappaByDeltaNbrMapped()));
461  sumKappaTByDeltaNbrMapped.ref() *= hFactor;
462  sumKappaByDeltaNbrMapped.ref() *= hFactor;
463  }
464 
465  add(sumKappaTByDelta, sumKappaTByDeltaNbrMapped);
466  add(sumKappaByDelta, sumKappaByDeltaNbrMapped);
467 
468  if (qNbr.valid())
469  {
470  sumq += mapper.fromNeighbour(qNbr);
471  }
472  }
473 
474  this->valueFraction() =
475  sumKappaByDelta()/(kappa()*patch().deltaCoeffs() + sumKappaByDelta());
476 
477  this->refValue() = (sumKappaTByDelta() + sumq)/sumKappaByDelta();
478 
479  this->refGrad() = qByKappa;
480 
481  mixedFvPatchScalarField::updateCoeffs();
482 
483  if (debug)
484  {
485  const scalar Q = gSum(kappa()*patch().magSf()*snGrad());
486 
487  Info<< patch().mesh().name() << ':'
488  << patch().name() << ':'
489  << this->internalField().name() << " <- "
490  << mapper.nbrMesh().name() << ':'
491  << patchNbr.name() << ':'
492  << this->internalField().name() << " :"
493  << " heat transfer rate:" << Q
494  << " walltemperature "
495  << " min:" << gMin(*this)
496  << " max:" << gMax(*this)
497  << " avg:" << gAverage(*this)
498  << endl;
499  }
500 
501  // Restore tag
502  UPstream::msgType() = oldTag;
503 }
504 
505 
507 (
508  Ostream& os
509 ) const
510 {
512 
513  writeEntryIfDifferent<word>(os, "Tnbr", "T", TnbrName_);
514  writeEntryIfDifferent<word>(os, "qrNbr", "none", qrNbrName_);
515 
516  if (qrName_ != "none")
517  {
518  writeEntry(os, "qr", qrName_);
519  writeEntry(os, "qrRelaxation", qrRelax_);
520  writeEntry(os, "qrPrevious", qrPrevious_);
521  }
522 
523  if (Qs_ != 0)
524  {
525  writeEntry(os, "Qs", Qs_);
526  }
527  else if (qs_.valid())
528  {
529  writeEntry(os, "qs", qs_());
530  }
531 
532  if (h_.valid())
533  {
534  writeEntry(os, h_());
535  }
536 }
537 
538 
539 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
540 
541 namespace Foam
542 {
544  (
547  );
548 
550  (
553  patchMapper,
554  turbulentTemperatureCoupledBaffleMixed,
555  "compressible::turbulentTemperatureCoupledBaffleMixed"
556  );
557 
559  (
562  dictionary,
563  turbulentTemperatureCoupledBaffleMixed,
564  "compressible::turbulentTemperatureCoupledBaffleMixed"
565  );
566 
567 
569  (
572  patchMapper,
573  turbulentTemperatureRadCoupledMixed,
574  "compressible::turbulentTemperatureRadCoupledMixed"
575  );
576 
578  (
581  dictionary,
582  turbulentTemperatureRadCoupledMixed,
583  "compressible::turbulentTemperatureRadCoupledMixed"
584  );
585 }
586 
587 
588 // ************************************************************************* //
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.
DimensionedField with a corresponding run-time selected function to evaluate and update the field.
Generic GeometricField class.
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:297
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
Mixed boundary condition for temperature, to be used for heat-transfer with another region in a CHT c...
virtual void getThis(tmp< scalarField > &kappa, tmp< scalarField > &sumKappaTByDelta, tmp< scalarField > &sumKappaByDelta, scalarField &qTot, tmp< scalarField > &qByKappa) const
Get the patch kappa, kappa*Tc/delta and kappa/delta and also the.
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.
void map(const coupledTemperatureFvPatchScalarField &, const fieldMapper &)
Map the given fvPatchField onto this fvPatchField.
virtual void getNbr(tmp< scalarField > &sumKappaTByDeltaNbr, tmp< scalarField > &sumKappaByDeltaNbr, tmp< scalarField > &qNbr) const
Get the neighbour patch kappa*Tc/delta and kappa/delta.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
void add(tmp< scalarField > &result, const tmp< scalarField > &field) const
Add field to result which may have not been previously set.
coupledTemperatureFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, fvMesh > &, const dictionary &)
Construct from patch, internal field and dictionary.
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Abstract base class for field mapping.
Definition: fieldMapper.H:48
const word & name() const
Return reference to name.
Definition: fvMesh.H:447
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:90
friend Ostream & operator(Ostream &, const fvPatchField< Type > &)
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:58
virtual const word & name() const
Return name.
Definition: fvPatch.H:135
const GeometricField::Patch & lookupPatchField(const word &name) const
Lookup and return the patchField of the named field from the.
Base class for fv patches that provide mapping between two fv patches.
const fvPatch & nbrFvPatch() const
Get the patch to map from.
static const mappedFvPatchBaseBase & getMap(const fvPatch &patch)
Cast the given fvPatch to a mappedFvPatchBaseBase. Handle errors.
const fvMesh & nbrMesh() const
Get the mesh for the region to map from.
static void validateMapForField(const PatchField &field, const FieldType &iF, const dictionary &context, const label froms=from::any)
Validate that the map exists and is appropriate for the given.
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
bool isTmp() const
Return true if this is really a temporary object.
Definition: tmpI.H:169
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
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
bool valid(const PtrList< ModelType > &l)
const dimensionedScalar kappa
Coulomb constant: default SI units: [N.m2/C2].
tmp< SurfaceField< Type > > snGrad(const VolField< Type > &vf, const word &name)
Definition: fvcSnGrad.C:45
const unitSet fraction
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
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
Type gAverage(const UList< Type > &f, const label comm)
void add(GeometricField< typename typeOfSum< Type1, Type2 >::type, GeoMesh, PrimitiveField1 > &gf, const GeometricField< Type1, GeoMesh, PrimitiveField2 > &gf1, const GeometricField< Type2, GeoMesh, PrimitiveField3 > &gf2)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
const dimensionSet & dimLength
Definition: dimensions.C:276
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
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")
const dimensionSet & dimTime
Definition: dimensions.C:277
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.
error FatalError
const dimensionSet & dimArea
Definition: dimensions.C:281
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
const dimensionSet & dimTemperature
Definition: dimensions.C:278
dictionary dict
volScalarField & p