Wichita State University, Dept. of Mathematics
version()
%display latex
viewer3d = 'jmol'
We begin by defining python functions that return the parametrization and chart of the associated surface of revolution.
def param(func): #parametrization map from (u,v) plane to surface
F = func;
var('u v')
surf = vector([u,F(x = u)*cos(v),F(x = u)*sin(v)]);
return surf
def chart(X,Y,Z): #chart from surface to (u,v) plane
CH = {};
var('x');
S(x) = arcsin(x);
C(x) = arccos(x);
ff = {S(x),C(x)};
qq = (Y/sqrt(Y^2 + Z^2));
for i in range(2):
CH[i] = vector([X,ff[i](x = qq)]);
return CH
var('x');
var('t');
f(x) = 2 + cos(x);
Sf = param(f)
Sf
parametric_plot3d(Sf,(u,-2*pi,2*pi),(v,0,2*pi))
Let's look at some plot options.
surf_plot = parametric_plot3d(Sf,(u,-2*pi,2*pi),(v,0,2*pi),opacity=0.5);
original_curve = parametric_plot3d([t,f(t),0],(t,-2*pi,2*pi),thickness=2,color='red');
show(surf_plot + original_curve)
%display latex
var('t');
t1(t) = t^3;
t2(t) = exp(t);
curve(t) = [Sf[0](u=t1,v=t2),Sf[1](u=t1,v=t2),Sf[2](u=t1,v=t2)];
curve_plot = parametric_plot3d(curve,(t,-2,2),color='red',thickness=2);
curve
curve_plot
This curve should lie on the surface.
show(surf_plot + curve_plot)
Next: induced metric, Christoffel symbols, and geodesics.
def sr_metric(func):
F = func;
FF = param(F);
uu = vector([FF[0].diff(u),FF[1].diff(u),FF[2].diff(u)]);
vv = vector([FF[0].diff(v),FF[1].diff(v),FF[2].diff(v)]);
g11 = uu.dot_product(uu).simplify_full();
g12 = uu.dot_product(vv).simplify_full();
g22 = vv.dot_product(vv).simplify_full();
M = matrix([[g11,g12],[g12,g22]]);
return M
g = sr_metric(f);
g
def sr_christoffel(func):
F = func;
G = sr_metric(F);
GI = G.inverse();
GG = [None]*2;
vv = [u,v];
for i in range(2):
GG[i] = {}
for j in range(2):
GG[i][j] = {}
for k in range(2):
GG[i][j][k] = (1/2)*sum(GI[k,m]*(G[m,i].diff(vv[j]) +
G[m,j].diff(vv[i]) - G[i,j].diff(vv[m])) for m in range(2)).simplify_full();
return GG
CS = sr_christoffel(f);
for i in range(2):
for j in range(2):
for k in range(2):
print (i,j,k), ' : ', CS[i][j][k]
The Christoffel symbols are the coefficients of the Levi-Civita connection (or covariant derivative), which describes how tangent vectors are parallel transported along curves in the surface. If $\{\partial_1,...\partial_n\}$ are the basis vector fields induced by the local coordinates, then
$\displaystyle \nabla_{\partial_i}\partial_j = \Sigma_{k=1}^n\Gamma_{ij}^k \partial_k$.
In particular, this applies to the velocity vector field of a curve along the curve itself: A curve $\alpha :(-t_0,t_0) \to S_f$ is said to be a geodesic if its velocity vector field is parallel; that is, if
$\ddot{\alpha} := \nabla_{\dot{\alpha}} \dot{\alpha} = 0$.
It is important to note here that $\ddot{\alpha}$ is not the component-wise second derivative from Calculus III. It is the covariant derivative of the velocity field along itself. The covariant derivative can be written out in terms of its coefficients, the Christoffel symbols. Thus we obtain a system of differential equations that determine criteria for $\alpha$ to be a geodesic. These are known as the geodesic equation(s). If $\alpha(t) = [\alpha_0(t), \alpha_1(t)]$ (indices chosen to match Sage code), then the geodesic equation for the $k^\mathrm{th}$ component is
$\dfrac{ d^2\alpha_k}{dt^2} + \Sigma_{i,j = 0}^1 \Gamma^k_{ij} \dfrac{d \alpha_i}{dt} \dfrac{d \alpha_j}{dt} = 0$.
def sr_geodesic(func,pos,vel): # geodesic equation
F = func;
# pos is initial position
# vel is initial velocity
CSF = sr_christoffel(F);
t = var('t');
U = function('U')(t);
V = function('V')(t);
WW = U.diff(t);
ZZ = V.diff(t)
comp = [U,V,WW,ZZ];
eqn = {}
for k in range(2):
eqn[k] = (comp[k+2].diff(t) + sum(sum(CSF[i][j][k](u = U)(v = V)*comp[i].diff(t)*comp[j].diff(t) for i in range(2)) for j in range(2)) == 0);
Sol = desolve_system([eqn[0],eqn[1]],[U,V,WW,ZZ],ivar=t,ics=[0,pos[0],pos[1],vel[0],vel[1]])
UU = Sol[0].simplify_full();
VV = Sol[1].simplify_full();
return UU, VV
GEO = sr_geodesic(f,[0,0],[0,1])
GEO
surf_plot = parametric_plot3d(Sf,(u,-2*pi,2*pi),(v,0,2*pi),opacity=0.25);
geod_plot = parametric_plot3d([Sf[0](u = GEO[0].rhs())(v = GEO[1].rhs()),
Sf[1](u = GEO[0].rhs())(v = GEO[1].rhs()),
Sf[2](u = GEO[0].rhs())(v = GEO[1].rhs())],(t,-4,4),color='red',thickness=1.5);
Let's try a "nicer" function.
g(x) = 2;
Sg = param(g);
geo_g1 = sr_geodesic(g,[0,0],[1,0]);
geo_g2 = sr_geodesic(g,[0,0],[0,1]);
geo_g3 = sr_geodesic(g,[0,0],[1,1]);
geo_plot1 = parametric_plot3d([Sg[0](u = geo_g1[0].rhs())(v = geo_g1[1].rhs()),
Sg[1](u = geo_g1[0].rhs())(v = geo_g1[1].rhs()),
Sg[2](u = geo_g1[0].rhs())(v = geo_g1[1].rhs())],(t,-4,4),color='red',thickness=1.5);
geo_plot2 = parametric_plot3d([Sg[0](u = geo_g2[0].rhs())(v = geo_g2[1].rhs()),
Sg[1](u = geo_g2[0].rhs())(v = geo_g2[1].rhs()),
Sg[2](u = geo_g2[0].rhs())(v = geo_g2[1].rhs())],(t,-4,4),color='black',thickness=1.5);
geo_plot3 = parametric_plot3d([Sg[0](u = geo_g3[0].rhs())(v = geo_g3[1].rhs()),
Sg[1](u = geo_g3[0].rhs())(v = geo_g3[1].rhs()),
Sg[2](u = geo_g3[0].rhs())(v = geo_g3[1].rhs())],(t,-4,4),color='purple',thickness=1.5);
surf_plot = parametric_plot3d(Sg,(u,-4,4),(v,0,2*pi),opacity=0.25);
show(surf_plot + geo_plot1 + geo_plot2 + geo_plot3)
h(x) = 1+ x^2;
Sh = param(h);
geo_h1 = sr_geodesic(h,[0,0],[1,0]);
geo_h2 = sr_geodesic(h,[0,0],[0,1]);
geo_h3 = sr_geodesic(h,[0,0],[1,1]);
geo_hplot1 = parametric_plot3d([Sh[0](u = geo_h1[0].rhs())(v = geo_h1[1].rhs()),
Sh[1](u = geo_h1[0].rhs())(v = geo_h1[1].rhs()),
Sh[2](u = geo_h1[0].rhs())(v = geo_h1[1].rhs())],(t,-4,4),color='red',thickness=1.5);
geo_hplot2 = parametric_plot3d([Sh[0](u = geo_h2[0].rhs())(v = geo_h2[1].rhs()),
Sh[1](u = geo_h2[0].rhs())(v = geo_h2[1].rhs()),
Sh[2](u = geo_h2[0].rhs())(v = geo_h2[1].rhs())],(t,-4,4),color='black',thickness=1.5);
geo_hplot3 = parametric_plot3d([Sh[0](u = geo_h3[0].rhs())(v = geo_h3[1].rhs()),
Sh[1](u = geo_h3[0].rhs())(v = geo_h3[1].rhs()),
Sh[2](u = geo_h3[0].rhs())(v = geo_h3[1].rhs())],(t,-4,4),color='purple',thickness=1.5);
surf_plot = parametric_plot3d(Sh,(u,-4,4),(v,0,2*pi),opacity=0.25);
show(surf_plot + geo_hplot1 + geo_hplot2 + geo_hplot3)