Differential Geometry Module¶
Introduction¶
Base Class Reference¶

class
sympy.diffgeom.
Manifold
[source]¶ Object representing a mathematical manifold.
The only role that this object plays is to keep a list of all patches defined on the manifold. It does not provide any means to study the topological characteristics of the manifold that it represents.

class
sympy.diffgeom.
Patch
[source]¶ Object representing a patch on a manifold.
On a manifold one can have many patches that do not always include the whole manifold. On these patches coordinate charts can be defined that permit the parameterization of any point on the patch in terms of a tuple of real numbers (the coordinates).
This object serves as a container/parent for all coordinate system charts that can be defined on the patch it represents.
Examples
Define a Manifold and a Patch on that Manifold:
>>> from sympy.diffgeom import Manifold, Patch >>> m = Manifold('M', 3) >>> p = Patch('P', m) >>> p in m.patches True

class
sympy.diffgeom.
CoordSystem
[source]¶ Contains all coordinate transformation logic.
Examples
Define a Manifold and a Patch, and then define two coord systems on that patch:
>>> from sympy import symbols, sin, cos, pi >>> from sympy.diffgeom import Manifold, Patch, CoordSystem >>> from sympy.simplify import simplify >>> r, theta = symbols('r, theta') >>> m = Manifold('M', 2) >>> patch = Patch('P', m) >>> rect = CoordSystem('rect', patch) >>> polar = CoordSystem('polar', patch) >>> rect in patch.coord_systems True
Connect the coordinate systems. An inverse transformation is automatically found by
solve
when possible:>>> polar.connect_to(rect, [r, theta], [r*cos(theta), r*sin(theta)]) >>> polar.coord_tuple_transform_to(rect, [0, 2]) Matrix([ [0], [0]]) >>> polar.coord_tuple_transform_to(rect, [2, pi/2]) Matrix([ [0], [2]]) >>> rect.coord_tuple_transform_to(polar, [1, 1]).applyfunc(simplify) Matrix([ [sqrt(2)], [ pi/4]])
Calculate the jacobian of the polar to cartesian transformation:
>>> polar.jacobian(rect, [r, theta]) Matrix([ [cos(theta), r*sin(theta)], [sin(theta), r*cos(theta)]])
Define a point using coordinates in one of the coordinate systems:
>>> p = polar.point([1, 3*pi/4]) >>> rect.point_to_coords(p) Matrix([ [sqrt(2)/2], [ sqrt(2)/2]])
Define a basis scalar field (i.e. a coordinate function), that takes a point and returns its coordinates. It is an instance of
BaseScalarField
.>>> rect.coord_function(0)(p) sqrt(2)/2 >>> rect.coord_function(1)(p) sqrt(2)/2
Define a basis vector field (i.e. a unit vector field along the coordinate line). Vectors are also differential operators on scalar fields. It is an instance of
BaseVectorField
.>>> v_x = rect.base_vector(0) >>> x = rect.coord_function(0) >>> v_x(x) 1 >>> v_x(v_x(x)) 0
Define a basis oneform field:
>>> dx = rect.base_oneform(0) >>> dx(v_x) 1
If you provide a list of names the fields will print nicely:  without provided names:
>>> x, v_x, dx (rect_0, e_rect_0, drect_0)
 with provided names
>>> rect = CoordSystem('rect', patch, ['x', 'y']) >>> rect.coord_function(0), rect.base_vector(0), rect.base_oneform(0) (x, e_x, dx)

base_oneform
(coord_index)[source]¶ Return a basis 1form field.
The basis oneform field for this coordinate system. It is also an operator on vector fields.
See the docstring of
CoordSystem
for examples.

base_oneforms
()[source]¶ Returns a list of all base oneforms.
For more details see the
base_oneform
method of this class.

base_vector
(coord_index)[source]¶ Return a basis vector field.
The basis vector field for this coordinate system. It is also an operator on scalar fields.
See the docstring of
CoordSystem
for examples.

base_vectors
()[source]¶ Returns a list of all base vectors.
For more details see the
base_vector
method of this class.

