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