// M_EigenValsProjsNum computes the eigenvalues and eigenprojectors of tensor 'a' (2nd order symmetric tensor in Mandel's basis) // using Jacobi rotation. func M_EigenValsProjsNum(P [][]float64, λ, a []float64) (err error) { Q := Alloc2() A := Alloc2() Man2Ten(A, a) _, err = la.Jacobi(Q, λ, A) if err != nil { return } P[0][0] = Q[0][0] * Q[0][0] P[0][1] = Q[1][0] * Q[1][0] P[0][2] = Q[2][0] * Q[2][0] P[0][3] = Q[0][0] * Q[1][0] * SQ2 P[1][0] = Q[0][1] * Q[0][1] P[1][1] = Q[1][1] * Q[1][1] P[1][2] = Q[2][1] * Q[2][1] P[1][3] = Q[0][1] * Q[1][1] * SQ2 P[2][0] = Q[0][2] * Q[0][2] P[2][1] = Q[1][2] * Q[1][2] P[2][2] = Q[2][2] * Q[2][2] P[2][3] = Q[0][2] * Q[1][2] * SQ2 if len(a) == 6 { P[0][4] = Q[1][0] * Q[2][0] * SQ2 P[0][5] = Q[2][0] * Q[0][0] * SQ2 P[1][4] = Q[1][1] * Q[2][1] * SQ2 P[1][5] = Q[2][1] * Q[0][1] * SQ2 P[2][4] = Q[1][2] * Q[2][2] * SQ2 P[2][5] = Q[2][2] * Q[0][2] * SQ2 } return }
// M_EigenValsNum returns the eigenvalues of tensor 'a' (2nd order symmetric tensor in Mandel's basis) // using Jacobi rotation func M_EigenValsNum(λ, a []float64) (err error) { Q := Alloc2() A := Alloc2() Man2Ten(A, a) _, err = la.Jacobi(Q, λ, A) return }
// M_PrincValsNum returns the (sorted, ascending) eigenvalues of tensor 'a' (2nd order symmetric tensor in Mandel's basis) // using Jacobi rotation. func M_PrincValsNum(a []float64) (λ0, λ1, λ2 float64, err error) { Q := Alloc2() A := Alloc2() v := make([]float64, 3) Man2Ten(A, a) _, err = la.Jacobi(Q, v, A) if err != nil { return } λ0, λ1, λ2 = v[0], v[1], v[2] utl.DblSort3(&λ0, &λ1, &λ2) return }
// M_EigenValsVecs returns the eigenvalues and eigenvectors of tensor 'a' (2nd order symmetric tensor in Mandel's basis) // using Jacobi rotation. func M_EigenValsVecsNum(Q [][]float64, λ, a []float64) (err error) { A := Alloc2() Man2Ten(A, a) _, err = la.Jacobi(Q, λ, A) return }
// M_EigenProjsDerivNum returns the derivatives of the eigenprojectors w.r.t its defining tensor // using the finite differences method. // Input: // a -- tensor in Mandel basis // h -- step size for finite differences // Output: // dPda -- derivatives [3][ncp][ncp] func M_EigenProjsDerivNum(dPda [][][]float64, a []float64, h float64) (err error) { ncp := len(a) λ := make([]float64, 3) P := la.MatAlloc(3, ncp) Q := Alloc2() A := Alloc2() q2p := func(k int) { switch k { case 0: P[0][0] = Q[0][0] * Q[0][0] P[0][1] = Q[1][0] * Q[1][0] P[0][2] = Q[2][0] * Q[2][0] P[0][3] = Q[0][0] * Q[1][0] * SQ2 if ncp == 6 { P[0][4] = Q[1][0] * Q[2][0] * SQ2 P[0][5] = Q[2][0] * Q[0][0] * SQ2 } case 1: P[1][0] = Q[0][1] * Q[0][1] P[1][1] = Q[1][1] * Q[1][1] P[1][2] = Q[2][1] * Q[2][1] P[1][3] = Q[0][1] * Q[1][1] * SQ2 if ncp == 6 { P[1][4] = Q[1][1] * Q[2][1] * SQ2 P[1][5] = Q[2][1] * Q[0][1] * SQ2 } case 2: P[2][0] = Q[0][2] * Q[0][2] P[2][1] = Q[1][2] * Q[1][2] P[2][2] = Q[2][2] * Q[2][2] P[2][3] = Q[0][2] * Q[1][2] * SQ2 if ncp == 6 { P[2][4] = Q[1][2] * Q[2][2] * SQ2 P[2][5] = Q[2][2] * Q[0][2] * SQ2 } } } var tmp float64 failed := false for k := 0; k < 3; k++ { for i := 0; i < ncp; i++ { for j := 0; j < ncp; j++ { dPda[k][i][j], _ = num.DerivCentral(func(x float64, args ...interface{}) float64 { tmp, a[j] = a[j], x defer func() { a[j] = tmp }() Man2Ten(A, a) _, err = la.Jacobi(Q, λ, A) if err != nil { failed = true return 0 } q2p(k) return P[k][i] }, a[j], h) if failed { return } } } } return }