LCOV - code coverage report
Current view: top level - src/materials/crystal_plasticity - CrystalPlasticityTwinningKalidindiUpdate.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #31405 (292dce) with base fef103 Lines: 162 168 96.4 %
Date: 2025-09-04 07:57:23 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         404 : CrystalPlasticityTwinningKalidindiUpdate::validParams()
      17             : {
      18         404 :   InputParameters params = CrystalPlasticityStressUpdateBase::validParams();
      19         404 :   params.addClassDescription(
      20             :       "Twinning propagation model based on Kalidindi's treatment of twinning in a FCC material");
      21         808 :   params.addParam<Real>(
      22             :       "initial_total_twin_volume_fraction",
      23         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      27             :       "twin_reference_strain_rate",
      28         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      33             :       "twin_strain_rate_sensitivity_exponent",
      34         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      39             :       "characteristic_twin_shear",
      40         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      44             :       "initial_twin_lattice_friction",
      45         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      50             :       "non_coplanar_coefficient_twin_hardening",
      51         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      56             :       "coplanar_coefficient_twin_hardening",
      57         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      62             :       "non_coplanar_twin_hardening_exponent",
      63         808 :       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        1212 :   params.addRangeCheckedParam<Real>(
      68             :       "upper_limit_twin_volume_fraction",
      69         808 :       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         404 :   return params;
      74           0 : }
      75             : 
      76         303 : CrystalPlasticityTwinningKalidindiUpdate::CrystalPlasticityTwinningKalidindiUpdate(
      77         303 :     const InputParameters & parameters)
      78             :   : CrystalPlasticityStressUpdateBase(parameters),
      79             : 
      80         303 :     _total_twin_volume_fraction(declareProperty<Real>(_base_name + "total_volume_fraction_twins")),
      81         303 :     _total_twin_volume_fraction_old(
      82         303 :         getMaterialPropertyOld<Real>(_base_name + "total_volume_fraction_twins")),
      83         606 :     _initial_total_twin_volume_fraction(getParam<Real>("initial_total_twin_volume_fraction")),
      84         303 :     _twin_volume_fraction(
      85         303 :         declareProperty<std::vector<Real>>(_base_name + "twin_system_volume_fraction")),
      86         303 :     _twin_volume_fraction_old(
      87         303 :         getMaterialPropertyOld<std::vector<Real>>(_base_name + "twin_system_volume_fraction")),
      88         303 :     _twin_volume_fraction_increment(
      89         303 :         declareProperty<std::vector<Real>>(_base_name + "twin_system_volume_fraction_increment")),
      90         606 :     _reference_strain_rate(getParam<Real>("twin_reference_strain_rate")),
      91         606 :     _rate_sensitivity_exponent(getParam<Real>("twin_strain_rate_sensitivity_exponent")),
      92         606 :     _characteristic_twin_shear(getParam<Real>("characteristic_twin_shear")),
      93         606 :     _twin_initial_lattice_friction(getParam<Real>("initial_twin_lattice_friction")),
      94         303 :     _non_coplanar_coefficient_twin_hardening(
      95         606 :         getParam<Real>("non_coplanar_coefficient_twin_hardening")),
      96         606 :     _coplanar_coefficient_twin_hardening(getParam<Real>("coplanar_coefficient_twin_hardening")),
      97         606 :     _noncoplanar_exponent(getParam<Real>("non_coplanar_twin_hardening_exponent")),
      98         606 :     _limit_twin_volume_fraction(getParam<Real>("upper_limit_twin_volume_fraction")),
      99             : 
     100             :     // resize local caching vectors used for substepping
     101         303 :     _previous_substep_twin_resistance(_number_slip_systems, 0.0),
     102         303 :     _previous_substep_twin_volume_fraction(_number_slip_systems, 0.0),
     103         303 :     _twin_resistance_before_update(_number_slip_systems, 0.0),
     104         606 :     _twin_volume_fraction_before_update(_number_slip_systems, 0.0)
     105             : {
     106         303 : }
     107             : 
     108             : void
     109       15168 : CrystalPlasticityTwinningKalidindiUpdate::initQpStatefulProperties()
     110             : {
     111       15168 :   CrystalPlasticityStressUpdateBase::initQpStatefulProperties();
     112             : 
     113             :   // Resize constitutive-model specific material properties
     114       15168 :   _twin_volume_fraction[_qp].resize(_number_slip_systems);
     115             : 
     116             :   // Set constitutive-model specific initial values from parameters
     117       15168 :   _total_twin_volume_fraction[_qp] = _initial_total_twin_volume_fraction;
     118       15168 :   const Real twin_volume_fraction_per_system =
     119       15168 :       _initial_total_twin_volume_fraction / _number_slip_systems;
     120      161344 :   for (const auto i : make_range(_number_slip_systems))
     121             :   {
     122      146176 :     _twin_volume_fraction[_qp][i] = twin_volume_fraction_per_system;
     123      146176 :     _slip_resistance[_qp][i] = _twin_initial_lattice_friction;
     124      146176 :     _slip_increment[_qp][i] = 0.0;
     125             :   }
     126       15168 : }
     127             : 
     128             : void
     129      588377 : CrystalPlasticityTwinningKalidindiUpdate::setMaterialVectorSize()
     130             : {
     131      588377 :   CrystalPlasticityStressUpdateBase::setMaterialVectorSize();
     132             : 
     133             :   // Resize non-stateful material properties
     134      588377 :   _twin_volume_fraction_increment[_qp].resize(_number_slip_systems);
     135      588377 : }
     136             : 
     137             : void
     138      577193 : CrystalPlasticityTwinningKalidindiUpdate::setInitialConstitutiveVariableValues()
     139             : {
     140      577193 :   _slip_resistance[_qp] = _slip_resistance_old[_qp];
     141      577193 :   _previous_substep_twin_resistance = _slip_resistance_old[_qp];
     142             : 
     143      577193 :   _twin_volume_fraction[_qp] = _twin_volume_fraction_old[_qp];
     144      577193 :   _previous_substep_twin_volume_fraction = _twin_volume_fraction_old[_qp];
     145      577193 : }
     146             : 
     147             : void
     148      581177 : CrystalPlasticityTwinningKalidindiUpdate::setSubstepConstitutiveVariableValues()
     149             : {
     150      581177 :   _slip_resistance[_qp] = _previous_substep_twin_resistance;
     151      581177 :   _twin_volume_fraction[_qp] = _previous_substep_twin_volume_fraction;
     152      581177 : }
     153             : 
     154             : bool
     155    10736125 : CrystalPlasticityTwinningKalidindiUpdate::calculateSlipRate()
     156             : {
     157             :   Real total_twin_volume_fraction = 0.0;
     158   118098075 :   for (const auto i : make_range(_number_slip_systems))
     159   107361950 :     total_twin_volume_fraction += _twin_volume_fraction[_qp][i];
     160             : 
     161    10736125 :   if (total_twin_volume_fraction < _limit_twin_volume_fraction)
     162             :   {
     163   117844299 :     for (const auto i : make_range(_number_slip_systems))
     164             :     {
     165   107127696 :       if (_tau[_qp][i] > 0.0)
     166             :       {
     167    58975634 :         const Real driving_force = (_tau[_qp][i] / _slip_resistance[_qp][i]);
     168    58975634 :         _slip_increment[_qp][i] = std::pow(driving_force, (1.0 / _rate_sensitivity_exponent)) *
     169    58975634 :                                   _reference_strain_rate * _substep_dt;
     170             :       }
     171             :       else // twin propagation is directional
     172    48152062 :         _slip_increment[_qp][i] = 0.0;
     173             : 
     174             :       // Check for allowable plastic strain due to twin propagation
     175   107127696 :       if (_slip_increment[_qp][i] > _slip_incr_tol)
     176             :       {
     177           2 :         if (_print_convergence_message)
     178           2 :           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           2 :                        _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       19520 :     std::fill(_slip_increment[_qp].begin(), _slip_increment[_qp].end(), 0.0);
     192             : 
     193             :   return true;
     194             : }
     195             : 
     196             : void
     197    10736123 : CrystalPlasticityTwinningKalidindiUpdate::calculateConstitutiveSlipDerivative(
     198             :     std::vector<Real> & dslip_dtau)
     199             : {
     200             :   Real total_twin_volume_fraction = 0.0;
     201   118098049 :   for (const auto i : make_range(_number_slip_systems))
     202   107361926 :     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    10736123 :   if (total_twin_volume_fraction >= _limit_twin_volume_fraction)
     206             :     std::fill(dslip_dtau.begin(), dslip_dtau.end(), 0.0);
     207             :   else
     208             :   {
     209   117844289 :     for (const auto i : make_range(_number_slip_systems))
     210             :     {
     211   107127686 :       if (_tau[_qp][i] <= 0.0)
     212    48152058 :         dslip_dtau[i] = 0.0;
     213             :       else
     214    58975628 :         dslip_dtau[i] =
     215    58975628 :             _slip_increment[_qp][i] / (_rate_sensitivity_exponent * _tau[_qp][i]) * _substep_dt;
     216             :     }
     217             :   }
     218    10736123 : }
     219             : 
     220             : bool
     221     1789161 : CrystalPlasticityTwinningKalidindiUpdate::areConstitutiveStateVariablesConverged()
     222             : {
     223     1789161 :   if (isConstitutiveStateVariableConverged(_twin_volume_fraction[_qp],
     224     1789161 :                                            _twin_volume_fraction_before_update,
     225     1789161 :                                            _previous_substep_twin_volume_fraction,
     226     2366227 :                                            _rel_state_var_tol) &&
     227      577066 :       isConstitutiveStateVariableConverged(_slip_resistance[_qp],
     228      577066 :                                            _twin_resistance_before_update,
     229      577066 :                                            _previous_substep_twin_resistance,
     230      577066 :                                            _resistance_tol))
     231             :     return true;
     232             :   return false;
     233             : }
     234             : 
     235             : void
     236      577011 : CrystalPlasticityTwinningKalidindiUpdate::updateSubstepConstitutiveVariableValues()
     237             : {
     238      577011 :   _previous_substep_twin_resistance = _slip_resistance[_qp];
     239      577011 :   _previous_substep_twin_volume_fraction = _twin_volume_fraction[_qp];
     240      577011 : }
     241             : 
     242             : void
     243     1838269 : CrystalPlasticityTwinningKalidindiUpdate::cacheStateVariablesBeforeUpdate()
     244             : {
     245     1838269 :   _twin_resistance_before_update = _slip_resistance[_qp];
     246     1838269 :   _twin_volume_fraction_before_update = _twin_volume_fraction[_qp];
     247     1838269 : }
     248             : 
     249             : void
     250     1838269 : CrystalPlasticityTwinningKalidindiUpdate::calculateStateVariableEvolutionRateComponent()
     251             : {
     252    21513355 :   for (const auto i : make_range(_number_slip_systems))
     253    19675086 :     _twin_volume_fraction_increment[_qp][i] =
     254    19675086 :         _slip_increment[_qp][i] / _characteristic_twin_shear * _substep_dt;
     255     1838269 : }
     256             : 
     257             : bool
     258     1838269 : CrystalPlasticityTwinningKalidindiUpdate::updateStateVariables()
     259             : {
     260     1838269 :   if (calculateTwinVolumeFraction())
     261             :     return true;
     262             :   else
     263         146 :     return false;
     264             : }
     265             : 
     266             : bool
     267     1838269 : CrystalPlasticityTwinningKalidindiUpdate::calculateTwinVolumeFraction()
     268             : {
     269     1838269 :   _total_twin_volume_fraction[_qp] = 0.0;
     270             : 
     271    21513355 :   for (const auto i : make_range(_number_slip_systems))
     272             :   {
     273    19675086 :     if (_previous_substep_twin_volume_fraction[i] < _zero_tol &&
     274    15343408 :         _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    19675086 :       _twin_volume_fraction[_qp][i] =
     278    19675086 :           _previous_substep_twin_volume_fraction[i] + _twin_volume_fraction_increment[_qp][i];
     279             : 
     280    19675086 :     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    19675086 :       _total_twin_volume_fraction[_qp] += _twin_volume_fraction[_qp][i];
     291             :   }
     292             : 
     293     1838269 :   if ((_total_twin_volume_fraction[_qp] - _limit_twin_volume_fraction) >
     294     1838269 :       (_rel_state_var_tol * _limit_twin_volume_fraction))
     295             :   {
     296         148 :     if (_print_convergence_message)
     297         148 :       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         148 :                    _limit_twin_volume_fraction,
     301             :                    " with a user-set tolerance value of ",
     302         148 :                    _rel_state_var_tol);
     303             : 
     304         146 :     return false;
     305             :   }
     306             :   else
     307             :   {
     308     1838121 :     calculateTwinResistance();
     309     1838121 :     return true;
     310             :   }
     311             : }
     312             : 
     313             : void
     314     1838121 : CrystalPlasticityTwinningKalidindiUpdate::calculateTwinResistance()
     315             : {
     316     1838121 :   DenseVector<Real> twin_hardening_increment(_number_slip_systems);
     317             : 
     318    21511431 :   for (const auto i : make_range(_number_slip_systems))
     319             :   {
     320    19673310 :     twin_hardening_increment(i) = 0.0;
     321   243449586 :     for (const auto j : make_range(_number_slip_systems))
     322             :     {
     323   223776276 :       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    55502526 :         if (_slip_increment[_qp][j] > 0.0)
     328    27835379 :           twin_hardening_increment(i) += _coplanar_coefficient_twin_hardening *
     329    27835379 :                                          _total_twin_volume_fraction[_qp] *
     330    27835379 :                                          _twin_volume_fraction[_qp][j];
     331             :       }
     332             :       else // assume non-coplanar
     333             :       {
     334   168273750 :         if (_slip_increment[_qp][j] > 0.0)
     335    85757241 :           twin_hardening_increment(i) +=
     336    85757241 :               _non_coplanar_coefficient_twin_hardening *
     337    85757241 :               std::pow(_total_twin_volume_fraction[_qp], _noncoplanar_exponent) *
     338    85757241 :               _twin_volume_fraction[_qp][j];
     339             :       }
     340             :     }
     341             :   }
     342             : 
     343    21511431 :   for (const auto i : make_range(_number_slip_systems))
     344             :   {
     345    19673310 :     twin_hardening_increment(i) *= _characteristic_twin_shear;
     346    19673310 :     if (twin_hardening_increment(i) <= 0.0)
     347      409086 :       _slip_resistance[_qp][i] = _previous_substep_twin_resistance[i];
     348             :     else
     349    19264224 :       _slip_resistance[_qp][i] = twin_hardening_increment(i) + _previous_substep_twin_resistance[i];
     350             :   }
     351     1838121 : }

Generated by: LCOV version 1.14