sXAct.jl — Interactive Tutorial

This Pluto notebook introduces the core workflow of XAct.jl: manifolds, metrics, canonicalization, and curvature.

Expressions are written using the typed API@indices declares index objects, tensor() looks up handles, and T[-a,-b] builds expressions with slot-count and manifold validation at construction time.

Each cell is reactive — editing a definition automatically re-evaluates all dependent cells.

begin
    import Pkg
    Pkg.activate(joinpath(@__DIR__, "..", ".."))
    using XAct
end

1. Define a Manifold

begin
    reset_state!()
    M = def_manifold!(:M, 4, [:a, :b, :c, :d, :e, :f])
    @indices M a b c d e f
end

2. Define a Metric

Lorentzian signature \((-,+,+,+)\). This automatically creates Riemann, Ricci, RicciScalar, Weyl, Einstein, and Christoffel tensors.

begin
    g = def_metric!(-1, "g[-a,-b]", :CD)
    Riem = tensor(:RiemannCD)
    Ric  = tensor(:RicciCD)
    g_h  = tensor(:g)
end
TensorHead(:g)

3. Canonicalization

The Butler-Portugal algorithm brings tensor expressions to canonical form. Expressions are built with [] — wrong slot count or manifold raises an error immediately, before reaching the engine.

ToCanonical(g_h[-b,-a] - g_h[-a,-b])

$$0$$

begin
    def_tensor!(:T, ["-a", "-b"], :M; symmetry_str="Symmetric[{-a,-b}]")
    T_h = tensor(:T)
    ToCanonical(T_h[-b,-a] - T_h[-a,-b])
end

$$0$$

4. Contraction

Lower an index with the metric — \(V_b = V^a g_{ab}\):

begin
    def_tensor!(:V, ["a"], :M)
    V_h = tensor(:V)
    Contract(V_h[a] * g_h[-a,-b])
end

$$\V_{\b}$$

5. Riemann Tensor Identities

The Riemann tensor satisfies 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$$

6. Perturbation Theory

Perturb the metric to first order:

begin
    def_tensor!(:h, ["-a", "-b"], :M; symmetry_str="Symmetric[{-a,-b}]")
    def_perturbation!(:h, :g, 1)
    perturb(g_h[-a,-b], 1)
end

$$\h$$

7. Validation

The typed API raises errors at construction time — before the expression reaches the engine:

try
    Riem[-a,-b]     # ERROR: RiemannCD has 4 slots, got 2
catch e
    e
end
ErrorException("RiemannCD has 4 slots, got 2")