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 "WCNSFVFlowPhysics.h"
11 : #include "WCNSFVTurbulencePhysics.h"
12 : #include "NSFVBase.h"
13 : #include "INSFVMomentumAdvection.h"
14 : #include "INSFVRhieChowInterpolator.h"
15 : #include "INSFVTimeKernel.h"
16 : #include "MapConversionUtils.h"
17 : #include "NS.h"
18 :
19 : registerWCNSFVFlowPhysicsBaseTasks("NavierStokesApp", WCNSFVFlowPhysics);
20 : registerMooseAction("NavierStokesApp", WCNSFVFlowPhysics, "add_fv_kernel");
21 : registerMooseAction("NavierStokesApp", WCNSFVFlowPhysics, "add_fv_bc");
22 :
23 : InputParameters
24 1012 : WCNSFVFlowPhysics::validParams()
25 : {
26 1012 : InputParameters params = WCNSFVFlowPhysicsBase::validParams();
27 1012 : params.addClassDescription(
28 : "Define the Navier Stokes weakly-compressible mass and momentum equations");
29 :
30 : // Rhie Chow interpolation parameters
31 1012 : params.transferParam<Real>(INSFVMomentumAdvection::validParams(), "characteristic_speed");
32 2024 : params.addParam<bool>(
33 : "time_derivative_contributes_to_RC_coefficients",
34 2024 : true,
35 : "Whether the time derivative term should contribute to the Rhie Chow coefficients. This adds "
36 : "stabilization, but makes the solution dependent on the time step size");
37 2024 : params.addParamNamesToGroup("time_derivative_contributes_to_RC_coefficients characteristic_speed",
38 : "Numerical scheme");
39 :
40 : // Used for flow mixtures, where one phase is solid / not moving under the action of gravity
41 2024 : params.addParam<MooseFunctorName>(
42 : "density_for_gravity_terms",
43 : "If specified, replaces the 'density' for the Boussinesq and gravity momentum kernels");
44 :
45 : // Additional porous media parameters
46 1012 : params.transferParam<unsigned short>(NSFVBase::validParams(), "porosity_smoothing_layers");
47 :
48 : // Techniques to limit or remove oscillations at porosity jump interfaces
49 1012 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "porosity_interface_pressure_treatment");
50 1012 : params.transferParam<std::vector<BoundaryName>>(NSFVBase::validParams(),
51 : "pressure_drop_sidesets");
52 1012 : params.transferParam<std::vector<Real>>(NSFVBase::validParams(), "pressure_drop_form_factors");
53 :
54 : // Friction correction, a technique to limit oscillations at friction interfaces
55 1012 : params.transferParam<bool>(NSFVBase::validParams(), "use_friction_correction");
56 1012 : params.transferParam<Real>(NSFVBase::validParams(), "consistent_scaling");
57 :
58 : // Couple to turbulence physics
59 2024 : params.addParam<PhysicsName>("coupled_turbulence_physics",
60 : "Turbulence Physics coupled with the flow");
61 :
62 : // Spatial discretization scheme
63 : // Specify the numerical schemes for interpolations of velocity and pressure
64 1012 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "pressure_face_interpolation");
65 1012 : params.transferParam<MooseEnum>(NSFVBase::validParams(), "mass_advection_interpolation");
66 1012 : params.transferParam<bool>(NSFVBase::validParams(),
67 : "pressure_allow_expansion_on_bernoulli_faces");
68 :
69 : // Nonlinear solver parameters
70 1012 : params.transferParam<Real>(NSFVBase::validParams(), "mass_scaling");
71 1012 : params.transferParam<Real>(NSFVBase::validParams(), "momentum_scaling");
72 :
73 : // Parameter groups
74 2024 : params.addParamNamesToGroup("coupled_turbulence_physics", "Coupled Physics");
75 2024 : params.addParamNamesToGroup(
76 : "porosity_interface_pressure_treatment pressure_allow_expansion_on_bernoulli_faces "
77 : "porosity_smoothing_layers use_friction_correction consistent_scaling "
78 : "pressure_drop_sidesets pressure_drop_form_factors",
79 : "Flow medium discontinuity treatment");
80 2024 : params.addParamNamesToGroup("pressure_face_interpolation "
81 : "mass_advection_interpolation momentum_advection_interpolation "
82 : "mass_scaling momentum_scaling characteristic_speed",
83 : "Numerical scheme");
84 :
85 : // TODO Add default preconditioning and move scaling parameters to a preconditioning group
86 :
87 1012 : return params;
88 0 : }
89 :
90 1012 : WCNSFVFlowPhysics::WCNSFVFlowPhysics(const InputParameters & parameters)
91 : : WCNSFVFlowPhysicsBase(parameters),
92 998 : _porosity_smoothing_layers(isParamValid("porosity_smoothing_layers")
93 1338 : ? getParam<unsigned short>("porosity_smoothing_layers")
94 1012 : : 0)
95 : {
96 998 : _flow_porosity_functor_name = isParamValid("porosity_smoothing_layers") &&
97 1508 : getParam<unsigned short>("porosity_smoothing_layers")
98 : ? NS::smoothed_porosity
99 998 : : _porosity_name;
100 :
101 : // Most likely to be a mistake
102 3145 : if (getParam<bool>("pin_pressure") &&
103 1300 : getParam<std::vector<MooseFunctorName>>("pressure_functors").size())
104 0 : paramError("pin_pressure", "Cannot pin the pressure if a pressure boundary exists");
105 :
106 : // Pressure pin checks
107 1996 : checkSecondParamSetOnlyIfFirstOneTrue("pin_pressure", "pinned_pressure_type");
108 1996 : checkSecondParamSetOnlyIfFirstOneTrue("pin_pressure", "pinned_pressure_value");
109 1996 : if (getParam<bool>("pin_pressure"))
110 : {
111 453 : if ((std::string(getParam<MooseEnum>("pinned_pressure_type")).find("point") !=
112 230 : std::string::npos) &&
113 309 : !isParamSetByUser("pinned_pressure_point"))
114 0 : paramError("pinned_pressure_point",
115 : "This parameter must be set to specify the pinned pressure point");
116 453 : else if ((std::string(getParam<MooseEnum>("pinned_pressure_type")).find("point") ==
117 151 : std::string::npos) &&
118 295 : isParamSetByUser("pinned_pressure_point"))
119 2 : paramError("pinned_pressure_point",
120 : "This parameter should not be given by the user with the corresponding "
121 2 : "pinned_pressure_type setting: " +
122 2 : std::string(getParam<MooseEnum>("pinned_pressure_type")) + ".");
123 : }
124 :
125 : // Porosity correction checks
126 1990 : checkSecondParamSetOnlyIfFirstOneTrue("porous_medium_treatment", "use_friction_correction");
127 1986 : checkSecondParamSetOnlyIfFirstOneTrue("use_friction_correction", "consistent_scaling");
128 1984 : checkSecondParamSetOnlyIfFirstOneTrue("porous_medium_treatment",
129 : "porosity_interface_pressure_treatment");
130 2976 : if (getParam<MooseEnum>("porosity_interface_pressure_treatment") != "bernoulli")
131 1874 : errorDependentParameter("porosity_interface_pressure_treatment",
132 : "bernoulli",
133 : {"pressure_allow_expansion_on_bernoulli_faces",
134 : "pressure_drop_sidesets",
135 : "pressure_drop_form_factors"});
136 :
137 : // Porous media parameters
138 1978 : checkSecondParamSetOnlyIfFirstOneTrue("porous_medium_treatment", "porosity_smoothing_layers");
139 988 : }
140 :
141 : void
142 968 : WCNSFVFlowPhysics::addSolverVariables()
143 : {
144 968 : if (!_has_flow_equations)
145 : return;
146 :
147 2856 : for (const auto d : make_range(dimension()))
148 3802 : saveSolverVariableName(_velocity_names[d]);
149 1910 : saveSolverVariableName(_pressure_name);
150 :
151 : // Check number of variables
152 955 : if (_velocity_names.size() != dimension() && _velocity_names.size() != 3)
153 2 : paramError("velocity_variable",
154 2 : "The number of velocity variable names supplied to the NSFVAction is not " +
155 4 : Moose::stringify(dimension()) + " (mesh dimension)" +
156 4 : ((dimension() == 3) ? "" : " or 3!") + "\nVelocity variables " +
157 2 : Moose::stringify(_velocity_names));
158 :
159 : // Velocities
160 2846 : for (const auto d : make_range(dimension()))
161 : {
162 3790 : if (!shouldCreateVariable(_velocity_names[d], _blocks, /*error if aux*/ true))
163 42 : reportPotentiallyMissedParameters({"system_names",
164 : "momentum_scaling",
165 : "momentum_face_interpolation",
166 : "momentum_two_term_bc_expansion"},
167 : "INSFVVelocityVariable");
168 1853 : else if (_define_variables)
169 : {
170 1851 : std::string variable_type = "INSFVVelocityVariable";
171 1851 : if (_porous_medium_treatment)
172 : variable_type = "PINSFVSuperficialVelocityVariable";
173 :
174 1851 : auto params = getFactory().getValidParams(variable_type);
175 1851 : assignBlocks(params, _blocks); // TODO: check wrt components
176 5553 : params.set<std::vector<Real>>("scaling") = {getParam<Real>("momentum_scaling")};
177 3702 : params.set<MooseEnum>("face_interp_method") =
178 3702 : getParam<MooseEnum>("momentum_face_interpolation");
179 1851 : params.set<bool>("two_term_boundary_expansion") =
180 5553 : getParam<bool>("momentum_two_term_bc_expansion");
181 :
182 3702 : params.set<SolverSystemName>("solver_sys") = getSolverSystem(_velocity_names[d]);
183 1851 : getProblem().addVariable(variable_type, _velocity_names[d], params);
184 1851 : }
185 : else
186 4 : paramError("velocity_variable",
187 2 : "Variable (" + _velocity_names[d] +
188 : ") supplied to the WCNSFVFlowPhysics does not exist!");
189 : }
190 :
191 : // Pressure
192 : const bool using_bernouilli_pressure_var =
193 951 : _porous_medium_treatment &&
194 1394 : getParam<MooseEnum>("porosity_interface_pressure_treatment") != "automatic";
195 : const auto pressure_type =
196 951 : using_bernouilli_pressure_var ? "BernoulliPressureVariable" : "INSFVPressureVariable";
197 1902 : if (!shouldCreateVariable(_pressure_name, _blocks, /*error if aux*/ true))
198 : {
199 : std::vector<std::string> potentially_missed = {"system_names",
200 : "mass_scaling",
201 : "pressure_face_interpolation",
202 28 : "pressure_two_term_bc_expansion"};
203 28 : if (using_bernouilli_pressure_var)
204 : {
205 : std::vector<std::string> other_missed = {"pressure_allow_expansion_on_bernoulli_faces",
206 : "pressure_drop_sidesets",
207 9 : "pressure_drop_form_factors"};
208 9 : potentially_missed.insert(potentially_missed.end(), other_missed.begin(), other_missed.end());
209 9 : }
210 56 : reportPotentiallyMissedParameters(potentially_missed, pressure_type);
211 28 : }
212 923 : else if (_define_variables)
213 : {
214 921 : auto params = getFactory().getValidParams(pressure_type);
215 921 : assignBlocks(params, _blocks);
216 2763 : params.set<std::vector<Real>>("scaling") = {getParam<Real>("mass_scaling")};
217 1842 : params.set<MooseEnum>("face_interp_method") =
218 1842 : getParam<MooseEnum>("pressure_face_interpolation");
219 921 : params.set<bool>("two_term_boundary_expansion") =
220 1842 : getParam<bool>("pressure_two_term_bc_expansion");
221 :
222 921 : if (using_bernouilli_pressure_var)
223 : {
224 90 : params.set<MooseFunctorName>("u") = _velocity_names[0];
225 45 : if (dimension() >= 2)
226 90 : params.set<MooseFunctorName>("v") = _velocity_names[1];
227 45 : if (dimension() == 3)
228 0 : params.set<MooseFunctorName>("w") = _velocity_names[2];
229 45 : params.set<MooseFunctorName>(NS::porosity) = _porosity_name;
230 45 : params.set<MooseFunctorName>(NS::density) = _density_name;
231 45 : params.set<bool>("allow_two_term_expansion_on_bernoulli_faces") =
232 90 : getParam<bool>("pressure_allow_expansion_on_bernoulli_faces");
233 90 : params.set<std::vector<BoundaryName>>("pressure_drop_sidesets") =
234 90 : getParam<std::vector<BoundaryName>>("pressure_drop_sidesets");
235 90 : params.set<std::vector<Real>>("pressure_drop_form_factors") =
236 135 : getParam<std::vector<Real>>("pressure_drop_form_factors");
237 : }
238 1842 : params.set<SolverSystemName>("solver_sys") = getSolverSystem(_pressure_name);
239 921 : getProblem().addVariable(pressure_type, _pressure_name, params);
240 921 : }
241 : else
242 2 : paramError("pressure_variable",
243 2 : "Variable (" + _pressure_name +
244 : ") supplied to the WCNSFVFlowPhysics does not exist!");
245 :
246 : // Add lagrange multiplier for pinning pressure, if needed
247 1898 : if (getParam<bool>("pin_pressure"))
248 : {
249 447 : auto type = getParam<MooseEnum>("pinned_pressure_type");
250 149 : auto lm_params = getFactory().getValidParams("MooseVariableScalar");
251 298 : lm_params.set<MooseEnum>("family") = "scalar";
252 298 : lm_params.set<MooseEnum>("order") = "first";
253 :
254 149 : if ((type == "point-value" || type == "average"))
255 : {
256 262 : if (!_problem->hasScalarVariable("lambda"))
257 : {
258 262 : lm_params.set<SolverSystemName>("solver_sys") = getSolverSystem("lambda");
259 262 : getProblem().addVariable("MooseVariableScalar", "lambda", lm_params);
260 : }
261 : else
262 0 : reportPotentiallyMissedParameters({"system_names"}, "MooseVariableScalar");
263 : }
264 149 : }
265 : }
266 :
267 : void
268 946 : WCNSFVFlowPhysics::addFVKernels()
269 : {
270 946 : if (!_has_flow_equations)
271 : return;
272 :
273 : // Mass equation: time derivative
274 937 : if (_compressibility == "weakly-compressible" &&
275 1091 : shouldCreateTimeDerivative(_pressure_name, _blocks, /*error if already defined*/ false))
276 72 : addMassTimeKernels();
277 :
278 : // Mass equation: divergence of momentum
279 937 : addMassKernels();
280 :
281 : // Pressure pin
282 1874 : if (getParam<bool>("pin_pressure"))
283 149 : addPressurePinKernel();
284 :
285 : // Momentum equation: time derivative
286 937 : if (isTransient())
287 170 : addMomentumTimeKernels();
288 :
289 : // Momentum equation: momentum advection
290 937 : addMomentumAdvectionKernels();
291 :
292 : // Momentum equation: momentum viscous stress
293 937 : addMomentumViscousDissipationKernels();
294 937 : addAxisymmetricViscousSource();
295 :
296 : // Momentum equation: pressure term
297 937 : addMomentumPressureKernels();
298 :
299 : // Momentum equation: gravity source term
300 937 : addMomentumGravityKernels();
301 :
302 : // Momentum equation: friction kernels
303 937 : if (_friction_types.size())
304 315 : addMomentumFrictionKernels();
305 :
306 : // Momentum equation: boussinesq approximation
307 1874 : if (getParam<bool>("boussinesq_approximation"))
308 34 : addMomentumBoussinesqKernels();
309 : }
310 :
311 : void
312 72 : WCNSFVFlowPhysics::addMassTimeKernels()
313 : {
314 72 : std::string mass_kernel_type = "WCNSFVMassTimeDerivative";
315 0 : std::string kernel_name = prefix() + "wcns_mass_time";
316 :
317 72 : if (_porous_medium_treatment)
318 : {
319 : mass_kernel_type = "PWCNSFVMassTimeDerivative";
320 60 : kernel_name = prefix() + "pwcns_mass_time";
321 : }
322 :
323 72 : InputParameters params = getFactory().getValidParams(mass_kernel_type);
324 72 : assignBlocks(params, _blocks);
325 72 : params.set<NonlinearVariableName>("variable") = _pressure_name;
326 216 : params.set<MooseFunctorName>(NS::time_deriv(NS::density)) = NS::time_deriv(_density_name);
327 72 : if (_porous_medium_treatment)
328 30 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
329 72 : getProblem().addFVKernel(mass_kernel_type, kernel_name, params);
330 144 : }
331 :
332 : void
333 937 : WCNSFVFlowPhysics::addMassKernels()
334 : {
335 937 : std::string kernel_type = "INSFVMassAdvection";
336 0 : std::string kernel_name = prefix() + "ins_mass_advection";
337 :
338 937 : if (_porous_medium_treatment)
339 : {
340 : kernel_type = "PINSFVMassAdvection";
341 886 : kernel_name = prefix() + "pins_mass_advection";
342 : }
343 :
344 937 : InputParameters params = getFactory().getValidParams(kernel_type);
345 937 : assignBlocks(params, _blocks);
346 937 : params.set<NonlinearVariableName>("variable") = _pressure_name;
347 937 : params.set<MooseFunctorName>(NS::density) = _density_name;
348 937 : params.set<MooseEnum>("velocity_interp_method") = _velocity_interpolation;
349 937 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
350 1874 : params.set<MooseEnum>("advected_interp_method") =
351 2811 : getParam<MooseEnum>("mass_advection_interpolation");
352 :
353 937 : getProblem().addFVKernel(kernel_type, kernel_name, params);
354 1874 : }
355 :
356 : void
357 149 : WCNSFVFlowPhysics::addPressurePinKernel()
358 : {
359 298 : const auto pin_type = getParam<MooseEnum>("pinned_pressure_type");
360 : const auto object_type =
361 149 : (pin_type == "average") ? "FVIntegralValueConstraint" : "FVPointValueConstraint";
362 149 : InputParameters params = getFactory().getValidParams(object_type);
363 149 : if (pin_type != "point-value" && pin_type != "average")
364 : return;
365 :
366 393 : params.set<CoupledName>("lambda") = {"lambda"};
367 393 : params.set<PostprocessorName>("phi0") = getParam<PostprocessorName>("pinned_pressure_value");
368 131 : params.set<NonlinearVariableName>("variable") = _pressure_name;
369 131 : if (pin_type == "point-value")
370 140 : params.set<Point>("point") = getParam<Point>("pinned_pressure_point");
371 :
372 393 : getProblem().addFVKernel(object_type, prefix() + "ins_mass_pressure_pin", params);
373 149 : }
374 :
375 : void
376 170 : WCNSFVFlowPhysics::addMomentumTimeKernels()
377 : {
378 170 : std::string kernel_type = (_compressibility == "weakly-compressible")
379 : ? "WCNSFVMomentumTimeDerivative"
380 268 : : "INSFVMomentumTimeDerivative";
381 170 : std::string kernel_name = prefix() +
382 170 : ((_compressibility == "weakly-compressible") ? "wcns_" : "ins_") +
383 : "momentum_time_";
384 :
385 170 : if (_porous_medium_treatment)
386 : {
387 : // Porosity does not appear in the term
388 75 : kernel_type = (_compressibility == "weakly-compressible") ? "WCNSFVMomentumTimeDerivative"
389 75 : : "PINSFVMomentumTimeDerivative";
390 150 : kernel_name = prefix() + ((_compressibility == "weakly-compressible") ? "pwcns_" : "pins_") +
391 75 : "momentum_time_";
392 : }
393 :
394 170 : InputParameters params = getFactory().getValidParams(kernel_type);
395 170 : assignBlocks(params, _blocks);
396 170 : params.set<MooseFunctorName>(NS::density) = _density_name;
397 170 : if (_compressibility == "weakly-compressible")
398 288 : params.set<MooseFunctorName>(NS::time_deriv(NS::density)) = NS::time_deriv(_density_name);
399 :
400 170 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
401 170 : params.set<bool>("contribute_to_rc") =
402 340 : getParam<bool>("time_derivative_contributes_to_RC_coefficients");
403 :
404 680 : for (const auto d : make_range(dimension()))
405 : {
406 680 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
407 680 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
408 :
409 680 : if (shouldCreateTimeDerivative(_velocity_names[d], _blocks, /*error if already defined*/ false))
410 680 : getProblem().addFVKernel(kernel_type, kernel_name + _velocity_names[d], params);
411 : }
412 340 : }
413 :
414 : void
415 937 : WCNSFVFlowPhysics::addMomentumAdvectionKernels()
416 : {
417 937 : std::string kernel_type = "INSFVMomentumAdvection";
418 0 : std::string kernel_name = prefix() + "ins_momentum_advection_";
419 :
420 937 : if (_porous_medium_treatment)
421 : {
422 : kernel_type = "PINSFVMomentumAdvection";
423 886 : kernel_name = prefix() + "pins_momentum_advection_";
424 : }
425 :
426 937 : InputParameters params = getFactory().getValidParams(kernel_type);
427 937 : assignBlocks(params, _blocks);
428 937 : params.set<MooseFunctorName>(NS::density) = _density_name;
429 937 : params.set<MooseEnum>("velocity_interp_method") = _velocity_interpolation;
430 937 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
431 937 : params.set<MooseEnum>("advected_interp_method") = _momentum_advection_interpolation;
432 937 : if (_porous_medium_treatment)
433 443 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
434 937 : params.applySpecificParameters(parameters(), INSFVMomentumAdvection::listOfCommonParams());
435 :
436 3739 : for (const auto d : make_range(dimension()))
437 : {
438 3730 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
439 3730 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
440 :
441 3730 : getProblem().addFVKernel(kernel_type, kernel_name + NS::directions[d], params);
442 : }
443 1874 : }
444 :
445 : void
446 937 : WCNSFVFlowPhysics::addMomentumViscousDissipationKernels()
447 : {
448 937 : std::string kernel_type = "INSFVMomentumDiffusion";
449 0 : std::string kernel_name = prefix() + "ins_momentum_diffusion_";
450 :
451 937 : if (_porous_medium_treatment)
452 : {
453 : kernel_type = "PINSFVMomentumDiffusion";
454 886 : kernel_name = prefix() + "pins_momentum_diffusion_";
455 : }
456 :
457 937 : InputParameters params = getFactory().getValidParams(kernel_type);
458 937 : assignBlocks(params, _blocks);
459 937 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
460 937 : params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
461 : const bool user_include_iso = includeIsotropicStress();
462 937 : if (user_include_iso && _porous_medium_treatment)
463 0 : paramWarning("include_isotropic_viscous_stress",
464 : "Including the isotropic viscous stress is not supported with the porous medium "
465 : "treatment. Ignoring the request.");
466 937 : const bool include_isotropic = (!_porous_medium_treatment) && user_include_iso;
467 : if (include_isotropic)
468 0 : params.set<bool>("include_isotropic_viscous_stress") = true;
469 2811 : params.set<MooseEnum>("mu_interp_method") = getParam<MooseEnum>("mu_interp_method");
470 1874 : params.set<MooseEnum>("variable_interp_method") =
471 2811 : getParam<MooseEnum>("momentum_face_interpolation");
472 : bool include_symmetric = includeSymmetrizedViscousStress();
473 937 : if (include_symmetric && _porous_medium_treatment)
474 : {
475 0 : paramWarning("include_symmetrized_viscous_stress",
476 : "Including the symmetrized viscous stress is not supported with the porous "
477 : "medium treatment. Ignoring the request.");
478 : include_symmetric = false;
479 : }
480 937 : if (include_symmetric || include_isotropic)
481 : {
482 30 : params.set<bool>("complete_expansion") = true;
483 120 : const std::string u_names[3] = {"u", "v", "w"};
484 90 : for (unsigned int i = 0; i < dimension(); ++i)
485 120 : params.set<MooseFunctorName>(u_names[i]) = _velocity_names[i];
486 120 : }
487 :
488 937 : if (_porous_medium_treatment)
489 443 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
490 : // Currently only Newton method for WCNSFVFlowPhysics
491 937 : params.set<bool>("newton_solve") = true;
492 3739 : for (const auto d : make_range(dimension()))
493 : {
494 3730 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
495 3730 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
496 :
497 3730 : getProblem().addFVKernel(kernel_type, kernel_name + NS::directions[d], params);
498 : }
499 1874 : }
500 :
501 : void
502 45 : WCNSFVFlowPhysics::addAxisymmetricViscousSourceKernel(const std::vector<SubdomainName> & rz_blocks,
503 : const unsigned int radial_index)
504 : {
505 45 : InputParameters params = getFactory().getValidParams("INSFVMomentumViscousSourceRZ");
506 45 : assignBlocks(params, rz_blocks);
507 45 : params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
508 45 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
509 90 : params.set<MooseEnum>("momentum_component") = NS::directions[radial_index];
510 45 : params.set<bool>("complete_expansion") = includeSymmetrizedViscousStress();
511 90 : params.set<NonlinearVariableName>("variable") = _velocity_names[radial_index];
512 :
513 135 : getProblem().addFVKernel("INSFVMomentumViscousSourceRZ",
514 45 : prefix() + "ins_momentum_viscous_source_rz_" +
515 : NS::directions[radial_index],
516 : params);
517 45 : }
518 :
519 : void
520 937 : WCNSFVFlowPhysics::addMomentumPressureKernels()
521 : {
522 937 : std::string kernel_type = "INSFVMomentumPressure";
523 0 : std::string kernel_name = prefix() + "ins_momentum_pressure_";
524 :
525 937 : if (_porous_medium_treatment)
526 : {
527 : kernel_type = "PINSFVMomentumPressure";
528 886 : kernel_name = prefix() + "pins_momentum_pressure_";
529 : }
530 :
531 937 : InputParameters params = getFactory().getValidParams(kernel_type);
532 937 : assignBlocks(params, _blocks);
533 937 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
534 1874 : params.set<MooseFunctorName>("pressure") = _pressure_name;
535 937 : params.set<bool>("correct_skewness") =
536 1874 : getParam<MooseEnum>("pressure_face_interpolation") == "skewness-corrected";
537 937 : if (_porous_medium_treatment)
538 443 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
539 :
540 3739 : for (const auto d : make_range(dimension()))
541 : {
542 1865 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
543 3730 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
544 3730 : getProblem().addFVKernel(kernel_type, kernel_name + NS::directions[d], params);
545 : }
546 1874 : }
547 :
548 : void
549 937 : WCNSFVFlowPhysics::addMomentumGravityKernels()
550 : {
551 1874 : if (parameters().isParamValid("gravity") && !_solve_for_dynamic_pressure)
552 : {
553 930 : std::string kernel_type = "INSFVMomentumGravity";
554 0 : std::string kernel_name = prefix() + "ins_momentum_gravity_";
555 :
556 930 : if (_porous_medium_treatment)
557 : {
558 : kernel_type = "PINSFVMomentumGravity";
559 886 : kernel_name = prefix() + "pins_momentum_gravity_";
560 : }
561 :
562 930 : InputParameters params = getFactory().getValidParams(kernel_type);
563 930 : assignBlocks(params, _blocks);
564 930 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
565 930 : params.set<MooseFunctorName>(NS::density) = _density_gravity_name;
566 1860 : params.set<RealVectorValue>("gravity") = getParam<RealVectorValue>("gravity");
567 930 : if (_porous_medium_treatment)
568 443 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
569 :
570 3711 : for (const auto d : make_range(dimension()))
571 : {
572 3702 : if (getParam<RealVectorValue>("gravity")(d) != 0)
573 : {
574 43 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
575 86 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
576 :
577 86 : getProblem().addFVKernel(kernel_type, kernel_name + NS::directions[d], params);
578 : }
579 : }
580 930 : }
581 937 : }
582 :
583 : void
584 34 : WCNSFVFlowPhysics::addMomentumBoussinesqKernels()
585 : {
586 34 : if (_compressibility == "weakly-compressible")
587 0 : paramError("boussinesq_approximation",
588 : "We cannot use boussinesq approximation while running in weakly-compressible mode!");
589 :
590 34 : std::string kernel_type = "INSFVMomentumBoussinesq";
591 0 : std::string kernel_name = prefix() + "ins_momentum_boussinesq_";
592 :
593 34 : if (_porous_medium_treatment)
594 : {
595 : kernel_type = "PINSFVMomentumBoussinesq";
596 18 : kernel_name = prefix() + "pins_momentum_boussinesq_";
597 : }
598 :
599 34 : InputParameters params = getFactory().getValidParams(kernel_type);
600 34 : assignBlocks(params, _blocks);
601 34 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
602 34 : params.set<MooseFunctorName>(NS::T_fluid) = _fluid_temperature_name;
603 34 : params.set<MooseFunctorName>(NS::density) = _density_gravity_name;
604 68 : params.set<RealVectorValue>("gravity") = getParam<RealVectorValue>("gravity");
605 68 : params.set<Real>("ref_temperature") = getParam<Real>("ref_temperature");
606 102 : params.set<MooseFunctorName>("alpha_name") = getParam<MooseFunctorName>("thermal_expansion");
607 34 : if (_porous_medium_treatment)
608 9 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
609 : // User declared the flow to be incompressible, we have to trust them
610 34 : params.set<bool>("_override_constant_check") = true;
611 :
612 136 : for (const auto d : make_range(dimension()))
613 : {
614 136 : if (getParam<RealVectorValue>("gravity")(d) != 0)
615 : {
616 34 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
617 68 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
618 :
619 68 : getProblem().addFVKernel(kernel_type, kernel_name + NS::directions[d], params);
620 : }
621 : }
622 68 : }
623 :
624 : void
625 315 : WCNSFVFlowPhysics::addMomentumFrictionKernels()
626 : {
627 315 : unsigned int num_friction_blocks = _friction_blocks.size();
628 : unsigned int num_used_blocks = num_friction_blocks ? num_friction_blocks : 1;
629 :
630 315 : const std::string kernel_type = "PINSFVMomentumFriction";
631 315 : InputParameters params = getFactory().getValidParams(kernel_type);
632 315 : params.set<MooseFunctorName>(NS::density) = _density_name;
633 315 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
634 315 : if (hasForchheimerFriction())
635 516 : params.set<MooseFunctorName>(NS::speed) = NS::speed;
636 315 : params.set<bool>("standard_friction_formulation") =
637 630 : getParam<bool>("standard_friction_formulation");
638 315 : params.set<bool>("is_porous_medium") = _porous_medium_treatment;
639 :
640 678 : for (const auto block_i : make_range(num_used_blocks))
641 : {
642 363 : std::string block_name = "";
643 363 : if (num_friction_blocks)
644 : {
645 114 : params.set<std::vector<SubdomainName>>("block") = _friction_blocks[block_i];
646 228 : block_name = Moose::stringify(_friction_blocks[block_i]);
647 : }
648 : else
649 : {
650 249 : assignBlocks(params, _blocks);
651 498 : block_name = std::to_string(block_i);
652 : }
653 :
654 1089 : for (const auto d : make_range(dimension()))
655 : {
656 1452 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
657 726 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
658 1986 : for (unsigned int type_i = 0; type_i < _friction_types[block_i].size(); ++type_i)
659 : {
660 1260 : const auto upper_name = MooseUtils::toUpper(_friction_types[block_i][type_i]);
661 1260 : if (upper_name == "DARCY")
662 : {
663 672 : params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
664 1344 : params.set<MooseFunctorName>("Darcy_name") = _friction_coeffs[block_i][type_i];
665 : }
666 588 : else if (upper_name == "FORCHHEIMER")
667 : {
668 1176 : params.set<MooseFunctorName>(NS::speed) = NS::speed;
669 1176 : params.set<MooseFunctorName>("Forchheimer_name") = _friction_coeffs[block_i][type_i];
670 : }
671 : else
672 0 : paramError("friction_types",
673 : "Friction type '",
674 : _friction_types[block_i][type_i],
675 : "' is not implemented");
676 : }
677 :
678 1452 : getProblem().addFVKernel(kernel_type,
679 2178 : prefix() + "momentum_friction_" + block_name + "_" +
680 : NS::directions[d],
681 : params);
682 : }
683 :
684 933 : if (_porous_medium_treatment && getParam<bool>("use_friction_correction"))
685 : {
686 240 : const std::string correction_kernel_type = "PINSFVMomentumFrictionCorrection";
687 240 : InputParameters corr_params = getFactory().getValidParams(correction_kernel_type);
688 240 : if (num_friction_blocks)
689 144 : corr_params.set<std::vector<SubdomainName>>("block") = _friction_blocks[block_i];
690 : else
691 168 : assignBlocks(corr_params, _blocks);
692 240 : corr_params.set<MooseFunctorName>(NS::density) = _density_name;
693 240 : corr_params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
694 480 : corr_params.set<Real>("consistent_scaling") = getParam<Real>("consistent_scaling");
695 720 : for (const auto d : make_range(dimension()))
696 : {
697 960 : corr_params.set<NonlinearVariableName>("variable") = _velocity_names[d];
698 480 : corr_params.set<MooseEnum>("momentum_component") = NS::directions[d];
699 1440 : for (unsigned int type_i = 0; type_i < _friction_types[block_i].size(); ++type_i)
700 : {
701 960 : const auto upper_name = MooseUtils::toUpper(_friction_types[block_i][type_i]);
702 960 : if (upper_name == "DARCY")
703 : {
704 480 : corr_params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
705 960 : corr_params.set<MooseFunctorName>("Darcy_name") = _friction_coeffs[block_i][type_i];
706 : }
707 480 : else if (upper_name == "FORCHHEIMER")
708 : {
709 960 : corr_params.set<MooseFunctorName>(NS::speed) = NS::speed;
710 960 : corr_params.set<MooseFunctorName>("Forchheimer_name") =
711 480 : _friction_coeffs[block_i][type_i];
712 : }
713 : }
714 :
715 960 : getProblem().addFVKernel(correction_kernel_type,
716 480 : prefix() + "pins_momentum_friction_correction_" + block_name +
717 960 : "_" + NS::directions[d],
718 : corr_params);
719 : }
720 240 : }
721 : }
722 630 : }
723 :
724 : void
725 938 : WCNSFVFlowPhysics::addInletBC()
726 : {
727 : // Check the size of the BC parameters
728 : unsigned int num_velocity_functor_inlets = 0;
729 2169 : for (const auto & [bdy, momentum_outlet_type] : _momentum_inlet_types)
730 1231 : if (momentum_outlet_type == "fixed-velocity" || momentum_outlet_type == "fixed-pressure")
731 1164 : num_velocity_functor_inlets++;
732 :
733 938 : if (num_velocity_functor_inlets != _momentum_inlet_functors.size())
734 0 : paramError("momentum_inlet_functors",
735 0 : "Size (" + std::to_string(_momentum_inlet_functors.size()) +
736 : ") is not the same as the number of entries in the momentum_inlet_types "
737 0 : "subvector for fixed-velocities/pressures functors (size " +
738 0 : std::to_string(num_velocity_functor_inlets) + ")");
739 :
740 : unsigned int flux_bc_counter = 0;
741 : unsigned int velocity_pressure_counter = 0;
742 2167 : for (const auto & [inlet_bdy, momentum_inlet_type] : _momentum_inlet_types)
743 : {
744 1231 : if (momentum_inlet_type == "fixed-velocity")
745 : {
746 1146 : const std::string bc_type = "INSFVInletVelocityBC";
747 1146 : InputParameters params = getFactory().getValidParams(bc_type);
748 3438 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
749 1146 : if (_momentum_inlet_functors.size() < velocity_pressure_counter + 1)
750 0 : paramError("momentum_inlet_functors",
751 0 : "More non-flux inlets than inlet functors (" +
752 0 : std::to_string(_momentum_inlet_functors.size()) + ")");
753 :
754 : // Check that enough functors have been provided for the dimension of the problem
755 1146 : const auto momentum_functors = libmesh_map_find(_momentum_inlet_functors, inlet_bdy);
756 1146 : if (momentum_functors.size() < dimension())
757 2 : paramError("momentum_inlet_functors",
758 4 : "Subvector for boundary '" + inlet_bdy + "' (size " +
759 2 : std::to_string(momentum_functors.size()) +
760 2 : ") is not the same size as the number of dimensions of the physics (" +
761 2 : std::to_string(dimension()) + ")");
762 :
763 3432 : for (const auto d : make_range(dimension()))
764 : {
765 4576 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
766 4576 : params.set<MooseFunctorName>("functor") = momentum_functors[d];
767 :
768 4576 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + inlet_bdy, params);
769 : }
770 : ++velocity_pressure_counter;
771 1144 : }
772 85 : else if (momentum_inlet_type == "fixed-pressure")
773 : {
774 18 : const std::string bc_type = "INSFVOutletPressureBC";
775 18 : InputParameters params = getFactory().getValidParams(bc_type);
776 36 : params.set<NonlinearVariableName>("variable") = _pressure_name;
777 18 : if (_momentum_inlet_functors.size() < velocity_pressure_counter + 1)
778 0 : paramError("momentum_inlet_functors",
779 0 : "More non-flux inlets than inlet functors (" +
780 0 : std::to_string(_momentum_inlet_functors.size()) + ")");
781 :
782 36 : params.set<FunctionName>("function") =
783 36 : libmesh_map_find(_momentum_inlet_functors, inlet_bdy)[0];
784 54 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
785 :
786 18 : getProblem().addFVBC(bc_type, _pressure_name + "_" + inlet_bdy, params);
787 : ++velocity_pressure_counter;
788 18 : }
789 67 : else if (momentum_inlet_type == "flux-mass" || momentum_inlet_type == "flux-velocity")
790 : {
791 : {
792 : const std::string bc_type =
793 127 : _porous_medium_treatment ? "PWCNSFVMomentumFluxBC" : "WCNSFVMomentumFluxBC";
794 67 : InputParameters params = getFactory().getValidParams(bc_type);
795 :
796 67 : if (_flux_inlet_directions.size())
797 14 : params.set<Point>("direction") = _flux_inlet_directions[flux_bc_counter];
798 :
799 67 : params.set<MooseFunctorName>(NS::density) = _density_name;
800 201 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
801 67 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
802 67 : if (_porous_medium_treatment)
803 7 : params.set<MooseFunctorName>(NS::porosity) = _porosity_name;
804 67 : if (_flux_inlet_pps.size() < flux_bc_counter + 1)
805 0 : paramError("flux_inlet_pps",
806 0 : "More inlet flux BCs than inlet flux pps (" +
807 0 : std::to_string(_flux_inlet_pps.size()) + ")");
808 :
809 67 : if (momentum_inlet_type == "flux-mass")
810 : {
811 28 : params.set<PostprocessorName>("mdot_pp") = _flux_inlet_pps[flux_bc_counter];
812 112 : params.set<PostprocessorName>("area_pp") = "area_pp_" + inlet_bdy;
813 : }
814 : else
815 78 : params.set<PostprocessorName>("velocity_pp") = _flux_inlet_pps[flux_bc_counter];
816 :
817 192 : for (const auto d : make_range(dimension()))
818 250 : params.set<MooseFunctorName>(NS::velocity_vector[d]) = _velocity_names[d];
819 :
820 192 : for (const auto d : make_range(dimension()))
821 : {
822 125 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
823 250 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
824 :
825 250 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + inlet_bdy, params);
826 : }
827 67 : }
828 : {
829 67 : const std::string bc_type = "WCNSFVMassFluxBC";
830 67 : InputParameters params = getFactory().getValidParams(bc_type);
831 67 : params.set<MooseFunctorName>(NS::density) = _density_name;
832 134 : params.set<NonlinearVariableName>("variable") = _pressure_name;
833 201 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
834 :
835 67 : if (_flux_inlet_directions.size())
836 14 : params.set<Point>("direction") = _flux_inlet_directions[flux_bc_counter];
837 :
838 67 : if (momentum_inlet_type == "flux-mass")
839 : {
840 28 : params.set<PostprocessorName>("mdot_pp") = _flux_inlet_pps[flux_bc_counter];
841 112 : params.set<PostprocessorName>("area_pp") = "area_pp_" + inlet_bdy;
842 : }
843 : else
844 78 : params.set<PostprocessorName>("velocity_pp") = _flux_inlet_pps[flux_bc_counter];
845 :
846 192 : for (const auto d : make_range(dimension()))
847 250 : params.set<MooseFunctorName>(NS::velocity_vector[d]) = _velocity_names[d];
848 :
849 67 : getProblem().addFVBC(bc_type, _pressure_name + "_" + inlet_bdy, params);
850 67 : }
851 :
852 : // need to increment flux_bc_counter
853 : ++flux_bc_counter;
854 : }
855 : }
856 936 : }
857 :
858 : void
859 936 : WCNSFVFlowPhysics::addOutletBC()
860 : {
861 : // Check the BCs size
862 : unsigned int num_pressure_outlets = 0;
863 1768 : for (const auto & [bdy, momentum_outlet_type] : _momentum_outlet_types)
864 868 : if (momentum_outlet_type == "fixed-pressure" ||
865 36 : momentum_outlet_type == "fixed-pressure-zero-gradient")
866 823 : num_pressure_outlets++;
867 :
868 936 : if (num_pressure_outlets != _pressure_functors.size())
869 0 : paramError("pressure_functors",
870 0 : "Size (" + std::to_string(_pressure_functors.size()) +
871 : ") is not the same as the number of pressure outlet boundaries in "
872 0 : "'fixed-pressure/fixed-pressure-zero-gradient' (size " +
873 0 : std::to_string(num_pressure_outlets) + ")");
874 :
875 3744 : const std::string u_names[3] = {"u", "v", "w"};
876 1768 : for (const auto & [outlet_bdy, momentum_outlet_type] : _momentum_outlet_types)
877 : {
878 1655 : if (momentum_outlet_type == "zero-gradient" ||
879 823 : momentum_outlet_type == "fixed-pressure-zero-gradient")
880 : {
881 : {
882 36 : const std::string bc_type = _porous_medium_treatment ? "PINSFVMomentumAdvectionOutflowBC"
883 63 : : "INSFVMomentumAdvectionOutflowBC";
884 36 : InputParameters params = getFactory().getValidParams(bc_type);
885 108 : params.set<std::vector<BoundaryName>>("boundary") = {outlet_bdy};
886 36 : if (_porous_medium_treatment)
887 9 : params.set<MooseFunctorName>(NS::porosity) = _flow_porosity_functor_name;
888 36 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
889 36 : params.set<MooseFunctorName>(NS::density) = _density_name;
890 :
891 108 : for (unsigned int i = 0; i < dimension(); ++i)
892 144 : params.set<MooseFunctorName>(u_names[i]) = _velocity_names[i];
893 :
894 108 : for (const auto d : make_range(dimension()))
895 : {
896 144 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
897 144 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
898 :
899 144 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + outlet_bdy, params);
900 : }
901 36 : }
902 : }
903 :
904 868 : if (momentum_outlet_type == "fixed-pressure" ||
905 36 : momentum_outlet_type == "fixed-pressure-zero-gradient")
906 : {
907 823 : const std::string bc_type = "INSFVOutletPressureBC";
908 823 : InputParameters params = getFactory().getValidParams(bc_type);
909 823 : params.set<NonlinearVariableName>("variable") = _pressure_name;
910 1646 : params.set<MooseFunctorName>("functor") = libmesh_map_find(_pressure_functors, outlet_bdy);
911 2469 : params.set<std::vector<BoundaryName>>("boundary") = {outlet_bdy};
912 :
913 823 : getProblem().addFVBC(bc_type, _pressure_name + "_" + outlet_bdy, params);
914 823 : }
915 9 : else if (momentum_outlet_type == "zero-gradient")
916 : {
917 9 : const std::string bc_type = "INSFVMassAdvectionOutflowBC";
918 9 : InputParameters params = getFactory().getValidParams(bc_type);
919 9 : params.set<NonlinearVariableName>("variable") = _pressure_name;
920 9 : params.set<MooseFunctorName>(NS::density) = _density_name;
921 27 : params.set<std::vector<BoundaryName>>("boundary") = {outlet_bdy};
922 :
923 27 : for (const auto d : make_range(dimension()))
924 36 : params.set<MooseFunctorName>(u_names[d]) = _velocity_names[d];
925 :
926 9 : getProblem().addFVBC(bc_type, _pressure_name + "_" + outlet_bdy, params);
927 9 : }
928 : }
929 4680 : }
930 :
931 : void
932 936 : WCNSFVFlowPhysics::addWallsBC()
933 : {
934 3744 : const std::string u_names[3] = {"u", "v", "w"};
935 :
936 : // Count the number of fixed velocity wall boundaries (moving walls)
937 : unsigned int num_functor_walls = 0;
938 2583 : for (const auto & [boundary_name, momentum_wall_type] : _momentum_wall_types)
939 1647 : if (momentum_wall_type == "noslip")
940 1147 : num_functor_walls++;
941 936 : if (_momentum_wall_functors.size() && num_functor_walls != _momentum_wall_functors.size())
942 0 : paramError("momentum_wall_functors",
943 : "If any wall functors are specified, the number of boundaries requiring a momentum "
944 0 : "functor (" +
945 0 : std::to_string(num_functor_walls) + ") and the number of functors specified (" +
946 0 : std::to_string(_momentum_wall_functors.size()) + ") must match");
947 1122 : for (const auto & wall_functors : _momentum_wall_functors)
948 186 : if (wall_functors.second.size() != dimension())
949 0 : paramError("momentum_wall_functors",
950 0 : "Number of wall functors (" + std::to_string(wall_functors.second.size()) +
951 0 : ") must match dimension (" + std::to_string(dimension()) +
952 0 : ").\nFunctors currently specified:" + Moose::stringify(wall_functors.second));
953 :
954 2583 : for (const auto & [boundary_name, wall_type] : _momentum_wall_types)
955 : {
956 1647 : if (wall_type == "noslip")
957 : {
958 1147 : const std::string bc_type = "INSFVNoSlipWallBC";
959 1147 : InputParameters params = getFactory().getValidParams(bc_type);
960 3441 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
961 :
962 3441 : for (const auto d : make_range(dimension()))
963 : {
964 4588 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
965 : if (_momentum_wall_functors.count(boundary_name) == 0)
966 3844 : params.set<FunctionName>("function") = "0";
967 : else
968 744 : params.set<FunctionName>("function") = _momentum_wall_functors[boundary_name][d];
969 :
970 4588 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + boundary_name, params);
971 : }
972 1147 : }
973 500 : else if (wall_type == "wallfunction")
974 : {
975 10 : const std::string bc_type = "INSFVWallFunctionBC";
976 10 : InputParameters params = getFactory().getValidParams(bc_type);
977 10 : params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
978 10 : params.set<MooseFunctorName>(NS::density) = _density_name;
979 30 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
980 10 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
981 :
982 30 : for (const auto d : make_range(dimension()))
983 40 : params.set<MooseFunctorName>(u_names[d]) = _velocity_names[d];
984 :
985 30 : for (const auto d : make_range(dimension()))
986 : {
987 40 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
988 40 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
989 :
990 40 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + boundary_name, params);
991 : }
992 10 : }
993 490 : else if (wall_type == "slip")
994 : {
995 272 : const std::string bc_type = "INSFVNaturalFreeSlipBC";
996 272 : InputParameters params = getFactory().getValidParams(bc_type);
997 816 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
998 272 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
999 :
1000 816 : for (const auto d : make_range(dimension()))
1001 : {
1002 1088 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
1003 1088 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
1004 :
1005 1088 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + boundary_name, params);
1006 : }
1007 272 : }
1008 218 : else if (wall_type == "symmetry")
1009 : {
1010 : {
1011 : std::string bc_type;
1012 218 : if (_porous_medium_treatment)
1013 : bc_type = "PINSFVSymmetryVelocityBC";
1014 : else
1015 : bc_type = "INSFVSymmetryVelocityBC";
1016 :
1017 218 : InputParameters params = getFactory().getValidParams(bc_type);
1018 654 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
1019 :
1020 : MooseFunctorName viscosity_name = _dynamic_viscosity_name;
1021 218 : if (hasTurbulencePhysics())
1022 30 : viscosity_name = NS::total_viscosity;
1023 218 : params.set<MooseFunctorName>(NS::mu) = viscosity_name;
1024 218 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
1025 :
1026 654 : for (const auto d : make_range(dimension()))
1027 872 : params.set<MooseFunctorName>(u_names[d]) = _velocity_names[d];
1028 :
1029 654 : for (const auto d : make_range(dimension()))
1030 : {
1031 872 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
1032 872 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
1033 :
1034 872 : getProblem().addFVBC(bc_type, _velocity_names[d] + "_" + boundary_name, params);
1035 : }
1036 218 : }
1037 : {
1038 218 : const std::string bc_type = "INSFVSymmetryPressureBC";
1039 218 : InputParameters params = getFactory().getValidParams(bc_type);
1040 436 : params.set<NonlinearVariableName>("variable") = _pressure_name;
1041 654 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
1042 :
1043 218 : getProblem().addFVBC(bc_type, _pressure_name + "_" + boundary_name, params);
1044 218 : }
1045 : }
1046 : }
1047 4680 : }
1048 :
1049 : void
1050 936 : WCNSFVFlowPhysics::addSeparatorBC()
1051 : {
1052 936 : if (_hydraulic_separators.size())
1053 : {
1054 9 : std::string bc_type = "INSFVVelocityHydraulicSeparatorBC";
1055 9 : InputParameters params = getFactory().getValidParams(bc_type);
1056 9 : params.set<std::vector<BoundaryName>>("boundary") = _hydraulic_separators;
1057 9 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
1058 :
1059 36 : for (const auto d : make_range(dimension()))
1060 : {
1061 36 : params.set<NonlinearVariableName>("variable") = _velocity_names[d];
1062 36 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
1063 54 : getProblem().addFVBC(bc_type, prefix() + _velocity_names[d] + "_separators", params);
1064 : }
1065 :
1066 : bc_type = "INSFVScalarFieldSeparatorBC";
1067 9 : params = getFactory().getValidParams(bc_type);
1068 9 : params.set<std::vector<BoundaryName>>("boundary") = _hydraulic_separators;
1069 18 : params.set<NonlinearVariableName>("variable") = _pressure_name;
1070 18 : getProblem().addFVBC(bc_type, prefix() + _pressure_name + "_separators", params);
1071 9 : }
1072 936 : }
1073 :
1074 : void
1075 960 : WCNSFVFlowPhysics::addUserObjects()
1076 : {
1077 : // Rhie Chow user object for interpolation velocities
1078 960 : addRhieChowUserObjects();
1079 954 : }
1080 :
1081 : void
1082 954 : WCNSFVFlowPhysics::addCorrectors()
1083 : {
1084 954 : if (!_has_flow_equations)
1085 : return;
1086 :
1087 : // Pressure pin
1088 1890 : if (getParam<bool>("pin_pressure"))
1089 : {
1090 298 : const auto pin_type = getParam<MooseEnum>("pinned_pressure_type");
1091 149 : std::string object_type = "NSPressurePin";
1092 :
1093 : // No need for the user object
1094 149 : if (pin_type == "point-value" || pin_type == "average")
1095 : return;
1096 :
1097 : // Create the average value postprocessor if needed
1098 18 : if (pin_type == "average-uo")
1099 : {
1100 : // Volume average by default, but we could do inlet or outlet for example
1101 9 : InputParameters params = getFactory().getValidParams("ElementAverageValue");
1102 27 : params.set<std::vector<VariableName>>("variable") = {_pressure_name};
1103 9 : assignBlocks(params, _blocks);
1104 27 : params.set<std::vector<OutputName>>("outputs") = {"none"};
1105 18 : getProblem().addPostprocessor("ElementAverageValue", "ns_pressure_average", params);
1106 9 : }
1107 :
1108 18 : InputParameters params = getFactory().getValidParams(object_type);
1109 18 : if (pin_type == "point-value" || pin_type == "point-value-uo")
1110 18 : params.set<MooseEnum>("pin_type") = "point-value";
1111 : else
1112 18 : params.set<MooseEnum>("pin_type") = "average";
1113 :
1114 54 : params.set<PostprocessorName>("phi0") = getParam<PostprocessorName>("pinned_pressure_value");
1115 18 : params.set<NonlinearVariableName>("variable") = _pressure_name;
1116 18 : if (pin_type == "point-value" || pin_type == "point-value-uo")
1117 18 : params.set<Point>("point") = getParam<Point>("pinned_pressure_point");
1118 9 : else if (pin_type == "average-uo")
1119 18 : params.set<PostprocessorName>("pressure_average") = "ns_pressure_average";
1120 :
1121 36 : getProblem().addUserObject(object_type, prefix() + "ins_mass_pressure_pin", params);
1122 167 : }
1123 9 : }
1124 :
1125 : bool
1126 1261 : WCNSFVFlowPhysics::hasForchheimerFriction() const
1127 : {
1128 1399 : for (const auto block_i : index_range(_friction_types))
1129 1254 : for (const auto type_i : index_range(_friction_types[block_i]))
1130 2232 : if (MooseUtils::toUpper(_friction_types[block_i][type_i]) == "FORCHHEIMER")
1131 : return true;
1132 : return false;
1133 : }
1134 :
1135 : unsigned short
1136 8235 : WCNSFVFlowPhysics::getNumberAlgebraicGhostingLayersNeeded() const
1137 : {
1138 8235 : auto ghost_layers = WCNSFVFlowPhysicsBase::getNumberAlgebraicGhostingLayersNeeded();
1139 14971 : if (_porous_medium_treatment && isParamValid("porosity_smoothing_layers"))
1140 1008 : ghost_layers = std::max(getParam<unsigned short>("porosity_smoothing_layers"), ghost_layers);
1141 3368 : if ((_porous_medium_treatment &&
1142 22828 : getParam<MooseEnum>("porosity_interface_pressure_treatment") != "automatic") ||
1143 27317 : getParam<MooseEnum>("momentum_face_interpolation") == "skewness-corrected" ||
1144 23949 : getParam<MooseEnum>("pressure_face_interpolation") == "skewness-corrected")
1145 756 : ghost_layers = std::max(ghost_layers, (unsigned short)3);
1146 8235 : return ghost_layers;
1147 : }
1148 :
1149 : void
1150 960 : WCNSFVFlowPhysics::addRhieChowUserObjects()
1151 : {
1152 : mooseAssert(dimension(), "0-dimension not supported");
1153 :
1154 : // First make sure that we only add this object once
1155 : // Potential cases:
1156 : // - there is a flow physics, and an advection one (UO should be added by one)
1157 : // - there is only an advection physics (UO should be created)
1158 : // - there are two advection physics on different blocks with set velocities (first one picks)
1159 : // Counting RC UOs defined on the same blocks seems to be the most fool proof option
1160 : std::vector<UserObject *> objs;
1161 : getProblem()
1162 : .theWarehouse()
1163 960 : .query()
1164 960 : .condition<AttribSystem>("UserObject")
1165 1920 : .condition<AttribThread>(0)
1166 : .queryInto(objs);
1167 : bool have_matching_rc_uo = false;
1168 1068 : for (const auto & obj : objs)
1169 108 : if (const auto * const rc_obj = dynamic_cast<INSFVRhieChowInterpolator *>(obj); rc_obj)
1170 : // Latter check is for whether one of the RC user object is defined everywhere
1171 0 : if (rc_obj->blocks() == _blocks || (rc_obj->blocks().size() == 0 || _blocks.size() == 0))
1172 : {
1173 : have_matching_rc_uo = true;
1174 0 : _rc_uo_name = rc_obj->name();
1175 : break;
1176 : }
1177 :
1178 : if (have_matching_rc_uo)
1179 : return;
1180 :
1181 : _rc_uo_name =
1182 960 : _porous_medium_treatment ? +"pins_rhie_chow_interpolator" : "ins_rhie_chow_interpolator";
1183 :
1184 3822 : const std::string u_names[3] = {"u", "v", "w"};
1185 : const auto object_type =
1186 960 : _porous_medium_treatment ? "PINSFVRhieChowInterpolator" : "INSFVRhieChowInterpolator";
1187 :
1188 960 : auto params = getFactory().getValidParams(object_type);
1189 960 : assignBlocks(params, _blocks);
1190 2871 : for (unsigned int d = 0; d < dimension(); ++d)
1191 3822 : params.set<VariableName>(u_names[d]) = _velocity_names[d];
1192 :
1193 1920 : params.set<VariableName>("pressure") = _pressure_name;
1194 :
1195 960 : if (_porous_medium_treatment)
1196 : {
1197 443 : params.set<MooseFunctorName>(NS::porosity) = _porosity_name;
1198 443 : unsigned short smoothing_layers = isParamValid("porosity_smoothing_layers")
1199 779 : ? getParam<unsigned short>("porosity_smoothing_layers")
1200 611 : : 0;
1201 443 : params.set<unsigned short>("smoothing_layers") = smoothing_layers;
1202 : }
1203 :
1204 960 : if (!_has_flow_equations)
1205 : {
1206 13 : checkRhieChowFunctorsDefined();
1207 18 : params.set<MooseFunctorName>("a_u") = "ax";
1208 18 : params.set<MooseFunctorName>("a_v") = "ay";
1209 18 : params.set<MooseFunctorName>("a_w") = "az";
1210 : }
1211 :
1212 956 : params.applySpecificParameters(parameters(), INSFVRhieChowInterpolator::listOfCommonParams());
1213 956 : getProblem().addUserObject(object_type, _rc_uo_name, params);
1214 4770 : }
1215 :
1216 : void
1217 13 : WCNSFVFlowPhysics::checkRhieChowFunctorsDefined() const
1218 : {
1219 26 : if (!getProblem().hasFunctor("ax", /*thread_id=*/0))
1220 2 : mooseError("Rhie Chow coefficient ax must be provided for advection by auxiliary velocities");
1221 31 : if (dimension() >= 2 && !getProblem().hasFunctor("ay", /*thread_id=*/0))
1222 2 : mooseError("Rhie Chow coefficient ay must be provided for advection by auxiliary velocities");
1223 9 : if (dimension() == 3 && !getProblem().hasFunctor("az", /*thread_id=*/0))
1224 0 : mooseError("Rhie Chow coefficient az must be provided for advection by auxiliary velocities");
1225 9 : }
1226 :
1227 : MooseFunctorName
1228 0 : WCNSFVFlowPhysics::getLinearFrictionCoefName() const
1229 : {
1230 : // Check all blocks. If more than one block, they would need to be consolidated #include in
1231 : // a single functor material. We won't implement this for now
1232 0 : if (_friction_types.empty())
1233 : return "";
1234 0 : else if (_friction_types.size() == 1)
1235 : {
1236 0 : for (const auto & type_i : index_range(_friction_types[0]))
1237 : {
1238 0 : const auto upper_name = MooseUtils::toUpper(_friction_types[0][type_i]);
1239 0 : if (upper_name == "DARCY")
1240 : return _friction_coeffs[0][type_i];
1241 : }
1242 : // No linear type found
1243 : return "";
1244 : }
1245 0 : else if (_friction_types.size() > 1)
1246 : {
1247 : bool linear_friction_factor_found = false;
1248 : MooseFunctorName linear_friction_factor;
1249 0 : for (const auto block_i : index_range(_friction_types))
1250 0 : for (const auto type_i : index_range(_friction_types[block_i]))
1251 : {
1252 0 : const auto upper_name = MooseUtils::toUpper(_friction_types[block_i][type_i]);
1253 0 : if (upper_name == "DARCY" && !linear_friction_factor_found)
1254 : {
1255 : linear_friction_factor_found = true;
1256 0 : linear_friction_factor = _friction_types[block_i][type_i];
1257 : }
1258 0 : else if (upper_name == "DARCY" && !linear_friction_factor_found)
1259 0 : if (linear_friction_factor != _friction_types[block_i][type_i])
1260 0 : mooseError("Multiple linear friction factor with different names have been specified. "
1261 : "This is not currently supported as a single name should be retrievable. "
1262 : "Use a PiecewiseByBlockFunctorMaterial to consolidate them.");
1263 : }
1264 0 : if (linear_friction_factor_found)
1265 : return linear_friction_factor;
1266 : else
1267 : return "";
1268 : }
1269 0 : mooseError("Should not get here");
1270 : }
|