Reference documentation for deal.II version Git 28ce845196 2019-06-26 10:31:03 +0200
symmetric_tensor.h File Reference
#include <deal.II/base/numbers.h>
#include <deal.II/base/table_indices.h>
#include <deal.II/base/template_constraints.h>
#include <deal.II/base/tensor.h>
#include <algorithm>
#include <array>
#include <functional>
Include dependency graph for symmetric_tensor.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

## Namespaces

internal

internal::SymmetricTensorImplementation

internal::SymmetricTensorAccessors

## Enumerations

enum  SymmetricTensorEigenvectorMethod { SymmetricTensorEigenvectorMethod::hybrid, SymmetricTensorEigenvectorMethod::ql_implicit_shifts, SymmetricTensorEigenvectorMethod::jacobi }

## Functions

template<int dim, typename Number >
SymmetricTensor< 2, dim, Number > unit_symmetric_tensor ()

template<int dim, typename Number >
SymmetricTensor< 4, dim, Number > deviator_tensor ()

template<int dim, typename Number >
SymmetricTensor< 4, dim, Number > identity_tensor ()

template<int dim, typename Number >
SymmetricTensor< 2, dim, Number > invert (const SymmetricTensor< 2, dim, Number > &)

template<int dim, typename Number >
SymmetricTensor< 4, dim, Number > invert (const SymmetricTensor< 4, dim, Number > &)

template<int dim, typename Number >
SymmetricTensor< 2, dim, Number > deviator (const SymmetricTensor< 2, dim, Number > &)

template<int dim, typename Number >
Number determinant (const SymmetricTensor< 2, dim, Number > &)

TableIndices< 2 > internal::SymmetricTensorAccessors::merge (const TableIndices< 2 > &previous_indices, const unsigned int new_index, const unsigned int position)

TableIndices< 4 > internal::SymmetricTensorAccessors::merge (const TableIndices< 4 > &previous_indices, const unsigned int new_index, const unsigned int position)

template<int rank_, int dim, typename Number , typename OtherNumber >
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+ (const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)

template<int rank_, int dim, typename Number , typename OtherNumber >
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator- (const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)

template<int rank_, int dim, typename Number , typename OtherNumber >
Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+ (const SymmetricTensor< rank_, dim, Number > &left, const Tensor< rank_, dim, OtherNumber > &right)

template<int rank_, int dim, typename Number , typename OtherNumber >
Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+ (const Tensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)

template<int rank_, int dim, typename Number , typename OtherNumber >
Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator- (const SymmetricTensor< rank_, dim, Number > &left, const Tensor< rank_, dim, OtherNumber > &right)

template<int rank_, int dim, typename Number , typename OtherNumber >
Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator- (const Tensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)

template<int dim, typename Number >
Number third_invariant (const SymmetricTensor< 2, dim, Number > &t)

template<int dim, typename Number >
Number trace (const SymmetricTensor< 2, dim, Number > &d)

template<int dim, typename Number >
Number first_invariant (const SymmetricTensor< 2, dim, Number > &t)

template<typename Number >
Number second_invariant (const SymmetricTensor< 2, 1, Number > &)

template<typename Number >
Number second_invariant (const SymmetricTensor< 2, 2, Number > &t)

template<typename Number >
Number second_invariant (const SymmetricTensor< 2, 3, Number > &t)

template<typename Number >
std::array< Number, 1 > eigenvalues (const SymmetricTensor< 2, 1, Number > &T)

template<typename Number >
std::array< Number, 2 > eigenvalues (const SymmetricTensor< 2, 2, Number > &T)

template<typename Number >
std::array< Number, 3 > eigenvalues (const SymmetricTensor< 2, 3, Number > &T)

template<int dim, typename Number >
void internal::SymmetricTensorImplementation::tridiagonalize (const ::SymmetricTensor< 2, dim, Number > &A, ::Tensor< 2, dim, Number > &Q, std::array< Number, dim > &d, std::array< Number, dim - 1 > &e)

template<int dim, typename Number >
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > internal::SymmetricTensorImplementation::ql_implicit_shifts (const ::SymmetricTensor< 2, dim, Number > &A)

template<int dim, typename Number >
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > internal::SymmetricTensorImplementation::jacobi (::SymmetricTensor< 2, dim, Number > A)

template<typename Number >
std::array< std::pair< Number, Tensor< 1, 2, Number > >, 2 > internal::SymmetricTensorImplementation::hybrid (const ::SymmetricTensor< 2, 2, Number > &A)

template<typename Number >
std::array< std::pair< Number, Tensor< 1, 3, Number > >, 3 > internal::SymmetricTensorImplementation::hybrid (const ::SymmetricTensor< 2, 3, Number > &A)

template<int dim, typename Number >
std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors (const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)

template<int rank_, int dim, typename Number >
SymmetricTensor< rank_, dim, Number > transpose (const SymmetricTensor< rank_, dim, Number > &t)

template<int dim>
SymmetricTensor< 2, dim > unit_symmetric_tensor ()

template<int dim>
SymmetricTensor< 4, dim > deviator_tensor ()

template<int dim>
SymmetricTensor< 4, dim > identity_tensor ()

template<int dim, typename Number >
SymmetricTensor< 4, dim, Number > outer_product (const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)

template<int dim, typename Number >
SymmetricTensor< 2, dim, Number > symmetrize (const Tensor< 2, dim, Number > &t)

