Other operators

Transpose-dot

The dot product between the transpose of a tensor with itself. Results in a symmetric tensor.

\[\mathbf{A} = \mathbf{B}^\text{T} \cdot \mathbf{B} \Leftrightarrow A_{ij} = B_{ki}^\text{T} B_{kj} = B_{ik} B_{kj}\]
\[\mathbf{A} = \mathbf{B} \cdot \mathbf{B}^\text{T} \Leftrightarrow A_{ij} = B_{ik} B_{jk}^\text{T} = B_{ik} B_{kj}\]
Tensors.tdotFunction
tdot(::SecondOrderTensor)

Compute the transpose-dot product of a second order tensor with itself. Return a SymmetricTensor.

Examples

julia> A = rand(Tensor{2,3})
3×3 Tensor{2,3,Float64,9}:
 0.590845  0.460085  0.200586
 0.766797  0.794026  0.298614
 0.566237  0.854147  0.246837

julia> tdot(A)
3×3 SymmetricTensor{2,3,Float64,6}:
 1.2577   1.36435   0.48726
 1.36435  1.57172   0.540229
 0.48726  0.540229  0.190334
Tensors.dottFunction
dott(::SecondOrderTensor)

Compute the dot-transpose product of a second order tensor with itself. Return a SymmetricTensor.

Examples

julia> A = rand(Tensor{2,3})
3×3 Tensor{2,3,Float64,9}:
 0.590845  0.460085  0.200586
 0.766797  0.794026  0.298614
 0.566237  0.854147  0.246837

julia> dott(A)
3×3 SymmetricTensor{2,3,Float64,6}:
 0.601011  0.878275  0.777051
 0.878275  1.30763   1.18611
 0.777051  1.18611   1.11112

Norm

The (2)-norm of a tensor is defined for a vector, second order tensor and fourth order tensor as

\[\|\mathbf{a}\| = \sqrt{\mathbf{a} \cdot \mathbf{a}} \Leftrightarrow \|a_i\| = \sqrt{a_i a_i},\]
\[\|\mathbf{A}\| = \sqrt{\mathbf{A} : \mathbf{A}} \Leftrightarrow \|A_{ij}\| = \sqrt{A_{ij} A_{ij}},\]
\[\|\mathsf{A}\| = \sqrt{\mathsf{A} :: \mathsf{A}} \Leftrightarrow \|A_{ijkl}\| = \sqrt{A_{ijkl} A_{ijkl}}.\]
LinearAlgebra.normFunction
norm(::Vec)
norm(::SecondOrderTensor)
norm(::FourthOrderTensor)

Computes the norm of a tensor.

Examples

julia> A = rand(Tensor{2,3})
3×3 Tensor{2,3,Float64,9}:
 0.590845  0.460085  0.200586
 0.766797  0.794026  0.298614
 0.566237  0.854147  0.246837

julia> norm(A)
1.7377443667834924

Trace

The trace for a second order tensor is defined as the sum of the diagonal elements. This can be written as

\[\text{tr}(\mathbf{A}) = \mathbf{I} : \mathbf{A} \Leftrightarrow \text{tr}(A_{ij}) = A_{ii}.\]
LinearAlgebra.trFunction
tr(::SecondOrderTensor)

Computes the trace of a second order tensor.

Examples

julia> A = rand(SymmetricTensor{2,3})
3×3 SymmetricTensor{2,3,Float64,6}:
 0.590845  0.766797  0.566237
 0.766797  0.460085  0.794026
 0.566237  0.794026  0.854147

julia> tr(A)
1.9050765715072775

Determinant

Determinant for a second order tensor.

LinearAlgebra.detFunction
det(::SecondOrderTensor)

Computes the determinant of a second order tensor.

Examples

julia> A = rand(SymmetricTensor{2,3})
3×3 SymmetricTensor{2,3,Float64,6}:
 0.590845  0.766797  0.566237
 0.766797  0.460085  0.794026
 0.566237  0.794026  0.854147

julia> det(A)
-0.1005427219925894

Inverse

Inverse of a second order tensor such that

\[\mathbf{A}^{-1} \cdot \mathbf{A} = \mathbf{I}\]

where $\mathbf{I}$ is the second order identitiy tensor.

Base.invFunction
inv(::SecondOrderTensor)

Computes the inverse of a second order tensor.

Examples

julia> A = rand(Tensor{2,3})
3×3 Tensor{2,3,Float64,9}:
 0.590845  0.460085  0.200586
 0.766797  0.794026  0.298614
 0.566237  0.854147  0.246837

julia> inv(A)
3×3 Tensor{2,3,Float64,9}:
  19.7146   -19.2802    7.30384
   6.73809  -10.7687    7.55198
 -68.541     81.4917  -38.8361

