Riemann Invariant Simplification (Invar)
This tutorial covers the use of the Invar module for simplifying scalar polynomial invariants of the Riemann tensor. This is essential for proving the equivalence of different spacetime metrics.
1. Setup
We'll need a manifold and a metric to work with.
Julia
using XAct
reset_state!()
def_manifold!(:M, 4, [:a, :b, :c, :d, :e, :f, :g, :h])
def_metric!(-1, "g[-a,-b]", :CD)MetricObj(:g, :M, :CD, -1)Python
import xact
xact.reset()
M = xact.Manifold("M", 4, ["a", "b", "c", "d", "e", "f", "g", "h"])
g = xact.Metric(M, "g", signature=-1, covd="CD")2. RiemannToPerm
The core of the Invar pipeline is converting tensor expressions into a canonical permutation representation.
Julia
expr = "RiemannCD[-a, -b, b, a]"
res = RiemannToPerm(expr, :CD)1-element Vector{Tuple{Rational{Int64}, RPerm}}:
(-1, RPerm(:CD, InvariantCase([0]), [3, 4, 1, 2]))RiemannToPerm may return a single RPerm or a vector of (coeff, RPerm)
rperm = res isa RPerm ? res : res[1][2]
println("Permutation form: ", rperm.perm)Permutation form: [3, 4, 1, 2]Python
rperm = xact.riemann_to_perm("RiemannCD[-a, -b, b, a]", "CD")
print(f"Permutation: {rperm}")3. Loading the Invar Database
RiemannSimplify requires the pre-computed Invar database. The database ships with Wolfram xAct and must be available at resources/xAct/Invar/.
invar_db_dir = joinpath(@__DIR__, "..", "..", "resources", "xAct", "Invar")
_has_invar_db = isdir(invar_db_dir) && isdir(joinpath(invar_db_dir, "Riemann"))
if _has_invar_db
LoadInvarDB(invar_db_dir)
println("Invar database loaded")
else
@warn "Invar database not found at $invar_db_dir — skipping RiemannSimplify examples"
end┌ Warning: Invar database not found at /home/runner/work/XAct.jl/XAct.jl/docs/build/examples/../../resources/xAct/Invar — skipping RiemannSimplify examples
└ @ Main invar.md:674. RiemannSimplify
RiemannSimplify is the high-level entry point for simplifying Riemann invariants. It uses a pre-computed database of multi-term identities.
Consider the Kretschmann scalar. Different dummy index labelings should simplify to the same canonical form.
Julia
expr1 = "RiemannCD[-a,-b,-c,-d] RiemannCD[a,b,c,d]"
expr2 = "RiemannCD[-c,-d,-a,-b] RiemannCD[c,d,a,b]"
diff = "$expr1 - $expr2"
_has_invar_db && println("Difference simplified: ", RiemannSimplify(diff, :CD))falsePython
diff = "RiemannCD[-a,-b,-c,-d] RiemannCD[a,b,c,d] - RiemannCD[-c,-d,-a,-b] RiemannCD[c,d,a,b]"
result = xact.riemann_simplify(diff, "CD")
print(f"Result: {result}")Wolfram (xAct)
RiemannSimplify[RiemannCD[-a,-b,-c,-d] RiemannCD[a,b,c,d] - RiemannCD[-c,-d,-a,-b] RiemannCD[c,d,a,b], CD]
(* returns 0 *)5. Simplification Levels
You can control the depth of simplification using the level parameter:
- Identity only
- Monoterm (cyclic)
- Bianchi identities
- Covariant derivative commutation
- Dimension-dependent identities
- Dual invariants (4D only)
Julia
expr = "2 RiemannCD[-a,-b,-c,-d] RiemannCD[a,c,b,d] + RiemannCD[-a,-b,-c,-d] RiemannCD[a,b,c,d]"
_has_invar_db && println("Level 2: ", RiemannSimplify(expr, :CD; level=2))
_has_invar_db && println("Level 3: ", RiemannSimplify(expr, :CD; level=3))false6. Dual Invariants (4D)
In 4 dimensions, we can simplify invariants involving the Levi-Civita epsilon tensor (represented as DualRiemann in Wolfram, or via n_epsilon=1 cases in Invar).
Julia Dual invariants are only supported if dim=4.
_has_invar_db && println(
"Level 6 (4D) result: ",
RiemannSimplify("RiemannCD[-a, -b, b, a]", :CD; level=6, dim=4),
)false7. Summary
The Invar module provides:
RiemannToPerm: Tensor string → Canonical PermutationPermToRiemann: Canonical Permutation → Tensor stringRiemannSimplify: End-to-end multi-term simplificationInvSimplify: Low-level simplification of invariant lists
This page was generated using Literate.jl.