sXAct.jl — Getting Started
Note: Auto-generated from
notebooks/julia/basics.qmdvia Quarto. Edit the source.qmdfile, not the.ipynb.
Overview
This notebook walks through the core workflow of XAct.jl: defining a spacetime manifold, adding a metric, computing curvature tensors, and simplifying expressions using the Butler-Portugal canonicalization algorithm.
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.
Google Colab: select Runtime → Change runtime type → Julia.
1. Setup
If running on Google Colab or a fresh environment, install the package first. In the Docker image or a local dev checkout this cell is a no-op.
# Uncomment the lines below if running on Google Colab:
# using Pkg
# Pkg.add(url="https://github.com/sashakile/XAct.jl.git")2. Setup
using XAct2. Define a Manifold
A 4-dimensional spacetime manifold $M$ with abstract indices $a, b, c, d, e, f$.
@indices declares typed index variables bound to the manifold — -a then gives a covariant (down) index.
reset_state!()
M = def_manifold!(:M, 4, [:a, :b, :c, :d, :e, :f])
@indices M a b c d e f3. Define a Metric
The metric $g_{ab}$ with Lorentzian signature $(-,+,+,+)$ and covariant derivative $\nabla$ (called CD internally). This automatically creates Riemann, Ricci, RicciScalar, Weyl, Einstein, and Christoffel tensors.
g = def_metric!(-1, "g[-a,-b]", :CD)
# Grab tensor handles for use throughout the notebook.
Riem = tensor(:RiemannCD)
Ric = tensor(:RicciCD)
g_h = tensor(:g)TensorHead(:g)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$:
ToCanonical(g_h[-b,-a] - g_h[-a,-b])0
Define a symmetric rank-2 tensor $T_{ab}$ (e.g. the energy-momentum tensor) and verify symmetry:
def_tensor!(:T, ["-a", "-b"], :M; symmetry_str="Symmetric[{-a,-b}]")
T_h = tensor(:T)
ToCanonical(T_h[-b,-a] - T_h[-a,-b])0
String API:
ToCanonical("T[-b,-a] - T[-a,-b]")is equivalent. Strings still work everywhere; the typed API adds upfront validation.
5. Contraction
Contract lowers/raises indices via the metric. Define a vector $V^a$ and contract with the metric to get $V_b$:
def_tensor!(:V, ["a"], :M)
V_h = tensor(:V)
Contract(V_h[a] * g_h[-a,-b])\V_{\b}
6. Riemann Tensor Identities
The Riemann tensor has well-known symmetries that the canonicalizer automatically recognizes.
First Bianchi identity — $R_{abcd} + R_{acdb} + R_{adbc} = 0$:
ToCanonical(Riem[-a,-b,-c,-d] + Riem[-a,-c,-d,-b] + Riem[-a,-d,-b,-c])0
Antisymmetry in the first pair — $R_{abcd} + R_{bacd} = 0$:
ToCanonical(Riem[-a,-b,-c,-d] + Riem[-b,-a,-c,-d])0
Pair symmetry — $R_{abcd} = R_{cdab}$:
ToCanonical(Riem[-a,-b,-c,-d] - Riem[-c,-d,-a,-b])0
7. Perturbation Theory
Define a perturbation tensor $h_{ab}$ (symmetric, same slots as the metric) and perturb the metric to first order:
def_tensor!(:h, ["-a", "-b"], :M; symmetry_str="Symmetric[{-a,-b}]")
def_perturbation!(:h, :g, 1)
perturb(g_h[-a,-b], 1)\h
8. Validation
The typed API catches mistakes at construction time:
# Wrong slot count — raised before reaching the engine
try
Riem[-a,-b] # ERROR: RiemannCD has 4 slots, got 2
catch e
println(e)
end┌ Warning: Assignment to `e` in soft scope is ambiguous because a global variable by the same name exists: `e` will be treated as a new local. Disambiguate by using `local e` to suppress this warning or `global e` to assign to the existing global variable.
└ @ basics_julia.md:143
ErrorException("RiemannCD has 4 slots, got 2")Next Steps
- Coordinate components (xCoba): assign a basis, compute Christoffel symbols numerically
- Covariant derivatives: commute CovDs, integration by parts
- Invariant simplification:
RiemannSimplifyfor scalar polynomial identities - Full documentation: sashakile.github.io/sxAct