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.
math_utils.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: Pooyan Dadvand
11 // Riccardo Rossi
12 //
13 // Collaborators: Vicente Mataix Ferrandiz
14 // Pablo Becker
15 //
16 
17 #pragma once
18 
19 // System includes
20 #include <cmath>
21 #include <type_traits>
22 
23 // External includes
24 
25 // Project includes
26 #include "input_output/logger.h"
29 
30 namespace Kratos
31 {
32 
35 
39 
43 
47 
51 
60 template<class TDataType = double>
61 class KRATOS_API(KRATOS_CORE) MathUtils
62 {
63 public:
64 
67 
69  using MatrixType = Matrix;
70 
72  using VectorType = Vector;
73 
75  using SizeType = std::size_t;
76 
78  using IndexType = std::size_t;
79 
81  using IndirectArrayType = boost::numeric::ublas::indirect_array<DenseVector<std::size_t>>;
82 
84  static constexpr double ZeroTolerance = std::numeric_limits<double>::epsilon();
85 
89 
93 
97 
102  static inline double GetZeroTolerance()
103  {
104  return ZeroTolerance;
105  }
106 
114  template<bool TCheck>// = false>
115  static inline double Heron(
116  double a,
117  double b,
118  double c
119  )
120  {
121  const double s = 0.5 * (a + b + c);
122  const double A2 = s * (s - a) * (s - b) * (s - c);
123  if constexpr(TCheck) {
124  if(A2 < 0.0) {
125  KRATOS_ERROR << "The square of area is negative, probably the triangle is in bad shape:" << A2 << std::endl;
126  } else {
127  return std::sqrt(A2);
128  }
129  } else {
130  return std::sqrt(std::abs(A2));
131  }
132  }
133 
141  template<class TMatrixType>
142  static double Cofactor(const TMatrixType& rMat, IndexType i, IndexType j)
143  {
144  static_assert(std::is_same<typename TMatrixType::value_type, double>::value, "Bad value type.");
145 
146  KRATOS_ERROR_IF(rMat.size1() != rMat.size2() || rMat.size1() == 0) << "Bad matrix dimensions." << std::endl;
147 
148  if (rMat.size1() == 1)
149  return 1;
150 
151  IndirectArrayType ia1(rMat.size1() - 1), ia2(rMat.size2() - 1);
152 
153  // Construct the submatrix structure for the first minor.
154  unsigned i_sub = 0;
155  for (unsigned k = 0; k < rMat.size1(); ++k)
156  if (k != i)
157  ia1(i_sub++) = k;
158 
159  unsigned j_sub = 0;
160  for (unsigned k = 0; k < rMat.size2(); ++k)
161  if (k != j)
162  ia2(j_sub++) = k;
163 
164  boost::numeric::ublas::matrix_indirect<const TMatrixType, IndirectArrayType> sub_mat(rMat, ia1, ia2);
165  const double first_minor = Det(sub_mat);
166  return ((i + j) % 2) ? -first_minor : first_minor;
167  }
168 
174  template<class TMatrixType>
175  static MatrixType CofactorMatrix(const TMatrixType& rMat)
176  {
177  static_assert(std::is_same<typename TMatrixType::value_type, double>::value, "Bad value type.");
178 
179  MatrixType cofactor_matrix(rMat.size1(), rMat.size2());
180 
181  for (IndexType i = 0; i < rMat.size1(); ++i)
182  for (IndexType j = 0; j < rMat.size2(); ++j)
183  cofactor_matrix(i, j) = Cofactor(rMat, i, j);
184 
185  return cofactor_matrix;
186  }
187 
195  template<SizeType TDim>
196  KRATOS_DEPRECATED_MESSAGE("Please use InvertMatrix() instead")
197  static inline BoundedMatrix<double, TDim, TDim> InvertMatrix(
198  const BoundedMatrix<double, TDim, TDim>& rInputMatrix,
199  double& rInputMatrixDet,
200  const double Tolerance = ZeroTolerance
201  )
202  {
203  BoundedMatrix<double, TDim, TDim> inverted_matrix;
204 
205  /* Compute Determinant of the matrix */
206  rInputMatrixDet = Det(rInputMatrix);
207 
208  if constexpr (TDim == 1) {
209  inverted_matrix(0,0) = 1.0/rInputMatrix(0,0);
210  rInputMatrixDet = rInputMatrix(0,0);
211  } else if constexpr (TDim == 2) {
212  InvertMatrix2(rInputMatrix, inverted_matrix, rInputMatrixDet);
213  } else if constexpr (TDim == 3) {
214  InvertMatrix3(rInputMatrix, inverted_matrix, rInputMatrixDet);
215  } else if constexpr (TDim == 4) {
216  InvertMatrix4(rInputMatrix, inverted_matrix, rInputMatrixDet);
217  } else {
218  KRATOS_ERROR << "Size not implemented. Size: " << TDim << std::endl;
219  }
220 
221  // Checking condition number
222  if (Tolerance > 0.0) { // Check is skipped for negative tolerances
223  CheckConditionNumber(rInputMatrix, inverted_matrix, Tolerance);
224  }
225 
226  return inverted_matrix;
227  }
228 
235  template<class TMatrix1, class TMatrix2>
236  static inline bool CheckConditionNumber(
237  const TMatrix1& rInputMatrix,
238  TMatrix2& rInvertedMatrix,
239  const double Tolerance = std::numeric_limits<double>::epsilon(),
240  const bool ThrowError = true
241  )
242  {
243  // We want at least 4 significant digits
244  const double max_condition_number = (1.0/Tolerance) * 1.0e-4;
245 
246  // Find the condition number to define is inverse is OK
247  const double input_matrix_norm = norm_frobenius(rInputMatrix);
248  const double inverted_matrix_norm = norm_frobenius(rInvertedMatrix);
249 
250  // Now the condition number is the product of both norms
251  const double cond_number = input_matrix_norm * inverted_matrix_norm ;
252  // Finally check if the condition number is low enough
253  if (cond_number > max_condition_number) {
254  if (ThrowError) {
255  KRATOS_WATCH(rInputMatrix);
256  KRATOS_ERROR << " Condition number of the matrix is too high!, cond_number = " << cond_number << std::endl;
257  }
258  return false;
259  }
260 
261  return true;
262  }
263 
273  template<class TMatrix1, class TMatrix2>
275  const TMatrix1& rInputMatrix,
276  TMatrix2& rInvertedMatrix,
277  double& rInputMatrixDet,
278  const double Tolerance = ZeroTolerance
279  )
280  {
281  const SizeType size_1 = rInputMatrix.size1();
282  const SizeType size_2 = rInputMatrix.size2();
283 
284  if (size_1 == size_2) {
285  InvertMatrix(rInputMatrix, rInvertedMatrix, rInputMatrixDet, Tolerance);
286  } else if (size_1 < size_2) { // Right inverse
287  if (rInvertedMatrix.size1() != size_2 || rInvertedMatrix.size2() != size_1) {
288  rInvertedMatrix.resize(size_2, size_1, false);
289  }
290  const Matrix aux = prod(rInputMatrix, trans(rInputMatrix));
291  Matrix auxInv;
292  InvertMatrix(aux, auxInv, rInputMatrixDet, Tolerance);
293  rInputMatrixDet = std::sqrt(rInputMatrixDet);
294  noalias(rInvertedMatrix) = prod(trans(rInputMatrix), auxInv);
295  } else { // Left inverse
296  if (rInvertedMatrix.size1() != size_2 || rInvertedMatrix.size2() != size_1) {
297  rInvertedMatrix.resize(size_2, size_1, false);
298  }
299  const Matrix aux = prod(trans(rInputMatrix), rInputMatrix);
300  Matrix auxInv;
301  InvertMatrix(aux, auxInv, rInputMatrixDet, Tolerance);
302  rInputMatrixDet = std::sqrt(rInputMatrixDet);
303  noalias(rInvertedMatrix) = prod(auxInv, trans(rInputMatrix));
304  }
305  }
306 
313  static void Solve(
314  MatrixType A,
315  VectorType& rX,
316  const VectorType& rB
317  );
318 
327  template<class TMatrix1, class TMatrix2>
328  static void InvertMatrix(
329  const TMatrix1& rInputMatrix,
330  TMatrix2& rInvertedMatrix,
331  double& rInputMatrixDet,
332  const double Tolerance = ZeroTolerance
333  )
334  {
335  KRATOS_DEBUG_ERROR_IF_NOT(rInputMatrix.size1() == rInputMatrix.size2()) << "Matrix provided is non-square" << std::endl;
336 
337  const SizeType size = rInputMatrix.size2();
338 
339  if(size == 1) {
340  if(rInvertedMatrix.size1() != 1 || rInvertedMatrix.size2() != 1) {
341  rInvertedMatrix.resize(1,1,false);
342  }
343  rInvertedMatrix(0,0) = 1.0/rInputMatrix(0,0);
344  rInputMatrixDet = rInputMatrix(0,0);
345  } else if (size == 2) {
346  InvertMatrix2(rInputMatrix, rInvertedMatrix, rInputMatrixDet);
347  } else if (size == 3) {
348  InvertMatrix3(rInputMatrix, rInvertedMatrix, rInputMatrixDet);
349  } else if (size == 4) {
350  InvertMatrix4(rInputMatrix, rInvertedMatrix, rInputMatrixDet);
351  } else if (std::is_same<TMatrix1, Matrix>::value) {
352 
353  const SizeType size1 = rInputMatrix.size1();
354  const SizeType size2 = rInputMatrix.size2();
355  if(rInvertedMatrix.size1() != size1 || rInvertedMatrix.size2() != size2) {
356  rInvertedMatrix.resize(size1, size2,false);
357  }
358 
359  Matrix A(rInputMatrix);
360  typedef permutation_matrix<SizeType> pmatrix;
361  pmatrix pm(A.size1());
362  const int singular = lu_factorize(A,pm);
363  rInvertedMatrix.assign( IdentityMatrix(A.size1()));
364  KRATOS_ERROR_IF(singular == 1) << "Matrix is singular: " << rInputMatrix << std::endl;
365  lu_substitute(A, pm, rInvertedMatrix);
366 
367  // Calculating determinant
368  rInputMatrixDet = 1.0;
369 
370  for (IndexType i = 0; i < size1;++i) {
371  IndexType ki = pm[i] == i ? 0 : 1;
372  rInputMatrixDet *= (ki == 0) ? A(i,i) : -A(i,i);
373  }
374  } else { // Bounded-matrix case
375  const SizeType size1 = rInputMatrix.size1();
376  const SizeType size2 = rInputMatrix.size2();
377 
378  Matrix A(rInputMatrix);
379  Matrix invA(rInvertedMatrix);
380 
381  typedef permutation_matrix<SizeType> pmatrix;
382  pmatrix pm(size1);
383  const int singular = lu_factorize(A,pm);
384  invA.assign( IdentityMatrix(size1));
385  KRATOS_ERROR_IF(singular == 1) << "Matrix is singular: " << rInputMatrix << std::endl;
386  lu_substitute(A, pm, invA);
387 
388  // Calculating determinant
389  rInputMatrixDet = 1.0;
390 
391  for (IndexType i = 0; i < size1;++i) {
392  IndexType ki = pm[i] == i ? 0 : 1;
393  rInputMatrixDet *= (ki == 0) ? A(i,i) : -A(i,i);
394  }
395 
396  for (IndexType i = 0; i < size1;++i) {
397  for (IndexType j = 0; j < size2;++j) {
398  rInvertedMatrix(i,j) = invA(i,j);
399  }
400  }
401  }
402 
403  // Checking condition number
404  if (Tolerance > 0.0) { // Check is skipped for negative tolerances
405  CheckConditionNumber(rInputMatrix, rInvertedMatrix, Tolerance);
406  }
407  }
408 
415  template<class TMatrix1, class TMatrix2>
416  static void InvertMatrix2(
417  const TMatrix1& rInputMatrix,
418  TMatrix2& rInvertedMatrix,
419  double& rInputMatrixDet
420  )
421  {
422  KRATOS_TRY;
423 
424  KRATOS_DEBUG_ERROR_IF_NOT(rInputMatrix.size1() == rInputMatrix.size2()) << "Matrix provided is non-square" << std::endl;
425 
426  if(rInvertedMatrix.size1() != 2 || rInvertedMatrix.size2() != 2) {
427  rInvertedMatrix.resize(2,2,false);
428  }
429 
430  rInputMatrixDet = rInputMatrix(0,0)*rInputMatrix(1,1)-rInputMatrix(0,1)*rInputMatrix(1,0);
431 
432  rInvertedMatrix(0,0) = rInputMatrix(1,1);
433  rInvertedMatrix(0,1) = -rInputMatrix(0,1);
434  rInvertedMatrix(1,0) = -rInputMatrix(1,0);
435  rInvertedMatrix(1,1) = rInputMatrix(0,0);
436 
437  rInvertedMatrix/=rInputMatrixDet;
438 
439  KRATOS_CATCH("");
440  }
441 
448  template<class TMatrix1, class TMatrix2>
449  static void InvertMatrix3(
450  const TMatrix1& rInputMatrix,
451  TMatrix2& rInvertedMatrix,
452  double& rInputMatrixDet
453  )
454  {
455  KRATOS_TRY;
456 
457  KRATOS_DEBUG_ERROR_IF_NOT(rInputMatrix.size1() == rInputMatrix.size2()) << "Matrix provided is non-square" << std::endl;
458 
459  if(rInvertedMatrix.size1() != 3 || rInvertedMatrix.size2() != 3) {
460  rInvertedMatrix.resize(3,3,false);
461  }
462 
463  // Filling the inverted matrix with the algebraic complements
464  // First column
465  rInvertedMatrix(0,0) = rInputMatrix(1,1)*rInputMatrix(2,2) - rInputMatrix(1,2)*rInputMatrix(2,1);
466  rInvertedMatrix(1,0) = -rInputMatrix(1,0)*rInputMatrix(2,2) + rInputMatrix(1,2)*rInputMatrix(2,0);
467  rInvertedMatrix(2,0) = rInputMatrix(1,0)*rInputMatrix(2,1) - rInputMatrix(1,1)*rInputMatrix(2,0);
468 
469  // Second column
470  rInvertedMatrix(0,1) = -rInputMatrix(0,1)*rInputMatrix(2,2) + rInputMatrix(0,2)*rInputMatrix(2,1);
471  rInvertedMatrix(1,1) = rInputMatrix(0,0)*rInputMatrix(2,2) - rInputMatrix(0,2)*rInputMatrix(2,0);
472  rInvertedMatrix(2,1) = -rInputMatrix(0,0)*rInputMatrix(2,1) + rInputMatrix(0,1)*rInputMatrix(2,0);
473 
474  // Third column
475  rInvertedMatrix(0,2) = rInputMatrix(0,1)*rInputMatrix(1,2) - rInputMatrix(0,2)*rInputMatrix(1,1);
476  rInvertedMatrix(1,2) = -rInputMatrix(0,0)*rInputMatrix(1,2) + rInputMatrix(0,2)*rInputMatrix(1,0);
477  rInvertedMatrix(2,2) = rInputMatrix(0,0)*rInputMatrix(1,1) - rInputMatrix(0,1)*rInputMatrix(1,0);
478 
479  // Calculation of determinant (of the input matrix)
480  rInputMatrixDet = rInputMatrix(0,0)*rInvertedMatrix(0,0) + rInputMatrix(0,1)*rInvertedMatrix(1,0) + rInputMatrix(0,2)*rInvertedMatrix(2,0);
481 
482  // Finalizing the calculation of the inverted matrix
483  rInvertedMatrix /= rInputMatrixDet;
484 
485  KRATOS_CATCH("")
486  }
487 
494  template<class TMatrix1, class TMatrix2>
495  static void InvertMatrix4(
496  const TMatrix1& rInputMatrix,
497  TMatrix2& rInvertedMatrix,
498  double& rInputMatrixDet
499  )
500  {
501  KRATOS_TRY;
502 
503  KRATOS_DEBUG_ERROR_IF_NOT(rInputMatrix.size1() == rInputMatrix.size2()) << "Matrix provided is non-square" << std::endl;
504 
505  if (rInvertedMatrix.size1() != 4 || rInvertedMatrix.size2() != 4) {
506  rInvertedMatrix.resize(4, 4, false);
507  }
508 
509  /* Compute inverse of the Matrix */
510  // First column
511  rInvertedMatrix(0, 0) = -(rInputMatrix(1, 3) * rInputMatrix(2, 2) * rInputMatrix(3, 1)) + rInputMatrix(1, 2) * rInputMatrix(2, 3) * rInputMatrix(3, 1) + rInputMatrix(1, 3) * rInputMatrix(2, 1) * rInputMatrix(3, 2) - rInputMatrix(1, 1) * rInputMatrix(2, 3) * rInputMatrix(3, 2) - rInputMatrix(1, 2) * rInputMatrix(2, 1) * rInputMatrix(3, 3) + rInputMatrix(1, 1) * rInputMatrix(2, 2) * rInputMatrix(3, 3);
512  rInvertedMatrix(0, 1) = rInputMatrix(0, 3) * rInputMatrix(2, 2) * rInputMatrix(3, 1) - rInputMatrix(0, 2) * rInputMatrix(2, 3) * rInputMatrix(3, 1) - rInputMatrix(0, 3) * rInputMatrix(2, 1) * rInputMatrix(3, 2) + rInputMatrix(0, 1) * rInputMatrix(2, 3) * rInputMatrix(3, 2) + rInputMatrix(0, 2) * rInputMatrix(2, 1) * rInputMatrix(3, 3) - rInputMatrix(0, 1) * rInputMatrix(2, 2) * rInputMatrix(3, 3);
513  rInvertedMatrix(0, 2) = -(rInputMatrix(0, 3) * rInputMatrix(1, 2) * rInputMatrix(3, 1)) + rInputMatrix(0, 2) * rInputMatrix(1, 3) * rInputMatrix(3, 1) + rInputMatrix(0, 3) * rInputMatrix(1, 1) * rInputMatrix(3, 2) - rInputMatrix(0, 1) * rInputMatrix(1, 3) * rInputMatrix(3, 2) - rInputMatrix(0, 2) * rInputMatrix(1, 1) * rInputMatrix(3, 3) + rInputMatrix(0, 1) * rInputMatrix(1, 2) * rInputMatrix(3, 3);
514  rInvertedMatrix(0, 3) = rInputMatrix(0, 3) * rInputMatrix(1, 2) * rInputMatrix(2, 1) - rInputMatrix(0, 2) * rInputMatrix(1, 3) * rInputMatrix(2, 1) - rInputMatrix(0, 3) * rInputMatrix(1, 1) * rInputMatrix(2, 2) + rInputMatrix(0, 1) * rInputMatrix(1, 3) * rInputMatrix(2, 2) + rInputMatrix(0, 2) * rInputMatrix(1, 1) * rInputMatrix(2, 3) - rInputMatrix(0, 1) * rInputMatrix(1, 2) * rInputMatrix(2, 3);
515 
516  // Second column
517  rInvertedMatrix(1, 0) = rInputMatrix(1, 3) * rInputMatrix(2, 2) * rInputMatrix(3, 0) - rInputMatrix(1, 2) * rInputMatrix(2, 3) * rInputMatrix(3, 0) - rInputMatrix(1, 3) * rInputMatrix(2, 0) * rInputMatrix(3, 2) + rInputMatrix(1, 0) * rInputMatrix(2, 3) * rInputMatrix(3, 2) + rInputMatrix(1, 2) * rInputMatrix(2, 0) * rInputMatrix(3, 3) - rInputMatrix(1, 0) * rInputMatrix(2, 2) * rInputMatrix(3, 3);
518  rInvertedMatrix(1, 1) = -(rInputMatrix(0, 3) * rInputMatrix(2, 2) * rInputMatrix(3, 0)) + rInputMatrix(0, 2) * rInputMatrix(2, 3) * rInputMatrix(3, 0) + rInputMatrix(0, 3) * rInputMatrix(2, 0) * rInputMatrix(3, 2) - rInputMatrix(0, 0) * rInputMatrix(2, 3) * rInputMatrix(3, 2) - rInputMatrix(0, 2) * rInputMatrix(2, 0) * rInputMatrix(3, 3) + rInputMatrix(0, 0) * rInputMatrix(2, 2) * rInputMatrix(3, 3);
519  rInvertedMatrix(1, 2) = rInputMatrix(0, 3) * rInputMatrix(1, 2) * rInputMatrix(3, 0) - rInputMatrix(0, 2) * rInputMatrix(1, 3) * rInputMatrix(3, 0) - rInputMatrix(0, 3) * rInputMatrix(1, 0) * rInputMatrix(3, 2) + rInputMatrix(0, 0) * rInputMatrix(1, 3) * rInputMatrix(3, 2) + rInputMatrix(0, 2) * rInputMatrix(1, 0) * rInputMatrix(3, 3) - rInputMatrix(0, 0) * rInputMatrix(1, 2) * rInputMatrix(3, 3);
520  rInvertedMatrix(1, 3) = -(rInputMatrix(0, 3) * rInputMatrix(1, 2) * rInputMatrix(2, 0)) + rInputMatrix(0, 2) * rInputMatrix(1, 3) * rInputMatrix(2, 0) + rInputMatrix(0, 3) * rInputMatrix(1, 0) * rInputMatrix(2, 2) - rInputMatrix(0, 0) * rInputMatrix(1, 3) * rInputMatrix(2, 2) - rInputMatrix(0, 2) * rInputMatrix(1, 0) * rInputMatrix(2, 3) + rInputMatrix(0, 0) * rInputMatrix(1, 2) * rInputMatrix(2, 3);
521 
522  // Third column
523  rInvertedMatrix(2, 0) = -(rInputMatrix(1, 3) * rInputMatrix(2, 1) * rInputMatrix(3, 0)) + rInputMatrix(1, 1) * rInputMatrix(2, 3) * rInputMatrix(3, 0) + rInputMatrix(1, 3) * rInputMatrix(2, 0) * rInputMatrix(3, 1) - rInputMatrix(1, 0) * rInputMatrix(2, 3) * rInputMatrix(3, 1) - rInputMatrix(1, 1) * rInputMatrix(2, 0) * rInputMatrix(3, 3) + rInputMatrix(1, 0) * rInputMatrix(2, 1) * rInputMatrix(3, 3);
524  rInvertedMatrix(2, 1) = rInputMatrix(0, 3) * rInputMatrix(2, 1) * rInputMatrix(3, 0) - rInputMatrix(0, 1) * rInputMatrix(2, 3) * rInputMatrix(3, 0) - rInputMatrix(0, 3) * rInputMatrix(2, 0) * rInputMatrix(3, 1) + rInputMatrix(0, 0) * rInputMatrix(2, 3) * rInputMatrix(3, 1) + rInputMatrix(0, 1) * rInputMatrix(2, 0) * rInputMatrix(3, 3) - rInputMatrix(0, 0) * rInputMatrix(2, 1) * rInputMatrix(3, 3);
525  rInvertedMatrix(2, 2) = -(rInputMatrix(0, 3) * rInputMatrix(1, 1) * rInputMatrix(3, 0)) + rInputMatrix(0, 1) * rInputMatrix(1, 3) * rInputMatrix(3, 0) + rInputMatrix(0, 3) * rInputMatrix(1, 0) * rInputMatrix(3, 1) - rInputMatrix(0, 0) * rInputMatrix(1, 3) * rInputMatrix(3, 1) - rInputMatrix(0, 1) * rInputMatrix(1, 0) * rInputMatrix(3, 3) + rInputMatrix(0, 0) * rInputMatrix(1, 1) * rInputMatrix(3, 3);
526  rInvertedMatrix(2, 3) = rInputMatrix(0, 3) * rInputMatrix(1, 1) * rInputMatrix(2, 0) - rInputMatrix(0, 1) * rInputMatrix(1, 3) * rInputMatrix(2, 0) - rInputMatrix(0, 3) * rInputMatrix(1, 0) * rInputMatrix(2, 1) + rInputMatrix(0, 0) * rInputMatrix(1, 3) * rInputMatrix(2, 1) + rInputMatrix(0, 1) * rInputMatrix(1, 0) * rInputMatrix(2, 3) - rInputMatrix(0, 0) * rInputMatrix(1, 1) * rInputMatrix(2, 3);
527 
528  // Fourth column
529  rInvertedMatrix(3, 0) = rInputMatrix(1, 2) * rInputMatrix(2, 1) * rInputMatrix(3, 0) - rInputMatrix(1, 1) * rInputMatrix(2, 2) * rInputMatrix(3, 0) - rInputMatrix(1, 2) * rInputMatrix(2, 0) * rInputMatrix(3, 1) + rInputMatrix(1, 0) * rInputMatrix(2, 2) * rInputMatrix(3, 1) + rInputMatrix(1, 1) * rInputMatrix(2, 0) * rInputMatrix(3, 2) - rInputMatrix(1, 0) * rInputMatrix(2, 1) * rInputMatrix(3, 2);
530  rInvertedMatrix(3, 1) = -(rInputMatrix(0, 2) * rInputMatrix(2, 1) * rInputMatrix(3, 0)) + rInputMatrix(0, 1) * rInputMatrix(2, 2) * rInputMatrix(3, 0) + rInputMatrix(0, 2) * rInputMatrix(2, 0) * rInputMatrix(3, 1) - rInputMatrix(0, 0) * rInputMatrix(2, 2) * rInputMatrix(3, 1) - rInputMatrix(0, 1) * rInputMatrix(2, 0) * rInputMatrix(3, 2) + rInputMatrix(0, 0) * rInputMatrix(2, 1) * rInputMatrix(3, 2);
531  rInvertedMatrix(3, 2) = rInputMatrix(0, 2) * rInputMatrix(1, 1) * rInputMatrix(3, 0) - rInputMatrix(0, 1) * rInputMatrix(1, 2) * rInputMatrix(3, 0) - rInputMatrix(0, 2) * rInputMatrix(1, 0) * rInputMatrix(3, 1) + rInputMatrix(0, 0) * rInputMatrix(1, 2) * rInputMatrix(3, 1) + rInputMatrix(0, 1) * rInputMatrix(1, 0) * rInputMatrix(3, 2) - rInputMatrix(0, 0) * rInputMatrix(1, 1) * rInputMatrix(3, 2);
532  rInvertedMatrix(3, 3) = -(rInputMatrix(0, 2) * rInputMatrix(1, 1) * rInputMatrix(2, 0)) + rInputMatrix(0, 1) * rInputMatrix(1, 2) * rInputMatrix(2, 0) + rInputMatrix(0, 2) * rInputMatrix(1, 0) * rInputMatrix(2, 1) - rInputMatrix(0, 0) * rInputMatrix(1, 2) * rInputMatrix(2, 1) - rInputMatrix(0, 1) * rInputMatrix(1, 0) * rInputMatrix(2, 2) + rInputMatrix(0, 0) * rInputMatrix(1, 1) * rInputMatrix(2, 2);
533 
534  // Calculation of determinant (of the input matrix)
535  rInputMatrixDet = rInputMatrix(0, 1) * rInputMatrix(1, 3) * rInputMatrix(2, 2) * rInputMatrix(3, 0) - rInputMatrix(0, 1) * rInputMatrix(1, 2) * rInputMatrix(2, 3) * rInputMatrix(3, 0) - rInputMatrix(0, 0) * rInputMatrix(1, 3) * rInputMatrix(2, 2) * rInputMatrix(3, 1) + rInputMatrix(0, 0) * rInputMatrix(1, 2) * rInputMatrix(2, 3) * rInputMatrix(3, 1) - rInputMatrix(0, 1) * rInputMatrix(1, 3) * rInputMatrix(2, 0) * rInputMatrix(3, 2) + rInputMatrix(0, 0) * rInputMatrix(1, 3) * rInputMatrix(2, 1) * rInputMatrix(3, 2) + rInputMatrix(0, 1) * rInputMatrix(1, 0) * rInputMatrix(2, 3) * rInputMatrix(3, 2) - rInputMatrix(0, 0) * rInputMatrix(1, 1) * rInputMatrix(2, 3) * rInputMatrix(3, 2) + rInputMatrix(0, 3) * (rInputMatrix(1, 2) * rInputMatrix(2, 1) * rInputMatrix(3, 0) - rInputMatrix(1, 1) * rInputMatrix(2, 2) * rInputMatrix(3, 0) - rInputMatrix(1, 2) * rInputMatrix(2, 0) * rInputMatrix(3, 1) + rInputMatrix(1, 0) * rInputMatrix(2, 2) * rInputMatrix(3, 1) + rInputMatrix(1, 1) * rInputMatrix(2, 0) * rInputMatrix(3, 2) - rInputMatrix(1, 0) * rInputMatrix(2, 1) * rInputMatrix(3, 2)) + (rInputMatrix(0, 1) * rInputMatrix(1, 2) * rInputMatrix(2, 0) - rInputMatrix(0, 0) * rInputMatrix(1, 2) * rInputMatrix(2, 1) - rInputMatrix(0, 1) * rInputMatrix(1, 0) * rInputMatrix(2, 2) + rInputMatrix(0, 0) * rInputMatrix(1, 1) * rInputMatrix(2, 2)) * rInputMatrix(3, 3) + rInputMatrix(0, 2) * (-(rInputMatrix(1, 3) * rInputMatrix(2, 1) * rInputMatrix(3, 0)) + rInputMatrix(1, 1) * rInputMatrix(2, 3) * rInputMatrix(3, 0) + rInputMatrix(1, 3) * rInputMatrix(2, 0) * rInputMatrix(3, 1) - rInputMatrix(1, 0) * rInputMatrix(2, 3) * rInputMatrix(3, 1) - rInputMatrix(1, 1) * rInputMatrix(2, 0) * rInputMatrix(3, 3) + rInputMatrix(1, 0) * rInputMatrix(2, 1) * rInputMatrix(3, 3));
536 
537  // Finalizing the calculation of the inverted matrix
538  rInvertedMatrix /= rInputMatrixDet;
539 
540  KRATOS_CATCH("");
541  }
542 
548  template<class TMatrixType>
549  static inline double Det2(const TMatrixType& rA)
550  {
551  KRATOS_DEBUG_ERROR_IF_NOT(rA.size1() == rA.size2()) << "Matrix provided is non-square" << std::endl;
552 
553  return (rA(0,0)*rA(1,1)-rA(0,1)*rA(1,0));
554  }
555 
561  template<class TMatrixType>
562  static inline double Det3(const TMatrixType& rA)
563  {
564  KRATOS_DEBUG_ERROR_IF_NOT(rA.size1() == rA.size2()) << "Matrix provided is non-square" << std::endl;
565 
566  // Calculating the algebraic complements to the first line
567  const double a = rA(1,1)*rA(2,2) - rA(1,2)*rA(2,1);
568  const double b = rA(1,0)*rA(2,2) - rA(1,2)*rA(2,0);
569  const double c = rA(1,0)*rA(2,1) - rA(1,1)*rA(2,0);
570 
571  return rA(0,0)*a - rA(0,1)*b + rA(0,2)*c;
572  }
573 
579  template<class TMatrixType>
580  static inline double Det4(const TMatrixType& rA)
581  {
582  KRATOS_DEBUG_ERROR_IF_NOT(rA.size1() == rA.size2()) << "Matrix provided is non-square" << std::endl;
583 
584  const double det = rA(0,1)*rA(1,3)*rA(2,2)*rA(3,0)-rA(0,1)*rA(1,2)*rA(2,3)*rA(3,0)-rA(0,0)*rA(1,3)*rA(2,2)*rA(3,1)+rA(0,0)*rA(1,2)*rA(2,3)*rA(3,1)
585  -rA(0,1)*rA(1,3)*rA(2,0)*rA(3,2)+rA(0,0)*rA(1,3)*rA(2,1)*rA(3,2)+rA(0,1)*rA(1,0)*rA(2,3)*rA(3,2)-rA(0,0)*rA(1,1)*rA(2,3)*rA(3,2)+rA(0,3)*(rA(1,2)*rA(2,1)*rA(3,0)-rA(1,1)*rA(2,2)*rA(3,0)-rA(1,2)*rA(2,0)*rA(3,1)+rA(1,0)*rA(2,2)*rA(3,1)+rA(1,1)*rA(2,0)*rA(3,2)
586  -rA(1,0)*rA(2,1)*rA(3,2))+(rA(0,1)*rA(1,2)*rA(2,0)-rA(0,0)*rA(1,2)*rA(2,1)-rA(0,1)*rA(1,0)*rA(2,2)+rA(0,0)*rA(1,1)*rA(2,2))*rA(3,3)+rA(0,2)*(-(rA(1,3)*rA(2,1)*rA(3,0))+rA(1,1)*rA(2,3)*rA(3,0)+rA(1,3)*rA(2,0)*rA(3,1)-rA(1,0)*rA(2,3)*rA(3,1)-rA(1,1)*rA(2,0)*rA(3,3)+rA(1,0)*rA(2,1)*rA(3,3));
587  return det;
588  }
589 
590 public:
596  template<class TMatrixType>
597  static inline double Det(const TMatrixType& rA)
598  {
599  KRATOS_DEBUG_ERROR_IF_NOT(rA.size1() == rA.size2()) << "Matrix provided is non-square" << std::endl;
600 
601  switch (rA.size1()) {
602  case 2:
603  return Det2(rA);
604  case 3:
605  return Det3(rA);
606  case 4:
607  return Det4(rA);
608  default:
609  double det = 1.0;
610  using namespace boost::numeric::ublas;
611  typedef permutation_matrix<SizeType> pmatrix;
612  Matrix Aux(rA);
613  pmatrix pm(Aux.size1());
614  bool singular = lu_factorize(Aux,pm);
615 
616  if (singular) {
617  return 0.0;
618  }
619 
620  for (IndexType i = 0; i < Aux.size1();++i) {
621  IndexType ki = pm[i] == i ? 0 : 1;
622  det *= std::pow(-1.0, ki) * Aux(i,i);
623  }
624  return det;
625  }
626  }
627 
633  template<class TMatrixType>
634  static inline double GeneralizedDet(const TMatrixType& rA)
635  {
636  if (rA.size1() == rA.size2()) {
637  return Det(rA);
638  } else if (rA.size1() < rA.size2()) { // Right determinant
639  const Matrix AAT = prod( rA, trans(rA) );
640  return std::sqrt(Det(AAT));
641  } else { // Left determinant
642  const Matrix ATA = prod( trans(rA), rA );
643  return std::sqrt(Det(ATA));
644  }
645  }
646 
654  static inline double Dot3(
655  const Vector& a,
656  const Vector& b
657  )
658  {
659  return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
660  }
661 
669  static inline double Dot(
670  const Vector& rFirstVector,
671  const Vector& rSecondVector
672  )
673  {
674  Vector::const_iterator i = rFirstVector.begin();
675  Vector::const_iterator j = rSecondVector.begin();
676  double temp = 0.0;
677  while(i != rFirstVector.end()) {
678  temp += *i++ * *j++;
679  }
680  return temp;
681  //return std::inner_product(rFirstVector.begin(), rFirstVector.end(), rSecondVector.begin(), 0.0);
682  }
683 
690  template<class TVectorType>
691  static inline double Norm3(const TVectorType& a)
692  {
693  double temp = std::pow(a[0],2) + std::pow(a[1],2) + std::pow(a[2],2);
694  temp = std::sqrt(temp);
695  return temp;
696  }
697 
703  static inline double Norm(const Vector& a)
704  {
705  Vector::const_iterator i = a.begin();
706  double temp = 0.0;
707  while(i != a.end()) {
708  temp += (*i) * (*i);
709  i++;
710  }
711  return std::sqrt(temp);
712  }
713 
720  static inline double StableNorm(const Vector& a)
721  {
722  if (a.size() == 0) {
723  return 0;
724  }
725 
726  if (a.size() == 1) {
727  return a[0];
728  }
729 
730  double scale {0};
731 
732  double sqr_sum_scaled {1};
733 
734  for (auto it = a.begin(); it != a.end(); ++it) {
735  double x = *it;
736 
737  if (x != 0) {
738  const double abs_x = std::abs(x);
739 
740  if (scale < abs_x) {
741  const double f = scale / abs_x;
742  sqr_sum_scaled = sqr_sum_scaled * (f * f) + 1.0;
743  scale = abs_x;
744  } else {
745  x = abs_x / scale;
746  sqr_sum_scaled += x * x;
747  }
748  }
749  }
750 
751  return scale * std::sqrt(sqr_sum_scaled);
752  }
753 
761  template<class T>
762  static inline T CrossProduct(
763  const T& a,
764  const T& b
765  )
766  {
767  T c(a);
768 
769  c[0] = a[1]*b[2] - a[2]*b[1];
770  c[1] = a[2]*b[0] - a[0]*b[2];
771  c[2] = a[0]*b[1] - a[1]*b[0];
772 
773  return c;
774  }
775 
781  template< class T1, class T2>
782  static inline typename std::enable_if<std::is_same<T1, T2>::value, bool>::type CheckIsAlias(T1& value1, T2& value2)
783  {
784  return value1 == value2;
785  }
786 
792  template< class T1, class T2>
793  static inline typename std::enable_if<!std::is_same<T1, T2>::value, bool>::type CheckIsAlias(T1& value1, T2& value2)
794  {
795  return false;
796  }
797 
805  template< class T1, class T2 , class T3>
806  static inline void CrossProduct(T1& c, const T2& a, const T3& b ){
807  if (c.size() != 3) c.resize(3);
808 
809  KRATOS_DEBUG_ERROR_IF(a.size() != 3 || b.size() != 3 || c.size() != 3)
810  << "The size of the vectors is different of 3: "
811  << a << ", " << b << " and " << c << std::endl;
812  KRATOS_DEBUG_ERROR_IF(CheckIsAlias(c, a))
813  << "Aliasing between the output parameter and the first "
814  << "input parameter" << std::endl;
815  KRATOS_DEBUG_ERROR_IF(CheckIsAlias(c, b)) << "Aliasing between "
816  << "the output parameter and the second input parameter" << std::endl;
817 
818  c[0] = a[1]*b[2] - a[2]*b[1];
819  c[1] = a[2]*b[0] - a[0]*b[2];
820  c[2] = a[0]*b[1] - a[1]*b[0];
821  }
822 
830  template< class T1, class T2 , class T3>
831  static inline void UnitCrossProduct(T1& c, const T2& a, const T3& b ){
832  CrossProduct(c,a,b);
833  const double norm = norm_2(c);
834  KRATOS_DEBUG_ERROR_IF(norm < 1000.0*ZeroTolerance)
835  << "norm is 0 when making the UnitCrossProduct of the vectors "
836  << a << " and " << b << std::endl;
837  c/=norm;
838  }
839 
847  template< class T1, class T2 , class T3>
848  static inline void OrthonormalBasis(const T1& c,T2& a,T3& b, const IndexType Type = 0 ){
849  if (Type == 0)
850  OrthonormalBasisHughesMoeller(c,a,b);
851  else if (Type == 1)
852  OrthonormalBasisFrisvad(c,a,b);
853  else
854  OrthonormalBasisNaive(c,a,b);
855  }
856 
864  template< class T1, class T2 , class T3>
865  static inline void OrthonormalBasisHughesMoeller(const T1& c,T2& a,T3& b ){
866  KRATOS_DEBUG_ERROR_IF(norm_2(c) < (1.0 - 1.0e-6) || norm_2(c) > (1.0 + 1.0e-6)) << "Input should be a normal vector" << std::endl;
867  // Choose a vector orthogonal to n as the direction of b2.
868  if(std::abs(c[0]) > std::abs(c[2])) {
869  b[0] = c[1];
870  b[1] = -c[0];
871  b[2] = 0.0;
872  } else {
873  b[0] = 0.0;
874  b[1] = c[2];
875  b[2] = -c[1];
876  }
877  b /= norm_2(b); // Normalize b
878  UnitCrossProduct(a, b , c); // Construct a using a cross product
879  }
880 
888  template< class T1, class T2 , class T3>
889  static inline void OrthonormalBasisFrisvad(const T1& c,T2& a,T3& b ){
890  KRATOS_DEBUG_ERROR_IF(norm_2(c) < (1.0 - 1.0e-3) || norm_2(c) > (1.0 + 1.0e-3)) << "Input should be a normal vector" << std::endl;
891  if ((c[2] + 1.0) > 1.0e4 * ZeroTolerance) {
892  a[0] = 1.0 - std::pow(c[0], 2)/(1.0 + c[2]);
893  a[1] = - (c[0] * c[1])/(1.0 + c[2]);
894  a[2] = - c[0];
895  const double norm_a = norm_2(a);
896  a /= norm_a;
897  b[0] = - (c[0] * c[1])/(1.0 + c[2]);
898  b[1] = 1.0 - std::pow(c[1], 2)/(1.0 + c[2]);
899  b[2] = -c[1];
900  const double norm_b = norm_2(b);
901  b /= norm_b;
902  } else { // In case that the vector is in negative Z direction
903  a[0] = 1.0;
904  a[1] = 0.0;
905  a[2] = 0.0;
906  b[0] = 0.0;
907  b[1] = -1.0;
908  b[2] = 0.0;
909  }
910  }
911 
919  template< class T1, class T2 , class T3>
920  static inline void OrthonormalBasisNaive(const T1& c,T2& a,T3& b ){
921  KRATOS_DEBUG_ERROR_IF(norm_2(c) < (1.0 - 1.0e-3) || norm_2(c) > (1.0 + 1.0e-3)) << "Input should be a normal vector" << std::endl;
922  // If c is near the x-axis , use the y-axis. Otherwise use the x-axis.
923  if(c[0] > 0.9f) {
924  a[0] = 0.0;
925  a[1] = 1.0;
926  a[2] = 0.0;
927  } else {
928  a[0] = 1.0;
929  a[1] = 0.0;
930  a[2] = 0.0;
931  }
932  a -= c * inner_prod(a, c); // Make a orthogonal to c
933  a /= norm_2(a); // Normalize a
934  UnitCrossProduct(b, c, a); // Construct b using a cross product
935  }
936 
942  template< class T1, class T2>
943  static inline double VectorsAngle(const T1& rV1, const T2& rV2 ){
944  const T1 aux_1 = rV1 * norm_2(rV2);
945  const T2 aux_2 = norm_2(rV1) * rV2;
946  const double num = norm_2(aux_1 - aux_2);
947  const double denom = norm_2(aux_1 + aux_2);
948  return 2.0 * std::atan2( num , denom);
949  }
950 
959  static inline MatrixType TensorProduct3(
960  const Vector& a,
961  const Vector& b
962  )
963  {
964  MatrixType A(3,3);
965 
966  A(0,0) = a[0]*b[0];
967  A(0,1) = a[0]*b[1];
968  A(0,2) = a[0]*b[2];
969  A(1,0) = a[1]*b[0];
970  A(1,1) = a[1]*b[1];
971  A(1,2) = a[1]*b[2];
972  A(2,0) = a[2]*b[0];
973  A(2,1) = a[2]*b[1];
974  A(2,2) = a[2]*b[2];
975 
976  return A;
977  }
978 
987  template<class TMatrixType1, class TMatrixType2>
988  static inline void AddMatrix(
989  TMatrixType1& rDestination,
990  const TMatrixType2& rInputMatrix,
991  const IndexType InitialRow,
992  const IndexType InitialCol
993  )
994  {
995  KRATOS_TRY
996 
997  for(IndexType i = 0; i < rInputMatrix.size1(); ++i) {
998  for(IndexType j = 0; j < rInputMatrix.size2(); ++j) {
999  rDestination(InitialRow+i, InitialCol+j) += rInputMatrix(i,j);
1000  }
1001  }
1002  KRATOS_CATCH("")
1003  }
1004 
1012  template<class TVectorType1, class TVectorType2>
1013  static inline void AddVector(
1014  TVectorType1& rDestination,
1015  const TVectorType2& rInputVector,
1016  const IndexType InitialIndex
1017  )
1018  {
1019  KRATOS_TRY
1020 
1021  for(IndexType i = 0; i < rInputVector.size(); ++i) {
1022  rDestination[InitialIndex+i] += rInputVector[i];
1023  }
1024  KRATOS_CATCH("")
1025  }
1026 
1035  static inline void SubtractMatrix(
1036  MatrixType& rDestination,
1037  const MatrixType& rInputMatrix,
1038  const IndexType InitialRow,
1039  const IndexType InitialCol
1040  )
1041  {
1042  KRATOS_TRY;
1043 
1044  for(IndexType i = 0; i<rInputMatrix.size1(); ++i) {
1045  for(IndexType j = 0; j<rInputMatrix.size2(); ++j) {
1046  rDestination(InitialRow+i, InitialCol+j) -= rInputMatrix(i,j);
1047  }
1048  }
1049 
1050  KRATOS_CATCH("");
1051  }
1052 
1062  static inline void WriteMatrix(
1063  MatrixType& rDestination,
1064  const MatrixType& rInputMatrix,
1065  const IndexType InitialRow,
1066  const IndexType InitialCol
1067  )
1068  {
1069  KRATOS_TRY;
1070 
1071  for(IndexType i = 0; i < rInputMatrix.size1(); ++i) {
1072  for(IndexType j = 0; j < rInputMatrix.size2(); ++j) {
1073  rDestination(InitialRow+i, InitialCol+j) = rInputMatrix(i,j);
1074  }
1075  }
1076 
1077  KRATOS_CATCH("");
1078  }
1079 
1086  static inline void ExpandReducedMatrix(
1087  MatrixType& rDestination,
1088  const MatrixType& rReducedMatrix,
1089  const SizeType Dimension
1090  )
1091  {
1092  KRATOS_TRY;
1093 
1094  const SizeType size = rReducedMatrix.size2();
1095  IndexType rowindex = 0;
1096  IndexType colindex = 0;
1097 
1098  for (IndexType i = 0; i < size; ++i) {
1099  rowindex = i * Dimension;
1100  for (IndexType j = 0; j < size; ++j) {
1101  colindex = j * Dimension;
1102  for(IndexType ii = 0; ii < Dimension; ++ii) {
1103  rDestination(rowindex+ii, colindex+ii) = rReducedMatrix(i, j);
1104  }
1105  }
1106  }
1107 
1108  KRATOS_CATCH("");
1109  }
1110 
1117  static inline void ExpandAndAddReducedMatrix(
1118  MatrixType& rDestination,
1119  const MatrixType& rReducedMatrix,
1120  const SizeType Dimension
1121  )
1122  {
1123  KRATOS_TRY;
1124 
1125  const SizeType size = rReducedMatrix.size2();
1126  IndexType rowindex = 0;
1127  IndexType colindex = 0;
1128 
1129  for (IndexType i = 0; i < size; ++i) {
1130  rowindex = i * Dimension;
1131  for (IndexType j = 0; j < size; ++j) {
1132  colindex = j * Dimension;
1133  for(IndexType ii = 0; ii < Dimension; ++ii) {
1134  rDestination(rowindex+ii, colindex+ii) += rReducedMatrix(i, j);
1135  }
1136  }
1137  }
1138 
1139  KRATOS_CATCH("");
1140  }
1141 
1148  static inline void VecAdd(
1149  Vector& rX,
1150  const double coeff,
1151  Vector& rY
1152  )
1153  {
1154  KRATOS_TRY
1155  SizeType size=rX.size();
1156 
1157  for (IndexType i=0; i<size; ++i) {
1158  rX[i] += coeff * rY[i];
1159  }
1160  KRATOS_CATCH("")
1161  }
1162 
1173  template<class TVector, class TMatrixType = MatrixType>
1174  static inline TMatrixType StressVectorToTensor(const TVector& rStressVector)
1175  {
1176  KRATOS_TRY;
1177 
1178  const SizeType matrix_size = rStressVector.size() == 3 ? 2 : 3;
1179  TMatrixType stress_tensor(matrix_size, matrix_size);
1180 
1181  if (rStressVector.size()==3) {
1182  stress_tensor(0,0) = rStressVector[0];
1183  stress_tensor(0,1) = rStressVector[2];
1184  stress_tensor(1,0) = rStressVector[2];
1185  stress_tensor(1,1) = rStressVector[1];
1186  } else if (rStressVector.size()==4) {
1187  stress_tensor(0,0) = rStressVector[0];
1188  stress_tensor(0,1) = rStressVector[3];
1189  stress_tensor(0,2) = 0.0;
1190  stress_tensor(1,0) = rStressVector[3];
1191  stress_tensor(1,1) = rStressVector[1];
1192  stress_tensor(1,2) = 0.0;
1193  stress_tensor(2,0) = 0.0;
1194  stress_tensor(2,1) = 0.0;
1195  stress_tensor(2,2) = rStressVector[2];
1196  } else if (rStressVector.size()==6) {
1197  stress_tensor(0,0) = rStressVector[0];
1198  stress_tensor(0,1) = rStressVector[3];
1199  stress_tensor(0,2) = rStressVector[5];
1200  stress_tensor(1,0) = rStressVector[3];
1201  stress_tensor(1,1) = rStressVector[1];
1202  stress_tensor(1,2) = rStressVector[4];
1203  stress_tensor(2,0) = rStressVector[5];
1204  stress_tensor(2,1) = rStressVector[4];
1205  stress_tensor(2,2) = rStressVector[2];
1206  }
1207 
1208  return stress_tensor;
1209 
1210  KRATOS_CATCH("");
1211  }
1212 
1224  template<class TVector, class TMatrixType = MatrixType>
1225  static inline TMatrixType VectorToSymmetricTensor(const TVector& rVector)
1226  {
1227  KRATOS_TRY;
1228 
1229  const SizeType matrix_size = rVector.size() == 3 ? 2 : 3;
1230  TMatrixType tensor(matrix_size, matrix_size);
1231 
1232  if (rVector.size() == 3) {
1233  tensor(0,0) = rVector[0];
1234  tensor(0,1) = rVector[2];
1235  tensor(1,0) = rVector[2];
1236  tensor(1,1) = rVector[1];
1237  } else if (rVector.size() == 4) {
1238  tensor(0,0) = rVector[0];
1239  tensor(0,1) = rVector[3];
1240  tensor(0,2) = 0.0;
1241  tensor(1,0) = rVector[3];
1242  tensor(1,1) = rVector[1];
1243  tensor(1,2) = 0.0;
1244  tensor(2,0) = 0.0;
1245  tensor(2,1) = 0.0;
1246  tensor(2,2) = rVector[2];
1247  } else if (rVector.size() == 6) {
1248  tensor(0,0) = rVector[0];
1249  tensor(0,1) = rVector[3];
1250  tensor(0,2) = rVector[5];
1251  tensor(1,0) = rVector[3];
1252  tensor(1,1) = rVector[1];
1253  tensor(1,2) = rVector[4];
1254  tensor(2,0) = rVector[5];
1255  tensor(2,1) = rVector[4];
1256  tensor(2,2) = rVector[2];
1257  }
1258 
1259  return tensor;
1260 
1261  KRATOS_CATCH("");
1262  }
1263 
1269  static inline int Sign(const double& ThisDataType)
1270  {
1271  KRATOS_TRY;
1272  const double& x = ThisDataType;
1273  return (x > 0) ? 1 : ((x < 0) ? -1 : 0);
1274  KRATOS_CATCH("");
1275  }
1276 
1277 
1289  template<class TVector, class TMatrixType = MatrixType>
1290  static inline TMatrixType StrainVectorToTensor( const TVector& rStrainVector)
1291  {
1292  KRATOS_TRY
1293 
1294  const SizeType matrix_size = rStrainVector.size() == 3 ? 2 : 3;
1295  TMatrixType strain_tensor(matrix_size, matrix_size);
1296 
1297  if (rStrainVector.size()==3) {
1298  strain_tensor(0,0) = rStrainVector[0];
1299  strain_tensor(0,1) = 0.5*rStrainVector[2];
1300  strain_tensor(1,0) = 0.5*rStrainVector[2];
1301  strain_tensor(1,1) = rStrainVector[1];
1302  } else if (rStrainVector.size()==4) {
1303  strain_tensor(0,0) = rStrainVector[0];
1304  strain_tensor(0,1) = 0.5*rStrainVector[3];
1305  strain_tensor(0,2) = 0;
1306  strain_tensor(1,0) = 0.5*rStrainVector[3];
1307  strain_tensor(1,1) = rStrainVector[1];
1308  strain_tensor(1,2) = 0;
1309  strain_tensor(2,0) = 0;
1310  strain_tensor(2,1) = 0;
1311  strain_tensor(2,2) = rStrainVector[2];
1312  } else if (rStrainVector.size()==6) {
1313  strain_tensor(0,0) = rStrainVector[0];
1314  strain_tensor(0,1) = 0.5*rStrainVector[3];
1315  strain_tensor(0,2) = 0.5*rStrainVector[5];
1316  strain_tensor(1,0) = 0.5*rStrainVector[3];
1317  strain_tensor(1,1) = rStrainVector[1];
1318  strain_tensor(1,2) = 0.5*rStrainVector[4];
1319  strain_tensor(2,0) = 0.5*rStrainVector[5];
1320  strain_tensor(2,1) = 0.5*rStrainVector[4];
1321  strain_tensor(2,2) = rStrainVector[2];
1322  }
1323 
1324  return strain_tensor;
1325 
1326  KRATOS_CATCH("");
1327  }
1328 
1343  template<class TMatrixType, class TVector = Vector>
1345  const TMatrixType& rStrainTensor,
1346  SizeType rSize = 0
1347  )
1348  {
1349  KRATOS_TRY;
1350 
1351  if(rSize == 0) {
1352  if(rStrainTensor.size1() == 2) {
1353  rSize = 3;
1354  } else if(rStrainTensor.size1() == 3) {
1355  rSize = 6;
1356  }
1357  }
1358 
1359  Vector strain_vector(rSize);
1360 
1361  if (rSize == 3) {
1362  strain_vector[0] = rStrainTensor(0,0);
1363  strain_vector[1] = rStrainTensor(1,1);
1364  strain_vector[2] = 2.0*rStrainTensor(0,1);
1365  } else if (rSize == 4) {
1366  strain_vector[0] = rStrainTensor(0,0);
1367  strain_vector[1] = rStrainTensor(1,1);
1368  strain_vector[2] = rStrainTensor(2,2);
1369  strain_vector[3] = 2.0*rStrainTensor(0,1);
1370  } else if (rSize == 6) {
1371  strain_vector[0] = rStrainTensor(0,0);
1372  strain_vector[1] = rStrainTensor(1,1);
1373  strain_vector[2] = rStrainTensor(2,2);
1374  strain_vector[3] = 2.0*rStrainTensor(0,1);
1375  strain_vector[4] = 2.0*rStrainTensor(1,2);
1376  strain_vector[5] = 2.0*rStrainTensor(0,2);
1377  }
1378 
1379  return strain_vector;
1380 
1381  KRATOS_CATCH("");
1382  }
1383 
1398  template<class TMatrixType, class TVector = Vector>
1399  static inline TVector StressTensorToVector(
1400  const TMatrixType& rStressTensor,
1401  SizeType rSize = 0
1402  )
1403  {
1404  KRATOS_TRY;
1405 
1406  if(rSize == 0) {
1407  if(rStressTensor.size1() == 2) {
1408  rSize = 3;
1409  } else if(rStressTensor.size1() == 3) {
1410  rSize = 6;
1411  }
1412  }
1413 
1414  TVector stress_vector(rSize);
1415 
1416  if (rSize == 3) {
1417  stress_vector[0] = rStressTensor(0,0);
1418  stress_vector[1] = rStressTensor(1,1);
1419  stress_vector[2] = rStressTensor(0,1);
1420  } else if (rSize == 4) {
1421  stress_vector[0] = rStressTensor(0,0);
1422  stress_vector[1] = rStressTensor(1,1);
1423  stress_vector[2] = rStressTensor(2,2);
1424  stress_vector[3] = rStressTensor(0,1);
1425  } else if (rSize == 6) {
1426  stress_vector[0] = rStressTensor(0,0);
1427  stress_vector[1] = rStressTensor(1,1);
1428  stress_vector[2] = rStressTensor(2,2);
1429  stress_vector[3] = rStressTensor(0,1);
1430  stress_vector[4] = rStressTensor(1,2);
1431  stress_vector[5] = rStressTensor(0,2);
1432  }
1433 
1434  return stress_vector;
1435 
1436  KRATOS_CATCH("");
1437  }
1438 
1450  template<class TMatrixType, class TVector = Vector>
1451  static inline TVector SymmetricTensorToVector(
1452  const TMatrixType& rTensor,
1453  SizeType rSize = 0
1454  )
1455  {
1456  KRATOS_TRY;
1457 
1458  if(rSize == 0) {
1459  if(rTensor.size1() == 2) {
1460  rSize = 3;
1461  } else if(rTensor.size1() == 3) {
1462  rSize = 6;
1463  }
1464  }
1465 
1466  Vector vector(rSize);
1467 
1468  if (rSize == 3) {
1469  vector[0]= rTensor(0,0);
1470  vector[1]= rTensor(1,1);
1471  vector[2]= rTensor(0,1);
1472 
1473  } else if (rSize==4) {
1474  vector[0]= rTensor(0,0);
1475  vector[1]= rTensor(1,1);
1476  vector[2]= rTensor(2,2);
1477  vector[3]= rTensor(0,1);
1478  } else if (rSize==6) {
1479  vector[0]= rTensor(0,0);
1480  vector[1]= rTensor(1,1);
1481  vector[2]= rTensor(2,2);
1482  vector[3]= rTensor(0,1);
1483  vector[4]= rTensor(1,2);
1484  vector[5]= rTensor(0,2);
1485  }
1486 
1487  return vector;
1488 
1489  KRATOS_CATCH("");
1490  }
1491 
1501  template<class TMatrixType1, class TMatrixType2, class TMatrixType3>
1502  static inline void BtDBProductOperation(
1503  TMatrixType1& rA,
1504  const TMatrixType2& rD,
1505  const TMatrixType3& rB
1506  )
1507  {
1508  // The sizes
1509  const SizeType size1 = rB.size2();
1510  const SizeType size2 = rB.size2();
1511 
1512  if (rA.size1() != size1 || rA.size2() != size2)
1513  rA.resize(size1, size2, false);
1514 
1515  // Direct multiplication
1516  // noalias(rA) = prod( trans( rB ), MatrixType(prod(rD, rB)));
1517 
1518  // Manual multiplication
1519  rA.clear();
1520  for(IndexType k = 0; k< rD.size1(); ++k) {
1521  for(IndexType l = 0; l < rD.size2(); ++l) {
1522  const double Dkl = rD(k, l);
1523  for(IndexType j = 0; j < rB.size2(); ++j) {
1524  const double DklBlj = Dkl * rB(l, j);
1525  for(IndexType i = 0; i< rB.size2(); ++i) {
1526  rA(i, j) += rB(k, i) * DklBlj;
1527  }
1528  }
1529  }
1530  }
1531  }
1532 
1542  template<class TMatrixType1, class TMatrixType2, class TMatrixType3>
1543  static inline void BDBtProductOperation(
1544  TMatrixType1& rA,
1545  const TMatrixType2& rD,
1546  const TMatrixType3& rB
1547  )
1548  {
1549  // The sizes
1550  const SizeType size1 = rB.size1();
1551  const SizeType size2 = rB.size1();
1552 
1553  if (rA.size1() != size1 || rA.size2() != size2)
1554  rA.resize(size1, size2, false);
1555 
1556  // Direct multiplication
1557  // noalias(rA) = prod(rB, MatrixType(prod(rD, trans(rB))));
1558 
1559  // Manual multiplication
1560  rA.clear();
1561  for(IndexType k = 0; k< rD.size1(); ++k) {
1562  for(IndexType l = 0; l < rD.size2(); ++l) {
1563  const double Dkl = rD(k,l);
1564  for(IndexType j = 0; j < rB.size1(); ++j) {
1565  const double DklBjl = Dkl * rB(j,l);
1566  for(IndexType i = 0; i< rB.size1(); ++i) {
1567  rA(i, j) += rB(i, k) * DklBjl;
1568  }
1569  }
1570  }
1571  }
1572  }
1573 
1586  template<class TMatrixType1, class TMatrixType2>
1587  static inline bool GaussSeidelEigenSystem(
1588  const TMatrixType1& rA,
1589  TMatrixType2& rEigenVectorsMatrix,
1590  TMatrixType2& rEigenValuesMatrix,
1591  const double Tolerance = 1.0e-18,
1592  const SizeType MaxIterations = 20
1593  )
1594  {
1595  bool is_converged = false;
1596 
1597  const SizeType size = rA.size1();
1598 
1599  if (rEigenVectorsMatrix.size1() != size || rEigenVectorsMatrix.size2() != size)
1600  rEigenVectorsMatrix.resize(size, size, false);
1601  if (rEigenValuesMatrix.size1() != size || rEigenValuesMatrix.size2() != size)
1602  rEigenValuesMatrix.resize(size, size, false);
1603 
1604  const TMatrixType2 identity_matrix = IdentityMatrix(size);
1605  noalias(rEigenVectorsMatrix) = identity_matrix;
1606  noalias(rEigenValuesMatrix) = rA;
1607 
1608  // Auxiliar values
1609  TMatrixType2 aux_A, aux_V_matrix, rotation_matrix;
1610  double a, u, c, s, gamma, teta;
1611  IndexType index1, index2;
1612 
1613  aux_A.resize(size,size,false);
1614  aux_V_matrix.resize(size,size,false);
1615  rotation_matrix.resize(size,size,false);
1616 
1617  for(IndexType iterations = 0; iterations < MaxIterations; ++iterations) {
1618  is_converged = true;
1619 
1620  a = 0.0;
1621  index1 = 0;
1622  index2 = 1;
1623 
1624  for(IndexType i = 0; i < size; ++i) {
1625  for(IndexType j = (i + 1); j < size; ++j) {
1626  if((std::abs(rEigenValuesMatrix(i, j)) > a ) && (std::abs(rEigenValuesMatrix(i, j)) > Tolerance)) {
1627  a = std::abs(rEigenValuesMatrix(i,j));
1628  index1 = i;
1629  index2 = j;
1630  is_converged = false;
1631  }
1632  }
1633  }
1634 
1635  if(is_converged) {
1636  break;
1637  }
1638 
1639  // Calculation of Rotation angle
1640  gamma = (rEigenValuesMatrix(index2, index2)-rEigenValuesMatrix(index1, index1)) / (2 * rEigenValuesMatrix(index1, index2));
1641  u = 1.0;
1642 
1643  if(std::abs(gamma) > Tolerance && std::abs(gamma)< (1.0/Tolerance)) {
1644  u = gamma / std::abs(gamma) * 1.0 / (std::abs(gamma) + std::sqrt(1.0 + gamma * gamma));
1645  } else {
1646  if (std::abs(gamma) >= (1.0/Tolerance)) {
1647  u = 0.5 / gamma;
1648  }
1649  }
1650 
1651  c = 1.0 / (std::sqrt(1.0 + u * u));
1652  s = c * u;
1653  teta = s / (1.0 + c);
1654 
1655  // Rotation of the Matrix
1656  noalias(aux_A) = rEigenValuesMatrix;
1657  aux_A(index2, index2) = rEigenValuesMatrix(index2,index2) + u * rEigenValuesMatrix(index1, index2);
1658  aux_A(index1, index1) = rEigenValuesMatrix(index1,index1) - u * rEigenValuesMatrix(index1, index2);
1659  aux_A(index1, index2) = 0.0;
1660  aux_A(index2, index1) = 0.0;
1661 
1662  for(IndexType i = 0; i < size; ++i) {
1663  if((i!= index1) && (i!= index2)) {
1664  aux_A(index2, i) = rEigenValuesMatrix(index2, i) + s * (rEigenValuesMatrix(index1, i)- teta * rEigenValuesMatrix(index2, i));
1665  aux_A(i, index2) = rEigenValuesMatrix(index2, i) + s * (rEigenValuesMatrix(index1, i)- teta * rEigenValuesMatrix(index2, i));
1666  aux_A(index1, i) = rEigenValuesMatrix(index1, i) - s * (rEigenValuesMatrix(index2, i) + teta * rEigenValuesMatrix(index1, i));
1667  aux_A(i, index1) = rEigenValuesMatrix(index1, i) - s * (rEigenValuesMatrix(index2, i) + teta * rEigenValuesMatrix(index1, i));
1668  }
1669  }
1670 
1671  noalias(rEigenValuesMatrix) = aux_A;
1672 
1673  // Calculation of the eigeneigen vector matrix V
1674  noalias(rotation_matrix) = identity_matrix;
1675  rotation_matrix(index2, index1) = -s;
1676  rotation_matrix(index1, index2) = s;
1677  rotation_matrix(index1, index1) = c;
1678  rotation_matrix(index2, index2) = c;
1679 
1680  noalias(aux_V_matrix) = ZeroMatrix(size, size);
1681 
1682  for(IndexType i = 0; i < size; ++i) {
1683  for(IndexType j = 0; j < size; ++j) {
1684  for(IndexType k = 0; k < size; ++k) {
1685  aux_V_matrix(i, j) += rEigenVectorsMatrix(i, k) * rotation_matrix(k, j);
1686  }
1687  }
1688  }
1689  noalias(rEigenVectorsMatrix) = aux_V_matrix;
1690  }
1691 
1692  KRATOS_WARNING_IF("MathUtils::EigenSystem", !is_converged) << "Spectral decomposition not converged " << std::endl;
1693 
1694  return is_converged;
1695  }
1696 
1709  template<SizeType TDim>
1710  KRATOS_DEPRECATED_MESSAGE("Please use GaussSeidelEigenSystem() instead. Note the resulting EigenVectors matrix is transposed respect GaussSeidelEigenSystem()")
1711  static inline bool EigenSystem(
1712  const BoundedMatrix<double, TDim, TDim>& rA,
1713  BoundedMatrix<double, TDim, TDim>& rEigenVectorsMatrix,
1714  BoundedMatrix<double, TDim, TDim>& rEigenValuesMatrix,
1715  const double Tolerance = 1.0e-18,
1716  const SizeType MaxIterations = 20
1717  )
1718  {
1719  const bool is_converged = GaussSeidelEigenSystem(rA, rEigenVectorsMatrix, rEigenValuesMatrix, Tolerance, MaxIterations);
1720 
1721  const BoundedMatrix<double, TDim, TDim> V_matrix = rEigenVectorsMatrix;
1722  for(IndexType i = 0; i < TDim; ++i) {
1723  for(IndexType j = 0; j < TDim; ++j) {
1724  rEigenVectorsMatrix(i, j) = V_matrix(j, i);
1725  }
1726  }
1727 
1728  return is_converged;
1729  }
1730 
1746  template<class TMatrixType1, class TMatrixType2>
1747  static inline bool MatrixSquareRoot(
1748  const TMatrixType1 &rA,
1749  TMatrixType2 &rMatrixSquareRoot,
1750  const double Tolerance = 1.0e-18,
1751  const SizeType MaxIterations = 20
1752  )
1753  {
1754  // Do an eigenvalue decomposition of the input matrix
1755  TMatrixType2 eigenvectors_matrix, eigenvalues_matrix;
1756  const bool is_converged = GaussSeidelEigenSystem(rA, eigenvectors_matrix, eigenvalues_matrix, Tolerance, MaxIterations);
1757  KRATOS_WARNING_IF("MatrixSquareRoot", !is_converged) << "GaussSeidelEigenSystem did not converge.\n";
1758 
1759  // Get the square root of the eigenvalues
1760  SizeType size = eigenvalues_matrix.size1();
1761  for (SizeType i = 0; i < size; ++i) {
1762  KRATOS_ERROR_IF(eigenvalues_matrix(i,i) < 0) << "Eigenvalue " << i << " is negative. Square root matrix cannot be computed" << std::endl;
1763  eigenvalues_matrix(i,i) = std::sqrt(eigenvalues_matrix(i,i));
1764  }
1765 
1766  // Calculate the solution from the previous decomposition and eigenvalues square root
1767  BDBtProductOperation(rMatrixSquareRoot, eigenvalues_matrix, eigenvectors_matrix);
1768 
1769  return is_converged;
1770  }
1771 
1776  template<class TIntegerType>
1777  static inline TIntegerType Factorial(const TIntegerType Number)
1778  {
1779  if (Number == 0) {
1780  return 1;
1781  }
1782  TIntegerType k = Number;
1783  for (TIntegerType i = Number - 1; i > 0; --i){
1784  k *= i;
1785  }
1786  return k;
1787  }
1788 
1795  template<class TMatrixType>
1796  static inline void CalculateExponentialOfMatrix(
1797  const TMatrixType& rMatrix,
1798  TMatrixType& rExponentialMatrix,
1799  const double Tolerance = 1000.0*ZeroTolerance,
1800  const SizeType MaxTerms = 200
1801  )
1802  {
1803  SizeType series_term = 2;
1804  SizeType factorial = 1;
1805  const SizeType dimension = rMatrix.size1();
1806 
1807  noalias(rExponentialMatrix) = IdentityMatrix(dimension) + rMatrix;
1808  TMatrixType exponent_matrix = rMatrix;
1809  TMatrixType aux_matrix;
1810 
1811  while (series_term < MaxTerms) {
1812  noalias(aux_matrix) = prod(exponent_matrix, rMatrix);
1813  noalias(exponent_matrix) = aux_matrix;
1814  factorial = Factorial(series_term);
1815  noalias(rExponentialMatrix) += exponent_matrix / factorial;
1816  const double norm_series_term = std::abs(norm_frobenius(exponent_matrix) / factorial);
1817  if (norm_series_term < Tolerance)
1818  break;
1819  series_term++;
1820  }
1821  }
1822 
1823 
1824  static double DegreesToRadians(double AngleInDegrees)
1825  {
1826  return (AngleInDegrees * Globals::Pi) / 180.0;
1827  }
1828 
1830 
1831 private:
1832 
1835 
1836  MathUtils(void);
1837 
1838  MathUtils(MathUtils& rSource);
1839 
1841 }; /* Class MathUtils */
1842 
1845 
1849 
1850 } /* namespace Kratos.*/
iterator end()
Definition: amatrix_interface.h:243
iterator begin()
Definition: amatrix_interface.h:241
AMatrix::RandomAccessIterator< const double > const_iterator
Definition: amatrix_interface.h:53
Various mathematical utilitiy functions.
Definition: math_utils.h:62
static void ExpandAndAddReducedMatrix(MatrixType &rDestination, const MatrixType &rReducedMatrix, const SizeType Dimension)
Performs the Kroneker product of the Reduced Matrix with the identity matrix of size "dimension" ADDI...
Definition: math_utils.h:1117
static void AddVector(TVectorType1 &rDestination, const TVectorType2 &rInputVector, const IndexType InitialIndex)
"rInputVector" is ADDED to "Destination" vector starting from InitialIndex of the destination matrix
Definition: math_utils.h:1013
static double Dot3(const Vector &a, const Vector &b)
Performs the dot product of two vectors of dimension 3.
Definition: math_utils.h:654
std::size_t SizeType
The size type.
Definition: math_utils.h:75
static TMatrixType VectorToSymmetricTensor(const TVector &rVector)
Transforms a vector into a symmetric matrix.
Definition: math_utils.h:1225
static void InvertMatrix4(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet)
It inverts matrices of order 4.
Definition: math_utils.h:495
static TIntegerType Factorial(const TIntegerType Number)
Calculates the Factorial of a number k, Factorial = k!
Definition: math_utils.h:1777
static double StableNorm(const Vector &a)
Calculates the norm of vector "a" while avoiding underflow and overflow.
Definition: math_utils.h:720
static void InvertMatrix3(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet)
It inverts matrices of order 3.
Definition: math_utils.h:449
static void GeneralizedInvertMatrix(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet, const double Tolerance=ZeroTolerance)
It inverts non square matrices (https://en.wikipedia.org/wiki/Inverse_element#Matrices)
Definition: math_utils.h:274
std::size_t IndexType
The index type.
Definition: math_utils.h:78
static void ExpandReducedMatrix(MatrixType &rDestination, const MatrixType &rReducedMatrix, const SizeType Dimension)
Performs the Kroneker product of the Reduced Matrix with the identity matrix of size "dimension".
Definition: math_utils.h:1086
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 double Norm3(const TVectorType &a)
Calculates the norm of vector "a" which is assumed to be of size 3.
Definition: math_utils.h:691
static void AddMatrix(TMatrixType1 &rDestination, const TMatrixType2 &rInputMatrix, const IndexType InitialRow, const IndexType InitialCol)
"rInputMatrix" is ADDED to "Destination" matrix starting from InitialRow and InitialCol of the destin...
Definition: math_utils.h:988
static void InvertMatrix2(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet)
It inverts matrices of order 2.
Definition: math_utils.h:416
static void InvertMatrix(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet, const double Tolerance=ZeroTolerance)
It inverts matrices of order 2, 3 and 4.
Definition: math_utils.h:328
static Vector StrainTensorToVector(const TMatrixType &rStrainTensor, SizeType rSize=0)
Transforms a given symmetric Strain Tensor to Voigt Notation:
Definition: math_utils.h:1344
static T CrossProduct(const T &a, const T &b)
Performs the vector product of the two input vectors a,b.
Definition: math_utils.h:762
static void OrthonormalBasisFrisvad(const T1 &c, T2 &a, T3 &b)
This computes a orthonormal basis from a given vector (Frisvad method)
Definition: math_utils.h:889
static double DegreesToRadians(double AngleInDegrees)
Definition: math_utils.h:1824
static std::enable_if<!std::is_same< T1, T2 >::value, bool >::type CheckIsAlias(T1 &value1, T2 &value2)
Checks there is aliasing.
Definition: math_utils.h:793
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 void UnitCrossProduct(T1 &c, const T2 &a, const T3 &b)
Performs the unitary cross product of the two input vectors a,b.
Definition: math_utils.h:831
static double Norm(const Vector &a)
Calculates the norm of vector "a".
Definition: math_utils.h:703
static double VectorsAngle(const T1 &rV1, const T2 &rV2)
Computes the angle between two vectors in 3D.
Definition: math_utils.h:943
static TMatrixType StrainVectorToTensor(const TVector &rStrainVector)
Transforms a strain vector into a matrix. Strains are assumed to be stored in the following way: for...
Definition: math_utils.h:1290
static void BtDBProductOperation(TMatrixType1 &rA, const TMatrixType2 &rD, const TMatrixType3 &rB)
Calculates the product operation B'DB.
Definition: math_utils.h:1502
static bool CheckConditionNumber(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, const double Tolerance=std::numeric_limits< double >::epsilon(), const bool ThrowError=true)
This method checks the condition number of amtrix.
Definition: math_utils.h:236
static double Cofactor(const TMatrixType &rMat, IndexType i, IndexType j)
Calculates the cofactor.
Definition: math_utils.h:142
static std::enable_if< std::is_same< T1, T2 >::value, bool >::type CheckIsAlias(T1 &value1, T2 &value2)
Checks there is aliasing.
Definition: math_utils.h:782
static MatrixType TensorProduct3(const Vector &a, const Vector &b)
Returns a matrix : A = a.tensorproduct.b.
Definition: math_utils.h:959
static double GeneralizedDet(const TMatrixType &rA)
Calculates the determinant of any matrix (no check performed on matrix size)
Definition: math_utils.h:634
static double Det3(const TMatrixType &rA)
Calculates the determinant of a matrix of dimension 3*3 (no check performed on matrix size)
Definition: math_utils.h:562
static TVector SymmetricTensorToVector(const TMatrixType &rTensor, SizeType rSize=0)
Transforms a given symmetric Tensor to Voigt Notation:
Definition: math_utils.h:1451
static void BDBtProductOperation(TMatrixType1 &rA, const TMatrixType2 &rD, const TMatrixType3 &rB)
Calculates the product operation BDB'.
Definition: math_utils.h:1543
static void OrthonormalBasis(const T1 &c, T2 &a, T3 &b, const IndexType Type=0)
This computes a orthonormal basis from a given vector (Frisvad method)
Definition: math_utils.h:848
static MatrixType CofactorMatrix(const TMatrixType &rMat)
Calculates the cofactor matrix.
Definition: math_utils.h:175
boost::numeric::ublas::indirect_array< DenseVector< std::size_t > > IndirectArrayType
The indirect array type.
Definition: math_utils.h:81
static double Det4(const TMatrixType &rA)
Calculates the determinant of a matrix of dimension 4*4 (no check performed on matrix size)
Definition: math_utils.h:580
static void CalculateExponentialOfMatrix(const TMatrixType &rMatrix, TMatrixType &rExponentialMatrix, const double Tolerance=1000.0 *ZeroTolerance, const SizeType MaxTerms=200)
Calculates the exponential of a matrix.
Definition: math_utils.h:1796
KRATOS_DEPRECATED_MESSAGE("Please use GaussSeidelEigenSystem() instead. Note the resulting EigenVectors matrix is transposed respect GaussSeidelEigenSystem()") static inline bool EigenSystem(const BoundedMatrix< double
Calculates the eigenvectors and eigenvalues of given symmetric TDimxTDim matrix.
static void WriteMatrix(MatrixType &rDestination, const MatrixType &rInputMatrix, const IndexType InitialRow, const IndexType InitialCol)
"rInputMatrix" is WRITTEN on "Destination" matrix starting from InitialRow and InitialCol of the dest...
Definition: math_utils.h:1062
static double Det2(const TMatrixType &rA)
Calculates the determinant of a matrix of dimension 2x2 (no check performed on matrix size)
Definition: math_utils.h:549
static void CrossProduct(T1 &c, const T2 &a, const T3 &b)
Performs the cross product of the two input vectors a,b.
Definition: math_utils.h:806
static int Sign(const double &ThisDataType)
Sign function.
Definition: math_utils.h:1269
static void VecAdd(Vector &rX, const double coeff, Vector &rY)
Performs rX += coeff*rY. no check on bounds is performed.
Definition: math_utils.h:1148
static double Dot(const Vector &rFirstVector, const Vector &rSecondVector)
Performs the dot product of two vectors of arbitrary size.
Definition: math_utils.h:669
static void SubtractMatrix(MatrixType &rDestination, const MatrixType &rInputMatrix, const IndexType InitialRow, const IndexType InitialCol)
"rInputMatrix" is SUBTRACTED to "rDestination" matrix starting from InitialRow and InitialCol of the ...
Definition: math_utils.h:1035
static bool GaussSeidelEigenSystem(const TMatrixType1 &rA, TMatrixType2 &rEigenVectorsMatrix, TMatrixType2 &rEigenValuesMatrix, const double Tolerance=1.0e-18, const SizeType MaxIterations=20)
Calculates the eigenvectors and eigenvalues of given symmetric matrix.
Definition: math_utils.h:1587
static double GetZeroTolerance()
This function returns the machine precision.
Definition: math_utils.h:102
static void OrthonormalBasisHughesMoeller(const T1 &c, T2 &a, T3 &b)
This computes a orthonormal basis from a given vector (Hughes Moeller method)
Definition: math_utils.h:865
static double Heron(double a, double b, double c)
In geometry, Heron's formula (sometimes called Hero's formula), named after Hero of Alexandria,...
Definition: math_utils.h:115
static void OrthonormalBasisNaive(const T1 &c, T2 &a, T3 &b)
This computes a orthonormal basis from a given vector (Naive method)
Definition: math_utils.h:920
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_WATCH(variable)
Definition: define.h:806
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
#define KRATOS_DEBUG_ERROR_IF_NOT(conditional)
Definition: exception.h:172
#define KRATOS_WARNING_IF(label, conditional)
Definition: logger.h:266
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
constexpr double Pi
Definition: global_variables.h:25
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
AMatrix::IdentityMatrix< double > IdentityMatrix
Definition: amatrix_interface.h:564
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
Internals::Matrix< double, AMatrix::dynamic, AMatrix::dynamic > Matrix
Definition: amatrix_interface.h:470
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
std::size_t SizeType
The definition of the size type.
Definition: mortar_classes.h:43
namespace KRATOS_DEPRECATED_MESSAGE("Please use std::filesystem directly") filesystem
Definition: kratos_filesystem.h:33
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
TExpressionType::data_type norm_frobenius(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:687
list coeff
Definition: bombardelli_test.py:41
def CrossProduct(A, B)
Definition: define_wake_process_3d.py:13
f
Definition: generate_convection_diffusion_explicit_element.py:112
type
Definition: generate_gid_list_file.py:35
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
float gamma
Definition: generate_two_fluid_navier_stokes.py:131
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
int dimension
Definition: isotropic_damage_automatic_differentiation.py:123
tuple const
Definition: ode_solve.py:403
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
float temp
Definition: rotating_cone.py:85
A
Definition: sensitivityMatrix.py:70
x
Definition: sensitivityMatrix.py:49
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31