Pseudo-Riemannian Manifolds

A pseudo-Riemannian manifold is a pair \((M,g)\) where \(M\) is a real differentiable manifold \(M\) (see DifferentiableManifold) and \(g\) is a field of non-degenerate symmetric bilinear forms on \(M\), which is called the metric tensor, or simply the metric (see PseudoRiemannianMetric).

Two important subcases are

  • Riemannian manifold: the metric \(g\) is positive definite, i.e. its signature is \(n = \dim M\);
  • Lorentzian manifold: the metric \(g\) has signature \(n-2\) (positive convention) or \(2-n\) (negative convention).

On a pseudo-Riemannian manifold, one may use various standard operators acting on scalar and tensor fields, like grad() or div().

All pseudo-Riemannian manifolds, whatever the metric signature, are implemented via the class PseudoRiemannianManifold.

Example 1: the sphere as a Riemannian manifold of dimension 2

We start by declaring \(S^2\) as a 2-dimensional Riemannian manifold:

sage: M = Manifold(2, 'S^2', structure='Riemannian')
sage: M
2-dimensional Riemannian manifold S^2

We then cover \(S^2\) by two stereographic charts, from the North pole and from the South pole respectively:

sage: U = M.open_subset('U')
sage: stereoN.<x,y> = U.chart()
sage: V = M.open_subset('V')
sage: stereoS.<u,v> = V.chart()
sage: M.declare_union(U,V)
sage: stereoN_to_S = stereoN.transition_map(stereoS,
....:                [x/(x^2+y^2), y/(x^2+y^2)], intersection_name='W',
....:                restrictions1= x^2+y^2!=0, restrictions2= u^2+v^2!=0)
sage: W = U.intersection(V)
sage: stereoN_to_S
Change of coordinates from Chart (W, (x, y)) to Chart (W, (u, v))
sage: stereoN_to_S.display()
u = x/(x^2 + y^2)
v = y/(x^2 + y^2)
sage: stereoN_to_S.inverse().display()
x = u/(u^2 + v^2)
y = v/(u^2 + v^2)

We get the metric defining the Riemannian structure by:

sage: g = M.metric()
sage: g
Riemannian metric g on the 2-dimensional Riemannian manifold S^2

At this stage, the metric \(g\) is defined as a Python object but there remains to initialize it by setting its components with respect to the vector frames associated with the stereographic coordinates. Let us begin with the frame of chart stereoN:

sage: eU = stereoN.frame()
sage: g[eU, 0, 0] = 4/(1 + x^2 + y^2)^2
sage: g[eU, 1, 1] = 4/(1 + x^2 + y^2)^2

The metric components in the frame of chart stereoS are obtained by continuation of the expressions found in \(W = U\cap V\) from the known change-of-coordinate formulas:

sage: eV = stereoS.frame()
sage: g.add_comp_by_continuation(eV, W)

At this stage, the metric \(g\) is well defined in all \(S^2\):

sage: g.display(eU)
g = 4/(x^2 + y^2 + 1)^2 dx*dx + 4/(x^2 + y^2 + 1)^2 dy*dy
sage: g.display(eV)
g = 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) du*du
 + 4/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1) dv*dv

The expression in frame eV can be given a shape similar to that in frame eU, by factorizing the components:

sage: g[eV, 0, 0].factor()
4/(u^2 + v^2 + 1)^2
sage: g[eV, 1, 1].factor()
4/(u^2 + v^2 + 1)^2
sage: g.display(eV)
g = 4/(u^2 + v^2 + 1)^2 du*du + 4/(u^2 + v^2 + 1)^2 dv*dv

Let us consider a scalar field \(f\) on \(S^2\):

sage: f = M.scalar_field({stereoN: 1/(1+x^2+y^2)}, name='f')
sage: f.add_expr_by_continuation(stereoS, W)
sage: f.display()
f: S^2 --> R
on U: (x, y) |--> 1/(x^2 + y^2 + 1)
on V: (u, v) |--> (u^2 + v^2)/(u^2 + v^2 + 1)

The gradient of \(f\) (with respect to the metric \(g\)) is:

sage: gradf = f.gradient()
sage: gradf
Vector field grad(f) on the 2-dimensional Riemannian manifold S^2
sage: gradf.display(eU)
grad(f) = -1/2*x d/dx - 1/2*y d/dy
sage: gradf.display(eV)
grad(f) = 1/2*u d/du + 1/2*v d/dv