Transpose

Transpose of tensors is defined by changing the order of the tensor's "legs". The transpose of a vector/symmetric tensor is the vector/tensor itself. The transpose of a second order tensor can be written as:

\[A_{ij}^\text{T} = A_{ji}\]

and for a fourth order tensor the minor transpose can be written as

\[A_{ijkl}^\text{t} = A_{jilk}\]

and the major transpose as

\[A_{ijkl}^\text{T} = A_{klij}.\]
Base.transposeFunction
transpose(::Vec)
transpose(::SecondOrderTensor)
transpose(::FourthOrderTensor)

Compute the transpose of a tensor. For a fourth order tensor, the transpose is the minor transpose.

Examples

julia> A = rand(Tensor{2,2})
2×2 Tensor{2,2,Float64,4}:
 0.590845  0.566237
 0.766797  0.460085

julia> A'
2×2 Tensor{2,2,Float64,4}:
 0.590845  0.766797
 0.566237  0.460085
Tensors.minortransposeFunction
minortranspose(::FourthOrderTensor)

Compute the minor transpose of a fourth order tensor.

Tensors.majortransposeFunction
majortranspose(::FourthOrderTensor)

Compute the major transpose of a fourth order tensor.

Symmetric

The symmetric part of a second and fourth order tensor is defined by:

\[\mathbf{A}^\text{sym} = \frac{1}{2}(\mathbf{A} + \mathbf{A}^\text{T}) \Leftrightarrow A_{ij}^\text{sym} = \frac{1}{2}(A_{ij} + A_{ji}),\]
\[\mathsf{A}^\text{sym} = \frac{1}{2}(\mathsf{A} + \mathsf{A}^\text{t}) \Leftrightarrow A_{ijkl}^\text{sym} = \frac{1}{2}(A_{ijkl} + A_{jilk}).\]
Tensors.symmetricFunction
symmetric(::SecondOrderTensor)
symmetric(::FourthOrderTensor)

Computes the (minor) symmetric part of a second or fourth order tensor. Return a SymmetricTensor.

Examples

julia> A = rand(Tensor{2,2})
2×2 Tensor{2,2,Float64,4}:
 0.590845  0.566237
 0.766797  0.460085

julia> symmetric(A)
2×2 SymmetricTensor{2,2,Float64,3}:
 0.590845  0.666517
 0.666517  0.460085
Tensors.minorsymmetricFunction
minorsymmetric(::FourthOrderTensor)

Compute the minor symmetric part of a fourth order tensor, return a SymmetricTensor{4}.

Tensors.majorsymmetricFunction
majorsymmetric(::FourthOrderTensor)

Compute the major symmetric part of a fourth order tensor.

Skew symmetric

The skew symmetric part of a second order tensor is defined by

\[\mathbf{A}^\text{skw} = \frac{1}{2}(\mathbf{A} - \mathbf{A}^\text{T}) \Leftrightarrow A^\text{skw}_{ij} = \frac{1}{2}(A_{ij} - A_{ji}).\]

The skew symmetric part of a symmetric tensor is zero.

Tensors.skewFunction
skew(::SecondOrderTensor)

Computes the skew-symmetric (anti-symmetric) part of a second order tensor, returns a Tensor{2}.

Deviatoric tensor

The deviatoric part of a second order tensor is defined by

\[\mathbf{A}^\text{dev} = \mathbf{A} - \frac{1}{3} \mathrm{tr}[\mathbf{A}] \mathbf{I} \Leftrightarrow A_{ij}^\text{dev} = A_{ij} - \frac{1}{3}A_{kk}\delta_{ij}.\]
Tensors.devFunction
dev(::SecondOrderTensor)

Computes the deviatoric part of a second order tensor.

Examples

julia> A = rand(Tensor{2, 3});

julia> dev(A)
3×3 Tensor{2,3,Float64,9}:
 0.0469421  0.460085   0.200586
 0.766797   0.250123   0.298614
 0.566237   0.854147  -0.297065

julia> tr(dev(A))
0.0

Volumetric tensor

The volumetric part of a second order tensor is defined by

\[\mathbf{A}^\text{vol} = \frac{1}{3} \mathrm{tr}[\mathbf{A}] \mathbf{I} \Leftrightarrow A_{ij}^\text{vol} = \frac{1}{3}A_{kk}\delta_{ij}.\]
Tensors.volFunction
vol(::SecondOrderTensor)

Computes the volumetric part of a second order tensor based on the additive decomposition.

Examples

