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:

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 bivector6-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

BasisBlades 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/I8-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 == -6xttrue

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:

NotationDisplay styleBasisDisplayStyle keyword arguments
$𝐞_{12} + 2𝐞_{13}$𝐞12 + 2𝐞13prefix="𝐞"
$γ^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 ∧ dxprefix="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 .|> bitstring8-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
Note

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.