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 "WCNSLinearFVFlowPhysics.h"
11 : #include "WCNSFVTurbulencePhysics.h"
12 : #include "NSFVBase.h"
13 : #include "INSFVMomentumAdvection.h"
14 : #include "RhieChowMassFlux.h"
15 : #include "INSFVTimeKernel.h"
16 : #include "MapConversionUtils.h"
17 : #include "NSFVUtils.h"
18 : #include "NS.h"
19 :
20 : registerWCNSFVFlowPhysicsBaseTasks("NavierStokesApp", WCNSLinearFVFlowPhysics);
21 : registerMooseAction("NavierStokesApp", WCNSLinearFVFlowPhysics, "add_interpolation_method_physics");
22 : registerMooseAction("NavierStokesApp", WCNSLinearFVFlowPhysics, "add_linear_fv_kernel");
23 : registerMooseAction("NavierStokesApp", WCNSLinearFVFlowPhysics, "add_linear_fv_bc");
24 : registerMooseAction("NavierStokesApp", WCNSLinearFVFlowPhysics, "add_functor_material");
25 :
26 : InputParameters
27 169 : WCNSLinearFVFlowPhysics::validParams()
28 : {
29 169 : InputParameters params = WCNSFVFlowPhysicsBase::validParams();
30 169 : params.addClassDescription(
31 : "Define the Navier Stokes weakly-compressible equations with the linear "
32 : "solver implementation of the SIMPLE scheme");
33 338 : params.set<MooseEnum>("momentum_advection_interpolation") = NS::fvAdvectedInterpolationMethods();
34 338 : params.addParam<InterpolationMethodName>(
35 : "momentum_advection_interpolation_method_name",
36 : "Name of an externally defined FVInterpolationMethod to use for momentum advection. When "
37 : "provided, this overrides 'momentum_advection_interpolation'.");
38 :
39 338 : params.addParam<bool>(
40 338 : "orthogonality_correction", false, "Whether to use orthogonality correction");
41 338 : params.renameParam("orthogonality_correction", "use_nonorthogonal_correction", "");
42 338 : params.addParam<MooseEnum>(
43 : "pressure_diffusion_interpolation",
44 338 : NS::fvFaceInterpolationMethods(),
45 : "The face interpolation method for Ainv in the pressure correction diffusion term.");
46 338 : params.addParamNamesToGroup("pressure_diffusion_interpolation", "Numerical scheme");
47 169 : params.set<unsigned short>("ghost_layers") = 1;
48 :
49 : // This will be adapted based on the dimension
50 338 : params.set<std::vector<SolverSystemName>>("system_names") = {
51 1183 : "u_system", "v_system", "w_system", "pressure_system"};
52 :
53 : // Implemented in the executioner
54 169 : params.suppressParameter<MooseEnum>("pinned_pressure_type");
55 169 : params.suppressParameter<Point>("pinned_pressure_point");
56 169 : params.suppressParameter<PostprocessorName>("pinned_pressure_value");
57 :
58 : // Not supported
59 169 : params.suppressParameter<bool>("add_flow_equations");
60 169 : params.set<bool>("porous_medium_treatment") = false;
61 338 : params.suppressParameter<bool>("porous_medium_treatment");
62 338 : params.set<MooseFunctorName>("porosity") = "1";
63 169 : params.suppressParameter<MooseFunctorName>("porosity");
64 169 : params.suppressParameter<MooseEnum>("mu_interp_method");
65 : // Not needed
66 169 : params.suppressParameter<bool>("add_flow_equations");
67 169 : params.suppressParameter<MooseEnum>("preconditioning");
68 :
69 : // No other options so far
70 338 : params.set<MooseEnum>("velocity_interpolation") = "rc";
71 169 : params.suppressParameter<MooseEnum>("velocity_interpolation");
72 :
73 : // Rhie-Chow
74 169 : params.transferParam<MooseEnum>(RhieChowMassFlux::validParams(), "pressure_projection_method");
75 338 : params.addParamNamesToGroup("momentum_advection_interpolation_method_name", "Numerical scheme");
76 :
77 169 : return params;
78 0 : }
79 :
80 169 : WCNSLinearFVFlowPhysics::WCNSLinearFVFlowPhysics(const InputParameters & parameters)
81 : : WCNSFVFlowPhysicsBase(parameters),
82 338 : _non_orthogonal_correction(getParam<bool>("orthogonality_correction"))
83 : {
84 169 : addRequiredPhysicsTask("add_interpolation_method_physics");
85 :
86 169 : if (_porous_medium_treatment)
87 0 : paramError("porous_medium_treatment", "Porous media unsupported");
88 169 : if (!_has_flow_equations)
89 0 : mooseError("Not supported");
90 :
91 169 : if (_hydraulic_separators.size())
92 0 : paramError("hydraulic_separator_sidesets",
93 : "Flow separators are not supported yet for linearFV!");
94 338 : if (getParam<bool>("pin_pressure"))
95 0 : paramError("pin_pressure",
96 : "Pressure pinning is implemented in the executioner for the linear finite volume "
97 : "segregated solves");
98 169 : }
99 :
100 : void
101 169 : WCNSLinearFVFlowPhysics::addFVInterpolationMethods()
102 : {
103 507 : if (!_has_flow_equations || isParamValid("momentum_advection_interpolation_method_name"))
104 : return;
105 :
106 489 : addFVAdvectedInterpolationMethod(getParam<MooseEnum>("momentum_advection_interpolation"));
107 : }
108 :
109 : void
110 169 : WCNSLinearFVFlowPhysics::initializePhysicsAdditional()
111 : {
112 169 : WCNSFVFlowPhysicsBase::initializePhysicsAdditional();
113 : // TODO Add support for multi-system by either:
114 : // - creating the problem in the Physics or,
115 : // - checking that the right systems are being created
116 169 : getProblem().needSolutionState(2, Moose::SolutionIterationType::Nonlinear);
117 : // TODO Ban all other nonlinear Physics for now
118 :
119 : // Fix the default system names if using a different dimension
120 338 : if (!isParamSetByUser("system_name"))
121 : {
122 169 : if (dimension() == 1)
123 128 : _system_names = {"u_system", "pressure_system"};
124 137 : else if (dimension() == 2)
125 655 : _system_names = {"u_system", "v_system", "pressure_system"};
126 : }
127 169 : }
128 :
129 : void
130 169 : WCNSLinearFVFlowPhysics::addSolverVariables()
131 : {
132 169 : if (!_has_flow_equations)
133 0 : return;
134 :
135 481 : for (const auto d : make_range(dimension()))
136 624 : saveSolverVariableName(_velocity_names[d]);
137 169 : saveSolverVariableName(_pressure_name);
138 :
139 169 : const std::vector<std::string> v_short = {"u", "v", "w"};
140 :
141 : // Check number of variables
142 169 : if (_velocity_names.size() != dimension() && _velocity_names.size() != 3)
143 0 : paramError("velocity_variable",
144 0 : "The number of velocity variable names supplied to the NSFVAction is not " +
145 0 : Moose::stringify(dimension()) + " (mesh dimension)" +
146 0 : ((dimension() == 3) ? "" : " or 3!") + "\nVelocity variables " +
147 0 : Moose::stringify(_velocity_names));
148 :
149 : // Velocities
150 481 : for (const auto d : make_range(dimension()))
151 : {
152 624 : if (!shouldCreateVariable(_velocity_names[d], _blocks, /*error if aux*/ true))
153 0 : reportPotentiallyMissedParameters({"system_names"}, "MooseLinearVariableFVReal");
154 312 : else if (_define_variables)
155 : {
156 312 : std::string variable_type = "MooseLinearVariableFVReal";
157 :
158 312 : auto params = getFactory().getValidParams(variable_type);
159 312 : assignBlocks(params, _blocks);
160 624 : params.set<SolverSystemName>("solver_sys") = getSolverSystem(_velocity_names[d]);
161 :
162 312 : getProblem().addVariable(variable_type, _velocity_names[d], params);
163 312 : }
164 : else
165 0 : paramError("velocity_variable",
166 0 : "Variable (" + _velocity_names[d] +
167 : ") supplied to the WCNSLinearFVFlowPhysics does not exist!");
168 : }
169 :
170 : // Pressure
171 338 : if (!shouldCreateVariable(_pressure_name, _blocks, /*error if aux*/ true))
172 0 : reportPotentiallyMissedParameters({"system_names"}, "MooseLinearVariableFVReal");
173 169 : else if (_define_variables)
174 : {
175 : const auto pressure_type = "MooseLinearVariableFVReal";
176 :
177 169 : auto params = getFactory().getValidParams(pressure_type);
178 169 : assignBlocks(params, _blocks);
179 338 : params.set<SolverSystemName>("solver_sys") = getSolverSystem(_pressure_name);
180 :
181 169 : getProblem().addVariable(pressure_type, _pressure_name, params);
182 169 : }
183 : else
184 0 : paramError("pressure_variable",
185 0 : "Variable (" + _pressure_name +
186 : ") supplied to the WCNSLinearFVFlowPhysics does not exist!");
187 169 : }
188 :
189 : void
190 169 : WCNSLinearFVFlowPhysics::addFVKernels()
191 : {
192 169 : if (!_has_flow_equations)
193 : return;
194 :
195 : // Pressure correction equation: divergence of momentum
196 169 : addPressureCorrectionKernels();
197 :
198 : // Momentum equation: time derivative
199 169 : if (isTransient())
200 31 : addMomentumTimeKernels();
201 :
202 : // Momentum equation: flux terms
203 169 : addMomentumFluxKernels();
204 :
205 : // Momentum equation: pressure term
206 169 : addMomentumPressureKernels();
207 :
208 : // Momentum equation: friction term
209 169 : if (_friction_types.size())
210 16 : addMomentumFrictionKernels();
211 :
212 : // Momentum equation: gravity source term
213 169 : addMomentumGravityKernels();
214 :
215 : // Momentum equation: boussinesq approximation
216 338 : if (getParam<bool>("boussinesq_approximation"))
217 8 : addMomentumBoussinesqKernels();
218 : }
219 :
220 : void
221 169 : WCNSLinearFVFlowPhysics::addPressureCorrectionKernels()
222 : {
223 : {
224 169 : std::string kernel_type = "LinearFVPressureCorrectionDiffusion";
225 169 : std::string kernel_name = prefix() + "p_diffusion";
226 :
227 169 : InputParameters params = getFactory().getValidParams(kernel_type);
228 169 : assignBlocks(params, _blocks);
229 338 : params.set<LinearVariableName>("variable") = _pressure_name;
230 338 : params.set<MooseFunctorName>("diffusion_tensor") = "Ainv";
231 169 : params.set<bool>("use_nonorthogonal_correction") = _non_orthogonal_correction;
232 :
233 169 : getProblem().addLinearFVKernel(kernel_type, kernel_name, params);
234 169 : }
235 : {
236 169 : std::string kernel_type = "LinearFVDivergence";
237 169 : std::string kernel_name = prefix() + "HbyA_divergence";
238 :
239 169 : InputParameters params = getFactory().getValidParams(kernel_type);
240 169 : assignBlocks(params, _blocks);
241 338 : params.set<LinearVariableName>("variable") = _pressure_name;
242 338 : params.set<MooseFunctorName>("face_flux") = "HbyA";
243 169 : params.set<bool>("force_boundary_execution") = true;
244 :
245 169 : getProblem().addLinearFVKernel(kernel_type, kernel_name, params);
246 169 : }
247 169 : }
248 :
249 : void
250 31 : WCNSLinearFVFlowPhysics::addMomentumTimeKernels()
251 : {
252 31 : std::string kernel_type = "LinearFVTimeDerivative";
253 31 : std::string kernel_name = prefix() + "ins_momentum_time";
254 :
255 31 : InputParameters params = getFactory().getValidParams(kernel_type);
256 31 : assignBlocks(params, _blocks);
257 31 : params.set<MooseFunctorName>("factor") = _density_name;
258 :
259 116 : for (const auto d : make_range(dimension()))
260 : {
261 108 : params.set<LinearVariableName>("variable") = _velocity_names[d];
262 108 : if (shouldCreateTimeDerivative(_velocity_names[d], _blocks, /*error if already defined*/ false))
263 108 : getProblem().addLinearFVKernel(kernel_type, kernel_name + "_" + NS::directions[d], params);
264 : }
265 62 : }
266 :
267 : void
268 169 : WCNSLinearFVFlowPhysics::addMomentumFluxKernels()
269 : {
270 : const auto momentum_advection_method_name =
271 169 : isParamValid("momentum_advection_interpolation_method_name")
272 169 : ? getParam<InterpolationMethodName>("momentum_advection_interpolation_method_name")
273 : : InterpolationMethodName(
274 670 : std::string(getParam<MooseEnum>("momentum_advection_interpolation")));
275 :
276 676 : const std::string u_names[3] = {"u", "v", "w"};
277 169 : std::string kernel_type = "LinearWCNSFVMomentumFlux";
278 169 : std::string kernel_name = prefix() + "ins_momentum_flux_";
279 :
280 169 : InputParameters params = getFactory().getValidParams(kernel_type);
281 169 : assignBlocks(params, _blocks);
282 169 : if (!_turbulence_physics)
283 139 : params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
284 : else
285 60 : params.set<MooseFunctorName>(NS::mu) = NS::mu_eff;
286 :
287 169 : params.set<UserObjectName>("rhie_chow_user_object") = rhieChowUOName();
288 169 : params.set<InterpolationMethodName>("advected_interp_method_name") =
289 : momentum_advection_method_name;
290 169 : params.set<bool>("use_nonorthogonal_correction") = _non_orthogonal_correction;
291 169 : params.set<bool>("use_deviatoric_terms") = includeSymmetrizedViscousStress();
292 :
293 481 : for (unsigned int i = 0; i < dimension(); ++i)
294 624 : params.set<SolverVariableName>(u_names[i]) = _velocity_names[i];
295 :
296 650 : for (const auto d : make_range(dimension()))
297 : {
298 624 : params.set<LinearVariableName>("variable") = _velocity_names[d];
299 624 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
300 :
301 624 : getProblem().addLinearFVKernel(kernel_type, kernel_name + NS::directions[d], params);
302 : }
303 1014 : }
304 :
305 : void
306 169 : WCNSLinearFVFlowPhysics::addMomentumPressureKernels()
307 : {
308 169 : std::string kernel_type = "LinearFVMomentumPressure";
309 169 : std::string kernel_name = prefix() + "ins_momentum_pressure_";
310 :
311 169 : InputParameters params = getFactory().getValidParams(kernel_type);
312 169 : assignBlocks(params, _blocks);
313 338 : params.set<VariableName>("pressure") = _pressure_name;
314 :
315 650 : for (const auto d : make_range(dimension()))
316 : {
317 312 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
318 624 : params.set<LinearVariableName>("variable") = _velocity_names[d];
319 624 : getProblem().addLinearFVKernel(kernel_type, kernel_name + NS::directions[d], params);
320 : }
321 338 : }
322 :
323 : void
324 16 : WCNSLinearFVFlowPhysics::addMomentumFrictionKernels()
325 : {
326 16 : unsigned int num_friction_blocks = _friction_blocks.size();
327 : unsigned int num_used_blocks = num_friction_blocks ? num_friction_blocks : 1;
328 :
329 16 : const std::string kernel_type = "LinearFVMomentumFriction";
330 16 : InputParameters params = getFactory().getValidParams(kernel_type);
331 :
332 32 : for (const auto block_i : make_range(num_used_blocks))
333 : {
334 16 : std::string block_name = "";
335 16 : if (num_friction_blocks)
336 : {
337 0 : params.set<std::vector<SubdomainName>>("block") = _friction_blocks[block_i];
338 0 : block_name = Moose::stringify(_friction_blocks[block_i]);
339 : }
340 : else
341 : {
342 16 : assignBlocks(params, _blocks);
343 32 : block_name = std::to_string(block_i);
344 : }
345 :
346 48 : for (const auto d : make_range(dimension()))
347 : {
348 64 : params.set<LinearVariableName>("variable") = _velocity_names[d];
349 32 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
350 64 : for (unsigned int type_i = 0; type_i < _friction_types[block_i].size(); ++type_i)
351 : {
352 32 : const auto upper_name = MooseUtils::toUpper(_friction_types[block_i][type_i]);
353 32 : if (upper_name == "DARCY")
354 : {
355 32 : params.set<MooseFunctorName>(NS::mu) = _dynamic_viscosity_name;
356 64 : params.set<MooseFunctorName>("Darcy_name") = _friction_coeffs[block_i][type_i];
357 : }
358 : else
359 0 : paramError("friction_types",
360 : "Friction type '",
361 : _friction_types[block_i][type_i],
362 : "' is not implemented");
363 : }
364 :
365 64 : getProblem().addLinearFVKernel(kernel_type,
366 96 : prefix() + "momentum_friction_" + block_name + "_" +
367 : NS::directions[d],
368 : params);
369 : }
370 : }
371 32 : }
372 :
373 : void
374 169 : WCNSLinearFVFlowPhysics::addMomentumGravityKernels()
375 : {
376 338 : if (parameters().isParamValid("gravity") && !_solve_for_dynamic_pressure)
377 : {
378 161 : std::string kernel_type = "LinearFVSource";
379 161 : std::string kernel_name = prefix() + "ins_momentum_gravity_";
380 :
381 161 : InputParameters params = getFactory().getValidParams(kernel_type);
382 161 : assignBlocks(params, _blocks);
383 322 : const auto gravity_vector = getParam<RealVectorValue>("gravity");
384 805 : const std::vector<std::string> comp_axis({"x", "y", "z"});
385 :
386 457 : for (const auto d : make_range(dimension()))
387 296 : if (gravity_vector(d) != 0)
388 : {
389 4 : params.set<MooseFunctorName>("source_density") = "rho_g_" + comp_axis[d];
390 2 : params.set<LinearVariableName>("variable") = _velocity_names[d];
391 :
392 2 : getProblem().addLinearFVKernel(kernel_type, kernel_name + NS::directions[d], params);
393 : }
394 161 : }
395 491 : }
396 :
397 : void
398 8 : WCNSLinearFVFlowPhysics::addMomentumBoussinesqKernels()
399 : {
400 8 : if (_compressibility == "weakly-compressible")
401 0 : paramError("boussinesq_approximation",
402 : "We cannot use boussinesq approximation while running in weakly-compressible mode!");
403 :
404 8 : std::string kernel_type = "LinearFVMomentumBoussinesq";
405 8 : std::string kernel_name = prefix() + "ins_momentum_boussinesq_";
406 :
407 8 : InputParameters params = getFactory().getValidParams(kernel_type);
408 8 : assignBlocks(params, _blocks);
409 8 : params.set<VariableName>(NS::T_fluid) = _fluid_temperature_name;
410 8 : params.set<MooseFunctorName>(NS::density) = _density_gravity_name;
411 16 : params.set<RealVectorValue>("gravity") = getParam<RealVectorValue>("gravity");
412 16 : params.set<Real>("ref_temperature") = getParam<Real>("ref_temperature");
413 24 : params.set<MooseFunctorName>("alpha_name") = getParam<MooseFunctorName>("thermal_expansion");
414 :
415 32 : for (const auto d : make_range(dimension()))
416 : {
417 16 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
418 32 : params.set<LinearVariableName>("variable") = _velocity_names[d];
419 :
420 32 : getProblem().addLinearFVKernel(kernel_type, kernel_name + NS::directions[d], params);
421 : }
422 16 : }
423 :
424 : void
425 169 : WCNSLinearFVFlowPhysics::addInletBC()
426 : {
427 : // Check the size of the BC parameters
428 : unsigned int num_velocity_functor_inlets = 0;
429 329 : for (const auto & [bdy, momentum_inlet_type] : _momentum_inlet_types)
430 160 : if (momentum_inlet_type == "fixed-velocity" || momentum_inlet_type == "fixed-pressure")
431 160 : num_velocity_functor_inlets++;
432 :
433 169 : if (num_velocity_functor_inlets != _momentum_inlet_functors.size())
434 0 : paramError("momentum_inlet_functors",
435 0 : "Size (" + std::to_string(_momentum_inlet_functors.size()) +
436 : ") is not the same as the number of entries in the momentum_inlet_types "
437 0 : "subvector for fixed-velocities/pressures functors (size " +
438 0 : std::to_string(num_velocity_functor_inlets) + ")");
439 :
440 : unsigned int velocity_pressure_counter = 0;
441 329 : for (const auto & [inlet_bdy, momentum_inlet_type] : _momentum_inlet_types)
442 : {
443 160 : if (momentum_inlet_type == "fixed-velocity")
444 : {
445 160 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorDirichletBC";
446 160 : InputParameters params = getFactory().getValidParams(bc_type);
447 480 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
448 160 : if (_momentum_inlet_functors.size() < velocity_pressure_counter + 1)
449 0 : paramError("momentum_inlet_functors",
450 0 : "More non-flux inlets than inlet functors (" +
451 0 : std::to_string(_momentum_inlet_functors.size()) + ")");
452 :
453 : // Check that enough functors have been provided for the dimension of the problem
454 160 : const auto momentum_functors = libmesh_map_find(_momentum_inlet_functors, inlet_bdy);
455 160 : if (momentum_functors.size() < dimension())
456 0 : paramError("momentum_inlet_functors",
457 0 : "Subvector for boundary '" + inlet_bdy + "' (size " +
458 0 : std::to_string(momentum_functors.size()) +
459 0 : ") is not the same size as the number of dimensions of the physics (" +
460 0 : std::to_string(dimension()) + ")");
461 :
462 454 : for (const auto d : make_range(dimension()))
463 : {
464 588 : params.set<LinearVariableName>("variable") = _velocity_names[d];
465 588 : params.set<MooseFunctorName>("functor") = momentum_functors[d];
466 :
467 588 : getProblem().addLinearFVBC(bc_type, _velocity_names[d] + "_" + inlet_bdy, params);
468 : }
469 : ++velocity_pressure_counter;
470 :
471 : // Add the two term BC expansion for pressure if requested
472 320 : if (getParam<bool>("pressure_two_term_bc_expansion"))
473 : {
474 40 : const std::string bc_type = "LinearFVExtrapolatedPressureBC";
475 40 : InputParameters params = getFactory().getValidParams(bc_type);
476 120 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
477 80 : params.set<LinearVariableName>("variable") = _pressure_name;
478 40 : params.set<bool>("use_two_term_expansion") = true;
479 40 : getProblem().addLinearFVBC(bc_type,
480 80 : _pressure_name + "_extrapolation_inlet_" +
481 40 : Moose::stringify(inlet_bdy),
482 : params);
483 40 : }
484 160 : }
485 0 : else if (momentum_inlet_type == "fixed-pressure")
486 : {
487 0 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorDirichletBC";
488 0 : InputParameters params = getFactory().getValidParams(bc_type);
489 0 : params.set<LinearVariableName>("variable") = _pressure_name;
490 0 : if (_momentum_inlet_functors.size() < velocity_pressure_counter + 1)
491 0 : paramError("momentum_inlet_functors",
492 0 : "More non-flux inlets than inlet functors (" +
493 0 : std::to_string(_momentum_inlet_functors.size()) + ")");
494 :
495 0 : params.set<MooseFunctorName>("functor") =
496 0 : libmesh_map_find(_momentum_inlet_functors, inlet_bdy)[0];
497 0 : params.set<std::vector<BoundaryName>>("boundary") = {inlet_bdy};
498 :
499 0 : getProblem().addLinearFVBC(bc_type, _pressure_name + "_" + inlet_bdy, params);
500 : ++velocity_pressure_counter;
501 0 : }
502 : else
503 0 : mooseError("Unsupported inlet boundary condition type: ", momentum_inlet_type);
504 : }
505 169 : }
506 :
507 : void
508 169 : WCNSLinearFVFlowPhysics::addOutletBC()
509 : {
510 : // Check the BCs size
511 : unsigned int num_pressure_outlets = 0;
512 317 : for (const auto & [bdy, momentum_outlet_type] : _momentum_outlet_types)
513 154 : if (momentum_outlet_type == "fixed-pressure" ||
514 6 : momentum_outlet_type == "fixed-pressure-zero-gradient")
515 148 : num_pressure_outlets++;
516 :
517 169 : if (num_pressure_outlets != _pressure_functors.size())
518 0 : paramError("pressure_functors",
519 0 : "Size (" + std::to_string(_pressure_functors.size()) +
520 : ") is not the same as the number of pressure outlet boundaries in "
521 0 : "'fixed-pressure/fixed-pressure-zero-gradient' (size " +
522 0 : std::to_string(num_pressure_outlets) + ")");
523 :
524 676 : const std::string u_names[3] = {"u", "v", "w"};
525 317 : for (const auto & [outlet_bdy, momentum_outlet_type] : _momentum_outlet_types)
526 : {
527 : // Zero tangeantial gradient condition on velocity
528 154 : if (momentum_outlet_type == "zero-gradient" || momentum_outlet_type == "fixed-pressure" ||
529 6 : momentum_outlet_type == "fixed-pressure-zero-gradient")
530 : {
531 148 : const std::string bc_type = "LinearFVAdvectionDiffusionOutflowBC";
532 148 : InputParameters params = getFactory().getValidParams(bc_type);
533 444 : params.set<std::vector<BoundaryName>>("boundary") = {outlet_bdy};
534 296 : params.set<bool>("use_two_term_expansion") = getParam<bool>("momentum_two_term_bc_expansion");
535 :
536 418 : for (const auto d : make_range(dimension()))
537 : {
538 540 : params.set<LinearVariableName>("variable") = _velocity_names[d];
539 540 : getProblem().addLinearFVBC(bc_type, _velocity_names[d] + "_" + outlet_bdy, params);
540 : }
541 148 : }
542 :
543 : // Fixed pressure condition, coming in the pressure correction equation
544 154 : if (momentum_outlet_type == "fixed-pressure" ||
545 6 : momentum_outlet_type == "fixed-pressure-zero-gradient")
546 : {
547 148 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorDirichletBC";
548 148 : InputParameters params = getFactory().getValidParams(bc_type);
549 296 : params.set<LinearVariableName>("variable") = _pressure_name;
550 296 : params.set<MooseFunctorName>("functor") = libmesh_map_find(_pressure_functors, outlet_bdy);
551 444 : params.set<std::vector<BoundaryName>>("boundary") = {outlet_bdy};
552 :
553 148 : getProblem().addLinearFVBC(bc_type, _pressure_name + "_" + outlet_bdy, params);
554 148 : }
555 : }
556 845 : }
557 :
558 : void
559 169 : WCNSLinearFVFlowPhysics::addWallsBC()
560 : {
561 676 : const std::string u_names[3] = {"u", "v", "w"};
562 : bool has_symmetry_bc = false;
563 :
564 497 : for (const auto & [boundary_name, momentum_wall_type] : _momentum_wall_types)
565 : {
566 328 : if (momentum_wall_type == "noslip")
567 : {
568 322 : const std::string bc_type = "LinearFVAdvectionDiffusionFunctorDirichletBC";
569 322 : InputParameters params = getFactory().getValidParams(bc_type);
570 966 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
571 :
572 990 : for (const auto d : make_range(dimension()))
573 : {
574 1336 : params.set<LinearVariableName>("variable") = _velocity_names[d];
575 : if (_momentum_wall_functors.count(boundary_name) == 0)
576 1144 : params.set<MooseFunctorName>("functor") = "0";
577 : else
578 192 : params.set<MooseFunctorName>("functor") = _momentum_wall_functors[boundary_name][d];
579 :
580 1336 : getProblem().addLinearFVBC(bc_type, _velocity_names[d] + "_" + boundary_name, params);
581 : }
582 322 : }
583 6 : else if (momentum_wall_type == "symmetry")
584 : {
585 : has_symmetry_bc = true;
586 : {
587 6 : const std::string bc_type = "LinearFVVelocitySymmetryBC";
588 6 : InputParameters params = getFactory().getValidParams(bc_type);
589 18 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
590 18 : for (unsigned int d = 0; d < dimension(); ++d)
591 24 : params.set<SolverVariableName>(u_names[d]) = _velocity_names[d];
592 :
593 18 : for (const auto d : make_range(dimension()))
594 : {
595 24 : params.set<LinearVariableName>("variable") = _velocity_names[d];
596 24 : params.set<MooseEnum>("momentum_component") = NS::directions[d];
597 :
598 24 : getProblem().addLinearFVBC(bc_type, _velocity_names[d] + "_" + boundary_name, params);
599 : }
600 6 : }
601 : {
602 6 : const std::string bc_type = "LinearFVPressureSymmetryBC";
603 6 : InputParameters params = getFactory().getValidParams(bc_type);
604 18 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
605 12 : params.set<LinearVariableName>("variable") = _pressure_name;
606 12 : params.set<MooseFunctorName>("HbyA_flux") = "HbyA";
607 6 : getProblem().addLinearFVBC(bc_type, _pressure_name + "_" + boundary_name, params);
608 6 : }
609 : }
610 : else
611 0 : mooseError("Unsupported wall boundary condition type: " + std::string(momentum_wall_type));
612 : }
613 :
614 338 : if (getParam<bool>("pressure_two_term_bc_expansion"))
615 : {
616 49 : if (!has_symmetry_bc)
617 : {
618 43 : const std::string bc_type = "LinearFVExtrapolatedPressureBC";
619 43 : InputParameters params = getFactory().getValidParams(bc_type);
620 43 : params.set<std::vector<BoundaryName>>("boundary") = _wall_boundaries;
621 86 : params.set<LinearVariableName>("variable") = _pressure_name;
622 43 : params.set<bool>("use_two_term_expansion") = true;
623 43 : getProblem().addLinearFVBC(
624 129 : bc_type, _pressure_name + "_extrapolation_" + Moose::stringify(_wall_boundaries), params);
625 43 : }
626 : else
627 18 : for (const auto & [boundary_name, momentum_wall_type] : _momentum_wall_types)
628 12 : if (momentum_wall_type != "symmetry")
629 : {
630 6 : const std::string bc_type = "LinearFVExtrapolatedPressureBC";
631 6 : InputParameters params = getFactory().getValidParams(bc_type);
632 18 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
633 12 : params.set<LinearVariableName>("variable") = _pressure_name;
634 6 : params.set<bool>("use_two_term_expansion") = true;
635 6 : getProblem().addLinearFVBC(
636 6 : bc_type, _pressure_name + "_extrapolation_" + boundary_name, params);
637 6 : }
638 : }
639 845 : }
640 :
641 : void
642 169 : WCNSLinearFVFlowPhysics::addUserObjects()
643 : {
644 : mooseAssert(!_porous_medium_treatment, "Not implemented");
645 : // Rhie Chow user object for interpolation velocities
646 169 : addRhieChowUserObjects();
647 169 : }
648 :
649 : void
650 169 : WCNSLinearFVFlowPhysics::addRhieChowUserObjects()
651 : {
652 : mooseAssert(dimension(), "0-dimension not supported");
653 :
654 : // First make sure that we only add this object once
655 : // Potential cases:
656 : // - there is a flow physics, and an advection one (UO should be added by one)
657 : // - there is only an advection physics (UO should be created)
658 : // - there are two advection physics on different blocks with set velocities (first one picks)
659 : // Counting RC UOs defined on the same blocks seems to be the most fool proof option
660 : std::vector<UserObject *> objs;
661 : getProblem()
662 : .theWarehouse()
663 169 : .query()
664 169 : .condition<AttribSystem>("UserObject")
665 338 : .condition<AttribThread>(0)
666 : .queryInto(objs);
667 : unsigned int num_rc_uo = 0;
668 177 : for (const auto & obj : objs)
669 8 : if (dynamic_cast<RhieChowMassFlux *>(obj))
670 : {
671 : const auto rc_obj = dynamic_cast<RhieChowMassFlux *>(obj);
672 0 : if (rc_obj->blocks() == _blocks)
673 0 : num_rc_uo++;
674 : // one of the RC user object is defined everywhere
675 0 : else if (rc_obj->blocks().size() == 0 || _blocks.size() == 0)
676 0 : num_rc_uo++;
677 : }
678 :
679 169 : if (num_rc_uo)
680 : return;
681 :
682 676 : const std::string u_names[3] = {"u", "v", "w"};
683 : const auto object_type = "RhieChowMassFlux";
684 :
685 169 : auto params = getFactory().getValidParams(object_type);
686 169 : assignBlocks(params, _blocks);
687 481 : for (unsigned int d = 0; d < dimension(); ++d)
688 624 : params.set<VariableName>(u_names[d]) = _velocity_names[d];
689 :
690 338 : params.set<VariableName>("pressure") = _pressure_name;
691 338 : params.set<std::string>("p_diffusion_kernel") = prefix() + "p_diffusion";
692 169 : params.set<MooseFunctorName>(NS::density) = _density_name;
693 338 : params.set<MooseEnum>("pressure_projection_method") =
694 338 : getParam<MooseEnum>("pressure_projection_method");
695 338 : params.set<MooseEnum>("pressure_diffusion_interpolation") =
696 338 : getParam<MooseEnum>("pressure_diffusion_interpolation");
697 :
698 169 : addUserObject(object_type, rhieChowUOName(), params);
699 845 : }
700 :
701 : std::vector<UserObjectName>
702 169 : WCNSLinearFVFlowPhysics::getSuppliedUserObjects() const
703 : {
704 338 : return {rhieChowUOName()};
705 169 : }
706 :
707 : void
708 169 : WCNSLinearFVFlowPhysics::addFunctorMaterials()
709 : {
710 338 : if (parameters().isParamValid("gravity"))
711 : {
712 338 : const auto gravity_vector = getParam<RealVectorValue>("gravity");
713 845 : const std::vector<std::string> comp_axis({"x", "y", "z"});
714 481 : for (const auto d : make_range(dimension()))
715 312 : if (gravity_vector(d) != 0)
716 : {
717 : // Add rho * g functor for each relevant direction
718 : // TODO: we could avoid using an AD functor material for non-AD density functor
719 9 : auto params = getFactory().getValidParams("ADParsedFunctorMaterial");
720 9 : assignBlocks(params, _blocks);
721 18 : params.set<std::string>("expression") =
722 27 : _density_gravity_name + " * " + std::to_string(gravity_vector(d));
723 9 : if (!MooseUtils::parsesToReal(_density_gravity_name))
724 3 : params.set<std::vector<std::string>>("functor_names") = {_density_gravity_name};
725 18 : params.set<std::string>("property_name") = "rho_g_" + comp_axis[d];
726 : // We don't output this helper material
727 27 : getProblem().addMaterial(
728 9 : "ADParsedFunctorMaterial", prefix() + "gravity_helper_" + comp_axis[d], params);
729 9 : }
730 169 : }
731 508 : }
732 :
733 : unsigned short
734 789 : WCNSLinearFVFlowPhysics::getNumberAlgebraicGhostingLayersNeeded() const
735 : {
736 789 : return 1;
737 : }
|