CoCalc Public FilesSageManifolds / Notebooks / SM_Euclidean_plane.ipynbOpen with one click!
Author: Eric Gourgoulhon
Views : 235
Description: Tutorial vector calculus 6: the Euclidean plane

Vector calculus in the Euclidean plane

This notebook illustrates some vector calculus capabilities of SageMath within the 2-dimensional Euclidean space. The corresponding tools have been developed within the SageManifolds project.

Click here to download the notebook file (ipynb format). To run it, you must start SageMath with the Jupyter interface, via the command sage -n jupyter

NB: a version of SageMath at least equal to 8.3 is required to run this notebook:

In [1]:
version()
'SageMath version 8.3, Release Date: 2018-08-03'

First we set up the notebook to display math formulas using LaTeX formatting:

In [2]:
%display latex

1. Defining the Euclidean plane

We define the Euclidean plane E2\mathbb{E}^2 as a 2-dimensional Euclidean space, with Cartesian coordinates (x,y)(x,y):

In [3]:
E.<x,y> = EuclideanSpace() print(E) E
Euclidean plane E^2
E2\mathbb{E}^{2}

Thanks to the use of <x,y> in the above command, the Python variables x and y are assigned to the symbolic variables xx and yy describing the Cartesian coordinates:

In [4]:
type(y)
<typex'sage.symbolic.expression.Expression'>\verb|<type|\phantom{\verb!x!}\verb|'sage.symbolic.expression.Expression'>|

Instead of using the variables x and y, one may also access to the coordinates by their indices in the chart of Cartesian coordinates:

In [5]:
cartesian = E.cartesian_coordinates() cartesian
(E2,(x,y))\left(\mathbb{E}^{2},(x, y)\right)
In [6]:
cartesian[1]
xx
In [7]:
cartesian[2]
yy
In [8]:
y is cartesian[2]
True\mathrm{True}

Each of the Cartesian coordinates spans the entire real line:

In [9]:
cartesian.coord_range()
x: (,+);y: (,+)x :\ \left( -\infty, +\infty \right) ;\quad y :\ \left( -\infty, +\infty \right)

2. Vector fields

The Euclidean plane E2\mathbb{E}^2 is canonically endowed with the vector frame associated with Cartesian coordinates:

In [10]:
E.default_frame()
(E2,(ex,ey))\left(\mathbb{E}^{2}, \left(e_{ x },e_{ y }\right)\right)

Vector fields on E2\mathbb{E}^2 are then defined from their components in that frame:

In [11]:
v = E.vector_field(-y, x, name='v') v.display()
v=yex+xeyv = -y e_{ x } + x e_{ y }

The access to individual components is performed by the square bracket operator:

In [12]:
v[1]
y-y
In [13]:
v[:]
[y,x]\left[-y, x\right]

A plot of the vector field vv (this is with default parameters, see the list of options for customizing the plot):

In [14]:
v.plot()

One may also define a vector field by setting the components in a second stage:

In [15]:
w = E.vector_field(name='w') w[1] = function('w_x')(x,y) w[2] = function('w_y')(x,y) w.display()
w=wx(x,y)ex+wy(x,y)eyw = w_{x}\left(x, y\right) e_{ x } + w_{y}\left(x, y\right) e_{ y }

Note that in the above example the components of ww are unspecified functions of (x,y)(x,y), contrary to the components of vv.

Standard linear algebra operations are available on vector fields:

In [16]:
s = 2*v + x*w s.display()
(xwx(x,y)2y)ex+(xwy(x,y)+2x)ey\left( x w_{x}\left(x, y\right) - 2 \, y \right) e_{ x } + \left( x w_{y}\left(x, y\right) + 2 \, x \right) e_{ y }

Scalar product and norm

The dot (scalar) product of vv by ww in performed by the operator dot_product; it gives rise to a scalar field on E2\mathbb{E}^2:

In [17]:
s = v.dot_product(w) print(s)
Scalar field v.w on the Euclidean plane E^2

