externalWallHeatFluxTemperature: Removed "mode"

Heat power (Q), heat flux (q) and heat transfer coefficient (h)
can now all be specified simultaneously. Their effects will be summed
into a single heat transfer rate. The "mode" keyword is no longer
required.
This commit is contained in:
Will Bainbridge
2022-03-07 09:01:49 +00:00
parent e7aaae76ac
commit 373c4993a8
3 changed files with 238 additions and 307 deletions

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -30,30 +30,6 @@ License
using Foam::constant::physicoChemical::sigma; using Foam::constant::physicoChemical::sigma;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
template<>
const char*
NamedEnum
<
externalWallHeatFluxTemperatureFvPatchScalarField::operationMode,
3
>::names[] =
{
"power",
"flux",
"coefficient"
};
}
const Foam::NamedEnum
<
Foam::externalWallHeatFluxTemperatureFvPatchScalarField::operationMode,
3
> Foam::externalWallHeatFluxTemperatureFvPatchScalarField::operationModeNames;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -66,15 +42,20 @@ externalWallHeatFluxTemperatureFvPatchScalarField
: :
mixedFvPatchScalarField(p, iF), mixedFvPatchScalarField(p, iF),
temperatureCoupledBase(patch()), temperatureCoupledBase(patch()),
mode_(fixedHeatFlux), haveQ_(false),
Q_(0), Q_(NaN),
haveq_(false),
q_(),
haveh_(false),
h_(),
Ta_(), Ta_(),
relaxation_(1),
emissivity_(0), emissivity_(0),
qrRelaxation_(1),
qrName_("undefined-qr"),
thicknessLayers_(), thicknessLayers_(),
kappaLayers_() kappaLayers_(),
relaxation_(1),
qrName_(word::null),
qrRelaxation_(1),
qrPrevious_()
{ {
refValue() = 0; refValue() = 0;
refGrad() = 0; refGrad() = 0;
@ -92,57 +73,50 @@ externalWallHeatFluxTemperatureFvPatchScalarField
: :
mixedFvPatchScalarField(p, iF), mixedFvPatchScalarField(p, iF),
temperatureCoupledBase(patch(), dict), temperatureCoupledBase(patch(), dict),
mode_(operationModeNames.read(dict.lookup("mode"))), haveQ_(dict.found("Q")),
Q_(0), Q_(haveQ_ ? dict.lookup<scalar>("Q") : NaN),
Ta_(), haveq_(dict.found("q")),
relaxation_(dict.lookupOrDefault<scalar>("relaxation", 1)), q_(haveq_ ? scalarField("q", dict, p.size()) : scalarField()),
haveh_(dict.found("h")),
h_(haveh_ ? scalarField("h", dict, p.size()) : scalarField()),
Ta_(haveh_ ? Function1<scalar>::New("Ta", dict).ptr() : nullptr),
emissivity_(dict.lookupOrDefault<scalar>("emissivity", 0)), emissivity_(dict.lookupOrDefault<scalar>("emissivity", 0)),
thicknessLayers_
(
dict.lookupOrDefault<scalarList>("thicknessLayers", scalarList())
),
kappaLayers_
(
dict.lookupOrDefault<scalarList>("kappaLayers", scalarList())
),
relaxation_(dict.lookupOrDefault<scalar>("relaxation", 1)),
qrName_(dict.lookupOrDefault<word>("qr", word::null)),
qrRelaxation_(dict.lookupOrDefault<scalar>("qrRelaxation", 1)), qrRelaxation_(dict.lookupOrDefault<scalar>("qrRelaxation", 1)),
qrName_(dict.lookupOrDefault<word>("qr", "none")), qrPrevious_
thicknessLayers_(), (
kappaLayers_() qrName_ != word::null
? dict.found("qrPrevious")
? scalarField("qrPrevious", dict, p.size())
: scalarField(0, p.size())
: scalarField()
)
{ {
switch (mode_)
{
case fixedPower:
{
dict.lookup("Q") >> Q_;
break;
}
case fixedHeatFlux:
{
q_ = scalarField("q", dict, p.size());
break;
}
case fixedHeatTransferCoeff:
{
h_ = scalarField("h", dict, p.size());
Ta_ = Function1<scalar>::New("Ta", dict);
if (dict.found("thicknessLayers"))
{
dict.lookup("thicknessLayers") >> thicknessLayers_;
dict.lookup("kappaLayers") >> kappaLayers_;
}
break;
}
}
fvPatchScalarField::operator=(scalarField("value", dict, p.size())); fvPatchScalarField::operator=(scalarField("value", dict, p.size()));
if (qrName_ != "none") if (!haveQ_ && !haveq_ && !haveh_)
{ {
if (dict.found("qrPrevious")) FatalIOErrorInFunction(dict)
{ << "One or more of Q (heat power), q (heat flux), and h (heat "
qrPrevious_ = scalarField("qrPrevious", dict, p.size()); << "transfer coefficient) must be specified"
} << exit(FatalIOError);
else }
{
qrPrevious_.setSize(p.size(), 0); if (thicknessLayers_.size() != kappaLayers_.size())
} {
FatalIOErrorInFunction(dict)
<< "If either thicknessLayers or kappaLayers is specified, then "
<< "both must be specified and be lists of the same length "
<< exit(FatalIOError);
} }
if (dict.found("refValue")) if (dict.found("refValue"))
@ -173,39 +147,26 @@ externalWallHeatFluxTemperatureFvPatchScalarField
: :
mixedFvPatchScalarField(ptf, p, iF, mapper), mixedFvPatchScalarField(ptf, p, iF, mapper),
temperatureCoupledBase(patch(), ptf), temperatureCoupledBase(patch(), ptf),
mode_(ptf.mode_), haveQ_(ptf.haveQ_),
Q_(ptf.Q_), Q_(ptf.Q_),
haveq_(ptf.haveq_),
q_(haveq_ ? mapper(ptf.q_)() : scalarField()),
haveh_(ptf.haveq_),
h_(haveh_ ? mapper(ptf.q_)() : scalarField()),
Ta_(ptf.Ta_, false), Ta_(ptf.Ta_, false),
relaxation_(ptf.relaxation_),
emissivity_(ptf.emissivity_), emissivity_(ptf.emissivity_),
qrRelaxation_(ptf.qrRelaxation_),
qrName_(ptf.qrName_),
thicknessLayers_(ptf.thicknessLayers_), thicknessLayers_(ptf.thicknessLayers_),
kappaLayers_(ptf.kappaLayers_) kappaLayers_(ptf.kappaLayers_),
{ relaxation_(ptf.relaxation_),
switch (mode_) qrName_(ptf.qrName_),
{ qrRelaxation_(ptf.qrRelaxation_),
case fixedPower: qrPrevious_
{ (
break; qrName_ != word::null
} ? mapper(ptf.qrPrevious_)()
case fixedHeatFlux: : scalarField()
{ )
mapper(q_, ptf.q_); {}
break;
}
case fixedHeatTransferCoeff:
{
mapper(h_, ptf.h_);
break;
}
}
if (qrName_ != "none")
{
mapper(qrPrevious_, ptf.qrPrevious_);
}
}
Foam::externalWallHeatFluxTemperatureFvPatchScalarField:: Foam::externalWallHeatFluxTemperatureFvPatchScalarField::
@ -217,18 +178,20 @@ externalWallHeatFluxTemperatureFvPatchScalarField
: :
mixedFvPatchScalarField(tppsf, iF), mixedFvPatchScalarField(tppsf, iF),
temperatureCoupledBase(patch(), tppsf), temperatureCoupledBase(patch(), tppsf),
mode_(tppsf.mode_), haveQ_(tppsf.haveQ_),
Q_(tppsf.Q_), Q_(tppsf.Q_),
haveq_(tppsf.haveq_),
q_(tppsf.q_), q_(tppsf.q_),
haveh_(tppsf.haveh_),
h_(tppsf.h_), h_(tppsf.h_),
Ta_(tppsf.Ta_, false), Ta_(tppsf.Ta_, false),
relaxation_(tppsf.relaxation_),
emissivity_(tppsf.emissivity_), emissivity_(tppsf.emissivity_),
qrPrevious_(tppsf.qrPrevious_),
qrRelaxation_(tppsf.qrRelaxation_),
qrName_(tppsf.qrName_),
thicknessLayers_(tppsf.thicknessLayers_), thicknessLayers_(tppsf.thicknessLayers_),
kappaLayers_(tppsf.kappaLayers_) kappaLayers_(tppsf.kappaLayers_),
relaxation_(tppsf.relaxation_),
qrName_(tppsf.qrName_),
qrRelaxation_(tppsf.qrRelaxation_),
qrPrevious_(tppsf.qrPrevious_)
{} {}
@ -241,27 +204,17 @@ void Foam::externalWallHeatFluxTemperatureFvPatchScalarField::autoMap
{ {
mixedFvPatchScalarField::autoMap(m); mixedFvPatchScalarField::autoMap(m);
switch (mode_) if (haveq_)
{ {
case fixedPower: m(q_, q_);
{
break;
}
case fixedHeatFlux:
{
m(q_, q_);
break;
}
case fixedHeatTransferCoeff:
{
m(h_, h_);
break;
}
} }
if (qrName_ != "none") if (haveh_)
{
m(h_, h_);
}
if (qrName_ != word::null)
{ {
m(qrPrevious_, qrPrevious_); m(qrPrevious_, qrPrevious_);
} }
@ -279,27 +232,17 @@ void Foam::externalWallHeatFluxTemperatureFvPatchScalarField::rmap
const externalWallHeatFluxTemperatureFvPatchScalarField& tiptf = const externalWallHeatFluxTemperatureFvPatchScalarField& tiptf =
refCast<const externalWallHeatFluxTemperatureFvPatchScalarField>(ptf); refCast<const externalWallHeatFluxTemperatureFvPatchScalarField>(ptf);
switch (mode_) if (haveq_)
{ {
case fixedPower: q_.rmap(tiptf.q_, addr);
{
break;
}
case fixedHeatFlux:
{
q_.rmap(tiptf.q_, addr);
break;
}
case fixedHeatTransferCoeff:
{
h_.rmap(tiptf.h_, addr);
break;
}
} }
if (qrName_ != "none") if (haveh_)
{
h_.rmap(tiptf.h_, addr);
}
if (qrName_ != word::null)
{ {
qrPrevious_.rmap(tiptf.qrPrevious_, addr); qrPrevious_.rmap(tiptf.qrPrevious_, addr);
} }
@ -319,103 +262,98 @@ void Foam::externalWallHeatFluxTemperatureFvPatchScalarField::updateCoeffs()
const scalarField valueFraction0(valueFraction()); const scalarField valueFraction0(valueFraction());
const scalarField refValue0(refValue()); const scalarField refValue0(refValue());
// Get the radiative heat flux and relax
scalarField qr(Tp.size(), 0); scalarField qr(Tp.size(), 0);
if (qrName_ != "none") if (qrName_ != word::null)
{ {
qr = qr =
qrRelaxation_ qrRelaxation_
*patch().lookupPatchField<volScalarField, scalar>(qrName_) *patch().lookupPatchField<volScalarField, scalar>(qrName_)
+ (1 - qrRelaxation_)*qrPrevious_; + (1 - qrRelaxation_)*qrPrevious_;
qrPrevious_ = qr; qrPrevious_ = qr;
} }
switch (mode_) // Compute the total non-convective heat flux
scalarField qTot(qr);
if (haveQ_)
{ {
case fixedPower: qTot += Q_;
{ }
refGrad() = (Q_/gSum(patch().magSf()) + qr)/kappa(*this); if (haveq_)
refValue() = Tp; {
valueFraction() = 0; qTot += q_;
}
break; // Evaluate
} if (!haveh_)
case fixedHeatFlux: {
refGrad() = qTot/kappa(*this);
refValue() = Tp;
valueFraction() = 0;
}
else
{
scalar totalSolidRes = 0;
if (thicknessLayers_.size())
{ {
refGrad() = (q_ + qr)/kappa(*this); forAll(thicknessLayers_, iLayer)
refValue() = Tp;
valueFraction() = 0;
break;
}
case fixedHeatTransferCoeff:
{
scalar totalSolidRes = 0;
if (thicknessLayers_.size())
{ {
forAll(thicknessLayers_, iLayer) const scalar l = thicknessLayers_[iLayer];
if (kappaLayers_[iLayer] > 0)
{ {
const scalar l = thicknessLayers_[iLayer]; totalSolidRes += l/kappaLayers_[iLayer];
if (kappaLayers_[iLayer] > 0)
{
totalSolidRes += l/kappaLayers_[iLayer];
}
} }
} }
}
const scalar Ta = Ta_->value(this->db().time().userTimeValue()); const scalar Ta = Ta_->value(this->db().time().userTimeValue());
const scalarField hp const scalarField hp
( (
1
/(
1 1
/( /(
1 (emissivity_ > 0)
/( ? (
(emissivity_ > 0) h_
? ( + emissivity_*sigma.value()
h_ *((pow3(Ta) + pow3(Tp)) + Ta*Tp*(Ta + Tp))
+ emissivity_*sigma.value() )()
*((pow3(Ta) + pow3(Tp)) + Ta*Tp*(Ta + Tp)) : h_
)() ) + totalSolidRes
: h_ )
) + totalSolidRes );
)
);
const scalarField hpTa(hp*Ta); const scalarField hpTa(hp*Ta);
const scalarField kappaDeltaCoeffs const scalarField kappaDeltaCoeffs
( (
this->kappa(*this)*patch().deltaCoeffs() this->kappa(*this)*patch().deltaCoeffs()
); );
refGrad() = 0; refGrad() = 0;
forAll(Tp, i)
forAll(Tp, i) {
if (qTot[i] < 0)
{ {
if (qr[i] < 0) const scalar hpmqTot = hp[i] - qTot[i]/Tp[i];
{ refValue()[i] = hpTa[i]/hpmqTot;
const scalar hpmqr = hp[i] - qr[i]/Tp[i]; valueFraction()[i] = hpmqTot/(hpmqTot + kappaDeltaCoeffs[i]);
}
refValue()[i] = hpTa[i]/hpmqr; else
valueFraction()[i] = hpmqr/(hpmqr + kappaDeltaCoeffs[i]); {
} refValue()[i] = (hpTa[i] + qTot[i])/hp[i];
else valueFraction()[i] = hp[i]/(hp[i] + kappaDeltaCoeffs[i]);
{
refValue()[i] = (hpTa[i] + qr[i])/hp[i];
valueFraction()[i] = hp[i]/(hp[i] + kappaDeltaCoeffs[i]);
}
} }
break;
} }
} }
// Relax
valueFraction() = valueFraction() =
relaxation_*valueFraction() relaxation_*valueFraction() + (1 - relaxation_)*valueFraction0;
+ (1 - relaxation_)*valueFraction0; refValue() =
relaxation_*refValue() + (1 - relaxation_)*refValue0;
refValue() = relaxation_*refValue() + (1 - relaxation_)*refValue0;
mixedFvPatchScalarField::updateCoeffs(); mixedFvPatchScalarField::updateCoeffs();
@ -443,54 +381,45 @@ void Foam::externalWallHeatFluxTemperatureFvPatchScalarField::write
{ {
fvPatchScalarField::write(os); fvPatchScalarField::write(os);
writeEntry(os, "mode", operationModeNames[mode_]);
temperatureCoupledBase::write(os); temperatureCoupledBase::write(os);
switch (mode_) if (haveQ_)
{ {
case fixedPower: writeEntry(os, "Q", Q_);
{
writeEntry(os, "Q", Q_);
break;
}
case fixedHeatFlux:
{
writeEntry(os, "q", q_);
break;
}
case fixedHeatTransferCoeff:
{
writeEntry(os, "h", h_);
writeEntry(os, Ta_());
if (relaxation_ < 1)
{
writeEntry(os, "relaxation", relaxation_);
}
if (emissivity_ > 0)
{
writeEntry(os, "emissivity", emissivity_);
}
if (thicknessLayers_.size())
{
writeEntry(os, "thicknessLayers", thicknessLayers_);
writeEntry(os, "kappaLayers", kappaLayers_);
}
break;
}
} }
writeEntry(os, "qr", qrName_); if (haveq_)
if (qrName_ != "none")
{ {
writeEntry(os, "qrRelaxation", qrRelaxation_); writeEntry(os, "q", q_);
}
if (haveh_)
{
writeEntry(os, "h", h_);
writeEntry(os, Ta_());
writeEntryIfDifferent(os, "emissivity", scalar(0), emissivity_);
writeEntryIfDifferent
(
os,
"thicknessLayers",
scalarList(),
thicknessLayers_
);
writeEntryIfDifferent
(
os,
"kappaLayers",
scalarList(),
kappaLayers_
);
}
writeEntryIfDifferent(os, "relaxation", scalar(1), relaxation_);
if (qrName_ != word::null)
{
writeEntry(os, "qr", qrName_);
writeEntry(os, "qrRelaxation", qrRelaxation_);
writeEntry(os, "qrPrevious", qrPrevious_); writeEntry(os, "qrPrevious", qrPrevious_);
} }

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -26,7 +26,7 @@ Class
Description Description
This boundary condition applies a heat flux condition to temperature This boundary condition applies a heat flux condition to temperature
on an external wall in one of three modes: on an external wall. Heat flux can be specified in the following ways:
- fixed power: supply Q - fixed power: supply Q
- fixed heat flux: supply q - fixed heat flux: supply q
@ -40,8 +40,11 @@ Description
Ta | Ambient temperature [K] Ta | Ambient temperature [K]
\endvartable \endvartable
For heat transfer coefficient mode optional thin thermal layer resistances If more than one parameter is given then the heat fluxes are summed.
can be specified through thicknessLayers and kappaLayers entries.
If a heat transfer coefficient is given optional thin thermal layer
resistances can be specified through thicknessLayers and kappaLayers
entries.
The thermal conductivity \c kappa can either be retrieved from various The thermal conductivity \c kappa can either be retrieved from various
possible sources, as detailed in the class temperatureCoupledBase. possible sources, as detailed in the class temperatureCoupledBase.
@ -52,12 +55,11 @@ Description
Usage Usage
\table \table
Property | Description | Required | Default value Property | Description | Required | Default value
mode | 'power', 'flux' or 'coefficient' | yes | Q | Power [W] | no | 0
Q | Power [W] | for mode 'power' | q | Heat flux [W/m^2] | no | 0
q | Heat flux [W/m^2] | for mode 'flux' | h | Heat transfer coefficient [W/m^2/K] | no | 0
h | Heat transfer coefficient [W/m^2/K] | for mode 'coefficent' | Ta | Ambient temperature [K] | if h is given |
Ta | Ambient temperature [K] | for mode 'coefficient' | thicknessLayers | Layer thicknesses [m] | no |
thicknessLayers | Layer thicknesses [m] | no |
kappaLayers | Layer thermal conductivities [W/m/K] | no | kappaLayers | Layer thermal conductivities [W/m/K] | no |
relaxation | Relaxation for the wall temperature | no | 1 relaxation | Relaxation for the wall temperature | no | 1
emissivity | Surface emissivity for radiative flux to ambient | no | 0 emissivity | Surface emissivity for radiative flux to ambient | no | 0
@ -71,8 +73,6 @@ Usage
{ {
type externalWallHeatFluxTemperature; type externalWallHeatFluxTemperature;
mode coefficient;
Ta constant 300.0; Ta constant 300.0;
h uniform 10.0; h uniform 10.0;
thicknessLayers (0.1 0.2 0.3 0.4); thicknessLayers (0.1 0.2 0.3 0.4);
@ -112,60 +112,63 @@ class externalWallHeatFluxTemperatureFvPatchScalarField
public mixedFvPatchScalarField, public mixedFvPatchScalarField,
public temperatureCoupledBase public temperatureCoupledBase
{ {
public:
// Public data
//- Operation mode enumeration
enum operationMode
{
fixedPower,
fixedHeatFlux,
fixedHeatTransferCoeff
};
static const NamedEnum<operationMode, 3> operationModeNames;
private: private:
// Private Data // Private Data
//- Operation mode // Heat power
operationMode mode_;
//- Heat power [W] //- Do we have a heat power?
scalar Q_; bool haveQ_;
//- Heat flux [W/m^2] //- Heat power [W]
scalarField q_; scalar Q_;
//- Heat transfer coefficient [W/m^2K]
scalarField h_;
//- Ambient temperature [K] // Heat flux
autoPtr<Function1<scalar>> Ta_;
//- Do we have a heat flux?
bool haveq_;
//- Heat flux [W/m^2]
scalarField q_;
// Heat transfer coefficient
//- Do we have a heat transfer coefficient?
bool haveh_;
//- Heat transfer coefficient [W/m^2K]
scalarField h_;
//- Ambient temperature [K]
autoPtr<Function1<scalar>> Ta_;
//- Optional surface emissivity for radiative transfer to ambient
scalar emissivity_;
//- Thickness of layers
scalarList thicknessLayers_;
//- Conductivity of layers
scalarList kappaLayers_;
//- Relaxation for the wall temperature (thermal inertia) //- Relaxation for the wall temperature (thermal inertia)
scalar relaxation_; scalar relaxation_;
//- Optional surface emissivity for radiative transfer to ambient
scalar emissivity_;
//- Cache qr for relaxation // Radiation
scalarField qrPrevious_;
//- Relaxation for qr //- Name of the radiative heat flux
scalar qrRelaxation_; const word qrName_;
//- Name of the radiative heat flux //- Relaxation for qr
const word qrName_; scalar qrRelaxation_;
//- Thickness of layers //- Cache qr for relaxation
scalarList thicknessLayers_; scalarField qrPrevious_;
//- Conductivity of layers
scalarList kappaLayers_;
public: public:

View File

@ -25,7 +25,6 @@ boundaryField
external external
{ {
type externalWallHeatFluxTemperature; type externalWallHeatFluxTemperature;
mode coefficient;
h uniform 1e3; h uniform 1e3;
Ta $internalField; Ta $internalField;
value $internalField; value $internalField;