{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"# Enneper's Minimal Surface and its Curvatures\n",
"\n",
"Let's consider a torus, parametrized as a surface of revolution and compute its different curvatures."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
],
"source": [
"u,v = var('u v')\n",
"x(u,v) = ( u-u^3/3+u*v^2, v - v^3/3 +v*u^2, u^2 - v^2 )"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## First Step, all the partial derivatives we'll need.\n",
"\n",
"For all of our computations, we'll want the $u$ and $v$ partial derivatives of $x(u,v)$ of order 1 and 2. So we compute them and store them in some variables."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 2,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"xu = x.diff(u)\n",
"xv = x.diff(v)\n",
"xuu = x.diff(u,2)\n",
"xuv = xu.diff(v)\n",
"xvv = x.diff(v,2)\n",
"\n",
"show(xuv) # just as a check"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## First Fundamental Form"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 3,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"E = xu.dot_product(xu).simplify_full()\n",
"F = xu.dot_product(xv).simplify_full()\n",
"G = xv.dot_product(xv).simplify_full()\n",
"\n",
"I = matrix(SR, 2,2, [E,F, F, G])\n",
"show(I) # as a check"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## The Normal Vector"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 4,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"q = xu.cross_product(xv)\n",
"size = q.norm().simplify_full().canonicalize_radical()\n",
"show(size) # this should equal sqrt(EG-F^2), let's check"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 5,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"show(sqrt(E*G-F^2).canonicalize_radical()) # here is sqrt(EG-F^2)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 6,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"n = (q(u,v)/size).simplify_full()\n",
"show(n) # the unit normal vector"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 7,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"norm(n).simplify_full() # another check, just because things get brittle and I get worried."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## The Second Fundamental Form\n",
"\n",
"Now we have enough data to compute the second fundamental form. We don't have script letters here, so I'm gonna cheat."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 8,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"ell = n.dot_product(xuu)\n",
"em = n.dot_product(xuv)\n",
"en = n.dot_product(xvv)\n",
"\n",
"II = matrix(SR, 2,2, [ell, em, em, en]).simplify_full()\n",
"show(II)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## The Shape Operator"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 16,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"Product = I.inverse()*II\n",
"S = Product.simplify_full().canonicalize_radical()\n",
"show(S)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"u^4 + 2*u^2*v^2 + v^4 + 2*u^2 + 2*v^2 + 1"
]
},
"execution_count": 18,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"# An aside... computers are bad at algebra, generally speaking. That crazy denominator is just\n",
"((u^2+v^2+1)^2).expand()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Finally, _curvatures_\n",
"\n",
"The Gaussian curvature is the determinant of the shape operator:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 10,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"K = det(S)\n",
"show(K)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"The mean curvature is half the trace of the shape operator:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 11,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"H = (1/2)*S.trace()\n",
"show(H)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"...and the principal curvatures are the eigenvaules of the shape operator. In this case, the matrix is diagonal, so these are easy to read off. But generally, one could use this command:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[-2/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1),\n",
" 2/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1)]"
]
},
"execution_count": 12,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"S.eigenvalues()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"and if for some reason that command won't work for you, you can always do it by hand:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 13,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"p = S.characteristic_polynomial()\n",
"show(p)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[(-2*sqrt((u^4 + 2*u^2*v^2 + v^4 + 2*u^2 + 2*v^2 + 1)^(-2)), 1),\n",
" (2*sqrt((u^4 + 2*u^2*v^2 + v^4 + 2*u^2 + 2*v^2 + 1)^(-2)), 1)]"
]
},
"execution_count": 14,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"p.roots()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[-2/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1),\n",
" 2/(u^4 + v^4 + 2*(u^2 + 1)*v^2 + 2*u^2 + 1)]"
]
},
"execution_count": 15,
"metadata": {
},
"output_type": "execute_result"
}
],
"source": [
"[elt[0].simplify_full().canonicalize_radical() for elt in p.roots()]"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
],
"source": [
"cm = colormaps.autumn\n",
"def my_color(u,v): return float((4 + K.subs(u=u,v=v))/4)\n",
"Surface = parametric_plot3d(x(u,v), (u,-2,2),(v,-2,2) , color=(my_color,cm))"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": "\n