KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
mpm_stress_principal_invariants_utility.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ \.
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Bodhinanda Chandra
11 //
12 
13 
14 #ifndef KRATOS_MPM_STRESS_PRINCIPAL_INVARIANTS_UTILITY
15 #define KRATOS_MPM_STRESS_PRINCIPAL_INVARIANTS_UTILITY
16 
17 // System includes
18 #include <cmath>
19 #include <set>
20 
21 // External includes
22 
23 // Project includes
24 #include "includes/define.h"
25 #include "includes/variables.h"
26 #include "utilities/math_utils.h"
27 
28 namespace Kratos
29 {
30 
32  {
33 
34  public:
35 
36  typedef Matrix MatrixType;
37 
38  typedef Vector VectorType;
39 
40  typedef unsigned int IndexType;
41 
42  typedef unsigned int SizeType;
43 
44  // Tolerance
45  static constexpr double tolerance = 1.0e-9;
46 
47 
54  static inline void SortPrincipalStress(Vector& rPrincipalStress, Vector& rMainStrain, Matrix& rMainDirections)
55  {
56  // Create Copy
57  Vector principal_direction_1 = ZeroVector(3);
58  Vector principal_direction_2 = ZeroVector(3);
59  Vector principal_direction_3 = ZeroVector(3);
60 
61  for(unsigned int i=0; i<3; i++)
62  {
63  principal_direction_1[i] = rMainDirections(0,i);
64  principal_direction_2[i] = rMainDirections(1,i);
65  principal_direction_3[i] = rMainDirections(2,i);
66  }
67 
68  // Reorder and swap
69  if(rPrincipalStress[0]<rPrincipalStress[1])
70  {
71  std::swap(rPrincipalStress[0],rPrincipalStress[1]);
72  std::swap(rMainStrain[0],rMainStrain[1]);
73  Vector temp_vector = principal_direction_1;
74  principal_direction_1 = principal_direction_2;
75  principal_direction_2 = temp_vector;
76  }
77 
78  if(rPrincipalStress[1]<rPrincipalStress[2])
79  {
80  std::swap(rPrincipalStress[1],rPrincipalStress[2]);
81  std::swap(rMainStrain[1],rMainStrain[2]);
82  Vector temp_vector = principal_direction_2;
83  principal_direction_2 = principal_direction_3;
84  principal_direction_3 = temp_vector;
85  }
86 
87  if(rPrincipalStress[0]<rPrincipalStress[1])
88  {
89  std::swap(rPrincipalStress[0],rPrincipalStress[1]);
90  std::swap(rMainStrain[0],rMainStrain[1]);
91  Vector temp_vector = principal_direction_1;
92  principal_direction_1 = principal_direction_2;
93  principal_direction_2 = temp_vector;
94  }
95 
96  // Copy back to original matrix
97  for(unsigned int i=0; i<3; i++)
98  {
99  rMainDirections(i,0) = principal_direction_1[i];
100  rMainDirections(i,1) = principal_direction_2[i];
101  rMainDirections(i,2) = principal_direction_3[i];
102  }
103  }
104 
105 
112  static inline void CalculateTensorInvariants( const Vector& rVector, double& rI1, double& rJ2 )
113  {
114  // Purely calculate invariant I1 = trace(rVector)
115  rI1 = 0;
116  for (unsigned int i = 0; i < 3; ++i)
117  rI1 += rVector[i];
118 
119  // Purely calculate invariant J2
120  rJ2 = 0;
121  for (unsigned int i = 0; i < 3; i++)
122  rJ2 += std::pow( rVector[i] - rI1/3.0, 2);
123 
124  if ( rVector.size() == 6 )
125  {
126  for (unsigned int i = 3; i < 6; i++)
127  rJ2 += 2.0 * std::pow( rVector[i], 2);
128  }
129  rJ2 /= 2.0;
130 
131  }
132 
133 
141  static inline void CalculateTensorInvariants( const Vector& rVector, double& rI1, double& rJ2, double& rJ3 )
142  {
143  CalculateTensorInvariants( rVector, rI1, rJ2 );
144 
145  // Purely calculate invariant J3
146  rJ3 = 0;
147  Vector s_vector = rVector;
148  for (unsigned int i = 0; i < 3; ++i)
149  s_vector[i] -= rI1/3.0;
150  Matrix tensor = PrincipalVectorToMatrix( s_vector , rVector.size());
151  rJ3 = MathUtils<double>::Det(tensor); // J_3 = det(tensor)
152  }
153 
154 
162  static inline void CalculateTensorInvariantsDerivatives( const Vector& rVector, Vector& rDI1, Vector& rDJ2, Vector& rDJ3 )
163  {
164  double i_1, j_2, j_3;
165  CalculateTensorInvariants(rVector, i_1, j_2, j_3);
166 
167  // dI1/dtensor
168  rDI1 = ZeroVector(rVector.size());
169  for (unsigned int i = 0; i < 3; ++i)
170  rDI1[i] = 1.0;
171 
172  // dJ2/dtensor
173  rDJ2 = ZeroVector(rVector.size());
174  rDJ2 = rVector;
175  for (unsigned int i = 0; i < 3; ++i)
176  rDJ2[i] -= i_1/3.0;
177 
178  // dJ3/dtensor
179  rDJ3 = ZeroVector(rVector.size());
180  Matrix s_tensor = PrincipalVectorToMatrix( rDJ2, rVector.size() );
181  Matrix t_tensor = prod(s_tensor,s_tensor);
182  for (unsigned int i = 0; i < 3; ++i)
183  t_tensor(i,i) -= 2.0/3.0 * j_2;
184  rDJ3 = PrincipalMatrixtoVector( t_tensor, rVector.size());
185 
186  }
187 
188 
196  static inline void CalculateTensorInvariantsSecondDerivatives( const Vector& rVector, Matrix& rD2I1, Matrix& rD2J2, Matrix& rD2J3 )
197  {
198  // This function should return a forth-order tensor and thus the current usage is limited only to rVector.size() = 3
199  if (rVector.size() == 3)
200  {
201  double i_1, j_2;
202  CalculateTensorInvariants(rVector, i_1, j_2);
203 
204  // d2I1/d2tensor
205  rD2I1 = ZeroMatrix(3,3);
206 
207  // d2J2/d2tensor = delta_mp * delta_nq - 1/3 delta_pq * delta_mn
208  rD2J2 = ZeroMatrix(3,3);
209  for (unsigned int i = 0; i < 3; ++i)
210  for (unsigned int j = 0; j < 3; ++j)
211  {
212  if (i == j) rD2J2(i,j) = 2.0/3.0;
213  else rD2J2(i,j) = -1.0/3.0;
214  }
215 
216  // d2J3/d2tensor
217  rD2J3 = ZeroMatrix(3,3);
218  Vector s_vector = rVector;
219  for (unsigned int i = 0; i < 3; ++i)
220  s_vector[i] -= i_1/3.0;
221 
222  for (unsigned int i = 0; i < 3; ++i)
223  for (unsigned int j = 0; j < 3; ++j)
224  {
225  if (i == j) rD2J3(i,j) = 2.0/3.0 * s_vector[i];
226  else rD2J3(i,j) = - 2.0/3.0* (s_vector[i] + s_vector[j]);
227  }
228  }
229  else
230  {
231  KRATOS_ERROR << "The given vector dimension is wrong! Given: " << rVector.size() << "; Expected: 3" << std::endl;
232  }
233 
234  }
235 
236 
243  static inline void CalculateStressInvariants( const Vector& rStress, double& rMeanStressP, double& rDeviatoricQ)
244  {
245  CalculateTensorInvariants(rStress, rMeanStressP, rDeviatoricQ);
246 
247  // Volumetric Equivalent (WARNING, you might want to check the sign. P is defined positive here)
248  rMeanStressP = rMeanStressP / 3.0;
249 
250  // Deviatoric Equivalent
251  rDeviatoricQ = std::sqrt(3 * rDeviatoricQ);
252  }
253 
254 
260  static inline void CalculateThirdStressInvariant(const Vector& rStress, double& rLodeAngle)
261  {
262  double i_1, j_2, j_3;
263  CalculateTensorInvariants( rStress, i_1, j_2, j_3);
264 
265  // Lode Angle
266  if ( std::abs(j_2) < tolerance ) // if j_2 is 0
267  j_2 = tolerance;
268 
269  rLodeAngle = -j_3 / 2.0 * std::pow(3.0/j_2, 1.5);
270  if ( std::abs( rLodeAngle ) > 1.0 ) // if current rLodeAngle magnitude is larger than 1.0
271  rLodeAngle = ( Globals::Pi / 6.0 ) * rLodeAngle / std::abs(rLodeAngle);
272  else // otherwise
273  rLodeAngle = std::asin( rLodeAngle ) / 3.0;
274 
275  }
276 
277 
285  static inline void CalculateStressInvariants( const Vector& rStress, double& rMeanStressP, double& rDeviatoricQ, double& rLodeAngle)
286  {
287  // Calculate first two stress invariant
288  CalculateStressInvariants( rStress, rMeanStressP, rDeviatoricQ);
289 
290  // Lode Angle
291  CalculateThirdStressInvariant(rStress, rLodeAngle);
292  }
293 
294 
301  static inline void CalculateDerivativeVectors( const Vector rStress, Vector& rC1, Vector& rC2)
302  {
303  // Calculate stress invariants
304  double p, q;
305  CalculateStressInvariants( rStress, p, q);
306 
307  // dP/dstress (WARNING, you might want to check the sign. dP is defined positive here)
308  rC1 = ZeroVector(rStress.size());
309  for (unsigned int i = 0; i < 3; i++)
310  rC1[i] = 1.0/3.0;
311 
312  // dQ/dstress
313  rC2 = ZeroVector(rStress.size());
314  if ( std::abs(q) > tolerance) {
315  rC2 = rStress;
316  for (unsigned int i = 0; i < 3; i++)
317  rC2[i] -= p;
318 
319  rC2 *= 3.0 / (2.0 * q);
320  }
321 
322  }
323 
324 
332  static inline void CalculateDerivativeVectors( const Vector rStress, Vector& rC1, Vector& rC2, Vector& rC3)
333  {
334  double i_1, j_2, j_3;
335  CalculateTensorInvariants(rStress, i_1, j_2, j_3);
336 
337  Vector di_1, dj_2, dj_3;
338  CalculateTensorInvariantsDerivatives(rStress, di_1, dj_2, dj_3);
339 
340  // Compute dP/dstress and dQ/dstress
341  CalculateDerivativeVectors(rStress, rC1, rC2);
342 
343  // Compute dLodeAngle/dstress
344  double lode_angle;
345  CalculateThirdStressInvariant(rStress, lode_angle);
346 
347  // Compute dLodeAngle/dstress
348  rC3 = ZeroVector(rStress.size());
349  if (std::abs(j_2) > tolerance)
350  {
351  rC3 = dj_3 - (3.0/2.0 * j_3/j_2) * dj_2;
352  rC3 *= - std::sqrt(3.0) / (2.0 * std::cos(3*lode_angle) * std::pow(j_2, 1.5));
353  }
354  }
355 
356 
363  static inline void CalculateSecondDerivativeMatrices( const Vector rStress, Matrix& r2C1, Matrix& r2C2)
364  {
365  // This function should return a forth-order tensor and thus the current usage is limited only to rStress.size() = 3
366  if (rStress.size() == 3)
367  {
368  // Calculate stress invariants
369  double p, q;
370  CalculateStressInvariants( rStress, p, q);
371 
372  // d2P/d2stress
373  r2C1 = ZeroMatrix(3,3);
374 
375  // d2Q/d2stress
376  r2C2 = ZeroMatrix(3,3);
377  if (std::abs(q) > tolerance)
378  {
379  Vector s_vector = rStress;
380  for (unsigned int i = 0; i < 3; ++i)
381  s_vector[i] -= p;
382 
383  for (unsigned int i = 0; i < 3; ++i)
384  for (unsigned int j = 0; j < 3; ++j)
385  {
386  if (i == j) r2C2(i,j) = 1.0 / q;
387  else r2C2(i,j) = - 1.0/2.0/q;
388 
389  r2C2(i,j) -= (9.0/4.0/std::pow(q, 3) * s_vector[i] * s_vector[j]);
390  }
391  }
392 
393  }
394  else
395  {
396  KRATOS_ERROR << "The given vector dimension is wrong! Given: " << rStress.size() << "; Expected: 3" << std::endl;
397  }
398 
399  }
400 
401 
409  static inline void CalculateSecondDerivativeMatrices( const Vector rStress, Matrix& r2C1, Matrix& r2C2, Matrix& r2C3)
410  {
411  // This function should return a forth-order tensor and thus the current usage is limited only to rStress.size() = 3
412  if (rStress.size() == 3)
413  {
414  // Compute d2P/d2stress and d2Q/d2stress
415  CalculateSecondDerivativeMatrices(rStress, r2C1, r2C2);
416 
417  // Compute d2LodeAngle/d2stress
418  double i_1, j_2, j_3;
419  CalculateTensorInvariants(rStress, i_1, j_2, j_3);
420 
421  Vector di_1, dj_2, dj_3;
422  CalculateTensorInvariantsDerivatives(rStress, di_1, dj_2, dj_3);
423 
424  Matrix d2i_1, d2j_2, d2j_3;
425  CalculateTensorInvariantsSecondDerivatives(rStress, d2i_1, d2j_2, d2j_3);
426 
427  Vector dp, dq, dlode_angle;
428  CalculateDerivativeVectors(rStress, dp, dq, dlode_angle);
429 
430  double lode_angle;
431  CalculateThirdStressInvariant(rStress, lode_angle);
432 
433  r2C3 = ZeroMatrix(3,3);
434  if (std::abs(j_2) > tolerance)
435  {
436  if (std::abs(j_3) < tolerance) j_3 = tolerance;
437 
438  // To reduce complication, we simplify into two components: d(LodeAngle)/dstress = AT * J3' + AS * J2'
439  const double AT = - std::sqrt(3) / (2.0 * j_2 * std::sqrt(j_2) * std::cos(3 * lode_angle));
440  const double AS = AT * (- 1.50 * j_3 / j_2);
441 
442  // Then we need to compute the derivative of each component with respect to stress
443  // 1. d(AT * J3')/dstress = dAT * J3' + AT * J3''
444  Matrix first_component = ZeroMatrix(3,3);
445  Vector aux_dAT = ZeroVector(3);
446  aux_dAT = AT * (-3.0/2.0/j_2 * dj_2 + 3.0 * std::tan(3*lode_angle) * dlode_angle);
447  first_component = MathUtils<double>::TensorProduct3(aux_dAT, dj_3);
448  first_component += AT * d2j_3;
449 
450  // 2. d(AS * J2')/dstress = dAS * J2' + AS * J2''
451  Matrix second_component = ZeroMatrix(3,3);
452  Vector aux_dAS = ZeroVector(3);
453  aux_dAS = AS * (-5.0/2.0/j_2 * dj_2 + 3.0 * std::tan(3*lode_angle) * dlode_angle + 1.0/j_3 * dj_3);
454  second_component = MathUtils<double>::TensorProduct3(aux_dAS, dj_2);
455  second_component += AS * d2j_2;
456 
457  // Sum the two components up
458  r2C3 = first_component + second_component;
459  }
460  }
461  else
462  {
463  KRATOS_ERROR << "The given vector dimension is wrong! Given: " << rStress.size() << "; Expected: 3" << std::endl;
464  }
465  }
466 
467 
474  static Matrix PrincipalVectorToMatrix(const Vector& rVector, const unsigned int& rSize)
475  {
476  Matrix matrix = ZeroMatrix(3,3);
477  if (rSize == 3)
478  {
479  for(unsigned int i=0; i<3; ++i)
480  matrix(i,i) = rVector[i];
481  }
482  else if (rSize == 6)
483  {
484  matrix = MathUtils<double>::StressVectorToTensor( rVector );
485  }
486  return matrix;
487  }
488 
489 
496  static Vector PrincipalMatrixtoVector(const Matrix& rMatrix, const unsigned int& rSize)
497  {
498  Vector vector = ZeroVector(3);
499  if (rSize == 3)
500  {
501  for(unsigned int i=0; i<3; ++i)
502  vector[i] = rMatrix(i,i);
503  }
504  else if (rSize == 6)
505  {
506  vector = MathUtils<double>::StressTensorToVector( rMatrix, rSize );
507  }
508  return vector;
509  }
510 
511 
512  static double CalculateMatrixDoubleContraction(const Matrix& rInput)
513  {
514  double result = 0.0;
515  KRATOS_ERROR_IF(rInput.size1() != rInput.size2())
516  << "CalculateMatrixDoubleContraction only takes square matrices\n";
517  for (size_t i = 0; i < rInput.size1(); ++i)
518  {
519  for (size_t j = 0; j < rInput.size2(); ++j)
520  {
521  result += rInput(i, j) * rInput(i, j);
522  }
523  }
524  return result;
525  }
526 
527 
528  static double CalculateMatrixTrace(const Matrix& rInput)
529  {
530  KRATOS_ERROR_IF(rInput.size1() != rInput.size2()) << "Can only calculate trace of square matrices";
531  double trace = 0.0;
532  for (size_t i = 0; i < rInput.size1(); ++i) trace += rInput(i, i);
533  return trace;
534  }
535  }; // end Class MPMStressPrincipalInvariantsUtility
536 
537 } // end namespace Kratos
538 
539 #endif // KRATOS_MPM_STRESS_PRINCIPAL_INVARIANTS_UTILITY
Definition: mpm_stress_principal_invariants_utility.h:32
static void CalculateTensorInvariants(const Vector &rVector, double &rI1, double &rJ2)
Calculate invariants I1 and J2 of a tensor.
Definition: mpm_stress_principal_invariants_utility.h:112
unsigned int SizeType
Definition: mpm_stress_principal_invariants_utility.h:42
static void CalculateTensorInvariants(const Vector &rVector, double &rI1, double &rJ2, double &rJ3)
Calculate invariants I1, J2, and J3 of a tensor.
Definition: mpm_stress_principal_invariants_utility.h:141
static Matrix PrincipalVectorToMatrix(const Vector &rVector, const unsigned int &rSize)
Transform Stress or Principal stress tensor to Matrix form (fully assuming 3D space).
Definition: mpm_stress_principal_invariants_utility.h:474
static double CalculateMatrixDoubleContraction(const Matrix &rInput)
Definition: mpm_stress_principal_invariants_utility.h:512
static Vector PrincipalMatrixtoVector(const Matrix &rMatrix, const unsigned int &rSize)
Transform Stress or Principal stress tensor to Vector form (fully assuming 3D space).
Definition: mpm_stress_principal_invariants_utility.h:496
static double CalculateMatrixTrace(const Matrix &rInput)
Definition: mpm_stress_principal_invariants_utility.h:528
unsigned int IndexType
Definition: mpm_stress_principal_invariants_utility.h:40
static void CalculateSecondDerivativeMatrices(const Vector rStress, Matrix &r2C1, Matrix &r2C2)
Calculate second stress invariant derivatives d2p/d2sigma (volumetric) and d2q/d2sigma (deviatoric).
Definition: mpm_stress_principal_invariants_utility.h:363
Matrix MatrixType
Definition: mpm_stress_principal_invariants_utility.h:36
static void CalculateSecondDerivativeMatrices(const Vector rStress, Matrix &r2C1, Matrix &r2C2, Matrix &r2C3)
Calculate second stress invariant derivatives d2p/d2sigma (volumetric), d2q/d2sigma (deviatoric),...
Definition: mpm_stress_principal_invariants_utility.h:409
static void SortPrincipalStress(Vector &rPrincipalStress, Vector &rMainStrain, Matrix &rMainDirections)
Sort Principal Stresses, Strains, and Directions to magnitude order.
Definition: mpm_stress_principal_invariants_utility.h:54
static void CalculateDerivativeVectors(const Vector rStress, Vector &rC1, Vector &rC2)
Calculate stress invariant derivatives dp/dsigma (volumetric) and dq/dsigma (deviatoric).
Definition: mpm_stress_principal_invariants_utility.h:301
static void CalculateTensorInvariantsDerivatives(const Vector &rVector, Vector &rDI1, Vector &rDJ2, Vector &rDJ3)
Calculate derivatives of invariants dI1/dtensor, dJ2/dtensor, and dJ3/dtensor.
Definition: mpm_stress_principal_invariants_utility.h:162
Vector VectorType
Definition: mpm_stress_principal_invariants_utility.h:38
static void CalculateStressInvariants(const Vector &rStress, double &rMeanStressP, double &rDeviatoricQ, double &rLodeAngle)
Calculate stress invariants p, q, and lode angle.
Definition: mpm_stress_principal_invariants_utility.h:285
static void CalculateTensorInvariantsSecondDerivatives(const Vector &rVector, Matrix &rD2I1, Matrix &rD2J2, Matrix &rD2J3)
Calculate second derivatives of invariants d2I1/d2tensor, d2J2/d2tensor, and d2J3/d2tensor.
Definition: mpm_stress_principal_invariants_utility.h:196
static constexpr double tolerance
Definition: mpm_stress_principal_invariants_utility.h:45
static void CalculateDerivativeVectors(const Vector rStress, Vector &rC1, Vector &rC2, Vector &rC3)
Calculate stress invariant derivatives dp/dsigma (volumetric), dq/dsigma (deviatoric),...
Definition: mpm_stress_principal_invariants_utility.h:332
static void CalculateThirdStressInvariant(const Vector &rStress, double &rLodeAngle)
Calculate the third stress invariants lode angle (we are using positive sine definition).
Definition: mpm_stress_principal_invariants_utility.h:260
static void CalculateStressInvariants(const Vector &rStress, double &rMeanStressP, double &rDeviatoricQ)
Calculate stress invariants p (volumetric equivalent) and q (deviatoric equivalent).
Definition: mpm_stress_principal_invariants_utility.h:243
static TMatrixType StressVectorToTensor(const TVector &rStressVector)
Transforms a stess vector into a matrix. Stresses are assumed to be stored in the following way: for...
Definition: math_utils.h:1174
static TVector StressTensorToVector(const TMatrixType &rStressTensor, SizeType rSize=0)
Transforms a given symmetric Stress Tensor to Voigt Notation:
Definition: math_utils.h:1399
static double Det(const TMatrixType &rA)
Calculates the determinant of a matrix of a square matrix of any size (no check performed on release ...
Definition: math_utils.h:597
static MatrixType TensorProduct3(const Vector &a, const Vector &b)
Returns a matrix : A = a.tensorproduct.b.
Definition: math_utils.h:959
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
constexpr double Pi
Definition: global_variables.h:25
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
q
Definition: generate_convection_diffusion_explicit_element.py:109
int j
Definition: quadrature.py:648
p
Definition: sensitivityMatrix.py:52
integer i
Definition: TensorModule.f:17