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.