Skip to content

Tensors ​

Building tensors, moving their components between bases and variances, and reading them back. The underlying notions are on Bases and variance and Tensor algebra.

Construction ​

A tensor is an array, a basis and a variance tuple. Supplying fewer arguments fills in the defaults — the canonical basis and fully contravariant variance.

julia
using TensND, SymPy, Tensors

V = Tens(Tensor{1, 3}(i -> symbols("v$i", real = true)))
T = Tens(Tensor{2, 3}((i, j) -> symbols("t$i$j", real = true)))
typeof(V), typeof(T)
(TensND.TensCanonical{1, 3, Sym{PyCall.PyObject}, Tensors.Vec{3, Sym{PyCall.PyObject}}}, TensND.TensCanonical{2, 3, Sym{PyCall.PyObject}, Tensors.Tensor{2, 3, Sym{PyCall.PyObject}, 9}})

The type follows the basis: a tensor on a canonical basis is a TensCanonical, on a rotated one a TensRotated, on an orthogonal one a TensOrthogonal, and only the general case is a Tens. Only the last two carry a variance tuple, because on an orthonormal basis the distinction collapses.

julia
ℬ = Basis(Sym[1 0 0; 0 1 0; 0 1 1])
typeof(Tens(get_array(T), ℬ, (:cov, :cov)))
Tens{2, 3, Sym{PyCall.PyObject}, Tensors.Tensor{2, 3, Sym{PyCall.PyObject}, 9}}

Data may come from a plain Array, or from a Tensors.jl container (Tensor, SymmetricTensor, Vec), in which case the symmetry is preserved.

Components ​

CallReturns
components(t, ℬ, var)components on ℬ with variance var
components(t, var)components on the tensor's own basis
components(t, ℬ)keeps the tensor's variance
components_canon(t)components in the canonical basis
get_array(t)the stored array, as is
julia
components(V, ℬ, (:cont,))

julia
components(V, ℬ, (:cov,))

get_array is not components

get_array returns the array as stored, in the tensor's own basis and variance. Two tensors that are mathematically equal can have completely different get_arrays. Comparing raw arrays is therefore meaningless unless both tensors are known to share a basis and a variance — bring them to a common one with components or change_tens first. This is a real source of bugs; a worked example is on Submanifolds.

Changing basis ​

change_tens returns a tensor re-expressed on another basis, where components returns a bare array:

julia
𝐞ᶿ, 𝐞ᵠ, 𝐞ʳ = init_spherical()[2]
ℬˢ = init_spherical()[3]
a = Tens(Vec{3}((i,) -> symbols("a$i", real = true)))
A = Tens(rot3(symbols("θ", real = true), symbols("ϕ", real = true)) * get_array(a))
simplify(change_tens(A, ℬˢ))

change_tens_canon is the shorthand for the canonical basis.

Accessors ​

FunctionReturns
get_orderthe order
get_dimthe dimension
get_basisthe basis
get_varthe variance tuple
get_datathe stored data (coefficients, for structured types)
get_arraythe full component array

Products ​

The full table, with index formulas, is on Tensor algebra. In practice:

julia
using TensND, SymPy, Tensors, LinearAlgebra

𝟏 = tens_Id2(Val(3), Val(Sym))
𝕀, 𝕁, 𝕂 = ISO(Val(3), Val(Sym))
𝕀 == 𝟏 ⊠ˢ 𝟏, 𝕁 == (𝟏 ⊗ 𝟏) / 3
(true, true)
julia
a = Tens(Vec{3}((i,) -> symbols("a$i", real = true)))
b = Tens(Vec{3}((i,) -> symbols("b$i", real = true)))
get_array(a ⊗ˢ b)

JuliaFunctionContracted indices
⊗otimesnone
⊗ˢsotimesnone, symmetrized
⊠otimesunone
⊠ˢotimesulnone, symmetrized
⋅dot1
⊡dcontract2
⊙qcontract4

Display ​

pprint prints a tensor expanded on its basis — as a sum of basis products rather than as a component array, which is far more readable for symbolic results:

julia
Spherical = coorsys_spherical()
𝐞ᶿ, 𝐞ᵠ, 𝐞ʳ = unitvec(Spherical)
pprint(𝐞ʳ ⊗ 𝐞ʳ + 2 * 𝐞ᶿ ⊗ 𝐞ᶿ, Spherical)
(2)𝐞ᶿ⊗𝐞ᶿ + 𝐞ʳ⊗𝐞ʳ

Applied to a scalar it falls back to the rich text/plain display, so a symbolic expression comes out in SymPy's two-dimensional form:

julia
LAPLACE(1 / getcoords(Spherical)[3], Spherical) |> pprint
0

Structured types print in their compact algebraic form instead — see Structured tensors.

Kelvin–Mandel ​

KM maps a symmetric order-2 tensor to a 6-vector and a minor-symmetric order-4 tensor to a   matrix; inv_KM inverts it. The convention and what it buys are on Kelvin–Mandel representation.

julia
C = tens_TI(10.0, 3.0, 2.5, 12.0, 2.0, [0.0, 0.0, 1.0])
KM(C)
6×6 Matrix{Float64}:
 10.0   3.0   2.5  0.0  0.0  0.0
  3.0  10.0   2.5  0.0  0.0  0.0
  2.5   2.5  12.0  0.0  0.0  0.0
  0.0   0.0   0.0  4.0  0.0  0.0
  0.0   0.0   0.0  0.0  4.0  0.0
  0.0   0.0   0.0  0.0  0.0  7.0

Symmetry predicates ​

issymmetric, isminorsymmetric and ismajorsymmetric test the index symmetries; is_ISO, is_TI, is_ORTHO test the material symmetry class and are documented under Projection.