LCOV - code coverage report
Current view: top level - src/materials/crystal_plasticity - ComputeMultipleCrystalPlasticityStress.C (source / functions) Hit Total Coverage
Test: idaholab/moose tensor_mechanics: d6b47a Lines: 302 356 84.8 %
Date: 2024-02-27 11:53:14 Functions: 18 19 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://www.mooseframework.org
       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 "ComputeMultipleCrystalPlasticityStress.h"
      11             : 
      12             : #include "CrystalPlasticityStressUpdateBase.h"
      13             : #include "libmesh/utility.h"
      14             : #include "Conversion.h"
      15             : #include "MooseException.h"
      16             : 
      17             : registerMooseObject("TensorMechanicsApp", ComputeMultipleCrystalPlasticityStress);
      18             : 
      19             : InputParameters
      20         585 : ComputeMultipleCrystalPlasticityStress::validParams()
      21             : {
      22         585 :   InputParameters params = ComputeFiniteStrainElasticStress::validParams();
      23             : 
      24         585 :   params.addClassDescription(
      25             :       "Crystal Plasticity base class: handles the Newton iteration over the stress residual and "
      26             :       "calculates the Jacobian based on constitutive laws from multiple material classes "
      27             :       "that are inherited from CrystalPlasticityStressUpdateBase");
      28        1170 :   params.addParam<std::string>(
      29             :       "base_name",
      30             :       "Optional parameter that allows the user to define multiple mechanics material systems on "
      31             :       "the same block, i.e. for multiple phases");
      32             : 
      33        1170 :   params.addRequiredParam<std::vector<MaterialName>>(
      34             :       "crystal_plasticity_models",
      35             :       "The material objects to use to calculate crystal plasticity stress and strains.");
      36        1170 :   params.addParam<std::vector<MaterialName>>(
      37             :       "eigenstrain_names", {}, "The material objects to calculate eigenstrains.");
      38        1170 :   params.addParam<MooseEnum>("tan_mod_type",
      39        1755 :                              MooseEnum("exact none", "none"),
      40             :                              "Type of tangent moduli for preconditioner: default elastic");
      41        1170 :   params.addParam<Real>("rtol", 1e-6, "Constitutive stress residual relative tolerance");
      42        1170 :   params.addParam<Real>("abs_tol", 1e-6, "Constitutive stress residual absolute tolerance");
      43        1170 :   params.addParam<unsigned int>("maxiter", 100, "Maximum number of iterations for stress update");
      44        1170 :   params.addParam<unsigned int>(
      45        1170 :       "maxiter_state_variable", 100, "Maximum number of iterations for state variable update");
      46        1170 :   params.addParam<unsigned int>(
      47        1170 :       "maximum_substep_iteration", 1, "Maximum number of substep iteration");
      48        1170 :   params.addParam<bool>("use_line_search", false, "Use line search in constitutive update");
      49        1170 :   params.addParam<Real>("min_line_search_step_size", 0.01, "Minimum line search step size");
      50        1170 :   params.addParam<Real>("line_search_tol", 0.5, "Line search bisection method tolerance");
      51        1170 :   params.addParam<unsigned int>(
      52        1170 :       "line_search_maxiter", 20, "Line search bisection method maximum number of iteration");
      53        1170 :   params.addParam<MooseEnum>("line_search_method",
      54        1755 :                              MooseEnum("CUT_HALF BISECTION", "CUT_HALF"),
      55             :                              "The method used in line search");
      56        1170 :   params.addParam<bool>(
      57             :       "print_state_variable_convergence_error_messages",
      58        1170 :       false,
      59             :       "Whether or not to print warning messages from the crystal plasticity specific convergence "
      60             :       "checks on the stress measure and general constitutive model quantinties.");
      61         585 :   return params;
      62           0 : }
      63             : 
      64         438 : ComputeMultipleCrystalPlasticityStress::ComputeMultipleCrystalPlasticityStress(
      65         438 :     const InputParameters & parameters)
      66             :   : ComputeFiniteStrainElasticStress(parameters),
      67         438 :     _num_models(getParam<std::vector<MaterialName>>("crystal_plasticity_models").size()),
      68         876 :     _num_eigenstrains(getParam<std::vector<MaterialName>>("eigenstrain_names").size()),
      69         912 :     _base_name(isParamValid("base_name") ? getParam<std::string>("base_name") + "_" : ""),
      70         876 :     _elasticity_tensor(getMaterialPropertyByName<RankFourTensor>(_base_name + "elasticity_tensor")),
      71         876 :     _rtol(getParam<Real>("rtol")),
      72         876 :     _abs_tol(getParam<Real>("abs_tol")),
      73         876 :     _maxiter(getParam<unsigned int>("maxiter")),
      74         876 :     _maxiterg(getParam<unsigned int>("maxiter_state_variable")),
      75         876 :     _tan_mod_type(getParam<MooseEnum>("tan_mod_type").getEnum<TangentModuliType>()),
      76         876 :     _max_substep_iter(getParam<unsigned int>("maximum_substep_iteration")),
      77         876 :     _use_line_search(getParam<bool>("use_line_search")),
      78         876 :     _min_line_search_step_size(getParam<Real>("min_line_search_step_size")),
      79         876 :     _line_search_tolerance(getParam<Real>("line_search_tol")),
      80         876 :     _line_search_max_iterations(getParam<unsigned int>("line_search_maxiter")),
      81         876 :     _line_search_method(getParam<MooseEnum>("line_search_method").getEnum<LineSearchMethod>()),
      82         438 :     _plastic_deformation_gradient(declareProperty<RankTwoTensor>("plastic_deformation_gradient")),
      83         438 :     _plastic_deformation_gradient_old(
      84         438 :         getMaterialPropertyOld<RankTwoTensor>("plastic_deformation_gradient")),
      85         438 :     _eigenstrain_deformation_gradient(
      86         438 :         _num_eigenstrains ? &declareProperty<RankTwoTensor>("eigenstrain_deformation_gradient")
      87             :                           : nullptr),
      88         438 :     _eigenstrain_deformation_gradient_old(
      89         438 :         _num_eigenstrains
      90         507 :             ? &getMaterialPropertyOld<RankTwoTensor>("eigenstrain_deformation_gradient")
      91             :             : nullptr),
      92         876 :     _deformation_gradient(getMaterialProperty<RankTwoTensor>(_base_name + "deformation_gradient")),
      93         438 :     _deformation_gradient_old(
      94         438 :         getMaterialPropertyOld<RankTwoTensor>(_base_name + "deformation_gradient")),
      95         438 :     _pk2(declareProperty<RankTwoTensor>("second_piola_kirchhoff_stress")),
      96         876 :     _pk2_old(getMaterialPropertyOld<RankTwoTensor>("second_piola_kirchhoff_stress")),
      97         438 :     _total_lagrangian_strain(
      98         438 :         declareProperty<RankTwoTensor>("total_lagrangian_strain")), // Lagrangian strain
      99         438 :     _updated_rotation(declareProperty<RankTwoTensor>("updated_rotation")),
     100         438 :     _crysrot(getMaterialProperty<RankTwoTensor>(
     101         438 :         _base_name + "crysrot")), // defined in the elasticity tensor classes for crystal plasticity
     102        1752 :     _print_convergence_message(getParam<bool>("print_state_variable_convergence_error_messages"))
     103             : {
     104         438 :   _convergence_failed = false;
     105         438 : }
     106             : 
     107             : void
     108       11392 : ComputeMultipleCrystalPlasticityStress::initQpStatefulProperties()
     109             : {
     110       11392 :   _plastic_deformation_gradient[_qp].zero();
     111       11392 :   _plastic_deformation_gradient[_qp].addIa(1.0);
     112             : 
     113       11392 :   if (_num_eigenstrains)
     114             :   {
     115        3200 :     (*_eigenstrain_deformation_gradient)[_qp].zero();
     116        3200 :     (*_eigenstrain_deformation_gradient)[_qp].addIa(1.0);
     117             :   }
     118             :   else
     119             :   {
     120             :     // set to identity if no eigenstrain is added
     121             :     _inverse_eigenstrain_deformation_grad.zero();
     122        8192 :     _inverse_eigenstrain_deformation_grad.addIa(1.0);
     123             :   }
     124             : 
     125       11392 :   _pk2[_qp].zero();
     126             : 
     127       11392 :   _total_lagrangian_strain[_qp].zero();
     128             : 
     129       11392 :   _updated_rotation[_qp].zero();
     130       11392 :   _updated_rotation[_qp].addIa(1.0);
     131             : 
     132       24064 :   for (unsigned int i = 0; i < _num_models; ++i)
     133             :   {
     134       12672 :     _models[i]->setQp(_qp);
     135       12672 :     _models[i]->initQpStatefulProperties();
     136             :   }
     137             : 
     138       14624 :   for (unsigned int i = 0; i < _num_eigenstrains; ++i)
     139             :   {
     140        3232 :     _eigenstrains[i]->setQp(_qp);
     141        3232 :     _eigenstrains[i]->initQpStatefulProperties();
     142             :   }
     143       11392 : }
     144             : 
     145             : void
     146         396 : ComputeMultipleCrystalPlasticityStress::initialSetup()
     147             : {
     148             :   // get crystal plasticity models
     149             :   std::vector<MaterialName> model_names =
     150         792 :       getParam<std::vector<MaterialName>>("crystal_plasticity_models");
     151             : 
     152         837 :   for (unsigned int i = 0; i < _num_models; ++i)
     153             :   {
     154             :     CrystalPlasticityStressUpdateBase * model =
     155         441 :         dynamic_cast<CrystalPlasticityStressUpdateBase *>(&getMaterialByName(model_names[i]));
     156             : 
     157         441 :     if (model)
     158             :     {
     159         441 :       _models.push_back(model);
     160             :       // TODO: check to make sure that the material model is compatible with this class
     161             :     }
     162             :     else
     163           0 :       mooseError("Model " + model_names[i] +
     164             :                  " is not compatible with ComputeMultipleCrystalPlasticityStress");
     165             :   }
     166             : 
     167             :   // get crystal plasticity eigenstrains
     168             :   std::vector<MaterialName> eigenstrain_names =
     169         792 :       getParam<std::vector<MaterialName>>("eigenstrain_names");
     170             : 
     171         474 :   for (unsigned int i = 0; i < _num_eigenstrains; ++i)
     172             :   {
     173             :     ComputeCrystalPlasticityEigenstrainBase * eigenstrain =
     174          78 :         dynamic_cast<ComputeCrystalPlasticityEigenstrainBase *>(
     175          78 :             &getMaterialByName(eigenstrain_names[i]));
     176             : 
     177          78 :     if (eigenstrain)
     178          78 :       _eigenstrains.push_back(eigenstrain);
     179             :     else
     180           0 :       mooseError("Eigenstrain" + eigenstrain_names[i] +
     181             :                  " is not compatible with ComputeMultipleCrystalPlasticityStress");
     182             :   }
     183         396 : }
     184             : 
     185             : void
     186      846917 : ComputeMultipleCrystalPlasticityStress::computeQpStress()
     187             : {
     188     1784074 :   for (unsigned int i = 0; i < _num_models; ++i)
     189      937157 :     _models[i]->setQp(_qp);
     190             : 
     191     1146415 :   for (unsigned int i = 0; i < _num_eigenstrains; ++i)
     192      299498 :     _eigenstrains[i]->setQp(_qp);
     193             : 
     194      846917 :   updateStress(_stress[_qp], _Jacobian_mult[_qp]); // This is NOT the exact jacobian
     195      846785 : }
     196             : 
     197             : void
     198      846917 : ComputeMultipleCrystalPlasticityStress::updateStress(RankTwoTensor & cauchy_stress,
     199             :                                                      RankFourTensor & jacobian_mult)
     200             : {
     201             :   // Does not support face/boundary material property calculation
     202      846917 :   if (isBoundaryMaterial())
     203             :     return;
     204             : 
     205             :   // Initialize substepping variables
     206             :   unsigned int substep_iter = 1;
     207             :   unsigned int num_substep = 1;
     208             : 
     209      845637 :   _temporary_deformation_gradient_old = _deformation_gradient_old[_qp];
     210      845637 :   if (_temporary_deformation_gradient_old.det() == 0)
     211           0 :     _temporary_deformation_gradient_old.addIa(1.0);
     212             : 
     213      845637 :   _delta_deformation_gradient = _deformation_gradient[_qp] - _temporary_deformation_gradient_old;
     214             : 
     215             :   // Loop through all models and calculate the schmid tensor for the current state of the crystal
     216             :   // lattice
     217             :   // Not sure if we should pass in the updated or the original rotation here
     218             :   // If not, then we should not need to compute the flow direction every iteration here
     219     1781514 :   for (unsigned int i = 0; i < _num_models; ++i)
     220      935877 :     _models[i]->calculateFlowDirection(_crysrot[_qp]);
     221             : 
     222             :   do
     223             :   {
     224      935027 :     _convergence_failed = false;
     225      935027 :     preSolveQp();
     226             : 
     227      935027 :     _substep_dt = _dt / num_substep;
     228     1960294 :     for (unsigned int i = 0; i < _num_models; ++i)
     229     1025267 :       _models[i]->setSubstepDt(_substep_dt);
     230             : 
     231             :     // calculate F^{eigen} only when we have eigenstrain
     232      935027 :     if (_num_eigenstrains)
     233      341410 :       calculateEigenstrainDeformationGrad();
     234             : 
     235     2007074 :     for (unsigned int istep = 0; istep < num_substep; ++istep)
     236             :     {
     237             :       _temporary_deformation_gradient =
     238     1161569 :           (static_cast<Real>(istep) + 1) / num_substep * _delta_deformation_gradient;
     239     1161569 :       _temporary_deformation_gradient += _temporary_deformation_gradient_old;
     240             : 
     241     1161569 :       solveQp();
     242             : 
     243     1161565 :       if (_convergence_failed)
     244             :       {
     245       89508 :         if (_print_convergence_message)
     246           0 :           mooseWarning(
     247             :               "The crystal plasticity constitutive model has failed to converge. Increasing "
     248             :               "the number of substeps.");
     249             : 
     250       89508 :         substep_iter++;
     251       89508 :         num_substep *= 2;
     252       89508 :         break;
     253             :       }
     254             :     }
     255             : 
     256      935013 :     if (substep_iter > _max_substep_iter && _convergence_failed)
     257         118 :       mooseException("ComputeMultipleCrystalPlasticityStress: Constitutive failure");
     258      934895 :   } while (_convergence_failed);
     259             : 
     260      845505 :   postSolveQp(cauchy_stress, jacobian_mult);
     261             : }
     262             : 
     263             : void
     264      935027 : ComputeMultipleCrystalPlasticityStress::preSolveQp()
     265             : {
     266     1960294 :   for (unsigned int i = 0; i < _num_models; ++i)
     267     1025267 :     _models[i]->setInitialConstitutiveVariableValues();
     268             : 
     269      935027 :   _pk2[_qp] = _pk2_old[_qp];
     270      935027 :   _inverse_plastic_deformation_grad_old = _plastic_deformation_gradient_old[_qp].inverse();
     271      935027 : }
     272             : 
     273             : void
     274     1161569 : ComputeMultipleCrystalPlasticityStress::solveQp()
     275             : {
     276     2413378 :   for (unsigned int i = 0; i < _num_models; ++i)
     277             :   {
     278     1251809 :     _models[i]->setSubstepConstitutiveVariableValues();
     279     1251809 :     _models[i]->calculateSlipResistance();
     280             :   }
     281             : 
     282     1161569 :   _inverse_plastic_deformation_grad = _inverse_plastic_deformation_grad_old;
     283             : 
     284     1161569 :   solveStateVariables();
     285     1161565 :   if (_convergence_failed)
     286             :     return; // pop back up and take a smaller substep
     287             : 
     288     2234354 :   for (unsigned int i = 0; i < _num_models; ++i)
     289     1162297 :     _models[i]->updateSubstepConstitutiveVariableValues();
     290             : 
     291             :   // save off the old F^{p} inverse now that have converged on the stress and state variables
     292     1072057 :   _inverse_plastic_deformation_grad_old = _inverse_plastic_deformation_grad;
     293             : }
     294             : 
     295             : void
     296      845505 : ComputeMultipleCrystalPlasticityStress::postSolveQp(RankTwoTensor & cauchy_stress,
     297             :                                                     RankFourTensor & jacobian_mult)
     298             : {
     299      845505 :   cauchy_stress = _elastic_deformation_gradient * _pk2[_qp] *
     300      845505 :                   _elastic_deformation_gradient.transpose() / _elastic_deformation_gradient.det();
     301             : 
     302      845505 :   calcTangentModuli(jacobian_mult);
     303             : 
     304      845505 :   _total_lagrangian_strain[_qp] =
     305      845505 :       _deformation_gradient[_qp].transpose() * _deformation_gradient[_qp] -
     306      845505 :       RankTwoTensor::Identity();
     307      845505 :   _total_lagrangian_strain[_qp] = _total_lagrangian_strain[_qp] * 0.5;
     308             : 
     309             :   // Calculate crystal rotation to track separately
     310      845505 :   RankTwoTensor rot;
     311      845505 :   _elastic_deformation_gradient.getRUDecompositionRotation(rot);
     312      845505 :   _updated_rotation[_qp] = rot * _crysrot[_qp];
     313      845505 : }
     314             : 
     315             : void
     316     1161569 : ComputeMultipleCrystalPlasticityStress::solveStateVariables()
     317             : {
     318             :   unsigned int iteration;
     319             :   bool iter_flag = true;
     320             : 
     321             :   iteration = 0;
     322             :   // Check for slip system resistance update tolerance
     323             :   do
     324             :   {
     325     1498836 :     solveStress();
     326     1498833 :     if (_convergence_failed)
     327             :       return;
     328             : 
     329     1409937 :     _plastic_deformation_gradient[_qp] =
     330     1409937 :         _inverse_plastic_deformation_grad.inverse(); // the postSoveStress
     331             : 
     332             :     // Update slip system resistance and state variable after the stress has been finalized
     333             :     // We loop through all the models for each calculation
     334             :     // in order to make sure that when coupling appears, the state variables are updated based on
     335             :     // the same components
     336     2973408 :     for (unsigned int i = 0; i < _num_models; ++i)
     337     1563471 :       _models[i]->cacheStateVariablesBeforeUpdate();
     338             : 
     339     2973408 :     for (unsigned int i = 0; i < _num_models; ++i)
     340     1563471 :       _models[i]->calculateStateVariableEvolutionRateComponent();
     341             : 
     342     2973407 :     for (unsigned int i = 0; i < _num_models; ++i)
     343     1563471 :       if (!_models[i]->updateStateVariables())
     344          58 :         _convergence_failed = true;
     345             : 
     346     2973406 :     for (unsigned int i = 0; i < _num_models; ++i)
     347     1563470 :       _models[i]->calculateSlipResistance();
     348             : 
     349     1409936 :     if (_convergence_failed)
     350             :       return;
     351             : 
     352     2572943 :     for (unsigned int i = 0; i < _num_models; ++i)
     353             :     {
     354             :       // iter_flag = false, stop iteration if all values are converged and good to go
     355             :       // iter_flag = true, continue iteration if any value is not converged
     356     1500886 :       if (!_models[i]->areConstitutiveStateVariablesConverged())
     357             :       {
     358             :         iter_flag = true;
     359             :         break;
     360             :       }
     361             :       else
     362             :         iter_flag = false; // iter_flag = false, stop iteration only when all models returns true
     363             :     }
     364             : 
     365     1409878 :     if (iter_flag)
     366             :     {
     367      337821 :       if (_print_convergence_message)
     368           0 :         mooseWarning("ComputeMultipleCrystalPlasticityStress: State variables (or the system "
     369             :                      "resistance) did not converge at element ",
     370           0 :                      _current_elem->id(),
     371             :                      " and qp ",
     372           0 :                      _qp,
     373             :                      "\n");
     374             :     }
     375     1072057 :     iteration++;
     376      337821 :   } while (iter_flag && iteration < _maxiterg);
     377             : 
     378     1072611 :   if (iteration == _maxiterg)
     379             :   {
     380         554 :     if (_print_convergence_message)
     381           0 :       mooseWarning(
     382             :           "ComputeMultipleCrystalPlasticityStress: Hardness Integration error. Reached the "
     383             :           "maximum number of iterations to solve for the state variables at element ",
     384           0 :           _current_elem->id(),
     385             :           " and qp ",
     386           0 :           _qp,
     387             :           "\n");
     388             : 
     389         554 :     _convergence_failed = true;
     390             :   }
     391             : }
     392             : 
     393             : void
     394     1498836 : ComputeMultipleCrystalPlasticityStress::solveStress()
     395             : {
     396             :   unsigned int iteration = 0;
     397     1498836 :   RankTwoTensor dpk2;
     398             :   Real rnorm, rnorm0, rnorm_prev;
     399             : 
     400             :   // Calculate stress residual
     401     1498836 :   calculateResidualAndJacobian();
     402     1498836 :   if (_convergence_failed)
     403             :   {
     404           0 :     if (_print_convergence_message)
     405           0 :       mooseWarning("ComputeMultipleCrystalPlasticityStress: the slip increment exceeds tolerance "
     406             :                    "at element ",
     407           0 :                    _current_elem->id(),
     408             :                    " and Gauss point ",
     409           0 :                    _qp);
     410             : 
     411           0 :     return;
     412             :   }
     413             : 
     414     1498836 :   rnorm = _residual_tensor.L2norm();
     415     1498836 :   rnorm0 = rnorm;
     416             : 
     417             :   // Check for stress residual tolerance; different from user object version which
     418             :   // compares the absolute tolerance of only the original rnorm value
     419     6470911 :   while (rnorm > _rtol * rnorm0 && rnorm > _abs_tol && iteration < _maxiter)
     420             :   {
     421             :     // Calculate stress increment
     422     5057938 :     dpk2 = -_jacobian.invSymm() * _residual_tensor;
     423     5057938 :     _pk2[_qp] = _pk2[_qp] + dpk2;
     424             : 
     425     5057938 :     calculateResidualAndJacobian();
     426             : 
     427     5057936 :     if (_convergence_failed)
     428             :     {
     429       85861 :       if (_print_convergence_message)
     430           0 :         mooseWarning("ComputeMultipleCrystalPlasticityStress: the slip increment exceeds tolerance "
     431             :                      "at element ",
     432           0 :                      _current_elem->id(),
     433             :                      " and Gauss point ",
     434           0 :                      _qp);
     435             : 
     436       85861 :       return;
     437             :     }
     438             : 
     439     4972075 :     rnorm_prev = rnorm;
     440     4972075 :     rnorm = _residual_tensor.L2norm();
     441             : 
     442     4972075 :     if (_use_line_search && rnorm > rnorm_prev && !lineSearchUpdate(rnorm_prev, dpk2))
     443             :     {
     444           0 :       if (_print_convergence_message)
     445           0 :         mooseWarning("ComputeMultipleCrystalPlasticityStress: Failed with line search");
     446             : 
     447           0 :       _convergence_failed = true;
     448           0 :       return;
     449             :     }
     450             : 
     451     4972075 :     if (_use_line_search)
     452      339648 :       rnorm = _residual_tensor.L2norm();
     453             : 
     454     4972075 :     iteration++;
     455             :   }
     456             : 
     457     1412973 :   if (iteration >= _maxiter)
     458             :   {
     459        3036 :     if (_print_convergence_message)
     460           1 :       mooseWarning("ComputeMultipleCrystalPlasticityStress: Stress Integration error rmax = ",
     461             :                    rnorm,
     462             :                    " and the tolerance is ",
     463           1 :                    _rtol * rnorm0,
     464             :                    " when the rnorm0 value is ",
     465             :                    rnorm0,
     466             :                    " for element ",
     467           0 :                    _current_elem->id(),
     468             :                    " and qp ",
     469           1 :                    _qp);
     470             : 
     471        3035 :     _convergence_failed = true;
     472             :   }
     473             : }
     474             : 
     475             : // Calculates stress residual equation and jacobian
     476             : void
     477     6556774 : ComputeMultipleCrystalPlasticityStress::calculateResidualAndJacobian()
     478             : {
     479     6556774 :   calculateResidual();
     480     6556772 :   if (_convergence_failed)
     481             :     return;
     482     6470911 :   calculateJacobian();
     483             : }
     484             : 
     485             : void
     486     6582694 : ComputeMultipleCrystalPlasticityStress::calculateResidual()
     487             : {
     488     6582694 :   RankTwoTensor ce, elastic_strain, ce_pk2, equivalent_slip_increment_per_model,
     489     6582694 :       equivalent_slip_increment, pk2_new;
     490             : 
     491             :   equivalent_slip_increment.zero();
     492             : 
     493             :   // calculate slip rate in order to compute F^{p-1}
     494    13609042 :   for (unsigned int i = 0; i < _num_models; ++i)
     495             :   {
     496             :     equivalent_slip_increment_per_model.zero();
     497             : 
     498             :     // calculate shear stress with consideration of contribution from other physics
     499     7112211 :     _models[i]->calculateShearStress(
     500     7112211 :         _pk2[_qp], _inverse_eigenstrain_deformation_grad, _num_eigenstrains);
     501             : 
     502     7112211 :     _convergence_failed = !_models[i]->calculateSlipRate();
     503             : 
     504     7112209 :     if (_convergence_failed)
     505             :       return;
     506             : 
     507     7026348 :     _models[i]->calculateEquivalentSlipIncrement(equivalent_slip_increment_per_model);
     508     7026348 :     equivalent_slip_increment += equivalent_slip_increment_per_model;
     509             :   }
     510             : 
     511             :   RankTwoTensor residual_equivalent_slip_increment =
     512     6496831 :       RankTwoTensor::Identity() - equivalent_slip_increment;
     513             :   _inverse_plastic_deformation_grad =
     514     6496831 :       _inverse_plastic_deformation_grad_old * residual_equivalent_slip_increment;
     515             : 
     516    12993662 :   _elastic_deformation_gradient = _temporary_deformation_gradient *
     517    12993662 :                                   _inverse_eigenstrain_deformation_grad *
     518     6496831 :                                   _inverse_plastic_deformation_grad;
     519             : 
     520     6496831 :   ce = _elastic_deformation_gradient.transpose() * _elastic_deformation_gradient;
     521             : 
     522     6496831 :   elastic_strain = ce - RankTwoTensor::Identity();
     523     6496831 :   elastic_strain *= 0.5;
     524             : 
     525     6496831 :   pk2_new = _elasticity_tensor[_qp] * elastic_strain;
     526     6496831 :   _residual_tensor = _pk2[_qp] - pk2_new;
     527             : }
     528             : 
     529             : void
     530     6470911 : ComputeMultipleCrystalPlasticityStress::calculateJacobian()
     531             : {
     532             :   // may not need to cache the dfpinvdpk2 here. need to double check
     533     6470911 :   RankFourTensor dfedfpinv, deedfe, dfpinvdpk2, dfpinvdpk2_per_model;
     534             : 
     535     6470911 :   RankTwoTensor ffeiginv = _temporary_deformation_gradient * _inverse_eigenstrain_deformation_grad;
     536             : 
     537    25883644 :   for (const auto i : make_range(Moose::dim))
     538    77650932 :     for (const auto j : make_range(Moose::dim))
     539   232952796 :       for (const auto k : make_range(Moose::dim))
     540   174714597 :         dfedfpinv(i, j, k, j) = ffeiginv(i, k);
     541             : 
     542    25883644 :   for (const auto i : make_range(Moose::dim))
     543    77650932 :     for (const auto j : make_range(Moose::dim))
     544   232952796 :       for (const auto k : make_range(Moose::dim))
     545             :       {
     546   174714597 :         deedfe(i, j, k, i) = deedfe(i, j, k, i) + _elastic_deformation_gradient(k, j) * 0.5;
     547   174714597 :         deedfe(i, j, k, j) = deedfe(i, j, k, j) + _elastic_deformation_gradient(k, i) * 0.5;
     548             :       }
     549             : 
     550    13471339 :   for (unsigned int i = 0; i < _num_models; ++i)
     551             :   {
     552     7000428 :     _models[i]->calculateTotalPlasticDeformationGradientDerivative(
     553             :         dfpinvdpk2_per_model,
     554     7000428 :         _inverse_plastic_deformation_grad_old,
     555     7000428 :         _inverse_eigenstrain_deformation_grad,
     556     7000428 :         _num_eigenstrains);
     557     7000428 :     dfpinvdpk2 += dfpinvdpk2_per_model;
     558             :   }
     559             : 
     560             :   _jacobian =
     561    12941822 :       RankFourTensor::IdentityFour() - (_elasticity_tensor[_qp] * deedfe * dfedfpinv * dfpinvdpk2);
     562     6470911 : }
     563             : 
     564             : void
     565      845505 : ComputeMultipleCrystalPlasticityStress::calcTangentModuli(RankFourTensor & jacobian_mult)
     566             : {
     567      845505 :   switch (_tan_mod_type)
     568             :   {
     569      845505 :     case TangentModuliType::EXACT:
     570      845505 :       elastoPlasticTangentModuli(jacobian_mult);
     571      845505 :       break;
     572           0 :     default:
     573           0 :       elasticTangentModuli(jacobian_mult);
     574             :   }
     575      845505 : }
     576             : 
     577             : void
     578      845505 : ComputeMultipleCrystalPlasticityStress::elastoPlasticTangentModuli(RankFourTensor & jacobian_mult)
     579             : {
     580      845505 :   RankFourTensor tan_mod;
     581      845505 :   RankTwoTensor pk2fet, fepk2, feiginvfpinv;
     582      845505 :   RankFourTensor deedfe, dsigdpk2dfe, dfedf;
     583             : 
     584             :   // Fill in the matrix stiffness material property
     585     3382020 :   for (const auto i : make_range(Moose::dim))
     586    10146060 :     for (const auto j : make_range(Moose::dim))
     587    30438180 :       for (const auto k : make_range(Moose::dim))
     588             :       {
     589    22828635 :         deedfe(i, j, k, i) = deedfe(i, j, k, i) + _elastic_deformation_gradient(k, j) * 0.5;
     590    22828635 :         deedfe(i, j, k, j) = deedfe(i, j, k, j) + _elastic_deformation_gradient(k, i) * 0.5;
     591             :       }
     592             : 
     593             :   usingTensorIndices(i_, j_, k_, l_);
     594      845505 :   dsigdpk2dfe = _elastic_deformation_gradient.times<i_, k_, j_, l_>(_elastic_deformation_gradient) *
     595      845505 :                 _elasticity_tensor[_qp] * deedfe;
     596             : 
     597      845505 :   pk2fet = _pk2[_qp] * _elastic_deformation_gradient.transpose();
     598      845505 :   fepk2 = _elastic_deformation_gradient * _pk2[_qp];
     599             : 
     600     3382020 :   for (const auto i : make_range(Moose::dim))
     601    10146060 :     for (const auto j : make_range(Moose::dim))
     602    30438180 :       for (const auto l : make_range(Moose::dim))
     603             :       {
     604    22828635 :         tan_mod(i, j, i, l) += pk2fet(l, j);
     605    22828635 :         tan_mod(i, j, j, l) += fepk2(i, l);
     606             :       }
     607             : 
     608      845505 :   tan_mod += dsigdpk2dfe;
     609             : 
     610      845505 :   const auto je = _elastic_deformation_gradient.det();
     611      845505 :   if (je > 0.0)
     612      845505 :     tan_mod /= je;
     613             : 
     614      845505 :   feiginvfpinv = _inverse_eigenstrain_deformation_grad * _inverse_plastic_deformation_grad;
     615     3382020 :   for (const auto i : make_range(Moose::dim))
     616    10146060 :     for (const auto j : make_range(Moose::dim))
     617    30438180 :       for (const auto l : make_range(Moose::dim))
     618    22828635 :         dfedf(i, j, i, l) = feiginvfpinv(l, j);
     619             : 
     620      845505 :   jacobian_mult = tan_mod * dfedf;
     621      845505 : }
     622             : 
     623             : void
     624           0 : ComputeMultipleCrystalPlasticityStress::elasticTangentModuli(RankFourTensor & jacobian_mult)
     625             : {
     626             :   // update jacobian_mult
     627           0 :   jacobian_mult = _elasticity_tensor[_qp];
     628           0 : }
     629             : 
     630             : bool
     631       25920 : ComputeMultipleCrystalPlasticityStress::lineSearchUpdate(const Real & rnorm_prev,
     632             :                                                          const RankTwoTensor & dpk2)
     633             : {
     634       25920 :   if (_line_search_method == LineSearchMethod::CutHalf)
     635             :   {
     636             :     Real rnorm;
     637       25920 :     Real step = 1.0;
     638             : 
     639             :     do
     640             :     {
     641       25920 :       _pk2[_qp] = _pk2[_qp] - step * dpk2;
     642       25920 :       step /= 2.0;
     643       25920 :       _pk2[_qp] = _pk2[_qp] + step * dpk2;
     644             : 
     645       25920 :       calculateResidual();
     646       25920 :       rnorm = _residual_tensor.L2norm();
     647       25920 :     } while (rnorm > rnorm_prev && step > _min_line_search_step_size);
     648             : 
     649             :     // has norm improved or is the step still above minumum search step size?
     650       25920 :     return (rnorm <= rnorm_prev || step > _min_line_search_step_size);
     651             :   }
     652           0 :   else if (_line_search_method == LineSearchMethod::Bisection)
     653             :   {
     654             :     unsigned int count = 0;
     655             :     Real step_a = 0.0;
     656             :     Real step_b = 1.0;
     657           0 :     Real step = 1.0;
     658             :     Real s_m = 1000.0;
     659             :     Real rnorm = 1000.0;
     660             : 
     661           0 :     calculateResidual();
     662           0 :     auto s_b = _residual_tensor.doubleContraction(dpk2);
     663           0 :     const auto rnorm1 = _residual_tensor.L2norm();
     664           0 :     _pk2[_qp] = _pk2[_qp] - dpk2;
     665           0 :     calculateResidual();
     666           0 :     auto s_a = _residual_tensor.doubleContraction(dpk2);
     667           0 :     const auto rnorm0 = _residual_tensor.L2norm();
     668           0 :     _pk2[_qp] = _pk2[_qp] + dpk2;
     669             : 
     670           0 :     if ((rnorm1 / rnorm0) < _line_search_tolerance || s_a * s_b > 0)
     671             :     {
     672           0 :       calculateResidual();
     673           0 :       return true;
     674             :     }
     675             : 
     676           0 :     while ((rnorm / rnorm0) > _line_search_tolerance && count < _line_search_max_iterations)
     677             :     {
     678           0 :       _pk2[_qp] = _pk2[_qp] - step * dpk2;
     679           0 :       step = 0.5 * (step_b + step_a);
     680           0 :       _pk2[_qp] = _pk2[_qp] + step * dpk2;
     681           0 :       calculateResidual();
     682           0 :       s_m = _residual_tensor.doubleContraction(dpk2);
     683           0 :       rnorm = _residual_tensor.L2norm();
     684             : 
     685           0 :       if (s_m * s_a < 0.0)
     686             :       {
     687             :         step_b = step;
     688             :         s_b = s_m;
     689             :       }
     690           0 :       if (s_m * s_b < 0.0)
     691             :       {
     692             :         step_a = step;
     693             :         s_a = s_m;
     694             :       }
     695           0 :       count++;
     696             :     }
     697             : 
     698             :     // below tolerance and max iterations?
     699           0 :     return ((rnorm / rnorm0) < _line_search_tolerance && count < _line_search_max_iterations);
     700             :   }
     701             :   else
     702           0 :     mooseError("Line search method is not provided.");
     703             : }
     704             : 
     705             : void
     706      341410 : ComputeMultipleCrystalPlasticityStress::calculateEigenstrainDeformationGrad()
     707             : {
     708             :   _inverse_eigenstrain_deformation_grad.zero();
     709      341410 :   _inverse_eigenstrain_deformation_grad.addIa(1.0);
     710             : 
     711      729114 :   for (unsigned int i = 0; i < _num_eigenstrains; ++i)
     712             :   {
     713      387714 :     _eigenstrains[i]->setSubstepDt(_substep_dt);
     714      387714 :     _eigenstrains[i]->computeQpProperties();
     715      387704 :     _inverse_eigenstrain_deformation_grad *= _eigenstrains[i]->getDeformationGradientInverse();
     716             :   }
     717      341400 :   (*_eigenstrain_deformation_gradient)[_qp] = _inverse_eigenstrain_deformation_grad.inverse();
     718      341400 : }

Generated by: LCOV version 1.14