31 params.addParam<std::vector<BoundaryName>>(
34 "The interfaces where we would like to add conjugate heat transfer handling.");
36 params.addRangeCheckedParam<
unsigned int>(
40 "Number of maximum fixed point iterations (FPI). Currently only applied to"
41 " conjugate heat transfer simulations. The default value of 1 essentially keeps"
42 " the FPI feature turned off. CHT iteration ends after this number of iteration even if the "
43 "tolerance is not met.");
45 params.addRangeCheckedParam<Real>(
46 "cht_heat_flux_tolerance",
48 "cht_heat_flux_tolerance > 0 & cht_heat_flux_tolerance <= 1.0",
49 "The relative tolerance for terminating conjugate heat transfer iteration before the maximum "
50 "number of CHT iterations. Relative tolerance is ignore if the maximum number of CHT "
51 "iterations is reached.");
53 params.addParam<std::vector<Real>>(
54 "cht_fluid_temperature_relaxation",
56 "The relaxation factors for the boundary temperature when being updated on the fluid side.");
57 params.addParam<std::vector<Real>>(
58 "cht_solid_temperature_relaxation",
60 "The relaxation factors for the boundary temperature when being updated on the solid side.");
61 params.addParam<std::vector<Real>>(
62 "cht_fluid_flux_relaxation",
64 "The relaxation factors for the boundary flux when being updated on the fluid side.");
65 params.addParam<std::vector<Real>>(
66 "cht_solid_flux_relaxation",
68 "The relaxation factors for the boundary flux when being updated on the solid side.");
69 params.addParam<UserObjectName>(
70 "surface_radiation_object_name",
71 "Name of the Gray-Lambert surface-radiation user object. On matching CHT interfaces, "
72 "its net outward heat flux density is removed from the heat flux transferred to the "
75 params.addParam<std::vector<MooseFunctorName>>(
77 std::vector<MooseFunctorName>({
"0"}),
78 "The custom area-normalized thermal resistance at each interface, in m^2*K/W. "
79 "Provide one value to use for all CHT interfaces or one value per entry in "
82 params.addParamNamesToGroup(
83 "cht_interfaces max_cht_fpi cht_heat_flux_tolerance cht_fluid_temperature_relaxation "
84 "cht_solid_temperature_relaxation cht_fluid_flux_relaxation "
85 "cht_solid_flux_relaxation surface_radiation_object_name thermal_resistance",
86 "Conjugate Heat Transfer");
96 "_fe_problem_base",
"This might happen if you don't have a mesh")),
97 _mesh(_problem.
mesh()),
98 _cht_boundary_names(getParam<
std::vector<BoundaryName>>(
"cht_interfaces")),
99 _cht_boundary_ids(_mesh.getBoundaryIDs(_cht_boundary_names)),
100 _max_cht_fpi(getParam<unsigned
int>(
"max_cht_fpi")),
101 _cht_heat_flux_tolerance(getParam<Real>(
"cht_heat_flux_tolerance")),
102 _surface_radiation_uo(nullptr)
105 paramError(
"cht_interfaces",
"You must declare at least one interface!");
108 "Surface radiation coupling requires at least one entry in 'cht_interfaces'.");
110 const auto & thermal_resistance_names =
111 getParam<std::vector<MooseFunctorName>>(
"thermal_resistance");
112 if (thermal_resistance_names.size() != 1 &&
115 "Provide either one thermal resistance for all CHT interfaces or one value per "
116 "entry in cht_interfaces.");
121 const auto & thermal_resistance_name = thermal_resistance_names.size() == 1
122 ? thermal_resistance_names[0]
123 : thermal_resistance_names[bd_index];
131 std::vector<SystemBase *> pm_radiation_systems)
139 "You selected to do conjugate heat transfer treatment, but it needs two energy "
140 "systems: a solid and a fluid. One of these systems is missing.");
153 &getUserObject<GrayLambertSurfaceRadiationBase>(
"surface_radiation_object_name");
156 const bool has_cht_surface =
159 [
this](
const auto boundary_id)
160 { return _surface_radiation_boundary_ids.count(boundary_id); });
162 if (!has_cht_surface)
164 "The supplied surface-radiation user object does not contain any of the "
165 "boundaries listed in 'cht_interfaces'.");
169 mooseError(
"We should have only one variable in the solid energy system: ",
171 "! Right now we have: ",
174 mooseError(
"We should have only one variable in the fluid energy system: ",
176 "! Right now we have: ",
178 const std::vector<std::string> solid_fluid({
"solid",
"fluid"});
203 const auto flux_relaxation_param_names =
204 std::vector<std::string>({
"cht_solid_flux_relaxation",
"cht_fluid_flux_relaxation"});
205 const auto temperature_relaxation_param_names = std::vector<std::string>(
206 {
"cht_solid_temperature_relaxation",
"cht_fluid_temperature_relaxation"});
212 for (
const auto region_index : index_range(solid_fluid))
215 const auto & flux_param_value =
216 getParam<std::vector<Real>>(flux_relaxation_param_names[region_index]);
218 paramError(flux_relaxation_param_names[region_index],
219 "The number of relaxation factors is not the same as the number of interfaces!");
225 if (param <= 0 || param > 1.0)
226 paramError(flux_relaxation_param_names[region_index],
227 "The relaxation parameter should be between 0 and 1!");
229 const auto & temperature_param_value =
230 getParam<std::vector<Real>>(temperature_relaxation_param_names[region_index]);
231 if (temperature_param_value.empty() ||
233 paramError(temperature_relaxation_param_names[region_index],
234 "The number of relaxation factors is not the same as the number of interfaces!");
240 if (param <= 0 || param > 1.0)
241 paramError(temperature_relaxation_param_names[region_index],
242 "The relaxation parameter should be between 0 and 1!");
245 std::vector<LinearFVFluxKernel *> flux_kernels;
248 .template condition<AttribSystem>(
"LinearFVFluxKernel")
249 .template condition<AttribVar>(0)
251 .queryInto(flux_kernels);
258 std::vector<LinearFVFluxKernel *> radiation_kernels;
261 .template condition<AttribSystem>(
"LinearFVFluxKernel")
262 .template condition<AttribVar>(0)
264 .queryInto(radiation_kernels);
266 if (radiation_kernels.size() > 1)
268 "We already have a kernel that describes the participating media radiation diffusion "
270 radiation_kernels[0]->
name(),
271 ". Make sure that you have only one conduction kernel.");
272 else if (radiation_kernels.empty())
273 mooseError(
"We did not find a diffusion kernel for the participating media radiation "
274 "diffusion to compute the "
275 "radiative heat flux. Please add a diffusion kernel.");
280 for (
auto kernel : flux_kernels)
285 mooseError(
"We already have a kernel that describes the heat conduction for the ",
286 solid_fluid[region_index],
289 " We found another one with the name: ",
290 (check_diff ? check_diff->name() : check_aniso_diff->name()),
291 " Make sure that you have only one conduction kernel on the ",
292 solid_fluid[region_index],
295 if (check_diff || check_aniso_diff)
306 std::vector<LinearFVBoundaryCondition *> bcs;
310 .template condition<AttribSystem>(
"LinearFVBoundaryCondition")
311 .template condition<AttribVar>(0)
313 .template condition<AttribBoundaries>(boundary_id)
320 std::vector<LinearFVBoundaryCondition *> rad_bcs;
323 .template condition<AttribSystem>(
"LinearFVBoundaryCondition")
324 .template condition<AttribVar>(0)
326 .template condition<AttribBoundaries>(boundary_id)
329 if (!rad_bcs.empty())
332 mooseError(
"No LinearFVBoundaryCondition found for the given boundary or system.");
336 mooseError(
"We found multiple or no boundary conditions for solid energy on boundary ",
340 "). Make sure you define exactly one for conjugate heat transfer applications!");
344 mooseError(
"The selected boundary condition cannot be used with CHT problems! Make sure it "
345 "inherits from LinearFVCHTBCInterface!");
374 if (fi->boundaryIDs().count(bd_id))
375 bd_fi_container.push_back(fi);
379 std::set<SubdomainID> combined_set;
384 std::inserter(combined_set, combined_set.begin()));
388 _problem.
mesh(), combined_set,
"heat_flux_to_solid_" + bd_name);
390 _problem.
mesh(), combined_set,
"heat_flux_to_fluid_" + bd_name);
394 {std::move(solid_bd_flux), std::move(fluid_bd_flux)}));
402 _problem.
mesh(), combined_set,
"interface_temperature_to_solid_" + bd_name);
404 _problem.
mesh(), combined_set,
"interface_temperature_to_fluid_" + bd_name);
408 {std::move(solid_bd_temperature), std::move(fluid_bd_temperature)}));
426 for (
const auto region_index : make_range(2))
427 for (
auto & fi : bd_fi_container)
429 flux_container[region_index][fi->id()] = 0.0;
430 temperature_container[region_index][fi->id()] = 0.0;
446 for (
const auto & fi : bd_fi_container)
449 const auto & solid_elem_info = solid_on_elem ? *fi->elemInfo() : *fi->neighborInfo();
450 const Real solid_face_value =
454 const auto & fluid_elem_info = fluid_on_elem ? *fi->elemInfo() : *fi->neighborInfo();
455 const Real fluid_face_value =
488 integrated_flux = 0.0;
492 Real surface_radiation_flux = 0.0;
497 surface_radiation_flux =
504 for (
const auto & fi : bd_fi_container)
506 other_kernel->setupFaceData(fi);
512 other_kernel->setCurrentFaceArea(1.0);
513 other_bc->setupFaceData(fi, fi->faceType(std::make_pair(0,
_cht_system_numbers[other_side])));
515 const auto boundary_temperature = other_bc->computeBoundaryValue();
518 const auto on_elem = resistance_functor.hasFaceSide(*fi,
true);
519 const auto on_neighbor = resistance_functor.hasFaceSide(*fi,
false);
521 if (!on_elem && !on_neighbor)
522 mooseError(
"The thermal resistance functor '",
523 resistance_functor.functorName(),
524 "' is not defined on either side of CHT interface '",
529 fi, Moose::FV::LimiterType::CentralDifference,
true,
false,
nullptr,
nullptr};
531 if (on_elem != on_neighbor)
532 resistance_face_arg.
face_side = on_elem ? fi->elemPtr() : fi->neighborPtr();
534 const auto thermal_resistance =
537 if (thermal_resistance < 0.0)
538 paramError(
"thermal_resistance",
"Thermal resistance must be non-negative.");
544 auto source_flux = other_kernel->computeBoundaryFlux(*other_bc);
562 const Real coupling_flux = source_flux - surface_radiation_flux;
563 const auto relaxed_flux =
564 flux_relaxation * coupling_flux + (1 - flux_relaxation) * flux_container[fi->id()];
565 flux_container[fi->id()] = relaxed_flux;
569 temperature_container[fi->id()] =
570 temperature_relaxation * (boundary_temperature - thermal_resistance * relaxed_flux) +
571 (1 - temperature_relaxation) * temperature_container[fi->id()];
575 const Real coordinate_area = fi->faceArea() * fi->faceCoord();
576 integrated_flux += source_flux * coordinate_area;
579 surface_radiation_flux * coordinate_area;
607 _console <<
" net outward surface-radiation flux: "
633 const Real f1 = boundary_flux[0];
634 const Real f2 = boundary_flux[1];
635 const Real radiation_flux =
640 if (
_fpi_it != 0 && f1 == 0.0 && f2 == 0.0 && radiation_flux == 0.0)
645 const Real diff = std::abs(f1 + f2 - radiation_flux);
647 std::max({std::fabs(f1), std::fabs(f2), std::fabs(radiation_flux), Real(1e-14)});
648 const Real rel_diff = diff / denom;
void ErrorVector unsigned int
virtual const std::set< SubdomainID > & blockIDs() const
const ConsoleStream _console
virtual MooseMesh & mesh() override
A functor whose evaluation relies on querying a map where the keys are face info ids and the values c...
Real getSurfaceHeatFluxDensity(BoundaryID id) const
std::set< BoundaryID > getSurfaceIDs() const
Base class that allows error checking for CHT applications.
TheWarehouse & theWarehouse()
const std::string & name() const
void paramError(const std::string ¶m, Args... args) const
bool isParamSetByUser(const std::string &name) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
MooseApp & getMooseApp() const
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
const std::vector< const FaceInfo * > & faceInfo() const
virtual bool hasFaceSide(const FaceInfo &fi, const bool fi_elem_side) const override
const Real _cht_heat_flux_tolerance
Tolerance for heat flux at the CHT interfaces.
std::vector< BoundaryName > _cht_boundary_names
The names of the CHT boundaries.
std::vector< Real > _integrated_boundary_surface_radiation_heat_flux
Integrated net outward surface-radiation flux, kept separate for the CHT energy balance.
void sumIntegratedFluxes()
Sum the integrated fluxes over all processors.
SystemBase * _energy_system
The energy system.
std::vector< unsigned int > _cht_pm_radiation_system_numbers
The participating media radiation system numbers.
std::vector< LinearFVFluxKernel * > _cht_conduction_kernels
The conduction kernels from the solid/fluid domains. Can't be const, considering we are updating the ...
void printIntegratedFluxes() const
Print the integrated heat fluxes.
std::vector< unsigned int > _cht_system_numbers
The solid (0) and fluid (1) system numbers.
std::vector< LinearFVFluxKernel * > _cht_pm_radiation_kernels
The conduction radiation kernels from the fluid domains.
std::vector< std::vector< Real > > _cht_flux_relaxation_factor
The relaxation factors for flux fields for the CHT boundaries first index is solid/fluid second is th...
std::vector< std::vector< FaceCenteredMapFunctor< Real, std::unordered_map< dof_id_type, Real > > > > _boundary_heat_flux
Functors describing the heat flux on the conjugate heat transfer interfaces.
SystemBase * _solid_energy_system
The solid energy system.
std::vector< std::vector< const FaceInfo * > > _cht_face_info
The subset of the FaceInfo objects that belong to the given boundaries.
std::vector< SystemBase * > _pm_radiation_systems
The solid energy system.
void resetIntegratedFluxes()
Reset the heat fluxes to 0.
void initializeCHTCouplingFields()
Initialize the coupling fields for the conjugate heat transfer routines.
CHTHandler(const InputParameters ¶meters)
Constructor with initialization parameters.
std::vector< std::vector< Real > > _integrated_boundary_heat_flux
Integrated source-domain flux for each boundary and solid/fluid transfer direction.
std::vector< std::vector< LinearFVBoundaryCondition * > > _cht_boundary_conditions
Vector of boundary conditions that describe the conjugate heat transfer from each side.
std::vector< std::vector< LinearFVBoundaryCondition * > > _cht_pm_radiation_boundary_conditions
Vector of boundary conditions that describe the radiation pm bcs from each side.
void deduceCHTBoundaryCoupling()
Run error checks and make sure everything works.
bool converged() const
Check if CHT iteration converged.
std::set< BoundaryID > _surface_radiation_boundary_ids
Boundaries represented by the surface-to-surface radiation model.
void setupConjugateHeatTransferContainers()
Set up the boundary condition pairs, functor maps, and every other necessary structure for the conjug...
std::vector< std::vector< FaceCenteredMapFunctor< Real, std::unordered_map< dof_id_type, Real > > > > _boundary_temperature
Functors describing the raw wall temperatures on the conjugate heat transfer interfaces.
std::vector< std::vector< Real > > _cht_temperature_relaxation_factor
The relaxation factors for temperature fields for the CHT boundaries first index is solid/fluid secon...
std::vector< BoundaryID > _cht_boundary_ids
The IDs of the CHT boundaries.
const MooseLinearVariableFVReal * _solid_variable
The solid-side temperature variable.
static InputParameters validParams()
const MooseLinearVariableFVReal * _fluid_variable
The fluid-side temperature variable.
FEProblemBase & _problem
Reference to FEProblem.
std::vector< const Moose::Functor< Real > * > _thermal_resistance
Thermal resistance functors, one per CHT interface.
void updateCHTBoundaryCouplingFields(const NS::CHTSide side)
Update the coupling fields for.
unsigned int _fpi_it
CHT fixed point iteration counter.
void linkEnergySystems(SystemBase *solid_energy_system, SystemBase *fluid_energy_system, std::vector< SystemBase * > pm_radiation_systems)
Link energy systems.
const unsigned int _max_cht_fpi
Maximum number of CHT fixed point iterations.
const GrayLambertSurfaceRadiationBase * _surface_radiation_uo
Optional surface-to-surface radiation model supplying net outward wall heat fluxes.
static InputParameters validParams()
THREAD_ID numThreads() const
void addFunctor(const std::string &name, const Moose::FunctorBase< T > &functor, const THREAD_ID tid)
virtual unsigned int nVariables() const
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
unsigned int number() const
const std::vector< VariableName > & getVariableNames() const
virtual const std::string & name() const
static InputParameters validParams()
const Parallel::Communicator & comm() const
std::string stringify(const T &t)
CHTSide
CHT side options, we want to make sure these can be used as integers so we are avoiding the enum clas...
const libMesh::Elem * face_side