1. Symmetric Stiffness Tensor and Voigt notation
1. Concepts
(1) Symmetric relations in
Voigt notation is a simple way to represent a symmetric tensor.
For a
0 -> (0,0)
1 -> (1,1)
2 -> (0,1) and (1,0)For
0 -> (0,0)
1 -> (1,1)
2 -> (2,2)
3 -> (1,2) and (2,1)
4 -> (0,2) and (2,0)
5 -> (0,1) and (1,0)Conventional sequence We often use
here.
For general formula for the number of Voigt indices can be calculated by
Note here we know from
where tensor rank is
(2) Symmetry of stiffness tensor
For elastic tensors
We have 2 minor symmetries :
And also under a strain-energy relation :
So a general anisotropic elastic material usually satisfy the minor and major symmetries :
We can use a symmetric
So by setting

which is 3x3 matrix (6 independent variable)
The sequence in picture is not same as conventional sequence, but valid for a
which is the sequence we later applied in the programming.
Why we often use the conventional sequence is because the consistency for 2D form :
(3) Common symmetry classes
| Material symmetry | Independent constants | Typical examples |
|---|---|---|
| Triclinic | 21 | General anisotropic crystal or composite |
| Monoclinic | 13 | Certain layered crystals and laminates |
| Orthotropic | 9 | Wood, woven composites, plywood |
| Transversely isotropic | 5 | Unidirectional fiber composites, graphite |
| Cubic | 3 | Silicon, copper, aluminum single crystals |
| Isotropic | 2 | Glass, isotropic polycrystals, random particulate composites |
| For the orthotropic material[2], An orthotropic material has three orthogonal symmetry planes. Since the symmetric plane yields |
A transversely isotropic material[3], with symmetry axis
Cubic symmetric materials :
For the isotropic materials, we further have
2. Transformation for Tensors and Voigt notations
(1) Engineering Strain vector
For strain with engineering strain notation, we should use :
This is because, the shear stress is
That is, when computing the stress, we should use the engineering strain vector to keep the expression consistent. So in the general Hook's Law[1:1][4], we have :
where
(2) Implementation
We can transfer the format of them using the following two functions :
def tensor_to_voigt(tensor, *, engineering_shear: bool = False):
r"""Return the Voigt vector of a symmetric tensor.
The component order is ``[xx, yy, xy]`` in 2-D and
``[xx, yy, zz, xy, xz, yz]`` in 3-D. Set ``engineering_shear`` to
``True`` to multiply shear entries by two, as required for engineering
strain vectors.
"""
dim = tensor.ufl_shape[0]
shear_scale = 2 if engineering_shear else 1
if dim == 2:
return ufl.as_vector(
(tensor[0, 0], tensor[1, 1], shear_scale * tensor[0, 1])
)
if dim == 3:
return ufl.as_vector(
(
tensor[0, 0],
tensor[1, 1],
tensor[2, 2],
shear_scale * tensor[0, 1],
shear_scale * tensor[0, 2],
shear_scale * tensor[1, 2],
)
)
raise ValueError("Voigt conversion supports only two- and three-dimensional tensors.")
def voigt_to_tensor(voigt, dim: int, *, engineering_shear: bool = False):
r"""Return the symmetric tensor associated with a Voigt vector.
The input component order is ``[xx, yy, xy]`` in 2-D and
``[xx, yy, zz, xy, xz, yz]`` in 3-D. Set ``engineering_shear`` to
``True`` when the input stores engineering shear entries, which are divided
by two before constructing the tensor.
"""
shear_scale = 0.5 if engineering_shear else 1
if dim == 2:
return ufl.as_matrix(
((voigt[0], shear_scale * voigt[2]),
(shear_scale * voigt[2], voigt[1]))
)
if dim == 3:
return ufl.as_matrix(
(
(voigt[0], shear_scale * voigt[3], shear_scale * voigt[4]),
(shear_scale * voigt[3], voigt[1], shear_scale * voigt[5]),
(shear_scale * voigt[4], shear_scale * voigt[5], voigt[2]),
)
)
raise ValueError("Voigt conversion supports only two- and three-dimensional tensors.")