A shortcut alias of dot_product is dot:

In [18]:
s == v.dot(w)
True\mathrm{True}
In [19]:
s.display()
vw:E2R(x,y)ywx(x,y)+xwy(x,y)\begin{array}{llcl} {v}\cdot{w}:& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & -y w_{x}\left(x, y\right) + x w_{y}\left(x, y\right) \end{array}

The symbolic expression representing the scalar field vwv\cdot w is obtained by means of the method expr():

In [20]:
s.expr()
ywx(x,y)+xwy(x,y)-y w_{x}\left(x, y\right) + x w_{y}\left(x, y\right)

The Euclidean norm of the vector field vv is a scalar field on E2\mathbb{E}^2:

In [21]:
s = norm(v) s.display()
v:E2R(x,y)x2+y2\begin{array}{llcl} \left\|v\right\|:& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \sqrt{x^{2} + y^{2}} \end{array}

Again, the corresponding symbolic expression is obtained via expr():

In [22]:
s.expr()
x2+y2\sqrt{x^{2} + y^{2}}
In [23]:
norm(w).expr()
wx(x,y)2+wy(x,y)2\sqrt{w_{x}\left(x, y\right)^{2} + w_{y}\left(x, y\right)^{2}}

We have of course v2=vv\|v\|^2 = v\cdot v :

In [24]:
norm(v)^2 == v.dot(v)
True\mathrm{True}

Values at a given point

We introduce a point pE2p\in \mathbb{E}^2 via the generic SageMath syntax for creating an element from its parent (here E2\mathbb{E}^2), i.e. the call operator (), with the Cartesian coordinates of the point as the first argument:

In [25]:
p = E((-2,3), name='p') print(p)
Point p on the Euclidean plane E^2

The coordinates of pp are returned by the method coord():

In [26]:
p.coord()
(2,3)\left(-2, 3\right)

or by letting the chart cartesian act on the point:

In [27]:
cartesian(p)
(2,3)\left(-2, 3\right)

The value of the scalar field s = norm(v) at pp is

In [28]:
s(p)
13\sqrt{13}

The value of a vector field at pp is obtained by the method at (since the call operator () is reserved for the action of vector fields on scalar fields, see Section 5 below):

In [29]:
vp = v.at(p) print(vp)
Vector v at Point p on the Euclidean plane E^2
In [30]:
vp.display()
v=3ex2eyv = -3 e_{ x } -2 e_{ y }
In [31]:
wp = w.at(p) wp.display()
w=wx(2,3)ex+wy(2,3)eyw = w_{x}\left(-2, 3\right) e_{ x } + w_{y}\left(-2, 3\right) e_{ y }
In [32]:
s = v.at(p) + pi*w.at(p) s.display()
(πwx(2,3)3)ex+(πwy(2,3)2)ey\left( \pi w_{x}\left(-2, 3\right) - 3 \right) e_{ x } + \left( \pi w_{y}\left(-2, 3\right) - 2 \right) e_{ y }

3. Differential operators

Tu use functional notations, i.e. div(v) instead of v.div() for the divergence of the vector field v, we import the functions div, grad, etc. in the global namespace:

In [33]:
from sage.manifolds.operators import *

Divergence

The divergence of a vector field is returned by the function div; the output is a scalar field on E2\mathbb{E}^2:

In [34]:
print(div(v))
Scalar field div(v) on the Euclidean plane E^2
In [35]:
div(v).display()
div(v):E2R(x,y)0\begin{array}{llcl} \mathrm{div}\left(v\right):& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & 0 \end{array}

In the present case, divv\mathrm{div}\, v vanishes identically:

In [36]:
div(v) == 0
True\mathrm{True}

On the contrary, the divergence of ww is

In [37]:
div(w).display()
div(w):E2R(x,y)wxx+wyy\begin{array}{llcl} \mathrm{div}\left(w\right):& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \frac{\partial\,w_{x}}{\partial x} + \frac{\partial\,w_{y}}{\partial y} \end{array}
In [38]:
div(w).expr()
xwx(x,y)+ywy(x,y)\frac{\partial}{\partial x}w_{x}\left(x, y\right) + \frac{\partial}{\partial y}w_{y}\left(x, y\right)

