LCOV - code coverage report
Current view: top level - src/utils - MultiPlasticityLinearSystem.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 267 272 98.2 %
Date: 2025-07-25 05:00:39 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14