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 "WCNSFVFluidHeatTransferPhysicsBase.h"
11 : #include "WCNSFVCoupledAdvectionPhysicsHelper.h"
12 : #include "WCNSFVFlowPhysics.h"
13 : #include "PINSFVEnergyAnisotropicDiffusion.h"
14 : #include "NSFVBase.h"
15 :
16 : InputParameters
17 773 : WCNSFVFluidHeatTransferPhysicsBase::validParams()
18 : {
19 773 : InputParameters params = NavierStokesPhysicsBase::validParams();
20 773 : params += WCNSFVCoupledAdvectionPhysicsHelper::validParams();
21 773 : params.addClassDescription("Define the Navier Stokes weakly-compressible energy equation");
22 :
23 773 : params += NSFVBase::commonFluidEnergyEquationParams();
24 773 : params.transferParam<bool>(PINSFVEnergyAnisotropicDiffusion::validParams(),
25 : "effective_conductivity");
26 1546 : params.addParamNamesToGroup("effective_conductivity", "Material properties");
27 :
28 : // TODO Remove the parameter once NavierStokesFV syntax has been removed
29 1546 : params.addParam<bool>("add_energy_equation",
30 : "Whether to add the energy equation. This parameter is not necessary if "
31 : "using the Physics syntax");
32 1546 : params.addParam<bool>("solve_for_enthalpy",
33 1546 : false,
34 : "Whether to solve for the enthalpy or the temperature of the fluid");
35 1546 : params.addParam<NonlinearVariableName>(
36 : "fluid_temperature_variable", NS::T_fluid, "Name of the fluid temperature variable");
37 :
38 773 : params.addParam<UserObjectName>(NS::fluid, "Fluid properties userobject");
39 773 : params.addParamNamesToGroup(NS::fluid, "Material properties");
40 :
41 : // Initial conditions
42 1546 : params.addParam<FunctionName>(
43 : "initial_enthalpy",
44 : "Initial value of the enthalpy variable, only to be used when solving for enthalpy");
45 :
46 : // Spatial finite volume discretization scheme
47 773 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "energy_advection_interpolation");
48 773 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "energy_face_interpolation");
49 773 : params.transferParam<bool>(NSFVBase::validParams(), "energy_two_term_bc_expansion");
50 :
51 1546 : params.addParamNamesToGroup("specific_heat thermal_conductivity thermal_conductivity_blocks "
52 : "use_external_enthalpy_material",
53 : "Material properties");
54 1546 : params.addParamNamesToGroup("energy_advection_interpolation energy_face_interpolation "
55 : "energy_two_term_bc_expansion",
56 : "Numerical scheme");
57 1546 : params.addParamNamesToGroup("energy_inlet_types energy_inlet_functors",
58 : "Inlet boundary conditions");
59 1546 : params.addParamNamesToGroup("energy_wall_boundaries energy_wall_types energy_wall_functors",
60 : "Wall boundary conditions");
61 :
62 773 : return params;
63 0 : }
64 :
65 773 : WCNSFVFluidHeatTransferPhysicsBase::WCNSFVFluidHeatTransferPhysicsBase(
66 773 : const InputParameters & parameters)
67 : : NavierStokesPhysicsBase(parameters),
68 : WCNSFVCoupledAdvectionPhysicsHelper(this),
69 773 : _has_energy_equation(
70 1546 : isParamValid("add_energy_equation")
71 2319 : ? getParam<bool>("add_energy_equation")
72 1791 : : (usingNavierStokesFVSyntax() ? isParamSetByUser("energy_inlet_functors") : true)),
73 1546 : _solve_for_enthalpy(getParam<bool>("solve_for_enthalpy")),
74 773 : _fluid_enthalpy_name(getSpecificEnthalpyName()),
75 1546 : _fluid_temperature_name(getParam<NonlinearVariableName>("fluid_temperature_variable")),
76 773 : _specific_heat_name(getParam<MooseFunctorName>("specific_heat")),
77 2319 : _thermal_conductivity_blocks(
78 773 : parameters.isParamValid("thermal_conductivity_blocks")
79 773 : ? getParam<std::vector<std::vector<SubdomainName>>>("thermal_conductivity_blocks")
80 : : std::vector<std::vector<SubdomainName>>()),
81 1546 : _thermal_conductivity_name(getParam<std::vector<MooseFunctorName>>("thermal_conductivity")),
82 1546 : _ambient_convection_blocks(
83 : getParam<std::vector<std::vector<SubdomainName>>>("ambient_convection_blocks")),
84 1546 : _ambient_convection_alpha(getParam<std::vector<MooseFunctorName>>("ambient_convection_alpha")),
85 1546 : _ambient_temperature(getParam<std::vector<MooseFunctorName>>("ambient_temperature")),
86 1546 : _energy_inlet_types(getParam<MultiMooseEnum>("energy_inlet_types")),
87 1546 : _energy_inlet_functors(getParam<std::vector<MooseFunctorName>>("energy_inlet_functors")),
88 1546 : _energy_wall_types(getParam<MultiMooseEnum>("energy_wall_types")),
89 2319 : _energy_wall_functors(getParam<std::vector<MooseFunctorName>>("energy_wall_functors"))
90 : {
91 : // For compatibility with Modules/NavierStokesFV syntax
92 773 : if (!_has_energy_equation)
93 : return;
94 :
95 488 : if (_solve_for_enthalpy)
96 41 : saveSolverVariableName(_fluid_enthalpy_name);
97 : else
98 447 : saveSolverVariableName(_fluid_temperature_name);
99 :
100 : // set block restrictions if not set by user
101 : // This should probably be done for all the coupled physics, tbd
102 976 : if (!isParamSetByUser("block"))
103 478 : _blocks = _flow_equations_physics->blocks();
104 :
105 : // Parameter checks
106 976 : checkSecondParamSetOnlyIfFirstOneTrue("solve_for_enthalpy", "initial_enthalpy");
107 976 : checkVectorParamsSameLengthIfSet<MooseFunctorName, MooseFunctorName>("ambient_convection_alpha",
108 : "ambient_temperature");
109 976 : checkSecondParamSetOnlyIfFirstOneSet("external_heat_source", "external_heat_source_coeff");
110 :
111 : // Check boundary parameters if provided.
112 : // The boundaries are checked again when the boundary conditions are added as we want
113 : // to be able to more boundary conditions to a Physics dynamically
114 976 : if (isParamValid("energy_inlet_types"))
115 942 : checkVectorParamAndMultiMooseEnumLength<MooseFunctorName>("energy_inlet_functors",
116 : "energy_inlet_types");
117 976 : if (isParamSetByUser("energy_wall_boundaries"))
118 48 : checkVectorParamsSameLengthIfSet<BoundaryName, MooseFunctorName>(
119 : "energy_wall_boundaries", "energy_wall_functors", false);
120 976 : if (isParamValid("energy_wall_types"))
121 916 : checkVectorParamAndMultiMooseEnumLength<MooseFunctorName>("energy_wall_functors",
122 : "energy_wall_types");
123 :
124 486 : addRequiredPhysicsTask("get_turbulence_physics");
125 486 : addRequiredPhysicsTask("add_variables_physics");
126 486 : addRequiredPhysicsTask("add_ics_physics");
127 486 : addRequiredPhysicsTask("add_fv_kernel");
128 486 : addRequiredPhysicsTask("add_fv_bc");
129 972 : addRequiredPhysicsTask("add_materials_physics");
130 0 : }
131 :
132 : void
133 731 : WCNSFVFluidHeatTransferPhysicsBase::addFVKernels()
134 : {
135 : // For compatibility with Modules/NavierStokesFV syntax
136 731 : if (!_has_energy_equation)
137 : return;
138 :
139 450 : if (shouldCreateTimeDerivative(_solve_for_enthalpy ? _fluid_enthalpy_name
140 : : _fluid_temperature_name,
141 450 : _blocks,
142 : /*error if already defined*/ false))
143 116 : addEnergyTimeKernels();
144 :
145 450 : addEnergyAdvectionKernels();
146 450 : addEnergyHeatConductionKernels();
147 888 : if (getParam<std::vector<MooseFunctorName>>("ambient_temperature").size())
148 131 : addEnergyAmbientConvection();
149 888 : if (isParamValid("external_heat_source"))
150 128 : addEnergyExternalHeatSource();
151 : }
152 :
153 : void
154 721 : WCNSFVFluidHeatTransferPhysicsBase::addFVBCs()
155 : {
156 : // For compatibility with Modules/NavierStokesFV syntax
157 721 : if (!_has_energy_equation)
158 : return;
159 :
160 440 : addEnergyInletBC();
161 438 : addEnergyWallBC();
162 436 : addEnergyOutletBC();
163 436 : addEnergySeparatorBC();
164 : }
165 :
166 : void
167 7518 : WCNSFVFluidHeatTransferPhysicsBase::actOnAdditionalTasks()
168 : {
169 : // Turbulence physics would not be initialized before this task
170 7518 : if (_current_task == "get_turbulence_physics")
171 : {
172 745 : _turbulence_physics = getCoupledTurbulencePhysics();
173 1983 : _has_turbulence_model = _turbulence_physics ? _turbulence_physics->hasTurbulenceModel() : false;
174 : }
175 7518 : }
176 :
177 : bool
178 450 : WCNSFVFluidHeatTransferPhysicsBase::processThermalConductivity()
179 : {
180 898 : checkBlockwiseConsistency<MooseFunctorName>("thermal_conductivity_blocks",
181 : {"thermal_conductivity"});
182 : bool have_scalar = false;
183 : bool have_vector = false;
184 :
185 907 : for (unsigned int i = 0; i < _thermal_conductivity_name.size(); ++i)
186 : {
187 : // First, check if the name is just a number (only in case of isotropic conduction)
188 459 : if (MooseUtils::parsesToReal(_thermal_conductivity_name[i]))
189 : have_scalar = true;
190 : // Now we determine what kind of functor we are dealing with
191 : else
192 : {
193 246 : if (getProblem().hasFunctorWithType<ADReal>(_thermal_conductivity_name[i],
194 268 : /*thread_id=*/0) ||
195 22 : getProblem().hasFunctorWithType<Real>(_thermal_conductivity_name[i],
196 : /*thread_id=*/0))
197 : have_scalar = true;
198 : else
199 : {
200 22 : if (getProblem().hasFunctorWithType<ADRealVectorValue>(_thermal_conductivity_name[i],
201 : /*thread_id=*/0))
202 : have_vector = true;
203 0 : else if (getProblem().hasFunctor(_thermal_conductivity_name[i],
204 : /*thread_id=*/0))
205 0 : paramError("thermal_conductivity",
206 : "We only allow functor of type Real/ADReal or ADRealVectorValue for thermal "
207 0 : "conductivity! Functor '" +
208 : _thermal_conductivity_name[i] + "' is not of the requested type.");
209 : else
210 : // If another Physics is creating this functor, we could be running into an order of
211 : // creation problem
212 0 : paramWarning("thermal_conductivity",
213 0 : "Functor '" + _thermal_conductivity_name[i] +
214 : "' was not found in the Problem. Did you mispell it?");
215 : }
216 : }
217 : }
218 :
219 448 : if (have_vector && !_porous_medium_treatment)
220 2 : paramError("thermal_conductivity", "Cannot use anisotropic diffusion with non-porous flows!");
221 :
222 446 : if (have_vector && (have_vector == have_scalar))
223 2 : paramError("thermal_conductivity",
224 : "The entries on thermal conductivity shall either be scalars of vectors, mixing "
225 : "them is not supported!");
226 444 : return have_vector;
227 : }
228 :
229 : void
230 733 : WCNSFVFluidHeatTransferPhysicsBase::addInitialConditions()
231 : {
232 : // For compatibility with Modules/NavierStokesFV syntax
233 733 : if (!_has_energy_equation)
234 281 : return;
235 456 : if (!_define_variables && isParamSetByUser("initial_temperature"))
236 2 : paramError(
237 : "initial_temperature",
238 : "T_fluid is defined externally of WCNSFVFluidHeatTransferPhysicsBase, so should the inital "
239 : "condition");
240 : // do not set initial conditions if we are not defining variables
241 450 : if (!_define_variables)
242 : {
243 0 : reportPotentiallyMissedParameters({"initial_temperature", "initial_enthalpy"}, "FunctionIC");
244 0 : return;
245 : }
246 :
247 450 : InputParameters params = getFactory().getValidParams("FVFunctionIC");
248 450 : assignBlocks(params, _blocks);
249 :
250 : // initial_temperature has a default so we should almost always set it (see shouldCreateIC logic)
251 : {
252 : bool temperature_ic_used = false;
253 450 : if (variableExists(_fluid_temperature_name, false) &&
254 846 : shouldCreateIC(_fluid_temperature_name,
255 : _blocks,
256 873 : /*whether IC is a default*/ !isParamSetByUser("initial_temperature"),
257 1296 : /*error if already an IC*/ isParamSetByUser("initial_temperature")))
258 : {
259 406 : params.set<VariableName>("variable") = _fluid_temperature_name;
260 1218 : params.set<FunctionName>("function") = getParam<FunctionName>("initial_temperature");
261 :
262 812 : getProblem().addFVInitialCondition("FVFunctionIC", _fluid_temperature_name + "_ic", params);
263 : temperature_ic_used = true;
264 : }
265 : // Needed to solve for enthalpy: an initial condition on enthalpy based on the initial
266 : // temperature
267 935 : if (isParamValid(NS::fluid) && _solve_for_enthalpy && !isParamValid("initial_enthalpy") &&
268 36 : shouldCreateIC(_fluid_enthalpy_name,
269 : _blocks,
270 468 : /*whether IC is a default*/ !isParamSetByUser("initial_temperature"),
271 486 : /*error if already an IC*/ isParamSetByUser("initial_temperature")))
272 : {
273 : // from the FluidProperties module
274 : InputParameters params =
275 18 : getFactory().getValidParams("SpecificEnthalpyFromPressureTemperatureIC");
276 18 : assignBlocks(params, _blocks);
277 36 : params.set<VariableName>("variable") = _fluid_enthalpy_name;
278 18 : params.set<UserObjectName>(NS::fluid) = getParam<UserObjectName>(NS::fluid);
279 54 : params.set<std::vector<VariableName>>("p") = {_flow_equations_physics->getPressureName()};
280 : Real temp;
281 54 : if (MooseUtils::parsesToReal(getParam<FunctionName>("initial_temperature"), &temp))
282 : {
283 18 : params.defaultCoupledValue("T", temp, 0);
284 18 : params.set<std::vector<VariableName>>("T") = {};
285 : }
286 : else
287 0 : paramError("initial_temperature", "Only Real values supported when solving for enthalpy");
288 54 : getProblem().addInitialCondition(
289 18 : "SpecificEnthalpyFromPressureTemperatureIC", _fluid_enthalpy_name + "_ic", params);
290 : temperature_ic_used = true;
291 18 : }
292 :
293 908 : if (!temperature_ic_used && isParamSetByUser("initial_temperature"))
294 0 : reportPotentiallyMissedParameters({"initial_temperature"}, "FunctionIC");
295 : }
296 1367 : if (isParamValid("initial_enthalpy") && _solve_for_enthalpy &&
297 17 : shouldCreateIC(_fluid_enthalpy_name,
298 : _blocks,
299 : /*whether IC is a default*/ false,
300 : /*error if already an IC*/ false))
301 : {
302 17 : params.set<VariableName>("variable") = _fluid_enthalpy_name;
303 51 : params.set<FunctionName>("function") = getParam<FunctionName>("initial_enthalpy");
304 :
305 34 : getProblem().addFVInitialCondition("FVFunctionIC", _fluid_enthalpy_name + "_ic", params);
306 : }
307 866 : else if (isParamValid("initial_enthalpy"))
308 0 : reportPotentiallyMissedParameters({"initial_enthalpy"}, "FunctionIC");
309 468 : }
310 :
311 : void
312 47 : WCNSFVFluidHeatTransferPhysicsBase::defineEffectiveThermalDiffusionCoeffFunctors(const bool use_ad)
313 : {
314 : // Define alpha, the diffusion coefficient when solving for enthalpy, on each block
315 94 : for (unsigned int i = 0; i < _thermal_conductivity_name.size(); ++i)
316 : {
317 47 : const auto object_type = use_ad ? "ADParsedFunctorMaterial" : "ParsedFunctorMaterial";
318 47 : InputParameters params = getFactory().getValidParams(object_type);
319 47 : assignBlocks(params, _blocks);
320 : std::vector<std::string> f_names;
321 47 : if (!MooseUtils::parsesToReal(_thermal_conductivity_name[i]))
322 35 : f_names.push_back(_thermal_conductivity_name[i]);
323 47 : if (_solve_for_enthalpy && !MooseUtils::parsesToReal(getSpecificHeatName()))
324 35 : f_names.push_back(getSpecificHeatName());
325 : const auto th_cond_name =
326 82 : _thermal_conductivity_name[i] + (_has_turbulence_model ? "_plus_kt" : "");
327 47 : if (!_has_turbulence_model)
328 70 : params.set<std::string>("expression") =
329 35 : _thermal_conductivity_name[i] +
330 105 : (_solve_for_enthalpy ? ("/" + getSpecificHeatName()) : "");
331 : else
332 : {
333 12 : f_names.push_back("k_t");
334 24 : params.set<std::string>("expression") =
335 36 : "(" + _thermal_conductivity_name[i] + " + k_t) " +
336 36 : (_solve_for_enthalpy ? ("/" + getSpecificHeatName()) : "");
337 : }
338 47 : params.set<std::vector<std::string>>("functor_names") = f_names;
339 100 : params.set<std::string>("property_name") = th_cond_name + (_solve_for_enthalpy ? "_by_cp" : "");
340 141 : getProblem().addMaterial(
341 141 : object_type, prefix() + "rho_alpha_from_" + _thermal_conductivity_name[i], params);
342 47 : }
343 47 : }
344 :
345 : unsigned short
346 2187 : WCNSFVFluidHeatTransferPhysicsBase::getNumberAlgebraicGhostingLayersNeeded() const
347 : {
348 4374 : unsigned short necessary_layers = getParam<unsigned short>("ghost_layers");
349 2187 : necessary_layers =
350 2187 : std::max(necessary_layers, _flow_equations_physics->getNumberAlgebraicGhostingLayersNeeded());
351 6561 : if (getParam<MooseEnum>("energy_face_interpolation") == "skewness-corrected")
352 0 : necessary_layers = std::max(necessary_layers, (unsigned short)3);
353 :
354 2187 : return necessary_layers;
355 : }
|