Tutorial: Symbolic Tools
This tutorial demonstrates in detail how to use the symbolic tools in pystein. For other tutorials
see all tutorials.
Coordinate Systems
The pystein CoordinateSystem extends the sympy.diffgeom api to make parameters more accessible. This is important
when computing partial derivatives.1
from sympy.diffgeom import Manifold, Patch
from pystein import coords
For example, a two-dimensional set of coordinates can be created (similarly to sympy.diffgeom.CoordSystem):
M = Manifold('M', dim=2)
P = Patch('origin', M)
cs = coords.CoordSystem('cartesian', P, ['x', 'y'])
cs
In sympy it is difficult to access underlying parameters, but the new base_symbols method makes it easy:
cs.base_symbols()
Metrics
Assembling a metric with pystein is easy! Metrics can be created either from a (Matrix, Coords) combo
or from a TwoForm expression constucted from the coordinate system’s base_oneforms.
from sympy import Array, symbols
from pystein import metric
from pystein.utilities import tensor_pow as tpow
Let’s create a metric from a twoform expression, using the basis of oneforms from the coordinate system:
a, b = symbols('a b') # some constants to use in the metric
dx, dy = cs.base_oneforms()
form = a ** 2 * tpow(dx, 2) + b ** 2 * tpow(dy, 2)
g1 = metric.Metric(twoform=form) # Note: don't have to specify coords since implied by basis of one-forms
Notice that the Metric class will represent itself as a twoform
g1
Now let’s create the same metric from a matrix. We create the matrix elements first:
matrix = Array([[a ** 2, 0], [0, b ** 2]])
matrix
Now we create the metric by specifying both the matrix and the coordinate system (since the axes of the Matrix are not labeled).
g2 = metric.Metric(matrix=matrix, coord_system=cs)
Note that the Metric class automatically computes the two-form and uses it for representation:
g2
Metrics can be inverted, and produce other metrics:
g3 = g2.inverse
g3
Curvature
It is easy to compute common curvature terms with pystein, such as Christoffel, Ricci, and Riemann tensor
components.
from sympy import Function
from pystein import curvature
As an example, we create a metric with some curvature:
x, y = cs.base_symbols() # grab the coordinate parameters
F = Function('F')(x, y) # Define an arbitrary function that depends on x and y
g4 = metric.Metric(twoform=F ** 2 * tpow(dx, 2) + b ** 2 * tpow(dy, 2))
Specific components may be computed individually, where the index numbers correspond to the same order as in
the CoordSystem object.
curvature.ricci_tensor_component(0, 0, g4).doit()
Often, it is desirable to compute all non-trivial components of a curvature tensor, which can also be done
with the utility function curvature.compute_components, which will return the non trivial Christoffel,
Ricci, and Riemann components:
christoffels, riemanns, riccis = curvature.compute_components(metric=g4)
If in a Jupyter environment, these symbols can be concatenated and displayed as a single LaTeX formula using
the display_components utility.
Matter
The pystein.matter module has some utilities for computing stress energy tensor components for common
matter sources.
from pystein import matter
For example, a perfect fluid in 1D. Need to quickly redefine the coordinates to have a temporal coordinate, and we’ll create a sample metric:
t, x, y = symbols('t x y')
M = Manifold('M', dim=3)
P = Patch('origin', M)
cs = coords.CoordSystem('OneDim', P, [t, x, y])
dt, dx, dy = cs.base_oneforms()
Q = Function('Q')(t, y) # Define an arbitrary function that depends on x and y
S = Function('S')(t, x) # Define an arbitrary function that depends on x and y
g5 = metric.Metric(twoform=- Q ** 2 * tpow(dt, 2) + b ** 2 * tpow(dx, 2) + S ** 2 * tpow(dy, 2), components=(Q, S, b))
g5
Now use the matter module to create the stress energy tensor for perfect fluid
T = matter.perfect_fluid(g5)
T
Individual components may also be computed:
utilities.clean_expr(curvature.einstein_tensor_component(0, 0, g5))
Note that in the limit Q -> 1:
g5_lim = g5.subs({Q: 1})
T_lim = matter.perfect_fluid(g5_lim)
T_lim
utilities.clean_expr(curvature.einstein_tensor_component(0, 0, g5_lim))
Gravity
It is also possible to directly compute the Einstein Equations:
from pystein import gravity
utilities.clean_expr(gravity.einstein_equation(0, 0, g5, T))
- 1
The default sympy.diffgeom behavior is to pass around coordinate functions, which the sympy differentiation doesn’t recognize as a parameter to other functions. We pass the symbols directly to allow normal differentiation to work.