The Blades
Type represents k-blades, and
supports a number of mathematical operations on them.
Both non-euclidean and degenerate metrics are supported as well as the standard euclidean metric. This makes it suitable for implementing a wide range of algebras based on graded exterior products.
This document attempts to be a somewhat self-contained description of the algebra implemented in the package. It is recommended to find more complete tutorials or learning materials on Geometric Algebra.
Blade Types with an associated algebra are generated by calling the macro @generate_basis(s)
where s
is a character string encoding the desired metric for each generating 1-vector of the algebra.
julia> @generate_basis("+++")
julia> show_basis()
UnionAll[e₁, e₂, e₃, e₁₂, e₁₃, e₂₃, e₁₂₃]
e₁, e₂, e₃ are the generating basis 1-vectors that are combined together with the wedge product, ∧
to form basis vectors of higher grades.
∧ is like the cross product but generates (hyper)planes/volumes of any dimension rather than the normal to a plane in 3D.
eᵢ∧eⱼ = 0 when i == j
eᵢ∧eⱼ = eᵢⱼ when i < j
eᵢ∧eⱼ = -eᵢⱼ when i > j
This completely specifies all subspace spanning k-vectors of the space.
Generate all possible combinations of wedge products starting with our orthogonal 1-vectors:
julia> abs.([eᵢ∧eⱼ for eᵢ in [1e₁, 1e₂, 1e₃] for eⱼ in [1e₁, 1e₂, 1e₃]]) |> unique |> c->filter(!iszero,c)
3-element Array{Number,1}:
1e₁₂
1e₁₃
1e₂₃
julia> abs.([eᵢ∧eⱼ for eᵢ in [1e₁, 1e₂, 1e₃] for eⱼ in ans]) |> unique |> c->filter(!iszero,c)
1-element Array{Number,1}:
1e₁₂₃
julia> abs.([eᵢ∧eⱼ for eᵢ in [1e₁, 1e₂, 1e₃] for eⱼ in ans]) |> unique |> c->filter(!iszero,c)
0-element Array{Int64,1}
The highest grade blade is known as the pseudoscalar, often written as I
.
The grade(b)
of a blade is the dimensionality of the subspace spanned by the k-blade. Same number as 'k' in k-blade, also the count of the number of indices in the Blade Type.
julia> 𝐼 = 1e₁₂₃; grade(𝐼) == length(subspace(𝐼)) == 3
true
julia> e₁₂₃ <: Blade{T,3} where T
true
Since the wedge product anti-commutes, the same basis k-blades can combine in two ways which have a differing sense of orientation. Note, Blades always orders k-blades indices in ascending manner.
julia> 1e₁∧1e₃
1e₁₃
julia> 1e₃∧1e₁
-1e₁₃
The metric defines the result when we operate on a given basis pair with an inner product. Also refered to as the quadratic form for the algebra.
Create an algebra with all 3 kinds of metrics, take all inner products. Note the result on the diagonal:
julia> module ProjectivizedSpaceTime
using Multivectors
@generate_basis("0-+++")
end
julia> g₁,g₂,g₃,g₄,g₅ = alle(ProjectivizedSpaceTime,5)[1:5]
julia> unitg = one.([g₁,g₂,g₃,g₄,g₅])
julia> reshape([gᵢ⋅gⱼ for gᵢ in unitg for gⱼ in unitg],(5,5))
5×5 Array{Int64,2}:
0 0 0 0 0
0 -1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
The inner product, ⋅
, choosen for Blades is the left contraction. For 1-blades it is the same as that used in vector algebra. This suffices for use in defining our quadratic form.
When blades of grade > 1 are involved it is not, in general, commutative, or even associative.
julia> a = 1e₁; b = 1e₂; c = 1e₃
1e₃
julia> B = a∧b
1e₁₂
julia> a⋅B
1e₂
julia> B⋅a
0
julia> a⋅(b⋅B)
-1
julia> (a⋅b)⋅B
0e₁₂
We could expand the algebra with the geometric product u*B = u∧B + u⋅B
.
Where u
is restricted to be 1-vector, due to non-commutativity/associativity of ⋅
.
The geometric product, addition and other operators on blades are better defined in a more general manner once we have Types for k-vectors and multivectors defined.
These Types and operators are defined by KVectors and Multivectors.
If we wished to we could define only addition of Blades with zero to complete our algebra of simple k-vectors ( blades ).
julia> Base.:+(a::B, b::Number) where {B<:Blade} = iszero(b) ? a : (a,b)
julia> Base.:+(a::Number, b::B) where {B<:Blade} = b+a
Afer defining these operators we could go back in this document and replace occurences of ∧
and ⋅
with *
to generate the k-blades and metric results using the geometric product.
Blades does define the geometric product without the need of the +
operator since only one of u∧B
or v⋅B
is ever non-zero. This fact expresses the geometric relationship of parallel and orthogonal vectors.
A k-blade is a blade of grade k. For any k-blade spanning a subspace of dimension k in vector space of dimension n, there exists an (n-k)-blade that represents the same object. This object is known as it's dual.
The orthogonal complement is very similar in that it is a map from a k-blade to an (n-k)-blade. Assuming the metric is non-degenerate. The difference is that the target space of the orthogonal complement is the same as the domain. For the dual it is better to think of the target space as not being the same space as the domain. The dual maps a geometric object to the same object in dual space.
Dual space is a very important concept in Projectivized Geometric Algebra. Blades optionally can generate a set of Types with raised indices if you wish to explicitly track which space you are in.
Both the notion of a metric dual and a non-metric dual are represented in Blades.
For a non-degenerate metric ( no 1-vectors square to 0 ) the dual
method is an alias for orthogonal_complement
, ⟂
, or !
.
Defined as !A = A*I⁻¹
where I⁻¹
is the inverse of the pseudoscalar.
It is prefered to not use dual
if what you really want is the orthogonal complement.
inv
the inverse operator is defined by inv(B) = reverse(B)/(B*reverse(B))
reverse
reverses the order of the generating 1-blades for the given Blade. Generally you end up with the same Blade, possibly with a sign (orientation) flip.
Since the inverse of the pseudoscalar does not exist when the metric is degenerate ( I*reverse(I) == 0
), we need an alternative mapping.
In the case of a degenerate metric, dual
is a mapping to/from projectivized dual space and primal space. This is done with a non-metric duality mapping that chooses a non-zero orthogonal complement in the dual space.
Both dual
and ⟂
can be thought of as taking a Blade to it's "other" space. e.g. plane to normal vector.
julia> cross(a,b) = !(a∧b)
cross (generic function with 1 method)
julia> cross(1e₁,1e₂)
1e₃
Raised indices can also be used to represent what is often called the reciprocal basis. The reciprocal basis is useful for geometry and calculus on curved surfaces. The reciprocal basis is meant to be independent of the metric when applied to a k-blade with lowered indices.
eᵢ⋅eʲ = δᵢⱼ
In this case you want to call @generate_basis
with options for reciprocal basis and zeroing mixed indices set to true
.
To enter these sybols into the Julia REPL or a Julia enabled editor.
e₁
: e\_1[Tab]e₁₂
: e\_1[Tab]\_2[Tab]∧
: \wedge[Tab]⟂
: \perp[Tab]⋅
: \cdot[Tab]⋆
: \star[Tab]
Simple blades alone are not terribly useful. For applications in geometry and simulation you will want to use Types built on Blades.