connect_to
(to_sys, from_coords, to_exprs, inverse=True, fill_in_gaps=False)[source]¶ Register the transformation used to switch to another coordinate system.
Parameters: to_sys
another instance of
CoordSystem
from_coords
list of symbols in terms of which
to_exprs
is givento_exprs
list of the expressions of the new coordinate tuple
inverse
try to deduce and register the inverse transformation
fill_in_gaps
try to deduce other transformation that are made possible by composing the present transformation with other already registered transformation

coord_function
(coord_index)[source]¶ Return a
BaseScalarField
that takes a point and returns one of the coords.Takes a point and returns its coordinate in this coordinate system.
See the docstring of
CoordSystem
for examples.

coord_functions
()[source]¶ Returns a list of all coordinate functions.
For more details see the
coord_function
method of this class.

coord_tuple_transform_to
(to_sys, coords)[source]¶ Transform
coords
to coord systemto_sys
.See the docstring of
CoordSystem
for examples.

class
sympy.diffgeom.
Point
(coord_sys, coords)[source]¶ Point in a Manifold object.
To define a point you must supply coordinates and a coordinate system.
The usage of this object after its definition is independent of the coordinate system that was used in order to define it, however due to limitations in the simplification routines you can arrive at complicated expressions if you use inappropriate coordinate systems.
Examples
Define the boilerplate Manifold, Patch and coordinate systems:
>>> from sympy import symbols, sin, cos, pi >>> from sympy.diffgeom import ( ... Manifold, Patch, CoordSystem, Point) >>> r, theta = symbols('r, theta') >>> m = Manifold('M', 2) >>> p = Patch('P', m) >>> rect = CoordSystem('rect', p) >>> polar = CoordSystem('polar', p) >>> polar.connect_to(rect, [r, theta], [r*cos(theta), r*sin(theta)])
Define a point using coordinates from one of the coordinate systems:
>>> p = Point(polar, [r, 3*pi/4]) >>> p.coords() Matrix([ [ r], [3*pi/4]]) >>> p.coords(rect) Matrix([ [sqrt(2)*r/2], [ sqrt(2)*r/2]])

class
sympy.diffgeom.
BaseScalarField
[source]¶ Base Scalar Field over a Manifold for a given Coordinate System.
A scalar field takes a point as an argument and returns a scalar.
A base scalar field of a coordinate system takes a point and returns one of the coordinates of that point in the coordinate system in question.
To define a scalar field you need to choose the coordinate system and the index of the coordinate.
The use of the scalar field after its definition is independent of the coordinate system in which it was defined, however due to limitations in the simplification routines you may arrive at more complicated expression if you use unappropriate coordinate systems.
You can build complicated scalar fields by just building up SymPy expressions containing
BaseScalarField
instances.Examples
Define boilerplate Manifold, Patch and coordinate systems:
>>> from sympy import symbols, sin, cos, pi, Function >>> from sympy.diffgeom import ( ... Manifold, Patch, CoordSystem, Point, BaseScalarField) >>> r0, theta0 = symbols('r0, theta0') >>> m = Manifold('M', 2) >>> p = Patch('P', m) >>> rect = CoordSystem('rect', p) >>> polar = CoordSystem('polar', p) >>> polar.connect_to(rect, [r0, theta0], [r0*cos(theta0), r0*sin(theta0)])
Point to be used as an argument for the filed:
>>> point = polar.point([r0, 0])
Examples of fields:
>>> fx = BaseScalarField(rect, 0) >>> fy = BaseScalarField(rect, 1) >>> (fx**2+fy**2).rcall(point) r0**2
>>> g = Function('g') >>> ftheta = BaseScalarField(polar, 1) >>> fg = g(fthetapi) >>> fg.rcall(point) g(pi)

