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 "CrystalPlasticityTwinningKalidindiUpdate.h"
11 : #include "libmesh/int_range.h"
12 :
13 : registerMooseObject("TensorMechanicsApp", CrystalPlasticityTwinningKalidindiUpdate);
14 :
15 : InputParameters
16 140 : CrystalPlasticityTwinningKalidindiUpdate::validParams()
17 : {
18 140 : InputParameters params = CrystalPlasticityStressUpdateBase::validParams();
19 140 : params.addClassDescription(
20 : "Twinning propagation model based on Kalidindi's treatment of twinning in a FCC material");
21 280 : params.addParam<Real>(
22 : "initial_total_twin_volume_fraction",
23 280 : 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 420 : params.addRangeCheckedParam<Real>(
27 : "twin_reference_strain_rate",
28 280 : 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 420 : params.addRangeCheckedParam<Real>(
33 : "twin_strain_rate_sensitivity_exponent",
34 280 : 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 420 : params.addRangeCheckedParam<Real>(
39 : "characteristic_twin_shear",
40 280 : 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 420 : params.addRangeCheckedParam<Real>(
44 : "initial_twin_lattice_friction",
45 280 : 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 420 : params.addRangeCheckedParam<Real>(
50 : "non_coplanar_coefficient_twin_hardening",
51 280 : 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 420 : params.addRangeCheckedParam<Real>(
56 : "coplanar_coefficient_twin_hardening",
57 280 : 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 420 : params.addRangeCheckedParam<Real>(
62 : "non_coplanar_twin_hardening_exponent",
63 280 : 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 420 : params.addRangeCheckedParam<Real>(
68 : "upper_limit_twin_volume_fraction",
69 280 : 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 140 : return params;
74 0 : }
75 :
76 105 : CrystalPlasticityTwinningKalidindiUpdate::CrystalPlasticityTwinningKalidindiUpdate(
77 105 : const InputParameters & parameters)
78 : : CrystalPlasticityStressUpdateBase(parameters),
79 :
80 105 : _total_twin_volume_fraction(declareProperty<Real>(_base_name + "total_volume_fraction_twins")),
81 105 : _total_twin_volume_fraction_old(
82 105 : getMaterialPropertyOld<Real>(_base_name + "total_volume_fraction_twins")),
83 210 : _initial_total_twin_volume_fraction(getParam<Real>("initial_total_twin_volume_fraction")),
84 105 : _twin_volume_fraction(
85 105 : declareProperty<std::vector<Real>>(_base_name + "twin_system_volume_fraction")),
86 105 : _twin_volume_fraction_old(
87 105 : getMaterialPropertyOld<std::vector<Real>>(_base_name + "twin_system_volume_fraction")),
88 105 : _twin_volume_fraction_increment(
89 105 : declareProperty<std::vector<Real>>(_base_name + "twin_system_volume_fraction_increment")),
90 210 : _reference_strain_rate(getParam<Real>("twin_reference_strain_rate")),
91 210 : _rate_sensitivity_exponent(getParam<Real>("twin_strain_rate_sensitivity_exponent")),
92 210 : _characteristic_twin_shear(getParam<Real>("characteristic_twin_shear")),
93 210 : _twin_initial_lattice_friction(getParam<Real>("initial_twin_lattice_friction")),
94 105 : _non_coplanar_coefficient_twin_hardening(
95 210 : getParam<Real>("non_coplanar_coefficient_twin_hardening")),
96 210 : _coplanar_coefficient_twin_hardening(getParam<Real>("coplanar_coefficient_twin_hardening")),
97 210 : _noncoplanar_exponent(getParam<Real>("non_coplanar_twin_hardening_exponent")),
98 210 : _limit_twin_volume_fraction(getParam<Real>("upper_limit_twin_volume_fraction")),
99 :
100 : // resize local caching vectors used for substepping
101 105 : _previous_substep_twin_resistance(_number_slip_systems, 0.0),
102 105 : _previous_substep_twin_volume_fraction(_number_slip_systems, 0.0),
103 105 : _twin_resistance_before_update(_number_slip_systems, 0.0),
104 210 : _twin_volume_fraction_before_update(_number_slip_systems, 0.0)
105 : {
106 105 : }
107 :
108 : void
109 6080 : CrystalPlasticityTwinningKalidindiUpdate::initQpStatefulProperties()
110 : {
111 6080 : CrystalPlasticityStressUpdateBase::initQpStatefulProperties();
112 :
113 : // Resize constitutive-model specific material properties
114 6080 : _twin_volume_fraction[_qp].resize(_number_slip_systems);
115 6080 : _twin_volume_fraction_increment[_qp].resize(_number_slip_systems);
116 :
117 : // Set constitutive-model specific initial values from parameters
118 6080 : _total_twin_volume_fraction[_qp] = _initial_total_twin_volume_fraction;
119 6080 : const Real twin_volume_fraction_per_system =
120 6080 : _initial_total_twin_volume_fraction / _number_slip_systems;
121 64704 : for (const auto i : make_range(_number_slip_systems))
122 : {
123 58624 : _twin_volume_fraction[_qp][i] = twin_volume_fraction_per_system;
124 58624 : _slip_resistance[_qp][i] = _twin_initial_lattice_friction;
125 58624 : _slip_increment[_qp][i] = 0.0;
126 : }
127 6080 : }
128 :
129 : void
130 202942 : CrystalPlasticityTwinningKalidindiUpdate::setInitialConstitutiveVariableValues()
131 : {
132 202942 : _slip_resistance[_qp] = _slip_resistance_old[_qp];
133 202942 : _previous_substep_twin_resistance = _slip_resistance_old[_qp];
134 :
135 202942 : _twin_volume_fraction[_qp] = _twin_volume_fraction_old[_qp];
136 202942 : _previous_substep_twin_volume_fraction = _twin_volume_fraction_old[_qp];
137 202942 : }
138 :
139 : void
140 203558 : CrystalPlasticityTwinningKalidindiUpdate::setSubstepConstitutiveVariableValues()
141 : {
142 203558 : _slip_resistance[_qp] = _previous_substep_twin_resistance;
143 203558 : _twin_volume_fraction[_qp] = _previous_substep_twin_volume_fraction;
144 203558 : }
145 :
146 : bool
147 2226207 : CrystalPlasticityTwinningKalidindiUpdate::calculateSlipRate()
148 : {
149 : Real total_twin_volume_fraction = 0.0;
150 21941681 : for (const auto i : make_range(_number_slip_systems))
151 19715474 : total_twin_volume_fraction += _twin_volume_fraction[_qp][i];
152 :
153 2226207 : if (total_twin_volume_fraction < _limit_twin_volume_fraction)
154 : {
155 21833565 : for (const auto i : make_range(_number_slip_systems))
156 : {
157 19615675 : if (_tau[_qp][i] > 0.0)
158 : {
159 11211183 : const Real driving_force = (_tau[_qp][i] / _slip_resistance[_qp][i]);
160 11211183 : _slip_increment[_qp][i] = std::pow(driving_force, (1.0 / _rate_sensitivity_exponent)) *
161 11211183 : _reference_strain_rate * _substep_dt;
162 : }
163 : else // twin propagation is directional
164 8404492 : _slip_increment[_qp][i] = 0.0;
165 :
166 : // Check for allowable plastic strain due to twin propagation
167 19615675 : if (_slip_increment[_qp][i] > _slip_incr_tol)
168 : {
169 1 : if (_print_convergence_message)
170 1 : mooseWarning("Maximum allowable plastic slip increment due to twinning exceeded the "
171 : "user-defined tolerance on twin system ",
172 : i,
173 : ", with a value of",
174 : _slip_increment[_qp][i],
175 : " when the increment tolerance is set at ",
176 1 : _slip_incr_tol);
177 :
178 0 : return false;
179 : }
180 : }
181 : }
182 : else // Once reach the limit of volume fraction, all subsequent increments will be zero
183 8316 : std::fill(_slip_increment[_qp].begin(), _slip_increment[_qp].end(), 0.0);
184 :
185 : return true;
186 : }
187 :
188 : void
189 2226206 : CrystalPlasticityTwinningKalidindiUpdate::calculateConstitutiveSlipDerivative(
190 : std::vector<Real> & dslip_dtau)
191 : {
192 : Real total_twin_volume_fraction = 0.0;
193 21941668 : for (const auto i : make_range(_number_slip_systems))
194 19715462 : total_twin_volume_fraction += _twin_volume_fraction[_qp][i];
195 :
196 : // Once reach the limit of volume fraction, all plastic slip increments will be zero
197 2226206 : if (total_twin_volume_fraction >= _limit_twin_volume_fraction)
198 : std::fill(dslip_dtau.begin(), dslip_dtau.end(), 0.0);
199 : else
200 : {
201 21833560 : for (const auto i : make_range(_number_slip_systems))
202 : {
203 19615670 : if (_tau[_qp][i] <= 0.0)
204 8404490 : dslip_dtau[i] = 0.0;
205 : else
206 11211180 : dslip_dtau[i] =
207 11211180 : _slip_increment[_qp][i] / (_rate_sensitivity_exponent * _tau[_qp][i]) * _substep_dt;
208 : }
209 : }
210 2226206 : }
211 :
212 : bool
213 449506 : CrystalPlasticityTwinningKalidindiUpdate::areConstitutiveStateVariablesConverged()
214 : {
215 449506 : if (isConstitutiveStateVariableConverged(_twin_volume_fraction[_qp],
216 449506 : _twin_volume_fraction_before_update,
217 449506 : _previous_substep_twin_volume_fraction,
218 652375 : _rel_state_var_tol) &&
219 202869 : isConstitutiveStateVariableConverged(_slip_resistance[_qp],
220 202869 : _twin_resistance_before_update,
221 202869 : _previous_substep_twin_resistance,
222 202869 : _resistance_tol))
223 : return true;
224 : return false;
225 : }
226 :
227 : void
228 202869 : CrystalPlasticityTwinningKalidindiUpdate::updateSubstepConstitutiveVariableValues()
229 : {
230 202869 : _previous_substep_twin_resistance = _slip_resistance[_qp];
231 202869 : _previous_substep_twin_volume_fraction = _twin_volume_fraction[_qp];
232 202869 : }
233 :
234 : void
235 458013 : CrystalPlasticityTwinningKalidindiUpdate::cacheStateVariablesBeforeUpdate()
236 : {
237 458013 : _twin_resistance_before_update = _slip_resistance[_qp];
238 458013 : _twin_volume_fraction_before_update = _twin_volume_fraction[_qp];
239 458013 : }
240 :
241 : void
242 458013 : CrystalPlasticityTwinningKalidindiUpdate::calculateStateVariableEvolutionRateComponent()
243 : {
244 5106445 : for (const auto i : make_range(_number_slip_systems))
245 4648432 : _twin_volume_fraction_increment[_qp][i] =
246 4648432 : _slip_increment[_qp][i] / _characteristic_twin_shear * _substep_dt;
247 458013 : }
248 :
249 : bool
250 458013 : CrystalPlasticityTwinningKalidindiUpdate::updateStateVariables()
251 : {
252 458013 : if (calculateTwinVolumeFraction())
253 : return true;
254 : else
255 58 : return false;
256 : }
257 :
258 : bool
259 458013 : CrystalPlasticityTwinningKalidindiUpdate::calculateTwinVolumeFraction()
260 : {
261 458013 : _total_twin_volume_fraction[_qp] = 0.0;
262 :
263 5106445 : for (const auto i : make_range(_number_slip_systems))
264 : {
265 4648432 : if (_previous_substep_twin_volume_fraction[i] < _zero_tol &&
266 3534082 : _twin_volume_fraction_increment[_qp][i] < 0.0)
267 0 : _twin_volume_fraction_increment[_qp][i] = _previous_substep_twin_volume_fraction[i];
268 : else
269 4648432 : _twin_volume_fraction[_qp][i] =
270 4648432 : _previous_substep_twin_volume_fraction[i] + _twin_volume_fraction_increment[_qp][i];
271 :
272 4648432 : if (_twin_volume_fraction[_qp][i] < 0.0)
273 : {
274 0 : if (_print_convergence_message)
275 0 : mooseWarning("A negative twin volume fraction value was computed: ",
276 : _twin_volume_fraction[_qp][i],
277 : " on twin system ",
278 : i);
279 0 : return false;
280 : }
281 : else
282 4648432 : _total_twin_volume_fraction[_qp] += _twin_volume_fraction[_qp][i];
283 : }
284 :
285 458013 : if ((_total_twin_volume_fraction[_qp] - _limit_twin_volume_fraction) >
286 458013 : (_rel_state_var_tol * _limit_twin_volume_fraction))
287 : {
288 59 : if (_print_convergence_message)
289 59 : mooseWarning("Maximum allowable twin volume fraction limit exceeded with a value of ",
290 : _total_twin_volume_fraction[_qp],
291 : " when the limit is set as ",
292 59 : _limit_twin_volume_fraction,
293 : " with a user-set tolerance value of ",
294 59 : _rel_state_var_tol);
295 :
296 58 : return false;
297 : }
298 : else
299 : {
300 457954 : calculateTwinResistance();
301 457954 : return true;
302 : }
303 : }
304 :
305 : void
306 457954 : CrystalPlasticityTwinningKalidindiUpdate::calculateTwinResistance()
307 : {
308 457954 : DenseVector<Real> twin_hardening_increment(_number_slip_systems);
309 :
310 5105678 : for (const auto i : make_range(_number_slip_systems))
311 : {
312 4647724 : twin_hardening_increment(i) = 0.0;
313 56139956 : for (const auto j : make_range(_number_slip_systems))
314 : {
315 51492232 : if (MooseUtils::relativeFuzzyEqual(_slip_plane_normal[j](0), _slip_plane_normal[i](0)) &&
316 : MooseUtils::relativeFuzzyEqual(_slip_plane_normal[j](1), _slip_plane_normal[i](1)))
317 : // If the first two are the same, the third index will have to be as well
318 : {
319 12751404 : if (_slip_increment[_qp][j] > 0.0)
320 6346892 : twin_hardening_increment(i) += _coplanar_coefficient_twin_hardening *
321 6346892 : _total_twin_volume_fraction[_qp] *
322 6346892 : _twin_volume_fraction[_qp][j];
323 : }
324 : else // assume non-coplanar
325 : {
326 38740828 : if (_slip_increment[_qp][j] > 0.0)
327 19720548 : twin_hardening_increment(i) +=
328 19720548 : _non_coplanar_coefficient_twin_hardening *
329 19720548 : std::pow(_total_twin_volume_fraction[_qp], _noncoplanar_exponent) *
330 19720548 : _twin_volume_fraction[_qp][j];
331 : }
332 : }
333 : }
334 :
335 5105678 : for (const auto i : make_range(_number_slip_systems))
336 : {
337 4647724 : twin_hardening_increment(i) *= _characteristic_twin_shear;
338 4647724 : if (twin_hardening_increment(i) <= 0.0)
339 183532 : _slip_resistance[_qp][i] = _previous_substep_twin_resistance[i];
340 : else
341 4464192 : _slip_resistance[_qp][i] = twin_hardening_increment(i) + _previous_substep_twin_resistance[i];
342 : }
343 457954 : }
|