Lyra Geometry is a Python library for symbolic differential geometry with a focus on tensor spaces, connections, and curvature in Lyra geometry. It is built on SymPy to support exact tensor manipulation in scripts and notebooks.
- Tensor spaces with index notation (up/down indices).
- Lyra connection and curvature tensors derived from a metric.
- Automatic Einstein summation for repeated labels.
- Covariant derivatives, torsion, and non-metricity support.
- Friendly API designed for interactive exploration.
- Python >= 3.9
- SymPy >= 1.12
python -m pip install lyra-geometryFor local development:
python -m pip install -e .[dev]Core objects:
SpaceTime(coords, metric, connection_strategy=...): main high-level API for metrics, connections, and curvature.st = pl.SpaceTime(coords=(x, y), metric=sp.diag(1, 1)) st.riemann
TensorSpace(dim, labels=...): lower-level tensor space without a metric.ts = pl.TensorSpace(dim=2, labels=("x", "y"))
Tensor: tensor container with index-aware arithmetic and contractions.t = st.tensor.generic("T", (pl.U, pl.D)) t[+a, -b]
Index,UpIndex,DownIndex: index labels and variance markers.a, b = st.index("a b") st.g[-a, -b]
U,D: convenience aliases for up/down index variance.v = st.tensor.generic("v", (pl.U,)) w = st.tensor.generic("w", (pl.D,))
Connection and curvature strategies:
LyraConnectionStrategy,LyraCurvatureStrategy: default Lyra geometry behavior.st = pl.SpaceTime(coords=(x, y), metric=sp.diag(1, 1)) st.gamma
FixedConnectionStrategy: use a fixed connection tensor.Gamma0 = sp.ImmutableDenseNDimArray([0] * 8, (2, 2, 2)) st = pl.SpaceTime(coords=(x, y), metric=sp.diag(1, 1), connection_strategy=pl.FixedConnectionStrategy(Gamma0))
Connection,ConnectionTensor,CurvatureStrategy: building blocks for custom strategies.
Helpers:
example_indexing(): small demo of index notation.pl.example_indexing()
greek(): helper for common Greek index labels.mu, nu = pl.greek("mu nu")
TensorSpace and SpaceTime accept a riemann_convention parameter to control
the overall sign of the curvature tensors. The default is "mtw"/"wald" and
matches the current library behavior:
R^rho_{ sigma mu nu } = d_mu Gamma^rho_{nu sigma}
- d_nu Gamma^rho_{mu sigma}
+ Gamma^rho_{mu lambda} Gamma^lambda_{nu sigma}
- Gamma^rho_{nu lambda} Gamma^lambda_{mu sigma}
Choosing "landau-lifshitz"/"weinberg" flips the global sign of the Riemann,
Ricci, and scalar curvature tensors.
st = pl.SpaceTime(coords=(x, y), metric=sp.diag(1, 1), riemann_convention="landau-lifshitz")The public API continues to be re-exported from lyra_geometry, but the
implementation is organized by responsibility:
lyra_geometry.core: tensor spaces, connections, curvature strategies.lyra_geometry.tensors: tensors, indices, and low-level tensor helpers.lyra_geometry.diff_ops: gradient/divergence/laplacian helpers.lyra_geometry.invariants: Ricci/Kretschmann/Euler invariants.lyra_geometry.utils: small utilities likegreekandexample_indexing.
The lyra-geometry is a symbolic library to work with relativistic gravity thoeries. Concretely, lyra-geometry provides:
- Exact symbolic tensor calculus built on top of SymPy.
- A clean, object-oriented
SpaceTimeabstraction that organizes:- metric, inverse metric, and determinant,
- Levi–Civita connection (by default),
- Riemann, Ricci, Einstein tensors, and scalar curvature,
- covariant derivatives with correct index bookkeeping.
- Explicit index variance (up/down indices) with:
- readable index notation,
- automatic Einstein summation on repeated labels.
- A workflow designed for interactive notebooks and analytic derivations, where expressions remain transparent and inspectable at every step.
In this default configuration, lyra-geometry behaves exactly as a symbolic
GR toolkit.
Where the library extends beyond standard GR is in its native support for Lyra geometry and related non-Riemannian structures:
- the Lyra scale field
$\phi$ can be introduced when desired, - alternative connection strategies,
- optional torsion and non-metricity sectors.
These features are opt-in. They do not interfere with ordinary GR unless explicitly enabled.
In short:
lyra-geometry is a symbolic GR library first, and a Lyra-geometry laboratory
second.
To set expectations clearly, lyra-geometry is not:
- A numerical relativity or cosmological simulation framework.
- A high-performance or HPC-oriented tensor engine.
- A “black-box” solver that automatically derives or solves field equations.
- A replacement for large, monolithic CAS environments (e.g. full SageMath).
- A library that enforces Lyra geometry or non-Riemannian assumptions by default.
If you never introduce a scale field, torsion, or non-metricity, the library remains purely Riemannian and fully compatible with standard GR practice.
lyra-geometry is particularly well suited if you want to:
- perform symbolic GR calculations with explicit index control,
- derive connections and curvature tensors from a metric in a reproducible way,
- check lengthy analytic derivations while minimizing index errors,
- work entirely in Python notebooks with a clean, inspectable API,
- explore extensions of GR (Lyra geometry, alternative connections) without rewriting your tensor infrastructure.
If your primary goal is large-scale numerics, data-driven cosmology, or observational pipelines, this library is best used in combination with other tools, or not at all.
| Library | Symbolic | Index Notation | Automatic Contraction | Curvature & Connection | Lyra Geometry | Numeric Focus | Philosophy |
|---|---|---|---|---|---|---|---|
| SymPy (tensor) | ✅ | ❌ | ❌ | General-purpose CAS | |||
| EinsteinPy | ✅ | ✅ | ✅ (GR) | ❌ | ✅ | End-to-end GR | |
| SageManifolds | ✅ | ✅ | ✅ | ✅ (very rich) | ❌ | Full math environment | |
| Cadabra | ✅ | ✅ | ✅ (very strong) | ❌ | ❌ | QFT/GR CAS | |
| OGRePy | ✅ | ✅ | ✅ | ✅ (GR) | ❌ | ❌ | OO GR toolkit |
| RicciPy | ✅ | ✅ (GR) | ❌ | ❌ | Ricci calculus | ||
| Pytearcat | ✅ | ✅ | ✅ | ❌ | ❌ | GR calculator | |
| galgebra | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | Geometric algebra |
| PyMetric | ❌ | ❌ | ❌ | Coord-based DG | |||
| lyra-geometry | ✅ | ✅ (core) | ✅ (automatic) | ✅ (Lyra & Riemann) | ✅ | ❌ | Symbolic DG focused on Lyra |
Create a space with a metric, then inspect its basic objects:
import sympy as sp
import lyra_geometry as pl
x, y = sp.symbols("x y", real=True)
metric = sp.diag(x + 2*y, x**2 * y)
st = pl.SpaceTime(coords=(x, y), metric=metric)
st.g # metric tensor
st.metric_inv # inverse metric matrix
st.detg # determinant of the metricUse index labels with explicit variance markers to access components:
a, b, c = st.index("a b c")
st.g[-a, -b] # g_ab
st.g[+a, +b] # g^ab
st.g[-a, -b](0, 0) # component accessBare indices (like t[a, b]) are not accepted; always use +a/-a.
Create symbolic tensors and let repeated labels contract automatically:
v = st.tensor.generic("v", (pl.U,))
w = st.tensor.generic("w", (pl.D,))
scalar = v[+a] * w[-a] # automatic contractionExplicit contraction and a simple index-string parser are also available:
st.contract(v[+a], w[-a])
st.eval_contract("v^a w_a")The Lyra covariant derivative adds one covariant index:
dv = st.nabla(v)
dv.signature # (D, U)
dv[-b, +a](0, 0)When a metric is provided, the Lyra connection and curvature tensors are computed automatically:
st.gamma # Gamma^a_{bc}
st.riemann # Riemann tensor
st.ricci # Ricci tensor
st.einstein # Einstein tensor
st.scalar_curvature # scalar curvatureYou can set a scale field and provide torsion/non-metricity explicitly:
phi = sp.Function("phi")(x)
st.set_scale(phi)
st.set_torsion(st.zeros((pl.D, pl.D, pl.D)))
st.set_nonmetricity(st.zeros((pl.U, pl.D, pl.D)))
st.update()If you already have Gamma components, you can fix the connection manually:
Gamma0 = sp.ImmutableDenseNDimArray([0] * (2**3), (2, 2, 2))
st2 = pl.SpaceTime(
coords=(x, y),
metric=sp.diag(1, 1),
connection_strategy=pl.FixedConnectionStrategy(Gamma0),
)
st2.gammaUse fmt() to expand and simplify expressions:
st.ricci.fmt()
st.einstein.fmt()
st.scalar_curvature.fmt()The notebook examples/example.ipynb walks through:
- A quick tutorial of the core API.
- Schwarzschild spacetime: metric, connection, and curvature tensors.
- FLRW spacetime: metric, curvature, and covariant derivative of a scalar.
- A spherically symmetric LyST solution with scale field and field equations.
src/lyra_geometry/core.py: core implementation.src/lyra_geometry/__init__.py: public exports and version.examples/example.ipynb: tutorial and physics examples.tests/: pytest smoke tests.
python -m pytestThis project follows SemVer 2.0 with a pre-1.0 policy:
- While major is 0, breaking changes bump the minor version.
- Backward-compatible changes (features, improvements) also bump the minor.
- Fixes that do not change behavior bump the patch.
The public API is the set of objects exported from src/lyra_geometry/__init__.py
and the behaviors documented in this README. Other internal modules may change
without notice.
Release checklist (short form):
- Move items from
Unreleasedinto a new version section inCHANGELOG.md. - Bump the version in
src/lyra_geometry/__init__.py. - Run
python -m pytestand record the outcome in the release notes. - Tag and publish the release.
MIT. See LICENSE.