LCOV - code coverage report
Current view: top level - src/materials - ComputeISoilStress.C (source / functions) Hit Total Coverage
Test: idaholab/mastodon: 55510a Lines: 247 262 94.3 %
Date: 2025-08-26 23:09:31 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*************************************************/
       2             : /*           DO NOT MODIFY THIS HEADER           */
       3             : /*                                               */
       4             : /*                     MASTODON                  */
       5             : /*                                               */
       6             : /*    (c) 2015 Battelle Energy Alliance, LLC     */
       7             : /*            ALL RIGHTS RESERVED                */
       8             : /*                                               */
       9             : /*   Prepared by Battelle Energy Alliance, LLC   */
      10             : /*     With the U. S. Department of Energy       */
      11             : /*                                               */
      12             : /*     See COPYRIGHT for full restrictions       */
      13             : /*************************************************/
      14             : 
      15             : // This code was implemented in colloboration with Ozgun Numanoglu
      16             : // ([email protected]) and Omar Baltaji ([email protected]) from UIUC.
      17             : 
      18             : #include "ComputeISoilStress.h"
      19             : 
      20             : #include "MooseMesh.h"
      21             : #include "Function.h"
      22             : #include "MastodonUtils.h"
      23             : #include "ISoilUtils.h"
      24             : #include "Conversion.h"
      25             : #include "FEProblem.h"
      26             : 
      27             : registerMooseObject("MastodonApp", ComputeISoilStress);
      28             : 
      29             : InputParameters
      30         302 : ComputeISoilStress::validParams()
      31             : {
      32         302 :   InputParameters params = ComputeFiniteStrainElasticStress::validParams();
      33         302 :   params.addClassDescription("Compute total stress for the nonlinear material "
      34             :                              "model I-Soil using a backbone curve.");
      35         604 :   params.addRequiredCoupledVar("layer_variable",
      36             :                                "The auxvariable providing the soil layer identification.");
      37         604 :   params.addRequiredParam<std::vector<unsigned int>>(
      38             :       "layer_ids",
      39             :       "Vector of layer ids that map one-to-one to the rest of the "
      40             :       "soil layer parameters provided as input.");
      41         604 :   params.addRequiredParam<std::vector<Real>>("poissons_ratio",
      42             :                                              "Poissons's ratio for the soil layers. The "
      43             :                                              "size of the vector should be same as the size of "
      44             :                                              "layer_ids.");
      45         604 :   params.addParam<Real>("b_exp",
      46         604 :                         0.0,
      47             :                         "The exponential factors for pressure "
      48             :                         "dependent stiffness for all the soil "
      49             :                         "layers.");
      50         604 :   params.addParam<std::vector<Real>>("p_ref",
      51             :                                      {},
      52             :                                      "The reference pressure at which "
      53             :                                      "the parameters are defined for "
      54             :                                      "each soil layer. If 'soil_type = "
      55             :                                      "darendeli', then the reference "
      56             :                                      "pressure must be input in kilopascals.");
      57         604 :   params.addParam<Real>("a0",
      58         604 :                         1.0,
      59             :                         "The first coefficient for pressure dependent yield strength "
      60             :                         "calculation for all the soil layers. If a0 = 1, a1 = 0 and "
      61             :                         "a2=0 for one soil layer, then the yield strength of that "
      62             :                         "layer is independent of pressure.");
      63         604 :   params.addParam<Real>("a1",
      64         604 :                         0.0,
      65             :                         "The second coefficient for pressure dependent yield "
      66             :                         "strength calculation for all the soil layers. If a0 = "
      67             :                         "1, a1 = 0, a2 = 0 for one soil layer, then the yield "
      68             :                         "strength of that layer is independent of pressure.");
      69         604 :   params.addParam<Real>("a2",
      70         604 :                         0.0,
      71             :                         "The third coefficient for pressure dependent yield "
      72             :                         "strength calculation for all the soil layers. If a0 = "
      73             :                         "1, a1=0 and a2=0 for one soil layer, then the yield "
      74             :                         "strength of that layer is independent of pressure.");
      75         604 :   params.addParam<Real>("tension_pressure_cut_off",
      76         604 :                         -1.0,
      77             :                         "The tension cut-off for all the soil layers. If the "
      78             :                         "pressure becomes lower than this value, then the "
      79             :                         "stiffness of the soil reduces to zero. A negative "
      80             :                         "pressure indicates tension. The default "
      81             :                         "value is -1.0 for all the soil layers.");
      82         604 :   params.addParam<bool>("pressure_dependency",
      83         604 :                         false,
      84             :                         "Set to true to turn on pressure dependent stiffness "
      85             :                         "and yield strength calculation.");
      86         604 :   params.addParam<bool>(
      87         604 :       "wave_speed_calculation", true, "Set to false to turn off P and S wave speed calculation.");
      88         604 :   params.addParam<std::vector<FunctionName>>(
      89             :       "initial_soil_stress",
      90             :       {},
      91             :       "A list of functions describing the initial stress. There "
      92             :       "must be 9 functions, corresponding to the xx, yx, zx, xy, yy, zy, xz, yz, "
      93             :       "zz components respectively. If not provided, all components of the "
      94             :       "initial stress will be zero.");
      95             :   // params for specific backbone types
      96         604 :   MooseEnum soil_type("user_defined darendeli gqh thin_layer");
      97         604 :   params.addRequiredParam<MooseEnum>(
      98             :       "soil_type",
      99             :       soil_type,
     100             :       "This parameter determines the type of backbone curve used. Use 'user_defined' "
     101             :       "for a user defined backbone curve provided in a data file, 'darendeli' "
     102             :       "if the backbone curve is to be determined using Darandeli equations, 'gqh' "
     103             :       "if the backbone curve is determined using the GQ/H approach and 'thin_layer' if the soil is "
     104             :       "being used to simulate a thin-layer friction interface.");
     105             :   // params required for user_defined backbone curve: soil_type = 'user_defined'
     106         604 :   params.addParam<std::vector<FileName>>(
     107             :       "backbone_curve_files",
     108             :       "The vector of file names of the files containing "
     109             :       "stress-strain backbone curves for the different soil layers. The "
     110             :       "size of the vector should be same as the size of layer_ids. All files "
     111             :       "should contain the same number of stress-strain points. Headers are not "
     112             :       "expected and it is assumed that the first column corresponds to strain values "
     113             :       "and the second column corresponds to the stress values. Additionally, two "
     114             :       "segments of a backbone curve cannot have the same slope.");
     115             :   // params required for soil_type = 'darendeli', 'GQ/H' and 'thin_layer'
     116         604 :   params.addRequiredParam<std::vector<Real>>("initial_shear_modulus",
     117             :                                              "The initial shear modulus of the soil layers. ");
     118         604 :   params.addParam<MaterialPropertyName>("shear_modulus",
     119             :                                         "Name of Material Property  or a constant real number "
     120             :                                         "defining the shear modulus of the materials.");
     121             :   // params required for soil_type = 'darendeli' and 'GQ/H'
     122         604 :   params.addParam<unsigned int>("number_of_points",
     123             :                                 "The total number of data points in which the "
     124             :                                 "backbone curve needs to be split for all soil "
     125             :                                 "layers (required for Darandeli or GQ/H type backbone curves).");
     126             :   // params required for Darandeli backbone curve: soil_type = 'darendeli'
     127         604 :   params.addParam<std::vector<Real>>("over_consolidation_ratio",
     128             :                                      "The over consolidation ratio of the soil "
     129             :                                      "layers. Required for Darandeli backbone curve.");
     130         604 :   params.addParam<std::vector<Real>>(
     131             :       "plasticity_index",
     132             :       "The plasticity index of the soil layers. Required for Darandeli backbone curve.");
     133             :   // params required for GQ/H backbone curve: soil_type = "gqh"
     134         604 :   params.addParam<std::vector<Real>>("theta_1",
     135             :                                      "The curve fit coefficient for "
     136             :                                      "GQ/H model"
     137             :                                      "for each soil layer.");
     138         604 :   params.addParam<std::vector<Real>>("theta_2",
     139             :                                      "The curve fit coefficient for "
     140             :                                      "GQ/H model"
     141             :                                      "for each soil layer.");
     142         604 :   params.addParam<std::vector<Real>>("theta_3",
     143             :                                      "The curve fit coefficient for "
     144             :                                      "GQ/H model"
     145             :                                      "for each soil layer.");
     146         604 :   params.addParam<std::vector<Real>>("theta_4",
     147             :                                      "The curve fit coefficient for "
     148             :                                      "GQ/H model"
     149             :                                      "for each soil layer.");
     150         604 :   params.addParam<std::vector<Real>>("theta_5",
     151             :                                      "The curve fit coefficient for "
     152             :                                      "GQ/H model"
     153             :                                      "for each soil layer.");
     154         604 :   params.addParam<std::vector<Real>>("taumax",
     155             :                                      "The ultimate shear strength of "
     156             :                                      "the soil layers. Required for "
     157             :                                      "GQ/H model");
     158             :   // params required for thin_layer contact model soil_type = "thin_layer"
     159         604 :   params.addParam<std::vector<Real>>("friction_coefficient",
     160             :                                      "Friction coefficients of the thin layers.");
     161         604 :   params.addParam<std::vector<Real>>("hardening_ratio",
     162             :                                      "Post-yield hardening ratios of the layers.");
     163         302 :   return params;
     164         302 : }
     165             : 
     166         227 : ComputeISoilStress::ComputeISoilStress(const InputParameters & parameters)
     167             :   : ComputeFiniteStrainElasticStress(parameters),
     168         227 :     _strain_increment(getMaterialProperty<RankTwoTensor>(_base_name + "strain_increment")),
     169             :     _base_models(),
     170             :     _stress_model(),
     171             :     _stress_model_old(),
     172             :     _yield_stress(), // *** YIELD STRAIN NOT YIELD STRESS ***
     173             :     _youngs(),
     174         227 :     _soil_layer_variable(coupledValue("layer_variable")),
     175         454 :     _layer_ids(getParam<std::vector<unsigned int>>("layer_ids")),
     176         454 :     _wave_speed_calculation(getParam<bool>("wave_speed_calculation")),
     177         454 :     _poissons_ratio(getParam<std::vector<Real>>("poissons_ratio")),
     178         454 :     _density(_wave_speed_calculation ? &getMaterialProperty<Real>("density") : nullptr),
     179         454 :     _b_exp(getParam<Real>("b_exp")),
     180         454 :     _p_ref(getParam<std::vector<Real>>("p_ref")),
     181         454 :     _a0(getParam<Real>("a0")),
     182         454 :     _a1(getParam<Real>("a1")),
     183         454 :     _a2(getParam<Real>("a2")),
     184         454 :     _p0(getParam<Real>("tension_pressure_cut_off")),
     185         454 :     _pressure_dependency(getParam<bool>("pressure_dependency")),
     186         227 :     _strength_pressure_correction(1.0),
     187         227 :     _stiffness_pressure_correction(1.0),
     188         227 :     _shear_wave_speed(_wave_speed_calculation ? &declareProperty<Real>("shear_wave_speed")
     189             :                                               : nullptr),
     190         227 :     _P_wave_speed(_wave_speed_calculation ? &declareProperty<Real>("P_wave_speed") : nullptr),
     191         227 :     _tangent_modulus(0.0),
     192         227 :     _pos(0),
     193         227 :     _initial_soil_stress_provided(
     194         454 :         getParam<std::vector<FunctionName>>("initial_soil_stress").size() ==
     195         454 :         LIBMESH_DIM * LIBMESH_DIM)
     196             : {
     197             : 
     198             :   // checking that density, and Poisson's ratio are the same size as layer_ids
     199         227 :   if (_poissons_ratio.size() != _layer_ids.size())
     200           0 :     mooseError("Error in " + name() + ". Poisson's ratio should be of the same "
     201             :                                       "size as layer_ids.");
     202             :   // checks for pressure dependency
     203         227 :   if (_pressure_dependency && _b_exp == 0.0)
     204          29 :     mooseWarning("Warning in " + name() + ". Pressure dependency is set to true "
     205             :                                           "but b_exp is set to 0.0. Stiffness "
     206             :                                           "pressure dependency is NOT "
     207             :                                           "turned on.");
     208         226 :   if (_pressure_dependency && (_a0 == 1.0 && _a1 == 0.0 && _a2 == 0.0))
     209           2 :     mooseWarning("Warning in " + name() +
     210             :                  ". Pressure dependency is set to true but a0, a1 and a2 are "
     211             :                  "set to 1.0, 0.0 and 0.0, respectively. Strength "
     212             :                  "pressure dependency is NOT turned on.");
     213         225 :   if (_pressure_dependency && (_a0 == 0.0 && _a1 == 0.0 && _a2 == 0.0))
     214           0 :     mooseError("Error in " + name() +
     215             :                ". When pressure dependency is turned on, "
     216             :                "all three strength coefficients, a0, a1, and a2, "
     217             :                "cannot simultaneously be set to 0.0. This "
     218             :                "combination results in division by 0.");
     219         225 :   if (_pressure_dependency && _p_ref.size() != _layer_ids.size())
     220           0 :     mooseError("Error in " + name() + ". When pressure dependency is turned on, "
     221             :                                       "a positive reference pressure "
     222             :                                       "(compressive) has to be defined for all "
     223             :                                       "the soil layers and the same number of reference "
     224             :                                       "pressures as soil layers should be provided.");
     225         225 :   if (_pressure_dependency && MastodonUtils::isNegativeOrZero(_p_ref))
     226           0 :     mooseError("Error in " + name() +
     227             :                ". Please provide positive (compressive) values for reference pressure.");
     228             : 
     229             :   // Initializing backbone curve
     230         450 :   const MooseEnum & soil_type = getParam<MooseEnum>("soil_type");
     231         225 :   std::vector<std::vector<Real>> backbone_stress(_layer_ids.size());
     232         225 :   std::vector<std::vector<Real>> backbone_strain(_layer_ids.size());
     233         450 :   std::vector<Real> initial_shear_modulus = getParam<std::vector<Real>>("initial_shear_modulus");
     234             : 
     235             :   // Calculating backbone curve for soil_type = user_defined
     236         225 :   if (soil_type == "user_defined")
     237             :   {
     238             :     std::vector<FileName> backbone_curve_files =
     239         216 :         getParam<std::vector<FileName>>("backbone_curve_files");
     240          72 :     if (backbone_curve_files.size() != _layer_ids.size())
     241           0 :       mooseError("Error in " + name() +
     242             :                  ". A vector of file names needs to "
     243             :                  "be provided for `backbone_curve_files` and the size of this vector "
     244             :                  "should be same as that of `layers_ids`.");
     245          72 :     ISoilUtils::computeUserDefinedBackbone(
     246             :         backbone_stress, backbone_strain, _layer_ids, backbone_curve_files, name());
     247          72 :   }
     248             :   // Calculating backbone curve for soil_type = darendeli
     249         153 :   else if (soil_type == "darendeli")
     250             :   {
     251             :     std::vector<Real> over_consolidation_ratio =
     252         108 :         getParam<std::vector<Real>>("over_consolidation_ratio");
     253         108 :     std::vector<Real> plasticity_index = getParam<std::vector<Real>>("plasticity_index");
     254         108 :     unsigned int number_of_points = getParam<unsigned int>("number_of_points");
     255          54 :     if (initial_shear_modulus.size() != _layer_ids.size() ||
     256         108 :         over_consolidation_ratio.size() != _layer_ids.size() ||
     257             :         plasticity_index.size() != _layer_ids.size())
     258           0 :       mooseError("Error in " + name() + ". initial_shear_modulus, "
     259             :                                         "over_consolidation_ratio and plasticity_index must be "
     260             :                                         "of the same size as layer_ids.");
     261         108 :     if (MastodonUtils::isNegativeOrZero(over_consolidation_ratio) || number_of_points <= 0 ||
     262          54 :         MastodonUtils::isNegativeOrZero(initial_shear_modulus))
     263           0 :       mooseError("Error in " + name() + ". Positive values have to be provided "
     264             :                                         "for over_consolidation_ratio, "
     265             :                                         "number_of_points, "
     266             :                                         "and initial_shear_modulus.");
     267          54 :     ISoilUtils::computeDarendeliBackbone(backbone_stress,
     268             :                                          backbone_strain,
     269             :                                          _layer_ids,
     270             :                                          initial_shear_modulus,
     271             :                                          over_consolidation_ratio,
     272             :                                          plasticity_index,
     273             :                                          _p_ref,
     274             :                                          number_of_points,
     275             :                                          name());
     276          54 :   }
     277             :   // Calculating backbone curve for soil_type = gqh
     278          99 :   else if (soil_type == "gqh")
     279             :   {
     280         162 :     unsigned int number_of_points = getParam<unsigned int>("number_of_points");
     281         162 :     std::vector<Real> theta_1 = getParam<std::vector<Real>>("theta_1");
     282         162 :     std::vector<Real> theta_2 = getParam<std::vector<Real>>("theta_2");
     283         162 :     std::vector<Real> theta_3 = getParam<std::vector<Real>>("theta_3");
     284         162 :     std::vector<Real> theta_4 = getParam<std::vector<Real>>("theta_4");
     285         162 :     std::vector<Real> theta_5 = getParam<std::vector<Real>>("theta_5");
     286         243 :     std::vector<Real> taumax = getParam<std::vector<Real>>("taumax");
     287          81 :     std::vector<std::vector<Real>> modulus(_layer_ids.size());
     288          81 :     if (initial_shear_modulus.size() != _layer_ids.size() || theta_1.size() != _layer_ids.size() ||
     289          81 :         theta_2.size() != _layer_ids.size() || theta_3.size() != _layer_ids.size() ||
     290         162 :         theta_4.size() != _layer_ids.size() || theta_5.size() != _layer_ids.size() ||
     291             :         taumax.size() != _layer_ids.size())
     292           0 :       mooseError("Error in " + name() +
     293             :                  ". initial_shear_modulus, theta_1, "
     294             :                  "theta_2, theta_3, theta_4, theta_5 and taumax should be of the "
     295             :                  "same size as layer_ids.");
     296         162 :     if (number_of_points <= 0 || MastodonUtils::isNegativeOrZero(taumax) ||
     297          81 :         MastodonUtils::isNegativeOrZero(initial_shear_modulus))
     298           0 :       mooseError("Error in " + name() + ". Please provide positive values for number of points, "
     299             :                                         "taumax and initial_shear_modulus.");
     300          81 :     ISoilUtils::computeGQHBackbone(backbone_stress,
     301             :                                    backbone_strain,
     302             :                                    _layer_ids,
     303             :                                    initial_shear_modulus,
     304             :                                    number_of_points,
     305             :                                    theta_1,
     306             :                                    theta_2,
     307             :                                    theta_3,
     308             :                                    theta_4,
     309             :                                    theta_5,
     310             :                                    taumax);
     311          81 :   }
     312             :   // Calculating backbone curve for soil_type = thin_layer
     313          18 :   else if (soil_type == "thin_layer")
     314             :   {
     315          18 :     _pressure_dependency = true;
     316          18 :     _a0 = 0.0;
     317          18 :     _a1 = 0.0;
     318          18 :     _a2 = 1.0;
     319          36 :     std::vector<Real> friction_coefficient = getParam<std::vector<Real>>("friction_coefficient");
     320          54 :     std::vector<Real> hardening_ratio = getParam<std::vector<Real>>("hardening_ratio");
     321          18 :     if (initial_shear_modulus.size() != _layer_ids.size() ||
     322          36 :         friction_coefficient.size() != _layer_ids.size() ||
     323             :         hardening_ratio.size() != _layer_ids.size())
     324           0 :       mooseError("Error in " + name() + ". initial_shear_modulus, friction_coefficient, "
     325             :                                         "hardening_ratio and p_ref must be "
     326             :                                         "of the same size as layer_ids.");
     327          36 :     if (MastodonUtils::isNegativeOrZero(initial_shear_modulus) ||
     328          36 :         MastodonUtils::isNegativeOrZero(friction_coefficient) ||
     329          18 :         MastodonUtils::isNegativeOrZero(hardening_ratio))
     330           0 :       mooseError("Error in " + name() + ". Positive values have to be provided "
     331             :                                         "for `initial_shear_modulus`, "
     332             :                                         "`friction_coefficient` and `hardening_ratio`");
     333          18 :     ISoilUtils::computeCoulombBackbone(backbone_stress,
     334             :                                        backbone_strain,
     335             :                                        _layer_ids,
     336             :                                        initial_shear_modulus,
     337             :                                        friction_coefficient,
     338             :                                        hardening_ratio,
     339             :                                        _p_ref,
     340             :                                        name());
     341          18 :   }
     342             :   else
     343           0 :     mooseError("Error in " + name() + ". The parameter soil_type is invalid.");
     344             :   // Deconstructing the backbone curves for all the soil layers into
     345             :   // elastic-perfectly-plastic components. Each backbone curve is split up into
     346             :   // a set of youngs modulus and yield stress pairs.
     347         225 :   _youngs.resize(_layer_ids.size());
     348         225 :   _yield_stress.resize(_layer_ids.size());
     349         225 :   ISoilUtils::computeSoilLayerProperties(
     350             :       _youngs,
     351             :       _yield_stress, // *** CALCULATES YIELD STRAIN NOT YIELD STRESS ***
     352             :       backbone_stress,
     353             :       backbone_strain,
     354             :       _layer_ids,
     355             :       _poissons_ratio,
     356             :       name());
     357         225 :   _stress_model.resize(_youngs[0].size());
     358         225 :   _stress_model_old.resize(_youngs[0].size());
     359         225 :   _base_models.resize(_youngs[0].size());
     360        7038 :   for (std::size_t i = 0; i < _youngs[0].size(); i++)
     361             :   {
     362        6813 :     _base_models[i] = Moose::stringify(i);
     363        6813 :     _stress_model[i] = &declareProperty<RankTwoTensor>(_base_models[i] + "_stress_model");
     364        6813 :     _stress_model_old[i] =
     365       13626 :         &getMaterialPropertyOld<RankTwoTensor>(_base_models[i] + "_stress_model");
     366             :   }
     367             : 
     368             :   const std::vector<FunctionName> & fcn_names(
     369         450 :       getParam<std::vector<FunctionName>>("initial_soil_stress"));
     370         225 :   const unsigned num = fcn_names.size();
     371             : 
     372         225 :   if (!(num == 0 || num == LIBMESH_DIM * LIBMESH_DIM))
     373           0 :     mooseError("Either zero or ",
     374           0 :                LIBMESH_DIM * LIBMESH_DIM,
     375             :                " initial soil stress functions must be provided.  You supplied ",
     376             :                num,
     377             :                "\n");
     378             : 
     379         225 :   _initial_soil_stress.resize(num);
     380        1764 :   for (unsigned i = 0; i < num; ++i)
     381        1539 :     _initial_soil_stress[i] = &getFunctionByName(fcn_names[i]);
     382             : 
     383             :   _stress_new.zero();
     384             :   _individual_stress_increment.zero();
     385             :   _deviatoric_trial_stress.zero();
     386             : 
     387             :   // // checking that the input and the backbone shear modulus values are consistent.
     388             :   std::vector<Real> initial_shear;
     389         225 :   initial_shear.resize(_poissons_ratio.size());
     390             :   Real tmp = 0.0;
     391         810 :   for (std::size_t j = 0; j < _poissons_ratio.size(); j++)
     392             :   {
     393             :     tmp = 0.0;
     394       43398 :     for (std::size_t i = 0; i < _base_models.size(); i++)
     395             :     {
     396       42813 :       tmp += _youngs[j][i] / (2 * (1 + _poissons_ratio[j]));
     397             :     }
     398         585 :     initial_shear[j] = tmp;
     399             :   }
     400             : 
     401         225 :   bool value_bool = MastodonUtils::checkEqual(initial_shear, initial_shear_modulus, 5.0);
     402         225 :   if (value_bool == false)
     403           9 :     mooseWarning(
     404             :         "Shear moduli inferred from the backbone curve are different from the input values."
     405             :         " Using the backbone curve inferred value for further computations.");
     406         225 : }
     407             : 
     408             : void
     409        1888 : ComputeISoilStress::initQpStatefulProperties()
     410             : {
     411        1888 :   ComputeStressBase::initQpStatefulProperties();
     412        1888 :   if (_initial_soil_stress_provided)
     413             :   {
     414        7040 :     for (unsigned i = 0; i < LIBMESH_DIM; ++i)
     415       21120 :       for (unsigned j = 0; j < LIBMESH_DIM; ++j)
     416       15840 :         _stress[_qp](i, j) = _initial_soil_stress[i * LIBMESH_DIM + j]->value(_t, _q_point[_qp]);
     417             :   }
     418      152192 :   for (std::size_t i = 0; i < _base_models.size(); i++)
     419      150304 :     (*_stress_model[i])[_qp].zero();
     420             : 
     421             :   // Determine the current id for the soil. The variable which is a Real must be
     422             :   // converted to a unsigned int for lookup, so first
     423             :   // it is rounded to avoid Real values that are just below the desired value.
     424        1888 :   _current_id = static_cast<unsigned int>(std::round(_soil_layer_variable[_qp]));
     425             :   // Get the position of the current id in the layer_ids array
     426        1888 :   _pos = find(_layer_ids.begin(), _layer_ids.end(), _current_id) - _layer_ids.begin();
     427             : 
     428        1888 :   if (_wave_speed_calculation)
     429             :   {
     430             :     Real initial_youngs = 0.0;
     431      152192 :     for (std::size_t i = 0; i < _base_models.size(); i++)
     432      150304 :       initial_youngs += _youngs[_pos][i];
     433             : 
     434             :     // shear wave speed is sqrt(shear_modulus/density)
     435        1888 :     (*_shear_wave_speed)[_qp] =
     436        1888 :         std::sqrt(initial_youngs / (2.0 * (1.0 + _poissons_ratio[_pos])) / (*_density)[_qp]);
     437             : 
     438             :     // P wave speed is sqrt(P wave modulus/density)
     439        1888 :     (*_P_wave_speed)[_qp] =
     440        1888 :         std::sqrt(initial_youngs * (1.0 - _poissons_ratio[_pos]) / (1.0 + _poissons_ratio[_pos]) /
     441        1888 :                   (1.0 - 2.0 * _poissons_ratio[_pos]) / (*_density)[_qp]);
     442             :   }
     443             : 
     444             :   // determine the lateral and vertical stresses
     445        1888 :   Real residual_vertical = _stress[_qp](2, 2);
     446        1888 :   Real residual_xx = _stress[_qp](0, 0);
     447        1888 :   Real residual_yy = _stress[_qp](1, 1);
     448        1888 :   Real mean_stress = _stress[_qp].trace() / (-3.0);
     449             : 
     450        1888 :   if (_pressure_dependency)
     451             :   {
     452         192 :     _stiffness_pressure_correction = pow((mean_stress - _p0) / _p_ref[_pos], _b_exp);
     453         192 :     _strength_pressure_correction =
     454         192 :         std::sqrt(_a0 + _a1 * (mean_stress - _p0) +
     455         192 :                   _a2 * (mean_stress - _p0) * (mean_stress - _p0)) /
     456         192 :         std::sqrt(_a0 + _a1 * (_p_ref[_pos]) + _a2 * (_p_ref[_pos]) * (_p_ref[_pos]));
     457             :   }
     458             : 
     459             :   // Calculate the K0 consistent stress distribution
     460        1888 :   RankTwoTensor dev_model;
     461      152192 :   for (std::size_t i = 0; i < _base_models.size(); i++)
     462             :   {
     463             :     Real _mean_pressure = 0.0;
     464      150304 :     if (residual_vertical != 0.0)
     465             :     {
     466             :       Real sum_youngs = 0.0;
     467             : 
     468     7268224 :       for (std::size_t j = i; j < _base_models.size(); j++)
     469     7124704 :         sum_youngs += _youngs[_pos][j];
     470             : 
     471      143520 :       (*_stress_model[i])[_qp](2, 2) = residual_vertical * _youngs[_pos][i] / sum_youngs;
     472      143520 :       (*_stress_model[i])[_qp](0, 0) = residual_xx * _youngs[_pos][i] / sum_youngs;
     473      143520 :       (*_stress_model[i])[_qp](1, 1) = residual_yy * _youngs[_pos][i] / sum_youngs;
     474      143520 :       dev_model = ((*_stress_model[i])[_qp]).deviatoric() / _youngs[_pos][i];
     475      143520 :       _mean_pressure = (*_stress_model[i])[_qp].trace() / 3.0;
     476      143520 :       Real J2_model = dev_model.doubleContraction(dev_model);
     477      143520 :       Real dev_stress_model = std::sqrt(3.0 / 2.0 * J2_model);
     478      143520 :       if (dev_stress_model > _yield_stress[_pos][i] * _strength_pressure_correction)
     479       92336 :         dev_model *= (_yield_stress[_pos][i] * _strength_pressure_correction) / dev_stress_model;
     480             : 
     481      143520 :       (*_stress_model[i])[_qp] = dev_model * _youngs[_pos][i]; // stress_model contains only the
     482             :                                                                // deviatoric part of the stress
     483             :     }
     484      150304 :     residual_vertical = residual_vertical - (*_stress_model[i])[_qp](2, 2) - _mean_pressure;
     485      150304 :     residual_xx = residual_xx - (*_stress_model[i])[_qp](0, 0) - _mean_pressure;
     486      150304 :     residual_yy = residual_yy - (*_stress_model[i])[_qp](1, 1) - _mean_pressure;
     487             :   }
     488        1888 : }
     489             : 
     490             : void
     491     1566064 : ComputeISoilStress::computeQpStress()
     492             : {
     493             :   // Nothing to update during the first time step, return immediately
     494     1566064 :   if (_t_step == 0)
     495             :     return;
     496             : 
     497             :   _stress_new.zero();
     498     1565120 :   computeStress();
     499     1565120 :   _stress[_qp] = _rotation_increment[_qp] * _stress_new * _rotation_increment[_qp].transpose();
     500             : 
     501             :   // Compute dstress_dstrain
     502     1565120 :   if (_tangent_modulus == 0.0)
     503      120848 :     _tangent_modulus = _youngs[_pos][_youngs.size() - 1];
     504             : 
     505     1565120 :   Real lame_1 = _elasticity_tensor[_qp](0, 0, 1, 1);
     506     1565120 :   Real lame_2 = (_elasticity_tensor[_qp](0, 0, 0, 0) - lame_1) / 2;
     507     1565120 :   Real initial_youngs = (lame_2 * (3 * lame_1 + 2 * lame_2)) / (lame_1 + lame_2);
     508             : 
     509     1565120 :   _Jacobian_mult[_qp] =
     510     1565120 :       _elasticity_tensor[_qp] * _tangent_modulus / initial_youngs; // This is NOT the exact jacobian
     511             : }
     512             : 
     513             : void
     514     1565120 : ComputeISoilStress::computeStress()
     515             : {
     516     1565120 :   if (_t_step == 0)
     517           0 :     return;
     518             : 
     519             :   // Determine the current id for the soil. The variable which is a Real must be
     520             :   // converted to a unsigned int for lookup, so first
     521             :   // it is rounded to avoid Real values that are just below the desired value.
     522     1565120 :   _current_id = static_cast<unsigned int>(std::round(_soil_layer_variable[_qp]));
     523             : 
     524             :   // Get the position of the current id in the layer_ids array
     525     1565120 :   _pos = find(_layer_ids.begin(), _layer_ids.end(), _current_id) - _layer_ids.begin();
     526             : 
     527             :   _individual_stress_increment.zero();
     528             : 
     529             :   _deviatoric_trial_stress.zero();
     530             : 
     531     1565120 :   _tangent_modulus = 0.0;
     532             : 
     533             :   // current pressure calculation
     534     1565120 :   Real mean_stress = _stress_old[_qp].trace() / (-3.0);
     535     1565120 :   if (mean_stress < _p0)
     536             :     mean_stress = 0.0;
     537             : 
     538     1565120 :   if (_pressure_dependency)
     539             :   {
     540      361152 :     _stiffness_pressure_correction = pow((mean_stress - _p0) / _p_ref[_pos], _b_exp);
     541      361152 :     _strength_pressure_correction =
     542      361152 :         std::sqrt(_a0 + _a1 * (mean_stress - _p0) +
     543      361152 :                   _a2 * (mean_stress - _p0) * (mean_stress - _p0)) /
     544      361152 :         std::sqrt(_a0 + _a1 * (_p_ref[_pos]) + _a2 * (_p_ref[_pos]) * (_p_ref[_pos]));
     545             :   }
     546             : 
     547     1565120 :   _mean_pressure = 0.0;
     548             : 
     549     1565120 :   Real lame_1 = _elasticity_tensor[_qp](0, 0, 1, 1);
     550     1565120 :   Real lame_2 = (_elasticity_tensor[_qp](0, 0, 0, 0) - lame_1) / 2;
     551     1565120 :   Real initial_youngs = (lame_2 * (3 * lame_1 + 2 * lame_2)) / (lame_1 + lame_2);
     552             : 
     553             :   // compute trial stress increment - note that _elasticity_tensor here
     554     1565120 :   _individual_stress_increment =
     555     1565120 :       _elasticity_tensor[_qp] * (_strain_increment[_qp]) / initial_youngs;
     556             : 
     557     1565120 :   _mean_pressure_tmp = _individual_stress_increment.trace() / 3.0 * _stiffness_pressure_correction;
     558             : 
     559     1565120 :   _deviatoric_trial_stress_tmp =
     560     1565120 :       _individual_stress_increment.deviatoric() * _stiffness_pressure_correction;
     561             : 
     562     1565120 :   _dev_trial_stress_squared = 0.0;
     563             : 
     564     1565120 :   _effective_trial_stress = 0.0;
     565             : 
     566     1565120 :   _yield_condition = 0.0;
     567             : 
     568    48474752 :   for (std::size_t i = 0; i < _base_models.size(); i++)
     569             :   {
     570             : 
     571             :     // calculate pressure for each element
     572    46909632 :     _mean_pressure += _mean_pressure_tmp * _youngs[_pos][i];
     573             : 
     574             :     // compute the deviatoric trial stress normalized by non pressure dependent
     575             :     // youngs modulus.
     576    46909632 :     _deviatoric_trial_stress =
     577    46909632 :         _deviatoric_trial_stress_tmp + (*_stress_model_old[i])[_qp] / (_youngs[_pos][i]);
     578             : 
     579             :     // compute the effective trial stress
     580    46909632 :     _dev_trial_stress_squared =
     581    46909632 :         _deviatoric_trial_stress.doubleContraction(_deviatoric_trial_stress);
     582    46909632 :     _effective_trial_stress = std::sqrt(3.0 / 2.0 * _dev_trial_stress_squared);
     583             : 
     584             :     // check yield condition and calculate plastic strain
     585    46909632 :     _yield_condition =
     586    46909632 :         _effective_trial_stress - _yield_stress[_pos][i] * _strength_pressure_correction;
     587             : 
     588    46909632 :     if (_yield_condition > 0.0)
     589             :       _deviatoric_trial_stress *=
     590    18559303 :           _yield_stress[_pos][i] * _strength_pressure_correction / _effective_trial_stress;
     591             :     else
     592    28350329 :       _tangent_modulus += _youngs[_pos][i];
     593             : 
     594    46909632 :     (*_stress_model[i])[_qp] = _youngs[_pos][i] * (_deviatoric_trial_stress);
     595             : 
     596    46909632 :     _stress_new += (*_stress_model[i])[_qp];
     597             :   }
     598     1565120 :   _stress_new(0, 0) += _mean_pressure - mean_stress;
     599     1565120 :   _stress_new(1, 1) += _mean_pressure - mean_stress;
     600     1565120 :   _stress_new(2, 2) += _mean_pressure - mean_stress;
     601             : 
     602     1565120 :   _tangent_modulus *= _stiffness_pressure_correction;
     603             : }

Generated by: LCOV version 1.14