LCOV - code coverage report
Current view: top level - src/materials - RichardsMaterial.C (source / functions) Hit Total Coverage
Test: idaholab/moose richards: #31405 (292dce) with base fef103 Lines: 336 338 99.4 %
Date: 2025-09-04 07:56:35 Functions: 9 9 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 "RichardsMaterial.h"
      11             : #include "Assembly.h"
      12             : #include "MooseMesh.h"
      13             : 
      14             : #include <cmath> // std::sinh and std::cosh
      15             : 
      16             : #include "libmesh/quadrature.h"
      17             : 
      18             : registerMooseObject("RichardsApp", RichardsMaterial);
      19             : 
      20             : InputParameters
      21        1205 : RichardsMaterial::validParams()
      22             : {
      23        1205 :   InputParameters params = Material::validParams();
      24             : 
      25        2410 :   params.addRequiredParam<Real>(
      26             :       "mat_porosity", "The porosity of the material.  Should be between 0 and 1.  Eg, 0.1");
      27        2410 :   params.addCoupledVar("por_change",
      28             :                        0,
      29             :                        "An auxillary variable describing porosity changes.  "
      30             :                        "Porosity = mat_porosity + por_change.  If this is not "
      31             :                        "provided, zero is used.");
      32        2410 :   params.addRequiredParam<RealTensorValue>("mat_permeability", "The permeability tensor (m^2).");
      33        2410 :   params.addCoupledVar("perm_change",
      34             :                        "A list of auxillary variable describing permeability "
      35             :                        "changes.  There must be 9 of these, corresponding to the "
      36             :                        "xx, xy, xz, yx, yy, yz, zx, zy, zz components respectively. "
      37             :                        " Permeability = mat_permeability*10^(perm_change).");
      38        2410 :   params.addRequiredParam<UserObjectName>(
      39             :       "richardsVarNames_UO", "The UserObject that holds the list of Richards variable names.");
      40        2410 :   params.addRequiredParam<std::vector<UserObjectName>>(
      41             :       "relperm_UO", "List of names of user objects that define relative permeability");
      42        2410 :   params.addRequiredParam<std::vector<UserObjectName>>(
      43             :       "seff_UO",
      44             :       "List of name of user objects that define effective saturation as a function of "
      45             :       "pressure list");
      46        2410 :   params.addRequiredParam<std::vector<UserObjectName>>(
      47             :       "sat_UO",
      48             :       "List of names of user objects that define saturation as a function of effective saturation");
      49        2410 :   params.addRequiredParam<std::vector<UserObjectName>>(
      50             :       "density_UO", "List of names of user objects that define the fluid density");
      51        2410 :   params.addRequiredParam<std::vector<UserObjectName>>(
      52             :       "SUPG_UO", "List of names of user objects that define the SUPG");
      53        2410 :   params.addRequiredParam<std::vector<Real>>(
      54             :       "viscosity", "List of viscosity of fluids (Pa.s).  Typical value for water is=1E-3");
      55        2410 :   params.addRequiredParam<RealVectorValue>(
      56             :       "gravity",
      57             :       "Gravitational acceleration (m/s^2) as a vector pointing downwards.  Eg (0,0,-10)");
      58             :   // params.addRequiredCoupledVar("pressure_vars", "List of variables that represent the pressure");
      59        2410 :   params.addParam<bool>(
      60             :       "linear_shape_fcns",
      61        2410 :       true,
      62             :       "If you are using second-order Lagrange shape functions you need to set this to false.");
      63        1205 :   return params;
      64           0 : }
      65             : 
      66         900 : RichardsMaterial::RichardsMaterial(const InputParameters & parameters)
      67             :   : Material(parameters),
      68             : 
      69         900 :     _material_por(getParam<Real>("mat_porosity")),
      70         900 :     _por_change(coupledValue("por_change")),
      71         900 :     _por_change_old(coupledValueOld("por_change")),
      72             : 
      73        1800 :     _material_perm(getParam<RealTensorValue>("mat_permeability")),
      74             : 
      75        1800 :     _material_gravity(getParam<RealVectorValue>("gravity")),
      76             : 
      77         900 :     _porosity_old(declareProperty<Real>("porosity_old")),
      78         900 :     _porosity(declareProperty<Real>("porosity")),
      79         900 :     _permeability(declareProperty<RealTensorValue>("permeability")),
      80         900 :     _gravity(declareProperty<RealVectorValue>("gravity")),
      81             : 
      82         900 :     _richards_name_UO(getUserObject<RichardsVarNames>("richardsVarNames_UO")),
      83         900 :     _num_p(_richards_name_UO.num_v()),
      84             : 
      85        1807 :     _perm_change(isCoupled("perm_change")
      86         900 :                      ? coupledValues("perm_change")
      87         900 :                      : std::vector<const VariableValue *>(LIBMESH_DIM * LIBMESH_DIM, &_zero)),
      88             : 
      89         900 :     _trace_perm(_material_perm.tr()),
      90             : 
      91        1800 :     _material_viscosity(getParam<std::vector<Real>>("viscosity")),
      92             : 
      93         900 :     _pp_old(declareProperty<std::vector<Real>>("porepressure_old")),
      94         900 :     _pp(declareProperty<std::vector<Real>>("porepressure")),
      95         900 :     _dpp_dv(declareProperty<std::vector<std::vector<Real>>>("dporepressure_dv")),
      96         900 :     _d2pp_dv(declareProperty<std::vector<std::vector<std::vector<Real>>>>("d2porepressure_dvdv")),
      97             : 
      98         900 :     _viscosity(declareProperty<std::vector<Real>>("viscosity")),
      99             : 
     100         900 :     _density_old(declareProperty<std::vector<Real>>("density_old")),
     101         900 :     _density(declareProperty<std::vector<Real>>("density")),
     102         900 :     _ddensity_dv(declareProperty<std::vector<std::vector<Real>>>("ddensity_dv")),
     103             : 
     104         900 :     _seff_old(declareProperty<std::vector<Real>>("s_eff_old")),
     105         900 :     _seff(declareProperty<std::vector<Real>>("s_eff")),
     106         900 :     _dseff_dv(declareProperty<std::vector<std::vector<Real>>>("ds_eff_dv")),
     107         900 :     _d2seff_dv(declareProperty<std::vector<std::vector<std::vector<Real>>>>("d2s_eff_dvdv")),
     108             : 
     109         900 :     _sat_old(declareProperty<std::vector<Real>>("sat_old")),
     110         900 :     _sat(declareProperty<std::vector<Real>>("sat")),
     111         900 :     _dsat_dv(declareProperty<std::vector<std::vector<Real>>>("dsat_dv")),
     112             : 
     113         900 :     _rel_perm(declareProperty<std::vector<Real>>("rel_perm")),
     114         900 :     _drel_perm_dv(declareProperty<std::vector<std::vector<Real>>>("drel_perm_dv")),
     115             : 
     116         900 :     _mass_old(declareProperty<std::vector<Real>>("mass_old")),
     117         900 :     _mass(declareProperty<std::vector<Real>>("mass")),
     118         900 :     _dmass(declareProperty<std::vector<std::vector<Real>>>("dmass")),
     119             : 
     120         900 :     _flux_no_mob(declareProperty<std::vector<RealVectorValue>>("flux_no_mob")),
     121         900 :     _dflux_no_mob_dv(declareProperty<std::vector<std::vector<RealVectorValue>>>("dflux_no_mob_dv")),
     122         900 :     _dflux_no_mob_dgradv(
     123         900 :         declareProperty<std::vector<std::vector<RealTensorValue>>>("dflux_no_mob_dgradv")),
     124             : 
     125         900 :     _flux(declareProperty<std::vector<RealVectorValue>>("flux")),
     126         900 :     _dflux_dv(declareProperty<std::vector<std::vector<RealVectorValue>>>("dflux_dv")),
     127         900 :     _dflux_dgradv(declareProperty<std::vector<std::vector<RealTensorValue>>>("dflux_dgradv")),
     128         900 :     _d2flux_dvdv(
     129         900 :         declareProperty<std::vector<std::vector<std::vector<RealVectorValue>>>>("d2flux_dvdv")),
     130         900 :     _d2flux_dgradvdv(
     131         900 :         declareProperty<std::vector<std::vector<std::vector<RealTensorValue>>>>("d2flux_dgradvdv")),
     132         900 :     _d2flux_dvdgradv(
     133         900 :         declareProperty<std::vector<std::vector<std::vector<RealTensorValue>>>>("d2flux_dvdgradv")),
     134             : 
     135         900 :     _tauvel_SUPG(declareProperty<std::vector<RealVectorValue>>("tauvel_SUPG")),
     136         900 :     _dtauvel_SUPG_dgradp(
     137         900 :         declareProperty<std::vector<std::vector<RealTensorValue>>>("dtauvel_SUPG_dgradv")),
     138        1800 :     _dtauvel_SUPG_dp(declareProperty<std::vector<std::vector<RealVectorValue>>>("dtauvel_SUPG_dv"))
     139             : 
     140             : {
     141             : 
     142             :   // Need to add the variables that the user object is coupled to as dependencies so MOOSE will
     143             :   // compute them
     144             :   {
     145             :     const std::vector<MooseVariableFEBase *> & coupled_vars =
     146         900 :         _richards_name_UO.getCoupledMooseVars();
     147        2085 :     for (unsigned int i = 0; i < coupled_vars.size(); i++)
     148        2370 :       addMooseVariableDependency(coupled_vars[i]);
     149             :   }
     150             : 
     151         900 :   if (_material_por <= 0 || _material_por >= 1)
     152           2 :     mooseError("Porosity set to ", _material_por, " but it must be between 0 and 1");
     153             : 
     154         911 :   if (isCoupled("perm_change") && (coupledComponents("perm_change") != LIBMESH_DIM * LIBMESH_DIM))
     155           0 :     mooseError(LIBMESH_DIM * LIBMESH_DIM,
     156             :                " components of perm_change must be given to a RichardsMaterial.  You supplied ",
     157           1 :                coupledComponents("perm_change"),
     158             :                "\n");
     159             : 
     160         897 :   if (!(_material_viscosity.size() == _num_p &&
     161        2689 :         getParam<std::vector<UserObjectName>>("relperm_UO").size() == _num_p &&
     162        2687 :         getParam<std::vector<UserObjectName>>("seff_UO").size() == _num_p &&
     163        2685 :         getParam<std::vector<UserObjectName>>("sat_UO").size() == _num_p &&
     164        2683 :         getParam<std::vector<UserObjectName>>("density_UO").size() == _num_p &&
     165        2682 :         getParam<std::vector<UserObjectName>>("SUPG_UO").size() == _num_p))
     166           6 :     mooseError("There are ",
     167           6 :                _num_p,
     168             :                " Richards fluid variables, so you need to specify this "
     169             :                "number of viscosities, relperm_UO, seff_UO, sat_UO, "
     170             :                "density_UO, SUPG_UO");
     171             : 
     172         891 :   _d2density.resize(_num_p);
     173         891 :   _d2rel_perm_dv.resize(_num_p);
     174         891 :   _pressure_vals.resize(_num_p);
     175         891 :   _pressure_old_vals.resize(_num_p);
     176         891 :   _material_relperm_UO.resize(_num_p);
     177         891 :   _material_seff_UO.resize(_num_p);
     178         891 :   _material_sat_UO.resize(_num_p);
     179         891 :   _material_density_UO.resize(_num_p);
     180         891 :   _material_SUPG_UO.resize(_num_p);
     181         891 :   _grad_p.resize(_num_p);
     182             : 
     183        2061 :   for (unsigned int i = 0; i < _num_p; ++i)
     184             :   {
     185             :     // DON'T WANT "pressure_vars" at all since pp_name_UO contains the same info
     186             :     //_pressure_vals[i] = &coupledValue("pressure_vars", i); // coupled value returns a reference
     187             :     //_pressure_old_vals[i] = (_is_transient ? &coupledValueOld("pressure_vars", i) : &_zero);
     188             :     //_grad_p[i] = &coupledGradient("pressure_vars", i);
     189             : 
     190             :     // in the following.  first get the userobject names that were inputted, then get the i_th one
     191             :     // of these, then get the actual userobject that this corresponds to, then finally & gives
     192             :     // pointer to RichardsRelPerm object.
     193        1170 :     _material_relperm_UO[i] = &getUserObjectByName<RichardsRelPerm>(
     194        2340 :         getParam<std::vector<UserObjectName>>("relperm_UO")[i]);
     195        1170 :     _material_seff_UO[i] =
     196        2340 :         &getUserObjectByName<RichardsSeff>(getParam<std::vector<UserObjectName>>("seff_UO")[i]);
     197        1170 :     _material_sat_UO[i] =
     198        2340 :         &getUserObjectByName<RichardsSat>(getParam<std::vector<UserObjectName>>("sat_UO")[i]);
     199        1170 :     _material_density_UO[i] = &getUserObjectByName<RichardsDensity>(
     200        1170 :         getParam<std::vector<UserObjectName>>("density_UO")[i]);
     201        1170 :     _material_SUPG_UO[i] =
     202        3510 :         &getUserObjectByName<RichardsSUPG>(getParam<std::vector<UserObjectName>>("SUPG_UO")[i]);
     203             :   }
     204         891 : }
     205             : 
     206             : void
     207     1899373 : RichardsMaterial::computePandSeff()
     208             : {
     209             :   // Get the pressure and effective saturation at each quadpoint
     210             :   // From these we will build the relative permeability, density, flux, etc
     211     1899373 :   if (_richards_name_UO.var_types() == "pppp")
     212             :   {
     213     4108964 :     for (unsigned int i = 0; i < _num_p; ++i)
     214             :     {
     215     2209591 :       _pressure_vals[i] = _richards_name_UO.richards_vals(i);
     216     2209591 :       _pressure_old_vals[i] = _richards_name_UO.richards_vals_old(i);
     217     2209591 :       _grad_p[i] = _richards_name_UO.grad_var(i);
     218             :     }
     219             :   }
     220             : 
     221     7784090 :   for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
     222             :   {
     223     5884717 :     _pp_old[qp].resize(_num_p);
     224     5884717 :     _pp[qp].resize(_num_p);
     225     5884717 :     _dpp_dv[qp].resize(_num_p);
     226     5884717 :     _d2pp_dv[qp].resize(_num_p);
     227             : 
     228     5884717 :     _seff_old[qp].resize(_num_p);
     229     5884717 :     _seff[qp].resize(_num_p);
     230     5884717 :     _dseff_dv[qp].resize(_num_p);
     231     5884717 :     _d2seff_dv[qp].resize(_num_p);
     232             : 
     233     5884717 :     if (_richards_name_UO.var_types() == "pppp")
     234             :     {
     235    12637859 :       for (unsigned int i = 0; i < _num_p; ++i)
     236             :       {
     237     6753142 :         _pp_old[qp][i] = (*_pressure_old_vals[i])[qp];
     238     6753142 :         _pp[qp][i] = (*_pressure_vals[i])[qp];
     239             : 
     240     6753142 :         _dpp_dv[qp][i].assign(_num_p, 0);
     241     6753142 :         _dpp_dv[qp][i][i] = 1;
     242             : 
     243     6753142 :         _d2pp_dv[qp][i].resize(_num_p);
     244    15243134 :         for (unsigned int j = 0; j < _num_p; ++j)
     245     8489992 :           _d2pp_dv[qp][i][j].assign(_num_p, 0);
     246             : 
     247     6753142 :         _seff_old[qp][i] = (*_material_seff_UO[i]).seff(_pressure_old_vals, qp);
     248     6753142 :         _seff[qp][i] = (*_material_seff_UO[i]).seff(_pressure_vals, qp);
     249             : 
     250     6753142 :         _dseff_dv[qp][i].resize(_num_p);
     251     6753142 :         (*_material_seff_UO[i]).dseff(_pressure_vals, qp, _dseff_dv[qp][i]);
     252             : 
     253     6753142 :         _d2seff_dv[qp][i].resize(_num_p);
     254    15243134 :         for (unsigned int j = 0; j < _num_p; ++j)
     255     8489992 :           _d2seff_dv[qp][i][j].resize(_num_p);
     256     6753142 :         (*_material_seff_UO[i]).d2seff(_pressure_vals, qp, _d2seff_dv[qp][i]);
     257             :       }
     258             :     }
     259             :     // the above lines of code are only valid for "pppp"
     260             :     // if you decide to code other RichardsVariables (eg "psss")
     261             :     // you will need to add some lines here
     262             :   }
     263     1899373 : }
     264             : 
     265             : void
     266     5884717 : RichardsMaterial::computeDerivedQuantities(unsigned int qp)
     267             : {
     268             :   // fluid viscosity
     269     5884717 :   _viscosity[qp].resize(_num_p);
     270    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     271     6753142 :     _viscosity[qp][i] = _material_viscosity[i];
     272             : 
     273             :   // fluid saturation
     274     5884717 :   _sat_old[qp].resize(_num_p);
     275     5884717 :   _sat[qp].resize(_num_p);
     276     5884717 :   _dsat_dv[qp].resize(_num_p);
     277    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     278             :   {
     279     6753142 :     _sat_old[qp][i] = (*_material_sat_UO[i]).sat(_seff_old[qp][i]);
     280     6753142 :     _sat[qp][i] = (*_material_sat_UO[i]).sat(_seff[qp][i]);
     281     6753142 :     _dsat_dv[qp][i].assign(_num_p, (*_material_sat_UO[i]).dsat(_seff[qp][i]));
     282    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     283     8489992 :       _dsat_dv[qp][i][j] *= _dseff_dv[qp][i][j];
     284             :   }
     285             : 
     286             :   // fluid density
     287     5884717 :   _density_old[qp].resize(_num_p);
     288     5884717 :   _density[qp].resize(_num_p);
     289     5884717 :   _ddensity_dv[qp].resize(_num_p);
     290    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     291             :   {
     292     6753142 :     _density_old[qp][i] = (*_material_density_UO[i]).density(_pp_old[qp][i]);
     293     6753142 :     _density[qp][i] = (*_material_density_UO[i]).density(_pp[qp][i]);
     294     6753142 :     _ddensity_dv[qp][i].assign(_num_p, (*_material_density_UO[i]).ddensity(_pp[qp][i]));
     295    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     296     8489992 :       _ddensity_dv[qp][i][j] *= _dpp_dv[qp][i][j];
     297             :   }
     298             : 
     299             :   // relative permeability
     300     5884717 :   _rel_perm[qp].resize(_num_p);
     301     5884717 :   _drel_perm_dv[qp].resize(_num_p);
     302    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     303             :   {
     304     6753142 :     _rel_perm[qp][i] = (*_material_relperm_UO[i]).relperm(_seff[qp][i]);
     305     6753142 :     _drel_perm_dv[qp][i].assign(_num_p, (*_material_relperm_UO[i]).drelperm(_seff[qp][i]));
     306    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     307     8489992 :       _drel_perm_dv[qp][i][j] *= _dseff_dv[qp][i][j];
     308             :   }
     309             : 
     310             :   // fluid mass
     311     5884717 :   _mass_old[qp].resize(_num_p);
     312     5884717 :   _mass[qp].resize(_num_p);
     313     5884717 :   _dmass[qp].resize(_num_p);
     314    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     315             :   {
     316     6753142 :     _mass_old[qp][i] = _porosity_old[qp] * _density_old[qp][i] * _sat_old[qp][i];
     317     6753142 :     _mass[qp][i] = _porosity[qp] * _density[qp][i] * _sat[qp][i];
     318     6753142 :     _dmass[qp][i].resize(_num_p);
     319    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     320     8489992 :       _dmass[qp][i][j] = _porosity[qp] * (_ddensity_dv[qp][i][j] * _sat[qp][i] +
     321     8489992 :                                           _density[qp][i] * _dsat_dv[qp][i][j]);
     322             :   }
     323             : 
     324             :   // flux without the mobility part
     325     5884717 :   _flux_no_mob[qp].resize(_num_p);
     326     5884717 :   _dflux_no_mob_dv[qp].resize(_num_p);
     327     5884717 :   _dflux_no_mob_dgradv[qp].resize(_num_p);
     328    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     329             :   {
     330     6753142 :     _flux_no_mob[qp][i] = _permeability[qp] * ((*_grad_p[i])[qp] - _density[qp][i] * _gravity[qp]);
     331             : 
     332     6753142 :     _dflux_no_mob_dv[qp][i].resize(_num_p);
     333    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     334     8489992 :       _dflux_no_mob_dv[qp][i][j] = _permeability[qp] * (-_ddensity_dv[qp][i][j] * _gravity[qp]);
     335             : 
     336     6753142 :     _dflux_no_mob_dgradv[qp][i].resize(_num_p);
     337    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     338     8489992 :       _dflux_no_mob_dgradv[qp][i][j] = _permeability[qp] * _dpp_dv[qp][i][j];
     339             :   }
     340             : 
     341             :   // flux
     342     5884717 :   _flux[qp].resize(_num_p);
     343     5884717 :   _dflux_dv[qp].resize(_num_p);
     344     5884717 :   _dflux_dgradv[qp].resize(_num_p);
     345    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     346             :   {
     347     6753142 :     _flux[qp][i] = _density[qp][i] * _rel_perm[qp][i] * _flux_no_mob[qp][i] / _viscosity[qp][i];
     348             : 
     349     6753142 :     _dflux_dv[qp][i].resize(_num_p);
     350    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     351             :     {
     352     8489992 :       _dflux_dv[qp][i][j] =
     353     8489992 :           _density[qp][i] * _rel_perm[qp][i] * _dflux_no_mob_dv[qp][i][j] / _viscosity[qp][i];
     354             :       _dflux_dv[qp][i][j] +=
     355     8489992 :           (_ddensity_dv[qp][i][j] * _rel_perm[qp][i] + _density[qp][i] * _drel_perm_dv[qp][i][j]) *
     356     8489992 :           _flux_no_mob[qp][i] / _viscosity[qp][i];
     357             :     }
     358             : 
     359     6753142 :     _dflux_dgradv[qp][i].resize(_num_p);
     360    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     361     8489992 :       _dflux_dgradv[qp][i][j] =
     362     8489992 :           _density[qp][i] * _rel_perm[qp][i] * _dflux_no_mob_dgradv[qp][i][j] / _viscosity[qp][i];
     363             :   }
     364     5884717 : }
     365             : 
     366             : void
     367     5884717 : RichardsMaterial::zero2ndDerivedQuantities(unsigned int qp)
     368             : {
     369     5884717 :   _d2flux_dvdv[qp].resize(_num_p);
     370     5884717 :   _d2flux_dgradvdv[qp].resize(_num_p);
     371     5884717 :   _d2flux_dvdgradv[qp].resize(_num_p);
     372             : 
     373    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     374             :   {
     375     6753142 :     _d2flux_dvdv[qp][i].resize(_num_p);
     376     6753142 :     _d2flux_dgradvdv[qp][i].resize(_num_p);
     377     6753142 :     _d2flux_dvdgradv[qp][i].resize(_num_p);
     378    15243134 :     for (unsigned int j = 0; j < _num_p; ++j)
     379             :     {
     380     8489992 :       _d2flux_dvdv[qp][i][j].assign(_num_p, RealVectorValue());
     381     8489992 :       _d2flux_dgradvdv[qp][i][j].assign(_num_p, RealTensorValue());
     382     8489992 :       _d2flux_dvdgradv[qp][i][j].assign(_num_p, RealTensorValue());
     383             :     }
     384             :   }
     385     5884717 : }
     386             : 
     387             : void
     388     5884717 : RichardsMaterial::compute2ndDerivedQuantities(unsigned int qp)
     389             : {
     390     5884717 :   zero2ndDerivedQuantities(qp);
     391             : 
     392    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     393             :   {
     394     6753142 :     if ((*_material_SUPG_UO[i]).SUPG_trivial())
     395      475124 :       continue; // as the derivatives won't be needed
     396             : 
     397             :     // second derivative of density
     398     6278018 :     _d2density[i].resize(_num_p);
     399     6278018 :     Real ddens = (*_material_density_UO[i]).ddensity(_pp[qp][i]);
     400     6278018 :     Real d2dens = (*_material_density_UO[i]).d2density(_pp[qp][i]);
     401    14199510 :     for (unsigned int j = 0; j < _num_p; ++j)
     402             :     {
     403     7921492 :       _d2density[i][j].resize(_num_p);
     404    19129932 :       for (unsigned int k = 0; k < _num_p; ++k)
     405    11208440 :         _d2density[i][j][k] =
     406    11208440 :             d2dens * _dpp_dv[qp][i][j] * _dpp_dv[qp][i][k] + ddens * _d2pp_dv[qp][i][j][k];
     407             :     }
     408             : 
     409             :     // second derivative of relative permeability
     410     6278018 :     _d2rel_perm_dv[i].resize(_num_p);
     411     6278018 :     Real drel = (*_material_relperm_UO[i]).drelperm(_seff[qp][i]);
     412     6278018 :     Real d2rel = (*_material_relperm_UO[i]).d2relperm(_seff[qp][i]);
     413    14199510 :     for (unsigned int j = 0; j < _num_p; ++j)
     414             :     {
     415     7921492 :       _d2rel_perm_dv[i][j].resize(_num_p);
     416    19129932 :       for (unsigned int k = 0; k < _num_p; ++k)
     417    11208440 :         _d2rel_perm_dv[i][j][k] =
     418    11208440 :             d2rel * _dseff_dv[qp][i][j] * _dseff_dv[qp][i][k] + drel * _d2seff_dv[qp][i][j][k];
     419             :     }
     420             : 
     421             :     // now compute the second derivs of the fluxes
     422    14199510 :     for (unsigned int j = 0; j < _num_p; ++j)
     423             :     {
     424    19129932 :       for (unsigned int k = 0; k < _num_p; ++k)
     425             :       {
     426    11208440 :         _d2flux_dvdv[qp][i][j][k] =
     427    11208440 :             _d2density[i][j][k] * _rel_perm[qp][i] *
     428    11208440 :             (_permeability[qp] * ((*_grad_p[i])[qp] - _density[qp][i] * _gravity[qp]));
     429             :         _d2flux_dvdv[qp][i][j][k] +=
     430    11208440 :             (_ddensity_dv[qp][i][j] * _drel_perm_dv[qp][i][k] +
     431    11208440 :              _ddensity_dv[qp][i][k] * _drel_perm_dv[qp][i][j]) *
     432    11208440 :             (_permeability[qp] * ((*_grad_p[i])[qp] - _density[qp][i] * _gravity[qp]));
     433             :         _d2flux_dvdv[qp][i][j][k] +=
     434    11208440 :             _density[qp][i] * _d2rel_perm_dv[i][j][k] *
     435    11208440 :             (_permeability[qp] * ((*_grad_p[i])[qp] - _density[qp][i] * _gravity[qp]));
     436    11208440 :         _d2flux_dvdv[qp][i][j][k] += (_ddensity_dv[qp][i][j] * _rel_perm[qp][i] +
     437    11208440 :                                       _density[qp][i] * _drel_perm_dv[qp][i][j]) *
     438    11208440 :                                      (_permeability[qp] * (-_ddensity_dv[qp][i][k] * _gravity[qp]));
     439    11208440 :         _d2flux_dvdv[qp][i][j][k] += (_ddensity_dv[qp][i][k] * _rel_perm[qp][i] +
     440    11208440 :                                       _density[qp][i] * _drel_perm_dv[qp][i][k]) *
     441    11208440 :                                      (_permeability[qp] * (-_ddensity_dv[qp][i][j] * _gravity[qp]));
     442    11208440 :         _d2flux_dvdv[qp][i][j][k] += _density[qp][i] * _rel_perm[qp][i] *
     443    11208440 :                                      (_permeability[qp] * (-_d2density[i][j][k] * _gravity[qp]));
     444             :       }
     445             :     }
     446    14199510 :     for (unsigned int j = 0; j < _num_p; ++j)
     447    19129932 :       for (unsigned int k = 0; k < _num_p; ++k)
     448    11208440 :         _d2flux_dvdv[qp][i][j][k] /= _viscosity[qp][i];
     449             : 
     450    14199510 :     for (unsigned int j = 0; j < _num_p; ++j)
     451             :     {
     452    19129932 :       for (unsigned int k = 0; k < _num_p; ++k)
     453             :       {
     454    11208440 :         _d2flux_dgradvdv[qp][i][j][k] = (_ddensity_dv[qp][i][k] * _rel_perm[qp][i] +
     455    11208440 :                                          _density[qp][i] * _drel_perm_dv[qp][i][k]) *
     456    11208440 :                                         _permeability[qp] * _dpp_dv[qp][i][j] / _viscosity[qp][i];
     457    11208440 :         _d2flux_dvdgradv[qp][i][k][j] = _d2flux_dgradvdv[qp][i][j][k];
     458             :       }
     459             :     }
     460             :   }
     461     5884717 : }
     462             : 
     463             : void
     464     5884717 : RichardsMaterial::zeroSUPG(unsigned int qp)
     465             : {
     466     5884717 :   _tauvel_SUPG[qp].assign(_num_p, RealVectorValue());
     467     5884717 :   _dtauvel_SUPG_dgradp[qp].resize(_num_p);
     468     5884717 :   _dtauvel_SUPG_dp[qp].resize(_num_p);
     469    12637859 :   for (unsigned int i = 0; i < _num_p; ++i)
     470             :   {
     471     6753142 :     _dtauvel_SUPG_dp[qp][i].assign(_num_p, RealVectorValue());
     472     6753142 :     _dtauvel_SUPG_dgradp[qp][i].assign(_num_p, RealTensorValue());
     473             :   }
     474     5884717 : }
     475             : 
     476             : void
     477     1756151 : RichardsMaterial::computeSUPG()
     478             : {
     479             :   // Grab reference to linear Lagrange finite element object pointer,
     480             :   // currently this is always a linear Lagrange element, so this might need to
     481             :   // be generalized if we start working with higher-order elements...
     482     5268453 :   auto && fe = _assembly.getFE(getParam<bool>("linear_shape_fcns") ? FEType(FIRST, LAGRANGE)
     483             :                                                                    : FEType(SECOND, LAGRANGE),
     484     1756151 :                                _current_elem->dim());
     485             : 
     486             :   // Grab references to FE object's mapping data from the _subproblem's FE object
     487     1756151 :   const std::vector<Real> & dxidx(fe->get_dxidx());
     488             :   const std::vector<Real> & dxidy(fe->get_dxidy());
     489             :   const std::vector<Real> & dxidz(fe->get_dxidz());
     490             :   const std::vector<Real> & detadx(fe->get_detadx());
     491             :   const std::vector<Real> & detady(fe->get_detady());
     492             :   const std::vector<Real> & detadz(fe->get_detadz());
     493             :   const std::vector<Real> & dzetadx(fe->get_dzetadx());
     494             :   const std::vector<Real> & dzetady(fe->get_dzetady());
     495             :   const std::vector<Real> & dzetadz(fe->get_dzetadz());
     496             : 
     497     7212432 :   for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
     498             :   {
     499             : 
     500             :     // Bounds checking on element data and putting into vector form
     501             :     mooseAssert(qp < dxidx.size(), "Insufficient data in dxidx array!");
     502             :     mooseAssert(qp < dxidy.size(), "Insufficient data in dxidy array!");
     503             :     mooseAssert(qp < dxidz.size(), "Insufficient data in dxidz array!");
     504     5456281 :     if (_mesh.dimension() >= 2)
     505             :     {
     506             :       mooseAssert(qp < detadx.size(), "Insufficient data in detadx array!");
     507             :       mooseAssert(qp < detady.size(), "Insufficient data in detady array!");
     508             :       mooseAssert(qp < detadz.size(), "Insufficient data in detadz array!");
     509             :     }
     510     5456281 :     if (_mesh.dimension() >= 3)
     511             :     {
     512             :       mooseAssert(qp < dzetadx.size(), "Insufficient data in dzetadx array!");
     513             :       mooseAssert(qp < dzetady.size(), "Insufficient data in dzetady array!");
     514             :       mooseAssert(qp < dzetadz.size(), "Insufficient data in dzetadz array!");
     515             :     }
     516             : 
     517             :     // CHECK : Does this work spherical, cylindrical, etc?
     518     5456281 :     RealVectorValue xi_prime(dxidx[qp], dxidy[qp], dxidz[qp]);
     519             :     RealVectorValue eta_prime, zeta_prime;
     520     5456281 :     if (_mesh.dimension() >= 2)
     521             :     {
     522     3122603 :       eta_prime(0) = detadx[qp];
     523     3122603 :       eta_prime(1) = detady[qp];
     524             :     }
     525     5456281 :     if (_mesh.dimension() == 3)
     526             :     {
     527     1725471 :       eta_prime(2) = detadz[qp];
     528     1725471 :       zeta_prime(0) = dzetadx[qp];
     529     1725471 :       zeta_prime(1) = dzetady[qp];
     530     1725471 :       zeta_prime(2) = dzetadz[qp];
     531             :     }
     532             : 
     533     5456281 :     _trace_perm = _permeability[qp].tr();
     534    11734299 :     for (unsigned int i = 0; i < _num_p; ++i)
     535             :     {
     536             :       RealVectorValue vel =
     537     6278018 :           (*_material_SUPG_UO[i])
     538     6278018 :               .velSUPG(_permeability[qp], (*_grad_p[i])[qp], _density[qp][i], _gravity[qp]);
     539     6278018 :       RealTensorValue dvel_dgradp = (*_material_SUPG_UO[i]).dvelSUPG_dgradp(_permeability[qp]);
     540             :       RealVectorValue dvel_dp =
     541             :           (*_material_SUPG_UO[i])
     542     6278018 :               .dvelSUPG_dp(_permeability[qp], _ddensity_dv[qp][i][i], _gravity[qp]);
     543             :       RealVectorValue bb =
     544     6278018 :           (*_material_SUPG_UO[i]).bb(vel, _mesh.dimension(), xi_prime, eta_prime, zeta_prime);
     545             :       RealVectorValue dbb2_dgradp =
     546     6278018 :           (*_material_SUPG_UO[i]).dbb2_dgradp(vel, dvel_dgradp, xi_prime, eta_prime, zeta_prime);
     547     6278018 :       Real dbb2_dp = (*_material_SUPG_UO[i]).dbb2_dp(vel, dvel_dp, xi_prime, eta_prime, zeta_prime);
     548     6278018 :       Real tau = (*_material_SUPG_UO[i]).tauSUPG(vel, _trace_perm, bb);
     549             :       RealVectorValue dtau_dgradp =
     550     6278018 :           (*_material_SUPG_UO[i]).dtauSUPG_dgradp(vel, dvel_dgradp, _trace_perm, bb, dbb2_dgradp);
     551     6278018 :       Real dtau_dp = (*_material_SUPG_UO[i]).dtauSUPG_dp(vel, dvel_dp, _trace_perm, bb, dbb2_dp);
     552             : 
     553     6278018 :       _tauvel_SUPG[qp][i] = tau * vel;
     554             : 
     555     6278018 :       RealTensorValue dtauvel_dgradp = tau * dvel_dgradp;
     556    25112072 :       for (const auto j : make_range(Moose::dim))
     557    75336216 :         for (const auto k : make_range(Moose::dim))
     558    56502162 :           dtauvel_dgradp(j, k) +=
     559    56502162 :               dtau_dgradp(j) * vel(k); // this is outerproduct - maybe libmesh can do it better?
     560    14199510 :       for (unsigned int j = 0; j < _num_p; ++j)
     561     7921492 :         _dtauvel_SUPG_dgradp[qp][i][j] = dtauvel_dgradp * _dpp_dv[qp][i][j];
     562             : 
     563             :       RealVectorValue dtauvel_dp = dtau_dp * vel + tau * dvel_dp;
     564    14199510 :       for (unsigned int j = 0; j < _num_p; ++j)
     565     7921492 :         _dtauvel_SUPG_dp[qp][i][j] = dtauvel_dp * _dpp_dv[qp][i][j];
     566             :     }
     567             :   }
     568     1756151 : }
     569             : 
     570             : void
     571     1899373 : RichardsMaterial::computeProperties()
     572             : {
     573             :   // compute porepressures and effective saturations
     574             :   // with algorithms depending on the _richards_name_UO.var_types()
     575     1899373 :   computePandSeff();
     576             : 
     577             :   // porosity, permeability, and gravity
     578     7784090 :   for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
     579             :   {
     580     5884717 :     _porosity[qp] = _material_por + _por_change[qp];
     581     5884717 :     _porosity_old[qp] = _material_por + _por_change_old[qp];
     582             : 
     583     5884717 :     _permeability[qp] = _material_perm;
     584    23538868 :     for (const auto i : make_range(Moose::dim))
     585    70616604 :       for (const auto j : make_range(Moose::dim))
     586    52962453 :         _permeability[qp](i, j) *= std::pow(10, (*_perm_change[LIBMESH_DIM * i + j])[qp]);
     587             : 
     588     5884717 :     _gravity[qp] = _material_gravity;
     589             :   }
     590             : 
     591             :   // compute "derived" quantities -- those that depend on P and Seff --- such as density, relperm
     592     7784090 :   for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
     593     5884717 :     computeDerivedQuantities(qp);
     594             : 
     595             :   // compute certain second derivatives of the derived quantities
     596             :   // These are needed in Jacobian calculations if doing SUPG
     597     7784090 :   for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
     598     5884717 :     compute2ndDerivedQuantities(qp);
     599             : 
     600             :   // Now for SUPG itself
     601     7784090 :   for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
     602     5884717 :     zeroSUPG(qp);
     603             : 
     604             :   // the following saves computational effort if all SUPG is trivial
     605             :   bool trivial_supg = true;
     606     4108964 :   for (unsigned int i = 0; i < _num_p; ++i)
     607     2209591 :     trivial_supg = trivial_supg && (*_material_SUPG_UO[i]).SUPG_trivial();
     608     1899373 :   if (trivial_supg)
     609             :     return;
     610             :   else
     611     1756151 :     computeSUPG();
     612             : }

Generated by: LCOV version 1.14