Skip to content

Commit

Permalink
Merge pull request #27853 from joshuahansel/hs-coupler-2d3d-convection
Browse files Browse the repository at this point in the history
Added convection to HSCoupler2D3D
  • Loading branch information
joshuahansel authored Jun 11, 2024
2 parents 5f09752 + ae3f9dc commit ed37a79
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# HSCoupler2D3D

This component is used to couple a [HeatStructureCylindrical.md] and a
[HeatStructureFromFile3D.md] via gap conduction and radiation.
[HeatStructureFromFile3D.md] via gap conduction, radiation, and convection.

## Formulation

Expand Down Expand Up @@ -34,10 +34,10 @@ where

This approach guarantees energy conservation of this heat exchange.

The heat flux is composed of two pieces, corresponding to conduction and radiation:
The heat flux is composed of three pieces, corresponding to conduction, radiation, and convection:

!equation
q_{z,\theta} = q^\text{cond}_{z,\theta} + q^\text{rad}_{z,\theta} \,.
q_{z,\theta} = q^\text{cond}_{z,\theta} + q^\text{rad}_{z,\theta} + q^\text{conv}_{r,\theta} \,.

Before describing these pieces, we describe some preliminaries.

Expand Down Expand Up @@ -116,6 +116,18 @@ q^\text{rad}_{z,\theta} = \frac{\sigma (T_z^4 - T_{z,\theta}^4)}{\mathcal{R}_{z,

where $\sigma$ is the Stefan-Boltzmann constant.

### Convection Heat Flux

The convection heat flux is computed as

!equation
q^\text{conv}_{z,\theta} = h^\text{gap}_{z,\theta} (T_z - T_{z,\theta}) \,,

where the gap heat transfer coefficient is evaluated at the gap temperature:

!equation
h^\text{gap}_{z,\theta} = h_\text{gap}(T^\text{gap}_{z,\theta}) \,.

## Restrictions and Assumptions

- Currently, no contact ($\delta = 0$) is permitted, but this restriction is
Expand All @@ -135,19 +147,26 @@ corresponding to each heat structure, at which the heat exchange occurs.

The parameters [!param](/Components/HSCoupler2D3D/emissivity_2d),
[!param](/Components/HSCoupler2D3D/emissivity_3d),
[!param](/Components/HSCoupler2D3D/gap_thickness), and
[!param](/Components/HSCoupler2D3D/gap_thermal_conductivity) correspond
[!param](/Components/HSCoupler2D3D/gap_thickness),
[!param](/Components/HSCoupler2D3D/gap_thermal_conductivity), and
[!param](/Components/HSCoupler2D3D/gap_htc) correspond
to [Functions](Functions/index.md) of the relevant temperature; respectively,
these correspond to

- $\epsilon_\text{2D}(T_\text{2D})$,
- $\epsilon_\text{3D}(T_\text{3D})$,
- $\delta(T_\text{gap})$, and
- $k_\text{gap}(T_\text{gap})$.
- $\delta(T_\text{gap})$,
- $k_\text{gap}(T_\text{gap})$, and
- $h_\text{gap}(T_\text{gap})$.

The temperature values are substituted in place of the time coordinate for
these `Function`s.

The radiation component of the heat flux can be disabled by setting
[!param](/Components/HSCoupler2D3D/include_radiation) to `false`, and in this
case the parameters [!param](/Components/HSCoupler2D3D/emissivity_2d) and
[!param](/Components/HSCoupler2D3D/emissivity_3d) should not be specified.

### MOOSE Configuration

Because a 2D surface is being coupled to a 3D surface, there is potentially
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ class HSCoupler2D3DUserObject : public SideUserObject
const Function & _emissivity_2d_fn;
/// Emissivity of the 3D heat structure boundary as a function of temperature
const Function & _emissivity_3d_fn;
/// Include radiation?
const bool _include_radiation;
/// Gap thickness as a function of temperature
const Function & _gap_thickness_fn;
/// Gap thermal conductivity as a function of temperature
const Function & _k_gap_fn;
/// Gap heat transfer coefficient as a function of temperature
const Function & _htc_gap_fn;

/// User object containing the temperature values on the 2D boundary
const StoreVariableByElemIDSideUserObject & _temperature_2d_uo;
Expand Down
28 changes: 24 additions & 4 deletions modules/thermal_hydraulics/src/components/HSCoupler2D3D.C
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@ HSCoupler2D3D::validParams()
params.addRequiredParam<BoundaryName>("boundary_3d",
"The boundary of the 3D heat structure to couple");

params.addRequiredParam<FunctionName>(
params.addParam<bool>("include_radiation", true, "Include radiation component of heat flux");
params.addParam<FunctionName>(
"emissivity_2d",
"Emissivity of the 2D heat structure boundary as a function of temperature [K]");
params.addRequiredParam<FunctionName>(
params.addParam<FunctionName>(
"emissivity_3d",
"Emissivity of the 3D heat structure boundary as a function of temperature [K]");
params.addRequiredParam<FunctionName>("gap_thickness",
"Gap thickness [m] as a function of temperature [K]");
params.addRequiredParam<FunctionName>(
"gap_thermal_conductivity",
"Gap thermal conductivity [W/(m-K)] as a function of temperature [K]");
params.addParam<FunctionName>(
"gap_htc", 0, "Gap heat transfer coefficient [W/(m^2-K)] as a function of temperature [K]");

params.addClassDescription("Couples a 2D heat structure boundary to a 3D heat structure boundary "
"using gap heat transfer.");
Expand Down Expand Up @@ -95,6 +98,19 @@ HSCoupler2D3D::check() const
{
BoundaryBase::check();

if (getParam<bool>("include_radiation"))
{
if (!(isParamValid("emissivity_2d") && isParamValid("emissivity_3d")))
logError("If 'include_radiation' is 'true', then 'emissivity_2d' and 'emissivity_3d' are "
"required.");
}
else
{
if (isParamValid("emissivity_2d") || isParamValid("emissivity_3d"))
logError("If 'include_radiation' is 'false', then neither 'emissivity_2d' nor "
"'emissivity_3d' can be specified.");
}

if (hasComponentByName<HeatStructureCylindricalBase>(_hs_name_2d))
{
const auto & hs = getComponentByName<HeatStructureCylindricalBase>(_hs_name_2d);
Expand Down Expand Up @@ -161,11 +177,15 @@ HSCoupler2D3D::addMooseObjects()
params.set<std::vector<BoundaryName>>("boundary") = {_boundary_3d};
params.set<std::vector<VariableName>>("temperature") = {HeatConductionModel::TEMPERATURE};
params.set<Real>("radius_2d") = radius_2d;
params.set<FunctionName>("emissivity_2d") = getParam<FunctionName>("emissivity_2d");
params.set<FunctionName>("emissivity_3d") = getParam<FunctionName>("emissivity_3d");
if (getParam<bool>("include_radiation"))
{
params.set<FunctionName>("emissivity_2d") = getParam<FunctionName>("emissivity_2d");
params.set<FunctionName>("emissivity_3d") = getParam<FunctionName>("emissivity_3d");
}
params.set<FunctionName>("gap_thickness") = getParam<FunctionName>("gap_thickness");
params.set<FunctionName>("gap_thermal_conductivity") =
getParam<FunctionName>("gap_thermal_conductivity");
params.set<FunctionName>("gap_htc") = getParam<FunctionName>("gap_htc");
params.set<UserObjectName>("temperature_2d_uo") = temperature_2d_uo_name;
params.set<MeshAlignment2D3D *>("mesh_alignment") = &_mesh_alignment;
params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,21 @@ HSCoupler2D3DUserObject::validParams()

params.addRequiredCoupledVar("temperature", "Temperature");
params.addRequiredParam<Real>("radius_2d", "Radius of the 2D heat structure boundary [m]");
params.addRequiredParam<FunctionName>(
params.addParam<FunctionName>(
"emissivity_2d",
0,
"Emissivity of the 2D heat structure boundary as a function of temperature [K]");
params.addRequiredParam<FunctionName>(
params.addParam<FunctionName>(
"emissivity_3d",
0,
"Emissivity of the 3D heat structure boundary as a function of temperature [K]");
params.addRequiredParam<FunctionName>("gap_thickness",
"Gap thickness [m] as a function of temperature [K]");
params.addRequiredParam<FunctionName>(
"gap_thermal_conductivity",
"Gap thermal conductivity [W/(m-K)] as a function of temperature [K]");
params.addParam<FunctionName>(
"gap_htc", 0, "Gap heat transfer coefficient [W/(m^2-K)] as a function of temperature [K]");
params.addRequiredParam<UserObjectName>(
"temperature_2d_uo",
"StoreVariableByElemIDSideUserObject containing the temperature values on the 2D boundary");
Expand All @@ -51,8 +55,10 @@ HSCoupler2D3DUserObject::HSCoupler2D3DUserObject(const InputParameters & paramet
_r_2d(getParam<Real>("radius_2d")),
_emissivity_2d_fn(getFunction("emissivity_2d")),
_emissivity_3d_fn(getFunction("emissivity_3d")),
_include_radiation(isParamSetByUser("emissivity_2d") && isParamSetByUser("emissivity_3d")),
_gap_thickness_fn(getFunction("gap_thickness")),
_k_gap_fn(getFunction("gap_thermal_conductivity")),
_htc_gap_fn(getFunction("gap_htc")),
_temperature_2d_uo(getUserObject<StoreVariableByElemIDSideUserObject>("temperature_2d_uo")),
_mesh_alignment(*getParam<MeshAlignment2D3D *>("mesh_alignment"))
{
Expand Down Expand Up @@ -87,22 +93,29 @@ HSCoupler2D3DUserObject::execute()
const auto & T_3d = _T_3d[qp_3d];
const auto T_gap = 0.5 * (T_2d + T_3d);

const auto emissivity_2d = evaluateTemperatureFunction(_emissivity_2d_fn, T_2d);
const auto emissivity_3d = evaluateTemperatureFunction(_emissivity_3d_fn, T_3d);
const auto gap_thickness = evaluateTemperatureFunction(_gap_thickness_fn, T_gap);
const auto k_gap = evaluateTemperatureFunction(_k_gap_fn, T_gap);

if (!MooseUtils::absoluteFuzzyGreaterThan(gap_thickness, 0))
mooseError("Gap thickness must be > 0.");

const auto r_3d = _r_2d + gap_thickness;
const auto r_gap = 0.5 * (_r_2d + r_3d);

const auto heat_flux_cond =
HeatTransferModels::cylindricalGapConductionHeatFlux(k_gap, _r_2d, r_3d, T_2d, T_3d);
const auto heat_flux_rad = HeatTransferModels::cylindricalGapRadiationHeatFlux(
_r_2d, r_3d, emissivity_2d, emissivity_3d, T_2d, T_3d);
const auto heat_flux = heat_flux_cond + heat_flux_rad;
auto heat_flux = heat_flux_cond;

const auto htc = evaluateTemperatureFunction(_htc_gap_fn, T_gap);
heat_flux += htc * (T_2d - T_3d);

if (_include_radiation)
{
const auto emissivity_2d = evaluateTemperatureFunction(_emissivity_2d_fn, T_2d);
const auto emissivity_3d = evaluateTemperatureFunction(_emissivity_3d_fn, T_3d);

heat_flux += HeatTransferModels::cylindricalGapRadiationHeatFlux(
_r_2d, r_3d, emissivity_2d, emissivity_3d, T_2d, T_3d);
}

heat_flux_3d[qp_3d] = heat_flux;
heat_flux_2d[qp_2d] -= _JxW[qp_3d] * _coord[qp_3d] * heat_flux / area_2d[qp_2d];
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ n_elems_axial_extend = 12
boundary_2d = hs2d:matrix:outer
boundary_3d = hs3d:rmin

emissivity_2d = 0.4
emissivity_3d = 0.6
include_radiation = false
gap_thickness = 0.00001
gap_thermal_conductivity = 0.05
[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[Tests]
design = 'HSCoupler2D3D.md'
issues = '#23059'
issues = '#23059 #27830'

[check_input_mesh]
type = RunApp
Expand All @@ -11,10 +11,36 @@
[]

[test]
type = Exodiff
input = hs_coupler_2d3d.i
exodiff = hs_coupler_2d3d_out.e
requirement = 'The system shall couple a 2D heat structure with a 3D heat structure.'
requirement = 'The system shall couple a 2D heat structure with a 3D heat structure'

[conduction_plus_radiation]
type = Exodiff
input = hs_coupler_2d3d.i
cli_args = "
Components/hs_coupler/include_radiation=true
Components/hs_coupler/emissivity_2d=0.4
Components/hs_coupler/emissivity_3d=0.6
Outputs/file_base=conduction_plus_radiation"
exodiff = conduction_plus_radiation.e
detail = 'using conduction and radiation.'
[]
[conduction_only]
type = Exodiff
input = hs_coupler_2d3d.i
cli_args = 'Outputs/file_base=conduction_only'
exodiff = conduction_only.e
detail = 'using conduction only.'
[]
[convection_only]
type = Exodiff
input = hs_coupler_2d3d.i
cli_args = "
Components/hs_coupler/gap_thermal_conductivity=0
Components/hs_coupler/gap_htc=100
Outputs/file_base=convection_only"
exodiff = convection_only.e
detail = 'using convection only.'
[]
[]

[error_reporting]
Expand Down Expand Up @@ -70,5 +96,19 @@
expect_err = 'Gap thickness must be > 0.'
detail = 'If the gap thickness is less than or equal to zero.'
[]
[radiation_missing_emissivities]
type = RunException
input = hs_coupler_2d3d.i
cli_args = 'Components/hs_coupler/include_radiation=true'
expect_err = "If 'include_radiation' is 'true', then 'emissivity_2d' and 'emissivity_3d' are required."
detail = 'If radiation is specified to be included but the emissivities are not provided.'
[]
[no_radiation_but_provided_emissivity]
type = RunException
input = hs_coupler_2d3d.i
cli_args = 'Components/hs_coupler/emissivity_2d=0.4'
expect_err = "If 'include_radiation' is 'false', then neither 'emissivity_2d' nor 'emissivity_3d' can be specified."
detail = 'If radiation is specified to not be included but an emissivity is provided.'
[]
[]
[]

0 comments on commit ed37a79

Please sign in to comment.