It is possible to write grad(f) instead of f.gradient(), by importing the standard differential operators of vector calculus:

sage: from sage.manifolds.operators import *
sage: grad(f) == gradf
True

The Laplacian of \(f\) (with respect to the metric \(g\)) is obtained either as f.laplacian() or, thanks to the above import, as laplacian(f):

sage: Df = laplacian(f)
sage: Df
Scalar field Delta(f) on the 2-dimensional Riemannian manifold S^2
sage: Df.display()
Delta(f): S^2 --> R
on U: (x, y) |--> (x^2 + y^2 - 1)/(x^2 + y^2 + 1)
on V: (u, v) |--> -(u^2 + v^2 - 1)/(u^2 + v^2 + 1)

Let us check the standard formula \(\Delta f = \mathrm{div}( \mathrm{grad}\, f )\):

sage: Df == div(gradf)
True

Since each open subset of \(S^2\) inherits the structure of a Riemannian manifold, we can get the metric on it via the method metric():

sage: gU = U.metric()
sage: gU
Riemannian metric g on the Open subset U of the 2-dimensional Riemannian
 manifold S^2
sage: gU.display()
g = 4/(x^2 + y^2 + 1)^2 dx*dx + 4/(x^2 + y^2 + 1)^2 dy*dy

Of course, gU is nothing but the restriction of \(g\) to \(U\):

sage: gU is g.restrict(U)
True

Example 2: Minkowski spacetime as a Lorentzian manifold of dimension 4

We start by declaring a 4-dimensional Lorentzian manifold \(M\):

sage: M = Manifold(4, 'M', structure='Lorentzian')
sage: M
4-dimensional Lorentzian manifold M

We define Minkowskian coordinates on \(M\):

sage: X.<t,x,y,z> = M.chart()

We construct the metric tensor by:

sage: g = M.metric()
sage: g
Lorentzian metric g on the 4-dimensional Lorentzian manifold M

and initialize it to the Minkowskian value:

sage: g[0,0], g[1,1], g[2,2], g[3,3] = -1, 1, 1, 1
sage: g.display()
g = -dt*dt + dx*dx + dy*dy + dz*dz
sage: g[:]
[-1  0  0  0]
[ 0  1  0  0]
[ 0  0  1  0]
[ 0  0  0  1]

We may check that the metric is flat, i.e. has a vanishing Riemann curvature tensor:

sage: g.riemann().display()
Riem(g) = 0

A vector field on \(M\):

sage: u = M.vector_field(name='u')
sage: u[0] = cosh(t)
sage: u[1] = sinh(t)
sage: u.display()
u = cosh(t) d/dt + sinh(t) d/dx

The scalar square of \(u\) is:

sage: s = u.dot(u); s
Scalar field u.u on the 4-dimensional Lorentzian manifold M

Scalar products are taken with respect to the metric tensor:

sage: u.dot(u) == g(u,u)
True

\(u\) is a unit timelike vector, i.e. its scalar square is identically \(-1\):

sage: s.display()
u.u: M --> R
   (t, x, y, z) |--> -1
sage: s.expr()
-1

Let us consider a unit spacelike vector:

sage: v = M.vector_field(name='v')
sage: v[0] = sinh(t)
sage: v[1] = cosh(t)
sage: v.display()
v = sinh(t) d/dt + cosh(t) d/dx
sage: v.dot(v).display()
v.v: M --> R
   (t, x, y, z) |--> 1
sage: v.dot(v).expr()
1

\(u\) and \(v\) are orthogonal vectors with respect to Minkowski metric:

sage: u.dot(v).display()
    u.v: M --> R
   (t, x, y, z) |--> 0
sage: u.dot(v).expr()
0

The divergence of \(u\) is:

sage: s = u.div(); s
Scalar field div(u) on the 4-dimensional Lorentzian manifold M
sage: s.display()
div(u): M --> R
   (t, x, y, z) |--> sinh(t)

while its d’Alembertian is:

sage: Du = u.dalembertian(); Du
Vector field Box(u) on the 4-dimensional Lorentzian manifold M
sage: Du.display()
Box(u) = -cosh(t) d/dt - sinh(t) d/dx

AUTHORS:

  • Eric Gourgoulhon (2018): initial version

REFERENCES:

  • B. O’Neill : Semi-Riemannian Geometry [ONe1983]
  • J. M. Lee : Riemannian Manifolds [Lee1997]
sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold

