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

View File

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

View File

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