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  )
227  : nullptr
228  ),
229  qs_(psf.qs_.valid() ? new scalarField(p.size()) : nullptr),
230  Qs_(psf.Qs_)
231 {
232  map(psf, mapper);
233 }
234 
235 
238 (
241 )
242 :
243  mixedFvPatchScalarField(psf, iF),
244  TnbrName_(psf.TnbrName_),
245  qrNbrName_(psf.qrNbrName_),
246  qrName_(psf.qrName_),
247  qrRelax_(psf.qrRelax_),
248  qrPrevious_(psf.qrPrevious_),
249  h_
250  (
251  psf.h_.valid()
252  ? new FunctionalDimensionedField<scalar, fvPatch>
253  (
254  psf.h_()
255  )
256  : nullptr
257  ),
258  qs_(psf.qs_, false),
259  Qs_(psf.Qs_)
260 {}
261 
262 
265 (
267 ) const
268 {
270  (
272  );
273 }
274 
275 
276 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
277 
280 {}
281 
282 
283 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
284 
286 (
288  const fieldMapper& mapper
289 )
290 {
291  // Unmapped faces are considered zero-gradient/adiabatic
292  mapper(*this, ptf, [&](){ return patchInternalField(); });
293  mapper(refValue(), ptf.refValue(), [&](){ return patchInternalField(); });
294  mapper(refGrad(), ptf.refGrad(), scalar(0));
295  mapper(valueFraction(), ptf.valueFraction(), scalar(0));
296 
297  // Map the heat flux, if present
298  if (ptf.qs_.valid())
299  {
300  mapper(qs_(), ptf.qs_());
301  }
302 }
303 
304 
306 (
307  const fvPatchScalarField& ptf,
308  const fieldMapper& mapper
309 )
310 {
311  map(refCast<const coupledTemperatureFvPatchScalarField>(ptf), mapper);
312 
313  if (h_.valid())
314  {
315  h_->map(!mapper.direct());
316  }
317 }
318 
319 
321 (
322  const fvPatchScalarField& ptf
323 )
324 {
325  mixedFvPatchScalarField::reset(ptf);
326 
328  refCast<const coupledTemperatureFvPatchScalarField>(ptf);
329 
330  if (tiptf.qs_.valid())
331  {
332  qs_().reset(tiptf.qs_());
333  }
334 
335  if (h_.valid())
336  {
337  h_->reset();
338  }
339 }
340 
341 
343 {
344  if (updated())
345  {
346  return;
347  }
348 
349  // Since we're inside initEvaluate/evaluate there might be processor
350  // comms underway. Change the tag we use.
351  int oldTag = UPstream::msgType();
352  UPstream::msgType() = oldTag + 1;
353 
354  // Get the mapper and the neighbouring patch
355  const mappedFvPatchBaseBase& mapper =
357  const fvPatch& patchNbr = mapper.nbrFvPatch();
358 
359  const fvPatchScalarField& TpNbr =
360  patchNbr.lookupPatchField<volScalarField, scalar>(TnbrName_);
361 
362  if (!isA<coupledTemperatureFvPatchScalarField>(TpNbr))
363  {
365  << "Patch field for " << internalField().name() << " on "
366  << this->patch().name() << " is of type "
368  << endl << "The neighbouring patch field "
369  << internalField().name() << " on "
370  << patchNbr.name() << " is required to be the same, but is "
371  << "currently of type " << TpNbr.type() << exit(FatalError);
372  }
373 
374  const coupledTemperatureFvPatchScalarField& coupledTemperatureNbr =
375  refCast<const coupledTemperatureFvPatchScalarField>(TpNbr);
376 
377  scalarField sumq(size(), 0);
378 
379  if (qrName_ != "none")
380  {
381  sumq += patch().lookupPatchField<volScalarField, scalar>(qrName_);
382  }
383 
384  if (qrNbrName_ != "none")
385  {
386  sumq += mapper.fromNeighbour
387  (
388  patchNbr.lookupPatchField<volScalarField, scalar>(qrNbrName_)
389  );
390  }
391 
392  if (qrName_ != "none" || qrNbrName_ != "none")
393  {
394  sumq = qrRelax_*sumq + (1 - qrRelax_)*qrPrevious_;
395  qrPrevious_ = sumq;
396  }
397 
398  if (qs_.valid())
399  {
400  sumq += qs_();
401  }
402 
404  tmp<scalarField> sumKappaTByDelta;
405  tmp<scalarField> sumKappaByDelta;
406  tmp<scalarField> qByKappa;
407 
408  // q = alpha.this*sumq
409  getThis(kappa, sumKappaTByDelta, sumKappaByDelta, sumq, qByKappa);
410 
411  // Add neighbour contributions
412  {
413  tmp<scalarField> sumKappaTByDeltaNbr;
414  tmp<scalarField> sumKappaByDeltaNbr;
415  tmp<scalarField> qNbr;
416 
417  coupledTemperatureNbr.getNbr
418  (
419  sumKappaTByDeltaNbr,
420  sumKappaByDeltaNbr,
421  qNbr
422  );
423 
424  // Include the effect of the optional neighbour insulation layer
425  if (coupledTemperatureNbr.h_.valid())
426  {
428  (
429  coupledTemperatureNbr
430  ).h_->update();
431 
432  const scalarField hFactor
433  (
434  coupledTemperatureNbr.h_()
435  /(coupledTemperatureNbr.h_() + sumKappaByDeltaNbr())
436  );
437  sumKappaTByDeltaNbr.ref() *= hFactor;
438  sumKappaByDeltaNbr.ref() *= hFactor;
439  }
440 
441  tmp<scalarField> sumKappaTByDeltaNbrMapped
442  (
443  mapper.fromNeighbour(sumKappaTByDeltaNbr)
444  );
445 
446  tmp<scalarField> sumKappaByDeltaNbrMapped
447  (
448  mapper.fromNeighbour(sumKappaByDeltaNbr)
449  );
450 
451  // Include the effect of the optional insulation layer
452  if (h_.valid())
453  {
454  h_->update();
455 
456  const scalarField hFactor(h_()/(h_() + sumKappaByDeltaNbrMapped()));
457  sumKappaTByDeltaNbrMapped.ref() *= hFactor;
458  sumKappaByDeltaNbrMapped.ref() *= hFactor;
459  }
460 
461  add(sumKappaTByDelta, sumKappaTByDeltaNbrMapped);
462  add(sumKappaByDelta, sumKappaByDeltaNbrMapped);
463 
464  if (qNbr.valid())
465  {
466  sumq += mapper.fromNeighbour(qNbr);
467  }
468  }
469 
470  this->valueFraction() =
471  sumKappaByDelta()/(kappa()*patch().deltaCoeffs() + sumKappaByDelta());
472 
473  this->refValue() = (sumKappaTByDelta() + sumq)/sumKappaByDelta();
474 
475  this->refGrad() = qByKappa;
476 
477  mixedFvPatchScalarField::updateCoeffs();
478 
479  if (debug)
480  {
481  const scalar Q = gSum(kappa()*patch().magSf()*snGrad());
482 
483  Info<< patch().mesh().name() << ':'
484  << patch().name() << ':'
485  << this->internalField().name() << " <- "
486  << mapper.nbrMesh().name() << ':'
487  << patchNbr.name() << ':'
488  << this->internalField().name() << " :"
489  << " heat transfer rate:" << Q
490  << " walltemperature "
491  << " min:" << gMin(*this)
492  << " max:" << gMax(*this)
493  << " avg:" << gAverage(*this)
494  << endl;
495  }
496 
497  // Restore tag
498  UPstream::msgType() = oldTag;
499 }
500 
501 
503 (
504  Ostream& os
505 ) const
506 {
508 
509  writeEntryIfDifferent<word>(os, "Tnbr", "T", TnbrName_);
510  writeEntryIfDifferent<word>(os, "qrNbr", "none", qrNbrName_);
511 
512  if (qrName_ != "none")
513  {
514  writeEntry(os, "qr", qrName_);
515  writeEntry(os, "qrRelaxation", qrRelax_);
516  writeEntry(os, "qrPrevious", qrPrevious_);
517  }
518 
519  if (Qs_ != 0)
520  {
521  writeEntry(os, "Qs", Qs_);
522  }
523  else if (qs_.valid())
524  {
525  writeEntry(os, "qs", qs_());
526  }
527 
528  if (h_.valid())
529  {
530  writeEntry(os, h_());
531  }
532 }
533 
534 
535 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
536 
537 namespace Foam
538 {
540  (
543  );
544 
546  (
549  patchMapper,
550  turbulentTemperatureCoupledBaffleMixed,
551  "compressible::turbulentTemperatureCoupledBaffleMixed"
552  );
553 
555  (
558  dictionary,
559  turbulentTemperatureCoupledBaffleMixed,
560  "compressible::turbulentTemperatureCoupledBaffleMixed"
561  );
562 
563 
565  (
568  patchMapper,
569  turbulentTemperatureRadCoupledMixed,
570  "compressible::turbulentTemperatureRadCoupledMixed"
571  );
572 
574  (
577  dictionary,
578  turbulentTemperatureRadCoupledMixed,
579  "compressible::turbulentTemperatureRadCoupledMixed"
580  );
581 }
582 
583 
584 // ************************************************************************* //
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
virtual bool direct() const
Is the mapper direct?
Definition: fieldMapper.H:132
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:141
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:142
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.
error FatalError
const dimensionSet & dimArea
Definition: dimensions.C:149
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
const dimensionSet & dimTemperature
Definition: dimensions.C:143
dictionary dict
volScalarField & p