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

Generated by: LCOV version 1.14