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

Generated by: LCOV version 1.14