Gradient

The gradient of a scalar field, e.g. s = norm(v), is returned by the function grad; the output is a vector field:

In [39]:
s = norm(v) print(grad(s))
Vector field grad(|v|) on the Euclidean plane E^2
In [40]:
grad(s).display()
grad(v)=(xx2+y2)ex+(yx2+y2)ey\mathrm{grad}\left(\left\|v\right\|\right) = \left( \frac{x}{\sqrt{x^{2} + y^{2}}} \right) e_{ x } + \left( \frac{y}{\sqrt{x^{2} + y^{2}}} \right) e_{ y }
In [41]:
grad(s)[2]
yx2+y2\frac{y}{\sqrt{x^{2} + y^{2}}}

For a generic scalar field

In [42]:
F = E.scalar_field(function('f')(x,y), name='F')

we have

In [43]:
grad(F).display()
grad(F)=fxex+fyey\mathrm{grad}\left(F\right) = \frac{\partial\,f}{\partial x} e_{ x } + \frac{\partial\,f}{\partial y} e_{ y }
In [44]:
grad(F)[:]
[fx,fy]\left[\frac{\partial\,f}{\partial x}, \frac{\partial\,f}{\partial y}\right]

Of course, we may combine grad and div:

In [45]:
grad(div(w)).display()
grad(div(w))=(2wxx2+2wyxy)ex+(2wxxy+2wyy2)ey\mathrm{grad}\left(\mathrm{div}\left(w\right)\right) = \left( \frac{\partial^2\,w_{x}}{\partial x ^ 2} + \frac{\partial^2\,w_{y}}{\partial x\partial y} \right) e_{ x } + \left( \frac{\partial^2\,w_{x}}{\partial x\partial y} + \frac{\partial^2\,w_{y}}{\partial y ^ 2} \right) e_{ y }

Laplace operator

The Laplace operator is obtained by the function laplacian; it can act on a scalar field:

In [46]:
laplacian(F).display()
Δ(F):E2R(x,y)2fx2+2fy2\begin{array}{llcl} \Delta\left(F\right):& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & \frac{\partial^2\,f}{\partial x ^ 2} + \frac{\partial^2\,f}{\partial y ^ 2} \end{array}

as well as on a vector field:

In [47]:
laplacian(w).display()
Δ(w)=(2wxx2+2wxy2)ex+(2wyx2+2wyy2)ey\Delta\left(w\right) = \left( \frac{\partial^2\,w_{x}}{\partial x ^ 2} + \frac{\partial^2\,w_{x}}{\partial y ^ 2} \right) e_{ x } + \left( \frac{\partial^2\,w_{y}}{\partial x ^ 2} + \frac{\partial^2\,w_{y}}{\partial y ^ 2} \right) e_{ y }

For a scalar field, we have the identity:

In [48]:
laplacian(F) == div(grad(F))
True\mathrm{True}

4. Polar coordinates

Polar coordinates (r,ϕ)(r,\phi) are introduced on E2\mathbb{E}^2 by

In [49]:
polar.<r,ph> = E.polar_coordinates() polar
(E2,(r,ϕ))\left(\mathbb{E}^{2},(r, {\phi})\right)
In [50]:
polar.coord_range()
r: (0,+);ϕ: (0,2π)r :\ \left( 0 , +\infty \right) ;\quad {\phi} :\ \left( 0 , 2 \, \pi \right)

They are related to Cartesian coordinates by the following transformations:

