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 "WCNSFVFlowPhysicsBase.h"
11 : #include "WCNSFVTurbulencePhysics.h"
12 : #include "NSFVBase.h"
13 : #include "MapConversionUtils.h"
14 : #include "NS.h"
15 :
16 : InputParameters
17 1905 : WCNSFVFlowPhysicsBase::validParams()
18 : {
19 1905 : InputParameters params = NavierStokesPhysicsBase::validParams();
20 1905 : params.addClassDescription("Base class for Physics defining the Navier Stokes flow equations");
21 :
22 1905 : params += NSFVBase::commonMomentumEquationParams();
23 3810 : params.addParam<bool>("add_flow_equations",
24 3810 : true,
25 : "Whether to add the flow equations. This parameter is not necessary when "
26 : "using the Physics syntax");
27 :
28 : // We pull in parameters from various flow objects. This helps make sure the parameters are
29 : // spelled the same way and match the evolution of other objects.
30 : // If we remove these objects, or change their parameters, these parameters should be updated
31 : // Downstream actions must either implement all these options, or redefine the parameter with
32 : // a restricted MooseEnum, or place an error in the constructor for unsupported configurations
33 : // We mostly pull the boundary parameters from NSFV Action
34 :
35 1905 : params += NSFVBase::commonNavierStokesFlowParams();
36 3810 : params.addParam<bool>(
37 : "include_deviatoric_stress",
38 3810 : false,
39 : "Whether to include the full expansion (the transposed term as well) of the stress tensor");
40 :
41 : // Momentum boundary conditions are important for advection problems as well
42 1905 : params += NSFVBase::commonMomentumBoundaryTypesParams();
43 :
44 : // Specify the weakly compressible boundary flux information. They are used for specifying in flux
45 : // boundary conditions for advection physics in WCNSFV
46 1905 : params += NSFVBase::commonMomentumBoundaryFluxesParams();
47 3810 : params.addParam<std::vector<std::vector<MooseFunctorName>>>(
48 : "momentum_wall_functors",
49 : {},
50 : "Functors for each component of the velocity value on walls. This is only necessary for the "
51 : "fixed-velocity momentum wall types.");
52 :
53 : // Most downstream physics implementations are valid for porous media too
54 : // If yours is not, please remember to disable the 'porous_medium_treatment' parameter
55 1905 : params.transferParam<bool>(NSFVBase::validParams(), "porous_medium_treatment");
56 1905 : params.transferParam<MooseFunctorName>(NSFVBase::validParams(), "porosity");
57 :
58 : // New functor boundary conditions
59 3810 : params.deprecateParam("momentum_inlet_function", "momentum_inlet_functors", "01/01/2025");
60 3810 : params.deprecateParam("pressure_function", "pressure_functors", "01/01/2025");
61 :
62 : // Initialization parameters
63 1905 : params.transferParam<std::vector<FunctionName>>(NSFVBase::validParams(), "initial_velocity");
64 1905 : params.transferParam<FunctionName>(NSFVBase::validParams(), "initial_pressure");
65 :
66 : // Spatial discretization scheme
67 : // Specify the numerical schemes for interpolations of velocity and pressure
68 1905 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "velocity_interpolation");
69 1905 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "momentum_advection_interpolation");
70 1905 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "momentum_face_interpolation");
71 1905 : params.transferParam<bool>(NSFVBase::validParams(), "momentum_two_term_bc_expansion");
72 1905 : params.transferParam<bool>(NSFVBase::validParams(), "pressure_two_term_bc_expansion");
73 3810 : MooseEnum coeff_interp_method("average harmonic", "harmonic");
74 3810 : params.addParam<MooseEnum>("mu_interp_method",
75 : coeff_interp_method,
76 : "Switch that can select face interpolation method for the viscosity.");
77 :
78 : // Parameter groups
79 3810 : params.addParamNamesToGroup(
80 : "velocity_variable pressure_variable initial_pressure initial_velocity", "Variables");
81 3810 : params.addParamNamesToGroup("density dynamic_viscosity", "Material properties");
82 3810 : params.addParamNamesToGroup("inlet_boundaries momentum_inlet_types momentum_inlet_functors",
83 : "Inlet boundary conditions");
84 3810 : params.addParamNamesToGroup("outlet_boundaries momentum_outlet_types pressure_functors",
85 : "Outlet boundary conditions");
86 3810 : params.addParamNamesToGroup("wall_boundaries momentum_wall_types momentum_wall_functors",
87 : "Wall boundary conditions");
88 3810 : params.addParamNamesToGroup(
89 : "include_deviatoric_stress velocity_interpolation momentum_advection_interpolation "
90 : "momentum_two_term_bc_expansion pressure_two_term_bc_expansion mu_interp_method "
91 : "momentum_face_interpolation",
92 : "Numerical scheme");
93 3810 : params.addParamNamesToGroup("thermal_expansion", "Gravity treatment");
94 :
95 1905 : return params;
96 1905 : }
97 :
98 1905 : WCNSFVFlowPhysicsBase::WCNSFVFlowPhysicsBase(const InputParameters & parameters)
99 : : NavierStokesPhysicsBase(parameters),
100 3810 : _has_flow_equations(getParam<bool>("add_flow_equations")),
101 3810 : _compressibility(getParam<MooseEnum>("compressibility")),
102 3810 : _solve_for_dynamic_pressure(getParam<bool>("solve_for_dynamic_pressure")),
103 3810 : _porous_medium_treatment(getParam<bool>("porous_medium_treatment")),
104 3810 : _porosity_name(getParam<MooseFunctorName>("porosity")),
105 : _flow_porosity_functor_name(_porosity_name),
106 4000 : _velocity_names(
107 1905 : isParamValid("velocity_variable")
108 1905 : ? getParam<std::vector<std::string>>("velocity_variable")
109 1715 : : (_porous_medium_treatment
110 1715 : ? std::vector<std::string>(NS::superficial_velocity_vector,
111 : NS::superficial_velocity_vector + 3)
112 : : std::vector<std::string>(NS::velocity_vector, NS::velocity_vector + 3))),
113 3987 : _pressure_name(isParamValid("pressure_variable")
114 2259 : ? getParam<NonlinearVariableName>("pressure_variable")
115 : : NS::pressure),
116 3854 : _fluid_temperature_name(isParamValid("fluid_temperature_variable")
117 1993 : ? getParam<NonlinearVariableName>("fluid_temperature_variable")
118 : : NS::T_fluid),
119 1905 : _density_name(getParam<MooseFunctorName>("density")),
120 3810 : _density_gravity_name(isParamValid("density_gravity")
121 1905 : ? getParam<MooseFunctorName>("density_gravity")
122 5715 : : getParam<MooseFunctorName>("density")),
123 1905 : _dynamic_viscosity_name(getParam<MooseFunctorName>("dynamic_viscosity")),
124 3810 : _velocity_interpolation(getParam<MooseEnum>("velocity_interpolation")),
125 3810 : _momentum_advection_interpolation(getParam<MooseEnum>("momentum_advection_interpolation")),
126 3810 : _momentum_face_interpolation(getParam<MooseEnum>("momentum_face_interpolation")),
127 3810 : _friction_blocks(getParam<std::vector<std::vector<SubdomainName>>>("friction_blocks")),
128 3810 : _friction_types(getParam<std::vector<std::vector<std::string>>>("friction_types")),
129 3810 : _friction_coeffs(getParam<std::vector<std::vector<std::string>>>("friction_coeffs")),
130 3810 : _inlet_boundaries(getParam<std::vector<BoundaryName>>("inlet_boundaries")),
131 3810 : _outlet_boundaries(getParam<std::vector<BoundaryName>>("outlet_boundaries")),
132 3810 : _wall_boundaries(getParam<std::vector<BoundaryName>>("wall_boundaries")),
133 5715 : _hydraulic_separators(getParam<std::vector<BoundaryName>>("hydraulic_separator_sidesets")),
134 3810 : _flux_inlet_pps(getParam<std::vector<PostprocessorName>>("flux_inlet_pps")),
135 7620 : _flux_inlet_directions(getParam<std::vector<Point>>("flux_inlet_directions"))
136 : {
137 : // Inlet boundary parameter checking
138 3810 : checkSecondParamSetOnlyIfFirstOneSet("flux_inlet_pps", "flux_inlet_directions");
139 1905 : if (_flux_inlet_directions.size())
140 36 : checkVectorParamsSameLengthIfSet<PostprocessorName, Point>("flux_inlet_pps",
141 : "flux_inlet_directions");
142 :
143 : // Boussinesq parameters checks
144 3810 : checkSecondParamSetOnlyIfFirstOneTrue("boussinesq_approximation", "ref_temperature");
145 3810 : checkSecondParamSetOnlyIfFirstOneSet("gravity", "boussinesq_approximation");
146 :
147 : // Dynamic pressure parameter checks
148 1905 : if (_compressibility != "incompressible" && _solve_for_dynamic_pressure)
149 0 : paramError("compressibility",
150 : "Solving for dynamic pressure is only implemented for incompressible flow");
151 :
152 : // Boundary parameters checking
153 3808 : checkVectorParamAndMultiMooseEnumLength<BoundaryName>("inlet_boundaries", "momentum_inlet_types");
154 3804 : checkVectorParamAndMultiMooseEnumLength<BoundaryName>("outlet_boundaries",
155 : "momentum_outlet_types");
156 3800 : checkVectorParamAndMultiMooseEnumLength<BoundaryName>("wall_boundaries", "momentum_wall_types");
157 : checkVectorParamLengthSameAsCombinedOthers<BoundaryName,
158 : std::vector<MooseFunctorName>,
159 3796 : PostprocessorName>(
160 : "inlet_boundaries", "momentum_inlet_functors", "flux_inlet_pps");
161 1897 : checkVectorParamsNoOverlap<BoundaryName>(
162 : {"inlet_boundaries", "outlet_boundaries", "wall_boundaries"});
163 :
164 : // Porous media parameters
165 3794 : checkSecondParamSetOnlyIfFirstOneTrue("porous_medium_treatment", "porosity");
166 :
167 1897 : if (_define_variables && _porous_medium_treatment)
168 3366 : for (const auto & name : NS::velocity_vector)
169 : {
170 2525 : const auto & it = std::find(_velocity_names.begin(), _velocity_names.end(), name);
171 2525 : if (it != _velocity_names.end())
172 2 : paramError("velocity_variable",
173 2 : "For porous medium simulations, functor name " + *it +
174 : " is already reserved for the automatically-computed interstitial velocity. "
175 : "Please choose another name for your external velocity variable!");
176 : }
177 :
178 : // Friction parameter checks
179 1895 : if (_friction_blocks.size())
180 348 : checkVectorParamsSameLength<std::vector<SubdomainName>, std::vector<std::string>>(
181 : "friction_blocks", "friction_types");
182 3788 : checkTwoDVectorParamsSameLength<std::string, std::string>("friction_types", "friction_coeffs");
183 :
184 : // Create maps for boundary-restricted parameters
185 3786 : _momentum_inlet_types = Moose::createMapFromVectorAndMultiMooseEnum<BoundaryName>(
186 : _inlet_boundaries, getParam<MultiMooseEnum>("momentum_inlet_types"));
187 3786 : _momentum_outlet_types = Moose::createMapFromVectorAndMultiMooseEnum<BoundaryName>(
188 : _outlet_boundaries, getParam<MultiMooseEnum>("momentum_outlet_types"));
189 3786 : _momentum_wall_types = Moose::createMapFromVectorAndMultiMooseEnum<BoundaryName>(
190 : _wall_boundaries, getParam<MultiMooseEnum>("momentum_wall_types"));
191 3786 : if (isParamSetByUser("momentum_inlet_functors"))
192 : {
193 : // Not all inlet boundary types require the specification of an inlet functor
194 : std::vector<BoundaryName> inlet_boundaries_with_functors;
195 4106 : for (const auto & boundary : _inlet_boundaries)
196 2390 : if (libmesh_map_find(_momentum_inlet_types, boundary) == "fixed-velocity" ||
197 38 : libmesh_map_find(_momentum_inlet_types, boundary) == "fixed-pressure")
198 2352 : inlet_boundaries_with_functors.push_back(boundary);
199 : _momentum_inlet_functors =
200 3508 : Moose::createMapFromVectors<BoundaryName, std::vector<MooseFunctorName>>(
201 : inlet_boundaries_with_functors,
202 : getParam<std::vector<std::vector<MooseFunctorName>>>("momentum_inlet_functors"));
203 1754 : }
204 3786 : if (isParamSetByUser("pressure_functors"))
205 : {
206 : // Not all outlet boundary types require the specification of an inlet functor
207 : std::vector<BoundaryName> outlet_boundaries_with_functors;
208 3366 : for (const auto & boundary : _outlet_boundaries)
209 3376 : if (libmesh_map_find(_momentum_outlet_types, boundary) == "fixed-pressure-zero-gradient" ||
210 1655 : libmesh_map_find(_momentum_outlet_types, boundary) == "fixed-pressure")
211 1702 : outlet_boundaries_with_functors.push_back(boundary);
212 3290 : const auto & pressure_functors = getParam<std::vector<MooseFunctorName>>("pressure_functors");
213 1645 : if (outlet_boundaries_with_functors.size() != pressure_functors.size())
214 4 : paramError("pressure_functors",
215 2 : "Size (" + std::to_string(pressure_functors.size()) +
216 : ") is not the same as the number of pressure outlet boundaries in "
217 2 : "'fixed-pressure/fixed-pressure-zero-gradient' (size " +
218 2 : std::to_string(outlet_boundaries_with_functors.size()) + ")");
219 1643 : _pressure_functors = Moose::createMapFromVectors<BoundaryName, MooseFunctorName>(
220 : outlet_boundaries_with_functors, pressure_functors);
221 1643 : }
222 :
223 3782 : if (isParamSetByUser("momentum_wall_functors"))
224 : {
225 : // Not all wall boundary types require the specification of an inlet functor
226 : std::vector<BoundaryName> wall_boundaries_with_functors;
227 362 : for (const auto & boundary : _wall_boundaries)
228 286 : if (libmesh_map_find(_momentum_wall_types, boundary) == "noslip")
229 286 : wall_boundaries_with_functors.push_back(boundary);
230 : const auto & momentum_wall_functors =
231 152 : getParam<std::vector<std::vector<MooseFunctorName>>>("momentum_wall_functors");
232 76 : if (wall_boundaries_with_functors.size() != momentum_wall_functors.size())
233 0 : paramError("momentum_wall_functors",
234 0 : "Size (" + std::to_string(momentum_wall_functors.size()) +
235 : ") is not the same as the number of momentum_wall wall boundaries with "
236 0 : "no-slip boundary conditions ' (size " +
237 0 : std::to_string(wall_boundaries_with_functors.size()) + ")");
238 :
239 : _momentum_wall_functors =
240 76 : Moose::createMapFromVectors<BoundaryName, std::vector<MooseFunctorName>>(
241 : wall_boundaries_with_functors, momentum_wall_functors);
242 76 : }
243 1891 : }
244 :
245 : void
246 1861 : WCNSFVFlowPhysicsBase::initializePhysicsAdditional()
247 : {
248 1861 : getProblem().needFV();
249 1861 : }
250 :
251 : void
252 24222 : WCNSFVFlowPhysicsBase::actOnAdditionalTasks()
253 : {
254 : // Turbulence physics would not be initialized before this task
255 24222 : if (_current_task == "get_turbulence_physics")
256 1853 : _turbulence_physics = getCoupledTurbulencePhysics();
257 24222 : }
258 :
259 : void
260 1831 : WCNSFVFlowPhysicsBase::addFVBCs()
261 : {
262 1831 : addInletBC();
263 1829 : addOutletBC();
264 1829 : addWallsBC();
265 1829 : addSeparatorBC();
266 1829 : }
267 :
268 : void
269 1839 : WCNSFVFlowPhysicsBase::addMaterials()
270 : {
271 1839 : if (hasForchheimerFriction() || _porous_medium_treatment)
272 879 : addPorousMediumSpeedMaterial();
273 : else
274 960 : addNonPorousMediumSpeedMaterial();
275 1839 : }
276 :
277 : void
278 879 : WCNSFVFlowPhysicsBase::addPorousMediumSpeedMaterial()
279 : {
280 879 : InputParameters params = getFactory().getValidParams("PINSFVSpeedFunctorMaterial");
281 879 : assignBlocks(params, _blocks);
282 :
283 2637 : for (unsigned int dim_i = 0; dim_i < dimension(); ++dim_i)
284 3516 : params.set<MooseFunctorName>(NS::superficial_velocity_vector[dim_i]) = _velocity_names[dim_i];
285 879 : if (_porous_medium_treatment)
286 841 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
287 : else
288 76 : params.set<MooseFunctorName>(NS::porosity) = "1";
289 879 : params.set<bool>("define_interstitial_velocity_components") = _porous_medium_treatment;
290 :
291 2637 : getProblem().addMaterial("PINSFVSpeedFunctorMaterial", prefix() + "pins_speed_material", params);
292 879 : }
293 :
294 : void
295 960 : WCNSFVFlowPhysicsBase::addNonPorousMediumSpeedMaterial()
296 : {
297 960 : const std::string class_name = "ADVectorMagnitudeFunctorMaterial";
298 960 : InputParameters params = getFactory().getValidParams(class_name);
299 960 : assignBlocks(params, _blocks);
300 :
301 3840 : const std::vector<std::string> param_names{"x_functor", "y_functor", "z_functor"};
302 2861 : for (unsigned int dim_i = 0; dim_i < dimension(); ++dim_i)
303 3802 : params.set<MooseFunctorName>(param_names[dim_i]) = _velocity_names[dim_i];
304 1920 : params.set<MooseFunctorName>("vector_magnitude_name") = NS::speed;
305 :
306 1920 : getProblem().addMaterial(class_name, prefix() + "ins_speed_material", params);
307 3840 : }
308 :
309 : void
310 1847 : WCNSFVFlowPhysicsBase::addInitialConditions()
311 : {
312 1859 : if (!_define_variables && parameters().isParamSetByUser("initial_velocity") &&
313 3702 : parameters().isParamSetByUser("velocity_variable") &&
314 1851 : getParam<std::vector<FunctionName>>("initial_velocity").size() != 0)
315 : // TODO: Rework and remove this last statement once the NSFV action is removed
316 2 : paramError("initial_velocity",
317 : "Velocity is defined externally of WCNSFVFlowPhysicsBase, so should the inital "
318 : "conditions");
319 3690 : if (!_define_variables && parameters().isParamSetByUser("initial_pressure") &&
320 1849 : parameters().isParamSetByUser("pressure_variable"))
321 2 : paramError("initial_pressure",
322 : "Pressure is defined externally of WCNSFVFlowPhysicsBase, so should the inital "
323 : "condition");
324 :
325 : // Check dimension
326 7363 : if (getParam<std::vector<FunctionName>>("initial_velocity").size() != dimension() &&
327 3688 : getParam<std::vector<FunctionName>>("initial_velocity").size() != 3 &&
328 1847 : getParam<std::vector<FunctionName>>("initial_velocity").size() != 0)
329 : // TODO: Rework and remove this last statement once the NSFV action is removed
330 2 : paramError("initial_velocity",
331 4 : "The number of velocity components in the " + type() + " initial condition is not " +
332 2 : std::to_string(dimension()) + " or 3!");
333 :
334 1841 : InputParameters params = getFactory().getValidParams("FunctionIC");
335 1841 : assignBlocks(params, _blocks);
336 3682 : auto vvalue = getParam<std::vector<FunctionName>>("initial_velocity");
337 :
338 7345 : for (const auto d : make_range(dimension()))
339 : {
340 7326 : params.set<VariableName>("variable") = _velocity_names[d];
341 3663 : params.set<FunctionName>("function") = vvalue[d];
342 :
343 7326 : if (shouldCreateIC(_velocity_names[d],
344 : _blocks,
345 10989 : /*whether IC is a default*/ !isParamSetByUser("initial_velocity"),
346 7326 : /*error if already an IC*/ isParamSetByUser("initial_velocity")))
347 13724 : getProblem().addInitialCondition("FunctionIC", prefix() + _velocity_names[d] + "_ic", params);
348 : }
349 :
350 3682 : if (shouldCreateIC(_pressure_name,
351 : _blocks,
352 5523 : /*whether IC is a default*/ !isParamSetByUser("initial_pressure"),
353 3682 : /*error if already an IC*/ isParamSetByUser("initial_pressure")))
354 : {
355 3530 : params.set<VariableName>("variable") = _pressure_name;
356 5295 : params.set<FunctionName>("function") = getParam<FunctionName>("initial_pressure");
357 :
358 7060 : getProblem().addInitialCondition("FunctionIC", prefix() + _pressure_name + "_ic", params);
359 : }
360 1841 : }
361 :
362 : unsigned short
363 14976 : WCNSFVFlowPhysicsBase::getNumberAlgebraicGhostingLayersNeeded() const
364 : {
365 : unsigned short ghost_layers = 2;
366 14976 : return ghost_layers;
367 : }
368 :
369 : void
370 1839 : WCNSFVFlowPhysicsBase::addPostprocessors()
371 : {
372 3678 : const auto momentum_inlet_types = getParam<MultiMooseEnum>("momentum_inlet_types");
373 :
374 4200 : for (unsigned int bc_ind = 0; bc_ind < momentum_inlet_types.size(); ++bc_ind)
375 2361 : if (momentum_inlet_types[bc_ind] == "flux-mass" ||
376 2325 : momentum_inlet_types[bc_ind] == "flux-velocity")
377 : {
378 63 : const std::string pp_type = "AreaPostprocessor";
379 63 : InputParameters params = getFactory().getValidParams(pp_type);
380 189 : params.set<std::vector<BoundaryName>>("boundary") = {_inlet_boundaries[bc_ind]};
381 126 : params.set<ExecFlagEnum>("execute_on") = EXEC_INITIAL;
382 :
383 63 : const auto name_pp = "area_pp_" + _inlet_boundaries[bc_ind];
384 63 : if (!getProblem().hasUserObject(name_pp))
385 63 : getProblem().addPostprocessor(pp_type, name_pp, params);
386 63 : }
387 1839 : }
388 :
389 : VariableName
390 0 : WCNSFVFlowPhysicsBase::getFlowVariableName(const std::string & short_name) const
391 : {
392 0 : if (short_name == NS::pressure)
393 0 : return getPressureName();
394 0 : else if (short_name == NS::velocity_x && dimension() > 0)
395 : return getVelocityNames()[0];
396 0 : else if (short_name == NS::velocity_y && dimension() > 1)
397 : return getVelocityNames()[1];
398 0 : else if (short_name == NS::velocity_z && dimension() > 2)
399 : return getVelocityNames()[2];
400 0 : else if (short_name == NS::temperature)
401 0 : return getFluidTemperatureName();
402 : else
403 0 : mooseError("Short Variable name '", short_name, "' not recognized.");
404 : }
405 :
406 : MooseFunctorName
407 339 : WCNSFVFlowPhysicsBase::getPorosityFunctorName(bool smoothed) const
408 : {
409 339 : if (smoothed)
410 : return _flow_porosity_functor_name;
411 : else
412 : return _porosity_name;
413 : }
414 :
415 : const WCNSFVTurbulencePhysics *
416 1853 : WCNSFVFlowPhysicsBase::getCoupledTurbulencePhysics() const
417 : {
418 : // User passed it, just use that
419 3706 : if (isParamValid("coupled_turbulence_physics"))
420 0 : return getCoupledPhysics<WCNSFVTurbulencePhysics>(
421 : getParam<PhysicsName>("coupled_flow_physics"));
422 : // Look for any physics of the right type, and check the block restriction
423 : else
424 : {
425 1853 : const auto all_turbulence_physics = getCoupledPhysics<const WCNSFVTurbulencePhysics>(true);
426 1853 : for (const auto physics : all_turbulence_physics)
427 1089 : if (checkBlockRestrictionIdentical(
428 : physics->name(), physics->blocks(), /*error_if_not_identical=*/false))
429 : return physics;
430 1853 : }
431 : // Did not find one
432 764 : return nullptr;
433 : }
|