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 : }
|