In [51]:
E.coord_change(polar, cartesian).display()
{x=rcos(ϕ)y=rsin(ϕ)\left\{\begin{array}{lcl} x & = & r \cos\left({\phi}\right) \\ y & = & r \sin\left({\phi}\right) \end{array}\right.
In [52]:
E.coord_change(cartesian, polar).display()
{r=x2+y2ϕ=arctan(y,x)\left\{\begin{array}{lcl} r & = & \sqrt{x^{2} + y^{2}} \\ {\phi} & = & \arctan\left(y, x\right) \end{array}\right.

The orthonormal vector frame associated to polar coordinates is

In [53]:
polar_frame = E.polar_frame() polar_frame
(E2,(er,eϕ))\left(\mathbb{E}^{2}, \left(e_{ r },e_{ {\phi} }\right)\right)
In [54]:
er = polar_frame[1] er.display() # display in the default frame (Cartesian frame) # with the default coordinates (Cartesian)
er=(xx2+y2)ex+(yx2+y2)eye_{ r } = \left( \frac{x}{\sqrt{x^{2} + y^{2}}} \right) e_{ x } + \left( \frac{y}{\sqrt{x^{2} + y^{2}}} \right) e_{ y }
In [55]:
er.display(cartesian.frame(), polar) # display in the Cartesian frame # with components expressed in polar coordinates
er=cos(ϕ)ex+sin(ϕ)eye_{ r } = \cos\left({\phi}\right) e_{ x } + \sin\left({\phi}\right) e_{ y }
In [56]:
eph = polar_frame[2] eph.display()
eϕ=(yx2+y2)ex+(xx2+y2)eye_{ {\phi} } = \left( -\frac{y}{\sqrt{x^{2} + y^{2}}} \right) e_{ x } + \left( \frac{x}{\sqrt{x^{2} + y^{2}}} \right) e_{ y }
In [57]:
eph.display(cartesian.frame(), polar)
eϕ=sin(ϕ)ex+cos(ϕ)eye_{ {\phi} } = -\sin\left({\phi}\right) e_{ x } + \cos\left({\phi}\right) e_{ y }

We may check that (er,eϕ)(e_r, e_\phi) is an orthonormal frame:

In [58]:
all([er.dot(er) == 1, er.dot(eph) == 0, eph.dot(eph) == 1])
True\mathrm{True}

Scalar fields can be expressed in terms of polar coordinates:

In [59]:
F.display()
F:E2R(x,y)f(x,y)(r,ϕ)f(rcos(ϕ),rsin(ϕ))\begin{array}{llcl} F:& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & f\left(x, y\right) \\ & \left(r, {\phi}\right) & \longmapsto & f\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) \end{array}
In [60]:
F.display(polar)
F:E2R(r,ϕ)f(rcos(ϕ),rsin(ϕ))\begin{array}{llcl} F:& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(r, {\phi}\right) & \longmapsto & f\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) \end{array}

and we may ask for the components of vector fields in terms of the polar frame:

In [61]:
v.display() # default frame and default coordinates (both Cartesian ones)
v=yex+xeyv = -y e_{ x } + x e_{ y }
In [62]:
v.display(polar_frame) # polar frame and default coordinates
v=(x2+y2)eϕv = \left( \sqrt{x^{2} + y^{2}} \right) e_{ {\phi} }
In [63]:
v.display(polar_frame, polar) # polar frame and polar coordinates
v=reϕv = r e_{ {\phi} }
In [64]:
w.display()
w=wx(x,y)ex+wy(x,y)eyw = w_{x}\left(x, y\right) e_{ x } + w_{y}\left(x, y\right) e_{ y }
In [65]:
w.display(polar_frame, polar)
w=(cos(ϕ)wx(rcos(ϕ),rsin(ϕ))+sin(ϕ)wy(rcos(ϕ),rsin(ϕ)))er+(sin(ϕ)wx(rcos(ϕ),rsin(ϕ))+cos(ϕ)wy(rcos(ϕ),rsin(ϕ)))eϕw = \left( \cos\left({\phi}\right) w_{x}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) + \sin\left({\phi}\right) w_{y}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) \right) e_{ r } + \left( -\sin\left({\phi}\right) w_{x}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) + \cos\left({\phi}\right) w_{y}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) \right) e_{ {\phi} }

Gradient in polar coordinates

