User Guide
GeometricAlgebra.jl implements a flexible, performant type for multivectors in geometric (or Clifford) algebra.
Installation
This package is not yet registered, but can be installed directly from source.
julia> using Pkg
julia> Pkg.add(url="https://github.com/Jollywatt/GeometricAlgebra.jl", rev="v0.2.1")
julia> using GeometricAlgebra
Quick start
To construct a geometric multivector from a vector of components, provide the metric signature and grade as type parameters.
For example, a 3D Euclidean vector of grade one:
julia> u = Multivector{3,1}([1, -1, 0])
3-component Multivector{3, 1, Vector{Int64}}: 1 v1 -1 v2 0 v3
The Multivector
type is simply a wrapper which associates a geometric algebra and multivector grade(s) to the underlying components vector (accessed with u.comps
).
Many multivector operations are implemented, including:
+
,-
,*
(geometric_prod
),inv
,/
grade
for grade projection,scalar
∧
(wedge
),∨
(antiwedge
),⋅
(inner
),⊙
(scalar_prod
),⨼
(lcontract
),⨽
(rcontract
)~
(reversion
),involution
,clifford_conj
ldual
,rdual
,hodgedual
exp
,log
, trigonometric functions
Non-euclidean metric signatures can be specified, such as Cl(3,0,1)
for projective geometric algebra (PGA), or a named tuple such as (t=-1, x=+1)
for custom basis vector names (see Custom basis display styles for more control).
For example, here is a bivector in the spacetime algebra (STA) using the $({-}{+}{+}{+})$ metric.
julia> B = Multivector{Cl("-+++"),2}(1:6) # Lorentzian bivector
6-component Multivector{Cl("-+++"), 2, UnitRange{Int64}}: 1 v12 2 v13 3 v23 4 v14 5 v24 6 v34
julia> exp(B)
8-component Multivector{Cl("-+++"), 0:2:4, MVector{8, Float64}}: 1.18046 0.818185 v12 + -0.141944 v13 + 0.153208 v23 + 1.076 v14 + 1.16194 v24 + 1.03866 v34 0.999268 v1234
Notice that the grades parameter of this bivector exponential is 0:2:4
, for an even multivector having 8 components (instead of 16 components of a general 4D multivector).
Working with an orthonormal basis
You can obtain an orthonormal basis for a metric signature with basis
.
julia> v = basis(3)
3-element Vector{BasisBlade{3, 1, Int64}}: 1 v1 1 v2 1 v3
BasisBlade
s represent individual components of a Multivector
. The macro @basis
introduces basis blades into the current namespace for interactive use.
julia> @basis "+---"
[ Info: Defined basis blades v1, v2, v3, v4, v12, v13, v23, v14, v24, v34, v123, v124, v134, v234, v1234, I in Main
julia> 1 + 10v23 + 1000/I
8-component Multivector{Cl("+---"), 0:2:4, MVector{8, Float64}}: 1.0 10.0 v23 -1000.0 v1234
julia> @basis (t = +1, x = -1) allperms=true
[ Info: Defined basis blades t, x, tx, xt, I in Main
julia> 6tx == -6xt
true
Code generation
The @symbolicga
macro may be used to generate loop- and allocation-free code from geometric algebra expressions.
julia> volume(v1, v2, v3) = @symbolicga 3 (v1=1, v2=1, v3=1) (v1 ∧ v2 ∧ v3).comps[]
volume (generic function with 1 method)
julia> volume((1, 1, 1), (2, 3, 4), (5, 0, 5))
10
Custom basis display styles
You can customise both the notation and canonical ordering with which basis blades are displayed to agree with conventions. This can be done by defining a BasisDisplayStyle(dim; kwargs...)
and setting a key of GeometricAlgebra.BASIS_DISPLAY_STYLES
.
Some example styles for v12 + 2v13
are:
Notation | Display style | BasisDisplayStyle keyword arguments |
---|---|---|
$𝐞_{12} + 2𝐞_{13}$ | 𝐞12 + 2𝐞13 | prefix="𝐞" |
$γ^0γ^1 + 2γ^0γ^2$ | γ⁰γ¹ + 2γ⁰γ² | prefix="γ", sep="", indices="⁰¹²³" |
$\mathrm{d}x ∧ \mathrm{d}y - 2 \mathrm{d}z ∧ \mathrm{d}x$ | dx ∧ dy - 2 dz ∧ dx | prefix="d", sep=" ∧ ", indices="xyz" |
The last style additionally uses a custom basis blade ordering.
Custom basis blade orderings
By default, multivectors are displayed with their components the same sign and in the same order as they are stored. Internally, the basis vectors in a blade are encoded in binary (see bits_to_indices
and indices_to_bits
.) For example:
julia> BasisBlade{4}(42, 0b1101)
BasisBlade{4, 3, Int64}: 42 v134
Multivector components are stored in order of grade, then by binary value. For example, the components of a full 3D multivector correspond to the basis blades:
julia> GeometricAlgebra.componentbits(Multivector{3,0:3}) .|> UInt8 .|> bitstring
8-element StaticArraysCore.SVector{8, String} with indices SOneTo(8): "00000000" "00000001" "00000010" "00000100" "00000011" "00000101" "00000110" "00000111"
However, it can sometimes be convenient to adopt different conventions. For example, in 3D, it is common to see “cyclical” basis bivectors, $(𝐯_{23}, 𝐯_{31}, 𝐯_{12})$, as these are the respective duals of $(𝐯_1, 𝐯_2, 𝐯_3)$. This style can be achieved as follows:
julia> style = BasisDisplayStyle( 3, # dimension of algebra Dict(2 => [[2,3], [3,1], [1,2]]), # indices and order of basis bivectors prefix="𝐞" )
BasisDisplayStyle: dim: 3 blades: [0b101 => [3, 1], 0b110 => [2, 3], 0b011 => [1, 2]] parities: [0b101 => true, 0b110 => false, 0b011 => false] order: [2 => [0b110, 0b101, 0b011]] indices: ["1", "2", "3"] prefix: "𝐞" sep: nothing labels: [] preview: 0 │ 𝐞 1 │ 𝐞1 𝐞2 𝐞3 2 │ 𝐞23 𝐞31 𝐞12 3 │ 𝐞123
julia> GeometricAlgebra.BASIS_DISPLAY_STYLES[3] = style;
The second argument of BasisDisplayStyle
defines the complete list of basis blade indices for each grade.
With this style, it is easier to “read off” the duals of a 3D (bi)vector:
julia> u = Multivector{3,1}(rand(1:100, 3))
3-component Multivector{3, 1, Vector{Int64}}: 61 𝐞1 11 𝐞2 50 𝐞3
julia> ldual(u)
3-component Multivector{3, 2, MVector{3, Int64}}: 61 𝐞23 11 𝐞31 50 𝐞12
Notice how the vector and dual vector components align nicely. To recover the default style:
julia> delete!(GeometricAlgebra.BASIS_DISPLAY_STYLES, 3)
IdDict{Any, BasisDisplayStyle}()
julia> ldual(u)
3-component Multivector{3, 2, MVector{3, Int64}}: 50 v12 -11 v13 61 v23
BasisDisplayStyle
does not affect how components are stored internally. Bear this in mind when accessing the components field of a Multivector
when using a style with custom ordering.