LCOV - code coverage report
Current view: top level - src/kernels - PorousFlowDispersiveFlux.C (source / functions) Hit Total Coverage
Test: idaholab/moose porous_flow: #33380 (547b29) with base 8581c3 Lines: 122 134 91.0 %
Date: 2026-07-20 19:40:36 Functions: 9 12 75.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 "PorousFlowDispersiveFlux.h"
      11             : 
      12             : #include "MooseVariable.h"
      13             : 
      14             : registerMooseObject("PorousFlowApp", PorousFlowDispersiveFlux);
      15             : registerMooseObject("PorousFlowApp", ADPorousFlowDispersiveFlux);
      16             : 
      17             : template <bool is_ad>
      18             : InputParameters
      19        1376 : PorousFlowDispersiveFluxTempl<is_ad>::validParams()
      20             : {
      21             :   InputParameters params = GenericKernel<is_ad>::validParams();
      22        1402 :   params.addParam<unsigned int>(
      23        1402 :       "fluid_component", 0, "The index corresponding to the fluid component for this kernel");
      24        1402 :   params.addRequiredParam<UserObjectName>(
      25             :       "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
      26        1402 :   params.addRequiredParam<std::vector<Real>>(
      27             :       "disp_long", "Vector of longitudinal dispersion coefficients for each phase");
      28        1402 :   params.addRequiredParam<std::vector<Real>>(
      29             :       "disp_trans", "Vector of transverse dispersion coefficients for each phase");
      30        1402 :   params.addRequiredParam<RealVectorValue>("gravity",
      31             :                                            "Gravitational acceleration vector downwards (m/s^2)");
      32         701 :   params.addClassDescription(
      33             :       "Dispersive and diffusive flux of the component given by fluid_component in all phases");
      34         701 :   return params;
      35           0 : }
      36             : 
      37             : template <bool is_ad>
      38         372 : PorousFlowDispersiveFluxTempl<is_ad>::PorousFlowDispersiveFluxTempl(
      39             :     const InputParameters & parameters)
      40             :   : GenericKernel<is_ad>(parameters),
      41         372 :     _fluid_density_qp(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
      42             :         "PorousFlow_fluid_phase_density_qp")),
      43         372 :     _dfluid_density_qp_dvar(
      44             :         is_ad ? nullptr
      45         358 :               : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
      46             :                     "dPorousFlow_fluid_phase_density_qp_dvar")),
      47         372 :     _grad_mass_frac(
      48         372 :         this->template getGenericMaterialProperty<std::vector<std::vector<RealGradient>>, is_ad>(
      49             :             "PorousFlow_grad_mass_frac_qp")),
      50         372 :     _dmass_frac_dvar(
      51             :         is_ad ? nullptr
      52         358 :               : &this->template getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
      53             :                     "dPorousFlow_mass_frac_qp_dvar")),
      54         744 :     _porosity_qp(this->template getGenericMaterialProperty<Real, is_ad>("PorousFlow_porosity_qp")),
      55         372 :     _dporosity_qp_dvar(is_ad ? nullptr
      56         358 :                              : &this->template getMaterialProperty<std::vector<Real>>(
      57             :                                    "dPorousFlow_porosity_qp_dvar")),
      58         744 :     _tortuosity(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
      59             :         "PorousFlow_tortuosity_qp")),
      60         372 :     _dtortuosity_dvar(is_ad ? nullptr
      61         358 :                             : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
      62             :                                   "dPorousFlow_tortuosity_qp_dvar")),
      63         744 :     _diffusion_coeff(this->template getMaterialProperty<std::vector<std::vector<Real>>>(
      64             :         "PorousFlow_diffusion_coeff_qp")),
      65         372 :     _ddiffusion_coeff_dvar(
      66             :         is_ad ? nullptr
      67         358 :               : &this->template getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
      68             :                     "dPorousFlow_diffusion_coeff_qp_dvar")),
      69         372 :     _dictator(this->template getUserObject<PorousFlowDictator>("PorousFlowDictator")),
      70         744 :     _fluid_component(this->template getParam<unsigned int>("fluid_component")),
      71         372 :     _num_phases(_dictator.numPhases()),
      72         372 :     _identity_tensor(GenericRankTwoTensor<is_ad>::initIdentity),
      73         744 :     _relative_permeability(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
      74             :         "PorousFlow_relative_permeability_qp")),
      75         372 :     _drelative_permeability_dvar(
      76             :         is_ad ? nullptr
      77         358 :               : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
      78             :                     "dPorousFlow_relative_permeability_qp_dvar")),
      79         744 :     _fluid_viscosity(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
      80             :         "PorousFlow_viscosity_qp")),
      81         372 :     _dfluid_viscosity_dvar(
      82             :         is_ad ? nullptr
      83         358 :               : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
      84             :                     "dPorousFlow_viscosity_qp_dvar")),
      85         744 :     _permeability(this->template getGenericMaterialProperty<RealTensorValue, is_ad>(
      86             :         "PorousFlow_permeability_qp")),
      87         372 :     _dpermeability_dvar(is_ad ? nullptr
      88         358 :                               : &this->template getMaterialProperty<std::vector<RealTensorValue>>(
      89             :                                     "dPorousFlow_permeability_qp_dvar")),
      90         372 :     _dpermeability_dgradvar(
      91             :         is_ad ? nullptr
      92         358 :               : &this->template getMaterialProperty<std::vector<std::vector<RealTensorValue>>>(
      93             :                     "dPorousFlow_permeability_qp_dgradvar")),
      94         744 :     _grad_p(this->template getGenericMaterialProperty<std::vector<RealGradient>, is_ad>(
      95             :         "PorousFlow_grad_porepressure_qp")),
      96         372 :     _dgrad_p_dgrad_var(is_ad ? nullptr
      97         358 :                              : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
      98             :                                    "dPorousFlow_grad_porepressure_qp_dgradvar")),
      99         372 :     _dgrad_p_dvar(is_ad
     100             :                       ? nullptr
     101         358 :                       : &this->template getMaterialProperty<std::vector<std::vector<RealGradient>>>(
     102             :                             "dPorousFlow_grad_porepressure_qp_dvar")),
     103         744 :     _gravity(this->template getParam<RealVectorValue>("gravity")),
     104         744 :     _disp_long(this->template getParam<std::vector<Real>>("disp_long")),
     105         744 :     _disp_trans(this->template getParam<std::vector<Real>>("disp_trans")),
     106         744 :     _perm_derivs(_dictator.usePermDerivs())
     107             : {
     108         372 :   if (_fluid_component >= _dictator.numComponents())
     109           0 :     this->paramError(
     110             :         "fluid_component",
     111             :         "The Dictator proclaims that the maximum fluid component index in this simulation is ",
     112           0 :         _dictator.numComponents() - 1,
     113             :         " whereas you have used ",
     114           0 :         _fluid_component,
     115             :         ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
     116             : 
     117         372 :   if (_disp_long.size() != _num_phases)
     118           0 :     this->paramError(
     119             :         "disp_long",
     120             :         "The number of longitudinal dispersion coefficients is not equal to the number of phases");
     121             : 
     122         372 :   if (_disp_trans.size() != _num_phases)
     123           0 :     this->paramError("disp_trans",
     124             :                      "The number of transverse dispersion coefficients disp_trans is not equal to "
     125             :                      "the number of phases");
     126         372 : }
     127             : 
     128             : template <bool is_ad>
     129             : GenericReal<is_ad>
     130     3767344 : PorousFlowDispersiveFluxTempl<is_ad>::computeQpResidual()
     131             : {
     132             :   GenericRealVectorValue<is_ad> flux;
     133             :   GenericRealVectorValue<is_ad> velocity;
     134             :   GenericReal<is_ad> velocity_abs;
     135     3767344 :   GenericRankTwoTensor<is_ad> v2;
     136     3767344 :   GenericRankTwoTensor<is_ad> dispersion;
     137        8064 :   dispersion.zero();
     138             :   GenericReal<is_ad> diffusion;
     139             : 
     140     7708688 :   for (unsigned int ph = 0; ph < _num_phases; ++ph)
     141             :   {
     142     3941344 :     diffusion =
     143     3941344 :         _porosity_qp[_qp] * _tortuosity[_qp][ph] * _diffusion_coeff[_qp][ph][_fluid_component];
     144             : 
     145     3941344 :     velocity = _permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity) *
     146     3941344 :                _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph];
     147     3941344 :     velocity_abs = velocity.norm();
     148             : 
     149     3941344 :     if (MetaPhysicL::raw_value(velocity_abs) > 0.0)
     150             :     {
     151     3478136 :       v2 = GenericRankTwoTensor<is_ad>::selfOuterProduct(velocity);
     152     3478136 :       diffusion += GenericReal<is_ad>(_disp_trans[ph]) * velocity_abs;
     153     3486200 :       dispersion = GenericReal<is_ad>(_disp_long[ph] - _disp_trans[ph]) * v2 / velocity_abs;
     154             :     }
     155             : 
     156     3949408 :     flux += _fluid_density_qp[_qp][ph] * (diffusion * _identity_tensor + dispersion) *
     157     3941344 :             _grad_mass_frac[_qp][ph][_fluid_component];
     158             :   }
     159     3767344 :   return _grad_test[_i][_qp] * flux;
     160             : }
     161             : 
     162             : template <bool is_ad>
     163             : Real
     164     9614832 : PorousFlowDispersiveFluxTempl<is_ad>::computeQpJacobian()
     165             : {
     166     9614832 :   return computeQpJac(_var.number());
     167             : }
     168             : 
     169             : template <bool is_ad>
     170             : Real
     171     9614272 : PorousFlowDispersiveFluxTempl<is_ad>::computeQpOffDiagJacobian(unsigned int jvar)
     172             : {
     173     9614272 :   return computeQpJac(jvar);
     174             : }
     175             : 
     176             : template <bool is_ad>
     177             : Real
     178    19229104 : PorousFlowDispersiveFluxTempl<is_ad>::computeQpJac(unsigned int jvar) const
     179             : {
     180             :   if constexpr (!is_ad)
     181             :   {
     182    19229104 :     if (_dictator.notPorousFlowVariable(jvar))
     183             :       return 0.0;
     184             : 
     185    19229104 :     const unsigned int pvar = _dictator.porousFlowVariableNum(jvar);
     186             : 
     187             :     RealVectorValue velocity;
     188             :     Real velocity_abs;
     189    19229104 :     RankTwoTensor v2;
     190    19229104 :     RankTwoTensor dispersion;
     191             :     dispersion.zero();
     192             :     Real diffusion;
     193             :     RealVectorValue dflux = 0.0;
     194             : 
     195    39573392 :     for (unsigned int ph = 0; ph < _num_phases; ++ph)
     196             :     {
     197    20344288 :       diffusion =
     198    20344288 :           _porosity_qp[_qp] * _tortuosity[_qp][ph] * _diffusion_coeff[_qp][ph][_fluid_component];
     199             : 
     200    20344288 :       velocity = _permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity) *
     201    20344288 :                  _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph];
     202    20344288 :       velocity_abs = MetaPhysicL::raw_value(velocity).norm();
     203             : 
     204    20344288 :       if (velocity_abs > 0.0)
     205             :       {
     206    18202624 :         v2 = RankTwoTensor::selfOuterProduct(velocity);
     207    18202624 :         diffusion += _disp_trans[ph] * velocity_abs;
     208    18202624 :         dispersion = (_disp_long[ph] - _disp_trans[ph]) * v2 / velocity_abs;
     209             :       }
     210             : 
     211             :       RealVectorValue dvelocity =
     212    20344288 :           _permeability[_qp] *
     213    20344288 :           (_grad_phi[_j][_qp] * (*_dgrad_p_dgrad_var)[_qp][ph][pvar] -
     214    20344288 :            _phi[_j][_qp] * (*_dfluid_density_qp_dvar)[_qp][ph][pvar] * _gravity);
     215    20344288 :       dvelocity += _permeability[_qp] * ((*_dgrad_p_dvar)[_qp][ph][pvar] * _phi[_j][_qp]);
     216             : 
     217    20344288 :       if (_perm_derivs)
     218             :       {
     219           0 :         dvelocity += (*_dpermeability_dvar)[_qp][pvar] * _phi[_j][_qp] *
     220           0 :                      (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity);
     221             : 
     222           0 :         for (const auto i : make_range(Moose::dim))
     223           0 :           dvelocity += (*_dpermeability_dgradvar)[_qp][i][pvar] * _grad_phi[_j][_qp](i) *
     224           0 :                        (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity);
     225             :       }
     226             : 
     227    20344288 :       dvelocity =
     228             :           dvelocity * _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph] +
     229    20344288 :           (_permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity)) *
     230    20344288 :               ((*_drelative_permeability_dvar)[_qp][ph][pvar] / _fluid_viscosity[_qp][ph] -
     231    20344288 :                _relative_permeability[_qp][ph] * (*_dfluid_viscosity_dvar)[_qp][ph][pvar] /
     232             :                    std::pow(_fluid_viscosity[_qp][ph], 2)) *
     233             :               _phi[_j][_qp];
     234             : 
     235    20344288 :       Real dvelocity_abs = 0.0;
     236    20344288 :       if (velocity_abs > 0.0)
     237    18202624 :         dvelocity_abs = velocity * dvelocity / velocity_abs;
     238             : 
     239    20344288 :       Real ddiffusion = _phi[_j][_qp] * (*_dporosity_qp_dvar)[_qp][pvar] * _tortuosity[_qp][ph] *
     240    20344288 :                         _diffusion_coeff[_qp][ph][_fluid_component];
     241    20344288 :       ddiffusion += _phi[_j][_qp] * _porosity_qp[_qp] * (*_dtortuosity_dvar)[_qp][ph][pvar] *
     242             :                     _diffusion_coeff[_qp][ph][_fluid_component];
     243    20344288 :       ddiffusion += _phi[_j][_qp] * _porosity_qp[_qp] * _tortuosity[_qp][ph] *
     244    20344288 :                     (*_ddiffusion_coeff_dvar)[_qp][ph][_fluid_component][pvar];
     245    20344288 :       ddiffusion += _disp_trans[ph] * dvelocity_abs;
     246             : 
     247    20344288 :       RankTwoTensor ddispersion;
     248             :       ddispersion.zero();
     249    20344288 :       if (velocity_abs > 0.0)
     250             :       {
     251    18202624 :         RankTwoTensor dv2a, dv2b;
     252    18202624 :         dv2a = RankTwoTensor::outerProduct(velocity, dvelocity);
     253    18202624 :         dv2b = RankTwoTensor::outerProduct(dvelocity, velocity);
     254    18202624 :         ddispersion = (_disp_long[ph] - _disp_trans[ph]) * (dv2a + dv2b) / velocity_abs;
     255    36405248 :         ddispersion -=
     256    18202624 :             (_disp_long[ph] - _disp_trans[ph]) * v2 * dvelocity_abs / velocity_abs / velocity_abs;
     257             :       }
     258             : 
     259    20344288 :       dflux += _phi[_j][_qp] * (*_dfluid_density_qp_dvar)[_qp][ph][pvar] *
     260    20344288 :                (diffusion * _identity_tensor + dispersion) *
     261    20344288 :                _grad_mass_frac[_qp][ph][_fluid_component];
     262    20344288 :       dflux += _fluid_density_qp[_qp][ph] * (ddiffusion * _identity_tensor + ddispersion) *
     263             :                _grad_mass_frac[_qp][ph][_fluid_component];
     264             : 
     265             :       // NOTE: Here we assume that d(grad_mass_frac)/d(var) = d(mass_frac)/d(var) * grad_phi
     266             :       //       This is true for most PorousFlow scenarios, but not for chemical reactions
     267             :       //       where mass_frac is a nonlinear function of the primary MOOSE Variables
     268             :       dflux += _fluid_density_qp[_qp][ph] * (diffusion * _identity_tensor + dispersion) *
     269    20344288 :                (*_dmass_frac_dvar)[_qp][ph][_fluid_component][pvar] * _grad_phi[_j][_qp];
     270             :     }
     271             : 
     272    19229104 :     return _grad_test[_i][_qp] * dflux;
     273             :   }
     274             :   else
     275             :     libmesh_ignore(jvar);
     276           0 :   return 0.0;
     277             : }
     278             : 
     279             : template class PorousFlowDispersiveFluxTempl<false>;
     280             : template class PorousFlowDispersiveFluxTempl<true>;

Generated by: LCOV version 1.14