Let us define a generic scalar field in terms of polar coordinates:

In [66]:
H = E.scalar_field({polar: function('h')(r,ph)}, name='H') H.display(polar)
H:E2R(r,ϕ)h(r,ϕ)\begin{array}{llcl} H:& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(r, {\phi}\right) & \longmapsto & h\left(r, {\phi}\right) \end{array}

The gradient of HH is then

In [67]:
grad(H).display(polar_frame, polar)
grad(H)=hrer+hϕreϕ\mathrm{grad}\left(H\right) = \frac{\partial\,h}{\partial r} e_{ r } + \frac{\frac{\partial\,h}{\partial {\phi}}}{r} e_{ {\phi} }

To access to individual components is perfomed by the square bracket operator, where, in addition to the index, one has to specify the vector frame and the coordinates if they are not the default ones:

In [68]:
grad(H).display(cartesian.frame(), polar)
grad(H)=(rcos(ϕ)hrsin(ϕ)hϕr)ex+(rsin(ϕ)hr+cos(ϕ)hϕr)ey\mathrm{grad}\left(H\right) = \left( \frac{r \cos\left({\phi}\right) \frac{\partial\,h}{\partial r} - \sin\left({\phi}\right) \frac{\partial\,h}{\partial {\phi}}}{r} \right) e_{ x } + \left( \frac{r \sin\left({\phi}\right) \frac{\partial\,h}{\partial r} + \cos\left({\phi}\right) \frac{\partial\,h}{\partial {\phi}}}{r} \right) e_{ y }
In [69]:
grad(H)[polar_frame,2,polar]
hϕr\frac{\frac{\partial\,h}{\partial {\phi}}}{r}

Divergence in polar coordinates

Let us define a generic vector field in terms of polar coordinates:

In [70]:
u = E.vector_field(function('u_r')(r,ph), function('u_ph', latex_name=r'u_\phi')(r,ph), frame=polar_frame, chart=polar, name='u') u.display(polar_frame, polar)
u=ur(r,ϕ)er+uϕ(r,ϕ)eϕu = u_{r}\left(r, {\phi}\right) e_{ r } + u_\phi\left(r, {\phi}\right) e_{ {\phi} }
In [71]:
div(u).display(polar)
div(u):E2R(r,ϕ)rurr+ur(r,ϕ)+uϕϕr\begin{array}{llcl} \mathrm{div}\left(u\right):& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(r, {\phi}\right) & \longmapsto & \frac{r \frac{\partial\,u_{r}}{\partial r} + u_{r}\left(r, {\phi}\right) + \frac{\partial\,u_\phi}{\partial {\phi}}}{r} \end{array}
In [72]:
div(u).expr(polar)
rrur(r,ϕ)+ur(r,ϕ)+ϕuϕ(r,ϕ)r\frac{r \frac{\partial}{\partial r}u_{r}\left(r, {\phi}\right) + u_{r}\left(r, {\phi}\right) + \frac{\partial}{\partial {\phi}}u_\phi\left(r, {\phi}\right)}{r}
In [73]:
div(u).expr(polar).expand()
ur(r,ϕ)r+ϕuϕ(r,ϕ)r+rur(r,ϕ)\frac{u_{r}\left(r, {\phi}\right)}{r} + \frac{\frac{\partial}{\partial {\phi}}u_\phi\left(r, {\phi}\right)}{r} + \frac{\partial}{\partial r}u_{r}\left(r, {\phi}\right)

Using polar coordinates by default:

In order to avoid specifying the arguments polar_frame and polar in display(), expr() and [], we may change the default values by

In [74]:
E.set_default_chart(polar) E.set_default_frame(polar_frame)

Then we have

