LCOV - code coverage report
Current view: top level - src/physics - WCNSLinearFVFlowPhysics.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: 9fc4b0 Lines: 307 363 84.6 %
Date: 2025-08-14 10:14:56 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14