class
sympy.diffgeom.
BaseVectorField
[source]¶ Vector Field over a Manifold.
A vector field is an operator taking a scalar field and returning a directional derivative (which is also a scalar field).
A base vector field is the same type of operator, however the derivation is specifically done with respect to a chosen coordinate.
To define a base vector field you need to choose the coordinate system and the index of the coordinate.
The use of the vector field after its definition is independent of the coordinate system in which it was defined, however due to limitations in the simplification routines you may arrive at more complicated expression if you use unappropriate coordinate systems.
Examples
Use the predefined R2 manifold, setup some boilerplate.
>>> from sympy import symbols, pi, Function >>> from sympy.diffgeom.rn import R2, R2_p, R2_r >>> from sympy.diffgeom import BaseVectorField >>> from sympy import pprint >>> x0, y0, r0, theta0 = symbols('x0, y0, r0, theta0')
Points to be used as arguments for the field:
>>> point_p = R2_p.point([r0, theta0]) >>> point_r = R2_r.point([x0, y0])
Scalar field to operate on:
>>> g = Function('g') >>> s_field = g(R2.x, R2.y) >>> s_field.rcall(point_r) g(x0, y0) >>> s_field.rcall(point_p) g(r0*cos(theta0), r0*sin(theta0))
Vector field:
>>> v = BaseVectorField(R2_r, 1) >>> pprint(v(s_field)) / d \ (g(x, xi_2)) \dxi_2 /xi_2=y >>> pprint(v(s_field).rcall(point_r).doit()) d (g(x0, y0)) dy0 >>> pprint(v(s_field).rcall(point_p)) / d \ (g(r0*cos(theta0), xi_2)) \dxi_2 /xi_2=r0*sin(theta0)

class
sympy.diffgeom.
Commutator
(v1, v2)[source]¶ Commutator of two vector fields.
The commutator of two vector fields \(v_1\) and \(v_2\) is defined as the vector field \([v_1, v_2]\) that evaluated on each scalar field \(f\) is equal to \(v_1(v_2(f))  v_2(v_1(f))\).
Examples
Use the predefined R2 manifold, setup some boilerplate.
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import Commutator >>> from sympy import pprint >>> from sympy.simplify import simplify
Vector fields:
>>> e_x, e_y, e_r = R2.e_x, R2.e_y, R2.e_r >>> c_xy = Commutator(e_x, e_y) >>> c_xr = Commutator(e_x, e_r) >>> c_xy 0
Unfortunately, the current code is not able to compute everything:
>>> c_xr Commutator(e_x, e_r)
>>> simplify(c_xr(R2.y**2)) 2*y**2*cos(theta)/(x**2 + y**2)

class
sympy.diffgeom.
Differential
(form_field)[source]¶ Return the differential (exterior derivative) of a form field.
The differential of a form (i.e. the exterior derivative) has a complicated definition in the general case.
The differential \(df\) of the 0form \(f\) is defined for any vector field \(v\) as \(df(v) = v(f)\).
Examples
Use the predefined R2 manifold, setup some boilerplate.
>>> from sympy import Function >>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import Differential >>> from sympy import pprint
Scalar field (0forms):
>>> g = Function('g') >>> s_field = g(R2.x, R2.y)
Vector fields:
>>> e_x, e_y, = R2.e_x, R2.e_y
Differentials:
>>> dg = Differential(s_field) >>> dg d(g(x, y)) >>> pprint(dg(e_x)) / d \ (g(xi_1, y)) \dxi_1 /xi_1=x >>> pprint(dg(e_y)) / d \ (g(x, xi_2)) \dxi_2 /xi_2=y
Applying the exterior derivative operator twice always results in:
>>> Differential(dg) 0

class
sympy.diffgeom.
TensorProduct
(*args)[source]¶ Tensor product of forms.
The tensor product permits the creation of multilinear functionals (i.e. higher order tensors) out of lower order fields (e.g. 1forms and vector fields). However, the higher tensors thus created lack the interesting features provided by the other type of product, the wedge product, namely they are not antisymmetric and hence are not form fields.
Examples
Use the predefined R2 manifold, setup some boilerplate.
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import TensorProduct
>>> TensorProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) 1 >>> TensorProduct(R2.dx, R2.dy)(R2.e_y, R2.e_x) 0 >>> TensorProduct(R2.dx, R2.x*R2.dy)(R2.x*R2.e_x, R2.e_y) x**2 >>> TensorProduct(R2.e_x, R2.e_y)(R2.x**2, R2.y**2) 4*x*y >>> TensorProduct(R2.e_y, R2.dx)(R2.y) dx
You can nest tensor products.
>>> tp1 = TensorProduct(R2.dx, R2.dy) >>> TensorProduct(tp1, R2.dx)(R2.e_x, R2.e_y, R2.e_x) 1
You can make partial contraction for instance when ‘raising an index’. Putting
None
in the second argument ofrcall
means that the respective position in the tensor product is left as it is.>>> TP = TensorProduct >>> metric = TP(R2.dx, R2.dx) + 3*TP(R2.dy, R2.dy) >>> metric.rcall(R2.e_y, None) 3*dy
Or automatically pad the args with
None
without specifying them.>>> metric.rcall(R2.e_y) 3*dy

