sxAct — Getting Started (Python)
Note: Auto-generated from
notebooks/python/basics.qmdvia Quarto. Edit the source.qmdfile, not the.ipynb.
Overview
This notebook walks through the same workflow as the Julia version, using the xact Python package. Under the hood, all computation is performed by the Julia engine — but the API is fully Pythonic.
Expressions are written using the typed API — index objects and operator overloading — which validates slot counts and manifold membership at construction time rather than deep inside the engine.
Requirements: Python 3.10+, Julia 1.10+.
1. Setup
If xact is not already installed, install the published xact-py release first. Only use a local checkout of this repository if you explicitly need unreleased changes while developing.
# | eval: false
import importlib
import sys
if (
"google.colab" in sys.modules
or "BINDER_SERVICE_HOST" in __import__("os").environ
or importlib.util.find_spec("xact") is None
):
!pip install -q xact-pyLoad the module.
import xact
xact.reset()2. Define a Manifold
A 4-dimensional spacetime manifold with abstract indices.
xact.indices() returns typed index objects bound to the manifold — -a then gives a covariant (down) index.
M = xact.Manifold("M", 4, ["a", "b", "c", "d", "e", "f"])
a, b, c, d, e, f = xact.indices(M)3. Define a Metric
Lorentzian signature, covariant derivative CD. Automatically creates Riemann, Ricci, Weyl, Einstein, Christoffel.
g = xact.Metric(M, "g", signature=-1, covd="CD")
# Grab tensor handles for use throughout the notebook.
Riem = xact.tensor("RiemannCD")
Ric = xact.tensor("RicciCD")4. Canonicalization
The Butler-Portugal algorithm brings tensor expressions into a canonical form. Build expressions with [] — the tensor handle validates the slot count and manifold membership immediately.
Symmetric metric: $g_{ba} - g_{ab} = 0$:
xact.canonicalize(g[-b, -a] - g[-a, -b])Define a symmetric rank-2 tensor $T_{ab}$ and verify symmetry:
T = xact.Tensor("T", ["-a", "-b"], M, symmetry="Symmetric[{-a,-b}]")
T_h = xact.tensor("T")
xact.canonicalize(T_h[-b, -a] - T_h[-a, -b])String API:
xact.canonicalize("T[-b,-a] - T[-a,-b]")is equivalent. Strings still work everywhere; the typed API adds upfront validation.
5. Contraction
Lower an index with the metric:
V = xact.Tensor("V", ["a"], M)
V_h = xact.tensor("V")
xact.contract(V_h[a] * g[-a, -b])6. Riemann Identities
First Bianchi identity — $R_{abcd} + R_{acdb} + R_{adbc} = 0$:
xact.canonicalize(Riem[-a, -b, -c, -d] + Riem[-a, -c, -d, -b] + Riem[-a, -d, -b, -c])Antisymmetry in the first pair — $R_{abcd} + R_{bacd} = 0$:
xact.canonicalize(Riem[-a, -b, -c, -d] + Riem[-b, -a, -c, -d])Pair symmetry — $R_{abcd} = R_{cdab}$:
xact.canonicalize(Riem[-a, -b, -c, -d] - Riem[-c, -d, -a, -b])7. Perturbation Theory
h = xact.Tensor("h", ["-a", "-b"], M, symmetry="Symmetric[{-a,-b}]")
xact.Perturbation(h, g, order=1)
xact.perturb(g[-a, -b], order=1)8. Validation
The typed API catches mistakes at construction time:
# Wrong slot count — raised before reaching the engine
try:
Riem[-a, -b] # IndexError: RiemannCD has 4 slots, got 2
except IndexError as err:
print(err)Next Steps
- Full Julia API for more advanced workflows
- Coordinate components, covariant derivative commutation
- Documentation: sashakile.github.io/sxAct