In this blog post, we will explore the Grassmann.jl library written in Julia for working with Clifford algebras.
First, we import the library and the GLMakie
plotting library.
using Grassmann
using GLMakie
set_theme!(theme_light())
The following code constructs a positive definite 3-dimensional TensorBundle
with an additional plane at infinity:
@basis S"∞+++"
(⟨∞111⟩, v, v∞, v₁, v₂, v₃, v∞₁, v∞₂, v∞₃, v₁₂, v₁₃, v₂₃, v∞₁₂, v∞₁₃, v∞₂₃, v₁₂₃, v∞₁₂₃)
then plot the following vector field:
$$ \exp\left(\frac{\frac{\pi}{2}(v_{12}+v_{\infty3})}{2}\right) $$First we project it into the submanifold $\langle\infty++\_\rangle$:
streamplot(
vectorfield(
exp((π/2)*(v12+v∞3)/2),
V(1,2,3),V(1,2,3)
),-1.5..1.5,-1.5..1.5,-1.5..1.5,gridsize=(12,12))
Then we project it into the submanifold $\langle\_+++\rangle$:
speed = Observable{Float64}(0.0)
vf = @lift(vectorfield(
exp((π/2)*(v12+$speed*v∞3)/2),
V(2,3,4),V(2,3,4)
))
fig, ax, pl = streamplot(vf,-1.5..1.5,-1.5..1.5,-1.5..1.5,gridsize=(12,12))
framerate = 24
timestamps = range(0, 2, step=1/framerate)
record(fig, "streamplot.mp4", timestamps; framerate = framerate) do t
speed[] = Float64(t/10.0)
# ax.azimuth[] = 1.7pi + 0.3 * sin(2pi * t / 120)
# pl.colorrange = (0, t)
end
"streamplot.mp4"
basis"2" # Euclidean
streamplot(vectorfield(v1*exp((π/4)*v12/2)),-1.5..1.5,-1.5..1.5)
@basis S"+-" # Hyperbolic
streamplot(vectorfield(v1*exp((π/4)*v12/2)),-1.5..1.5,-1.5..1.5)
@basis S"∞+++"
f(t) = (↓(exp(π*t*((3/7)*v12+v∞3))>>>↑(v1+v2+v3)))
lines(V(2,3,4).(points(f)))
Base.@kwdef mutable struct Lorenz
dt::Float64 = 0.01
σ::Float64 = 10
ρ::Float64 = 28
β::Float64 = 8/3
x::Float64 = 1
y::Float64 = 1
z::Float64 = 1
end
function step!(l::Lorenz)
dx = l.σ * (l.y - l.x)
dy = l.x * (l.ρ - l.z) - l.y
dz = l.x * l.y - l.β * l.z
l.x += l.dt * dx
l.y += l.dt * dy
l.z += l.dt * dz
Point3f(l.x, l.y, l.z)
end
attractor = Lorenz()
lorenz_points = Observable(Point3f[])
colors = Observable(Int[])
set_theme!(theme_black())
fig, ax, l = lines(lorenz_points, color = colors,
colormap = :inferno, transparency = true,
axis = (; type = Axis3, protrusions = (0, 0, 0, 0),
viewmode = :fit, limits = (-30, 30, -30, 30, 0, 50)))
record(fig, "lorenz.mp4", 1:120) do frame
for i in 1:50
push!(lorenz_points[], step!(attractor))
push!(colors[], frame)
end
ax.azimuth[] = 1.7pi + 0.3 * sin(2pi * frame / 120)
notify(lorenz_points)
notify(colors)
l.colorrange = (0, frame)
end
"lorenz.mp4"