class
sympy.diffgeom.
WedgeProduct
(*args)[source]¶ Wedge product of forms.
In the context of integration only completely antisymmetric forms make sense. The wedge product permits the creation of such forms.
Examples
Use the predefined R2 manifold, setup some boilerplate.
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import WedgeProduct
>>> WedgeProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) 1 >>> WedgeProduct(R2.dx, R2.dy)(R2.e_y, R2.e_x) 1 >>> WedgeProduct(R2.dx, R2.x*R2.dy)(R2.x*R2.e_x, R2.e_y) x**2 >>> WedgeProduct(R2.e_x,R2.e_y)(R2.y,None) e_x
You can nest wedge products.
>>> wp1 = WedgeProduct(R2.dx, R2.dy) >>> WedgeProduct(wp1, R2.dx)(R2.e_x, R2.e_y, R2.e_x) 0

class
sympy.diffgeom.
LieDerivative
(v_field, expr)[source]¶ Lie derivative with respect to a vector field.
The transport operator that defines the Lie derivative is the pushforward of the field to be derived along the integral curve of the field with respect to which one derives.
Examples
>>> from sympy.diffgeom import (LieDerivative, TensorProduct) >>> from sympy.diffgeom.rn import R2 >>> LieDerivative(R2.e_x, R2.y) 0 >>> LieDerivative(R2.e_x, R2.x) 1 >>> LieDerivative(R2.e_x, R2.e_x) 0
The Lie derivative of a tensor field by another tensor field is equal to their commutator:
>>> LieDerivative(R2.e_x, R2.e_r) Commutator(e_x, e_r) >>> LieDerivative(R2.e_x + R2.e_y, R2.x) 1 >>> tp = TensorProduct(R2.dx, R2.dy) >>> LieDerivative(R2.e_x, tp) LieDerivative(e_x, TensorProduct(dx, dy)) >>> LieDerivative(R2.e_x, tp) LieDerivative(e_x, TensorProduct(dx, dy))

class
sympy.diffgeom.
BaseCovarDerivativeOp
(coord_sys, index, christoffel)[source]¶ Covariant derivative operator with respect to a base vector.
Examples
>>> from sympy.diffgeom.rn import R2, R2_r >>> from sympy.diffgeom import BaseCovarDerivativeOp >>> from sympy.diffgeom import metric_to_Christoffel_2nd, TensorProduct >>> TP = TensorProduct >>> ch = metric_to_Christoffel_2nd(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) >>> ch [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] >>> cvd = BaseCovarDerivativeOp(R2_r, 0, ch) >>> cvd(R2.x) 1 >>> cvd(R2.x*R2.e_x) e_x

class
sympy.diffgeom.
CovarDerivativeOp
(wrt, christoffel)[source]¶ Covariant derivative operator.
Examples
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import CovarDerivativeOp >>> from sympy.diffgeom import metric_to_Christoffel_2nd, TensorProduct >>> TP = TensorProduct >>> ch = metric_to_Christoffel_2nd(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) >>> ch [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] >>> cvd = CovarDerivativeOp(R2.x*R2.e_x, ch) >>> cvd(R2.x) x >>> cvd(R2.x*R2.e_x) x*e_x

