# -*- coding: utf-8 -*-
"""
Created on Wed Apr 27 21:09:24 2022
@author: nicolas.christ@kit.edu
Tensor class for basic arithmetic operations. More information on tensor representation in Voigt and Mandel notations are given in [Brannon2018]_.
"""
import numpy as np
[docs]class Tensor:
"""
Tensor class to help with basic arithmetic operations on tensor space.
Attributes
----------
e1 : ndarray of shape (3,)
Vector 1 of orthonormalbasis of 1st order tensors.
e2 : ndarray of shape (3,)
Vector 2 of orthonormalbasis of 1st order tensors.
e3 : ndarray of shape (3,)
Vector 3 of orthonormalbasis of 1st order tensors.
B : ndarray of shape (3, 3, 6)
Orthonormalbasis of 4th order tensors in normalized Voigt notation.
"""
def __init__(self):
self.e1 = np.array([1, 0, 0])
self.e2 = np.array([0, 1, 0])
self.e3 = np.array([0, 0, 1])
# Orthonormalbasis 4th order tensor
self.B = np.zeros((3, 3, 6))
self.B[:, :, 0] = self._diade(self.e1, self.e1)
self.B[:, :, 1] = self._diade(self.e2, self.e2)
self.B[:, :, 2] = self._diade(self.e3, self.e3)
self.B[:, :, 3] = (
np.sqrt(2)
/ 2
* (self._diade(self.e2, self.e3) + self._diade(self.e3, self.e2))
)
self.B[:, :, 4] = (
np.sqrt(2)
/ 2
* (self._diade(self.e1, self.e3) + self._diade(self.e3, self.e1))
)
self.B[:, :, 5] = (
np.sqrt(2)
/ 2
* (self._diade(self.e1, self.e2) + self._diade(self.e2, self.e1))
)
[docs] def _diade(self, di, dj):
"""
Return diadic product of two directional vectors. This is used to
calculate the basis tensors in the normalized Voigt notation.
Parameters
----------
di : ndarray of shape (3,)
Directional vector #1.
dj : ndarray of shape (3,)
Directional vector #2.
Returns
-------
ndarray of shape (3, 3)
Tensor of 2nd order in tensor notation.
"""
return np.einsum("i,j->ij", di, dj)
[docs] def _diade4(self, bi, bj):
"""
Return diadic product of two tensors. This is used to transfer
stiffness tensors from normalized Voigt notation to regular tensor
notation.
Parameters
----------
bi : ndarray of shape (3, 3)
Orthonormal basis tensor #1.
bj : ndarray of shape (3, 3)
Orthonormal basis tensor #2.
Returns
-------
ndarray of shape (3, 3, 3, 3)
Tensor of 4th order in tensor notation.
"""
return np.einsum("ij,kl->ijkl", bi, bj)
[docs] def tensor_product(self, tensor_a, tensor_b):
"""
Return the mapping of one tensor of 4th order to another in the
normalized Voigt notation.
Parameters
----------
tensor_a : ndarray of shape (6, 6)
Tensor #1.
tensor_b : ndarray of shape (6, 6)
Tensor #2.
Returns
-------
ndarray of shape (6, 6)
Resulting mapping.
"""
return np.einsum("ij,jk->ik", tensor_a, tensor_b)
[docs] def matrix2voigt(self, matrix):
"""
Return the Voigt notation of a tensor of 2nd order
calculated from the regular tensor notation.
Parameters
----------
matrix : ndarray of shape (3, 3)
Tensor of 2nd order in regular tensor notation.
Returns
-------
ndarray of shape (6,)
Tensor in Voigt notation.
"""
return np.array(
[
matrix[0, 0],
matrix[1, 1],
matrix[2, 2],
matrix[1, 2],
matrix[0, 2],
matrix[0, 1],
]
)
[docs] def matrix2mandel(self, matrix):
"""
Return the normalized Voigt notation of a tensor of 2nd order
calculated from the regular tensor notation.
Parameters
----------
matrix : ndarray of shape (3, 3)
Tensor of 2nd order in regular tensor notation.
Returns
-------
ndarray of shape (6,)
Tensor in normalized Voigt notation.
"""
b = np.sqrt(2)
return np.array(
[
matrix[0, 0],
matrix[1, 1],
matrix[2, 2],
b * matrix[1, 2],
b * matrix[0, 2],
b * matrix[0, 1],
]
)
[docs] def tensor2mandel(self, tensor):
"""
Return the normalized Voigt (Mandel) notation of a tensor of 4th
order calculated fromthe regular tensor notation.
Parameters
----------
tensor : ndarray of shape (3, 3, 3, 3)
Tensor of 4th order in regular tensor notation.
Returns
-------
ndarray of shape (6, 6)
Tensor in normalized Voigt notation.
"""
b = np.sqrt(2)
g = tensor
return np.array(
[
[
g[0, 0, 0, 0],
g[0, 0, 1, 1],
g[0, 0, 2, 2],
b * g[0, 0, 1, 2],
b * g[0, 0, 0, 2],
b * g[0, 0, 0, 1],
],
[
g[1, 1, 0, 0],
g[1, 1, 1, 1],
g[1, 1, 2, 2],
b * g[1, 1, 1, 2],
b * g[1, 1, 0, 2],
b * g[1, 1, 0, 1],
],
[
g[2, 2, 0, 0],
g[2, 2, 1, 1],
g[2, 2, 2, 2],
b * g[2, 2, 1, 2],
b * g[2, 2, 0, 2],
b * g[2, 2, 0, 1],
],
[
b * g[1, 2, 0, 0],
b * g[1, 2, 1, 1],
b * g[1, 2, 2, 2],
2 * g[1, 2, 1, 2],
2 * g[1, 2, 0, 2],
2 * g[1, 2, 0, 1],
],
[
b * g[0, 2, 0, 0],
b * g[0, 2, 1, 1],
b * g[0, 2, 2, 2],
2 * g[0, 2, 1, 2],
2 * g[0, 2, 0, 2],
2 * g[0, 2, 0, 1],
],
[
b * g[0, 1, 0, 0],
b * g[0, 1, 1, 1],
b * g[0, 1, 2, 2],
2 * g[0, 1, 1, 2],
2 * g[0, 1, 0, 2],
2 * g[0, 1, 0, 1],
],
]
)
[docs] def mandel2tensor(self, mandel):
"""
Return the regular tensor notation of a tensor calculated from
the normalized Voigt (Mandel) notation.
Parameters
----------
mandel : ndarray of shape (6, 6)
Tensor of 4th order in normalized Voigt notation.
Returns
-------
tensor : ndarray of shape (3, 3, 3, 3)
Tensor in regular tensor notation.
"""
tensor = np.zeros((3, 3, 3, 3))
for i in range(0, 6):
for j in range(0, 6):
tensor += mandel[i, j] * self._diade4(self.B[:, :, i], self.B[:, :, j])
return tensor