-->

Etiquetas

Change of curvilinear coordinates with Python SymPy

Curvilinear coordinates with Python SymPy

This post comes from my interest to continue studying the properties of the cosmic microwave background. The usual method for the analysis of their anisotropies requires working in spherical coordinates decomposing the signal into a series of spherical harmonics. Therefore I'm now beginning some posts devoted to the subject of spherical harmonics. These come as the angular component of the solution to Laplace's equation:

$$\nabla^2 f = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2} + \frac{\partial^2 f}{\partial z^2} = 0$$

when this is expressed in spherical coordinates. So the first step, which is the subject of this post, is to write the Laplacian operator in spherical coordinates. Of course the result can be found easily on the internet and textbooks, but I thought it might be interesting to do it using the SymPy symbolic math library for Python as an exercise.

This article has been written entirely using the Notebook of IPython.

Imports and references

In [1]:
from __future__ import division
import sympy as sym
sym.init_printing()

# This IPython magic generates a table with version information
#https://github.com/jrjohansson/version_information
%load_ext version_information
%version_information sympy
Out[1]:
SoftwareVersion
Python2.7.9 64bit [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
IPython3.1.0
OSLinux 3.13.0 49 generic x86_64 with debian jessie sid
sympy0.7.6
Tue Apr 21 19:49:45 2015 CEST

This article is heavily inspired by the following example: Example of changing variables in curvilinear coordinates with SymPy

Also useful the metric tensor article on Wikipedia

And, as will be seen below, we'll also need the definition of the Laplace-Beltrami operator

Some theory

Let's address the expression of the Lagrangian in coordinates different of the cartesian ones. We'll begin with some theory taking as a first example the conversion of cartesian coordinates to polar coordinates in the plane.

The metric tensor

Let's begin with the case of the plane $\mathbb{R}^2$.A coordinate system, possibly curvilinear, $(u, v)$ on the plane, is an application $\varphi(\mathbf p) = (u,v)$ which associates to each point $\mathbf p$ of the plane a pair of real numbers $(u, v)$, for example, its polar coordinates.

Given a coordinate system, we can associate to each point $\mathbf p$ in the plane, two vectors called coordinate tangent vectors

$$\vec r_u = \frac{\partial \varphi^{-1}}{\partial u}(\varphi(\mathbf p)) $$$$\vec r_v = \frac{\partial \varphi^{-1}}{\partial v}(\varphi(\mathbf p)) $$

Example: polar coordinates

For example, the polar coordinate system associate to each point $\mathbf p = (x, y)$ in the plane two real numbers $(\rho, \theta)$ defined in the usual manner.

$$\varphi(x, y) = (\rho, \theta)$$

The inverse coordinates application will be given by:

$$ \varphi^{-1}(\rho, \theta) = (x, y) = (\rho \cos \theta, \rho \sin \theta)$$

That is simply expressed by the equations:

$$x = \rho \cos \theta $$$$y = \rho \sin \theta $$

The coordinate tangent vectors will therefore be:

$$ \vec r_\rho = \frac{\partial \varphi^{-1}}{\partial \rho} = \left( \frac{\partial x}{\partial \rho} , \frac{\partial y}{\partial \rho} \right) = (\cos \theta, \sin \theta)$$$$ \vec r_\theta = \frac{\partial \varphi^{-1}}{\partial \theta} = \left( \frac{\partial x}{\partial \theta} , \frac{\partial y}{\partial \theta} \right) = (-r \sin \theta, r \cos \theta)$$

Definition of the metric tensor in the plane

Returning to the general case of any $(u, v)$ coordinates, taking the coordinate tangent vectors and using the dot product of $\mathbb{R}^2$, we can define the following quantities:

$E = \vec r_u \cdot \vec r_u \quad , \quad F = \vec r_u \cdot \vec r_v \quad , \quad G = \vec r_v \cdot \vec r_v $

And from them we can define the metric tensor as the matrix:

$$ g = \left( g_{ij} \right) = \begin{pmatrix} E & F \\ F & G \end{pmatrix} $$

For example, in the case of polar coordinates, calculating the scalar products with the tangent vectors $ \vec r_\rho , \vec r_\theta $ obtained above, the metric tensor is:

$$ g_{\: \text{polar}}= \begin{pmatrix} 1 & 0 \\ 0 & \rho^2 \end{pmatrix} $$

Change of coordinates

The metric tensor is indeed a tensor by the way it is transformed in a change of coordinates. Indeed, suppose that we have another coordinate system $(u', v')$.

$$\varphi: (x, y) \longrightarrow (u, v)$$$$\psi: (x, y) \longrightarrow (u', v')$$

We can make the old coordinates dependent on the new ones by the transformation:

$$\varphi \circ \psi^{-1}: (u', v') \longrightarrow (u, v)$$

Whose Jacobian matrix is

$$ J = \begin{pmatrix} \frac{\partial u}{\partial u'} & \frac{\partial u}{\partial v'} \\ \frac{\partial v}{\partial u'} & \frac{\partial v}{\partial v'} \end{pmatrix} $$

And applying the rules of derivation it can be seen that the metric tensor expressed in the new coordinates is:

$$ \begin{pmatrix} E' & F' \\ F' & G' \end{pmatrix} = J^T \begin{pmatrix} E & F \\ F & G \end{pmatrix} J $$

Getting the metric tensor in polar coordinates

Now, as an application of the above, we will check that, by a change of coordinates from the metric tensor in cartesian coordinates (the unit matrix), we can get the metric tensor in polar coordinates:

In [2]:
from sympy import symbols, sin, cos, Matrix, eye, simplify, sqrt, Function, expand, sympify
In [3]:
# In SymPy we must always define the symbols that we will use
theta = symbols('theta', real=True)
rho = symbols('rho', real=True, negative=False)
In [4]:
#coordinate change equations
x = rho * cos(theta)
y = rho * sin(theta)
In [5]:
C = [x, y]    # cartesian coordinates
P = [rho, theta] # polar coordinates
In [6]:
# Calculate the Jacobian of C coordinates with respect to P
J = Matrix(C).jacobian(P) # Matrix() is used to convert C
                        # into a SymPy object with the Jacobian method
J
Out[6]:
$$\left[\begin{matrix}\cos{\left (\theta \right )} & - \rho \sin{\left (\theta \right )}\\\sin{\left (\theta \right )} & \rho \cos{\left (\theta \right )}\end{matrix}\right]$$
In [7]:
eye(2)   # this is the metric tensor in cartesian coordinates
Out[7]:
$$\left[\begin{matrix}1 & 0\\0 & 1\end{matrix}\right]$$
In [8]:
# And this is the metric tensor in polar coordinates
g = simplify(J.T * eye(2) * J)
g
Out[8]:
$$\left[\begin{matrix}1 & 0\\0 & \rho^{2}\end{matrix}\right]$$

Line element

From the metric it can be obtained the element of length $ds$, it's square is defined by the expression:

$$ ds^2 = (du, dv) \begin{pmatrix} E & F \\ F & G \end{pmatrix} \begin{pmatrix} du \\ dv \end{pmatrix} $$

This doesn't depend on the chosen coordinate system. For this reason, $ds^2$ is called first fundamental form.

In [9]:
# Example: line element in polar coordinates:
drho, dtheta = symbols(r'd\rho d\theta')
dP = Matrix([drho, dtheta])
ds2 = dP.T * g * dP
ds2[0]
Out[9]:
$$d\rho^{2} + d\theta^{2} \rho^{2}$$

Differential element of area

The element of area gives another intrinsic element of the surface, which does not depend on the chosen coordinate system. We can express it as:

$$da = \sqrt{\det(g)} \; du \; dv$$
In [10]:
#Example: element of area in polar coordinates:
da = sqrt(g.det())*drho*dtheta
da
Out[10]:
$$d\rho d\theta \rho$$

The Laplace-Beltrami operator

The Laplace-Beltrami operator is a differential operator that generalizes the Laplace operator to be used with a system $(\theta_1, \theta_2, \dots \:)$ of curvilinear coordinates. Its expression is:

$$ \nabla^2 f = \frac{1}{\sqrt{\lvert g \rvert}} \frac{\partial}{\partial \theta_i} \left( \sqrt{\lvert g \rvert} g^{ij} \frac{\partial f}{\partial \theta_j} \right) $$

Where:

  • $g$ is the metric tensor, $\vert g \vert$ the determinant of its matrix.
  • $g^{ij}$ are the components of the inverse of the matrix of the metric tensor.

So, we will use this expression to obtain the Laplacian on a system of coordinates different of the cartesian ones.

The Laplacian in polar coordinates

First we will use the Laplace_Beltrami operator to express the Laplacian operator in polar coordinates $(\rho, \theta)$

In [11]:
f = sym.Function('f')
f = f(*list(P))    # Express f as a function of the polar coordinates
In [12]:
#Computing the inverse of the metric:
g_inv = g.inv()
g_inv
Out[12]:
$$\left[\begin{matrix}1 & 0\\0 & \frac{1}{\rho^{2}}\end{matrix}\right]$$
In [13]:
# And the determinant of the metric:
g_det = g.det()
g_det
Out[13]:
$$\rho^{2}$$
In [14]:
# And finally we can express the Laplace-Beltrami operator following its definition:
L_B_pol = 0
for i in range(2):
    for j in range(2):
        L_B_pol += (sqrt(g_det) * g_inv[i,j] * f.diff(P[j])).diff(P[i])
L_B_pol = expand(L_B_pol / sqrt(g_det))
L_B_pol
Out[14]:
$$\frac{\partial^{2}}{\partial \rho^{2}} f{\left (\rho,\theta \right )} + \frac{1}{\rho} \frac{\partial}{\partial \rho} f{\left (\rho,\theta \right )} + \frac{1}{\rho^{2}} \frac{\partial^{2}}{\partial \theta^{2}} f{\left (\rho,\theta \right )}$$

If you would like to use this expression in another notebook, you can generate a string from it, which could be copied to the clipboard and generate the expression again with sympify()

In [15]:
str(L_B_pol)
Out[15]:
'Derivative(f(rho, theta), rho, rho) + Derivative(f(rho, theta), rho)/rho + Derivative(f(rho, theta), theta, theta)/rho**2'
In [16]:
sympify('Derivative(f(rho, theta), rho, rho) + \
        Derivative(f(rho, theta), rho)/rho +   \
        Derivative(f(rho, theta), theta, theta)/rho**2')
Out[16]:
$$\frac{\partial^{2}}{\partial \rho^{2}} f{\left (\rho,\theta \right )} + \frac{1}{\rho} \frac{\partial}{\partial \rho} f{\left (\rho,\theta \right )} + \frac{1}{\rho^{2}} \frac{\partial^{2}}{\partial \theta^{2}} f{\left (\rho,\theta \right )}$$

The Laplacian in spherical coordinates

In [17]:
# Theta is the co-latitude, phi the longitude
rho, theta, phi = sym.symbols('rho theta phi', real=True, negative=False)
rho, theta, phi
Out[17]:
$$\left ( \rho, \quad \theta, \quad \phi\right )$$
In [18]:
# Change of coordinates equations:
x = rho * sin(theta) * cos(phi)
y = rho * sin(theta) * sin(phi)
z = rho * cos(theta)
In [19]:
C = [x, y, z]    # cartesian coordinates
S = [rho, theta, phi] # spherical coordinates
C
Out[19]:
$$\left [ \rho \sin{\left (\theta \right )} \cos{\left (\phi \right )}, \quad \rho \sin{\left (\phi \right )} \sin{\left (\theta \right )}, \quad \rho \cos{\left (\theta \right )}\right ]$$
In [20]:
# Calculate the Jacobian of C coordinates with respect to S
J = Matrix(C).jacobian(S)
J
Out[20]:
$$\left[\begin{matrix}\sin{\left (\theta \right )} \cos{\left (\phi \right )} & \rho \cos{\left (\phi \right )} \cos{\left (\theta \right )} & - \rho \sin{\left (\phi \right )} \sin{\left (\theta \right )}\\\sin{\left (\phi \right )} \sin{\left (\theta \right )} & \rho \sin{\left (\phi \right )} \cos{\left (\theta \right )} & \rho \sin{\left (\theta \right )} \cos{\left (\phi \right )}\\\cos{\left (\theta \right )} & - \rho \sin{\left (\theta \right )} & 0\end{matrix}\right]$$
In [21]:
# This is the metric tensor in spherical coordinates
g = simplify(J.T * eye(3) * J)
g
Out[21]:
$$\left[\begin{matrix}1 & 0 & 0\\0 & \rho^{2} & 0\\0 & 0 & \rho^{2} \sin^{2}{\left (\theta \right )}\end{matrix}\right]$$
In [22]:
# And the determinant of the metric tensor:
g_det = g.det()
g_det
Out[22]:
$$\rho^{4} \sin^{2}{\left (\theta \right )}$$
In [23]:
#The inverse of the metric:
g_inv = g.inv()
g_inv
Out[23]:
$$\left[\begin{matrix}1 & 0 & 0\\0 & \frac{1}{\rho^{2}} & 0\\0 & 0 & \frac{1}{\rho^{2} \sin^{2}{\left (\theta \right )}}\end{matrix}\right]$$
In [24]:
f = sym.Function('f')
f = f(*list(S))    # express f as a function of the spherical coordinates
f
Out[24]:
$$f{\left (\rho,\theta,\phi \right )}$$
In [25]:
# And finally we get the expression of the Laplace-Beltrami operator:
L_B_esf = 0
for i in range(3):
    for j in range(3):
        L_B_esf += (sqrt(g_det) * g_inv[i,j] * f.diff(S[j])).diff(S[i])
L_B_esf = expand(L_B_esf / sqrt(g_det))
L_B_esf
Out[25]:
$$\frac{\partial^{2}}{\partial \rho^{2}} f{\left (\rho,\theta,\phi \right )} + \frac{2}{\rho} \frac{\partial}{\partial \rho} f{\left (\rho,\theta,\phi \right )} + \frac{\cos{\left (\theta \right )} \frac{\partial}{\partial \theta} f{\left (\rho,\theta,\phi \right )}}{\rho^{2} \left\lvert{\sin{\left (\theta \right )}}\right\rvert} \operatorname{sign}{\left (\sin{\left (\theta \right )} \right )} + \frac{1}{\rho^{2}} \frac{\partial^{2}}{\partial \theta^{2}} f{\left (\rho,\theta,\phi \right )} + \frac{\frac{\partial^{2}}{\partial \phi^{2}} f{\left (\rho,\theta,\phi \right )}}{\rho^{2} \sin^{2}{\left (\theta \right )}}$$

This is the correct result, provided that we notice that the sign and absolute value in sin($\theta$) cancel out (SymPy apparently does not), just letting $\sin(\theta)$ in the denominator.

However, you can simplify this expression by brute force, eliminating the absolute value sign, and replacing the sign by 1:

In [26]:
L_B_esf = L_B_esf.replace(sym.Abs, sym.Id).replace(sym.sign(sin(theta)), 1)
L_B_esf
Out[26]:
$$\frac{\partial^{2}}{\partial \rho^{2}} f{\left (\rho,\theta,\phi \right )} + \frac{2}{\rho} \frac{\partial}{\partial \rho} f{\left (\rho,\theta,\phi \right )} + \frac{1}{\rho^{2}} \frac{\partial^{2}}{\partial \theta^{2}} f{\left (\rho,\theta,\phi \right )} + \frac{\cos{\left (\theta \right )} \frac{\partial}{\partial \theta} f{\left (\rho,\theta,\phi \right )}}{\rho^{2} \sin{\left (\theta \right )}} + \frac{\frac{\partial^{2}}{\partial \phi^{2}} f{\left (\rho,\theta,\phi \right )}}{\rho^{2} \sin^{2}{\left (\theta \right )}}$$

The spherical Laplacian

It is the Laplacian operator (better, the Laplace-Beltrami operator) restricted to the spherical surface of radius $\rho = 1$. In this case we have a differential operator on a surface whose local coordinates are the angular ones: $(\theta, \phi)$. Let us apply the same method as above to obtain its expression in terms of these coordinates:

In [27]:
# Equations of change of coordinates
x = sin(theta) * cos(phi)
y = sin(theta) * sin(phi)
z = cos(theta)

C = [x, y, z]    # cartesian coordinates
S2 = [theta, phi] # Spherical coordinates

J = Matrix(C).jacobian(S2)
g = simplify(J.T * eye(3) * J)
g_det = g.det()
g_inv = g.inv()
In [28]:
f = sym.Function('f')
f = f(*list(S2))    # express f as a function of the spherical coordinates
f
Out[28]:
$$f{\left (\theta,\phi \right )}$$
In [29]:
# Finally we obtain the expression of the Laplace-Beltrami operator on the unit sphere
L_B_s_esf = 0
for i in range(2):
    for j in range(2):
        L_B_s_esf += (sqrt(g_det) * g_inv[i,j] * f.diff(S2[j])).diff(S2[i])
L_B_s_esf = expand(L_B_s_esf / sqrt(g_det))
L_B_s_esf = L_B_s_esf.replace(sym.Abs, sym.Id).replace(sym.sign(sin(theta)), 1)
L_B_s_esf
Out[29]:
$$\frac{\partial^{2}}{\partial \theta^{2}} f{\left (\theta,\phi \right )} + \frac{\frac{\partial}{\partial \theta} f{\left (\theta,\phi \right )}}{\sin{\left (\theta \right )}} \cos{\left (\theta \right )} + \frac{\frac{\partial^{2}}{\partial \phi^{2}} f{\left (\theta,\phi \right )}}{\sin^{2}{\left (\theta \right )}}$$

No hay comentarios:

Publicar un comentario