sympy.diffgeom.
intcurve_series
(vector_field, param, start_point, n=6, coord_sys=None, coeffs=False)[source]¶ Return the series expansion for an integral curve of the field.
Integral curve is a function \(\gamma\) taking a parameter in \(R\) to a point in the manifold. It verifies the equation:
\(V(f)\big(\gamma(t)\big) = \frac{d}{dt}f\big(\gamma(t)\big)\)
where the given
vector_field
is denoted as \(V\). This holds for any value \(t\) for the parameter and any scalar field \(f\).This equation can also be decomposed of a basis of coordinate functions
\(V(f_i)\big(\gamma(t)\big) = \frac{d}{dt}f_i\big(\gamma(t)\big) \quad \forall i\)
This function returns a series expansion of \(\gamma(t)\) in terms of the coordinate system
coord_sys
. The equations and expansions are necessarily done in coordinatesystemdependent way as there is no other way to represent movement between points on the manifold (i.e. there is no such thing as a difference of points for a general manifold).Parameters: vector_field
the vector field for which an integral curve will be given
param
the argument of the function \(\gamma\) from R to the curve
start_point
the point which corresponds to \(\gamma(0)\)
n
the order to which to expand
coord_sys
the coordinate system in which to expand coeffs (default False)  if True return a list of elements of the expansion
Examples
Use the predefined R2 manifold:
>>> from sympy.abc import t, x, y >>> from sympy.diffgeom.rn import R2, R2_p, R2_r >>> from sympy.diffgeom import intcurve_series
Specify a starting point and a vector field:
>>> start_point = R2_r.point([x, y]) >>> vector_field = R2_r.e_x
Calculate the series:
>>> intcurve_series(vector_field, t, start_point, n=3) Matrix([ [t + x], [ y]])
Or get the elements of the expansion in a list:
>>> series = intcurve_series(vector_field, t, start_point, n=3, coeffs=True) >>> series[0] Matrix([ [x], [y]]) >>> series[1] Matrix([ [t], [0]]) >>> series[2] Matrix([ [0], [0]])
The series in the polar coordinate system:
>>> series = intcurve_series(vector_field, t, start_point, ... n=3, coord_sys=R2_p, coeffs=True) >>> series[0] Matrix([ [sqrt(x**2 + y**2)], [ atan2(y, x)]]) >>> series[1] Matrix([ [t*x/sqrt(x**2 + y**2)], [ t*y/(x**2 + y**2)]]) >>> series[2] Matrix([ [t**2*(x**2/(x**2 + y**2)**(3/2) + 1/sqrt(x**2 + y**2))/2], [ t**2*x*y/(x**2 + y**2)**2]])
See also

sympy.diffgeom.
intcurve_diffequ
(vector_field, param, start_point, coord_sys=None)[source]¶ Return the differential equation for an integral curve of the field.
Integral curve is a function \(\gamma\) taking a parameter in \(R\) to a point in the manifold. It verifies the equation:
\(V(f)\big(\gamma(t)\big) = \frac{d}{dt}f\big(\gamma(t)\big)\)
where the given
vector_field
is denoted as \(V\). This holds for any value \(t\) for the parameter and any scalar field \(f\).This function returns the differential equation of \(\gamma(t)\) in terms of the coordinate system
coord_sys
. The equations and expansions are necessarily done in coordinatesystemdependent way as there is no other way to represent movement between points on the manifold (i.e. there is no such thing as a difference of points for a general manifold).Parameters: vector_field
the vector field for which an integral curve will be given
param
the argument of the function \(\gamma\) from R to the curve
start_point
the point which corresponds to \(\gamma(0)\)
coord_sys
the coordinate system in which to give the equations
Returns: a tuple of (equations, initial conditions)
Examples
Use the predefined R2 manifold:
>>> from sympy.abc import t >>> from sympy.diffgeom.rn import R2, R2_p, R2_r >>> from sympy.diffgeom import intcurve_diffequ
Specify a starting point and a vector field:
>>> start_point = R2_r.point([0, 1]) >>> vector_field = R2.y*R2.e_x + R2.x*R2.e_y
Get the equation:
>>> equations, init_cond = intcurve_diffequ(vector_field, t, start_point) >>> equations [f_1(t) + Derivative(f_0(t), t), f_0(t) + Derivative(f_1(t), t)] >>> init_cond [f_0(0), f_1(0)  1]
The series in the polar coordinate system:
>>> equations, init_cond = intcurve_diffequ(vector_field, t, start_point, R2_p) >>> equations [Derivative(f_0(t), t), Derivative(f_1(t), t)  1] >>> init_cond [f_0(0)  1, f_1(0)  pi/2]
See also