julia> A = rand(SymmetricTensor{2,3})
3×3 SymmetricTensor{2,3,Float64,6}:
 0.590845  0.766797  0.566237
 0.766797  0.460085  0.794026
 0.566237  0.794026  0.854147

julia> vol(A)
3×3 SymmetricTensor{2,3,Float64,6}:
 0.635026  0.0       0.0
 0.0       0.635026  0.0
 0.0       0.0       0.635026

julia> vol(A) + dev(A) ≈ A
true

Cross product

The cross product between two vectors is defined as

\[\mathbf{a} = \mathbf{b} \times \mathbf{c} \Leftrightarrow a_i = \epsilon_{ijk} b_j c_k\]
LinearAlgebra.crossFunction
cross(::Vec, ::Vec)

Computes the cross product between two Vec vectors, returns a Vec{3}. For dimensions 1 and 2 the Vec's are expanded to 3D first. The infix operator × (written \times) can also be used.

Examples

julia> a = rand(Vec{3})
3-element Tensor{1,3,Float64,3}:
 0.5908446386657102
 0.7667970365022592
 0.5662374165061859

julia> b = rand(Vec{3})
3-element Tensor{1,3,Float64,3}:
 0.4600853424625171
 0.7940257103317943
 0.8541465903790502

julia> a × b
3-element Tensor{1,3,Float64,3}:
  0.20535000738340053
 -0.24415039787171888
  0.11635375677388776

Eigenvalues and eigenvectors

The eigenvalues and eigenvectors of a (symmetric) second order tensor, $\mathbf{A}$ can be solved from the eigenvalue problem

\[\mathbf{A} \cdot \mathbf{v}_i = \lambda_i \mathbf{v}_i \qquad i = 1, \dots, \text{dim}\]

where $\lambda_i$ are the eigenvalues and $\mathbf{v}_i$ are the corresponding eigenvectors. For a symmetric fourth order tensor, $\mathsf{A}$ the second order eigentensors and eigenvalues can be solved from

\[\mathsf{A} : \mathbf{V}_i = \lambda_i \mathbf{V}_i \qquad i = 1, \dots, \text{dim}\]

where $\lambda_i$ are the eigenvalues and $\mathbf{V}_i$ the corresponding eigentensors.

LinearAlgebra.eigenFunction
eigen(A::SymmetricTensor{2})

Compute the eigenvalues and eigenvectors of a symmetric second order tensor and return an Eigen object. The eigenvalues are stored in a Vec, sorted in ascending order. The corresponding eigenvectors are stored as the columns of a Tensor.

See eigvals and eigvecs.

Examples

julia> A = rand(SymmetricTensor{2, 2});

julia> E = eigen(A);

julia> E.values
2-element Tensor{1,2,Float64,2}:
 -0.1883547111127678
  1.345436766284664

julia> E.vectors
2×2 Tensor{2,2,Float64,4}:
 -0.701412  0.712756
  0.712756  0.701412
eigen(A::SymmetricTensor{4})

Compute the eigenvalues and second order eigentensors of a symmetric fourth order tensor and return an FourthOrderEigen object. The eigenvalues and eigentensors are sorted in ascending order of the eigenvalues.

See also eigvals and eigvecs.

LinearAlgebra.eigvalsFunction
eigvals(::SymmetricTensor)

Compute the eigenvalues of a symmetric tensor.

eigvals(::Union{Eigen,FourthOrderEigen})

Extract eigenvalues from an Eigen or FourthOrderEigen object, returned by eigen.

LinearAlgebra.eigvecsFunction
eigvecs(::SymmetricTensor)

Compute the eigenvectors of a symmetric tensor.

eigvecs(::Union{Eigen,FourthOrderEigen})

Extract eigenvectors from an Eigen or FourthOrderEigen object, returned by eigen.

Tensor square root

Square root of a symmetric positive definite second order tensor $S$, defined such that

\[\sqrt{\mathbf{S}} \cdot \sqrt{\mathbf{S}} = S.\]
Base.sqrtFunction
sqrt(S::SymmetricTensor{2})

Calculate the square root of the positive definite symmetric second order tensor S, such that √S ⋅ √S == S.

Examples

julia> S = rand(SymmetricTensor{2,2}); S = tdot(S)
2×2 SymmetricTensor{2,2,Float64,3}:
 0.937075  0.887247
 0.887247  0.908603

julia> sqrt(S)
2×2 SymmetricTensor{2,2,Float64,3}:
 0.776178  0.578467
 0.578467  0.757614

julia> √S ⋅ √S ≈ S
true

Rotations

Tensors.rotateFunction
rotate(x::Vec{3}, u::Vec{3}, θ::Number)

Rotate a three dimensional vector x around another vector u a total of θ radians.

Examples

