# Differential forms on non-standard spherical coordinates

I'd like to compute an exterior derivative in spherical coordinates. So far I have the following:

E.<x,y,z> = EuclideanSpace(3)
Ec.<r,theta,phi> = E.spherical_coordinates()

EcM = Ec.manifold()

EcM.set_default_frame(EcM.spherical_frame())
EcM.set_default_chart(EcM.spherical_coordinates())

F = function('F')
show(F)
F_1 = function('F_r')(r, theta, phi)
F_2 = function('F_theta')(r, theta, phi)
F_3 = function('F_phi')(r, theta, phi)

psi = EcM.diff_form(2, 'psi')

psi[2, 3] = F_1
psi[1, 3] = -F_2
psi[1, 2] = F_3

show(psi.display())

res = psi.exterior_derivative()
show(res.display())


which works for the spherical coordinate transformation that is the default for Euclidean space. But, I see that Sagemath has a different spherical coordinate map than I do:

> print(E.coord_change(E.spherical_coordinates(), E.cartesian_coordinates()).display())
x = r*cos(phi)*sin(theta)
y = r*sin(phi)*sin(theta)
z = r*cos(theta)


x = r * cos(theta) * cos(phi)
y = r * sin(theta) * cos(phi)
z = r * sin(phi)


How can I supply a different change of coordinates function for this case?

edit retag close merge delete

You probably mean

x = r * cos(theta) * cos(phi)
y = r * sin(theta) * cos(phi)
z = r * sin(phi)


in which case the change of coordinates from Sage's spherical coordinates to yours is "(theta, phi) = (phi, pi/2 - theta)".

( 2021-04-28 02:24:20 +0100 )edit

Yes, I do -- thanks! How do I get a Manifold that has the right coordinate system attached?

( 2021-04-28 02:26:55 +0100 )edit
1

Having Sage provide various flavours of spherical coordinates is now tracked at:

( 2021-04-28 13:46:58 +0100 )edit

Sort by » oldest newest most voted

Simply use the method chart to define your own version of spherical coordinates and then relate them to Sage's default spherical coordinates via the method transition_map:

sage: E.<x,y,z> = EuclideanSpace()
sage: Ec.<r,theta,phi> = E.chart(r"r:(0,+oo) theta:(0,2*pi):periodic:\theta phi:(-pi/2,pi/2):\phi")
sage: Ec.coord_range()
r: (0, +oo); theta: [0, 2*pi] (periodic); phi: (-1/2*pi, 1/2*pi)
sage: Ec0.<r,theta0,phi0> = E.spherical_coordinates()       # the default spherical coordinates
sage: Ec0_to_Ec = Ec0.transition_map(Ec, (r, phi0, pi/2 - theta0))
sage: Ec0_to_Ec.display()
r = r
theta = phi0
phi = 1/2*pi - theta0
sage: Ec0_to_Ec.inverse().display()
r = r
theta0 = 1/2*pi - phi
phi0 = theta
sage: E.set_default_chart(Ec)
sage: E.set_default_frame(Ec.frame())


Then you can relate your spherical coordinates to the Cartesian ones as follows:

sage: Ec_to_cart = E.coord_change(Ec0, E.cartesian_coordinates()) * Ec0_to_Ec.inverse()
sage: Ec_to_cart.display()
x = r*cos(phi)*cos(theta)
y = r*cos(phi)*sin(theta)
z = r*sin(phi)


See E.chart? and Ec0.transition_map? for more details.

EDIT:

Another option is not to use Sage's standard spherical coordinates, but link your spherical coordinates directly to the Cartesian ones via transition_map:

sage: E.<x,y,z> = EuclideanSpace()
sage: Ec.<r,theta,phi> = E.chart(r"r:(0,+oo) theta:(0,2*pi):periodic:\theta phi:(-pi/2,pi/2):\phi")
sage: E.set_default_chart(Ec)
sage: E.set_default_frame(Ec.frame())
sage: cart = E.cartesian_coordinates()
sage: Ec_to_cart = Ec.transition_map(cart, (r*cos(theta)*cos(phi), r*sin(theta)*cos(phi), r*sin(phi)))
sage: Ec_to_cart.display()
x = r*cos(phi)*cos(theta)
y = r*cos(phi)*sin(theta)
z = r*sin(phi)


