{ "cells": [ { "cell_type": "markdown", "metadata": { "nbsphinx": "hidden" }, "source": [ "This notebook is part of the `clifford` documentation: https://clifford.readthedocs.io/." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Space Time Algebra " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Intro" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook demonstrates how to use `clifford` to work with Space Time Algebra.\n", "The Pauli algebra of space $\\mathbb{P}$, and Dirac algebra of space-time $\\mathbb{D}$, are related using the *spacetime split*.\n", "The split is implemented by using a `BladeMap` ([docs](../api/clifford.BladeMap.rst)), which maps a subset of blades in $\\mathbb{D}$ to the blades in $\\mathbb{P}$.\n", "This *split* allows a spacetime bivector $F$ to be broken up into relative electric and magnetic fields in space.\n", "Lorentz transformations are implemented as rotations in $\\mathbb{D}$, and the effects on the relative fields are computed with the split. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "First we import `clifford`, instantiate the two algebras, and populate the namespace with the blades of each algebra.\n", "The elements of $\\mathbb{D}$ are prefixed with $d$, while the elements of $\\mathbb{P}$ are prefixed with $p$.\n", "Although unconventional, it is easier to read and to translate into code. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from clifford import Cl, pretty\n", "\n", "pretty(precision=1)\n", "\n", "# Dirac Algebra `D`\n", "D, D_blades = Cl(1,3, firstIdx=0, names='d')\n", "\n", "# Pauli Algebra `P`\n", "P, P_blades = Cl(3, names='p')\n", "\n", "# put elements of each in namespace\n", "locals().update(D_blades)\n", "locals().update(P_blades)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Space Time Split" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To two algebras can be related by the spacetime-split.\n", "First, we create a `BladeMap` which relates the bivectors in $\\mathbb{D}$ to the vectors/bivectors in $\\mathbb{P}$.\n", "The scalars and pseudo-scalars in each algebra are equated.\n", "\n", "![](../_static/split.svg)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from clifford import BladeMap\n", "\n", "bm = BladeMap([(d01,p1),\n", " (d02,p2),\n", " (d03,p3),\n", " (d12,p12),\n", " (d23,p23),\n", " (d13,p13),\n", " (d0123, p123)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Splitting a space-time vector (an event)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A vector in $\\mathbb{D}$, represents a unique place in space and time, i.e. an event.\n", "To illustrate the split, create a random event $X$. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = D.randomV()*10\n", "X" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This can be *split* into time and space components by multiplying with the time-vector $d_0$," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X*d0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " and applying the `BladeMap`, which results in a scalar+vector in $\\mathbb{P}$\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bm(X*d0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The space and time components can be separated by grade projection, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = bm(X*d0)\n", "x(0) # the time component" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x(1) # the space component" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We therefor define a `split()` function, which has a simple condition allowing it to act on a vector or a multivector in $\\mathbb{D}$.\n", "Splitting a spacetime bivector will be treated in the next section. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def split(X):\n", " return bm(X.odd*d0+X.even)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split(X)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The split can be inverted by applying the `BladeMap` again, and multiplying by $d_0$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = split(X)\n", "bm(x)*d0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Splitting a Bivector" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Given a random bivector $F$ in $\\mathbb{D}$," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "F = D.randomMV()(2)\n", "F" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$F$ *splits* into a vector/bivector in $\\mathbb{P}$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split(F)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If $F$ is interpreted as the electromagnetic bivector, the Electric and Magnetic fields can be separated by grade " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "E = split(F)(1)\n", "iB = split(F)(2)\n", "\n", "E" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iB" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lorentz Transformations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lorentz Transformations are rotations in $\\mathbb{D}$, which are implemented with Rotors.\n", "A rotor in G4 will, in general, have scalar, bivector, and quadvector components." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "R = D.randomRotor()\n", "R" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this way, the effect of a lorentz transformation on the electric and magnetic fields can be computed by rotating the bivector with $F \\rightarrow RF\\tilde{R}$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "F_ = R*F*~R\n", "F_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then splitting into $E$ and $B$ fields" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "E_ = split(F_)(1)\n", "E_" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iB_ = split(F_)(2)\n", "iB_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lorentz Invariants" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since lorentz rotations in $\\mathbb{D}$, the magnitude of elements of $\\mathbb{D}$ are invariants of the lorentz transformation.\n", "For example, the magnitude of electromagnetic bivector $F$ is invariant, and it can be related to $E$ and $B$ fields in $\\mathbb{P}$ through the split," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = p123 \n", "E = split(F)(1)\n", "B = -i*split(F)(2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "F**2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split(F**2) == E**2 - B**2 + (2*E|B)*i" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" } }, "nbformat": 4, "nbformat_minor": 2 }