julia> x = Vec{3}((0.0, 0.0, 1.0))
3-element Tensor{1,3,Float64,3}:
 0.0
 0.0
 1.0

julia> u = Vec{3}((0.0, 1.0, 0.0))
3-element Tensor{1,3,Float64,3}:
 0.0
 1.0
 0.0

julia> rotate(x, u, π/2)
3-element Tensor{1,3,Float64,3}:
 1.0
 0.0
 6.123233995736766e-17

Special operations

For computing a special dot product between two vectors $\mathbf{a}$ and $\mathbf{b}$ with a fourth order symmetric tensor $\mathbf{C}$ such that $a_k C_{ikjl} b_l$ there is dotdot(a, C, b). This function is useful because it is the expression for the tangent matrix in continuum mechanics when the displacements are approximated by scalar shape functions.

Tensors.dotdotFunction
dotdot(::Vec, ::SymmetricFourthOrderTensor, ::Vec)

Computes a special dot product between two vectors and a symmetric fourth order tensor such that $a_k C_{ikjl} b_l$.

Voigt format

For some operations it is convenient to easily switch to the so called "Voigt"-format. For example when solving a local problem in a plasticity model. To simplify the conversion between tensors and Voigt format, see tovoigt, tovoigt! and fromvoigt documented below.

Tensors.tovoigtFunction
tovoigt(A::Union{SecondOrderTensor, FourthOrderTensor}; kwargs...)

Converts a tensor to "Voigt"-format.

Keyword arguments:

  • offdiagscale: determines the scaling factor for the offdiagonal elements. frommandel can also be used for "Mandel"-format which sets offdiagscale = √2. This argument is only applicable for SymmetricTensors.
  • order: matrix of the linear indices determining the Voigt order. The default index order is [11, 22, 33, 23, 13, 12, 32, 31, 21], corresponding to order = [1 6 5; 9 2 4; 8 7 3].

See also tovoigt! and fromvoigt.

julia> tovoigt(Tensor{2,3}(1:9))
9-element Array{Int64,1}:
 1
 5
 9
 8
 7
 4
 6
 3
 2

julia> tovoigt(SymmetricTensor{2,3}(1:6); offdiagscale = 2)
6-element Array{Int64,1}:
  1
  4
  6
 10
  6
  4

julia> tovoigt(Tensor{4,2}(1:16))
4×4 Array{Int64,2}:
 1  13   9  5
 4  16  12  8
 3  15  11  7
 2  14  10  6
Tensors.tovoigt!Function
tovoigt!(v::Array, A::Union{SecondOrderTensor, FourthOrderTensor}; kwargs...)

Converts a tensor to "Voigt"-format using the following index order: [11, 22, 33, 23, 13, 12, 32, 31, 21].

Keyword arguments:

  • offset: offset index for where in the array A the tensor should be stored. For 4th order tensors the keyword arguments are offset_i and offset_j, respectively. Defaults to 0.
  • offdiagscale: determines the scaling factor for the offdiagonal elements. frommandel can also be used for "Mandel"-format which sets offdiagscale = √2. This argument is only applicable for SymmetricTensors.
  • order: matrix of the linear indices determining the Voigt order. The default index order is [11, 22, 33, 23, 13, 12, 32, 31, 21].

See also tovoigt and fromvoigt.

julia> T = rand(Tensor{2,2})
2×2 Tensor{2,2,Float64,4}:
 0.590845  0.566237
 0.766797  0.460085

julia> x = zeros(4);

julia> tovoigt!(x, T)
4-element Array{Float64,1}:
 0.5908446386657102
 0.4600853424625171
 0.5662374165061859
 0.7667970365022592

julia> x = zeros(5);

julia> tovoigt!(x, T; offset=1)
5-element Array{Float64,1}:
 0.0
 0.5908446386657102
 0.4600853424625171
 0.5662374165061859
 0.7667970365022592
Tensors.fromvoigtFunction
fromvoigt(S::Type{<:AbstractTensor}, A::Array{T}; kwargs...)

Converts an array A stored in Voigt format to a Tensor of type S.

Keyword arguments:

  • offset: offset index for where in the array A the tensor starts. For 4th order tensors the keyword arguments are offset_i and offset_j, respectively. Defaults to 0.
  • offdiagscale: determines the inverse scaling factor on the offdiagonal elements. frommandel can also be used for "Mandel"-format which sets offdiagscale = √2. This argument is only applicable for SymmetricTensors.

See also tovoigt.

julia> fromvoigt(Tensor{2,3}, 1.0:1.0:9.0)
3×3 Tensor{2,3,Float64,9}:
 1.0  6.0  5.0
 9.0  2.0  4.0
 8.0  7.0  3.0