sympy.diffgeom.
vectors_in_basis
(expr, to_sys)[source]¶ Transform all base vectors in base vectors of a specified coord basis.
While the new base vectors are in the new coordinate system basis, any coefficients are kept in the old system.
Examples
>>> from sympy.diffgeom import vectors_in_basis >>> from sympy.diffgeom.rn import R2_r, R2_p >>> vectors_in_basis(R2_r.e_x, R2_p) x*e_r/sqrt(x**2 + y**2)  y*e_theta/(x**2 + y**2) >>> vectors_in_basis(R2_p.e_r, R2_r) sin(theta)*e_y + cos(theta)*e_x

sympy.diffgeom.
twoform_to_matrix
(expr)[source]¶ Return the matrix representing the twoform.
For the twoform \(w\) return the matrix \(M\) such that \(M[i,j]=w(e_i, e_j)\), where \(e_i\) is the ith base vector field for the coordinate system in which the expression of \(w\) is given.
Examples
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import twoform_to_matrix, TensorProduct >>> TP = TensorProduct >>> twoform_to_matrix(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) Matrix([ [1, 0], [0, 1]]) >>> twoform_to_matrix(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) Matrix([ [x, 0], [0, 1]]) >>> twoform_to_matrix(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)  TP(R2.dx, R2.dy)/2) Matrix([ [ 1, 0], [1/2, 1]])

sympy.diffgeom.
metric_to_Christoffel_1st
(expr)[source]¶ Return the nested list of Christoffel symbols for the given metric.
This returns the Christoffel symbol of first kind that represents the LeviCivita connection for the given metric.
Examples
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import metric_to_Christoffel_1st, TensorProduct >>> TP = TensorProduct >>> metric_to_Christoffel_1st(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] >>> metric_to_Christoffel_1st(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) [[[1/2, 0], [0, 0]], [[0, 0], [0, 0]]]

sympy.diffgeom.
metric_to_Christoffel_2nd
(expr)[source]¶ Return the nested list of Christoffel symbols for the given metric.
This returns the Christoffel symbol of second kind that represents the LeviCivita connection for the given metric.
Examples
>>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import metric_to_Christoffel_2nd, TensorProduct >>> TP = TensorProduct >>> metric_to_Christoffel_2nd(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] >>> metric_to_Christoffel_2nd(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) [[[1/(2*x), 0], [0, 0]], [[0, 0], [0, 0]]]

sympy.diffgeom.
metric_to_Riemann_components
(expr)[source]¶ Return the components of the Riemann tensor expressed in a given basis.
Given a metric it calculates the components of the Riemann tensor in the canonical basis of the coordinate system in which the metric expression is given.
Examples
>>> from sympy import exp >>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import metric_to_Riemann_components, TensorProduct >>> TP = TensorProduct >>> metric_to_Riemann_components(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) [[[[0, 0], [0, 0]], [[0, 0], [0, 0]]], [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]]
>>> non_trivial_metric = exp(2*R2.r)*TP(R2.dr, R2.dr) + R2.r**2*TP(R2.dtheta, R2.dtheta) >>> non_trivial_metric r**2*TensorProduct(dtheta, dtheta) + exp(2*r)*TensorProduct(dr, dr) >>> riemann = metric_to_Riemann_components(non_trivial_metric) >>> riemann[0, :, :, :] [[[0, 0], [0, 0]], [[0, r*exp(2*r)], [r*exp(2*r), 0]]] >>> riemann[1, :, :, :] [[[0, 1/r], [1/r, 0]], [[0, 0], [0, 0]]]

sympy.diffgeom.
metric_to_Ricci_components
(expr)[source]¶ Return the components of the Ricci tensor expressed in a given basis.
Given a metric it calculates the components of the Ricci tensor in the canonical basis of the coordinate system in which the metric expression is given.
Examples
>>> from sympy import exp >>> from sympy.diffgeom.rn import R2 >>> from sympy.diffgeom import metric_to_Ricci_components, TensorProduct >>> TP = TensorProduct >>> metric_to_Ricci_components(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) [[0, 0], [0, 0]]
>>> non_trivial_metric = exp(2*R2.r)*TP(R2.dr, R2.dr) + R2.r**2*TP(R2.dtheta, R2.dtheta) >>> non_trivial_metric r**2*TensorProduct(dtheta, dtheta) + exp(2*r)*TensorProduct(dr, dr) >>> metric_to_Ricci_components(non_trivial_metric) [[1/r, 0], [0, r*exp(2*r)]]