Skip to content

Bases

How to build a basis and read what it stores. The mathematics — dual basis, metric, variance, and why the type hierarchy exists — is on Bases and variance.

Constructors

Basis always returns the most specific type that applies, so the cost of every later component conversion is decided here.

CallReturnsMeaning
Basis{dim,T}()CanonicalBasisthe reference frame
Basis(θ)RotatedBasis2-D rotation by one angle
Basis(θ, ϕ, ψ = 0)RotatedBasis3-D rotation, Z–Y–Z Euler angles
Basis(ℬ, χᵢ)OrthogonalBasis scaled by one factor per direction
Basis(v::AbstractMatrix, var)most specificfrom a matrix of :cov or :cont vectors
Basis(eᵢ, eⁱ, gᵢⱼ, gⁱʲ)Basisall four matrices given explicitly

The matrix constructors take the basis vectors as columns, expressed in the canonical basis.

julia
using TensND, SymPy, LinearAlgebra

= Basis(Sym[1 0 0; 0 1 0; 0 1 1])

julia
typeof(ℬ), isorthogonal(ℬ), isorthonormal(ℬ)
(Basis{3, Sym}, false, false)

An orthonormal basis is detected automatically and gets the cheaper type:

julia
θ, ϕ, ψ = symbols("θ ϕ ψ", real = true)
typeof(Basis(θ, ϕ, ψ))
RotatedBasis{3, Sym{PyCall.PyObject}}

Accessors

FunctionReturns
vecbasis(ℬ, :cov)matrix of the
vecbasis(ℬ, :cont)matrix of the dual
metric(ℬ, :cov)
metric(ℬ, :cont)
angles(ℬ)Euler angles of a rotated basis
get_dim(ℬ)the dimension
isorthogonal, isorthonormalpredicates
julia
metric(ℬ, :cov)

julia
tsimplify(metric(ℬ, :cont) * metric(ℬ, :cov))

The product of the two metrics is the identity, by construction — the cheapest check that a basis is consistent.

Normalization

LinearAlgebra.normalize``(ℬ) divides each vector by its norm. It removes the scaling but not the obliquity: the metric acquires a unit diagonal while the off-diagonal terms, which measure the angles between the vectors, survive.

julia
metric(normalize(ℬ), :cov)

Predefined coordinates and basis vectors

The init_* helpers return a triple (coordinates, vectors, basis):

FunctionCoordinates
init_cartesian(dim) or
init_polar
init_cylindrical
init_spherical
init_rotated
julia
using TensND, SymPy
(r, θ, z), (𝐞ʳ, 𝐞ᶿ, 𝐞ᶻ), ℬᶜ = init_cylindrical()
ℬᶜ

The spherical ordering is (\theta,\varphi,r)

Not . The ordering is chosen so that    reproduces the canonical basis in the canonical order, which makes the spherical frame a genuine RotatedBasis. The same applies to coorsys_spherical — see Curvilinear differential calculus.

The canonical keyword

Each init_* takes canonical::Bool. It decides whether the returned vectors carry their components in the canonical basis (true) or in the local rotated basis (false, the default):

julia
(θs, ϕs, rs), (𝐞ᶿ, 𝐞ᵠ, 𝐞ʳ), ℬˢ = init_spherical()
components_canon(𝐞ʳ)

The default is usually what you want: further calculations then stay in the rotated frame, where components are the physical ones.