LCOV - code coverage report
Current view: top level - src/fvkernels - PINSFVMomentumFriction.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: ba1ead Lines: 82 90 91.1 %
Date: 2025-08-13 06:50:25 Functions: 5 5 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 "PINSFVMomentumFriction.h"
      11             : #include "NS.h"
      12             : #include "SystemBase.h"
      13             : #include "MooseVariableFV.h"
      14             : #include "NavierStokesMethods.h"
      15             : 
      16             : registerMooseObject("NavierStokesApp", PINSFVMomentumFriction);
      17             : 
      18             : InputParameters
      19        4551 : PINSFVMomentumFriction::validParams()
      20             : {
      21        4551 :   InputParameters params = INSFVElementalKernel::validParams();
      22        4551 :   params.addClassDescription(
      23             :       "Computes a friction force term on fluid in porous media in the "
      24             :       "Navier Stokes i-th momentum equation in Rhie-Chow (incompressible) contexts.");
      25        9102 :   params.addParam<MooseFunctorName>("Darcy_name", "Name of the Darcy coefficients property.");
      26        9102 :   params.addParam<MooseFunctorName>("Forchheimer_name",
      27             :                                     "Name of the Forchheimer coefficients property.");
      28        9102 :   params.addParam<bool>("is_porous_medium", true, "Boolean to choose the type of medium.");
      29        9102 :   params.addParam<bool>(
      30        9102 :       "standard_friction_formulation", true, "Boolean to choose the type of friction formulation.");
      31        4551 :   params.addParam<MooseFunctorName>(NS::mu, "The dynamic viscosity");
      32        4551 :   params.addParam<MooseFunctorName>(NS::speed, "The magnitude of the interstitial velocity.");
      33        9102 :   params.addParam<MooseFunctorName>("u",
      34             :                                     "The velocity in the x direction. Superficial in the case of "
      35             :                                     "porous treatment, interstitial otherwise");
      36        9102 :   params.addParam<MooseFunctorName>("v",
      37             :                                     "The velocity in the y direction. Superficial in the case of "
      38             :                                     "porous treatment, interstitial otherwise");
      39        9102 :   params.addParam<MooseFunctorName>("w",
      40             :                                     "The velocity in the z direction. Superficial in the case of "
      41             :                                     "porous treatment, interstitial otherwise");
      42        4551 :   params.addParam<MooseFunctorName>(NS::porosity, 1.0, "The porosity");
      43        4551 :   params.addRequiredParam<MooseFunctorName>(NS::density, "The density.");
      44        4551 :   return params;
      45           0 : }
      46             : 
      47        2776 : PINSFVMomentumFriction::PINSFVMomentumFriction(const InputParameters & params)
      48             :   : INSFVElementalKernel(params),
      49        7708 :     _D(isParamValid("Darcy_name") ? &getFunctor<ADRealVectorValue>("Darcy_name") : nullptr),
      50       10080 :     _F(isParamValid("Forchheimer_name") ? &getFunctor<ADRealVectorValue>("Forchheimer_name")
      51             :                                         : nullptr),
      52        5552 :     _use_Darcy_friction_model(isParamValid("Darcy_name")),
      53        5552 :     _use_Forchheimer_friction_model(isParamValid("Forchheimer_name")),
      54        5552 :     _is_porous_medium(getParam<bool>("is_porous_medium")),
      55        5552 :     _standard_friction_formulation(getParam<bool>("standard_friction_formulation")),
      56        2776 :     _mu(isParamValid(NS::mu) ? &getFunctor<ADReal>(NS::mu) : nullptr),
      57        2776 :     _rho(getFunctor<ADReal>(NS::density)),
      58        2776 :     _speed(isParamValid(NS::speed) ? &getFunctor<ADReal>(NS::speed) : nullptr),
      59        2776 :     _dim(_subproblem.mesh().dimension()),
      60        2944 :     _u_var(params.isParamValid("u") ? &(getFunctor<ADReal>("u")) : nullptr),
      61        2944 :     _v_var(params.isParamValid("v") ? &(getFunctor<ADReal>("v")) : nullptr),
      62        2776 :     _w_var(params.isParamValid("w") ? &(getFunctor<ADReal>("w")) : nullptr),
      63        2776 :     _epsilon(getFunctor<ADReal>(NS::porosity))
      64             : {
      65        2776 :   if (!_use_Darcy_friction_model && !_use_Forchheimer_friction_model)
      66           0 :     mooseError("At least one friction model needs to be specified.");
      67             : 
      68        2776 :   if (_standard_friction_formulation && _use_Darcy_friction_model && !_mu)
      69           0 :     mooseError("If using the standard Darcy friction model, then the '",
      70             :                NS::mu,
      71             :                "' parameter must be provided");
      72        2776 :   if (_use_Forchheimer_friction_model && !_speed)
      73             :   {
      74          84 :     if (_dim >= 1)
      75             :     {
      76          84 :       if (!_u_var)
      77           0 :         mooseError("The velocity variable 'u' should be defined if no speed functor material is "
      78             :                    "defined for this kernel when using the Forchheimer fromulation.");
      79             :     }
      80          84 :     if (_dim >= 2)
      81             :     {
      82          84 :       if (!_v_var)
      83           0 :         mooseError(
      84             :             "The velocity variable 'v' should be defined if no speed functor material is "
      85             :             "defined for this kernel and dimensions >= 2 when using the Forchheimer fromulation.");
      86             :     }
      87          84 :     if (_dim >= 3)
      88             :     {
      89           0 :       if (!_w_var)
      90           0 :         mooseError(
      91             :             "The velocity variable 'w' should be defined if no speed functor material is "
      92             :             "defined for this kernel and dimensions >= 3 when using the Forchheimer fromulation.");
      93             :     }
      94             :   }
      95        2776 : }
      96             : 
      97             : // We are going to follow the formulations in
      98             : // https://holzmann-cfd.com/community/blog-and-tools/darcy-forchheimer and
      99             : // https://www.simscale.com/knowledge-base/predict-darcy-and-forchheimer-coefficients-for-perforated-plates-using-analytical-approach/
     100             : // for Darcy and Forchheimer which define:
     101             : //
     102             : // \nabla p = \mu D v + \frac{\rho}{2} F |v| v
     103             : //
     104             : // where v denotes the superficial velocity.
     105             : // Both monolithic and segregated solves get multiplied by v in the gatherRCData and
     106             : // computeSegregatedContribution methods respectively, it is the job of the
     107             : // computeFrictionWCoefficient method to compute, for the Darcy term:
     108             : //
     109             : // \mu D
     110             : //
     111             : // and for the Forchheimer term
     112             : //
     113             : // \frac{\rho}{2} F |v|
     114             : //
     115             : // For the non standard formulation we define :
     116             : // \nabla p = D v + F |v| v
     117             : 
     118             : ADReal
     119     9111052 : PINSFVMomentumFriction::computeFrictionWCoefficient(const Moose::ElemArg & elem_arg,
     120             :                                                     const Moose::StateArg & state)
     121             : {
     122             :   // Forward declaration of the coeffcients to be used and returned by the model
     123     9111052 :   ADReal coefficient = 0.0;
     124     9111052 :   ADReal speed = 0.0;
     125     9111052 :   ADReal rho = 0.0;
     126     9111052 :   ADReal mu = 0.0;
     127             :   /// Speed treatment
     128     9111052 :   if (_use_Forchheimer_friction_model && _speed)
     129     7856706 :     speed = (*_speed)(elem_arg, state);
     130     1254346 :   else if (_use_Forchheimer_friction_model && !_speed)
     131             :   {
     132             :     ADRealVectorValue superficial_velocity;
     133      808500 :     if (_dim >= 1)
     134             :     {
     135      808500 :       superficial_velocity(0) = (*_u_var)(elem_arg, state);
     136      808500 :       if (_dim >= 2)
     137             :       {
     138      808500 :         superficial_velocity(1) = (*_v_var)(elem_arg, state);
     139      808500 :         if (_dim >= 3)
     140           0 :           superficial_velocity(2) = (*_w_var)(elem_arg, state);
     141             :       }
     142             :     }
     143      808500 :     speed = NS::computeSpeed<ADReal>(superficial_velocity);
     144      808500 :     if (_is_porous_medium)
     145             :     {
     146     1617000 :       speed *= (1 / _epsilon(elem_arg, state));
     147             :     }
     148             :   }
     149             : 
     150             :   /// Fluid properies
     151     9111052 :   if (_use_Darcy_friction_model && _standard_friction_formulation)
     152             :   {
     153     7476546 :     mu = (*_mu)(elem_arg, state);
     154             :   }
     155             : 
     156     9111052 :   if (_use_Forchheimer_friction_model && _standard_friction_formulation)
     157             :   {
     158     7488226 :     rho = _rho(elem_arg, state);
     159             :   }
     160             : 
     161             :   ////////////////////////////////////////////////////////////////////
     162             :   ///// Switching across formulation cases
     163             :   ////////////////////////////////////////////////////////////////////
     164     9111052 :   if (_standard_friction_formulation)
     165             :   {
     166     7645386 :     if (_use_Darcy_friction_model)
     167    14953092 :       coefficient += mu * (*_D)(elem_arg, state)(_index);
     168     7645386 :     if (_use_Forchheimer_friction_model)
     169    14976452 :       coefficient += rho / 2 * (*_F)(elem_arg, state)(_index)*speed;
     170             :   }
     171             :   else
     172             :   {
     173     1465666 :     if (_use_Darcy_friction_model)
     174     1097186 :       coefficient += (*_D)(elem_arg, state)(_index);
     175     1465666 :     if (_use_Forchheimer_friction_model)
     176     2353960 :       coefficient += (*_F)(elem_arg, state)(_index)*speed;
     177             :   }
     178             : 
     179     9111052 :   return coefficient;
     180             : }
     181             : 
     182             : ADReal
     183     1620000 : PINSFVMomentumFriction::computeSegregatedContribution()
     184             : {
     185     1620000 :   const auto & elem_arg = makeElemArg(_current_elem);
     186     1620000 :   const auto state = determineState();
     187     1620000 :   return raw_value(computeFrictionWCoefficient(elem_arg, state)) * _u_functor(elem_arg, state);
     188             : }
     189             : 
     190             : void
     191     7491052 : PINSFVMomentumFriction::gatherRCData(const Elem & elem)
     192             : {
     193     7491052 :   const auto elem_arg = makeElemArg(&elem);
     194     7491052 :   const auto state = determineState();
     195             :   const auto coefficient =
     196     7491052 :       computeFrictionWCoefficient(elem_arg, state) * _assembly.elementVolume(&elem);
     197     7491052 :   _rc_uo.addToA(&elem, _index, coefficient);
     198     7491052 :   const auto dof_number = elem.dof_number(_sys.number(), _var.number(), 0);
     199    14982104 :   addResidualAndJacobian(coefficient * _u_functor(elem_arg, state), dof_number);
     200     7491052 : }

Generated by: LCOV version 1.14