In [75]:
u.display()
u=ur(r,ϕ)er+uϕ(r,ϕ)eϕu = u_{r}\left(r, {\phi}\right) e_{ r } + u_\phi\left(r, {\phi}\right) e_{ {\phi} }
In [76]:
u[1]
ur(r,ϕ)u_{r}\left(r, {\phi}\right)
In [77]:
v.display()
v=reϕv = r e_{ {\phi} }
In [78]:
v[2]
rr
In [79]:
w.display()
w=(cos(ϕ)wx(rcos(ϕ),rsin(ϕ))+sin(ϕ)wy(rcos(ϕ),rsin(ϕ)))er+(sin(ϕ)wx(rcos(ϕ),rsin(ϕ))+cos(ϕ)wy(rcos(ϕ),rsin(ϕ)))eϕw = \left( \cos\left({\phi}\right) w_{x}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) + \sin\left({\phi}\right) w_{y}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) \right) e_{ r } + \left( -\sin\left({\phi}\right) w_{x}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) + \cos\left({\phi}\right) w_{y}\left(r \cos\left({\phi}\right), r \sin\left({\phi}\right)\right) \right) e_{ {\phi} }
In [80]:
div(u).expr()
rrur(r,ϕ)+ur(r,ϕ)+ϕuϕ(r,ϕ)r\frac{r \frac{\partial}{\partial r}u_{r}\left(r, {\phi}\right) + u_{r}\left(r, {\phi}\right) + \frac{\partial}{\partial {\phi}}u_\phi\left(r, {\phi}\right)}{r}

5. Advanced topics: the Euclidean plane as a Riemannian manifold

E2\mathbb{E}^2 is actually a Riemannian manifold, i.e. a smooth real manifold endowed with a positive definite metric tensor:

In [81]:
E.category()
SmoothR\mathbf{Smooth}_{\Bold{R}}
In [82]:
print(E.category())
Category of smooth manifolds over Real Field with 53 bits of precision
In [83]:
E.base_field() is RR
True\mathrm{True}

