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

Generated by: LCOV version 1.14