PseudoRiemannian manifold.

A pseudo-Riemannian manifold is a pair \((M,g)\) where \(M\) is a real differentiable manifold \(M\) (see DifferentiableManifold) and \(g\) is a field of non-degenerate symmetric bilinear forms on \(M\), which is called the metric tensor, or simply the metric (see PseudoRiemannianMetric).

Two important subcases are

  • Riemannian manifold: the metric \(g\) is positive definite, i.e. its signature is \(n = \dim M\);
  • Lorentzian manifold: the metric \(g\) has signature \(n-2\) (positive convention) or \(2-n\) (negative convention).

INPUT:

  • n – positive integer; dimension of the manifold
  • name – string; name (symbol) given to the manifold
  • metric_name – (default: 'g') string; name (symbol) given to the metric
  • signature – (default: None) signature \(S\) of the metric as a single integer: \(S = n_+ - n_-\), where \(n_+\) (resp. \(n_-\)) is the number of positive terms (resp. number of negative terms) in any diagonal writing of the metric components; if signature is not provided, \(S\) is set to the manifold’s dimension (Riemannian signature)
  • ambient – (default: None) if not None, must be a differentiable manifold; the created object is then an open subset of ambient
  • diff_degree – (default: infinity) degree \(k\) of differentiability
  • latex_name – (default: None) string; LaTeX symbol to denote the manifold; if none is provided, it is set to name
  • metric_latex_name – (default: None) string; LaTeX symbol to denote the metric; if none is provided, it is set to metric_name
  • start_index – (default: 0) integer; lower value of the range of indices used for “indexed objects” on the manifold, e.g. coordinates in a chart
  • category – (default: None) to specify the category; if None, Manifolds(RR).Differentiable() (or Manifolds(RR).Smooth() if diff_degree = infinity) is assumed (see the category Manifolds)
  • unique_tag – (default: None) tag used to force the construction of a new object when all the other arguments have been used previously (without unique_tag, the UniqueRepresentation behavior inherited from ManifoldSubset, via DifferentiableManifold and TopologicalManifold, would return the previously constructed object corresponding to these arguments).

EXAMPLES:

Pseudo-Riemannian manifolds are constructed via the generic function Manifold(), using the keyword structure:

sage: M = Manifold(4, 'M', structure='pseudo-Riemannian', signature=0)
sage: M
4-dimensional pseudo-Riemannian manifold M
sage: M.category()
Category of smooth manifolds over Real Field with 53 bits of precision

The metric associated with M is:

sage: M.metric()
Pseudo-Riemannian metric g on the 4-dimensional pseudo-Riemannian
 manifold M
sage: M.metric().signature()
0
sage: M.metric().tensor_type()
(0, 2)

Its value has to be initialized either by setting its components in various vector frames (see the above examples regarding the 2-sphere and Minkowski spacetime) or by making it equal to a given field of symmetric bilinear forms (see the method set() of the metric class). Both methods are also covered in the documentation of method metric() below.

The metric object belongs to the class PseudoRiemannianMetric:

sage: isinstance(M.metric(), sage.manifolds.differentiable.metric.
....:                        PseudoRiemannianMetric)
True

See the documentation of this class for all operations available on metrics.

The default name of the metric is g; it can be customized:

sage: M = Manifold(4, 'M', structure='pseudo-Riemannian',
....:              metric_name='gam', metric_latex_name=r'\gamma')
sage: M.metric()
Riemannian metric gam on the 4-dimensional Riemannian manifold M
sage: latex(M.metric())
\gamma

A Riemannian manifold is constructed by the proper setting of the keyword structure:

sage: M = Manifold(4, 'M', structure='Riemannian'); M
4-dimensional Riemannian manifold M
sage: M.metric()
Riemannian metric g on the 4-dimensional Riemannian manifold M
sage: M.metric().signature()
4

Similarly, a Lorentzian manifold is obtained by:

sage: M = Manifold(4, 'M', structure='Lorentzian'); M
4-dimensional Lorentzian manifold M
sage: M.metric()
Lorentzian metric g on the 4-dimensional Lorentzian manifold M

The default Lorentzian signature is taken to be positive:

sage: M.metric().signature()
2

but one can opt for the negative convention via the keyword signature:

sage: M = Manifold(4, 'M', structure='Lorentzian', signature='negative')
sage: M.metric()
Lorentzian metric g on the 4-dimensional Lorentzian manifold M
sage: M.metric().signature()
-2