template<int rank_, int dim, typename Number >
SymmetricTensor< rank_, dim, Number > operator* (const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)

template<int rank_, int dim, typename Number >
SymmetricTensor< rank_, dim, Number > operator* (const Number &factor, const SymmetricTensor< rank_, dim, Number > &t)

template<int rank_, int dim, typename Number , typename OtherNumber >
SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator* (const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)

template<int rank_, int dim, typename Number , typename OtherNumber >
SymmetricTensor< rank_, dim, typename ProductType< OtherNumber, typename EnableIfScalar< Number >::type >::type > operator* (const Number &factor, const SymmetricTensor< rank_, dim, OtherNumber > &t)

template<int rank_, int dim, typename Number , typename OtherNumber >
SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/ (const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)

template<int rank_, int dim>
SymmetricTensor< rank_, dim > operator* (const SymmetricTensor< rank_, dim > &t, const double factor)

template<int rank_, int dim>
SymmetricTensor< rank_, dim > operator* (const double factor, const SymmetricTensor< rank_, dim > &t)

template<int rank_, int dim>
SymmetricTensor< rank_, dim > operator/ (const SymmetricTensor< rank_, dim > &t, const double factor)

template<int dim, typename Number , typename OtherNumber >
ProductType< Number, OtherNumber >::type scalar_product (const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)

template<int dim, typename Number , typename OtherNumber >
ProductType< Number, OtherNumber >::type scalar_product (const SymmetricTensor< 2, dim, Number > &t1, const Tensor< 2, dim, OtherNumber > &t2)

template<int dim, typename Number , typename OtherNumber >
ProductType< Number, OtherNumber >::type scalar_product (const Tensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)

template<typename Number , typename OtherNumber >
void double_contract (SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 1, Number > &t, const SymmetricTensor< 2, 1, OtherNumber > &s)

template<typename Number , typename OtherNumber >
void double_contract (SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 2, 1, Number > &s, const SymmetricTensor< 4, 1, OtherNumber > &t)

template<typename Number , typename OtherNumber >
void double_contract (SymmetricTensor< 2, 2, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 2, Number > &t, const SymmetricTensor< 2, 2, OtherNumber > &s)

template<typename Number , typename OtherNumber >
void double_contract (SymmetricTensor< 2, 2, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 2, 2, Number > &s, const SymmetricTensor< 4, 2, OtherNumber > &t)

template<typename Number , typename OtherNumber >
void double_contract (SymmetricTensor< 2, 3, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 3, Number > &t, const SymmetricTensor< 2, 3, OtherNumber > &s)

template<typename Number , typename OtherNumber >
void double_contract (SymmetricTensor< 2, 3, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 2, 3, Number > &s, const SymmetricTensor< 4, 3, OtherNumber > &t)

template<int dim, typename Number , typename OtherNumber >
Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator* (const SymmetricTensor< 2, dim, Number > &src1, const Tensor< 1, dim, OtherNumber > &src2)

template<int dim, typename Number , typename OtherNumber >
Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator* (const Tensor< 1, dim, Number > &src1, const SymmetricTensor< 2, dim, OtherNumber > &src2)

template<int rank_1, int rank_2, int dim, typename Number , typename OtherNumber >
Tensor< rank_1+rank_2 - 2, dim, typename ProductType< Number, OtherNumber >::type >::tensor_type operator* (const Tensor< rank_1, dim, Number > &src1, const SymmetricTensor< rank_2, dim, OtherNumber > &src2s)

template<int rank_1, int rank_2, int dim, typename Number , typename OtherNumber >
Tensor< rank_1+rank_2 - 2, dim, typename ProductType< Number, OtherNumber >::type >::tensor_type operator* (const SymmetricTensor< rank_1, dim, Number > &src1s, const Tensor< rank_2, dim, OtherNumber > &src2)

template<int dim, typename Number >
std::ostream & operator<< (std::ostream &out, const SymmetricTensor< 2, dim, Number > &t)

template<int dim, typename Number >
std::ostream & operator<< (std::ostream &out, const SymmetricTensor< 4, dim, Number > &t)

## ◆ SymmetricTensorEigenvectorMethod

 strong

An enumeration for the algorithm to be employed when performing the computation of normalized eigenvectors and their corresponding eigenvalues by the eigenvalues() and eigenvectors() methods operating on SymmetricTensor objects.

The specialized algorithms utilized in computing the eigenvectors are presented in

