https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FiniteStrainCrystalPlasticity.C
Go to the documentation of this file.
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
11#include "petscblaslapack.h"
12#include "libmesh/utility.h"
13
14#include <fstream>
15#include <cmath>
16
19 "11/15/2024 12:00");
20
23{
25 params.addClassDescription("Deprecated class: please use CrystalPlasticityKalidindiUpdate and "
26 "ComputeMultipleCrystalPlasticityStress instead. Crystal Plasticity "
27 "base class: FCC system with power law flow rule implemented");
28 params.addRequiredParam<int>("nss", "Number of slip systems");
29 params.addParam<std::vector<Real>>("gprops", {}, "Initial values of slip system resistances");
30 params.addParam<std::vector<Real>>("hprops", {}, "Hardening properties");
31 params.addParam<std::vector<Real>>("flowprops", {}, "Parameters used in slip rate equations");
32 params.addRequiredParam<FileName>("slip_sys_file_name",
33 "Name of the file containing the slip system");
34 params.addParam<FileName>(
35 "slip_sys_res_prop_file_name",
36 "",
37 "Name of the file containing the initial values of slip system resistances");
38 params.addParam<FileName>(
39 "slip_sys_flow_prop_file_name",
40 "",
41 "Name of the file containing the values of slip rate equation parameters");
42 params.addParam<FileName>(
43 "slip_sys_hard_prop_file_name",
44 "",
45 "Name of the file containing the values of hardness evolution parameters");
46 params.addParam<Real>("rtol", 1e-6, "Constitutive stress residue relative tolerance");
47 params.addParam<Real>("abs_tol", 1e-6, "Constitutive stress residue absolute tolerance");
48 params.addParam<Real>("gtol", 1e2, "Constitutive slip system resistance residual tolerance");
49 params.addParam<Real>("slip_incr_tol", 2e-2, "Maximum allowable slip in an increment");
50 params.addParam<unsigned int>("maxiter", 100, "Maximum number of iterations for stress update");
51 params.addParam<unsigned int>(
52 "maxitergss", 100, "Maximum number of iterations for slip system resistance update");
53 params.addParam<unsigned int>(
54 "num_slip_sys_flowrate_props",
55 2,
56 "Number of flow rate properties for a slip system"); // Used for reading flow rate parameters
57 params.addParam<UserObjectName>("read_prop_user_object",
58 "The ElementReadPropertyFile "
59 "GeneralUserObject to read element "
60 "specific property values from file");
61 MooseEnum tan_mod_options("exact none", "none"); // Type of read
62 params.addParam<MooseEnum>("tan_mod_type",
63 tan_mod_options,
64 "Type of tangent moduli for preconditioner: default elastic");
65 MooseEnum intvar_read_options("slip_sys_file slip_sys_res_file none", "none");
66 params.addParam<MooseEnum>(
67 "intvar_read_type",
68 intvar_read_options,
69 "Read from options for initial value of internal variables: Default from .i file");
70 params.addParam<unsigned int>("num_slip_sys_props",
71 0,
72 "Number of slip system specific properties provided in the file "
73 "containing slip system normals and directions");
74 params.addParam<bool>(
75 "gen_random_stress_flag",
76 false,
77 "Flag to generate random stress to perform time cutback on constitutive failure");
78 params.addParam<bool>("input_random_scaling_var",
79 false,
80 "Flag to input scaling variable: _Cijkl(0,0,0,0) when false");
81 params.addParam<Real>("random_scaling_var",
82 1e9,
83 "Random scaling variable: Large value can cause non-positive definiteness");
84 params.addParam<unsigned int>(
85 "random_seed",
86 2000,
87 "Random integer used to generate random stress when constitutive failure occurs");
88 params.addParam<unsigned int>(
89 "maximum_substep_iteration", 1, "Maximum number of substep iteration");
90 params.addParam<bool>("use_line_search", false, "Use line search in constitutive update");
91 params.addParam<Real>("min_line_search_step_size", 0.01, "Minimum line search step size");
92 params.addParam<Real>("line_search_tol", 0.5, "Line search bisection method tolerance");
93 params.addParam<unsigned int>(
94 "line_search_maxiter", 20, "Line search bisection method maximum number of iteration");
95 MooseEnum line_search_method("CUT_HALF BISECTION", "CUT_HALF");
96 params.addParam<MooseEnum>(
97 "line_search_method", line_search_method, "The method used in line search");
98
99 return params;
100}
101
103 : ComputeStressBase(parameters),
104 _nss(getParam<int>("nss")),
105 _gprops(getParam<std::vector<Real>>("gprops")),
106 _hprops(getParam<std::vector<Real>>("hprops")),
107 _flowprops(getParam<std::vector<Real>>("flowprops")),
108 _slip_sys_file_name(getParam<FileName>("slip_sys_file_name")),
109 _slip_sys_res_prop_file_name(getParam<FileName>("slip_sys_res_prop_file_name")),
110 _slip_sys_flow_prop_file_name(getParam<FileName>("slip_sys_flow_prop_file_name")),
111 _slip_sys_hard_prop_file_name(getParam<FileName>("slip_sys_hard_prop_file_name")),
112 _rtol(getParam<Real>("rtol")),
113 _abs_tol(getParam<Real>("abs_tol")),
114 _gtol(getParam<Real>("gtol")),
115 _slip_incr_tol(getParam<Real>("slip_incr_tol")),
116 _maxiter(getParam<unsigned int>("maxiter")),
117 _maxiterg(getParam<unsigned int>("maxitergss")),
118 _num_slip_sys_flowrate_props(getParam<unsigned int>("num_slip_sys_flowrate_props")),
119 _tan_mod_type(getParam<MooseEnum>("tan_mod_type")),
120 _intvar_read_type(getParam<MooseEnum>("intvar_read_type")),
121 _num_slip_sys_props(getParam<unsigned int>("num_slip_sys_props")),
122 _gen_rndm_stress_flag(getParam<bool>("gen_random_stress_flag")),
123 _input_rndm_scale_var(getParam<bool>("input_random_scaling_var")),
124 _rndm_scale_var(getParam<Real>("random_scaling_var")),
125 _rndm_seed(getParam<unsigned int>("random_seed")),
126 _max_substep_iter(getParam<unsigned int>("maximum_substep_iteration")),
127 _use_line_search(getParam<bool>("use_line_search")),
128 _min_lsrch_step(getParam<Real>("min_line_search_step_size")),
129 _lsrch_tol(getParam<Real>("line_search_tol")),
130 _lsrch_max_iter(getParam<unsigned int>("line_search_maxiter")),
131 _lsrch_method(getParam<MooseEnum>("line_search_method")),
132 _fp(declareProperty<RankTwoTensor>("fp")), // Plastic deformation gradient
133 _fp_old(getMaterialPropertyOld<RankTwoTensor>(
134 "fp")), // Plastic deformation gradient of previous increment
135 _pk2(declareProperty<RankTwoTensor>("pk2")), // 2nd Piola-Kirchoff Stress
136 _pk2_old(getMaterialPropertyOld<RankTwoTensor>(
137 "pk2")), // 2nd Piola Kirchoff Stress of previous increment
138 _lag_e(declareProperty<RankTwoTensor>("lage")), // Lagrangian strain
139 _lag_e_old(
140 getMaterialPropertyOld<RankTwoTensor>("lage")), // Lagrangian strain of previous increment
141 _gss(declareProperty<std::vector<Real>>("gss")), // Slip system resistances
142 _gss_old(getMaterialPropertyOld<std::vector<Real>>(
143 "gss")), // Slip system resistances of previous increment
144 _acc_slip(declareProperty<Real>("acc_slip")), // Accumulated slip
145 _acc_slip_old(
146 getMaterialPropertyOld<Real>("acc_slip")), // Accumulated slip of previous increment
147 _update_rot(declareProperty<RankTwoTensor>(
148 "update_rot")), // Rotation tensor considering material rotation and crystal orientation
149 _deformation_gradient(getMaterialProperty<RankTwoTensor>("deformation_gradient")),
150 _deformation_gradient_old(getMaterialPropertyOld<RankTwoTensor>("deformation_gradient")),
151 _elasticity_tensor_name(_base_name + "elasticity_tensor"),
152 _elasticity_tensor(getMaterialPropertyByName<RankFourTensor>(_elasticity_tensor_name)),
153 _crysrot(getMaterialProperty<RankTwoTensor>("crysrot")),
154 _mo(_nss * LIBMESH_DIM),
155 _no(_nss * LIBMESH_DIM),
156 _slip_incr(_nss),
157 _tau(_nss),
158 _dslipdtau(_nss),
159 _s0(_nss),
160 _gss_tmp(_nss),
161 _gss_tmp_old(_nss),
162 _dgss_dsliprate(_nss, _nss)
163{
164 _err_tol = false;
165
166 if (_num_slip_sys_props > 0)
168
169 _pk2_tmp.zero();
170 _delta_dfgrd.zero();
171
172 _first_step_iter = false;
173 _last_step_iter = false;
174 // Initialize variables in the first iteration of substepping
175 _first_substep = true;
176
178 if (_intvar_read_type == "slip_sys_file")
180
182 mooseError("Crystal Plasticity Error: Specify number of internal variable's initial values to "
183 "be read from slip system file");
184
186
188}
189
190void
192{
193 _stress[_qp].zero();
194
195 _fp[_qp].setToIdentity();
196
197 _pk2[_qp].zero();
198 _acc_slip[_qp] = 0.0;
199 _lag_e[_qp].zero();
200
201 _update_rot[_qp].setToIdentity();
202
203 initSlipSysProps(); // Initializes slip system related properties
205}
206
207void
209{
210 switch (_intvar_read_type)
211 {
212 case 0:
214 break;
215 case 1:
217 break;
218 default:
220 }
221
222 if (_slip_sys_flow_prop_file_name.length() != 0)
224 else
226
227 if (_slip_sys_hard_prop_file_name.length() != 0)
229 else
231}
232
233void
235{
236 _gss[_qp].resize(_nss);
237
238 for (unsigned int i = 0; i < _nss; ++i)
239 _gss[_qp][i] = _slip_sys_props(i);
240}
241
242// Read initial slip system resistances from .txt file. See test.
243void
245{
246 _gss[_qp].resize(_nss);
247
249
250 std::ifstream file;
251 file.open(_slip_sys_res_prop_file_name.c_str());
252
253 for (unsigned int i = 0; i < _nss; ++i)
254 if (!(file >> _gss[_qp][i]))
255 mooseError("Error FiniteStrainCrystalPlasticity: Premature end of slip_sys_res_prop file");
256
257 file.close();
258}
259
260// Read initial slip system resistances from .i file
261void
263{
264 if (_gprops.size() <= 0)
265 mooseError("FiniteStrainCrystalPLasticity: Error in reading slip system resistance properties: "
266 "Specify input in .i file or in slip_sys_res_prop_file or in slip_sys_file");
267
268 _gss[_qp].resize(_nss, 0.0);
269
270 unsigned int num_data_grp = 3; // Number of data per group e.g. start_slip_sys, end_slip_sys,
271 // value
272
273 for (unsigned int i = 0; i < _gprops.size() / num_data_grp; ++i)
274 {
275 Real vs, ve;
276 unsigned int is, ie;
277
278 vs = _gprops[i * num_data_grp];
279 ve = _gprops[i * num_data_grp + 1];
280
281 if (vs <= 0 || ve <= 0)
282 mooseError("FiniteStrainCrystalPLasticity: Indices in gss property read must be positive "
283 "integers: is = ",
284 vs,
285 " ie = ",
286 ve);
287
288 if (vs != floor(vs) || ve != floor(ve))
289 mooseError("FiniteStrainCrystalPLasticity: Error in reading slip system resistances: Values "
290 "specifying start and end number of slip system groups should be integer");
291
292 is = static_cast<unsigned int>(vs);
293 ie = static_cast<unsigned int>(ve);
294
295 if (is > ie)
296 mooseError("FiniteStrainCrystalPLasticity: Start index is = ",
297 is,
298 " should be greater than end index ie = ",
299 ie,
300 " in slip system resistance property read");
301
302 for (unsigned int j = is; j <= ie; ++j)
303 _gss[_qp][j - 1] = _gprops[i * num_data_grp + 2];
304 }
305
306 for (unsigned int i = 0; i < _nss; ++i)
307 if (_gss[_qp][i] <= 0.0)
308 mooseError("FiniteStrainCrystalPLasticity: Value of resistance for slip system ",
309 i + 1,
310 " non positive");
311}
312
313// Read flow rate parameters from .txt file. See test.
314void
316{
317 _a0.resize(_nss);
318 _xm.resize(_nss);
319
321
322 std::ifstream file;
323 file.open(_slip_sys_flow_prop_file_name.c_str());
324
325 std::vector<Real> vec;
327
328 for (unsigned int i = 0; i < _nss; ++i)
329 {
330 for (unsigned int j = 0; j < _num_slip_sys_flowrate_props; ++j)
331 if (!(file >> vec[j]))
333 "Error FiniteStrainCrystalPlasticity: Premature end of slip_sys_flow_rate_param file");
334
335 _a0(i) = vec[0];
336 _xm(i) = vec[1];
337 }
338
339 file.close();
340}
341
342// Read flow rate parameters from .i file
343void
345{
346 if (_flowprops.size() <= 0)
347 mooseError("FiniteStrainCrystalPLasticity: Error in reading flow rate properties: Specify "
348 "input in .i file or a slip_sys_flow_prop_file_name");
349
350 _a0.resize(_nss);
351 _xm.resize(_nss);
352
353 unsigned int num_data_grp = 2 + _num_slip_sys_flowrate_props; // Number of data per group e.g.
354 // start_slip_sys, end_slip_sys,
355 // value1, value2, ..
356
357 for (unsigned int i = 0; i < _flowprops.size() / num_data_grp; ++i)
358 {
359 Real vs, ve;
360 unsigned int is, ie;
361
362 vs = _flowprops[i * num_data_grp];
363 ve = _flowprops[i * num_data_grp + 1];
364
365 if (vs <= 0 || ve <= 0)
366 mooseError("FiniteStrainCrystalPLasticity: Indices in flow rate parameter read must be "
367 "positive integers: is = ",
368 vs,
369 " ie = ",
370 ve);
371
372 if (vs != floor(vs) || ve != floor(ve))
373 mooseError("FiniteStrainCrystalPLasticity: Error in reading flow props: Values specifying "
374 "start and end number of slip system groups should be integer");
375
376 is = static_cast<unsigned int>(vs);
377 ie = static_cast<unsigned int>(ve);
378
379 if (is > ie)
380 mooseError("FiniteStrainCrystalPLasticity: Start index is = ",
381 is,
382 " should be greater than end index ie = ",
383 ie,
384 " in flow rate parameter read");
385
386 for (unsigned int j = is; j <= ie; ++j)
387 {
388 _a0(j - 1) = _flowprops[i * num_data_grp + 2];
389 _xm(j - 1) = _flowprops[i * num_data_grp + 3];
390 }
391 }
392
393 for (unsigned int i = 0; i < _nss; ++i)
394 {
395 if (!(_a0(i) > 0.0 && _xm(i) > 0.0))
396 {
398 "FiniteStrainCrystalPlasticity: Non-positive flow rate parameters ", _a0(i), ",", _xm(i));
399 break;
400 }
401 }
402}
403
404// Read hardness parameters from .txt file
405void
409
410// Read hardness parameters from .i file
411void
413{
414 if (_hprops.size() <= 0)
415 mooseError("FiniteStrainCrystalPLasticity: Error in reading hardness properties: Specify input "
416 "in .i file or a slip_sys_hard_prop_file_name");
417
418 _r = _hprops[0];
419 _h0 = _hprops[1];
420 _tau_init = _hprops[2];
421 _tau_sat = _hprops[3];
422}
423
424// Read slip systems from file
425void
427{
428 Real vec[LIBMESH_DIM];
429 std::ifstream fileslipsys;
430
432
433 fileslipsys.open(_slip_sys_file_name.c_str());
434
435 for (unsigned int i = 0; i < _nss; ++i)
436 {
437 // Read the slip normal
438 for (const auto j : make_range(Moose::dim))
439 if (!(fileslipsys >> vec[j]))
440 mooseError("Crystal Plasticity Error: Premature end of file reading slip system file \n");
441
442 // Normalize the vectors
443 Real mag;
444 mag = Utility::pow<2>(vec[0]) + Utility::pow<2>(vec[1]) + Utility::pow<2>(vec[2]);
445 mag = std::sqrt(mag);
446
447 for (unsigned j = 0; j < LIBMESH_DIM; ++j)
448 _no(i * LIBMESH_DIM + j) = vec[j] / mag;
449
450 // Read the slip direction
451 for (const auto j : make_range(Moose::dim))
452 if (!(fileslipsys >> vec[j]))
453 mooseError("Crystal Plasticity Error: Premature end of file reading slip system file \n");
454
455 // Normalize the vectors
456 mag = Utility::pow<2>(vec[0]) + Utility::pow<2>(vec[1]) + Utility::pow<2>(vec[2]);
457 mag = std::sqrt(mag);
458
459 for (const auto j : make_range(Moose::dim))
460 _mo(i * LIBMESH_DIM + j) = vec[j] / mag;
461
462 mag = 0.0;
463 for (const auto j : make_range(Moose::dim))
464 mag += _mo(i * LIBMESH_DIM + j) * _no(i * LIBMESH_DIM + j);
465
466 if (std::abs(mag) > 1e-8)
468 "Crystal Plasicity Error: Slip direction and normal not orthonormal, System number = ",
469 i,
470 "\n");
471
473 for (unsigned int j = 0; j < _num_slip_sys_props; ++j)
474 if (!(fileslipsys >> _slip_sys_props(i * _num_slip_sys_props + j)))
475 mooseError("Crystal Plasticity Error: Premature end of file reading slip system file - "
476 "check in slip system file read input options/values\n");
477 }
478
479 fileslipsys.close();
480}
481
482// Initialize addtional stateful material properties
483void
487
492void
494{
495 unsigned int substep_iter = 1; // Depth of substepping; Limited to maximum substep iteration
496 unsigned int num_substep = 1; // Calculated from substep_iter as 2^substep_iter
497 Real dt_original = _dt; // Stores original _dt; Reset at the end of solve
498 _first_substep = true; // Initialize variables at substep_iter = 1
499
500 if (_max_substep_iter > 1)
501 {
503 if (_dfgrd_tmp_old.det() == 0)
505
507 _err_tol = true; // Indicator to continue substepping
508 }
509
510 // Substepping loop
511 while (_err_tol && _max_substep_iter > 1)
512 {
513 _dt = dt_original / num_substep;
514
515 for (unsigned int istep = 0; istep < num_substep; ++istep)
516 {
517 _first_step_iter = false;
518 if (istep == 0)
519 _first_step_iter = true;
520
521 _last_step_iter = false;
522 if (istep == num_substep - 1)
523 _last_step_iter = true;
524
525 _dfgrd_scale_factor = (static_cast<Real>(istep) + 1) / num_substep;
526
527 preSolveQp();
528 solveQp();
529
530 if (_err_tol)
531 {
532 substep_iter++;
533 num_substep *= 2;
534 break;
535 }
536 }
537
538 _first_substep = false; // Prevents reinitialization
539 _dt = dt_original; // Resets dt
540
541#ifdef DEBUG
542 if (substep_iter > _max_substep_iter)
543 mooseWarning("FiniteStrainCrystalPlasticity: Failure with substepping");
544#endif
545
546 if (!_err_tol || substep_iter > _max_substep_iter)
547 postSolveQp(); // Evaluate variables after successful solve or indicate failure
548 }
549
550 // No substepping
551 if (_max_substep_iter == 1)
552 {
553 preSolveQp();
554 solveQp();
555 postSolveQp();
556 }
557}
558
559void
561{
562 // Initialize variable
563 if (_first_substep)
564 {
565 _Jacobian_mult[_qp].zero(); // Initializes jacobian for preconditioner
567 }
568
569 if (_max_substep_iter == 1)
570 _dfgrd_tmp = _deformation_gradient[_qp]; // Without substepping
571 else
573
574 _err_tol = false;
575}
576
577void
586
587void
589{
590 if (_err_tol)
591 {
592 _err_tol = false;
594 {
596 _rndm_scale_var = _elasticity_tensor[_qp](0, 0, 0, 0);
597
599 }
600 else
601 mooseError("FiniteStrainCrystalPlasticity: Constitutive failure");
602 }
603 else
604 {
605 _stress[_qp] = _fe * _pk2[_qp] * _fe.transpose() / _fe.det();
606
607 _Jacobian_mult[_qp] += calcTangentModuli(); // Calculate jacobian for preconditioner
608
610
611 _lag_e[_qp] = _deformation_gradient[_qp].transpose() * _deformation_gradient[_qp] - iden;
612 _lag_e[_qp] = _lag_e[_qp] * 0.5;
613
614 RankTwoTensor rot;
615 rot = get_current_rotation(_deformation_gradient[_qp]); // Calculate material rotation
616 _update_rot[_qp] = rot * _crysrot[_qp];
617 }
618}
619
620void
622{
623 if (_max_substep_iter == 1) // No substepping
624 {
625 _gss_tmp = _gss_old[_qp];
627 }
628 else
629 {
631 {
634 }
635 else
637 }
638}
639
640void
642{
643 Real gmax, gdiff;
644 unsigned int iterg;
645 std::vector<Real> gss_prev(_nss);
646
647 gmax = 1.1 * _gtol;
648 iterg = 0;
649
650 while (gmax > _gtol && iterg < _maxiterg) // Check for slip system resistance update tolerance
651 {
653 solveStress();
654 if (_err_tol)
655 return;
657
658 gss_prev = _gss_tmp;
659
660 update_slip_system_resistance(); // Update slip system resistance
661
662 gmax = 0.0;
663 for (unsigned i = 0; i < _nss; ++i)
664 {
665 gdiff = std::abs(gss_prev[i] - _gss_tmp[i]); // Calculate increment size
666
667 if (gdiff > gmax)
668 gmax = gdiff;
669 }
670 iterg++;
671 }
672
673 if (iterg == _maxiterg)
674 {
675#ifdef DEBUG
676 mooseWarning("FiniteStrainCrystalPLasticity: Hardness Integration error gmax", gmax, "\n");
677#endif
678 _err_tol = true;
679 }
680}
681
682void
684{
685 if (_max_substep_iter == 1) // No substepping
686 {
687 _gss[_qp] = _gss_tmp;
688 _acc_slip[_qp] = _accslip_tmp;
689 }
690 else
691 {
692 if (_last_step_iter)
693 {
694 _gss[_qp] = _gss_tmp;
695 _acc_slip[_qp] = _accslip_tmp;
696 }
697 else
698 {
701 }
702 }
703}
704
705void
707{
708 if (_max_substep_iter == 1) // No substepping
709 {
710 _pk2_tmp = _pk2_old[_qp];
711 _fp_old_inv = _fp_old[_qp].inverse();
714 }
715 else
716 {
718 {
720 _fp_old_inv = _fp_old[_qp].inverse();
721 }
722 else
724
727 }
728}
729
730void
732{
733 unsigned int iter = 0;
734 RankTwoTensor resid, dpk2;
735 RankFourTensor jac;
736 Real rnorm, rnorm0, rnorm_prev;
737
738 calc_resid_jacob(resid, jac); // Calculate stress residual
739 if (_err_tol)
740 {
741#ifdef DEBUG
743 "FiniteStrainCrystalPLasticity: Slip increment exceeds tolerance - Element number ",
744 _current_elem->id(),
745 " Gauss point = ",
746 _qp);
747#endif
748 return;
749 }
750
751 rnorm = resid.L2norm();
752 rnorm0 = rnorm;
753
754 while (rnorm > _rtol * rnorm0 && rnorm0 > _abs_tol &&
755 iter < _maxiter) // Check for stress residual tolerance
756 {
757 dpk2 = -jac.invSymm() * resid; // Calculate stress increment
758 _pk2_tmp = _pk2_tmp + dpk2; // Update stress
759 calc_resid_jacob(resid, jac);
760 internalVariableUpdateNRiteration(); // update _fp_prev_inv
761
762 if (_err_tol)
763 {
764#ifdef DEBUG
766 "FiniteStrainCrystalPLasticity: Slip increment exceeds tolerance - Element number ",
767 _current_elem->id(),
768 " Gauss point = ",
769 _qp);
770#endif
771 return;
772 }
773
774 rnorm_prev = rnorm;
775 rnorm = resid.L2norm();
776
777 if (_use_line_search && rnorm > rnorm_prev && !line_search_update(rnorm_prev, dpk2))
778 {
779#ifdef DEBUG
780 mooseWarning("FiniteStrainCrystalPLasticity: Failed with line search");
781#endif
782 _err_tol = true;
783 return;
784 }
785
787 rnorm = resid.L2norm();
788
789 iter++;
790 }
791
792 if (iter >= _maxiter)
793 {
794#ifdef DEBUG
795 mooseWarning("FiniteStrainCrystalPLasticity: Stress Integration error rmax = ", rnorm);
796#endif
797 _err_tol = true;
798 }
799}
800
801void
803{
804 if (_max_substep_iter == 1) // No substepping
805 {
806 _fp[_qp] = _fp_inv.inverse();
807 _pk2[_qp] = _pk2_tmp;
808 }
809 else
810 {
811 if (_last_step_iter)
812 {
813 _fp[_qp] = _fp_inv.inverse();
814 _pk2[_qp] = _pk2_tmp;
815 }
816 else
817 {
820 }
821 }
822}
823
824// Update slip system resistance. Overide to incorporate new slip system resistance laws
825void
830
835void
837{
838 DenseVector<Real> hb(_nss);
839 Real qab;
840
841 Real a = _hprops[4]; // Kalidindi
842
844 for (unsigned int i = 0; i < _nss; ++i)
845 _accslip_tmp += std::abs(_slip_incr(i));
846
847 // Real val = std::cosh(_h0 * _accslip_tmp / (_tau_sat - _tau_init)); // Karthik
848 // val = _h0 * std::pow(1.0/val,2.0); // Kalidindi
849
850 for (unsigned int i = 0; i < _nss; ++i)
851 // hb(i)=val;
852 hb(i) = _h0 * std::pow(std::abs(1.0 - _gss_tmp[i] / _tau_sat), a) *
853 std::copysign(1.0, 1.0 - _gss_tmp[i] / _tau_sat);
854
855 for (unsigned int i = 0; i < _nss; ++i)
856 {
857 if (_max_substep_iter == 1) // No substepping
858 _gss_tmp[i] = _gss_old[_qp][i];
859 else
860 _gss_tmp[i] = _gss_tmp_old[i];
861
862 for (unsigned int j = 0; j < _nss; ++j)
863 {
864 unsigned int iplane, jplane;
865 iplane = i / 3;
866 jplane = j / 3;
867
868 if (iplane == jplane) // Kalidindi
869 qab = 1.0;
870 else
871 qab = _r;
872
873 _gss_tmp[i] += qab * hb(j) * std::abs(_slip_incr(j));
874 _dgss_dsliprate(i, j) = qab * hb(j) * std::copysign(1.0, _slip_incr(j)) * _dt;
875 }
876 }
877}
878
879// Calculates stress residual equation and jacobian
880void
882{
883 calcResidual(resid);
884 if (_err_tol)
885 return;
886 calcJacobian(jac);
887}
888
889void
891{
892 RankTwoTensor iden(RankTwoTensor::initIdentity), ce, ee, ce_pk2, eqv_slip_incr, pk2_new;
893
894 _fe = _dfgrd_tmp * _fp_prev_inv; // _fp_inv ==> _fp_prev_inv
895
896 ce = _fe.transpose() * _fe;
897 ce_pk2 = ce * _pk2_tmp;
898 ce_pk2 = ce_pk2 / _fe.det();
899
900 // Calculate Schmid tensor and resolved shear stresses
901 for (unsigned int i = 0; i < _nss; ++i)
902 _tau(i) = ce_pk2.doubleContraction(_s0[i]);
903
904 getSlipIncrements(); // Calculate dslip,dslipdtau
905
906 if (_err_tol)
907 return;
908
909 eqv_slip_incr.zero();
910 for (unsigned int i = 0; i < _nss; ++i)
911 eqv_slip_incr += _s0[i] * _slip_incr(i);
912
913 eqv_slip_incr = iden - eqv_slip_incr;
914 _fp_inv = _fp_old_inv * eqv_slip_incr;
916
917 ce = _fe.transpose() * _fe;
918 ee = ce - iden;
919 ee *= 0.5;
920
921 pk2_new = _elasticity_tensor[_qp] * ee;
922
923 resid = _pk2_tmp - pk2_new;
924}
925
926void
928{
929 RankFourTensor dfedfpinv, deedfe, dfpinvdpk2;
930
931 std::vector<RankTwoTensor> dtaudpk2(_nss), dfpinvdslip(_nss);
932
933 for (unsigned int i = 0; i < _nss; ++i)
934 {
935 dtaudpk2[i] = _s0[i];
936 dfpinvdslip[i] = -_fp_old_inv * _s0[i];
937 }
938
939 for (const auto i : make_range(Moose::dim))
940 for (const auto j : make_range(Moose::dim))
941 for (const auto k : make_range(Moose::dim))
942 dfedfpinv(i, j, k, j) = _dfgrd_tmp(i, k);
943
944 for (const auto i : make_range(Moose::dim))
945 for (const auto j : make_range(Moose::dim))
946 for (const auto k : make_range(Moose::dim))
947 {
948 deedfe(i, j, k, i) = deedfe(i, j, k, i) + _fe(k, j) * 0.5;
949 deedfe(i, j, k, j) = deedfe(i, j, k, j) + _fe(k, i) * 0.5;
950 }
951
952 for (unsigned int i = 0; i < _nss; ++i)
953 dfpinvdpk2 += (dfpinvdslip[i] * _dslipdtau(i)).outerProduct(dtaudpk2[i]);
954
955 jac =
956 RankFourTensor::IdentityFour() - (_elasticity_tensor[_qp] * deedfe * dfedfpinv * dfpinvdpk2);
957}
958
959// Calculate slip increment,dslipdtau. Override to modify.
960void
962{
963 for (unsigned int i = 0; i < _nss; ++i)
964 {
965 _slip_incr(i) = _a0(i) * std::pow(std::abs(_tau(i) / _gss_tmp[i]), 1.0 / _xm(i)) *
966 std::copysign(1.0, _tau(i)) * _dt;
967 if (std::abs(_slip_incr(i)) > _slip_incr_tol)
968 {
969 _err_tol = true;
970#ifdef DEBUG
971 mooseWarning("Maximum allowable slip increment exceeded ", std::abs(_slip_incr(i)));
972#endif
973 return;
974 }
975 }
976
977 for (unsigned int i = 0; i < _nss; ++i)
978 _dslipdtau(i) = _a0(i) / _xm(i) *
979 std::pow(std::abs(_tau(i) / _gss_tmp[i]), 1.0 / _xm(i) - 1.0) / _gss_tmp[i] *
980 _dt;
981}
982
983// Calls getMatRot to perform RU factorization of a tensor.
989
990// Performs RU factorization of a tensor
993{
994 RankTwoTensor rot;
995 RankTwoTensor c, diag, evec;
996 PetscScalar cmat[LIBMESH_DIM][LIBMESH_DIM], work[10];
997 PetscReal w[LIBMESH_DIM];
998 PetscBLASInt nd = LIBMESH_DIM, lwork = 10, info;
999
1000 c = a.transpose() * a;
1001
1002 for (const auto i : make_range(Moose::dim))
1003 for (const auto j : make_range(Moose::dim))
1004 cmat[i][j] = c(i, j);
1005
1006 LAPACKsyev_("V", "U", &nd, &cmat[0][0], &nd, w, work, &lwork, &info);
1007
1008 if (info != 0)
1009 mooseError("FiniteStrainCrystalPLasticity: DSYEV function call in getMatRot function failed");
1010
1011 diag.zero();
1012
1013 for (const auto i : make_range(Moose::dim))
1014 diag(i, i) = std::sqrt(w[i]);
1015
1016 for (const auto i : make_range(Moose::dim))
1017 for (const auto j : make_range(Moose::dim))
1018 evec(i, j) = cmat[i][j];
1019
1020 rot = a * ((evec.transpose() * diag * evec).inverse());
1021
1022 return rot;
1023}
1024
1025// Calculates tangent moduli which is used for global solve
1026void
1030
1033{
1034 RankFourTensor tan_mod;
1035
1036 switch (_tan_mod_type)
1037 {
1038 case 0:
1039 tan_mod = elastoPlasticTangentModuli();
1040 break;
1041 default:
1042 tan_mod = elasticTangentModuli();
1043 }
1044
1045 return tan_mod;
1046}
1047
1048void
1050{
1051 DenseVector<Real> mo(LIBMESH_DIM * _nss), no(LIBMESH_DIM * _nss);
1052
1053 // Update slip direction and normal with crystal orientation
1054 for (unsigned int i = 0; i < _nss; ++i)
1055 {
1056 for (const auto j : make_range(Moose::dim))
1057 {
1058 mo(i * LIBMESH_DIM + j) = 0.0;
1059 for (const auto k : make_range(Moose::dim))
1060 mo(i * LIBMESH_DIM + j) =
1061 mo(i * LIBMESH_DIM + j) + _crysrot[_qp](j, k) * _mo(i * LIBMESH_DIM + k);
1062 }
1063
1064 for (const auto j : make_range(Moose::dim))
1065 {
1066 no(i * LIBMESH_DIM + j) = 0.0;
1067 for (const auto k : make_range(Moose::dim))
1068 no(i * LIBMESH_DIM + j) =
1069 no(i * LIBMESH_DIM + j) + _crysrot[_qp](j, k) * _no(i * LIBMESH_DIM + k);
1070 }
1071 }
1072
1073 // Calculate Schmid tensor and resolved shear stresses
1074 for (unsigned int i = 0; i < _nss; ++i)
1075 for (const auto j : make_range(Moose::dim))
1076 for (const auto k : make_range(Moose::dim))
1077 _s0[i](j, k) = mo(i * LIBMESH_DIM + j) * no(i * LIBMESH_DIM + k);
1078}
1079
1082{
1083 RankFourTensor tan_mod;
1084 RankTwoTensor pk2fet, fepk2;
1085 RankFourTensor deedfe, dsigdpk2dfe;
1086
1087 // Fill in the matrix stiffness material property
1088
1089 for (const auto i : make_range(Moose::dim))
1090 for (const auto j : make_range(Moose::dim))
1091 for (const auto k : make_range(Moose::dim))
1092 {
1093 deedfe(i, j, k, i) = deedfe(i, j, k, i) + _fe(k, j) * 0.5;
1094 deedfe(i, j, k, j) = deedfe(i, j, k, j) + _fe(k, i) * 0.5;
1095 }
1096
1097 usingTensorIndices(i_, j_, k_, l_);
1098 dsigdpk2dfe = _fe.times<i_, k_, j_, l_>(_fe) * _elasticity_tensor[_qp] * deedfe;
1099
1100 pk2fet = _pk2_tmp * _fe.transpose();
1101 fepk2 = _fe * _pk2_tmp;
1102
1103 for (const auto i : make_range(Moose::dim))
1104 for (const auto j : make_range(Moose::dim))
1105 for (const auto l : make_range(Moose::dim))
1106 {
1107 tan_mod(i, j, i, l) = tan_mod(i, j, i, l) + pk2fet(l, j);
1108 tan_mod(i, j, j, l) = tan_mod(i, j, j, l) + fepk2(i, l);
1109 }
1110
1111 tan_mod += dsigdpk2dfe;
1112
1113 Real je = _fe.det();
1114 if (je > 0.0)
1115 tan_mod /= je;
1116
1117 return tan_mod;
1118}
1119
1122{
1123 return _elasticity_tensor[_qp]; // update jacobian_mult
1124}
1125
1126bool
1128{
1129 if (_lsrch_method == "CUT_HALF")
1130 {
1131 Real rnorm;
1132 RankTwoTensor resid;
1133 Real step = 1.0;
1134
1135 do
1136 {
1137 _pk2_tmp = _pk2_tmp - step * dpk2;
1138 step /= 2.0;
1139 _pk2_tmp = _pk2_tmp + step * dpk2;
1140
1141 calcResidual(resid);
1142 rnorm = resid.L2norm();
1143 } while (rnorm > rnorm_prev && step > _min_lsrch_step);
1144
1145 if (rnorm > rnorm_prev && step <= _min_lsrch_step)
1146 return false;
1147
1148 return true;
1149 }
1150 else if (_lsrch_method == "BISECTION")
1151 {
1152 unsigned int count = 0;
1153 Real step_a = 0.0;
1154 Real step_b = 1.0;
1155 Real step = 1.0;
1156 Real s_m = 1000.0;
1157 Real rnorm = 1000.0;
1158
1159 RankTwoTensor resid;
1160 calcResidual(resid);
1161 Real s_b = resid.doubleContraction(dpk2);
1162 Real rnorm1 = resid.L2norm();
1163 _pk2_tmp = _pk2_tmp - dpk2;
1164 calcResidual(resid);
1165 Real s_a = resid.doubleContraction(dpk2);
1166 Real rnorm0 = resid.L2norm();
1167 _pk2_tmp = _pk2_tmp + dpk2;
1168
1169 if ((rnorm1 / rnorm0) < _lsrch_tol || s_a * s_b > 0)
1170 {
1171 calcResidual(resid);
1172 return true;
1173 }
1174
1175 while ((rnorm / rnorm0) > _lsrch_tol && count < _lsrch_max_iter)
1176 {
1177 _pk2_tmp = _pk2_tmp - step * dpk2;
1178 step = 0.5 * (step_b + step_a);
1179 _pk2_tmp = _pk2_tmp + step * dpk2;
1180 calcResidual(resid);
1181 s_m = resid.doubleContraction(dpk2);
1182 rnorm = resid.L2norm();
1183
1184 if (s_m * s_a < 0.0)
1185 {
1186 step_b = step;
1187 s_b = s_m;
1188 }
1189 if (s_m * s_b < 0.0)
1190 {
1191 step_a = step;
1192 s_a = s_m;
1193 }
1194 count++;
1195 }
1196
1197 if ((rnorm / rnorm0) < _lsrch_tol && count < _lsrch_max_iter)
1198 return true;
1199
1200 return false;
1201 }
1202 else
1203 {
1204 mooseError("Line search meothod is not provided.");
1205 return false;
1206 }
1207}
1208
1209void
registerMooseObjectDeprecated("SolidMechanicsApp", FiniteStrainCrystalPlasticity, "11/15/2024 12:00")
void mooseWarning(Args &&... args)
void mooseError(Args &&... args)
unsigned int count
void ErrorVector unsigned int
MaterialProperty< RankFourTensor > & _Jacobian_mult
derivative of stress w.r.t. strain (_dstress_dstrain)
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
ComputeStressBase is the base class for stress tensors computed from MOOSE's strain calculators.
static InputParameters validParams()
FiniteStrainCrystalPlasticity uses the multiplicative decomposition of deformation gradient and solve...
virtual void solveStatevar()
This function solves internal variables.
virtual void calcResidual(RankTwoTensor &)
This function calculate stress residual.
Real _rtol
Stress residual equation relative tolerance.
virtual RankFourTensor elastoPlasticTangentModuli()
This function calculate the exact tangent moduli for preconditioner.
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
virtual void readFileHardnessParams()
This function read hardness parameters from file.
void calc_schmid_tensor()
This function calculate the Schmid tensor.
unsigned int _num_slip_sys_flowrate_props
Number of slip system flow rate parameters.
virtual void solveStress()
This function solves for stress, updates plastic deformation gradient.
void internalVariableUpdateNRiteration()
This function updates internal variables after each NewTon Raphson iteration (_fp_inv)
const MaterialProperty< RankTwoTensor > & _deformation_gradient_old
MaterialProperty< RankTwoTensor > & _fp
const MaterialProperty< RankTwoTensor > & _deformation_gradient
virtual void postSolveQp()
This function update stress and internal variable after solve.
virtual void getFlowRateParams()
This function assign flow rate parameters - see test.
const unsigned int _nss
Number of slip system resistance.
virtual void getInitSlipSysRes()
This function assign slip system resistances - see test.
Real _dfgrd_scale_factor
Scales the substepping increment to obtain deformation gradient at a substep iteration.
virtual void initSlipSysProps()
This function initializes slip system resistances.
virtual void update_slip_system_resistance()
This function updates the slip system resistances.
unsigned int _lsrch_max_iter
Line search bisection method maximum iteration number.
virtual void solveQp()
This function solves stress and internal variables.
Real _lsrch_tol
Line search bisection method tolerance.
unsigned int _maxiterg
Maximum number of iterations for internal variable update.
unsigned int _max_substep_iter
Maximum number of substep iterations.
unsigned int _maxiter
Maximum number of iterations for stress update.
MaterialProperty< std::vector< Real > > & _gss
virtual void computeQpElasticityTensor()
This function updates the elasticity tensor at a quadrature point.
RankTwoTensor _delta_dfgrd
Flag to check whether convergence is achieved.
bool _first_step_iter
Flags to reset variables and reinitialize variables.
virtual void calc_resid_jacob(RankTwoTensor &, RankFourTensor &)
This function calls the residual and jacobian functions used in the stress update algorithm.
Real _min_lsrch_step
Minimum line search step size.
virtual void preSolveStatevar()
This function set variables for internal variable solve.
std::string _slip_sys_hard_prop_file_name
The hardening parameters in this class are read from .i file. The user can override to read from file...
RankTwoTensor get_current_rotation(const RankTwoTensor &a)
This function perform RU decomposition to obtain the rotation tensor.
virtual void preSolveStress()
This function set variables for stress solve.
virtual void readFileFlowRateParams()
This function read flow rate parameters from file - see test.
virtual void computeQpStress()
This function updates the stress at a quadrature point.
virtual void updateGss()
This function updates the slip system resistances.
MaterialProperty< RankTwoTensor > & _lag_e
virtual RankFourTensor calcTangentModuli()
This function calculate the tangent moduli for preconditioner.
MooseEnum _intvar_read_type
Read from options for initial values of internal variables.
const MaterialProperty< RankTwoTensor > & _fp_old
FiniteStrainCrystalPlasticity(const InputParameters &parameters)
virtual RankFourTensor elasticTangentModuli()
This function calculate the elastic tangent moduli for preconditioner.
MaterialProperty< RankTwoTensor > & _update_rot
virtual void getSlipIncrements()
This function updates the slip increments.
virtual void calcJacobian(RankFourTensor &)
This function calculate jacobian.
virtual void initQpStatefulProperties()
This function initializes the stateful properties such as stress, plastic deformation gradient,...
virtual void preSolveQp()
This function set variables for stress and internal variable solve.
const MaterialProperty< RankTwoTensor > & _pk2_old
std::string _slip_sys_flow_prop_file_name
File should contain values of the flow rate equation parameters.
bool _input_rndm_scale_var
Input option for scaling variable to generate random stress when convergence fails.
virtual void assignSlipSysRes()
This function assign initial values of slip system resistances/internal variables read from getSlipSy...
const MaterialProperty< std::vector< Real > > & _gss_old
Real _abs_tol
Stress residual equation absolute tolerance.
bool line_search_update(const Real rnorm_prev, const RankTwoTensor)
This function performs the line search update.
unsigned int _num_slip_sys_props
Number of slip system specific properties provided in the file containing slip system normals and dir...
Real _slip_incr_tol
Slip increment tolerance.
const MaterialProperty< RankTwoTensor > & _crysrot
const MaterialProperty< Real > & _acc_slip_old
RankTwoTensor getMatRot(const RankTwoTensor &a)
This function perform RU decomposition to obtain the rotation tensor.
virtual void postSolveStress()
This function update stress and plastic deformation gradient after solve.
Real _gtol
Internal variable update equation tolerance.
MooseEnum _tan_mod_type
Type of tangent moduli calculation.
bool _use_line_search
Flag to activate line serach.
std::string _slip_sys_file_name
File should contain slip plane normal and direction. See test.
virtual void getHardnessParams()
This function assign flow rate parameters from .i file - see test.
virtual void initAdditionalProps()
This function initializes additional parameters.
virtual void getSlipSystems()
This function reads slip system from file - see test.
std::string _slip_sys_res_prop_file_name
File should contain initial values of the slip system resistances.
virtual void readFileInitSlipSysRes()
This function read slip system resistances from file - see test.
virtual void postSolveStatevar()
This function update internal variable after solve.
MaterialProperty< RankTwoTensor > & _pk2
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
virtual void resize(const std::size_t size) override final
RankFourTensorTempl< T > invSymm() const
static RankFourTensorTempl< T > IdentityFour()
static void initRandom(unsigned int)
void addIa(const T &a)
RankFourTensorTempl< T > times(const RankTwoTensorTempl< T > &b) const
T doubleContraction(const RankTwoTensorTempl< T > &a) const
RankTwoTensorTempl< T > inverse() const
RankTwoTensorTempl< T > transpose() const
static RankTwoTensorTempl< T > genRandomSymmTensor(T stddev, T mean)
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
static constexpr std::size_t dim