www.mooseframework.org
FiniteStrainCrystalPlasticity.C
Go to the documentation of this file.
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 
11 #include "petscblaslapack.h"
12 #include "libmesh/utility.h"
13 
14 #include <fstream>
15 #include <cmath>
16 
17 registerMooseObjectDeprecated("SolidMechanicsApp",
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 
177  _read_from_slip_sys_file = false;
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 
185  getSlipSystems();
186 
188 }
189 
190 void
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 
207 void
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 
233 void
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.
243 void
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
261 void
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.
314 void
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;
326  vec.resize(_num_slip_sys_flowrate_props);
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]))
332  mooseError(
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
343 void
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  {
397  mooseWarning(
398  "FiniteStrainCrystalPlasticity: Non-positive flow rate parameters ", _a0(i), ",", _xm(i));
399  break;
400  }
401  }
402 }
403 
404 // Read hardness parameters from .txt file
405 void
407 {
408 }
409 
410 // Read hardness parameters from .i file
411 void
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
425 void
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)
467  mooseError(
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
483 void
485 {
486 }
487 
492 void
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)
504  _dfgrd_tmp_old.addIa(1.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 
559 void
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 
577 void
579 {
581  solveStatevar();
582  if (_err_tol)
583  return;
585 }
586 
587 void
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 
620 void
622 {
623  if (_max_substep_iter == 1) // No substepping
624  {
625  _gss_tmp = _gss_old[_qp];
627  }
628  else
629  {
630  if (_first_step_iter)
631  {
634  }
635  else
637  }
638 }
639 
640 void
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  {
652  preSolveStress();
653  solveStress();
654  if (_err_tol)
655  return;
656  postSolveStress();
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 
682 void
684 {
685  if (_max_substep_iter == 1) // No substepping
686  {
687  _gss[_qp] = _gss_tmp;
689  }
690  else
691  {
692  if (_last_step_iter)
693  {
694  _gss[_qp] = _gss_tmp;
696  }
697  else
698  {
701  }
702  }
703 }
704 
705 void
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  {
717  if (_first_step_iter)
718  {
720  _fp_old_inv = _fp_old[_qp].inverse();
721  }
722  else
724 
727  }
728 }
729 
730 void
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
742  mooseWarning(
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
765  mooseWarning(
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 
786  if (_use_line_search)
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 
801 void
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
825 void
827 {
828  updateGss();
829 }
830 
835 void
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)
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
880 void
882 {
883  calcResidual(resid);
884  if (_err_tol)
885  return;
886  calcJacobian(jac);
887 }
888 
889 void
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;
915  _fe = _dfgrd_tmp * _fp_inv;
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 
926 void
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.
960 void
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;
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.
986 {
987  return getMatRot(a);
988 }
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
1026 void
1028 {
1029 }
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 
1048 void
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 
1126 bool
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 
1209 void
1211 {
1212  _fp_prev_inv = _fp_inv; // update _fp_prev_inv
1213 }
const MaterialProperty< RankTwoTensor > & _pk2_old
void internalVariableUpdateNRiteration()
This function updates internal variables after each NewTon Raphson iteration (_fp_inv) ...
MaterialProperty< RankFourTensor > & _Jacobian_mult
derivative of stress w.r.t. strain (_dstress_dstrain)
MaterialProperty< RankTwoTensor > & _lag_e
RankTwoTensorTempl< Real > inverse() const
const MaterialProperty< RankTwoTensor > & _deformation_gradient
ComputeStressBase is the base class for stress tensors computed from MOOSE&#39;s strain calculators...
bool _input_rndm_scale_var
Input option for scaling variable to generate random stress when convergence fails.
static void initRandom(unsigned int)
virtual void getHardnessParams()
This function assign flow rate parameters from .i file - see test.
bool _use_line_search
Flag to activate line serach.
const MaterialProperty< std::vector< Real > > & _gss_old
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
MPI_Info info
static RankFourTensorTempl< Real > IdentityFour()
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
virtual void calcJacobian(RankFourTensor &)
This function calculate jacobian.
static InputParameters validParams()
virtual void computeQpStress()
This function updates the stress at a quadrature point.
MaterialProperty< RankTwoTensor > & _pk2
virtual void initQpStatefulProperties()
This function initializes the stateful properties such as stress, plastic deformation gradient...
virtual void solveStress()
This function solves for stress, updates plastic deformation gradient.
std::string _slip_sys_flow_prop_file_name
File should contain values of the flow rate equation parameters.
virtual void solveStatevar()
This function solves internal variables.
FiniteStrainCrystalPlasticity(const InputParameters &parameters)
virtual void update_slip_system_resistance()
This function updates the slip system resistances.
static constexpr std::size_t dim
unsigned int _num_slip_sys_flowrate_props
Number of slip system flow rate parameters.
virtual void calcResidual(RankTwoTensor &)
This function calculate stress residual.
const MaterialProperty< RankTwoTensor > & _fp_old
void inverse(const std::vector< std::vector< Real >> &m, std::vector< std::vector< Real >> &m_inv)
RankTwoTensor getMatRot(const RankTwoTensor &a)
This function perform RU decomposition to obtain the rotation tensor.
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
virtual void readFileHardnessParams()
This function read hardness parameters from file.
virtual void updateGss()
This function updates the slip system resistances.
Real _rtol
Stress residual equation relative tolerance.
void mooseWarning(Args &&... args) const
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...
void addRequiredParam(const std::string &name, const std::string &doc_string)
unsigned int _maxiter
Maximum number of iterations for stress update.
virtual void resize(const std::size_t size) override final
virtual void assignSlipSysRes()
This function assign initial values of slip system resistances/internal variables read from getSlipSy...
Real _dfgrd_scale_factor
Scales the substepping increment to obtain deformation gradient at a substep iteration.
const unsigned int _nss
Number of slip system resistance.
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
virtual RankFourTensor elastoPlasticTangentModuli()
This function calculate the exact tangent moduli for preconditioner.
RankTwoTensor _delta_dfgrd
Flag to check whether convergence is achieved.
virtual RankFourTensor elasticTangentModuli()
This function calculate the elastic tangent moduli for preconditioner.
MaterialProperty< std::vector< Real > > & _gss
void addIa(const Real &a)
bool checkFileReadable(const std::string &filename, bool check_line_endings=false, bool throw_on_unreadable=true, bool check_for_git_lfs_pointer=true)
static RankTwoTensorTempl< Real > genRandomSymmTensor(Real stddev, Real mean)
virtual RankFourTensor calcTangentModuli()
This function calculate the tangent moduli for preconditioner.
bool line_search_update(const Real rnorm_prev, const RankTwoTensor)
This function performs the line search update.
const MaterialProperty< RankTwoTensor > & _deformation_gradient_old
Real doubleContraction(const RankTwoTensorTempl< Real > &a) const
const MaterialProperty< RankTwoTensor > & _crysrot
void calc_schmid_tensor()
This function calculate the Schmid tensor.
PetscErrorCode PetscInt const PetscInt IS * is
MaterialProperty< RankTwoTensor > & _fp
virtual void postSolveStatevar()
This function update internal variable after solve.
unsigned int _lsrch_max_iter
Line search bisection method maximum iteration number.
virtual void getFlowRateParams()
This function assign flow rate parameters - see test.
Real _gtol
Internal variable update equation tolerance.
std::string _slip_sys_res_prop_file_name
File should contain initial values of the slip system resistances.
virtual void postSolveQp()
This function update stress and internal variable after solve.
virtual void preSolveStress()
This function set variables for stress solve.
RankTwoTensorTempl< Real > transpose() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void postSolveStress()
This function update stress and plastic deformation gradient after solve.
virtual void calc_resid_jacob(RankTwoTensor &, RankFourTensor &)
This function calls the residual and jacobian functions used in the stress update algorithm...
MooseEnum _tan_mod_type
Type of tangent moduli calculation.
RankFourTensorTempl< Real > times(const RankTwoTensorTempl< Real > &b) const
Real _lsrch_tol
Line search bisection method tolerance.
virtual void computeQpElasticityTensor()
This function updates the elasticity tensor at a quadrature point.
IntRange< T > make_range(T beg, T end)
virtual void getSlipSystems()
This function reads slip system from file - see test.
void mooseError(Args &&... args) const
unsigned int _num_slip_sys_props
Number of slip system specific properties provided in the file containing slip system normals and dir...
void addClassDescription(const std::string &doc_string)
virtual void readFileFlowRateParams()
This function read flow rate parameters from file - see test.
unsigned int _max_substep_iter
Maximum number of substep iterations.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
bool _first_step_iter
Flags to reset variables and reinitialize variables.
virtual void initSlipSysProps()
This function initializes slip system resistances.
FiniteStrainCrystalPlasticity uses the multiplicative decomposition of deformation gradient and solve...
registerMooseObjectDeprecated("SolidMechanicsApp", FiniteStrainCrystalPlasticity, "11/15/2024 12:00")
virtual void getInitSlipSysRes()
This function assign slip system resistances - see test.
virtual void initAdditionalProps()
This function initializes additional parameters.
virtual void preSolveStatevar()
This function set variables for internal variable solve.
MaterialProperty< RankTwoTensor > & _update_rot
Real _abs_tol
Stress residual equation absolute tolerance.
virtual void readFileInitSlipSysRes()
This function read slip system resistances from file - see test.
unsigned int _maxiterg
Maximum number of iterations for internal variable update.
RankFourTensorTempl< T > invSymm() const
virtual void getSlipIncrements()
This function updates the slip increments.
MooseUnits pow(const MooseUnits &, int)
const MaterialProperty< Real > & _acc_slip_old
static const std::string k
Definition: NS.h:124
RankTwoTensor get_current_rotation(const RankTwoTensor &a)
This function perform RU decomposition to obtain the rotation tensor.
void ErrorVector unsigned int
virtual void solveQp()
This function solves stress and internal variables.
MooseEnum _intvar_read_type
Read from options for initial values of internal variables.
Real _min_lsrch_step
Minimum line search step size.
virtual void preSolveQp()
This function set variables for stress and internal variable solve.
std::string _slip_sys_file_name
File should contain slip plane normal and direction. See test.
Real _slip_incr_tol
Slip increment tolerance.