Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "WCNSLinearFVFluidHeatTransferPhysics.h"
11 : #include "WCNSFVFlowPhysics.h"
12 : #include "PINSFVEnergyAnisotropicDiffusion.h"
13 : #include "NSFVBase.h"
14 :
15 : registerNavierStokesPhysicsBaseTasks("NavierStokesApp", WCNSLinearFVFluidHeatTransferPhysics);
16 : registerWCNSFVFluidHeatTransferPhysicsBaseTasks("NavierStokesApp",
17 : WCNSLinearFVFluidHeatTransferPhysics);
18 : registerMooseAction("NavierStokesApp", WCNSLinearFVFluidHeatTransferPhysics, "add_aux_variable");
19 : registerMooseAction("NavierStokesApp", WCNSLinearFVFluidHeatTransferPhysics, "add_aux_kernel");
20 :
21 : InputParameters
22 64 : WCNSLinearFVFluidHeatTransferPhysics::validParams()
23 : {
24 64 : InputParameters params = WCNSFVFluidHeatTransferPhysicsBase::validParams();
25 192 : params.addParam<bool>(
26 : "use_nonorthogonal_correction",
27 128 : true,
28 : "Whether to use a non-orthogonal correction. This can potentially slow down convergence "
29 : ", but reduces numerical dispersion on non-orthogonal meshes. Can be safely turned off on "
30 : "orthogonal meshes.");
31 192 : params.set<std::vector<SolverSystemName>>("system_names") = {"energy_system"};
32 :
33 : // We could split between discretization and solver here.
34 128 : params.addParamNamesToGroup("use_nonorthogonal_correction system_names", "Numerical scheme");
35 :
36 : // Not implemented
37 64 : params.suppressParameter<bool>("effective_conductivity");
38 : // Not needed
39 64 : params.suppressParameter<bool>("add_energy_equation");
40 64 : params.suppressParameter<MooseEnum>("preconditioning");
41 :
42 64 : return params;
43 0 : }
44 :
45 64 : WCNSLinearFVFluidHeatTransferPhysics::WCNSLinearFVFluidHeatTransferPhysics(
46 64 : const InputParameters & parameters)
47 64 : : WCNSFVFluidHeatTransferPhysicsBase(parameters)
48 : {
49 64 : if (_porous_medium_treatment)
50 0 : paramError("porous_medium_treatment", "Porous media not supported at this time");
51 64 : checkSecondParamSetOnlyIfFirstOneTrue("solve_for_enthalpy", NS::fluid);
52 64 : }
53 :
54 : void
55 64 : WCNSLinearFVFluidHeatTransferPhysics::addSolverVariables()
56 : {
57 : // For compatibility with Modules/NavierStokesFV syntax
58 64 : if (!_has_energy_equation)
59 0 : return;
60 :
61 64 : const auto variable_name = _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
62 :
63 : // Dont add if the user already defined the variable
64 64 : if (!shouldCreateVariable(variable_name, _blocks, /*error if aux*/ true))
65 0 : reportPotentiallyMissedParameters({"system_names"}, "MooseLinearVariableFVReal");
66 64 : else if (_define_variables)
67 : {
68 : const auto var_type = "MooseLinearVariableFVReal";
69 64 : auto params = getFactory().getValidParams(var_type);
70 64 : assignBlocks(params, _blocks);
71 128 : params.set<SolverSystemName>("solver_sys") = getSolverSystem(variable_name);
72 64 : getProblem().addVariable(var_type, variable_name, params);
73 64 : }
74 : else
75 0 : paramError(_solve_for_enthalpy ? "solve_for_enthalpy" : "fluid_temperature_variable",
76 0 : "Variable (" + variable_name +
77 : ") supplied to the WCNSLinearFVFluidHeatTransferPhysics does not exist!");
78 : }
79 :
80 : void
81 8 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyTimeKernels()
82 : {
83 8 : std::string kernel_type = "LinearFVTimeDerivative";
84 8 : std::string kernel_name = prefix() + "ins_energy_time";
85 :
86 8 : InputParameters params = getFactory().getValidParams(kernel_type);
87 16 : params.set<LinearVariableName>("variable") =
88 8 : _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
89 8 : assignBlocks(params, _blocks);
90 8 : if (!_solve_for_enthalpy)
91 16 : params.set<MooseFunctorName>("factor") = "rho_cp";
92 : else
93 0 : params.set<MooseFunctorName>("factor") = _density_name;
94 :
95 8 : getProblem().addLinearFVKernel(kernel_type, kernel_name, params);
96 16 : }
97 :
98 : void
99 64 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyAdvectionKernels()
100 : {
101 64 : std::string kernel_type = "LinearFVEnergyAdvection";
102 64 : std::string kernel_name = prefix() + "ins_energy_advection";
103 :
104 64 : InputParameters params = getFactory().getValidParams(kernel_type);
105 64 : assignBlocks(params, _blocks);
106 128 : if (!getParam<bool>("solve_for_enthalpy"))
107 : {
108 100 : params.set<LinearVariableName>("variable") = _fluid_temperature_name;
109 100 : params.set<MooseEnum>("advected_quantity") = "temperature";
110 50 : if (!MooseUtils::isFloat(_specific_heat_name))
111 0 : paramError("specific_heat", "Must be a Real number. Functors not supported at this time");
112 50 : params.set<Real>("cp") = std::atof(_specific_heat_name.c_str());
113 : }
114 : else
115 28 : params.set<LinearVariableName>("variable") = _fluid_enthalpy_name;
116 64 : params.set<UserObjectName>("rhie_chow_user_object") = _flow_equations_physics->rhieChowUOName();
117 128 : params.set<MooseEnum>("advected_interp_method") =
118 192 : getParam<MooseEnum>("energy_advection_interpolation");
119 :
120 64 : getProblem().addLinearFVKernel(kernel_type, kernel_name, params);
121 128 : }
122 :
123 : void
124 64 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyHeatConductionKernels()
125 : {
126 : const auto num_blocks = _thermal_conductivity_blocks.size();
127 : const auto num_used_blocks = num_blocks ? num_blocks : 1;
128 :
129 128 : for (const auto block_i : make_range(num_used_blocks))
130 : {
131 64 : std::string block_name = "";
132 64 : if (num_blocks)
133 0 : block_name = Moose::stringify(_thermal_conductivity_blocks[block_i]);
134 : else
135 : block_name = "all";
136 :
137 64 : const std::string kernel_type = "LinearFVDiffusion";
138 64 : InputParameters params = getFactory().getValidParams(kernel_type);
139 64 : if (!_solve_for_enthalpy)
140 : {
141 100 : params.set<LinearVariableName>("variable") = _fluid_temperature_name;
142 100 : params.set<MooseFunctorName>("diffusion_coeff") =
143 144 : _thermal_conductivity_name[block_i] + (_has_turbulence_model ? "_plus_kt" : "");
144 : }
145 : else
146 : {
147 28 : params.set<LinearVariableName>("variable") = _fluid_enthalpy_name;
148 : const auto th_cond_name =
149 22 : _thermal_conductivity_name[block_i] + (_has_turbulence_model ? "_plus_kt" : "");
150 56 : params.set<MooseFunctorName>("diffusion_coeff") = th_cond_name + "_by_cp";
151 : }
152 : std::vector<SubdomainName> block_names =
153 64 : num_blocks ? _thermal_conductivity_blocks[block_i] : _blocks;
154 64 : assignBlocks(params, block_names);
155 : // NOTE: vector conductivities not supported at this time
156 64 : bool has_vector = processThermalConductivity();
157 64 : if (has_vector)
158 0 : paramError("thermal_conductivity",
159 : "Vector thermal conductivities not currently supported with the linear finite "
160 : "volume discretization");
161 :
162 64 : params.set<bool>("use_nonorthogonal_correction") =
163 192 : getParam<bool>("use_nonorthogonal_correction");
164 :
165 128 : getProblem().addLinearFVKernel(
166 64 : kernel_type, prefix() + "ins_energy_diffusion_" + block_name, params);
167 64 : }
168 64 : }
169 :
170 : void
171 12 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyAmbientConvection()
172 : {
173 12 : unsigned int num_convection_blocks = _ambient_convection_blocks.size();
174 : unsigned int num_used_blocks = num_convection_blocks ? num_convection_blocks : 1;
175 :
176 12 : const std::string kernel_type = "LinearFVVolumetricHeatTransfer";
177 12 : InputParameters params = getFactory().getValidParams(kernel_type);
178 24 : params.set<LinearVariableName>("variable") =
179 12 : _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
180 12 : params.set<VariableName>(NS::T_fluid) = _fluid_temperature_name;
181 12 : params.set<bool>("is_solid") = false;
182 :
183 24 : for (unsigned int block_i = 0; block_i < num_used_blocks; ++block_i)
184 : {
185 12 : std::string block_name = "";
186 12 : if (num_convection_blocks)
187 : {
188 12 : params.set<std::vector<SubdomainName>>("block") = _ambient_convection_blocks[block_i];
189 24 : block_name = Moose::stringify(_ambient_convection_blocks[block_i]);
190 : }
191 : else
192 : {
193 0 : assignBlocks(params, _blocks);
194 0 : block_name = std::to_string(block_i);
195 : }
196 :
197 24 : params.set<MooseFunctorName>("h_solid_fluid") = _ambient_convection_alpha[block_i];
198 24 : params.set<VariableName>(NS::T_solid) = _ambient_temperature[block_i];
199 :
200 24 : getProblem().addLinearFVKernel(
201 24 : kernel_type, prefix() + "ambient_convection_" + block_name, params);
202 : }
203 24 : }
204 :
205 : void
206 24 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyExternalHeatSource()
207 : {
208 24 : const std::string kernel_type = "LinearFVSource";
209 24 : InputParameters params = getFactory().getValidParams(kernel_type);
210 48 : params.set<LinearVariableName>("variable") =
211 24 : _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
212 24 : assignBlocks(params, _blocks);
213 48 : params.set<MooseFunctorName>("source_density") =
214 24 : getParam<MooseFunctorName>("external_heat_source");
215 48 : params.set<MooseFunctorName>("scaling_factor") =
216 72 : std::to_string(getParam<Real>("external_heat_source_coeff"));
217 :
218 48 : getProblem().addLinearFVKernel(kernel_type, prefix() + "external_heat_source", params);
219 48 : }
220 :
221 : void
222 64 : WCNSLinearFVFluidHeatTransferPhysics::addAuxiliaryVariables()
223 : {
224 64 : if (_solve_for_enthalpy)
225 : {
226 : // Dont add if the user already defined the variable
227 14 : if (variableExists(_fluid_temperature_name,
228 : /*error_if_aux=*/false))
229 0 : checkBlockRestrictionIdentical(_fluid_temperature_name,
230 0 : getProblem().getVariable(0, _fluid_temperature_name).blocks());
231 14 : else if (_define_variables)
232 : {
233 : const auto var_type = "MooseLinearVariableFVReal";
234 14 : auto params = getFactory().getValidParams(var_type);
235 14 : assignBlocks(params, _blocks);
236 14 : getProblem().addAuxVariable(var_type, _fluid_temperature_name, params);
237 14 : }
238 : else
239 0 : paramError("fluid_temperature_variable",
240 0 : "Variable (" + _fluid_temperature_name +
241 : ") supplied to the WCNSLinearFVFluidHeatTransferPhysics does not exist!");
242 : }
243 64 : }
244 :
245 : void
246 64 : WCNSLinearFVFluidHeatTransferPhysics::addAuxiliaryKernels()
247 : {
248 64 : if (_solve_for_enthalpy)
249 : {
250 : // Keep temperature updated
251 14 : const std::string kernel_type = "FunctorAux";
252 14 : InputParameters params = getFactory().getValidParams(kernel_type);
253 28 : params.set<AuxVariableName>("variable") = _fluid_temperature_name;
254 14 : assignBlocks(params, _blocks);
255 28 : params.set<MooseFunctorName>("functor") = "T_from_p_h";
256 42 : params.set<ExecFlagEnum>("execute_on") = {EXEC_NONLINEAR};
257 28 : getProblem().addAuxKernel(kernel_type, prefix() + "update_temperature", params);
258 14 : }
259 78 : }
260 :
261 : void
262 64 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyInletBC()
263 : {
264 64 : const auto & inlet_boundaries = _flow_equations_physics->getInletBoundaries();
265 : // These are parameter errors for now. If Components add boundaries to Physics, the error
266 : // may not be due to parameters anymore.
267 64 : if (inlet_boundaries.size() != _energy_inlet_types.size())
268 0 : paramError("energy_inlet_types",
269 0 : "Energy inlet types (size " + std::to_string(_energy_inlet_types.size()) +
270 0 : ") should be the same size as inlet_boundaries (size " +
271 0 : std::to_string(inlet_boundaries.size()) + ")");
272 64 : if (inlet_boundaries.size() != _energy_inlet_functors.size())
273 0 : paramError("energy_inlet_functors",
274 0 : "Energy inlet functors (size " + std::to_string(_energy_inlet_functors.size()) +
275 0 : ") should be the same size as inlet_boundaries (size " +
276 0 : std::to_string(inlet_boundaries.size()) + ")");
277 :
278 128 : for (const auto bc_ind : index_range(_energy_inlet_types))
279 : {
280 64 : if (_energy_inlet_types[bc_ind] == "fixed-temperature")
281 : {
282 64 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorDirichletBC";
283 64 : InputParameters params = getFactory().getValidParams(bc_type);
284 128 : params.set<LinearVariableName>("variable") = _fluid_temperature_name;
285 128 : params.set<MooseFunctorName>("functor") = _energy_inlet_functors[bc_ind];
286 192 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_boundaries[bc_ind]};
287 :
288 128 : getProblem().addLinearFVBC(
289 64 : bc_type, _fluid_temperature_name + "_" + inlet_boundaries[bc_ind], params);
290 :
291 : // Boundary condition on temperature must be forwarded to enthalpy
292 64 : if (_solve_for_enthalpy)
293 : {
294 28 : params.set<LinearVariableName>("variable") = _fluid_enthalpy_name;
295 28 : params.set<MooseFunctorName>("functor") = "h_from_p_T";
296 28 : getProblem().addLinearFVBC(
297 28 : bc_type, _fluid_enthalpy_name + "_" + inlet_boundaries[bc_ind], params);
298 : }
299 64 : }
300 0 : else if (_energy_inlet_types[bc_ind] == "heatflux")
301 0 : paramError("energy_inlet_types", "Heat flux inlet boundary conditions not yet supported");
302 0 : else if (_energy_inlet_types[bc_ind] == "flux-mass" ||
303 0 : _energy_inlet_types[bc_ind] == "flux-velocity")
304 0 : paramError("energy_inlet_types", "Flux inlet boundary conditions not yet supported");
305 : }
306 64 : }
307 :
308 : void
309 64 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyWallBC()
310 : {
311 128 : const auto & wall_boundaries = isParamSetByUser("energy_wall_boundaries")
312 134 : ? getParam<std::vector<BoundaryName>>("energy_wall_boundaries")
313 58 : : _flow_equations_physics->getWallBoundaries();
314 64 : if (wall_boundaries.size() != _energy_wall_types.size())
315 0 : paramError("energy_wall_types",
316 0 : "Energy wall types (size " + std::to_string(_energy_wall_types.size()) +
317 0 : ") should be the same size as wall_boundaries (size " +
318 0 : std::to_string(wall_boundaries.size()) + ")");
319 64 : if (wall_boundaries.size() != _energy_wall_functors.size())
320 0 : paramError("energy_wall_functors",
321 0 : "Energy wall functors (size " + std::to_string(_energy_wall_functors.size()) +
322 0 : ") should be the same size as wall_boundaries (size " +
323 0 : std::to_string(wall_boundaries.size()) + ")");
324 :
325 162 : for (unsigned int bc_ind = 0; bc_ind < _energy_wall_types.size(); ++bc_ind)
326 : {
327 98 : if (_energy_wall_types[bc_ind] == "fixed-temperature")
328 : {
329 56 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorDirichletBC";
330 56 : InputParameters params = getFactory().getValidParams(bc_type);
331 112 : params.set<LinearVariableName>("variable") = _fluid_temperature_name;
332 112 : params.set<MooseFunctorName>("functor") = _energy_wall_functors[bc_ind];
333 168 : params.set<std::vector<BoundaryName>>("boundary") = {wall_boundaries[bc_ind]};
334 :
335 112 : getProblem().addLinearFVBC(
336 56 : bc_type, _fluid_temperature_name + "_" + wall_boundaries[bc_ind], params);
337 :
338 : // Boundary condition on temperature must be forwarded to enthalpy
339 56 : if (_solve_for_enthalpy)
340 : {
341 32 : params.set<LinearVariableName>("variable") = _fluid_enthalpy_name;
342 32 : params.set<MooseFunctorName>("functor") = "h_from_p_T";
343 32 : getProblem().addLinearFVBC(
344 32 : bc_type, _fluid_enthalpy_name + "_" + wall_boundaries[bc_ind], params);
345 : }
346 56 : }
347 42 : else if (_energy_wall_types[bc_ind] == "heatflux")
348 : {
349 36 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorNeumannBC";
350 36 : InputParameters params = getFactory().getValidParams(bc_type);
351 36 : const auto var_name = _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
352 72 : params.set<LinearVariableName>("variable") = var_name;
353 72 : params.set<MooseFunctorName>("functor") = _energy_wall_functors[bc_ind];
354 108 : params.set<std::vector<BoundaryName>>("boundary") = {wall_boundaries[bc_ind]};
355 :
356 72 : getProblem().addLinearFVBC(
357 72 : bc_type, var_name + "_heatflux_" + wall_boundaries[bc_ind], params);
358 36 : }
359 6 : else if (_energy_wall_types[bc_ind] == "convection")
360 : {
361 6 : const std::string bc_type = "LinearFVConvectiveHeatTransferBC";
362 6 : InputParameters params = getFactory().getValidParams(bc_type);
363 12 : params.set<LinearVariableName>("variable") =
364 6 : _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
365 6 : params.set<MooseFunctorName>(NS::T_fluid) = _fluid_temperature_name;
366 : const auto Tinf_htc_functors =
367 12 : MooseUtils::split(_energy_wall_functors[bc_ind], /*delimiter=*/":", /*max_count=*/1);
368 6 : if (Tinf_htc_functors.size() != 2)
369 0 : paramError("energy_wall_functors",
370 : "'convection' wall types require two functors specified as "
371 : "<Tinf_functor>:<htc_functor>.");
372 12 : params.set<MooseFunctorName>(NS::T_solid) = Tinf_htc_functors[0];
373 12 : params.set<MooseFunctorName>("h") = Tinf_htc_functors[1];
374 18 : params.set<std::vector<BoundaryName>>("boundary") = {wall_boundaries[bc_ind]};
375 :
376 12 : getProblem().addLinearFVBC(
377 : bc_type,
378 6 : (_solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name) + "_" +
379 : wall_boundaries[bc_ind],
380 : params);
381 6 : }
382 : else
383 0 : paramError(
384 0 : "energy_wall_types", _energy_wall_types[bc_ind], " wall type is currently unsupported.");
385 : }
386 64 : }
387 :
388 : void
389 64 : WCNSLinearFVFluidHeatTransferPhysics::addEnergyOutletBC()
390 : {
391 64 : const auto & outlet_boundaries = _flow_equations_physics->getOutletBoundaries();
392 64 : if (outlet_boundaries.empty())
393 : return;
394 :
395 128 : for (const auto & outlet_bdy : outlet_boundaries)
396 : {
397 64 : const std::string bc_type = "LinearFVAdvectionDiffusionOutflowBC";
398 64 : const auto variable_name = _solve_for_enthalpy ? _fluid_enthalpy_name : _fluid_temperature_name;
399 64 : InputParameters params = getFactory().getValidParams(bc_type);
400 192 : params.set<std::vector<BoundaryName>>("boundary") = {outlet_bdy};
401 128 : params.set<bool>("use_two_term_expansion") = getParam<bool>("energy_two_term_bc_expansion");
402 :
403 128 : params.set<LinearVariableName>("variable") = variable_name;
404 64 : getProblem().addLinearFVBC(bc_type, variable_name + "_" + outlet_bdy, params);
405 64 : }
406 : }
407 :
408 : void
409 64 : WCNSLinearFVFluidHeatTransferPhysics::addMaterials()
410 : {
411 : // For compatibility with Modules/NavierStokesFV syntax
412 64 : if (!_has_energy_equation)
413 0 : return;
414 :
415 : // Note that this material choice would not work for Newton-INSFV + solve_for_enthalpy
416 : const auto object_type = "LinearFVEnthalpyFunctorMaterial";
417 :
418 64 : InputParameters params = getFactory().getValidParams(object_type);
419 64 : assignBlocks(params, _blocks);
420 64 : params.set<MooseFunctorName>(NS::pressure) = _flow_equations_physics->getPressureName();
421 64 : params.set<MooseFunctorName>(NS::T_fluid) = _fluid_temperature_name;
422 128 : params.set<MooseFunctorName>(NS::specific_enthalpy) = _fluid_enthalpy_name;
423 64 : if (isParamValid(NS::fluid))
424 8 : params.set<UserObjectName>(NS::fluid) = getParam<UserObjectName>(NS::fluid);
425 :
426 64 : if (_solve_for_enthalpy)
427 : {
428 14 : if (!isParamValid(NS::fluid))
429 : {
430 18 : if (!getProblem().hasFunctor("h_from_p_T_functor", 0) ||
431 18 : !getProblem().hasFunctor("T_from_p_h_functor", 0))
432 0 : paramError(NS::fluid,
433 : "Either 'fp' must be specified or the 'h_from_p_T_functor' and "
434 : "'T_from_p_h_functor' must be defined outside the Physics");
435 : // Note: we could define those in the Physics if cp is constant
436 12 : params.set<MooseFunctorName>("h_from_p_T_functor") = "h_from_p_T_functor";
437 12 : params.set<MooseFunctorName>("T_from_p_h_functor") = "T_from_p_h_functor";
438 : }
439 : }
440 : // If we are solving for enthalpy, we need this to compute temperature from p & h
441 : // Else we don't really need it
442 64 : if (_solve_for_enthalpy)
443 56 : getProblem().addMaterial(object_type, prefix() + "enthalpy_material", params);
444 :
445 64 : if (_solve_for_enthalpy || _has_turbulence_model)
446 20 : WCNSFVFluidHeatTransferPhysicsBase::defineEffectiveThermalDiffusionCoeffFunctors(
447 : /*use ad*/ false);
448 64 : }
|