pydrex.tensors
PyDRex: Tensor operation functions and helpers.
For Voigt notation, the symmetric 6x6 matrix representation is used, which assumes that the fourth order tensor being represented as such is also symmetric. The vectorial notation uses 21 components which are the independent components of the symmetric 6x6 matrix.
1"""> PyDRex: Tensor operation functions and helpers. 2 3For Voigt notation, the symmetric 6x6 matrix representation is used, 4which assumes that the fourth order tensor being represented as such is also symmetric. 5The vectorial notation uses 21 components which are the independent components of the 6symmetric 6x6 matrix. 7 8""" 9 10import numba as nb 11import numpy as np 12 13 14@nb.njit(fastmath=True) 15def polar_decompose(matrix, left=True): 16 """Compute polar decomposition of M as either M = RU (right) or M = VP (left).""" 17 U, S, Vh = np.linalg.svd(matrix) 18 if left: 19 return U @ Vh, U @ (np.diag(S) @ U.transpose()) 20 U_matrix = Vh.transpose() @ (np.diag(S) @ Vh) 21 return matrix @ np.linalg.inv(U_matrix), U_matrix 22 23 24@nb.njit(fastmath=True) 25def invariants_second_order(tensor): 26 """Calculate invariants of a second order tensor.""" 27 return ( 28 np.trace(tensor), 29 tensor[0, 0] * tensor[1, 1] 30 + tensor[1, 1] * tensor[2, 2] 31 + tensor[2, 2] * tensor[0, 0] 32 - tensor[0, 1] * tensor[1, 0] 33 - tensor[1, 2] * tensor[2, 1] 34 - tensor[2, 0] * tensor[0, 2], 35 np.linalg.det(tensor), 36 ) 37 38 39@nb.njit(fastmath=True) 40def voigt_decompose(matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]: 41 """Decompose elastic tensor (as 6x6 Voigt matrix) into distinct contractions. 42 43 Return the only two independent contractions of the elastic tensor given as a 6x6 44 Voigt `matrix`. With reference to the full 4-th order elastic tensor, the 45 contractions are defined as: 46 - $d_{ij} = C_{ijkk}$ (dilatational stiffness tensor) 47 - $v_{ij} = C_{ijkj}$ (deviatoric stiffness tensor) 48 49 Any vector which is an eigenvector of both $d_{ij}$ and $v_{ij}$ is always normal to 50 a symmetry plane of the elastic medium. 51 52 See Equations 3.4 & 3.5 in [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 53 54 """ 55 # 1. Compose dᵢⱼ = Cᵢⱼₖₖ (dilatational stiffness tensor) 56 # Eq. 3.4 in Browaeys & Chevrot, 2004. 57 stiffness_dilat = np.empty((3, 3)) 58 for i in range(3): 59 stiffness_dilat[i, i] = matrix[:3, i].sum() 60 stiffness_dilat[0, 1] = stiffness_dilat[1, 0] = matrix[:3, 5].sum() 61 stiffness_dilat[0, 2] = stiffness_dilat[2, 0] = matrix[:3, 4].sum() 62 stiffness_dilat[1, 2] = stiffness_dilat[2, 1] = matrix[:3, 3].sum() 63 # 2. Compose vᵢⱼ = Cᵢⱼₖⱼ (deviatoric stiffness tensor) 64 # Eq. 3.5, Browaeys & Chevrot, 2004. 65 stiffness_deviat = np.empty((3, 3)) 66 stiffness_deviat[0, 0] = matrix[0, 0] + matrix[4, 4] + matrix[5, 5] 67 stiffness_deviat[1, 1] = matrix[1, 1] + matrix[3, 3] + matrix[5, 5] 68 stiffness_deviat[2, 2] = matrix[2, 2] + matrix[3, 3] + matrix[4, 4] 69 stiffness_deviat[0, 1] = matrix[0, 5] + matrix[1, 5] + matrix[3, 4] 70 stiffness_deviat[0, 2] = matrix[0, 4] + matrix[2, 4] + matrix[3, 5] 71 stiffness_deviat[1, 2] = matrix[1, 3] + matrix[2, 3] + matrix[4, 5] 72 stiffness_deviat = upper_tri_to_symmetric(stiffness_deviat) 73 return stiffness_dilat, stiffness_deviat 74 75 76@nb.njit(fastmath=True) 77def mono_project(voigt_vector): 78 """Project 21-component `voigt_vector` onto monoclinic symmetry subspace. 79 80 Monoclinic symmetry is characterised by 13 independent elasticity components. 81 82 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 83 84 """ 85 out = voigt_vector.copy() 86 inds = (9, 10, 12, 13, 15, 16, 18, 19) 87 for i in inds: 88 out[i] = 0 89 return out 90 91 92@nb.njit(fastmath=True) 93def ortho_project(voigt_vector): 94 """Project 21-component `voigt_vector` onto orthorhombic symmetry subspace. 95 96 Orthorhombic symmetry is characterised by 9 independent elasticity components. 97 98 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 99 100 """ 101 out = voigt_vector.copy() 102 out[9:] = 0 103 return out 104 105 106@nb.njit(fastmath=True) 107def tetr_project(voigt_vector): 108 """Project 21-component `voigt_vector` onto tetragonal symmetry subspace. 109 110 Tetragonal symmetry is characterised by 6 independent elasticity components. 111 112 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 113 114 """ 115 out = ortho_project(voigt_vector) 116 for i, j in ((0, 1), (3, 4), (6, 7)): 117 for k in range(2): 118 out[i + k] = 0.5 * (voigt_vector[i] + voigt_vector[j]) 119 return out 120 121 122@nb.njit(fastmath=True) 123def hex_project(voigt_vector): 124 """Project 21-component `voigt_vector` onto hexagonal symmetry subspace. 125 126 Hexagonal symmetry (a.k.a. transverse isotropy) is characterised by 5 independent 127 elasticity components. 128 129 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 130 131 """ 132 x = voigt_vector 133 out = np.zeros(21) 134 out[0] = out[1] = 3 / 8 * (x[0] + x[1]) + x[5] / 4 / np.sqrt(2) + x[8] / 4 135 out[2] = x[2] 136 out[3] = out[4] = (x[3] + x[4]) / 2 137 out[5] = (x[0] + x[1]) / 4 / np.sqrt(2) + 3 / 4 * x[5] - x[8] / 2 / np.sqrt(2) 138 out[6] = out[7] = (x[6] + x[7]) / 2 139 out[8] = (x[0] + x[1]) / 4 - x[5] / 2 / np.sqrt(2) + x[8] / 2 140 return out 141 142 143@nb.njit(fastmath=True) 144def upper_tri_to_symmetric(arr): 145 """Create symmetric array using upper triangle of input array. 146 147 Examples: 148 149 >>> import numpy as np 150 >>> upper_tri_to_symmetric(np.array([ 151 ... [ 1., 2., 3., 4.], 152 ... [ 0., 5., 6., 7.], 153 ... [ 0., 0., 8., 9.], 154 ... [ 9., 0., 0., 10.] 155 ... ])) 156 array([[ 1., 2., 3., 4.], 157 [ 2., 5., 6., 7.], 158 [ 3., 6., 8., 9.], 159 [ 4., 7., 9., 10.]]) 160 161 """ 162 # <https://stackoverflow.com/questions/58718365/fast-way-to-convert-upper-triangular-matrix-into-symmetric-matrix> 163 upper_tri = np.triu(arr) 164 return np.where(upper_tri, upper_tri, upper_tri.transpose()) 165 166 167@nb.njit(fastmath=True) 168def voigt_to_elastic_tensor(matrix): 169 """Create 4-th order elastic tensor from an equivalent Voigt matrix. 170 171 See also: `elastic_tensor_to_voigt`. 172 173 """ 174 tensor = np.empty((3, 3, 3, 3)) 175 for p in range(3): 176 for q in range(3): 177 delta_pq = 1 if p == q else 0 178 i = (p + 1) * delta_pq + (1 - delta_pq) * (7 - p - q) - 1 179 for r in range(3): 180 for s in range(3): 181 delta_rs = 1 if r == s else 0 182 j = (r + 1) * delta_rs + (1 - delta_rs) * (7 - r - s) - 1 183 tensor[p, q, r, s] = matrix[i, j] 184 return tensor 185 186 187@nb.njit(fastmath=True) 188def elastic_tensor_to_voigt(tensor): 189 """Create a 6x6 Voigt matrix from an equivalent 4-th order elastic tensor.""" 190 matrix = np.zeros((6, 6)) 191 matrix_indices = np.zeros((6, 6)) 192 for p in range(3): 193 for q in range(3): 194 delta_pq = 1 if p == q else 0 195 i = (p + 1) * delta_pq + (1 - delta_pq) * (7 - p - q) - 1 196 for r in range(3): 197 for s in range(3): 198 delta_rs = 1 if r == s else 0 199 j = (r + 1) * delta_rs + (1 - delta_rs) * (7 - r - s) - 1 200 matrix[i, j] += tensor[p, q, r, s] 201 matrix_indices[i, j] += 1 202 matrix /= matrix_indices 203 return (matrix + matrix.transpose()) / 2 204 205 206@nb.njit(fastmath=True) 207def voigt_matrix_to_vector(matrix): 208 """Create the 21-component Voigt vector equivalent to the 6x6 Voigt matrix.""" 209 vector = np.zeros(21) 210 for i in range(3): 211 vector[i] = matrix[i, i] 212 vector[i + 3] = np.sqrt(2) * matrix[(i + 1) % 3, (i + 2) % 3] 213 vector[i + 6] = 2 * matrix[i + 3, i + 3] 214 vector[i + 9] = 2 * matrix[i, i + 3] 215 vector[i + 12] = 2 * matrix[(i + 2) % 3, i + 3] 216 vector[i + 15] = 2 * matrix[(i + 1) % 3, i + 3] 217 vector[i + 18] = 2 * np.sqrt(2) * matrix[(i + 1) % 3 + 3, (i + 2) % 3 + 3] 218 return vector 219 220 221@nb.njit(fastmath=True) 222def voigt_vector_to_matrix(vector): 223 """Create the 6x6 matrix representation of the 21-component Voigt vector. 224 225 See also: `voigt_matrix_to_vector`. 226 227 """ 228 matrix = np.zeros((6, 6)) 229 for i in range(3): 230 matrix[i, i] = vector[i] 231 matrix[i + 3, i + 3] = 0.5 * vector[i + 6] 232 233 matrix[1, 2] = 1 / np.sqrt(2) * vector[3] 234 matrix[0, 2] = 1 / np.sqrt(2) * vector[4] 235 matrix[0, 1] = 1 / np.sqrt(2) * vector[5] 236 237 matrix[0, 3] = 0.5 * vector[9] 238 matrix[1, 4] = 0.5 * vector[10] 239 matrix[2, 5] = 0.5 * vector[11] 240 matrix[2, 3] = 0.5 * vector[12] 241 242 matrix[0, 4] = 0.5 * vector[13] 243 matrix[1, 5] = 0.5 * vector[14] 244 matrix[1, 3] = 0.5 * vector[15] 245 246 matrix[2][4] = 0.5 * vector[16] 247 matrix[0][5] = 0.5 * vector[17] 248 matrix[4][5] = 0.5 * 1 / np.sqrt(2) * vector[18] 249 matrix[3][5] = 0.5 * 1 / np.sqrt(2) * vector[19] 250 matrix[3][4] = 0.5 * 1 / np.sqrt(2) * vector[20] 251 return upper_tri_to_symmetric(matrix) 252 253 254@nb.njit(fastmath=True) 255def rotate(tensor, rotation): 256 """Rotate 4-th order tensor using a 3x3 rotation matrix.""" 257 rotated_tensor = np.zeros((3, 3, 3, 3)) 258 for i in range(3): 259 for j in range(3): 260 for k in range(3): 261 for L in range(3): 262 for a in range(3): 263 for b in range(3): 264 for c in range(3): 265 for d in range(3): 266 rotated_tensor[i, j, k, L] += ( 267 rotation[i, a] 268 * rotation[j, b] 269 * rotation[k, c] 270 * rotation[L, d] 271 * tensor[a, b, c, d] 272 ) 273 return rotated_tensor
15@nb.njit(fastmath=True) 16def polar_decompose(matrix, left=True): 17 """Compute polar decomposition of M as either M = RU (right) or M = VP (left).""" 18 U, S, Vh = np.linalg.svd(matrix) 19 if left: 20 return U @ Vh, U @ (np.diag(S) @ U.transpose()) 21 U_matrix = Vh.transpose() @ (np.diag(S) @ Vh) 22 return matrix @ np.linalg.inv(U_matrix), U_matrix
Compute polar decomposition of M as either M = RU (right) or M = VP (left).
25@nb.njit(fastmath=True) 26def invariants_second_order(tensor): 27 """Calculate invariants of a second order tensor.""" 28 return ( 29 np.trace(tensor), 30 tensor[0, 0] * tensor[1, 1] 31 + tensor[1, 1] * tensor[2, 2] 32 + tensor[2, 2] * tensor[0, 0] 33 - tensor[0, 1] * tensor[1, 0] 34 - tensor[1, 2] * tensor[2, 1] 35 - tensor[2, 0] * tensor[0, 2], 36 np.linalg.det(tensor), 37 )
Calculate invariants of a second order tensor.
40@nb.njit(fastmath=True) 41def voigt_decompose(matrix: np.ndarray) -> tuple[np.ndarray, np.ndarray]: 42 """Decompose elastic tensor (as 6x6 Voigt matrix) into distinct contractions. 43 44 Return the only two independent contractions of the elastic tensor given as a 6x6 45 Voigt `matrix`. With reference to the full 4-th order elastic tensor, the 46 contractions are defined as: 47 - $d_{ij} = C_{ijkk}$ (dilatational stiffness tensor) 48 - $v_{ij} = C_{ijkj}$ (deviatoric stiffness tensor) 49 50 Any vector which is an eigenvector of both $d_{ij}$ and $v_{ij}$ is always normal to 51 a symmetry plane of the elastic medium. 52 53 See Equations 3.4 & 3.5 in [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 54 55 """ 56 # 1. Compose dᵢⱼ = Cᵢⱼₖₖ (dilatational stiffness tensor) 57 # Eq. 3.4 in Browaeys & Chevrot, 2004. 58 stiffness_dilat = np.empty((3, 3)) 59 for i in range(3): 60 stiffness_dilat[i, i] = matrix[:3, i].sum() 61 stiffness_dilat[0, 1] = stiffness_dilat[1, 0] = matrix[:3, 5].sum() 62 stiffness_dilat[0, 2] = stiffness_dilat[2, 0] = matrix[:3, 4].sum() 63 stiffness_dilat[1, 2] = stiffness_dilat[2, 1] = matrix[:3, 3].sum() 64 # 2. Compose vᵢⱼ = Cᵢⱼₖⱼ (deviatoric stiffness tensor) 65 # Eq. 3.5, Browaeys & Chevrot, 2004. 66 stiffness_deviat = np.empty((3, 3)) 67 stiffness_deviat[0, 0] = matrix[0, 0] + matrix[4, 4] + matrix[5, 5] 68 stiffness_deviat[1, 1] = matrix[1, 1] + matrix[3, 3] + matrix[5, 5] 69 stiffness_deviat[2, 2] = matrix[2, 2] + matrix[3, 3] + matrix[4, 4] 70 stiffness_deviat[0, 1] = matrix[0, 5] + matrix[1, 5] + matrix[3, 4] 71 stiffness_deviat[0, 2] = matrix[0, 4] + matrix[2, 4] + matrix[3, 5] 72 stiffness_deviat[1, 2] = matrix[1, 3] + matrix[2, 3] + matrix[4, 5] 73 stiffness_deviat = upper_tri_to_symmetric(stiffness_deviat) 74 return stiffness_dilat, stiffness_deviat
Decompose elastic tensor (as 6x6 Voigt matrix) into distinct contractions.
Return the only two independent contractions of the elastic tensor given as a 6x6
Voigt matrix
. With reference to the full 4-th order elastic tensor, the
contractions are defined as:
- $d_{ij} = C_{ijkk}$ (dilatational stiffness tensor)
- $v_{ij} = C_{ijkj}$ (deviatoric stiffness tensor)
Any vector which is an eigenvector of both $d_{ij}$ and $v_{ij}$ is always normal to a symmetry plane of the elastic medium.
See Equations 3.4 & 3.5 in Browaeys & Chevrot (2004).
77@nb.njit(fastmath=True) 78def mono_project(voigt_vector): 79 """Project 21-component `voigt_vector` onto monoclinic symmetry subspace. 80 81 Monoclinic symmetry is characterised by 13 independent elasticity components. 82 83 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 84 85 """ 86 out = voigt_vector.copy() 87 inds = (9, 10, 12, 13, 15, 16, 18, 19) 88 for i in inds: 89 out[i] = 0 90 return out
Project 21-component voigt_vector
onto monoclinic symmetry subspace.
Monoclinic symmetry is characterised by 13 independent elasticity components.
93@nb.njit(fastmath=True) 94def ortho_project(voigt_vector): 95 """Project 21-component `voigt_vector` onto orthorhombic symmetry subspace. 96 97 Orthorhombic symmetry is characterised by 9 independent elasticity components. 98 99 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 100 101 """ 102 out = voigt_vector.copy() 103 out[9:] = 0 104 return out
Project 21-component voigt_vector
onto orthorhombic symmetry subspace.
Orthorhombic symmetry is characterised by 9 independent elasticity components.
107@nb.njit(fastmath=True) 108def tetr_project(voigt_vector): 109 """Project 21-component `voigt_vector` onto tetragonal symmetry subspace. 110 111 Tetragonal symmetry is characterised by 6 independent elasticity components. 112 113 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 114 115 """ 116 out = ortho_project(voigt_vector) 117 for i, j in ((0, 1), (3, 4), (6, 7)): 118 for k in range(2): 119 out[i + k] = 0.5 * (voigt_vector[i] + voigt_vector[j]) 120 return out
Project 21-component voigt_vector
onto tetragonal symmetry subspace.
Tetragonal symmetry is characterised by 6 independent elasticity components.
123@nb.njit(fastmath=True) 124def hex_project(voigt_vector): 125 """Project 21-component `voigt_vector` onto hexagonal symmetry subspace. 126 127 Hexagonal symmetry (a.k.a. transverse isotropy) is characterised by 5 independent 128 elasticity components. 129 130 See [Browaeys & Chevrot (2004)](https://doi.org/10.1111/j.1365-246X.2004.02415.x). 131 132 """ 133 x = voigt_vector 134 out = np.zeros(21) 135 out[0] = out[1] = 3 / 8 * (x[0] + x[1]) + x[5] / 4 / np.sqrt(2) + x[8] / 4 136 out[2] = x[2] 137 out[3] = out[4] = (x[3] + x[4]) / 2 138 out[5] = (x[0] + x[1]) / 4 / np.sqrt(2) + 3 / 4 * x[5] - x[8] / 2 / np.sqrt(2) 139 out[6] = out[7] = (x[6] + x[7]) / 2 140 out[8] = (x[0] + x[1]) / 4 - x[5] / 2 / np.sqrt(2) + x[8] / 2 141 return out
Project 21-component voigt_vector
onto hexagonal symmetry subspace.
Hexagonal symmetry (a.k.a. transverse isotropy) is characterised by 5 independent elasticity components.
144@nb.njit(fastmath=True) 145def upper_tri_to_symmetric(arr): 146 """Create symmetric array using upper triangle of input array. 147 148 Examples: 149 150 >>> import numpy as np 151 >>> upper_tri_to_symmetric(np.array([ 152 ... [ 1., 2., 3., 4.], 153 ... [ 0., 5., 6., 7.], 154 ... [ 0., 0., 8., 9.], 155 ... [ 9., 0., 0., 10.] 156 ... ])) 157 array([[ 1., 2., 3., 4.], 158 [ 2., 5., 6., 7.], 159 [ 3., 6., 8., 9.], 160 [ 4., 7., 9., 10.]]) 161 162 """ 163 # <https://stackoverflow.com/questions/58718365/fast-way-to-convert-upper-triangular-matrix-into-symmetric-matrix> 164 upper_tri = np.triu(arr) 165 return np.where(upper_tri, upper_tri, upper_tri.transpose())
Create symmetric array using upper triangle of input array.
Examples:
>>> import numpy as np
>>> upper_tri_to_symmetric(np.array([
... [ 1., 2., 3., 4.],
... [ 0., 5., 6., 7.],
... [ 0., 0., 8., 9.],
... [ 9., 0., 0., 10.]
... ]))
array([[ 1., 2., 3., 4.],
[ 2., 5., 6., 7.],
[ 3., 6., 8., 9.],
[ 4., 7., 9., 10.]])
168@nb.njit(fastmath=True) 169def voigt_to_elastic_tensor(matrix): 170 """Create 4-th order elastic tensor from an equivalent Voigt matrix. 171 172 See also: `elastic_tensor_to_voigt`. 173 174 """ 175 tensor = np.empty((3, 3, 3, 3)) 176 for p in range(3): 177 for q in range(3): 178 delta_pq = 1 if p == q else 0 179 i = (p + 1) * delta_pq + (1 - delta_pq) * (7 - p - q) - 1 180 for r in range(3): 181 for s in range(3): 182 delta_rs = 1 if r == s else 0 183 j = (r + 1) * delta_rs + (1 - delta_rs) * (7 - r - s) - 1 184 tensor[p, q, r, s] = matrix[i, j] 185 return tensor
Create 4-th order elastic tensor from an equivalent Voigt matrix.
See also: elastic_tensor_to_voigt
.
188@nb.njit(fastmath=True) 189def elastic_tensor_to_voigt(tensor): 190 """Create a 6x6 Voigt matrix from an equivalent 4-th order elastic tensor.""" 191 matrix = np.zeros((6, 6)) 192 matrix_indices = np.zeros((6, 6)) 193 for p in range(3): 194 for q in range(3): 195 delta_pq = 1 if p == q else 0 196 i = (p + 1) * delta_pq + (1 - delta_pq) * (7 - p - q) - 1 197 for r in range(3): 198 for s in range(3): 199 delta_rs = 1 if r == s else 0 200 j = (r + 1) * delta_rs + (1 - delta_rs) * (7 - r - s) - 1 201 matrix[i, j] += tensor[p, q, r, s] 202 matrix_indices[i, j] += 1 203 matrix /= matrix_indices 204 return (matrix + matrix.transpose()) / 2
Create a 6x6 Voigt matrix from an equivalent 4-th order elastic tensor.
207@nb.njit(fastmath=True) 208def voigt_matrix_to_vector(matrix): 209 """Create the 21-component Voigt vector equivalent to the 6x6 Voigt matrix.""" 210 vector = np.zeros(21) 211 for i in range(3): 212 vector[i] = matrix[i, i] 213 vector[i + 3] = np.sqrt(2) * matrix[(i + 1) % 3, (i + 2) % 3] 214 vector[i + 6] = 2 * matrix[i + 3, i + 3] 215 vector[i + 9] = 2 * matrix[i, i + 3] 216 vector[i + 12] = 2 * matrix[(i + 2) % 3, i + 3] 217 vector[i + 15] = 2 * matrix[(i + 1) % 3, i + 3] 218 vector[i + 18] = 2 * np.sqrt(2) * matrix[(i + 1) % 3 + 3, (i + 2) % 3 + 3] 219 return vector
Create the 21-component Voigt vector equivalent to the 6x6 Voigt matrix.
222@nb.njit(fastmath=True) 223def voigt_vector_to_matrix(vector): 224 """Create the 6x6 matrix representation of the 21-component Voigt vector. 225 226 See also: `voigt_matrix_to_vector`. 227 228 """ 229 matrix = np.zeros((6, 6)) 230 for i in range(3): 231 matrix[i, i] = vector[i] 232 matrix[i + 3, i + 3] = 0.5 * vector[i + 6] 233 234 matrix[1, 2] = 1 / np.sqrt(2) * vector[3] 235 matrix[0, 2] = 1 / np.sqrt(2) * vector[4] 236 matrix[0, 1] = 1 / np.sqrt(2) * vector[5] 237 238 matrix[0, 3] = 0.5 * vector[9] 239 matrix[1, 4] = 0.5 * vector[10] 240 matrix[2, 5] = 0.5 * vector[11] 241 matrix[2, 3] = 0.5 * vector[12] 242 243 matrix[0, 4] = 0.5 * vector[13] 244 matrix[1, 5] = 0.5 * vector[14] 245 matrix[1, 3] = 0.5 * vector[15] 246 247 matrix[2][4] = 0.5 * vector[16] 248 matrix[0][5] = 0.5 * vector[17] 249 matrix[4][5] = 0.5 * 1 / np.sqrt(2) * vector[18] 250 matrix[3][5] = 0.5 * 1 / np.sqrt(2) * vector[19] 251 matrix[3][4] = 0.5 * 1 / np.sqrt(2) * vector[20] 252 return upper_tri_to_symmetric(matrix)
Create the 6x6 matrix representation of the 21-component Voigt vector.
See also: voigt_matrix_to_vector
.
255@nb.njit(fastmath=True) 256def rotate(tensor, rotation): 257 """Rotate 4-th order tensor using a 3x3 rotation matrix.""" 258 rotated_tensor = np.zeros((3, 3, 3, 3)) 259 for i in range(3): 260 for j in range(3): 261 for k in range(3): 262 for L in range(3): 263 for a in range(3): 264 for b in range(3): 265 for c in range(3): 266 for d in range(3): 267 rotated_tensor[i, j, k, L] += ( 268 rotation[i, a] 269 * rotation[j, b] 270 * rotation[k, c] 271 * rotation[L, d] 272 * tensor[a, b, c, d] 273 ) 274 return rotated_tensor
Rotate 4-th order tensor using a 3x3 rotation matrix.