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