Actually RR is used here as a proxy for the real field (this should be replaced in the future, see the discussion at #24456) and the 53 bits of precision play of course no role for the symbolic computations.

The user atlas of E2\mathbb{E}^2 has two charts:

In [84]:
E.atlas()
[(E2,(x,y)),(E2,(r,ϕ))]\left[\left(\mathbb{E}^{2},(x, y)\right), \left(\mathbb{E}^{2},(r, {\phi})\right)\right]

while there are three vector frames defined on E2\mathbb{E}^2:

In [85]:
E.frames()
[(E2,(ex,ey)),(E2,(r,ϕ)),(E2,(er,eϕ))]\left[\left(\mathbb{E}^{2}, \left(e_{ x },e_{ y }\right)\right), \left(\mathbb{E}^{2}, \left(\frac{\partial}{\partial r },\frac{\partial}{\partial {\phi} }\right)\right), \left(\mathbb{E}^{2}, \left(e_{ r },e_{ {\phi} }\right)\right)\right]

Indeed, there are two frames associated with polar coordinates: the coordinate frame (r,ϕ)(\frac{\partial}{\partial r}, \frac{\partial}{\partial \phi}) and the orthonormal frame (er,eϕ)(e_r, e_\phi).

Riemannian metric

The default metric tensor of E2\mathbb{E}^2 is

In [86]:
g = E.metric() print(g)
Riemannian metric g on the Euclidean plane E^2
In [87]:
g.display()
g=erer+eϕeϕg = e^{ r }\otimes e^{ r }+e^{ {\phi} }\otimes e^{ {\phi} }

In the above display, ere^r and eϕe^\phi are the 1-forms defining the coframe dual to the orthonormal polar frame (er,eϕ)(e_r,e_\phi), which is the default vector frame on E2\mathbb{E}^2:

In [88]:
polar_frame.coframe()
(E2,(er,eϕ))\left(\mathbb{E}^{2}, \left(e^{ r },e^{ {\phi} }\right)\right)

Of course, we may ask for display with respect to frames different from the default one:

In [89]:
g.display(cartesian.frame())
g=dxdx+dydyg = \mathrm{d} x\otimes \mathrm{d} x+\mathrm{d} y\otimes \mathrm{d} y
In [90]:
g.display(polar.frame())
g=drdr+r2dϕdϕg = \mathrm{d} r\otimes \mathrm{d} r + r^{2} \mathrm{d} {\phi}\otimes \mathrm{d} {\phi}
In [91]:
g[:]
(1001)\left(\begin{array}{rr} 1 & 0 \\ 0 & 1 \end{array}\right)
In [92]:
g[polar.frame(),:]
(100r2)\left(\begin{array}{rr} 1 & 0 \\ 0 & r^{2} \end{array}\right)

It is a flat metric: its (Riemann) curvature tensor is zero:

In [93]:
print(g.riemann())
Tensor field Riem(g) of type (1,3) on the Euclidean plane E^2
In [94]:
g.riemann().display()
Riem(g)=0\mathrm{Riem}\left(g\right) = 0

The metric gg is defining the dot product on E2\mathbb{E}^2:

In [95]:
v.dot(w) == g(v,w)
True\mathrm{True}
In [96]:
norm(v) == sqrt(g(v,v))
True\mathrm{True}

Vector fields as derivatives

Vector fields acts as derivative on scalar fields:

In [97]:
print(v(F))
Scalar field v(F) on the Euclidean plane E^2
In [98]:
v(F).display()
v(F):E2R(x,y)yfx+xfy(r,ϕ)rsin(ϕ)f(rcos(ϕ))+rcos(ϕ)f(rsin(ϕ))\begin{array}{llcl} v\left(F\right):& \mathbb{E}^{2} & \longrightarrow & \mathbb{R} \\ & \left(x, y\right) & \longmapsto & -y \frac{\partial\,f}{\partial x} + x \frac{\partial\,f}{\partial y} \\ & \left(r, {\phi}\right) & \longmapsto & -r \sin\left({\phi}\right) \frac{\partial\,f}{\partial \left( r \cos\left({\phi}\right) \right)} + r \cos\left({\phi}\right) \frac{\partial\,f}{\partial \left( r \sin\left({\phi}\right) \right)} \end{array}
In [99]:
v(F) == v.dot(grad(F))
True\mathrm{True}
In [100]:
dF = F.differential() print(dF)
1-form dF on the Euclidean plane E^2
In [101]:
v(F) == dF(v)
True\mathrm{True}

The set X(E2)\mathfrak{X}(\mathbb{E}^2) of all vector fields on E2\mathbb{E}^2 is a free module of rank 2 over the commutative algebra of smooth scalar fields on E2\mathbb{E}^2, C(E2)C^\infty(\mathbb{E}^2):

In [102]:
XE = v.parent() print(XE) XE
Free module X(E^2) of vector fields on the Euclidean plane E^2
X(E2)\mathfrak{X}\left(\mathbb{E}^{2}\right)
In [103]:
print(XE.category())
Category of finite dimensional modules over Algebra of differentiable scalar fields on the Euclidean plane E^2
In [104]:
print(XE.base_ring()) XE.base_ring()
Algebra of differentiable scalar fields on the Euclidean plane E^2
C(E2)C^{\infty}\left(\mathbb{E}^{2}\right)
In [105]:
CE = F.parent() CE
C(E2)C^{\infty}\left(\mathbb{E}^{2}\right)
In [106]:
CE is XE.base_ring()
True\mathrm{True}
In [107]:
print(CE.category())
Category of commutative algebras over Symbolic Ring
In [108]:
rank(XE)
22

The bases of the free module X(E2)\mathfrak{X}(\mathbb{E}^2) are nothing but the vector frames defined on E2\mathbb{E}^2:

In [109]:
XE.bases()
[(E2,(ex,ey)),(E2,(r,ϕ)),(E2,(er,eϕ))]\left[\left(\mathbb{E}^{2}, \left(e_{ x },e_{ y }\right)\right), \left(\mathbb{E}^{2}, \left(\frac{\partial}{\partial r },\frac{\partial}{\partial {\phi} }\right)\right), \left(\mathbb{E}^{2}, \left(e_{ r },e_{ {\phi} }\right)\right)\right]

Tangent spaces

Vector fields evaluated at a point are vectors in the tangent space at this point:

In [110]:
vp = v.at(p) vp.display()
v=3ex2eyv = -3 e_{ x } -2 e_{ y }
In [111]:
Tp = vp.parent() print(Tp) Tp
Tangent space at Point p on the Euclidean plane E^2
TpE2T_{p}\,\mathbb{E}^{2}
In [112]:
print(Tp.category())
Category of finite dimensional vector spaces over Symbolic Ring
In [113]:
dim(Tp)
22
In [114]:
isinstance(Tp, FiniteRankFreeModule)
True\mathrm{True}
In [115]:
Tp.bases()
[(ex,ey),(r,ϕ),(er,eϕ)]\left[\left(e_{ x },e_{ y }\right), \left(\frac{\partial}{\partial r },\frac{\partial}{\partial {\phi} }\right), \left(e_{ r },e_{ {\phi} }\right)\right]

Levi-Civita connection

The Levi-Civita connection associated to the Euclidean metric gg is

In [116]:
nabla = g.connection() print(nabla) nabla
Levi-Civita connection nabla_g associated with the Riemannian metric g on the Euclidean plane E^2
g\nabla_{g}

The corresponding Christoffel symbols with respect to the polar coordinates are:

In [117]:
g.christoffel_symbols_display()
Γrϕϕrϕϕ=rΓϕrϕϕrϕ=1r\begin{array}{lcl} \Gamma_{ \phantom{\, r} \, {\phi} \, {\phi} }^{ \, r \phantom{\, {\phi}} \phantom{\, {\phi}} } & = & -r \\ \Gamma_{ \phantom{\, {\phi}} \, r \, {\phi} }^{ \, {\phi} \phantom{\, r} \phantom{\, {\phi}} } & = & \frac{1}{r} \end{array}

By default, only nonzero and nonredundant values are displayed (for instance Γ ϕrϕ\Gamma^\phi_{\ \, \phi r} is skipped, since it can be deduced from Γ rϕϕ\Gamma^\phi_{\ \, r \phi} by symmetry on the last two indices).

The Christoffel symbols with respect to the Cartesian coordinates are all zero:

In [118]:
g.christoffel_symbols_display(chart=cartesian, only_nonzero=False)
Γxxxxxx=0Γxxyxxy=0Γxyyxyy=0Γyxxyxx=0Γyxyyxy=0Γyyyyyy=0\begin{array}{lcl} \Gamma_{ \phantom{\, x} \, x \, x }^{ \, x \phantom{\, x} \phantom{\, x} } & = & 0 \\ \Gamma_{ \phantom{\, x} \, x \, y }^{ \, x \phantom{\, x} \phantom{\, y} } & = & 0 \\ \Gamma_{ \phantom{\, x} \, y \, y }^{ \, x \phantom{\, y} \phantom{\, y} } & = & 0 \\ \Gamma_{ \phantom{\, y} \, x \, x }^{ \, y \phantom{\, x} \phantom{\, x} } & = & 0 \\ \Gamma_{ \phantom{\, y} \, x \, y }^{ \, y \phantom{\, x} \phantom{\, y} } & = & 0 \\ \Gamma_{ \phantom{\, y} \, y \, y }^{ \, y \phantom{\, y} \phantom{\, y} } & = & 0 \end{array}

g\nabla_g is the connection involved in differential operators:

In [119]:
grad(F) == nabla(F).up(g)
True\mathrm{True}
In [120]:
nabla(F) == grad(F).down(g)
True\mathrm{True}
In [121]:
div(v) == nabla(v).trace()
True\mathrm{True}
In [122]:
div(w) == nabla(w).trace()
True\mathrm{True}
In [123]:
laplacian(F) == nabla(nabla(F).up(g)).trace()
True\mathrm{True}
In [124]:
laplacian(w) == nabla(nabla(w).up(g)).trace(1,2)
True\mathrm{True}