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