Other operators
- Base.inv
- Base.sqrt
- Base.transpose
- LinearAlgebra.cross
- LinearAlgebra.det
- LinearAlgebra.eigen
- LinearAlgebra.eigvals
- LinearAlgebra.eigvecs
- LinearAlgebra.norm
- LinearAlgebra.tr
- Tensors.dev
- Tensors.dotdot
- Tensors.dott
- Tensors.fromvoigt
- Tensors.majorsymmetric
- Tensors.majortranspose
- Tensors.minorsymmetric
- Tensors.minortranspose
- Tensors.rotate
- Tensors.rotation_tensor
- Tensors.skew
- Tensors.symmetric
- Tensors.tdot
- Tensors.tovoigt
- Tensors.tovoigt!
- Tensors.vol
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.tdot — Functiontdot(A::SecondOrderTensor)Compute the transpose-dot product of A with itself, i.e. dot(A', A). Return a SymmetricTensor.
Examples
julia> A = rand(Tensor{2,3})
3×3 Tensor{2, 3, Float64, 9}:
 0.325977  0.894245  0.953125
 0.549051  0.353112  0.795547
 0.218587  0.394255  0.49425
julia> tdot(A)
3×3 SymmetricTensor{2, 3, Float64, 6}:
 0.455498  0.571559  0.855529
 0.571559  1.0798    1.3281
 0.855529  1.3281    1.78562Tensors.dott — Functiondott(A::SecondOrderTensor)Compute the dot-transpose product of A with itself, i.e. dot(A, A'). Return a SymmetricTensor.
Examples
julia> A = rand(Tensor{2,3})
3×3 Tensor{2, 3, Float64, 9}:
 0.325977  0.894245  0.953125
 0.549051  0.353112  0.795547
 0.218587  0.394255  0.49425
julia> dott(A)
3×3 SymmetricTensor{2, 3, Float64, 6}:
 1.81438   1.253    0.894897
 1.253     1.05904  0.65243
 0.894897  0.65243  0.4475Norm
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.norm — Functionnorm(::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.325977  0.894245  0.953125
 0.549051  0.353112  0.795547
 0.218587  0.394255  0.49425
julia> norm(A)
1.8223398556552728Trace
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.tr — Functiontr(::SecondOrderTensor)Computes the trace of a second order tensor.
Examples
julia> A = rand(SymmetricTensor{2,3})
3×3 SymmetricTensor{2, 3, Float64, 6}:
 0.325977  0.549051  0.218587
 0.549051  0.894245  0.353112
 0.218587  0.353112  0.394255
julia> tr(A)
1.6144775244804341Determinant
Determinant for a second order tensor.
LinearAlgebra.det — Functiondet(::SecondOrderTensor)Computes the determinant of a second order tensor.
Examples
julia> A = rand(SymmetricTensor{2,3})
3×3 SymmetricTensor{2, 3, Float64, 6}:
 0.325977  0.549051  0.218587
 0.549051  0.894245  0.353112
 0.218587  0.353112  0.394255
julia> det(A)
-0.002539324113350679Inverse
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.inv — Functioninv(::SecondOrderTensor)Computes the inverse of a second order tensor.
Examples
julia> A = rand(Tensor{2,3})
3×3 Tensor{2, 3, Float64, 9}:
 0.325977  0.894245  0.953125
 0.549051  0.353112  0.795547
 0.218587  0.394255  0.49425
julia> inv(A)
3×3 Tensor{2, 3, Float64, 9}:
 -587.685  -279.668   1583.46
 -411.743  -199.494   1115.12
  588.35    282.819  -1587.79Transpose
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.transpose — Functiontranspose(::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.325977  0.218587
 0.549051  0.894245
julia> A'
2×2 Tensor{2, 2, Float64, 4}:
 0.325977  0.549051
 0.218587  0.894245Tensors.minortranspose — Functionminortranspose(::FourthOrderTensor)Compute the minor transpose of a fourth order tensor.
Tensors.majortranspose — Functionmajortranspose(::FourthOrderTensor)Compute the major transpose of a fourth order tensor.
Symmetric
The symmetric part of a second 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}),\]
The major symmetric part of a fourth order tensor is defined by
\[\mathsf{A}^\text{majsym} = \frac{1}{2}(\mathsf{A} + \mathsf{A}^\text{T}) \Leftrightarrow A_{ijkl}^\text{majsym} = \frac{1}{2}(A_{ijkl} + A_{klij}).\]
The minor symmetric part of a fourth order tensor is defined by
\[A_{ijkl}^\text{minsym} = \frac{1}{4}(A_{ijkl} + A_{ijlk} + A_{jikl} + A_{jilk}).\]
Tensors.symmetric — Functionsymmetric(::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.325977  0.218587
 0.549051  0.894245
julia> symmetric(A)
2×2 SymmetricTensor{2, 2, Float64, 3}:
 0.325977  0.383819
 0.383819  0.894245Tensors.minorsymmetric — Functionminorsymmetric(::FourthOrderTensor)Compute the minor symmetric part of a fourth order tensor, return a SymmetricTensor{4}.
Tensors.majorsymmetric — Functionmajorsymmetric(::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.skew — Functionskew(::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.dev — Functiondev(::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.065136   0.894245   0.953125
  0.549051  -0.0380011  0.795547
  0.218587   0.394255   0.103137
julia> tr(dev(A))
5.551115123125783e-17Volumetric 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.vol — Functionvol(::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.325977  0.549051  0.218587
 0.549051  0.894245  0.353112
 0.218587  0.353112  0.394255
julia> vol(A)
3×3 SymmetricTensor{2, 3, Float64, 6}:
 0.538159  0.0       0.0
 0.0       0.538159  0.0
 0.0       0.0       0.538159
julia> vol(A) + dev(A) ≈ A
trueCross 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.cross — Functioncross(::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 Vec{3, Float64}:
 0.32597672886359486
 0.5490511363155669
 0.21858665481883066
julia> b = rand(Vec{3})
3-element Vec{3, Float64}:
 0.8942454282009883
 0.35311164439921205
 0.39425536741585077
julia> a × b
3-element Vec{3, Float64}:
  0.13928086435138393
  0.0669520417303531
 -0.37588028973385323Eigenvalues 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.eigen — Functioneigen(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.
Examples
julia> A = rand(SymmetricTensor{2, 2});
julia> E = eigen(A);
julia> E.values
2-element Vec{2, Float64}:
 -0.27938877799585415
  0.8239521616782797
julia> E.vectors
2×2 Tensor{2, 2, Float64, 4}:
 -0.671814  0.74072
  0.74072   0.671814eigen(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.
LinearAlgebra.eigvals — Functioneigvals(::SymmetricTensor)Compute the eigenvalues of a symmetric tensor.
eigvals(::Union{Eigen,FourthOrderEigen})Extract eigenvalues from an Eigen or FourthOrderEigen object, returned by eigen.
LinearAlgebra.eigvecs — Functioneigvecs(::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.sqrt — Functionsqrt(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.407718  0.298993
 0.298993  0.349237
julia> sqrt(S)
2×2 SymmetricTensor{2, 2, Float64, 3}:
 0.578172  0.270989
 0.270989  0.525169
julia> √S ⋅ √S ≈ S
trueRotations
Tensors.rotate — Functionrotate(x::AbstractTensor{3}, u::Vec{3}, θ::Number)Rotate a three dimensional tensor x around the vector u a total of θ radians.
Examples
julia> x = Vec{3}((0.0, 0.0, 1.0));
julia> u = Vec{3}((0.0, 1.0, 0.0));
julia> rotate(x, u, π/2)
3-element Vec{3, Float64}:
 1.0
 0.0
 6.123233995736766e-17rotate(x::AbstractTensor{2}, θ::Number)Rotate a two dimensional tensor x θ radians around the out-of-plane axis.
Examples
julia> x = Vec{2}((0.0, 1.0));
julia> rotate(x, π/4)
2-element Vec{2, Float64}:
 -0.7071067811865475
  0.7071067811865476Tensors.rotation_tensor — Functionrotation_tensor(θ::Number)Return the two-dimensional rotation matrix corresponding to rotation of θ radians around the out-of-plane axis (i.e. around (0, 0, 1)).
rotation_tensor(ψ::Number, θ::Number, ϕ::Number)Return the three-dimensional rotation matrix corresponding to the rotation described by the three Euler angles $ψ$, $θ$, $ϕ$.
\[R(ψ,θ,ϕ) = R_x(ψ)R_y(θ)R_z(ϕ)\]
see e.g. http://eecs.qmul.ac.uk/~gslabaugh/publications/euler.pdf for a complete description.
Note that the gimbal lock phenomena can occur when using this rotation tensor parametrization.
rotation_tensor(u::Vec{3}, θ::Number)Return the three-dimensional rotation matrix corresponding to rotation of θ radians around the vector u.
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.dotdot — Functiondotdot(::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. Care must be exercised when combined with differentiation, see Differentiation of Voigt format further down.
Tensors.tovoigt — Functiontovoigt([type::Type{<:AbstractArray}, ]A::Union{SecondOrderTensor, FourthOrderTensor}; kwargs...)Converts a tensor to "Voigt"-format.
Optional argument:
- type: determines the returned Array type. Possible types are- Arrayand- SArray(see- StaticArrays).
Keyword arguments:
- offdiagscale: determines the scaling factor for the offdiagonal elements. This argument is only applicable for- SymmetricTensors.- tomandelcan also be used for the "Mandel"-format which sets- offdiagscale = √2for- SymmetricTensors, and is equivalent to- tovoigtfor- Tensors.
- 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 Vector{Int64}:
 1
 5
 9
 8
 7
 4
 6
 3
 2
julia> tovoigt(SymmetricTensor{2,3}(1:6); offdiagscale = 2)
6-element Vector{Int64}:
  1
  4
  6
 10
  6
  4
julia> tovoigt(Tensor{4,2}(1:16))
4×4 Matrix{Int64}:
 1  13   9  5
 4  16  12  8
 3  15  11  7
 2  14  10  6
julia> using StaticArrays: SMatrix
julia> tovoigt(SMatrix, Tensor{4,2}(1:16))
4×4 SMatrix{4, 4, Int64, 16} with indices SOneTo(4)×SOneTo(4):
 1  13   9  5
 4  16  12  8
 3  15  11  7
 2  14  10  6Tensors.tovoigt! — Functiontovoigt!(v::AbstractArray, 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- Athe tensor should be stored. For 4th order tensors the keyword arguments are- offset_iand- offset_j, respectively. Defaults to- 0.
- offdiagscale: determines the scaling factor for the offdiagonal elements. This argument is only applicable for- SymmetricTensors.- frommandel!can also be used for the "Mandel"-format which sets- offdiagscale = √2for- SymmetricTensors, and is equivalent to- fromvoigt!for- Tensors.
- 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.325977  0.218587
 0.549051  0.894245
julia> x = zeros(4);
julia> tovoigt!(x, T)
4-element Vector{Float64}:
 0.32597672886359486
 0.8942454282009883
 0.21858665481883066
 0.5490511363155669
julia> x = zeros(5);
julia> tovoigt!(x, T; offset=1)
5-element Vector{Float64}:
 0.0
 0.32597672886359486
 0.8942454282009883
 0.21858665481883066
 0.5490511363155669Tensors.fromvoigt — Functionfromvoigt(S::Type{<:AbstractTensor}, A::AbstractArray{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- Athe tensor starts. For 4th order tensors the keyword arguments are- offset_iand- offset_j, respectively. Defaults to- 0.
- offdiagscale: determines the scaling factor for the offdiagonal elements. This argument is only applicable for- SymmetricTensors.- frommandelcan also be used for the "Mandel"-format which sets- offdiagscale = √2for- SymmetricTensors, and is equivalent to- fromvoigtfor- Tensors.
- 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.
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.0Differentiation of Voigt format
Differentiating with a Voigt representation of a symmetric tensor may lead to incorrect results when converted back to tensors. The tomandel, tomandel!, and frommandel versions of tovoigt, tovoigt!, and fromvoigt can then be used. As illustrated by the following example, this will give the correct result. In general, however, direct differentiation of Tensors is faster (see Automatic Differentiation).
julia> using Tensors, ForwardDiff
julia> fun(X::SymmetricTensor{2}) = X;
julia> A = rand(SymmetricTensor{2,2});Differentiation of a tensor directly (correct):
julia> tovoigt(gradient(fun, A))
3×3 Matrix{Float64}:
 1.0  0.0  0.0
 0.0  1.0  0.0
 0.0  0.0  0.5Converting to Voigt format, perform differentiation, convert back (WRONG!):
julia> ForwardDiff.jacobian(
           v -> tovoigt(fun(fromvoigt(SymmetricTensor{2,2}, v))),
           tovoigt(A)
       )
3×3 Matrix{Float64}:
 1.0  0.0  0.0
 0.0  1.0  0.0
 0.0  0.0  1.0Converting to Mandel format, perform differentiation, convert back (correct)
julia> tovoigt(
           frommandel(SymmetricTensor{4,2},
                ForwardDiff.jacobian(
                    v -> tomandel(fun(frommandel(SymmetricTensor{2,2}, v))),
                    tomandel(A)
                )
           )
       )
3×3 Matrix{Float64}:
 1.0  0.0  0.0
 0.0  1.0  0.0
 0.0  0.0  0.5