www.mooseframework.org
MultiPlasticityLinearSystem.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 "RankFourTensor.h"
12 
13 // Following is for perturbing distances in eliminating linearly-dependent directions
14 #include "MooseRandom.h"
15 
16 // Following is used to access PETSc's LAPACK routines
17 #include <petscblaslapack.h>
18 
20 
21 InputParameters
23 {
24  InputParameters params = MultiPlasticityRawComponentAssembler::validParams();
25  params.addRangeCheckedParam<Real>("linear_dependent",
26  1E-4,
27  "linear_dependent>=0 & linear_dependent<1",
28  "Flow directions are considered linearly dependent if the "
29  "smallest singular value is less than linear_dependent times "
30  "the largest singular value");
31  return params;
32 }
33 
36  _svd_tol(_params.get<Real>("linear_dependent")),
37  _min_f_tol(-1.0)
38 {
39  for (unsigned model = 0; model < _num_models; ++model)
40  if (_min_f_tol == -1.0 || _min_f_tol > _f[model]->_f_tol)
41  _min_f_tol = _f[model]->_f_tol;
42 
43  MooseRandom::seed(0);
44 }
45 
46 int
47 MultiPlasticityLinearSystem::singularValuesOfR(const std::vector<RankTwoTensor> & r,
48  std::vector<Real> & s)
49 {
50  int bm = r.size();
51  int bn = 6;
52 
53  s.resize(std::min(bm, bn));
54 
55  // prepare for gesvd or gesdd routine provided by PETSc
56  // Want to find the singular values of matrix
57  // ( r[0](0,0) r[0](0,1) r[0](0,2) r[0](1,1) r[0](1,2) r[0](2,2) )
58  // ( r[1](0,0) r[1](0,1) r[1](0,2) r[1](1,1) r[1](1,2) r[1](2,2) )
59  // a = ( r[2](0,0) r[2](0,1) r[2](0,2) r[2](1,1) r[2](1,2) r[2](2,2) )
60  // ( r[3](0,0) r[3](0,1) r[3](0,2) r[3](1,1) r[3](1,2) r[3](2,2) )
61  // ( r[4](0,0) r[4](0,1) r[4](0,2) r[4](1,1) r[4](1,2) r[4](2,2) )
62  // bm = 5
63 
64  std::vector<double> a(bm * 6);
65  // Fill in the a "matrix" by going down columns
66  unsigned ind = 0;
67  for (int col = 0; col < 3; ++col)
68  for (int row = 0; row < bm; ++row)
69  a[ind++] = r[row](0, col);
70  for (int col = 3; col < 5; ++col)
71  for (int row = 0; row < bm; ++row)
72  a[ind++] = r[row](1, col - 2);
73  for (int row = 0; row < bm; ++row)
74  a[ind++] = r[row](2, 2);
75 
76  // u and vt are dummy variables because they won't
77  // get referenced due to the "N" and "N" choices
78  int sizeu = 1;
79  std::vector<double> u(sizeu);
80  int sizevt = 1;
81  std::vector<double> vt(sizevt);
82 
83  int sizework = 16 * (bm + 6); // this is above the lowerbound specified in the LAPACK doco
84  std::vector<double> work(sizework);
85 
86  int info;
87 
88  LAPACKgesvd_("N",
89  "N",
90  &bm,
91  &bn,
92  &a[0],
93  &bm,
94  &s[0],
95  &u[0],
96  &sizeu,
97  &vt[0],
98  &sizevt,
99  &work[0],
100  &sizework,
101  &info);
102 
103  return info;
104 }
105 
106 void
108  const std::vector<Real> & intnl,
109  const std::vector<Real> & f,
110  const std::vector<RankTwoTensor> & r,
111  const std::vector<bool> & active,
112  std::vector<bool> & deactivated_due_to_ld)
113 {
114  deactivated_due_to_ld.resize(_num_surfaces, false);
115 
116  unsigned num_active = r.size();
117 
118  if (num_active <= 1)
119  return;
120 
121  std::vector<double> s;
122  int info = singularValuesOfR(r, s);
123  if (info != 0)
124  mooseError("In finding the SVD in the return-map algorithm, the PETSC LAPACK gesvd routine "
125  "returned with error code ",
126  info);
127 
128  // num_lin_dep are the number of linearly dependent
129  // "r vectors", if num_active <= 6
130  unsigned int num_lin_dep = 0;
131 
132  unsigned i = s.size();
133  while (i-- > 0)
134  if (s[i] < _svd_tol * s[0])
135  num_lin_dep++;
136  else
137  break;
138 
139  if (num_lin_dep == 0 && num_active <= 6)
140  return;
141 
142  // From here on, some flow directions are linearly dependent
143 
144  // Find the signed "distance" of the current (stress, internal) configuration
145  // from the yield surfaces. This distance will not be precise, but
146  // i want to preferentially deactivate yield surfaces that are close
147  // to the current stress point.
148  std::vector<RankTwoTensor> df_dstress;
149  dyieldFunction_dstress(stress, intnl, active, df_dstress);
150 
151  typedef std::pair<Real, unsigned> pair_for_sorting;
152  std::vector<pair_for_sorting> dist(num_active);
153  for (unsigned i = 0; i < num_active; ++i)
154  {
155  dist[i].first = f[i] / df_dstress[i].L2norm();
156  dist[i].second = i;
157  }
158  std::sort(dist.begin(), dist.end()); // sorted in ascending order
159 
160  // There is a potential problem when we have equal f[i], for it can give oscillations
161  bool equals_detected = false;
162  for (unsigned i = 0; i < num_active - 1; ++i)
163  if (std::abs(dist[i].first - dist[i + 1].first) < _min_f_tol)
164  {
165  equals_detected = true;
166  dist[i].first += _min_f_tol * (MooseRandom::rand() - 0.5);
167  }
168  if (equals_detected)
169  std::sort(dist.begin(), dist.end()); // sorted in ascending order
170 
171  std::vector<bool> scheduled_for_deactivation;
172  scheduled_for_deactivation.assign(num_active, false);
173 
174  // In the following loop we go through all the flow directions, from
175  // the one with the largest dist, to the one with the smallest dist,
176  // adding them one-by-one into r_tmp. Upon each addition we check
177  // for linear-dependence. if LD is found, we schedule the most
178  // recently added flow direction for deactivation, and pop it
179  // back off r_tmp
180  unsigned current_yf;
181  current_yf = dist[num_active - 1].second;
182  // the one with largest dist
183  std::vector<RankTwoTensor> r_tmp = {r[current_yf]};
184 
185  unsigned num_kept_active = 1;
186  for (unsigned yf_to_try = 2; yf_to_try <= num_active; ++yf_to_try)
187  {
188  current_yf = dist[num_active - yf_to_try].second;
189  if (num_active == 2) // shortcut to we don't have to singularValuesOfR
190  scheduled_for_deactivation[current_yf] = true;
191  else if (num_kept_active >= 6) // shortcut to we don't have to singularValuesOfR: there can
192  // never be > 6 linearly-independent r vectors
193  scheduled_for_deactivation[current_yf] = true;
194  else
195  {
196  r_tmp.push_back(r[current_yf]);
197  info = singularValuesOfR(r_tmp, s);
198  if (info != 0)
199  mooseError("In finding the SVD in the return-map algorithm, the PETSC LAPACK gesvd routine "
200  "returned with error code ",
201  info);
202  if (s[s.size() - 1] < _svd_tol * s[0])
203  {
204  scheduled_for_deactivation[current_yf] = true;
205  r_tmp.pop_back();
206  num_lin_dep--;
207  }
208  else
209  num_kept_active++;
210  if (num_lin_dep == 0 && num_active <= 6)
211  // have taken out all the vectors that were linearly dependent
212  // so no point continuing
213  break;
214  }
215  }
216 
217  unsigned int old_active_number = 0;
218  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
219  if (active[surface])
220  {
221  if (scheduled_for_deactivation[old_active_number])
222  deactivated_due_to_ld[surface] = true;
223  old_active_number++;
224  }
225 }
226 
227 void
229  const std::vector<Real> & intnl_old,
230  const std::vector<Real> & intnl,
231  const std::vector<Real> & pm,
232  const RankTwoTensor & delta_dp,
233  std::vector<Real> & f,
234  std::vector<RankTwoTensor> & r,
235  RankTwoTensor & epp,
236  std::vector<Real> & ic,
237  const std::vector<bool> & active)
238 {
239  // see comments at the start of .h file
240 
241  mooseAssert(intnl_old.size() == _num_models,
242  "Size of intnl_old is " << intnl_old.size()
243  << " which is incorrect in calculateConstraints");
244  mooseAssert(intnl.size() == _num_models,
245  "Size of intnl is " << intnl.size() << " which is incorrect in calculateConstraints");
246  mooseAssert(pm.size() == _num_surfaces,
247  "Size of pm is " << pm.size() << " which is incorrect in calculateConstraints");
248  mooseAssert(active.size() == _num_surfaces,
249  "Size of active is " << active.size()
250  << " which is incorrect in calculateConstraints");
251 
252  // yield functions
253  yieldFunction(stress, intnl, active, f);
254 
255  // flow directions and "epp"
256  flowPotential(stress, intnl, active, r);
257  epp = RankTwoTensor();
258  unsigned ind = 0;
259  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
260  if (active[surface])
261  epp += pm[surface] * r[ind++]; // note, even the deactivated_due_to_ld must get added in
262  epp -= delta_dp;
263 
264  // internal constraints
265  std::vector<Real> h;
266  hardPotential(stress, intnl, active, h);
267  ic.resize(0);
268  ind = 0;
269  std::vector<unsigned int> active_surfaces;
270  std::vector<unsigned int>::iterator active_surface;
271  for (unsigned model = 0; model < _num_models; ++model)
272  {
273  activeSurfaces(model, active, active_surfaces);
274  if (active_surfaces.size() > 0)
275  {
276  // some surfaces are active in this model, so must form an internal constraint
277  ic.push_back(intnl[model] - intnl_old[model]);
278  for (active_surface = active_surfaces.begin(); active_surface != active_surfaces.end();
279  ++active_surface)
280  ic[ic.size() - 1] += pm[*active_surface] * h[ind++]; // we know the correct one is h[ind]
281  // since it was constructed in the same
282  // manner
283  }
284  }
285 }
286 
287 void
289  const std::vector<Real> & intnl_old,
290  const std::vector<Real> & intnl,
291  const std::vector<Real> & pm,
292  const RankTwoTensor & delta_dp,
293  std::vector<Real> & rhs,
294  const std::vector<bool> & active,
295  bool eliminate_ld,
296  std::vector<bool> & deactivated_due_to_ld)
297 {
298  // see comments at the start of .h file
299 
300  mooseAssert(intnl_old.size() == _num_models,
301  "Size of intnl_old is " << intnl_old.size() << " which is incorrect in calculateRHS");
302  mooseAssert(intnl.size() == _num_models,
303  "Size of intnl is " << intnl.size() << " which is incorrect in calculateRHS");
304  mooseAssert(pm.size() == _num_surfaces,
305  "Size of pm is " << pm.size() << " which is incorrect in calculateRHS");
306  mooseAssert(active.size() == _num_surfaces,
307  "Size of active is " << active.size() << " which is incorrect in calculateRHS");
308 
309  std::vector<Real> f; // the yield functions
310  RankTwoTensor epp; // the plastic-strain constraint ("direction constraint")
311  std::vector<Real> ic; // the "internal constraints"
312 
313  std::vector<RankTwoTensor> r;
314  calculateConstraints(stress, intnl_old, intnl, pm, delta_dp, f, r, epp, ic, active);
315 
316  if (eliminate_ld)
317  eliminateLinearDependence(stress, intnl, f, r, active, deactivated_due_to_ld);
318  else
319  deactivated_due_to_ld.assign(_num_surfaces, false);
320 
321  std::vector<bool> active_not_deact(_num_surfaces);
322  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
323  active_not_deact[surface] = (active[surface] && !deactivated_due_to_ld[surface]);
324 
325  unsigned num_active_f = 0;
326  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
327  if (active_not_deact[surface])
328  num_active_f++;
329 
330  unsigned num_active_ic = 0;
331  for (unsigned model = 0; model < _num_models; ++model)
332  if (anyActiveSurfaces(model, active_not_deact))
333  num_active_ic++;
334 
335  unsigned int dim = 3;
336  unsigned int system_size = 6 + num_active_f + num_active_ic; // "6" comes from symmeterizing epp,
337  // num_active_f comes from "f",
338  // num_active_f comes from "ic"
339 
340  rhs.resize(system_size);
341 
342  unsigned ind = 0;
343  for (unsigned i = 0; i < dim; ++i)
344  for (unsigned j = 0; j <= i; ++j)
345  rhs[ind++] = -epp(i, j);
346  unsigned active_surface = 0;
347  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
348  if (active[surface])
349  {
350  if (!deactivated_due_to_ld[surface])
351  rhs[ind++] = -f[active_surface];
352  active_surface++;
353  }
354  unsigned active_model = 0;
355  for (unsigned model = 0; model < _num_models; ++model)
356  if (anyActiveSurfaces(model, active))
357  {
358  if (anyActiveSurfaces(model, active_not_deact))
359  rhs[ind++] = -ic[active_model];
360  active_model++;
361  }
362 
363  mooseAssert(ind == system_size, "Incorrect filling of the rhs in calculateRHS");
364 }
365 
366 void
368  const std::vector<Real> & intnl,
369  const std::vector<Real> & pm,
370  const RankFourTensor & E_inv,
371  const std::vector<bool> & active,
372  const std::vector<bool> & deactivated_due_to_ld,
373  std::vector<std::vector<Real>> & jac)
374 {
375  // see comments at the start of .h file
376 
377  mooseAssert(intnl.size() == _num_models,
378  "Size of intnl is " << intnl.size() << " which is incorrect in calculateJacobian");
379  mooseAssert(pm.size() == _num_surfaces,
380  "Size of pm is " << pm.size() << " which is incorrect in calculateJacobian");
381  mooseAssert(active.size() == _num_surfaces,
382  "Size of active is " << active.size() << " which is incorrect in calculateJacobian");
383  mooseAssert(deactivated_due_to_ld.size() == _num_surfaces,
384  "Size of deactivated_due_to_ld is " << deactivated_due_to_ld.size()
385  << " which is incorrect in calculateJacobian");
386 
387  unsigned ind = 0;
388  unsigned active_surface_ind = 0;
389 
390  std::vector<bool> active_surface(_num_surfaces); // active and not deactivated_due_to_ld
391  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
392  active_surface[surface] = (active[surface] && !deactivated_due_to_ld[surface]);
393  unsigned num_active_surface = 0;
394  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
395  if (active_surface[surface])
396  num_active_surface++;
397 
398  std::vector<bool> active_model(
399  _num_models); // whether a model has surfaces that are active and not deactivated_due_to_ld
400  for (unsigned model = 0; model < _num_models; ++model)
401  active_model[model] = anyActiveSurfaces(model, active_surface);
402 
403  unsigned num_active_model = 0;
404  for (unsigned model = 0; model < _num_models; ++model)
405  if (active_model[model])
406  num_active_model++;
407 
408  ind = 0;
409  std::vector<unsigned int> active_model_index(_num_models);
410  for (unsigned model = 0; model < _num_models; ++model)
411  if (active_model[model])
412  active_model_index[model] = ind++;
413  else
414  active_model_index[model] =
415  _num_models + 1; // just a dummy, that will probably cause a crash if something goes wrong
416 
417  std::vector<RankTwoTensor> df_dstress;
418  dyieldFunction_dstress(stress, intnl, active_surface, df_dstress);
419 
420  std::vector<Real> df_dintnl;
421  dyieldFunction_dintnl(stress, intnl, active_surface, df_dintnl);
422 
423  std::vector<RankTwoTensor> r;
424  flowPotential(stress, intnl, active, r);
425 
426  std::vector<RankFourTensor> dr_dstress;
427  dflowPotential_dstress(stress, intnl, active, dr_dstress);
428 
429  std::vector<RankTwoTensor> dr_dintnl;
430  dflowPotential_dintnl(stress, intnl, active, dr_dintnl);
431 
432  std::vector<Real> h;
433  hardPotential(stress, intnl, active, h);
434 
435  std::vector<RankTwoTensor> dh_dstress;
436  dhardPotential_dstress(stress, intnl, active, dh_dstress);
437 
438  std::vector<Real> dh_dintnl;
439  dhardPotential_dintnl(stress, intnl, active, dh_dintnl);
440 
441  // d(epp)/dstress = sum_{active alpha} pm[alpha]*dr_dstress
442  RankFourTensor depp_dstress;
443  ind = 0;
444  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
445  if (active[surface]) // includes deactivated_due_to_ld
446  depp_dstress += pm[surface] * dr_dstress[ind++];
447  depp_dstress += E_inv;
448 
449  // d(epp)/dpm_{active_surface_index} = r_{active_surface_index}
450  std::vector<RankTwoTensor> depp_dpm;
451  depp_dpm.resize(num_active_surface);
452  ind = 0;
453  active_surface_ind = 0;
454  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
455  {
456  if (active[surface])
457  {
458  if (active_surface[surface]) // do not include the deactived_due_to_ld, since their pm are not
459  // dofs in the NR
460  depp_dpm[active_surface_ind++] = r[ind];
461  ind++;
462  }
463  }
464 
465  // d(epp)/dintnl_{active_model_index} = sum(pm[asdf]*dr_dintnl[fdsa])
466  std::vector<RankTwoTensor> depp_dintnl;
467  depp_dintnl.assign(num_active_model, RankTwoTensor());
468  ind = 0;
469  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
470  {
471  if (active[surface])
472  {
473  unsigned int model_num = modelNumber(surface);
474  if (active_model[model_num]) // only include models with surfaces which are still active after
475  // deactivated_due_to_ld
476  depp_dintnl[active_model_index[model_num]] += pm[surface] * dr_dintnl[ind];
477  ind++;
478  }
479  }
480 
481  // df_dstress has been calculated above
482  // df_dpm is always zero
483  // df_dintnl has been calculated above, but only the active_surface+active_model stuff needs to be
484  // included in Jacobian: see below
485 
486  std::vector<RankTwoTensor> dic_dstress;
487  dic_dstress.assign(num_active_model, RankTwoTensor());
488  ind = 0;
489  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
490  {
491  if (active[surface])
492  {
493  unsigned int model_num = modelNumber(surface);
494  if (active_model[model_num]) // only include ic for models with active_surface (ie, if model
495  // only contains deactivated_due_to_ld don't include it)
496  dic_dstress[active_model_index[model_num]] += pm[surface] * dh_dstress[ind];
497  ind++;
498  }
499  }
500 
501  std::vector<std::vector<Real>> dic_dpm;
502  dic_dpm.resize(num_active_model);
503  ind = 0;
504  active_surface_ind = 0;
505  for (unsigned model = 0; model < num_active_model; ++model)
506  dic_dpm[model].assign(num_active_surface, 0);
507  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
508  {
509  if (active[surface])
510  {
511  if (active_surface[surface]) // only take derivs wrt active-but-not-deactivated_due_to_ld pm
512  {
513  unsigned int model_num = modelNumber(surface);
514  // if (active_model[model_num]) // do not need this check as if the surface has
515  // active_surface, the model must be deemed active!
516  dic_dpm[active_model_index[model_num]][active_surface_ind] = h[ind];
517  active_surface_ind++;
518  }
519  ind++;
520  }
521  }
522 
523  std::vector<std::vector<Real>> dic_dintnl;
524  dic_dintnl.resize(num_active_model);
525  for (unsigned model = 0; model < num_active_model; ++model)
526  {
527  dic_dintnl[model].assign(num_active_model, 0);
528  dic_dintnl[model][model] = 1; // deriv wrt internal parameter
529  }
530  ind = 0;
531  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
532  {
533  if (active[surface])
534  {
535  unsigned int model_num = modelNumber(surface);
536  if (active_model[model_num]) // only the models that contain surfaces that are still active
537  // after deactivation_due_to_ld
538  dic_dintnl[active_model_index[model_num]][active_model_index[model_num]] +=
539  pm[surface] * dh_dintnl[ind];
540  ind++;
541  }
542  }
543 
544  unsigned int dim = 3;
545  unsigned int system_size =
546  6 + num_active_surface + num_active_model; // "6" comes from symmeterizing epp
547  jac.resize(system_size);
548  for (unsigned i = 0; i < system_size; ++i)
549  jac[i].assign(system_size, 0);
550 
551  unsigned int row_num = 0;
552  unsigned int col_num = 0;
553  for (unsigned i = 0; i < dim; ++i)
554  for (unsigned j = 0; j <= i; ++j)
555  {
556  for (unsigned k = 0; k < dim; ++k)
557  for (unsigned l = 0; l <= k; ++l)
558  jac[col_num][row_num++] =
559  depp_dstress(i, j, k, l) +
560  (k != l ? depp_dstress(i, j, l, k)
561  : 0); // extra part is needed because i assume dstress(i, j) = dstress(j, i)
562  for (unsigned surface = 0; surface < num_active_surface; ++surface)
563  jac[col_num][row_num++] = depp_dpm[surface](i, j);
564  for (unsigned a = 0; a < num_active_model; ++a)
565  jac[col_num][row_num++] = depp_dintnl[a](i, j);
566  row_num = 0;
567  col_num++;
568  }
569 
570  ind = 0;
571  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
572  if (active_surface[surface])
573  {
574  for (unsigned k = 0; k < dim; ++k)
575  for (unsigned l = 0; l <= k; ++l)
576  jac[col_num][row_num++] =
577  df_dstress[ind](k, l) +
578  (k != l ? df_dstress[ind](l, k)
579  : 0); // extra part is needed because i assume dstress(i, j) = dstress(j, i)
580  for (unsigned beta = 0; beta < num_active_surface; ++beta)
581  jac[col_num][row_num++] = 0; // df_dpm
582  for (unsigned model = 0; model < _num_models; ++model)
583  if (active_model[model]) // only use df_dintnl for models in active_model
584  {
585  if (modelNumber(surface) == model)
586  jac[col_num][row_num++] = df_dintnl[ind];
587  else
588  jac[col_num][row_num++] = 0;
589  }
590  ind++;
591  row_num = 0;
592  col_num++;
593  }
594 
595  for (unsigned a = 0; a < num_active_model; ++a)
596  {
597  for (unsigned k = 0; k < dim; ++k)
598  for (unsigned l = 0; l <= k; ++l)
599  jac[col_num][row_num++] =
600  dic_dstress[a](k, l) +
601  (k != l ? dic_dstress[a](l, k)
602  : 0); // extra part is needed because i assume dstress(i, j) = dstress(j, i)
603  for (unsigned alpha = 0; alpha < num_active_surface; ++alpha)
604  jac[col_num][row_num++] = dic_dpm[a][alpha];
605  for (unsigned b = 0; b < num_active_model; ++b)
606  jac[col_num][row_num++] = dic_dintnl[a][b];
607  row_num = 0;
608  col_num++;
609  }
610 
611  mooseAssert(col_num == system_size, "Incorrect filling of cols in Jacobian");
612 }
613 
614 void
616  const std::vector<Real> & intnl_old,
617  const std::vector<Real> & intnl,
618  const std::vector<Real> & pm,
619  const RankFourTensor & E_inv,
620  const RankTwoTensor & delta_dp,
621  RankTwoTensor & dstress,
622  std::vector<Real> & dpm,
623  std::vector<Real> & dintnl,
624  const std::vector<bool> & active,
625  std::vector<bool> & deactivated_due_to_ld)
626 {
627  // Calculate RHS and Jacobian
628  std::vector<Real> rhs;
629  calculateRHS(stress, intnl_old, intnl, pm, delta_dp, rhs, active, true, deactivated_due_to_ld);
630 
631  std::vector<std::vector<Real>> jac;
632  calculateJacobian(stress, intnl, pm, E_inv, active, deactivated_due_to_ld, jac);
633 
634  // prepare for LAPACKgesv_ routine provided by PETSc
635  int system_size = rhs.size();
636 
637  std::vector<double> a(system_size * system_size);
638  // Fill in the a "matrix" by going down columns
639  unsigned ind = 0;
640  for (int col = 0; col < system_size; ++col)
641  for (int row = 0; row < system_size; ++row)
642  a[ind++] = jac[row][col];
643 
644  int nrhs = 1;
645  std::vector<int> ipiv(system_size);
646  int info;
647  LAPACKgesv_(&system_size, &nrhs, &a[0], &system_size, &ipiv[0], &rhs[0], &system_size, &info);
648 
649  if (info != 0)
650  mooseError("In solving the linear system in a Newton-Raphson process, the PETSC LAPACK gsev "
651  "routine returned with error code ",
652  info);
653 
654  // Extract the results back to dstress, dpm and dintnl
655  std::vector<bool> active_not_deact(_num_surfaces);
656  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
657  active_not_deact[surface] = (active[surface] && !deactivated_due_to_ld[surface]);
658 
659  unsigned int dim = 3;
660  ind = 0;
661 
662  for (unsigned i = 0; i < dim; ++i)
663  for (unsigned j = 0; j <= i; ++j)
664  dstress(i, j) = dstress(j, i) = rhs[ind++];
665  dpm.assign(_num_surfaces, 0);
666  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
667  if (active_not_deact[surface])
668  dpm[surface] = rhs[ind++];
669  dintnl.assign(_num_models, 0);
670  for (unsigned model = 0; model < _num_models; ++model)
671  if (anyActiveSurfaces(model, active_not_deact))
672  dintnl[model] = rhs[ind++];
673 
674  mooseAssert(static_cast<int>(ind) == system_size,
675  "Incorrect extracting of changes from NR solution in nrStep");
676 }
MultiPlasticityRawComponentAssembler::dflowPotential_dintnl
virtual void dflowPotential_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &dr_dintnl)
The derivative of the active flow potentials with respect to the active internal parameters The UserO...
Definition: MultiPlasticityRawComponentAssembler.C:235
MultiPlasticityRawComponentAssembler::modelNumber
unsigned int modelNumber(unsigned int surface)
returns the model number, given the surface number
Definition: MultiPlasticityRawComponentAssembler.C:785
defineLegacyParams
defineLegacyParams(MultiPlasticityLinearSystem)
MultiPlasticityLinearSystem::nrStep
virtual void nrStep(const RankTwoTensor &stress, const std::vector< Real > &intnl_old, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankFourTensor &E_inv, const RankTwoTensor &delta_dp, RankTwoTensor &dstress, std::vector< Real > &dpm, std::vector< Real > &dintnl, const std::vector< bool > &active, std::vector< bool > &deactivated_due_to_ld)
Performs one Newton-Raphson step.
Definition: MultiPlasticityLinearSystem.C:615
MultiPlasticityRawComponentAssembler::dhardPotential_dintnl
virtual void dhardPotential_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< Real > &dh_dintnl)
The derivative of the active hardening potentials with respect to the active internal parameters.
Definition: MultiPlasticityRawComponentAssembler.C:317
MultiPlasticityRawComponentAssembler::flowPotential
virtual void flowPotential(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &r)
The active flow potential(s) - one for each yield function.
Definition: MultiPlasticityRawComponentAssembler.C:180
MultiPlasticityLinearSystem::calculateConstraints
virtual void calculateConstraints(const RankTwoTensor &stress, const std::vector< Real > &intnl_old, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankTwoTensor &delta_dp, std::vector< Real > &f, std::vector< RankTwoTensor > &r, RankTwoTensor &epp, std::vector< Real > &ic, const std::vector< bool > &active)
The constraints.
Definition: MultiPlasticityLinearSystem.C:228
MultiPlasticityRawComponentAssembler::_num_surfaces
unsigned int _num_surfaces
Number of surfaces within the plastic models.
Definition: MultiPlasticityRawComponentAssembler.h:66
MultiPlasticityLinearSystem::eliminateLinearDependence
virtual void eliminateLinearDependence(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< Real > &f, const std::vector< RankTwoTensor > &r, const std::vector< bool > &active, std::vector< bool > &deactivated_due_to_ld)
Performs a number of singular-value decompositions to check for linear-dependence of the active direc...
Definition: MultiPlasticityLinearSystem.C:107
MultiPlasticityRawComponentAssembler::hardPotential
virtual void hardPotential(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< Real > &h)
The active hardening potentials (one for each internal parameter and for each yield function) by assu...
Definition: MultiPlasticityRawComponentAssembler.C:262
MultiPlasticityLinearSystem::calculateJacobian
virtual void calculateJacobian(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankFourTensor &E_inv, const std::vector< bool > &active, const std::vector< bool > &deactivated_due_to_ld, std::vector< std::vector< Real >> &jac)
d(rhs)/d(dof)
Definition: MultiPlasticityLinearSystem.C:367
MultiPlasticityLinearSystem::calculateRHS
virtual void calculateRHS(const RankTwoTensor &stress, const std::vector< Real > &intnl_old, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankTwoTensor &delta_dp, std::vector< Real > &rhs, const std::vector< bool > &active, bool eliminate_ld, std::vector< bool > &deactivated_due_to_ld)
Calculate the RHS which is rhs = -(epp(0,0), epp(1,0), epp(1,1), epp(2,0), epp(2,1),...
Definition: MultiPlasticityLinearSystem.C:288
MultiPlasticityRawComponentAssembler::_f
std::vector< const TensorMechanicsPlasticModel * > _f
User objects that define the yield functions, flow potentials, etc.
Definition: MultiPlasticityRawComponentAssembler.h:75
MultiPlasticityRawComponentAssembler
MultiPlasticityRawComponentAssembler holds and computes yield functions, flow directions,...
Definition: MultiPlasticityRawComponentAssembler.h:44
MultiPlasticityRawComponentAssembler::dyieldFunction_dintnl
virtual void dyieldFunction_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< Real > &df_dintnl)
The derivative of active yield function(s) with respect to their internal parameters (the user object...
Definition: MultiPlasticityRawComponentAssembler.C:153
MultiPlasticityRawComponentAssembler::validParams
static InputParameters validParams()
Definition: MultiPlasticityRawComponentAssembler.C:16
MultiPlasticityRawComponentAssembler::dhardPotential_dstress
virtual void dhardPotential_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &dh_dstress)
The derivative of the active hardening potentials with respect to stress By assumption in the Userobj...
Definition: MultiPlasticityRawComponentAssembler.C:289
MultiPlasticityLinearSystem::validParams
static InputParameters validParams()
Definition: MultiPlasticityLinearSystem.C:22
MultiPlasticityLinearSystem
MultiPlasticityLinearSystem computes the linear system and handles linear-dependence removal for use ...
Definition: MultiPlasticityLinearSystem.h:124
MultiPlasticityRawComponentAssembler::dyieldFunction_dstress
virtual void dyieldFunction_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &df_dstress)
The derivative of the active yield function(s) with respect to stress.
Definition: MultiPlasticityRawComponentAssembler.C:125
RankTwoTensor
RankTwoTensorTempl< Real > RankTwoTensor
Definition: ACGrGrElasticDrivingForce.h:17
MultiPlasticityLinearSystem.h
MultiPlasticityRawComponentAssembler::_num_models
unsigned int _num_models
Number of plastic models for this material.
Definition: MultiPlasticityRawComponentAssembler.h:57
MultiPlasticityRawComponentAssembler::anyActiveSurfaces
bool anyActiveSurfaces(int model, const std::vector< bool > &active)
returns true if any internal surfaces of the given model are active according to 'active'
Definition: MultiPlasticityRawComponentAssembler.C:791
MultiPlasticityLinearSystem::MultiPlasticityLinearSystem
MultiPlasticityLinearSystem(const MooseObject *moose_object)
Definition: MultiPlasticityLinearSystem.C:34
RankFourTensorTempl< Real >
MultiPlasticityLinearSystem::_min_f_tol
Real _min_f_tol
Minimum value of the _f_tol parameters for the Yield Function User Objects.
Definition: MultiPlasticityLinearSystem.h:136
MultiPlasticityRawComponentAssembler::yieldFunction
virtual void yieldFunction(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< Real > &f)
The active yield function(s)
Definition: MultiPlasticityRawComponentAssembler.C:98
MultiPlasticityLinearSystem::singularValuesOfR
virtual int singularValuesOfR(const std::vector< RankTwoTensor > &r, std::vector< Real > &s)
Performs a singular-value decomposition of r and returns the singular values.
Definition: MultiPlasticityLinearSystem.C:47
RankTwoTensorTempl< Real >
MultiPlasticityLinearSystem::_svd_tol
Real _svd_tol
Tolerance on the minimum ratio of singular values before flow-directions are deemed linearly dependen...
Definition: MultiPlasticityLinearSystem.h:133
MultiPlasticityRawComponentAssembler::activeSurfaces
void activeSurfaces(int model, const std::vector< bool > &active, std::vector< unsigned int > &active_surfaces)
Returns the external surface number(s) of the active surfaces of the given model This may be of size=...
Definition: MultiPlasticityRawComponentAssembler.C:800
MultiPlasticityRawComponentAssembler::dflowPotential_dstress
virtual void dflowPotential_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankFourTensor > &dr_dstress)
The derivative of the active flow potential(s) with respect to stress.
Definition: MultiPlasticityRawComponentAssembler.C:207