LCOV - code coverage report
Current view: top level - src/physics - WCNSLinearFVFlowPhysics.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: #33380 (547b29) with base 8581c3 Lines: 355 411 86.4 %
Date: 2026-07-20 19:39:27 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

          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         507 :       getParam<MooseEnum>("pressure_diffusion_interpolation");
     697             : 
     698         169 :   getProblem().addUserObject(object_type, rhieChowUOName(), params);
     699         845 : }
     700             : 
     701             : void
     702         169 : WCNSLinearFVFlowPhysics::addFunctorMaterials()
     703             : {
     704         338 :   if (parameters().isParamValid("gravity"))
     705             :   {
     706         338 :     const auto gravity_vector = getParam<RealVectorValue>("gravity");
     707         845 :     const std::vector<std::string> comp_axis({"x", "y", "z"});
     708         481 :     for (const auto d : make_range(dimension()))
     709         312 :       if (gravity_vector(d) != 0)
     710             :       {
     711             :         // Add rho * g functor for each relevant direction
     712             :         // TODO: we could avoid using an AD functor material for non-AD density functor
     713           9 :         auto params = getFactory().getValidParams("ADParsedFunctorMaterial");
     714           9 :         assignBlocks(params, _blocks);
     715          18 :         params.set<std::string>("expression") =
     716          27 :             _density_gravity_name + " * " + std::to_string(gravity_vector(d));
     717           9 :         if (!MooseUtils::parsesToReal(_density_gravity_name))
     718           3 :           params.set<std::vector<std::string>>("functor_names") = {_density_gravity_name};
     719          18 :         params.set<std::string>("property_name") = "rho_g_" + comp_axis[d];
     720             :         // We don't output this helper material
     721          27 :         getProblem().addMaterial(
     722           9 :             "ADParsedFunctorMaterial", prefix() + "gravity_helper_" + comp_axis[d], params);
     723           9 :       }
     724         169 :   }
     725         508 : }
     726             : 
     727             : unsigned short
     728         789 : WCNSLinearFVFlowPhysics::getNumberAlgebraicGhostingLayersNeeded() const
     729             : {
     730         789 :   return 1;
     731             : }

Generated by: LCOV version 1.14