@article{Kopp2008,
title = {Efficient numerical diagonalization of hermitian 3x3
matrices},
author = {Kopp, J.},
journal = {International Journal of Modern Physics C},
year = {2008},
volume = {19},
number = {3},
pages = {523--548},
doi = {10.1142/S0129183108012303},
eprinttype = {arXiv},
eprint = {physics/0610206v3},
eprintclass = {physics.comp-ph},
url =
{https://www.mpi-hd.mpg.de/personalhomes/globes/3x3/index.html}
}
Enumerator
hybrid

A hybrid approach that preferentially uses the characteristic equation to compute eigenvalues and an analytical approach based on the cross-product for the eigenvectors. If the computations are deemed too inaccurate then the method falls back to ql_implicit_shifts.

This method potentially offers the quickest computation if the pathological case is not encountered.

ql_implicit_shifts

The iterative QL algorithm with implicit shifts applied after tridiagonalization of the tensor using the householder method.

This method offers a compromise between speed of computation and its robustness. This method is particularly useful when the elements of $$T$$ have greatly varying magnitudes, which would typically lead to a loss of accuracy when computing the smaller eigenvalues.

jacobi

The iterative Jacobi algorithm.

This method offers is the most robust of the available options, with reliable results obtained for even the most pathological cases. It is, however, the slowest algorithm of all of those implemented.

Definition at line 3164 of file symmetric_tensor.h.

## ◆ unit_symmetric_tensor() [1/2]

template<int dim, typename Number >
 SymmetricTensor< 2, dim, Number > unit_symmetric_tensor ( )
inline

Return a unit symmetric tensor of rank 2, i.e., the dim-by-dim identity matrix.

Definition at line 3288 of file symmetric_tensor.h.

## ◆ deviator_tensor() [1/2]

template<int dim, typename Number >
 SymmetricTensor< 4, dim, Number > deviator_tensor ( )
inline

Return the tensor of rank 4 that, when multiplied by a symmetric rank 2 tensor t returns the deviator $$\textrm{dev}\ t$$. It is the operator representation of the linear deviator operator.

For every tensor t, there holds the identity deviator(t)==deviator_tensor<dim>()*t, up to numerical round-off. The reason this operator representation is provided is that one sometimes needs to invert operators like identity_tensor<dim>() + delta_t*deviator_tensor<dim>() or similar.

Definition at line 3346 of file symmetric_tensor.h.

## ◆ identity_tensor() [1/2]

template<int dim, typename Number >
 SymmetricTensor< 4, dim, Number > identity_tensor ( )
inline

Return the fourth-order symmetric identity tensor which maps symmetric second-order tensors to themselves.

Note that this tensor, even though it is the identity, has a somewhat funny form, and in particular does not only consist of zeros and ones. For example, for dim=2, the identity tensor has all zero entries except for id[0][0][0][0]=id[1][1][1][1]=1 and id[0][1][0][1]=id[0][1][1][0]=id[1][0][0][1]=id[1][0][1][0]=1/2. To see why this factor of 1/2 is necessary, consider computing A=Id : B. For the element a_01 we have a_01=id_0100 b_00 + id_0111 b_11 + id_0101 b_01 + id_0110 b_10. On the other hand, we need to have a_01=b_01, and symmetry implies b_01=b_10, leading to a_01=(id_0101+id_0110) b_01, or, again by symmetry, id_0101=id_0110=1/2. Similar considerations hold for the three- dimensional case.

This issue is also explained in the introduction to step-44.

Definition at line 3418 of file symmetric_tensor.h.

## ◆ invert() [1/2]

template<int dim, typename Number >
 SymmetricTensor< 2, dim, Number > invert ( const SymmetricTensor< 2, dim, Number > & t )
inline

Invert a symmetric rank-2 tensor.

Note
If a tensor is not invertible, then the result is unspecified, but will likely contain the results of a division by zero or a very small number at the very least.

Definition at line 3484 of file symmetric_tensor.h.

## ◆ invert() [2/2]

template<int dim, typename Number >
 SymmetricTensor< 4, dim, Number > invert ( const SymmetricTensor< 4, dim, Number > & t )
inline

Invert a symmetric rank-4 tensor. Since symmetric rank-4 tensors are mappings from and to symmetric rank-2 tensors, they can have an inverse.

If a tensor is not invertible, then the result is unspecified, but will likely contain the results of a division by zero or a very small number at the very least.

Definition at line 3505 of file symmetric_tensor.h.

## ◆ deviator()

template<int dim, typename Number >
 SymmetricTensor< 2, dim, Number > deviator ( const SymmetricTensor< 2, dim, Number > & t )
inline

Compute the deviator of a symmetric tensor, which is defined as dev[s] = s - 1/dim*tr[s]*I, where I is the identity operator. This quantity equals the original tensor minus its contractive or dilative component and refers to the shear in, for example, elasticity.

Definition at line 3265 of file symmetric_tensor.h.

## ◆ determinant()

template<int dim, typename Number >
 Number determinant ( const SymmetricTensor< 2, dim, Number > & t )
inline

Compute the determinant of a tensor or rank 2. The determinant is also commonly referred to as the third invariant of rank-2 tensors.

For a one-dimensional tensor, the determinant equals the only element and is therefore equivalent to the trace.

For greater notational simplicity, there is also a third_invariant function that returns the determinant of a tensor.

Definition at line 2688 of file symmetric_tensor.h.

## ◆ operator+() [1/3]

template<int rank_, int dim, typename Number , typename OtherNumber >
 SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+ ( const SymmetricTensor< rank_, dim, Number > & left, const SymmetricTensor< rank_, dim, OtherNumber > & right )
inline

Addition of two symmetric tensors of equal rank. The result is another SymmetricTensor that has a number type that is compatible with the operation.

If possible (e.g. when Number and OtherNumber are of the same type, or if the result of Number() + OtherNumber() is another Number), you should use operator += instead since this does not require the creation of a temporary variable.

Definition at line 2572 of file symmetric_tensor.h.

## ◆ operator-() [1/3]

template<int rank_, int dim, typename Number , typename OtherNumber >
 SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator- ( const SymmetricTensor< rank_, dim, Number > & left, const SymmetricTensor< rank_, dim, OtherNumber > & right )
inline

Subtraction of two symmetric tensors of equal rank. The result is another SymmetricTensor that has a number type that is compatible with the operation.

If possible (e.g. when Number and OtherNumber are of the same type, or if the result of Number() + OtherNumber() is another Number), you should use operator += instead since this does not require the creation of a temporary variable.

Definition at line 2598 of file symmetric_tensor.h.

## ◆ operator+() [2/3]

template<int rank_, int dim, typename Number , typename OtherNumber >
 Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+ ( const SymmetricTensor< rank_, dim, Number > & left, const Tensor< rank_, dim, OtherNumber > & right )
inline

Addition of a SymmetricTensor and a general Tensor of equal rank. The result is a general Tensor that has a number type that is compatible with the operation.

Definition at line 2617 of file symmetric_tensor.h.

## ◆ operator+() [3/3]

template<int rank_, int dim, typename Number , typename OtherNumber >
 Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+ ( const Tensor< rank_, dim, Number > & left, const SymmetricTensor< rank_, dim, OtherNumber > & right )
inline

Addition of a general Tensor with a SymmetricTensor of equal rank. The result is a general Tensor that has a number type that is compatible with the operation.

Definition at line 2633 of file symmetric_tensor.h.

## ◆ operator-() [2/3]

template<int rank_, int dim, typename Number , typename OtherNumber >
 Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator- ( const SymmetricTensor< rank_, dim, Number > & left, const Tensor< rank_, dim, OtherNumber > & right )
inline

Subtraction of a general Tensor from a SymmetricTensor of equal rank. The result is a general Tensor that has a number type that is compatible with the operation.

Definition at line 2649 of file symmetric_tensor.h.

## ◆ operator-() [3/3]

template<int rank_, int dim, typename Number , typename OtherNumber >
 Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator- ( const Tensor< rank_, dim, Number > & left, const SymmetricTensor< rank_, dim, OtherNumber > & right )
inline

Subtraction of a SymmetricTensor from a general Tensor of equal rank. The result is a general Tensor that has a number type that is compatible with the operation.

Definition at line 2665 of file symmetric_tensor.h.

## ◆ third_invariant()

template<int dim, typename Number >
 Number third_invariant ( const SymmetricTensor< 2, dim, Number > & t )
inline

Compute the determinant of a tensor or rank 2. This function therefore computes the same value as the determinant() functions and is only provided for greater notational simplicity (since there are also functions first_invariant() and second_invariant()).

Definition at line 2726 of file symmetric_tensor.h.

## ◆ trace()

template<int dim, typename Number >
 Number trace ( const SymmetricTensor< 2, dim, Number > & d )

Compute and return the trace of a tensor of rank 2, i.e. the sum of its diagonal entries. The trace is the first invariant of a rank-2 tensor.

Definition at line 2742 of file symmetric_tensor.h.

## ◆ first_invariant()

template<int dim, typename Number >
 Number first_invariant ( const SymmetricTensor< 2, dim, Number > & t )
inline

Compute the trace of a tensor or rank 2. This function therefore computes the same value as the trace() functions and is only provided for greater notational simplicity (since there are also functions second_invariant() and third_invariant()).

Definition at line 2762 of file symmetric_tensor.h.

## ◆ second_invariant() [1/3]

template<typename Number >
 Number second_invariant ( const SymmetricTensor< 2, 1, Number > & )
inline

Compute the second invariant of a tensor of rank 2. The second invariant of a tensor $$\sigma$$ is defined as $$II(\sigma) = \frac 12 \left[ (\text{trace}\ \sigma)^2 -\text{trace}\ (\sigma^2) \right]$$.

For the kind of arguments to this function, i.e., a rank-2 tensor of size 1, the result is simply zero.

Definition at line 2782 of file symmetric_tensor.h.

## ◆ second_invariant() [2/3]

template<typename Number >
 Number second_invariant ( const SymmetricTensor< 2, 2, Number > & t )
inline

Compute the second invariant of a tensor of rank 2. The second invariant of a tensor $$\sigma$$ is defined as $$II(\sigma) = \frac 12 \left[ (\text{trace}\ \sigma)^2 -\text{trace}\ (\sigma^2) \right]$$.

For the kind of arguments to this function, i.e., a rank-2 tensor of size 2, the result is (counting indices starting at one) $$II(\sigma) = \frac 12 \left[ (\sigma_{11} + \sigma_{22})^2 -(\sigma_{11}^2+2\sigma_{12}^2+\sigma_{22}^2) \right] = \sigma_{11}\sigma_{22} - \sigma_{12}^2$$. As expected, for the $$2\times 2$$ symmetric tensors this function handles, this equals the determinant of the tensor. (This is so because for $$2\times 2$$ symmetric tensors, there really are only two invariants, so the second and third invariant are the same; the determinant is the third invariant.)

Definition at line 2810 of file symmetric_tensor.h.

## ◆ second_invariant() [3/3]

template<typename Number >
 Number second_invariant ( const SymmetricTensor< 2, 3, Number > & t )
inline

Compute the second invariant of a tensor of rank 2. The second invariant of a tensor $$\sigma$$ is defined as $$II(\sigma) = \frac 12 \left[ (\text{trace}\ \sigma)^2 -\text{trace}\ (\sigma^2) \right]$$.

Definition at line 2828 of file symmetric_tensor.h.

## ◆ eigenvalues() [1/3]

template<typename Number >
 std::array< Number, 1 > eigenvalues ( const SymmetricTensor< 2, 1, Number > & T )

Return the eigenvalues of a symmetric 1x1 tensor of rank 2. The (single) entry of the tensor is, of course, equal to the (single) eigenvalue.

## ◆ eigenvalues() [2/3]

template<typename Number >
 std::array< Number, 2 > eigenvalues ( const SymmetricTensor< 2, 2, Number > & T )

Return the eigenvalues of a symmetric 2x2 tensor of rank 2. The array of eigenvalues is sorted in descending order.

For 2x2 tensors, the eigenvalues of tensor $$T$$ are the roots of the characteristic polynomial $$0 = \lambda^{2} - \lambda\textrm{tr}(T) + \textrm{det}(T)$$ as given by $$\lambda = \frac{\textrm{tr}(T) \pm \sqrt{[\textrm{tr}(T)]^{2} - 4\textrm{det}(T)}}{2}$$.

Warning
The algorithm employed here determines the eigenvalues by computing the roots of the characteristic polynomial. In the case that there exists a common root (the eigenvalues are equal), the computation is subject to round-off errors of order $$\sqrt{\epsilon}$$. As an alternative, the eigenvectors() function provides a more robust, but costly, method to compute the eigenvalues of a symmetric tensor.

## ◆ eigenvalues() [3/3]

template<typename Number >
 std::array< Number, 3 > eigenvalues ( const SymmetricTensor< 2, 3, Number > & T )

Return the eigenvalues of a symmetric 3x3 tensor of rank 2. The array of eigenvalues is sorted in descending order.

For 3x3 tensors, the eigenvalues of tensor $$T$$ are the roots of the characteristic polynomial $$0 = \lambda^{3} - \lambda^{2}\textrm{tr}(T) - \frac{1}{2} \lambda (\textrm{tr}(T^{2}) - [\textrm{tr}(T)]^{2}) - \textrm{det}(T)$$.

Warning
The algorithm employed here determines the eigenvalues by computing the roots of the characteristic polynomial. In the case that there exists a common root (the eigenvalues are equal), the computation is subject to round-off errors of order $$\sqrt{\epsilon}$$. As an alternative, the eigenvectors() function provides a more robust, but costly, method to compute the eigenvalues of a symmetric tensor.

## ◆ eigenvectors()

template<int dim, typename Number >
 std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors ( const SymmetricTensor< 2, dim, Number > & T, const SymmetricTensorEigenvectorMethod method = SymmetricTensorEigenvectorMethod::ql_implicit_shifts )

Return the eigenvalues and eigenvectors of a real-valued rank-2 symmetric tensor $$T$$. The array of matched eigenvalue and eigenvector pairs is sorted in descending order (determined by the eigenvalues).

The specialized algorithms utilized in computing the eigenvectors are presented in

@article{Kopp2008,
title = {Efficient numerical diagonalization of hermitian 3x3
matrices},
author = {Kopp, J.},
journal = {International Journal of Modern Physics C},
year = {2008},
volume = {19},
number = {3},
pages = {523--548},
doi = {10.1142/S0129183108012303},
eprinttype = {arXiv},
eprint = {physics/0610206v3},
eprintclass = {physics.comp-ph},
url =
{https://www.mpi-hd.mpg.de/personalhomes/globes/3x3/index.html}
}

## ◆ transpose()

template<int rank_, int dim, typename Number >
 SymmetricTensor< rank_, dim, Number > transpose ( const SymmetricTensor< rank_, dim, Number > & t )
inline

Return the transpose of the given symmetric tensor. Since we are working with symmetric objects, the transpose is of course the same as the original tensor. This function mainly exists for compatibility with the Tensor class.

Definition at line 3247 of file symmetric_tensor.h.

## ◆ unit_symmetric_tensor() [2/2]

template<int dim>
 SymmetricTensor< 2, dim > unit_symmetric_tensor ( )
inline

Return a unit symmetric tensor of rank 2, i.e., the dim-by-dim identity matrix. This specialization of the function uses double as the data type for the elements.

Definition at line 3323 of file symmetric_tensor.h.

## ◆ deviator_tensor() [2/2]

template<int dim>
 SymmetricTensor< 4, dim > deviator_tensor ( )
inline

Return the tensor of rank 4 that, when multiplied by a symmetric rank 2 tensor t returns the deviator dev t. It is the operator representation of the linear deviator operator.

For every tensor t, there holds the identity deviator(t)==deviator_tensor<dim>()*t, up to numerical round-off. The reason this operator representation is provided is that one sometimes needs to invert operators like identity_tensor<dim>() + delta_t*deviator_tensor<dim>() or similar.

Definition at line 3387 of file symmetric_tensor.h.

## ◆ identity_tensor() [2/2]

template<int dim>
 SymmetricTensor< 4, dim > identity_tensor ( )
inline

Return the tensor of rank 4 that, when multiplied by a symmetric rank 2 tensor t returns the deviator dev t. It is the operator representation of the linear deviator operator.

Note that this tensor, even though it is the identity, has a somewhat funny form, and in particular does not only consist of zeros and ones. For example, for dim=2, the identity tensor has all zero entries except for id[0][0][0][0]=id[1][1][1][1]=1 and id[0][1][0][1]=id[0][1][1][0]=id[1][0][0][1]=id[1][0][1][0]=1/2. To see why this factor of 1/2 is necessary, consider computing A=Id . B. For the element a_01 we have a_01=id_0100 b_00 + id_0111 b_11 + id_0101 b_01 + id_0110 b_10. On the other hand, we need to have a_01=b_01, and symmetry implies b_01=b_10, leading to a_01=(id_0101+id_0110) b_01, or, again by symmetry, id_0101=id_0110=1/2. Similar considerations hold for the three- dimensional case.

Definition at line 3465 of file symmetric_tensor.h.

## ◆ outer_product()

template<int dim, typename Number >
 SymmetricTensor< 4, dim, Number > outer_product ( const SymmetricTensor< 2, dim, Number > & t1, const SymmetricTensor< 2, dim, Number > & t2 )
inline

Return the tensor of rank 4 that is the outer product of the two tensors given as arguments, i.e. the result $$T=t1 \otimes t2$$ satisfies T phi = t1 (t2 : phi) for all symmetric tensors phi.

For example, the deviator tensor can be computed as identity_tensor<dim,Number>() - 1/d*outer_product(unit_symmetric_tensor<dim,Number>(), unit_symmetric_tensor<dim,Number>()), since the (double) contraction with the unit tensor yields the trace of a symmetric tensor.

Definition at line 3529 of file symmetric_tensor.h.

## ◆ symmetrize()

template<int dim, typename Number >
 SymmetricTensor< 2, dim, Number > symmetrize ( const Tensor< 2, dim, Number > & t )
inline

Return the symmetrized version of a full rank-2 tensor, i.e. (t+transpose(t))/2, as a symmetric rank-2 tensor. This is the version for general dimensions.

Definition at line 3556 of file symmetric_tensor.h.

## ◆ operator*() [1/10]

template<int rank_, int dim, typename Number >
 SymmetricTensor< rank_, dim, Number > operator* ( const SymmetricTensor< rank_, dim, Number > & t, const Number & factor )
inline

Multiplication of a symmetric tensor of general rank with a scalar from the right. This version of the operator is used if the scalar has the same data type as is used to store the elements of the symmetric tensor.

Definition at line 3578 of file symmetric_tensor.h.

## ◆ operator*() [2/10]

template<int rank_, int dim, typename Number >
 SymmetricTensor< rank_, dim, Number > operator* ( const Number & factor, const SymmetricTensor< rank_, dim, Number > & t )
inline

Multiplication of a symmetric tensor of general rank with a scalar from the left. This version of the operator is used if the scalar has the same data type as is used to store the elements of the symmetric tensor.

Definition at line 3596 of file symmetric_tensor.h.

## ◆ operator*() [3/10]

template<int rank_, int dim, typename Number , typename OtherNumber >
 SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator* ( const SymmetricTensor< rank_, dim, Number > & t, const OtherNumber & factor )
inline

Multiplication of a symmetric tensor with a scalar number from the right.

The purpose of this operator is to enable only multiplication of a tensor by a scalar number (i.e., a floating point number, a complex floating point number, etc.). The function is written in a way that only allows the compiler to consider the function if the second argument is indeed a scalar number – in other words, OtherNumber will not match, for example std::vector<double> as the product of a tensor and a vector clearly would make no sense. The mechanism by which the compiler is prohibited of considering this operator for multiplication with non-scalar types are explained in the documentation of the EnableIfScalar class.

The return type of the function is chosen so that it matches the types of both the tensor and the scalar argument. For example, if you multiply a SymmetricTensor<2,dim,double> by std::complex<double>, then the result will be a SymmetricTensor<2,dim,std::complex<double>>. In other words, the type with which the returned tensor stores its components equals the type you would get if you multiplied an individual component of the input tensor by the scalar factor.

Definition at line 3635 of file symmetric_tensor.h.

## ◆ operator*() [4/10]

template<int rank_, int dim, typename Number , typename OtherNumber >
 SymmetricTensor< rank_, dim, typename ProductType< OtherNumber, typename EnableIfScalar< Number >::type >::type > operator* ( const Number & factor, const SymmetricTensor< rank_, dim, OtherNumber > & t )
inline

Multiplication of a symmetric tensor with a scalar number from the left. See the discussion with the operator with switched arguments for more information about template arguments and the return type.

Definition at line 3674 of file symmetric_tensor.h.

## ◆ operator/() [1/2]

template<int rank_, int dim, typename Number , typename OtherNumber >
 SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/ ( const SymmetricTensor< rank_, dim, Number > & t, const OtherNumber & factor )
inline

Division of a symmetric tensor of general rank by a scalar.

Definition at line 3694 of file symmetric_tensor.h.

## ◆ operator*() [5/10]

template<int rank_, int dim>
 SymmetricTensor< rank_, dim > operator* ( const SymmetricTensor< rank_, dim > & t, const double factor )
inline

Multiplication of a symmetric tensor of general rank with a scalar from the right.

Definition at line 3713 of file symmetric_tensor.h.

## ◆ operator*() [6/10]

template<int rank_, int dim>
 SymmetricTensor< rank_, dim > operator* ( const double factor, const SymmetricTensor< rank_, dim > & t )
inline

Multiplication of a symmetric tensor of general rank with a scalar from the left.

Definition at line 3730 of file symmetric_tensor.h.

## ◆ operator/() [2/2]

template<int rank_, int dim>
 SymmetricTensor< rank_, dim > operator/ ( const SymmetricTensor< rank_, dim > & t, const double factor )
inline

Division of a symmetric tensor of general rank by a scalar.

Definition at line 3746 of file symmetric_tensor.h.

## ◆ scalar_product() [1/3]

template<int dim, typename Number , typename OtherNumber >
 ProductType< Number, OtherNumber >::type scalar_product ( const SymmetricTensor< 2, dim, Number > & t1, const SymmetricTensor< 2, dim, OtherNumber > & t2 )
inline

Compute the scalar product $$a:b=\sum_{i,j} a_{ij}b_{ij}$$ between two tensors $$a,b$$ of rank 2. In the current case where both arguments are symmetric tensors, this is equivalent to calling the expression t1*t2 which uses the overloaded operator* between two symmetric tensors of rank 2.

Definition at line 3764 of file symmetric_tensor.h.

## ◆ scalar_product() [2/3]

template<int dim, typename Number , typename OtherNumber >
 ProductType< Number, OtherNumber >::type scalar_product ( const SymmetricTensor< 2, dim, Number > & t1, const Tensor< 2, dim, OtherNumber > & t2 )
inline

Compute the scalar product $$a:b=\sum_{i,j} a_{ij}b_{ij}$$ between two tensors $$a,b$$ of rank 2. We don't use operator* for this operation since the product between two tensors is usually assumed to be the contraction over the last index of the first tensor and the first index of the second tensor, for example $$(a\cdot b)_{ij}=\sum_k a_{ik}b_{kj}$$.

Definition at line 3782 of file symmetric_tensor.h.

## ◆ scalar_product() [3/3]

template<int dim, typename Number , typename OtherNumber >
 ProductType< Number, OtherNumber >::type scalar_product ( const Tensor< 2, dim, Number > & t1, const SymmetricTensor< 2, dim, OtherNumber > & t2 )
inline

Compute the scalar product $$a:b=\sum_{i,j} a_{ij}b_{ij}$$ between two tensors $$a,b$$ of rank 2. We don't use operator* for this operation since the product between two tensors is usually assumed to be the contraction over the last index of the first tensor and the first index of the second tensor, for example $$(a\cdot b)_{ij}=\sum_k a_{ik}b_{kj}$$.

Definition at line 3805 of file symmetric_tensor.h.

## ◆ double_contract() [1/6]

template<typename Number , typename OtherNumber >
 void double_contract ( SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > & tmp, const SymmetricTensor< 4, 1, Number > & t, const SymmetricTensor< 2, 1, OtherNumber > & s )
inline

Double contraction between a rank-4 and a rank-2 symmetric tensor, resulting in the symmetric tensor of rank 2 that is given as first argument to this function. This operation is the symmetric tensor analogon of a matrix-vector multiplication.

This function does the same as the member operator* of the SymmetricTensor class. It should not be used, however, since the member operator has knowledge of the actual data storage format and is at least 2 orders of magnitude faster. This function mostly exists for compatibility purposes with the general tensor class.

Definition at line 3828 of file symmetric_tensor.h.

## ◆ double_contract() [2/6]

template<typename Number , typename OtherNumber >
 void double_contract ( SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > & tmp, const SymmetricTensor< 2, 1, Number > & s, const SymmetricTensor< 4, 1, OtherNumber > & t )
inline

Double contraction between a rank-4 and a rank-2 symmetric tensor, resulting in the symmetric tensor of rank 2 that is given as first argument to this function. This operation is the symmetric tensor analogon of a matrix-vector multiplication.

This function does the same as the member operator* of the SymmetricTensor class. It should not be used, however, since the member operator has knowledge of the actual data storage format and is at least 2 orders of magnitude faster. This function mostly exists for compatibility purposes with the general tensor class.

Definition at line 3854 of file symmetric_tensor.h.

## ◆ double_contract() [3/6]

template<typename Number , typename OtherNumber >
 void double_contract ( SymmetricTensor< 2, 2, typename ProductType< Number, OtherNumber >::type > & tmp, const SymmetricTensor< 4, 2, Number > & t, const SymmetricTensor< 2, 2, OtherNumber > & s )
inline

Double contraction between a rank-4 and a rank-2 symmetric tensor, resulting in the symmetric tensor of rank 2 that is given as first argument to this function. This operation is the symmetric tensor analogon of a matrix-vector multiplication.

This function does the same as the member operator* of the SymmetricTensor class. It should not be used, however, since the member operator has knowledge of the actual data storage format and is at least 2 orders of magnitude faster. This function mostly exists for compatibility purposes with the general tensor class.

Definition at line 3879 of file symmetric_tensor.h.

## ◆ double_contract() [4/6]

template<typename Number , typename OtherNumber >
 void double_contract ( SymmetricTensor< 2, 2, typename ProductType< Number, OtherNumber >::type > & tmp, const SymmetricTensor< 2, 2, Number > & s, const SymmetricTensor< 4, 2, OtherNumber > & t )
inline

Double contraction between a rank-4 and a rank-2 symmetric tensor, resulting in the symmetric tensor of rank 2 that is given as first argument to this function. This operation is the symmetric tensor analogon of a matrix-vector multiplication.

This function does the same as the member operator* of the SymmetricTensor class. It should not be used, however, since the member operator has knowledge of the actual data storage format and is at least 2 orders of magnitude faster. This function mostly exists for compatibility purposes with the general tensor class.

Definition at line 3910 of file symmetric_tensor.h.

## ◆ double_contract() [5/6]

template<typename Number , typename OtherNumber >
 void double_contract ( SymmetricTensor< 2, 3, typename ProductType< Number, OtherNumber >::type > & tmp, const SymmetricTensor< 4, 3, Number > & t, const SymmetricTensor< 2, 3, OtherNumber > & s )
inline

Double contraction between a rank-4 and a rank-2 symmetric tensor, resulting in the symmetric tensor of rank 2 that is given as first argument to this function. This operation is the symmetric tensor analogon of a matrix-vector multiplication.

This function does the same as the member operator* of the SymmetricTensor class. It should not be used, however, since the member operator has knowledge of the actual data storage format and is at least 2 orders of magnitude faster. This function mostly exists for compatibility purposes with the general tensor class.

Definition at line 3941 of file symmetric_tensor.h.

## ◆ double_contract() [6/6]

template<typename Number , typename OtherNumber >
 void double_contract ( SymmetricTensor< 2, 3, typename ProductType< Number, OtherNumber >::type > & tmp, const SymmetricTensor< 2, 3, Number > & s, const SymmetricTensor< 4, 3, OtherNumber > & t )
inline

Double contraction between a rank-4 and a rank-2 symmetric tensor, resulting in the symmetric tensor of rank 2 that is given as first argument to this function. This operation is the symmetric tensor analogon of a matrix-vector multiplication.

This function does the same as the member operator* of the SymmetricTensor class. It should not be used, however, since the member operator has knowledge of the actual data storage format and is at least 2 orders of magnitude faster. This function mostly exists for compatibility purposes with the general tensor class.

Definition at line 3973 of file symmetric_tensor.h.

## ◆ operator*() [7/10]

template<int dim, typename Number , typename OtherNumber >
 Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator* ( const SymmetricTensor< 2, dim, Number > & src1, const Tensor< 1, dim, OtherNumber > & src2 )

Multiply a symmetric rank-2 tensor (i.e., a matrix) by a rank-1 tensor (i.e., a vector). The result is a rank-1 tensor (i.e., a vector).

Definition at line 3998 of file symmetric_tensor.h.

## ◆ operator*() [8/10]

template<int dim, typename Number , typename OtherNumber >
 Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator* ( const Tensor< 1, dim, Number > & src1, const SymmetricTensor< 2, dim, OtherNumber > & src2 )

Multiply a rank-1 tensor (i.e., a vector) by a symmetric rank-2 tensor (i.e., a matrix). The result is a rank-1 tensor (i.e., a vector).

Definition at line 4018 of file symmetric_tensor.h.

## ◆ operator*() [9/10]

template<int rank_1, int rank_2, int dim, typename Number , typename OtherNumber >
 Tensor< rank_1+rank_2 - 2, dim, typename ProductType< Number, OtherNumber >::type >::tensor_type operator* ( const Tensor< rank_1, dim, Number > & src1, const SymmetricTensor< rank_2, dim, OtherNumber > & src2s )
inline

The dot product (single contraction) for tensors: Return a tensor of rank $$(\text{rank}_1 + \text{rank}_2 - 2)$$ that is the contraction of the last index of a tensor src1 of rank rank_1 with the first index of a tensor src2 of rank rank_2:

$\text{result}_{i_1,\ldots,i_{r1},j_1,\ldots,j_{r2}} = \sum_{k} \text{left}_{i_1,\ldots,i_{r1}, k} \text{right}_{k, j_1,\ldots,j_{r2}}$

Note
As one operand is a Tensor, the multiplication operator only performs a contraction over a single pair of indices. This is in contrast to the multiplication operator for SymmetricTensor, which does the double contraction.

Definition at line 4056 of file symmetric_tensor.h.

## ◆ operator*() [10/10]

template<int rank_1, int rank_2, int dim, typename Number , typename OtherNumber >
 Tensor< rank_1+rank_2 - 2, dim, typename ProductType< Number, OtherNumber >::type >::tensor_type operator* ( const SymmetricTensor< rank_1, dim, Number > & src1s, const Tensor< rank_2, dim, OtherNumber > & src2 )
inline

The dot product (single contraction) for tensors: Return a tensor of rank $$(\text{rank}_1 + \text{rank}_2 - 2)$$ that is the contraction of the last index of a tensor src1 of rank rank_1 with the first index of a tensor src2 of rank rank_2:

$\text{result}_{i_1,\ldots,i_{r1},j_1,\ldots,j_{r2}} = \sum_{k} \text{left}_{i_1,\ldots,i_{r1}, k} \text{right}_{k, j_1,\ldots,j_{r2}}$

Note
As one operand is a Tensor, the multiplication operator only performs a contraction over a single pair of indices. This is in contrast to the multiplication operator for SymmetricTensor, which does the double contraction.

Definition at line 4094 of file symmetric_tensor.h.

## ◆ operator<<() [1/2]

template<int dim, typename Number >
 std::ostream & operator<< ( std::ostream & out, const SymmetricTensor< 2, dim, Number > & t )
inline

Output operator for symmetric tensors of rank 2. Print the elements consecutively, with a space in between, two spaces between rank 1 subtensors, three between rank 2 and so on. No special amends are made to represents the symmetry in the output, for example by outputting only the unique entries.

Definition at line 4114 of file symmetric_tensor.h.

## ◆ operator<<() [2/2]

template<int dim, typename Number >
 std::ostream & operator<< ( std::ostream & out, const SymmetricTensor< 4, dim, Number > & t )
inline

Output operator for symmetric tensors of rank 4. Print the elements consecutively, with a space in between, two spaces between rank 1 subtensors, three between rank 2 and so on. No special amends are made to represents the symmetry in the output, for example by outputting only the unique entries.

Definition at line 4141 of file symmetric_tensor.h.