turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2018-2020 OpenCFD Ltd
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
30 #include "fvPatchFieldMapper.H"
31 #include "volFields.H"
32 #include "phaseSystem.H"
33 #include "mappedPatchBase.H"
34 #include "solidThermo.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 const Foam::Enum
39 <
42 >
43 Foam::compressible::
44 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::regionTypeNames_
45 {
46  { regionType::solid, "solid" },
47  { regionType::fluid, "fluid" },
48 };
49 
50 
51 const Foam::Enum
52 <
55 >
56 Foam::compressible::
57 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::KMethodTypeNames_
58 {
59  { KMethodType::mtSolidThermo, "solidThermo" },
60  { KMethodType::mtLookup, "lookup" },
61  { KMethodType::mtPhaseSystem, "phaseSystem" }
62 };
63 
64 
65 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
66 
67 
68 Foam::tmp<Foam::scalarField> Foam::compressible::
69 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
70 kappa
71 (
72  const scalarField& Tp
73 ) const
74 {
75  const polyMesh& mesh = patch().boundaryMesh().mesh();
76  const label patchi = patch().index();
77 
78  switch (method_)
79  {
80  case mtSolidThermo:
81  {
82  const solidThermo& thermo =
83  mesh.lookupObject<solidThermo>(basicThermo::dictName);
84 
85  return thermo.kappa(patchi);
86  break;
87  }
88 
89  case mtLookup:
90  {
91  {
92  const auto* ptr =
93  mesh.cfindObject<volScalarField>(kappaName_);
94 
95  if (ptr)
96  {
97  return patch().patchField(*ptr);
98  }
99  }
100  {
101  const auto* ptr =
102  mesh.cfindObject<volSymmTensorField>(kappaName_);
103 
104  if (ptr)
105  {
106  const symmTensorField& KWall = patch().patchField(*ptr);
107 
108  const vectorField n(patch().nf());
109 
110  return n & KWall & n;
111  }
112  }
113 
114  {
116  << "Did not find field " << kappaName_
117  << " on mesh " << mesh.name() << " patch " << patch().name()
118  << nl
119  << " Please set 'kappa' to the name of a volScalarField"
120  << " or volSymmTensorField."
121  << exit(FatalError);
122  }
123  break;
124  }
125 
126  case mtPhaseSystem:
127  {
128  // Lookup the fluid model
129  const phaseSystem& fluid =
130  (
131  mesh.lookupObject<phaseSystem>("phaseProperties")
132  );
133 
134  auto tkappaEff = tmp<scalarField>::New(patch().size(), Zero);
135  auto& kappaEff = tkappaEff.ref();
136 
137  forAll(fluid.phases(), phasei)
138  {
139  const phaseModel& phase = fluid.phases()[phasei];
140 
141  const fvPatchScalarField& alpha = phase.boundaryField()[patchi];
142 
143  kappaEff += alpha*phase.kappaEff(patchi)();
144  }
145 
146  return tkappaEff;
147 
148  break;
149  }
150 
151  default:
152  {
154  << "Unimplemented method " << KMethodTypeNames_[method_] << nl
155  << "Please set 'kappaMethod' to one of "
156  << flatOutput(KMethodTypeNames_.sortedToc()) << nl
157  << "and 'kappa' to the name of the volScalar"
158  << exit(FatalError);
159  }
160  }
161 
162  // Return zero-sized (not nullptr)
163  return tmp<scalarField>::New();
164 }
165 
166 
167 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
168 
169 
170 namespace Foam
171 {
172 namespace compressible
173 {
174 
175 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
176 
179 (
180  const fvPatch& p,
181  const DimensionedField<scalar, volMesh>& iF
182 )
183 :
184  mixedFvPatchScalarField(p, iF),
185  regionType_(fluid),
186  method_(mtLookup),
187  kappaName_("none"),
188  otherPhaseName_("vapor"),
189  TnbrName_("undefined-Tnbr"),
190  qrNbrName_("undefined-qrNbr"),
191  qrName_("undefined-qr")
192 {
193  this->refValue() = 0.0;
194  this->refGrad() = 0.0;
195  this->valueFraction() = 1.0;
196 }
197 
198 
199 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
200 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
201 (
202  const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField& psf,
203  const fvPatch& p,
204  const DimensionedField<scalar, volMesh>& iF,
205  const fvPatchFieldMapper& mapper
206 )
207 :
208  mixedFvPatchScalarField(psf, p, iF, mapper),
209  regionType_(psf.regionType_),
210  method_(psf.method_),
211  kappaName_(psf.kappaName_),
212  otherPhaseName_(psf.otherPhaseName_),
213  TnbrName_(psf.TnbrName_),
214  qrNbrName_(psf.qrNbrName_),
215  qrName_(psf.qrName_)
216 {}
217 
218 
219 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
220 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
221 (
222  const fvPatch& p,
223  const DimensionedField<scalar, volMesh>& iF,
224  const dictionary& dict
225 )
226 :
227  mixedFvPatchScalarField(p, iF),
228  regionType_(regionTypeNames_.get("region", dict)),
229  method_(KMethodTypeNames_.get("kappaMethod", dict)),
230  kappaName_(dict.getOrDefault<word>("kappa", "none")),
231  otherPhaseName_(dict.get<word>("otherPhase")),
232  TnbrName_(dict.getOrDefault<word>("Tnbr", "T")),
233  qrNbrName_(dict.getOrDefault<word>("qrNbr", "none")),
234  qrName_(dict.getOrDefault<word>("qr", "none"))
235 {
236  if (!isA<mappedPatchBase>(this->patch().patch()))
237  {
239  << "' not type '" << mappedPatchBase::typeName << "'"
240  << "\n for patch " << p.name()
241  << " of field " << internalField().name()
242  << " in file " << internalField().objectPath()
243  << exit(FatalError);
244  }
245 
246 
247  this->readValueEntry(dict, IOobjectOption::MUST_READ);
248 
249  if (this->readMixedEntries(dict))
250  {
251  // Full restart
252  }
253  else
254  {
255  // Start from user entered data. Assume fixedValue.
256  refValue() = *this;
257  refGrad() = 0.0;
258  valueFraction() = 1.0;
259  }
260 }
261 
262 
263 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
264 turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
265 (
266  const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField& psf,
267  const DimensionedField<scalar, volMesh>& iF
268 )
269 :
270  mixedFvPatchScalarField(psf, iF),
271  regionType_(psf.regionType_),
272  method_(psf.method_),
273  kappaName_(psf.kappaName_),
274  otherPhaseName_(psf.otherPhaseName_),
275  TnbrName_(psf.TnbrName_),
276  qrNbrName_(psf.qrNbrName_),
277  qrName_(psf.qrName_)
278 {}
279 
280 
281 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
282 
283 void turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
284 updateCoeffs()
285 {
286  if (updated())
287  {
288  return;
289  }
290 
291  const polyMesh& mesh = patch().boundaryMesh().mesh();
292 
293  // Since we're inside initEvaluate/evaluate there might be processor
294  // comms underway. Change the tag we use.
295  int oldTag = UPstream::msgType();
296  UPstream::msgType() = oldTag+1;
297 
298  // Get the coupling information from the mappedPatchBase
299  const label patchi = patch().index();
300  const mappedPatchBase& mpp =
301  refCast<const mappedPatchBase>(patch().patch());
302  const polyMesh& nbrMesh = mpp.sampleMesh();
303  const label samplePatchi = mpp.samplePolyPatch().index();
304  const fvPatch& nbrPatch =
305  refCast<const fvMesh>(nbrMesh).boundary()[samplePatchi];
306 
307  scalarField& Tp = *this;
308 
309  const auto& nbrField =
310  refCast
311  <
312  const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
313  >(nbrPatch.lookupPatchField<volScalarField>(TnbrName_));
314 
315  // Swap to obtain full local values of neighbour internal field
316  scalarField TcNbr(nbrField.patchInternalField());
317  mpp.distribute(TcNbr);
318 
319 
320  // Swap to obtain full local values of neighbour K*delta
321  scalarField KDeltaNbr;
322  KDeltaNbr = nbrField.kappa(nbrField)*nbrPatch.deltaCoeffs();
323  mpp.distribute(KDeltaNbr);
324 
325  scalarField KDelta(kappa(Tp)*patch().deltaCoeffs());
326 
327  scalarField qr(Tp.size(), 0.0);
328  if (qrName_ != "none")
329  {
330  qr = patch().lookupPatchField<volScalarField>(qrName_);
331  }
332 
333  scalarField qrNbr(Tp.size(), 0.0);
334  if (qrNbrName_ != "none")
335  {
336  qrNbr = nbrPatch.lookupPatchField<volScalarField>(qrNbrName_);
337  mpp.distribute(qrNbr);
338  }
339 
340 
341  if (regionType_ == solid)
342  {
343  // Lookup the fluid model in the nbrFvMesh
344  const phaseSystem& fluid =
345  (
346  nbrMesh.lookupObject<phaseSystem>("phaseProperties")
347  );
348 
349  // The BC is applied to the liquid phase of the fluid
350  const phaseModel& liquid
351  (
352  fluid.phases()[nbrField.internalField().group()]
353  );
354 
355  const phaseModel& vapor(fluid.phases()[otherPhaseName_]);
356 
357 
358  scalarField KDeltaLiqNbr;
359  const fvPatchScalarField& alphal = liquid.boundaryField()[samplePatchi];
360  KDeltaLiqNbr =
361  alphal*(liquid.kappaEff(samplePatchi))*nbrPatch.deltaCoeffs();
362  mpp.distribute(KDeltaLiqNbr);
363 
364  scalarField KDeltaVapNbr;
365  const fvPatchScalarField& alphav = vapor.boundaryField()[samplePatchi];
366  KDeltaVapNbr =
367  alphav*(vapor.kappaEff(samplePatchi))*nbrPatch.deltaCoeffs();
368  mpp.distribute(KDeltaVapNbr);
369 
370  scalarField TvNbr;
371  const fvPatchScalarField& Tv =
372  vapor.thermo().T().boundaryField()[samplePatchi];
373  TvNbr = Tv.patchInternalField();
374  mpp.distribute(TvNbr);
375 
376  // TcNbr: liquid Tp
377  // TvNbr: vapour Tp
378  scalarField c(TcNbr*KDeltaLiqNbr + TvNbr*KDeltaVapNbr);
379 
380  //valueFraction() = KDeltaNbr/(KDeltaNbr + KDelta);
381  //refValue() = c/KDeltaNbr;
382  scalarField KDeltaLiqVapNbr(KDeltaLiqNbr + KDeltaVapNbr);
383  valueFraction() = KDeltaLiqVapNbr/(KDeltaLiqVapNbr + KDelta);
384  refValue() = c/KDeltaLiqVapNbr;
385  refGrad() = (qr + qrNbr)/kappa(Tp);
386 
387  if (debug)
388  {
389  scalar Q = gSum(kappa(Tp)*patch().magSf()*snGrad());
390 
391  Info<< "T solid : " << nl << endl;
392 
393  Info
394  << " heat transfer rate from solid:" << Q
395  << " walltemperature "
396  << " min:" << gMin(Tp)
397  << " max:" << gMax(Tp)
398  << " avg:" << gAverage(Tp) << nl
399  << endl;
400  }
401  }
402  else if (regionType_ == fluid)
403  {
404  const phaseSystem& fluid =
405  (
406  mesh.lookupObject<phaseSystem>("phaseProperties")
407  );
408 
409  const phaseModel& liquid
410  (
411  fluid.phases()[internalField().group()]
412  );
413 
414  const phaseModel& vapor(fluid.phases()[otherPhaseName_]);
415 
416  const fvPatchScalarField& Tv =
417  vapor.thermo().T().boundaryField()[patchi];
418 
419  const fvPatchScalarField& alphav = vapor.boundaryField()[patchi];
420 
421  const scalarField KdeltaVap
422  (
423  alphav*(vapor.kappaEff(patchi))*patch().deltaCoeffs()
424  );
425 
426  const fvPatchScalarField& alphal = liquid.boundaryField()[patchi];
427 
428  const scalarField KdeltaLiq
429  (
430  alphal*(liquid.kappaEff(patchi))*patch().deltaCoeffs()
431  );
432 
433  // TcNbr: solid Tp
434  // Tv: vapour Tp
435  const scalarField c(TcNbr*KDeltaNbr + Tv.patchInternalField()*KdeltaVap);
436 
437  const scalarField a(KdeltaVap + KDeltaNbr);
438 
439  valueFraction() = a/(a + KdeltaLiq);
440  refValue() = c/a;
441  refGrad() = (qr + qrNbr)/kappa(Tp);
442 
443  if (debug)
444  {
445  scalarField Tc(patchInternalField());
446  scalarField qLiq((Tp - Tc)*KdeltaLiq);
447  scalarField qVap((Tp - Tv.patchInternalField())*KdeltaVap);
448 
449  Info<< "T flow : " << nl << endl;
450 
451  Info<< " qLiq: " << gMin(qLiq) << " - " << gMax(qLiq) << endl;
452  Info<< " qVap: " << gMin(qVap) << " - " << gMax(qVap) << endl;
453 
454  scalar QLiq = gSum(qLiq*patch().magSf());
455  scalar QVap = gSum(qVap*patch().magSf());
456 
457  Info<< " Heat transfer to Liq: " << QLiq << endl;
458  Info<< " Heat transfer to Vap: " << QVap << endl;
459 
460  Info<< " walltemperature "
461  << " min:" << gMin(Tp)
462  << " max:" << gMax(Tp)
463  << " avg:" << gAverage(Tp)
464  << endl;
465  }
466  }
467  else
468  {
470  << "Unknown phase type. Valid types are: "
471  << regionTypeNames_ << nl << exit(FatalError);
472  }
473 
474  mixedFvPatchScalarField::updateCoeffs();
475 
476  // Restore tag
477  UPstream::msgType() = oldTag;
478 }
479 
480 
482 (
483  Ostream& os
484 ) const
485 {
487  os.writeEntry("kappaMethod", KMethodTypeNames_[method_]);
488  os.writeEntryIfDifferent<word>("kappa","none", kappaName_);
489 
490  os.writeEntry("Tnbr", TnbrName_);
491 
492  os.writeEntryIfDifferent<word>("qrNbr", "none", qrNbrName_);
493  os.writeEntryIfDifferent<word>("qr", "none", qrName_);
494 
495  os.writeEntry("region", regionTypeNames_[regionType_]);
496  os.writeEntry("otherPhase", otherPhaseName_);
497 }
498 
499 
500 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
501 
503 (
505  turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
506 );
507 
508 
509 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
510 
511 } // End namespace compressible
512 } // End namespace Foam
513 
514 
515 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
word dictName() const
The local dictionary name (final part of scoped name)
Definition: dictionaryI.H:53
faceListList boundary
twoPhaseSystem & fluid
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
Definition: volFieldsFwd.H:85
dictionary dict
Field< symmTensor > symmTensorField
Specialisation of Field<T> for symmTensor.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
label phasei
Definition: pEqn.H:27
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
Type gMin(const FieldField< Field, Type > &f)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Type & refCast(U &obj)
A dynamic_cast (for references). Generates a FatalError on failed casts and uses the virtual type() m...
Definition: typeInfo.H:159
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
kappaEff
Definition: TEqn.H:10
const dimensionedScalar kappa
Coulomb constant: default SI units: [N.m2/C2].
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
psiReactionThermo & thermo
Definition: createFields.H:28
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
dynamicFvMesh & mesh
Type gSum(const FieldField< Field, Type > &f)
fvPatchField< scalar > fvPatchScalarField
alphal
Definition: alphavPsi.H:3
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:212
bool compressible
Definition: pEqn.H:2
int debug
Static debugging option.
Type gMax(const FieldField< Field, Type > &f)
OBJstream os(runTime.globalPath()/outputName)
List< word > sortedToc() const
The sorted list of enum names.
Definition: EnumI.H:63
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Type gAverage(const FieldField< Field, Type > &f)
const dimensionedScalar c
Speed of light in a vacuum.
const std::string patch
OpenFOAM patch number as a std::string.
messageStream Info
Information stream (stdout output on master, null elsewhere)
tmp< Field< Type > > T() const
Return the field transpose (only defined for second rank tensors)
Definition: Field.C:711
label n
Field< vector > vectorField
Specialisation of Field<T> for vector.
#define makePatchTypeField(PatchTypeField, typePatchTypeField)
Define a concrete fvPatchField type and add to run-time tables Example, (fvPatchScalarField, calculatedFvPatchScalarField)
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, volMesh > &)
Construct from patch and internal field.
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvcSnGrad.C:40
Namespace for OpenFOAM.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133