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

Generated by: LCOV version 1.14