To complete the relation to Cartesian coordinates, you have to provide the inverse transition map (it is too involved for Sage to compute it automatically via the method inverse()). This is done by means of set_inverse:

sage: Ec_to_cart.set_inverse(sqrt(x^2 + y^2 + z^2), atan2(y, x), atan(z/sqrt(x^2 + y^2)))
Check of the inverse coordinate transformation:
r == r  *passed*
theta == arctan2(r*cos(phi)*sin(theta), r*cos(phi)*cos(theta))  **failed**
phi == arctan(sin(phi)/cos(phi))  **failed**
x == x  *passed*
y == y  *passed*
z == z  *passed*
NB: a failed report can reflect a mere lack of simplification.


You have then:

sage: Ec_to_cart.inverse().display()
r = sqrt(x^2 + y^2 + z^2)
theta = arctan2(y, x)
phi = arctan(z/sqrt(x^2 + y^2))


As a check that everything goes well with your version of spherical coordinates, you can ask Sage to display the Euclidean metric:

sage: E.metric().display()
g = dr*dr + r^2*cos(phi)^2 dtheta*dtheta + r^2 dphi*dphi


EDIT 2: orthonormal frame associated with the customized spherical coordinates

One may introduce the orthonormal frame $(e_r, e_{\theta}, e_{\phi})$ such that $e_r = \frac{\partial}{\partial r}$, $e_\theta = \frac{1}{r\cos\phi} \frac{\partial}{\partial\theta}$, $e_\phi = \frac{1}{r}\frac{\partial}{\partial\phi}$, as follows:

sage: e1 = E.vector_field(1, 0, 0, name='e_r')
sage: e2 = E.vector_field(0, 1/(r*cos(phi)), 0, name='e_theta')
sage: e3 = E.vector_field(0, 0, 1/r, name='e_phi')
sage: e = E.vector_frame('e', (e1, e2, e3))


Then:

sage: for v in e:
....:     v.display(Ec.frame())
....:
e_1 = d/dr
e_2 = 1/(r*cos(phi)) d/dtheta
e_3 = 1/r d/dphi
sage: for v in e:
....:     v.display(cart.frame())
....:
e_1 = cos(phi)*cos(theta) e_x + cos(phi)*sin(theta) e_y + sin(phi) e_z
e_2 = -sin(theta) e_x + cos(theta) e_y
e_3 = -cos(theta)*sin(phi) e_x - sin(phi)*sin(theta) e_y + cos(phi) e_z


The dual coframe is

sage: e.coframe()
Coframe (E^3, (e^1,e^2,e^3))
sage: for f in e.coframe():
....:     f.display(Ec.frame())
....:
e^1 = dr
e^2 = r*cos(phi) dtheta
e^3 = r dphi


We check that e is an orthonormal frame:

sage: E.metric().display(e)
g = e^1*e^1 + e^2*e^2 + e^3*e^3
sage: E.metric()[e,:]
[1 0 0]
[0 1 0]
[0 0 1]


and use it as the default vector frame on the Euclidean space E:

sage: E.set_default_frame(e)

more

How do I make sure the differential forms are on the right space? (Apologies if my vocabulary is not correct here). When I try this (https://controlc.com/55a81f63) I end up with: dpsi = (d(F_phi)/dphi + d(F_r)/dr + d(F_theta)/dtheta) dr/\dtheta/\dphi which is not correct: it's missing scaling factors of e.g. 1/(r * cos(theta))

( 2021-04-28 15:41:50 +0100 )edit

It looks correct to me: in the coordinate basis dr/\dtheta/\dphi there should not be any scaling factor like 1/(r*cos(theta)). Do you intend to use an orthonormal basis instead? If yes, introduce it explicitly and make it the default frame. I have edited my answer to add the construction of the orthonormal basis (cf. EDIT 2).

( 2021-04-28 18:23:29 +0100 )edit