Coordinate systems (symbolic)
<!– crosslinks: written by .github/scripts/crosslinks.py from docs/crosslinks.toml; do not edit –>
See also
Theory: Curvilinear differential calculus
Manual: Coordinate systems (numerical)
Tutorials: Differential operators, symbolically · Christoffel symbols · Differential operators, numerically · Classical identities of the differential operators
<!– /crosslinks –>
Differential operators on tensor fields, with exact symbolic derivatives. The mathematics — natural basis, Lamé coefficients, Christoffel symbols, the index placement of each operator — is on Curvilinear differential calculus.
Predefined systems
| Constructor | Coordinates | Lamé |
|---|---|---|
coorsys_cartesian | ||
coorsys_polar | ||
coorsys_cylindrical | ||
coorsys_spherical | ||
coorsys_spheroidal | prolate spheroidal |
Each curvilinear system is drawn, with its normalized basis and its surfaces of constant coordinate, in an interactive figure of Predefined systems.
Load SymPyPythonCall for the default coordinates
Called without coordinates (coorsys_spherical()), a constructor names its coordinates with SymPy symbols, which needs using TensND, SymPyPythonCall. With Symbolics, pass the variables, coorsys_spherical(Tuple(@variables θ ϕ r)), or the type, coorsys_spherical(Val(Num)).
Spherical coordinates are ordered (\theta,\varphi,r)
Not
The operators
using TensND, SymPyPythonCall
Polar = coorsys_polar()
r, θ = get_coords(Polar)
𝐞ʳ, 𝐞ᶿ = unitvec(Polar)
@set_coorsys Polar
laplacian(SymFunction("f", real = true)(r, θ))@set_coorsys installs a default system so the operators take one argument; without it, pass the system explicitly, laplacian(f, Polar).
| Call | Does |
|---|---|
@set_coorsysCS / set_coorsys!(CS) | make CS the default |
default_coorsys() | the current default (throws if none) |
unset_coorsys!() | forget it |
∂ is deliberately not affected by the default
∂(t, x) always means the plain derivative of t with respect to the symbol x; for the covariant derivative pass the chart explicitly, ∂(t, x, CS).
Earlier versions had @set_coorsys define methods in the TensND module, including one for ∂(t, x). That method was more specific than the plain-derivative fallback, so the same call silently changed meaning — and since both CoordinateSystem and Submanifold differentiate a position vector while being built, constructing any new chart after a @set_coorsys failed. The default is now simply stored, and the single-argument operator methods are defined once.
| Operator | Order | Meaning |
|---|---|---|
grad | gradient, derivative index appended on the right | |
symgrad | symmetrized gradient; for a displacement, the strain | |
divergence | divergence, contracting the last index | |
laplacian | ||
hess |
n = symbols("n", integer = true)
simplify(laplacian(r^n * cos(n * θ)))Accessors
| Function | Returns |
|---|---|
get_coords | the coordinate symbols |
position_vector | the position vector |
unitvec | vectors of the normalized basis |
natvec | vectors of the natural basis (:cov or :cont) |
normalized_basis, natural_basis | the two bases |
lame_coefficients | the |
christoffel | the array |
∂ | the covariant derivative along one coordinate |
using TensND, SymPyPythonCall
Spherical = coorsys_spherical()
lame_coefficients(Spherical)(r, r*sin(θ), 1)christoffel(Spherical)[1, 1, 3] # Γʳ_θθ = −rCustom systems
CoordinateSystem(OM, coords, tmp_coords = (), params = ();
rules = Dict(), tmp_var = Dict(), to_coords = Dict())The position vector and the coordinate symbols suffice; the natural basis, Lamé coefficients and Christoffel symbols are derived. A variant takes the normalized basis and the
using TensND, SymPyPythonCall
x, y = symbols("x y", real = true)
a = symbols("a", positive = true)
Parabolic = CoordinateSystem(Tens([(x^2 - y^2) / 2, x * y]), (x, y))
lame_coefficients(Parabolic)(sqrt(x^2 + y^2), sqrt(x^2 + y^2))Taming symbolic expressions
Non-trivial charts produce metric expressions SymPy will not reduce unaided, and the Christoffel symbols become unusable nested radicals. Four optional arguments control this:
| Argument | Role |
|---|---|
tmp_coords | auxiliary symbols standing for compound expressions |
params | constants appearing in |
tmp_var | substitutions replacing expressions by those symbols |
to_coords | how to eliminate them again before differentiating |
rules | rewrite rules applied after each simplification |
The prolate spheroidal system is the standard illustration, and coorsys_spheroidal is built exactly this way:
Spheroidal = coorsys_spheroidal()
lame_coefficients(Spheroidal)(c*sqrt(1 - p^2)*sqrt(q^2 - 1), c*sqrt(-p^2 + q^2)/sqrt(1 - p^2), c*sqrt(-p^2 + q^2)/sqrt(q^2 - 1))simplify(laplacian(position_vector(Spheroidal)[1]^2, Spheroidal))rules is also what resolves sign ambiguities such as
Symbolic or numerical?
For pointwise evaluation, sweeps and gradients, use the pointwise CoordinateSystem instead — same operator names, derivatives by automatic differentiation. See Numerical coordinate systems.