LCOV - code coverage report
Current view: top level - src/materials/crystal_plasticity - CrystalPlasticityTwinningKalidindiUpdate.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #32971 (54bef8) with base c6cf66 Lines: 162 168 96.4 %
Date: 2026-05-29 20:40:07 Functions: 15 15 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 "CrystalPlasticityTwinningKalidindiUpdate.h"
      11             : #include "libmesh/int_range.h"
      12             : 
      13             : registerMooseObject("SolidMechanicsApp", CrystalPlasticityTwinningKalidindiUpdate);
      14             : 
      15             : InputParameters
      16         228 : CrystalPlasticityTwinningKalidindiUpdate::validParams()
      17             : {
      18         228 :   InputParameters params = CrystalPlasticityStressUpdateBase::validParams();
      19         228 :   params.addClassDescription(
      20             :       "Twinning propagation model based on Kalidindi's treatment of twinning in a FCC material");
      21         456 :   params.addParam<Real>(
      22             :       "initial_total_twin_volume_fraction",
      23         456 :       0.0,
      24             :       "The initial sum of the twin volume fraction across all twin systems in the crystal, if "
      25             :       "any. This value is distributed evenly across all twin systems in the crystal.");
      26         684 :   params.addRangeCheckedParam<Real>(
      27             :       "twin_reference_strain_rate",
      28         456 :       1.0e-3,
      29             :       "twin_reference_strain_rate>0",
      30             :       "The reference strain rate, gamma_o, for the power law plastic slip law "
      31             :       "due to twin propagation.");
      32         684 :   params.addRangeCheckedParam<Real>(
      33             :       "twin_strain_rate_sensitivity_exponent",
      34         456 :       0.05,
      35             :       "twin_strain_rate_sensitivity_exponent>0",
      36             :       "The strain rate sensitivity exponent for twin propagation power law "
      37             :       "strain rate calculation");
      38         684 :   params.addRangeCheckedParam<Real>(
      39             :       "characteristic_twin_shear",
      40         456 :       1.0 / std::sqrt(2.0),
      41             :       "characteristic_twin_shear>0",
      42             :       "The amount of shear that is associated with a twin in this cubic structure");
      43         684 :   params.addRangeCheckedParam<Real>(
      44             :       "initial_twin_lattice_friction",
      45         456 :       0.0,
      46             :       "initial_twin_lattice_friction>=0",
      47             :       "The initial value of the lattice friction for twin propogation, often "
      48             :       "calculated as a fraction of the Peierls strength");
      49         684 :   params.addRangeCheckedParam<Real>(
      50             :       "non_coplanar_coefficient_twin_hardening",
      51         456 :       8000.0,
      52             :       "non_coplanar_coefficient_twin_hardening>=0",
      53             :       "The factor to apply to the hardening of non-coplanar twin systems "
      54             :       "strength as a function of the volume fraction of twins");
      55         684 :   params.addRangeCheckedParam<Real>(
      56             :       "coplanar_coefficient_twin_hardening",
      57         456 :       800.0,
      58             :       "coplanar_coefficient_twin_hardening>=0",
      59             :       "Hardening coefficient for coplanar twin systems strength as a function of "
      60             :       "the volume fraction of twins");
      61         684 :   params.addRangeCheckedParam<Real>(
      62             :       "non_coplanar_twin_hardening_exponent",
      63         456 :       0.05,
      64             :       "non_coplanar_twin_hardening_exponent>=0",
      65             :       "Parameter used to increase the hardening of non-coplanar twin systems such that the "
      66             :       "propagation of twins on conplanar systems is favored at early deformation stages.");
      67         684 :   params.addRangeCheckedParam<Real>(
      68             :       "upper_limit_twin_volume_fraction",
      69         456 :       0.8,
      70             :       "upper_limit_twin_volume_fraction>0&upper_limit_twin_volume_fraction<=1",
      71             :       "The maximumum amount of twinning volume fraction allowed");
      72             : 
      73         228 :   return params;
      74           0 : }
      75             : 
      76         171 : CrystalPlasticityTwinningKalidindiUpdate::CrystalPlasticityTwinningKalidindiUpdate(
      77         171 :     const InputParameters & parameters)
      78             :   : CrystalPlasticityStressUpdateBase(parameters),
      79             : 
      80         171 :     _total_twin_volume_fraction(declareProperty<Real>(_base_name + "total_volume_fraction_twins")),
      81         171 :     _total_twin_volume_fraction_old(
      82         171 :         getMaterialPropertyOld<Real>(_base_name + "total_volume_fraction_twins")),
      83         342 :     _initial_total_twin_volume_fraction(getParam<Real>("initial_total_twin_volume_fraction")),
      84         171 :     _twin_volume_fraction(
      85         171 :         declareProperty<std::vector<Real>>(_base_name + "twin_system_volume_fraction")),
      86         171 :     _twin_volume_fraction_old(
      87         171 :         getMaterialPropertyOld<std::vector<Real>>(_base_name + "twin_system_volume_fraction")),
      88         171 :     _twin_volume_fraction_increment(
      89         171 :         declareProperty<std::vector<Real>>(_base_name + "twin_system_volume_fraction_increment")),
      90         342 :     _reference_strain_rate(getParam<Real>("twin_reference_strain_rate")),
      91         342 :     _rate_sensitivity_exponent(getParam<Real>("twin_strain_rate_sensitivity_exponent")),
      92         342 :     _characteristic_twin_shear(getParam<Real>("characteristic_twin_shear")),
      93         342 :     _twin_initial_lattice_friction(getParam<Real>("initial_twin_lattice_friction")),
      94         171 :     _non_coplanar_coefficient_twin_hardening(
      95         342 :         getParam<Real>("non_coplanar_coefficient_twin_hardening")),
      96         342 :     _coplanar_coefficient_twin_hardening(getParam<Real>("coplanar_coefficient_twin_hardening")),
      97         342 :     _noncoplanar_exponent(getParam<Real>("non_coplanar_twin_hardening_exponent")),
      98         342 :     _limit_twin_volume_fraction(getParam<Real>("upper_limit_twin_volume_fraction")),
      99             : 
     100             :     // resize local caching vectors used for substepping
     101         171 :     _previous_substep_twin_resistance(_number_slip_systems, 0.0),
     102         171 :     _previous_substep_twin_volume_fraction(_number_slip_systems, 0.0),
     103         171 :     _twin_resistance_before_update(_number_slip_systems, 0.0),
     104         342 :     _twin_volume_fraction_before_update(_number_slip_systems, 0.0)
     105             : {
     106         171 : }
     107             : 
     108             : void
     109        9088 : CrystalPlasticityTwinningKalidindiUpdate::initQpStatefulProperties()
     110             : {
     111        9088 :   CrystalPlasticityStressUpdateBase::initQpStatefulProperties();
     112             : 
     113             :   // Resize constitutive-model specific material properties
     114        9088 :   _twin_volume_fraction[_qp].resize(_number_slip_systems);
     115             : 
     116             :   // Set constitutive-model specific initial values from parameters
     117        9088 :   _total_twin_volume_fraction[_qp] = _initial_total_twin_volume_fraction;
     118        9088 :   const Real twin_volume_fraction_per_system =
     119        9088 :       _initial_total_twin_volume_fraction / _number_slip_systems;
     120       96640 :   for (const auto i : make_range(_number_slip_systems))
     121             :   {
     122       87552 :     _twin_volume_fraction[_qp][i] = twin_volume_fraction_per_system;
     123       87552 :     _slip_resistance[_qp][i] = _twin_initial_lattice_friction;
     124       87552 :     _slip_increment[_qp][i] = 0.0;
     125             :   }
     126        9088 : }
     127             : 
     128             : void
     129      356349 : CrystalPlasticityTwinningKalidindiUpdate::setMaterialVectorSize()
     130             : {
     131      356349 :   CrystalPlasticityStressUpdateBase::setMaterialVectorSize();
     132             : 
     133             :   // Resize non-stateful material properties
     134      356349 :   _twin_volume_fraction_increment[_qp].resize(_number_slip_systems);
     135      356349 : }
     136             : 
     137             : void
     138      349661 : CrystalPlasticityTwinningKalidindiUpdate::setInitialConstitutiveVariableValues()
     139             : {
     140      349661 :   _slip_resistance[_qp] = _slip_resistance_old[_qp];
     141      349661 :   _previous_substep_twin_resistance = _slip_resistance_old[_qp];
     142             : 
     143      349661 :   _twin_volume_fraction[_qp] = _twin_volume_fraction_old[_qp];
     144      349661 :   _previous_substep_twin_volume_fraction = _twin_volume_fraction_old[_qp];
     145      349661 : }
     146             : 
     147             : void
     148      352061 : CrystalPlasticityTwinningKalidindiUpdate::setSubstepConstitutiveVariableValues()
     149             : {
     150      352061 :   _slip_resistance[_qp] = _previous_substep_twin_resistance;
     151      352061 :   _twin_volume_fraction[_qp] = _previous_substep_twin_volume_fraction;
     152      352061 : }
     153             : 
     154             : bool
     155     6406934 : CrystalPlasticityTwinningKalidindiUpdate::calculateSlipRate()
     156             : {
     157             :   Real total_twin_volume_fraction = 0.0;
     158    70764738 :   for (const auto i : make_range(_number_slip_systems))
     159    64357804 :     total_twin_volume_fraction += _twin_volume_fraction[_qp][i];
     160             : 
     161     6406934 :   if (total_twin_volume_fraction < _limit_twin_volume_fraction)
     162             :   {
     163    70612474 :     for (const auto i : make_range(_number_slip_systems))
     164             :     {
     165    64217253 :       if (_tau[_qp][i] > 0.0)
     166             :       {
     167    35165929 :         const Real driving_force = (_tau[_qp][i] / _slip_resistance[_qp][i]);
     168    35165929 :         _slip_increment[_qp][i] = std::pow(driving_force, (1.0 / _rate_sensitivity_exponent)) *
     169    35165929 :                                   _reference_strain_rate * _substep_dt;
     170             :       }
     171             :       else // twin propagation is directional
     172    29051324 :         _slip_increment[_qp][i] = 0.0;
     173             : 
     174             :       // Check for allowable plastic strain due to twin propagation
     175    64217253 :       if (_slip_increment[_qp][i] > _slip_incr_tol)
     176             :       {
     177           1 :         if (_print_convergence_message)
     178           1 :           mooseWarning("Maximum allowable plastic slip increment due to twinning exceeded the "
     179             :                        "user-defined tolerance on twin system ",
     180             :                        i,
     181             :                        ", with a value of",
     182             :                        _slip_increment[_qp][i],
     183             :                        " when the increment tolerance is set at ",
     184           1 :                        _slip_incr_tol);
     185             : 
     186           0 :         return false;
     187             :       }
     188             :     }
     189             :   }
     190             :   else // Once reach the limit of volume fraction, all subsequent increments will be zero
     191       11712 :     std::fill(_slip_increment[_qp].begin(), _slip_increment[_qp].end(), 0.0);
     192             : 
     193             :   return true;
     194             : }
     195             : 
     196             : void
     197     6406933 : CrystalPlasticityTwinningKalidindiUpdate::calculateConstitutiveSlipDerivative(
     198             :     std::vector<Real> & dslip_dtau)
     199             : {
     200             :   Real total_twin_volume_fraction = 0.0;
     201    70764725 :   for (const auto i : make_range(_number_slip_systems))
     202    64357792 :     total_twin_volume_fraction += _twin_volume_fraction[_qp][i];
     203             : 
     204             :   // Once reach the limit of volume fraction, all plastic slip increments will be zero
     205     6406933 :   if (total_twin_volume_fraction >= _limit_twin_volume_fraction)
     206             :     std::fill(dslip_dtau.begin(), dslip_dtau.end(), 0.0);
     207             :   else
     208             :   {
     209    70612469 :     for (const auto i : make_range(_number_slip_systems))
     210             :     {
     211    64217248 :       if (_tau[_qp][i] <= 0.0)
     212    29051322 :         dslip_dtau[i] = 0.0;
     213             :       else
     214    35165926 :         dslip_dtau[i] =
     215    35165926 :             _slip_increment[_qp][i] / (_rate_sensitivity_exponent * _tau[_qp][i]) * _substep_dt;
     216             :     }
     217             :   }
     218     6406933 : }
     219             : 
     220             : bool
     221     1081321 : CrystalPlasticityTwinningKalidindiUpdate::areConstitutiveStateVariablesConverged()
     222             : {
     223     1081321 :   if (isConstitutiveStateVariableConverged(_twin_volume_fraction[_qp],
     224     1081321 :                                            _twin_volume_fraction_before_update,
     225     1081321 :                                            _previous_substep_twin_volume_fraction,
     226     1430906 :                                            _rel_state_var_tol) &&
     227      349585 :       isConstitutiveStateVariableConverged(_slip_resistance[_qp],
     228      349585 :                                            _twin_resistance_before_update,
     229      349585 :                                            _previous_substep_twin_resistance,
     230      349585 :                                            _resistance_tol))
     231             :     return true;
     232             :   return false;
     233             : }
     234             : 
     235             : void
     236      349552 : CrystalPlasticityTwinningKalidindiUpdate::updateSubstepConstitutiveVariableValues()
     237             : {
     238      349552 :   _previous_substep_twin_resistance = _slip_resistance[_qp];
     239      349552 :   _previous_substep_twin_volume_fraction = _twin_volume_fraction[_qp];
     240      349552 : }
     241             : 
     242             : void
     243     1107970 : CrystalPlasticityTwinningKalidindiUpdate::cacheStateVariablesBeforeUpdate()
     244             : {
     245     1107970 :   _twin_resistance_before_update = _slip_resistance[_qp];
     246     1107970 :   _twin_volume_fraction_before_update = _twin_volume_fraction[_qp];
     247     1107970 : }
     248             : 
     249             : void
     250     1107970 : CrystalPlasticityTwinningKalidindiUpdate::calculateStateVariableEvolutionRateComponent()
     251             : {
     252    12978552 :   for (const auto i : make_range(_number_slip_systems))
     253    11870582 :     _twin_volume_fraction_increment[_qp][i] =
     254    11870582 :         _slip_increment[_qp][i] / _characteristic_twin_shear * _substep_dt;
     255     1107970 : }
     256             : 
     257             : bool
     258     1107970 : CrystalPlasticityTwinningKalidindiUpdate::updateStateVariables()
     259             : {
     260     1107970 :   if (calculateTwinVolumeFraction())
     261             :     return true;
     262             :   else
     263          88 :     return false;
     264             : }
     265             : 
     266             : bool
     267     1107970 : CrystalPlasticityTwinningKalidindiUpdate::calculateTwinVolumeFraction()
     268             : {
     269     1107970 :   _total_twin_volume_fraction[_qp] = 0.0;
     270             : 
     271    12978552 :   for (const auto i : make_range(_number_slip_systems))
     272             :   {
     273    11870582 :     if (_previous_substep_twin_volume_fraction[i] < _zero_tol &&
     274     9284610 :         _twin_volume_fraction_increment[_qp][i] < 0.0)
     275           0 :       _twin_volume_fraction_increment[_qp][i] = _previous_substep_twin_volume_fraction[i];
     276             :     else
     277    11870582 :       _twin_volume_fraction[_qp][i] =
     278    11870582 :           _previous_substep_twin_volume_fraction[i] + _twin_volume_fraction_increment[_qp][i];
     279             : 
     280    11870582 :     if (_twin_volume_fraction[_qp][i] < 0.0)
     281             :     {
     282           0 :       if (_print_convergence_message)
     283           0 :         mooseWarning("A negative twin volume fraction value was computed: ",
     284             :                      _twin_volume_fraction[_qp][i],
     285             :                      " on twin system ",
     286             :                      i);
     287           0 :       return false;
     288             :     }
     289             :     else
     290    11870582 :       _total_twin_volume_fraction[_qp] += _twin_volume_fraction[_qp][i];
     291             :   }
     292             : 
     293     1107970 :   if ((_total_twin_volume_fraction[_qp] - _limit_twin_volume_fraction) >
     294     1107970 :       (_rel_state_var_tol * _limit_twin_volume_fraction))
     295             :   {
     296          89 :     if (_print_convergence_message)
     297          89 :       mooseWarning("Maximum allowable twin volume fraction limit exceeded with a value of ",
     298             :                    _total_twin_volume_fraction[_qp],
     299             :                    " when the limit is set as ",
     300          89 :                    _limit_twin_volume_fraction,
     301             :                    " with a user-set tolerance value of ",
     302          89 :                    _rel_state_var_tol);
     303             : 
     304          88 :     return false;
     305             :   }
     306             :   else
     307             :   {
     308     1107881 :     calculateTwinResistance();
     309     1107881 :     return true;
     310             :   }
     311             : }
     312             : 
     313             : void
     314     1107881 : CrystalPlasticityTwinningKalidindiUpdate::calculateTwinResistance()
     315             : {
     316     1107881 :   DenseVector<Real> twin_hardening_increment(_number_slip_systems);
     317             : 
     318    12977395 :   for (const auto i : make_range(_number_slip_systems))
     319             :   {
     320    11869514 :     twin_hardening_increment(i) = 0.0;
     321   146973430 :     for (const auto j : make_range(_number_slip_systems))
     322             :     {
     323   135103916 :       if (MooseUtils::relativeFuzzyEqual(_slip_plane_normal[j](0), _slip_plane_normal[i](0)) &&
     324             :           MooseUtils::relativeFuzzyEqual(_slip_plane_normal[j](1), _slip_plane_normal[i](1)))
     325             :       // If the first two are the same, the third index will have to be as well
     326             :       {
     327    33520986 :         if (_slip_increment[_qp][j] > 0.0)
     328    16800625 :           twin_hardening_increment(i) += _coplanar_coefficient_twin_hardening *
     329    16800625 :                                          _total_twin_volume_fraction[_qp] *
     330    16800625 :                                          _twin_volume_fraction[_qp][j];
     331             :       }
     332             :       else // assume non-coplanar
     333             :       {
     334   101582930 :         if (_slip_increment[_qp][j] > 0.0)
     335    51717619 :           twin_hardening_increment(i) +=
     336    51717619 :               _non_coplanar_coefficient_twin_hardening *
     337    51717619 :               std::pow(_total_twin_volume_fraction[_qp], _noncoplanar_exponent) *
     338    51717619 :               _twin_volume_fraction[_qp][j];
     339             :       }
     340             :     }
     341             :   }
     342             : 
     343    12977395 :   for (const auto i : make_range(_number_slip_systems))
     344             :   {
     345    11869514 :     twin_hardening_increment(i) *= _characteristic_twin_shear;
     346    11869514 :     if (twin_hardening_increment(i) <= 0.0)
     347      247858 :       _slip_resistance[_qp][i] = _previous_substep_twin_resistance[i];
     348             :     else
     349    11621656 :       _slip_resistance[_qp][i] = twin_hardening_increment(i) + _previous_substep_twin_resistance[i];
     350             :   }
     351     1107881 : }

Generated by: LCOV version 1.14