{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Mixed Forms and Characteristic Classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This Jupyter notebook illustrates SageMath's functionalities regarding mixed differential forms and characteristic classes. The involved tools have been developed through the [SageManifolds](https://sagemanifolds.obspm.fr) project. \n", "\n", "**Author:** *Michael Jung*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A version of SageMath at least equal to 9.4 is required to run this notebook:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'SageMath version 9.4.rc1, Release Date: 2021-08-08'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we set up the notebook to display math formulas using LaTeX formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%display latex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mixed Differential Forms" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We briefly demonstrate the capabilities of our implementation, and start by declaring the manifold $M=\\mathbb{R}^2$:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "M = Manifold(2, 'R^2', latex_name=r'\\mathbb{R}^2')\n", "X. = M.chart()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define the corresponding spaces of differential forms:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Algebra of differentiable scalar fields on the 2-dimensional differentiable manifold R^2\n", "Free module Omega^1(R^2) of 1-forms on the 2-dimensional differentiable manifold R^2\n", "Free module Omega^2(R^2) of 2-forms on the 2-dimensional differentiable manifold R^2\n" ] } ], "source": [ "Omega0 = M.diff_form_module(0); print(Omega0)\n", "Omega1 = M.diff_form_module(1); print(Omega1)\n", "Omega2 = M.diff_form_module(2); print(Omega2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The algebra of mixed forms is returned by a simple command:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Graded algebra Omega^*(R^2) of mixed differential forms on the 2-dimensional differentiable manifold R^2\n" ] } ], "source": [ "Omega = M.mixed_form_algebra(); print(Omega)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It belongs to the category of graded algebras over the symbolic ring:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Join of Category of graded algebras over Symbolic Ring and Category of chain complexes over Symbolic Ring\n" ] } ], "source": [ "print(Omega.category())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us define a mixed differential form:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mixed differential form A on the 2-dimensional differentiable manifold R^2\n" ] } ], "source": [ "A = M.mixed_form(name='A'); print(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The homogeneous components of A can be accessed and altered using the A[i] syntax:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "A[0].set_expr(x^2)\n", "A[1][:] = y, 2*x\n", "A[2][0,1] = 4*x^3" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}A = {A}_{0} + {A}_{1} + {A}_{2}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}A = {A}_{0} + {A}_{1} + {A}_{2}$$" ], "text/plain": [ "A = A_0 + A_1 + A_2" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.display()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}A = x^{2} + y \\mathrm{d} x + 2 \\, x \\mathrm{d} y + 4 \\, x^{3} \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}A = x^{2} + y \\mathrm{d} x + 2 \\, x \\mathrm{d} y + 4 \\, x^{3} \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "A = x^2 + y dx + 2*x dy + 4*x^3 dx∧dy" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.display_expansion()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\begin{array}{llcl} {A}_{0}:& \\mathbb{R}^2 & \\longrightarrow & \\mathbb{R} \\\\ & \\left(x, y\\right) & \\longmapsto & x^{2} \\end{array}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\begin{array}{llcl} {A}_{0}:& \\mathbb{R}^2 & \\longrightarrow & \\mathbb{R} \\\\ & \\left(x, y\\right) & \\longmapsto & x^{2} \\end{array}$$" ], "text/plain": [ "A_0: R^2 → ℝ\n", " (x, y) ↦ x^2" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[0].display()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}{A}_{1} = y \\mathrm{d} x + 2 \\, x \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}{A}_{1} = y \\mathrm{d} x + 2 \\, x \\mathrm{d} y$$" ], "text/plain": [ "A_1 = y dx + 2*x dy" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1].display()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}{A}_{2} = 4 \\, x^{3} \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}{A}_{2} = 4 \\, x^{3} \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "A_2 = 4*x^3 dx∧dy" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[2].display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The category framework of Sage captures the entire setup:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}$$" ], "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all([A[0] in Omega0,\n", " A[0] in Omega,\n", " A[1] in Omega1,\n", " A[1] in Omega,\n", " A[2] in Omega2,\n", " A[2] in Omega])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us perform some computations and define another mixed form. This time, we predefine some differential forms:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "f = M.scalar_field(2, name='f')\n", "\n", "eta = M.diff_form(1, name='eta', latex_name=r'\\eta')\n", "eta[:] = x, y\n", "\n", "xi = M.diff_form(2, name='xi', latex_name=r'\\xi')\n", "xi[0,1] = y^2" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B = f + \\eta + 0\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B = f + \\eta + 0$$" ], "text/plain": [ "B = f + eta + zero" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = M.mixed_form([f,eta,0], name='B'); B.display()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B = 2 + x \\mathrm{d} x + y \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B = 2 + x \\mathrm{d} x + y \\mathrm{d} y$$" ], "text/plain": [ "B = 2 + x dx + y dy" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B.display_expansion()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Though the homogeneous components share the same name, they are independent instances:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}$$" ], "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B[0] == f" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{False}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{False}$$" ], "text/plain": [ "False" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B[0] is f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As long as B is mutable, the homogeneous components can still be changed:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "B[2] = xi" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B = f + \\eta + \\xi\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B = f + \\eta + \\xi$$" ], "text/plain": [ "B = f + eta + xi" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But if we set the mixed form immutable, this is no longer possible:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "B.set_immutable()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "the components of an immutable element cannot be changed\n" ] } ], "source": [ "try:\n", " B[1] = 0\n", "except ValueError as ve:\n", " print(ve)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The multiplication is executed degree wise:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{True}$$" ], "text/plain": [ "True" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all((A * B)[k] == sum(A[j].wedge(B[k - j])\n", " for j in range(k + 1))\n", " for k in Omega.irange())" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}A\\wedge B = 2 \\, x^{2} + \\left( x^{3} + 2 \\, y \\right) \\mathrm{d} x + \\left( x^{2} y + 4 \\, x \\right) \\mathrm{d} y + \\left( 8 \\, x^{3} + {\\left(x^{2} + 1\\right)} y^{2} - 2 \\, x^{2} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}A\\wedge B = 2 \\, x^{2} + \\left( x^{3} + 2 \\, y \\right) \\mathrm{d} x + \\left( x^{2} y + 4 \\, x \\right) \\mathrm{d} y + \\left( 8 \\, x^{3} + {\\left(x^{2} + 1\\right)} y^{2} - 2 \\, x^{2} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "A∧B = 2*x^2 + (x^3 + 2*y) dx + (x^2*y + 4*x) dy + (8*x^3 + (x^2 + 1)*y^2 - 2*x^2) dx∧dy" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(A * B).display_expansion()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This particular example is also convenient to demonstrate that the multiplication given by the wedge product is in general neither commutative nor anticommutative:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B\\wedge A = 2 \\, x^{2} + \\left( x^{3} + 2 \\, y \\right) \\mathrm{d} x + \\left( x^{2} y + 4 \\, x \\right) \\mathrm{d} y + \\left( 8 \\, x^{3} + {\\left(x^{2} - 1\\right)} y^{2} + 2 \\, x^{2} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}B\\wedge A = 2 \\, x^{2} + \\left( x^{3} + 2 \\, y \\right) \\mathrm{d} x + \\left( x^{2} y + 4 \\, x \\right) \\mathrm{d} y + \\left( 8 \\, x^{3} + {\\left(x^{2} - 1\\right)} y^{2} + 2 \\, x^{2} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "B∧A = 2*x^2 + (x^3 + 2*y) dx + (x^2*y + 4*x) dy + (8*x^3 + (x^2 - 1)*y^2 + 2*x^2) dx∧dy" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(B * A).display_expansion()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, let us compute the exterior derivative:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{d}A = 2 \\, x \\mathrm{d} x +\\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{d}A = 2 \\, x \\mathrm{d} x +\\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "dA = 2*x dx + dx∧dy" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dA = A.exterior_derivative(); dA.display_expansion()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Characteristic Classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Chern Character over Minkowski Space" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We want to exemplify the usage of characteristic classes within Sage by computing the Chern character form $\\mathrm{ch}(E, \\nabla^E)$ on a complex trivial line bundle $E$ over the 2-dimensional Minkowski space $M$ equipped with a bundle connection $\\nabla^E$. We start with the general setup:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Differentiable complex vector bundle E -> M of rank 1 over the base space 2-dimensional Lorentzian manifold M\n" ] } ], "source": [ "M = Manifold(2, 'M', structure='Lorentzian')\n", "X. = M.chart()\n", "E = M.vector_bundle(1, 'E', field='complex'); print(E)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To trivialize the vector bundle $E$, we fix a global frame $e$:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "e = E.local_frame('e') # trivialize" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us declare an $\\mathrm{U}(1)$-connection $\\nabla^E$ on $E$ given by an electromagnetic potential $A(t)$:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "nab = E.bundle_connection('nabla^E', latex_name=r'\\nabla^E')\n", "A = function('A')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The corresponding connection form $\\omega$ turns out as:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\omega = i \\, A\\left(t\\right) \\mathrm{d} x\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\omega = i \\, A\\left(t\\right) \\mathrm{d} x$$" ], "text/plain": [ "omega = I*A(t) dx" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "omega = M.one_form(name='omega', latex_name=r'\\omega')\n", "omega[1] = I*A(t)\n", "omega.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us put this into the connection:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "nab[0,0] = omega" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the following, nab must be hashable. Thus we have to make it immutable first:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "nab.set_immutable()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the Chern character $\\mathrm{ch}(E)$ is already predefined in the system. We can get it by the following command:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Characteristic class ch of additive type associated to e^x on the Differentiable complex vector bundle E -> M of rank 1 over the base space 2-dimensional Lorentzian manifold M\n" ] } ], "source": [ "ch = E.characteristic_class('ChernChar'); print(ch)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The computation of the corresponding Chern character form $\\mathrm{ch}(E,\\nabla^E)$ can be invoked by the method get_form:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{ch}(E, \\nabla^E) = 1 + \\frac{\\frac{\\partial\\,A}{\\partial t}}{2 \\, \\pi} \\mathrm{d} t\\wedge \\mathrm{d} x\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{ch}(E, \\nabla^E) = 1 + \\frac{\\frac{\\partial\\,A}{\\partial t}}{2 \\, \\pi} \\mathrm{d} t\\wedge \\mathrm{d} x$$" ], "text/plain": [ "ch(E, nabla^E) = 1 + 1/2*d(A)/dt/pi dt∧dx" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ch_form = ch.get_form(nab)\n", "ch_form.display_expansion()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the resulting 2-form coincides with the Faraday tensor divided by $2 \\pi$ as expected." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example: Chern Class of the Tautological Line Bundle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start our computation by initializing the complex projective space as 2-dimensional real manifold with coordinates on $U:= \\mathbb{CP}^1 \\setminus \\left\\{ [1:0] \\right\\}$:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "M = Manifold(2, 'CP^1', start_index=1)\n", "U = M.open_subset('U')\n", "c_cart. = U.chart() # [1:x+I*y]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the sake of convenience, we additionally declare the complex coordinates $z$ and $\\bar{z}$ on $U$:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{lcl} {z} & = & x + i \\, y \\\\ {\\bar{z}} & = & x - i \\, y \\end{array}\\right.\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{lcl} {z} & = & x + i \\, y \\\\ {\\bar{z}} & = & x - i \\, y \\end{array}\\right.$$" ], "text/plain": [ "z = x + I*y\n", "zbar = x - I*y" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c_comp. = U.chart(r'z:z zbar:\\bar{z}')\n", "cart_to_comp = c_cart.transition_map(c_comp, (x+I*y, x-I*y))\n", "cart_to_comp.display()" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{lcl} x & = & \\frac{1}{2} \\, {z} + \\frac{1}{2} \\, {\\bar{z}} \\\\ y & = & -\\frac{1}{2} i \\, {z} + \\frac{1}{2} i \\, {\\bar{z}} \\end{array}\\right.\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{lcl} x & = & \\frac{1}{2} \\, {z} + \\frac{1}{2} \\, {\\bar{z}} \\\\ y & = & -\\frac{1}{2} i \\, {z} + \\frac{1}{2} i \\, {\\bar{z}} \\end{array}\\right.$$" ], "text/plain": [ "x = 1/2*z + 1/2*zbar\n", "y = -1/2*I*z + 1/2*I*zbar" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "comp_to_cart = cart_to_comp.inverse()\n", "comp_to_cart.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we are ready to construct the tautological line bundle $\\gamma_1$:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "E = M.vector_bundle(1, 'gamma_1',\n", " latex_name=r'\\gamma_1',\n", " field='complex')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Furthermore we declare a local frame $e$ on $U$ naturally given by $[z:1] \\mapsto \\left(\\begin{smallmatrix} z \\\\ 1 \\end{smallmatrix}\\right)$:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "e = E.local_frame('e', domain=U)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To compute the Chern class, we still need a connection. The tautological line bundle inherits a Hermitian metric from the overlying trivial bundle $\\mathbb{C}^2 \\times \\mathbb{CP}^1$:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "nab = E.bundle_connection('nabla', latex_name=r'\\nabla')\n", "omega = U.one_form(name='omega')\n", "omega[c_comp.frame(), 1, c_comp] = zbar/(1+z*zbar)\n", "nab[e, 1, 1] = omega\n", "nab.set_immutable()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is time to initialize $c(\\gamma_1)$. Fortunately Sage already knows the Chern class:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Characteristic class c of multiplicative type associated to x + 1 on the Differentiable complex vector bundle gamma_1 -> CP^1 of rank 1 over the base space 2-dimensional differentiable manifold CP^1\n" ] } ], "source": [ "c = E.characteristic_class('Chern'); print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let the machinery do its work:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}c(\\gamma_1, \\nabla) = 1 + \\frac{i}{2 \\, {\\left(\\pi + \\pi {z}^{2} {\\bar{z}}^{2} + 2 \\, \\pi {z} {\\bar{z}}\\right)}} \\mathrm{d} {z}\\wedge \\mathrm{d} {\\bar{z}}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}c(\\gamma_1, \\nabla) = 1 + \\frac{i}{2 \\, {\\left(\\pi + \\pi {z}^{2} {\\bar{z}}^{2} + 2 \\, \\pi {z} {\\bar{z}}\\right)}} \\mathrm{d} {z}\\wedge \\mathrm{d} {\\bar{z}}$$" ], "text/plain": [ "c(gamma_1, nabla) = 1 + 1/2*I/(pi + pi*z^2*zbar^2 + 2*pi*z*zbar) dz∧dzbar" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c_form = c.get_form(nab)\n", "c_form.display_expansion(c_comp.frame(), chart=c_comp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since this particular representation is defined outside a set of measure zero, we can compute its integral over $\\mathbb{CP}^1$ in real coordinates:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}1\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}1$$" ], "text/plain": [ "1" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(integrate(c_form[2][[1,2]].expr(c_cart), x, -infinity, infinity).full_simplify(), y, -infinity, infinity)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result shows that $c_1(\\gamma_1)$ generates the second integer cohomology $H^2(\\mathbb{CP}^1, \\mathbb{Z})$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Euler Class of $\\mathbb{S}^2$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, we want to compute the Euler class of the 2-sphere $\\mathbb{S}^2 \\subset \\mathbb{R}^3$. As usual, we cover $\\mathbb{S}^2$ by two parallelizable open subsets $U:=\\mathbb{S}^2 \\setminus \\{(0,0,1)\\}$ and $V:=\\mathbb{S}^2 \\setminus \\{(0,0,-1)\\}$ for which the point $(0,0,1)$ is identified with the north pole. We state stereographic coordinates in Sage: " ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "M = Manifold(2, name='S^2', latex_name=r'\\mathbb{S}^2',\n", " structure='Riemannian', start_index=1)\n", "U = M.open_subset('U') ; V = M.open_subset('V')\n", "M.declare_union(U,V) # M is the union of U and V\n", "stereoN. = U.chart()\n", "stereoS. = V.chart(\"xp:x' yp:y'\")\n", "N_to_S = stereoN.transition_map(stereoS,\n", " (x/(x^2+y^2), y/(x^2+y^2)),\n", " intersection_name='W',\n", " restrictions1= x^2+y^2!=0,\n", " restrictions2= xp^2+yp^2!=0)\n", "S_to_N = N_to_S.inverse()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we define the tangent bundle and its local frames induced by the charts:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "eU = stereoN.frame(); eV = stereoS.frame()\n", "TM = M.tangent_bundle()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Euler class is also one of the predefined classes. Thus, we can easily get it from the tangent bundle's instance:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Characteristic class e of Pfaffian type associated to x on the Tangent bundle TS^2 over the 2-dimensional Riemannian manifold S^2\n" ] } ], "source": [ "e_class = TM.characteristic_class('Euler'); print(e_class)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To compute a form representing the Euler class, we need to state a suitable connection first. Here we want to use the Levi-Civita connection induced by the standard metric. This is simply given by the pullback of the Euclidean scalar product of the ambient space $\\mathbb{R}^3$ along the canonical embedding $\\iota: \\mathbb{S}^2 \\hookrightarrow \\mathbb{R}^3$. Let us define the ambient space $\\mathbb{R}^3$ and its Euclidean scalar product $h$:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}h = \\mathrm{d} X\\otimes \\mathrm{d} X+\\mathrm{d} Y\\otimes \\mathrm{d} Y+\\mathrm{d} Z\\otimes \\mathrm{d} Z\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}h = \\mathrm{d} X\\otimes \\mathrm{d} X+\\mathrm{d} Y\\otimes \\mathrm{d} Y+\\mathrm{d} Z\\otimes \\mathrm{d} Z$$" ], "text/plain": [ "h = dX⊗dX + dY⊗dY + dZ⊗dZ" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E = Manifold(3, 'R^3', latex_name=r'\\mathbb{R}^3', start_index=1)\n", "cart. = E.chart()\n", "h = E.metric('h')\n", "h[1,1], h[2,2], h[3, 3] = 1, 1, 1\n", "h.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On that account, we declare the embedding $\\iota: \\mathbb{S}^2 \\hookrightarrow \\mathbb{R}^3$ in stereographic coordinates when one considers its projection from the north pole $(0, 0, 1)$ to the equatorial plane $Z=0$:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\begin{array}{llcl} \\iota:& \\mathbb{S}^2 & \\longrightarrow & \\mathbb{R}^3 \\\\ \\mbox{on}\\ U : & \\left(x, y\\right) & \\longmapsto & \\left(X, Y, Z\\right) = \\left(\\frac{2 \\, x}{x^{2} + y^{2} + 1}, \\frac{2 \\, y}{x^{2} + y^{2} + 1}, -\\frac{x^{2} + y^{2} - 1}{x^{2} + y^{2} + 1}\\right) \\\\ \\mbox{on}\\ V : & \\left({x'}, {y'}\\right) & \\longmapsto & \\left(X, Y, Z\\right) = \\left(\\frac{2 \\, {x'}}{{x'}^{2} + {y'}^{2} + 1}, \\frac{2 \\, {y'}}{{x'}^{2} + {y'}^{2} + 1}, \\frac{{x'}^{2} + {y'}^{2} - 1}{{x'}^{2} + {y'}^{2} + 1}\\right) \\end{array}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\begin{array}{llcl} \\iota:& \\mathbb{S}^2 & \\longrightarrow & \\mathbb{R}^3 \\\\ \\mbox{on}\\ U : & \\left(x, y\\right) & \\longmapsto & \\left(X, Y, Z\\right) = \\left(\\frac{2 \\, x}{x^{2} + y^{2} + 1}, \\frac{2 \\, y}{x^{2} + y^{2} + 1}, -\\frac{x^{2} + y^{2} - 1}{x^{2} + y^{2} + 1}\\right) \\\\ \\mbox{on}\\ V : & \\left({x'}, {y'}\\right) & \\longmapsto & \\left(X, Y, Z\\right) = \\left(\\frac{2 \\, {x'}}{{x'}^{2} + {y'}^{2} + 1}, \\frac{2 \\, {y'}}{{x'}^{2} + {y'}^{2} + 1}, \\frac{{x'}^{2} + {y'}^{2} - 1}{{x'}^{2} + {y'}^{2} + 1}\\right) \\end{array}$$" ], "text/plain": [ "iota: S^2 → R^3\n", "on U: (x, y) ↦ (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1), -(x^2 + y^2 - 1)/(x^2 + y^2 + 1))\n", "on V: (xp, yp) ↦ (X, Y, Z) = (2*xp/(xp^2 + yp^2 + 1), 2*yp/(xp^2 + yp^2 + 1), (xp^2 + yp^2 - 1)/(xp^2 + yp^2 + 1))" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iota = M.diff_map(E, {(stereoN, cart):\n", " [2*x/(1+x^2+y^2), 2*y/(1+x^2+y^2),\n", " (1-x^2-y^2)/(1+x^2+y^2)],\n", " (stereoS, cart):\n", " [2*xp/(1+xp^2+yp^2), 2*yp/(1+xp^2+yp^2),\n", " (xp^2+yp^2-1)/(1+xp^2+yp^2)]},\n", " name='iota', latex_name=r'\\iota')\n", "iota.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can define the standard metric $g$ on $\\mathbb{S}^2$ by setting it as the pullback metric $\\iota^*h$:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}g = \\frac{4}{{\\left(x^{2} + y^{2} + 1\\right)}^{2}} \\mathrm{d} x\\otimes \\mathrm{d} x + \\frac{4}{{\\left(x^{2} + y^{2} + 1\\right)}^{2}} \\mathrm{d} y\\otimes \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}g = \\frac{4}{{\\left(x^{2} + y^{2} + 1\\right)}^{2}} \\mathrm{d} x\\otimes \\mathrm{d} x + \\frac{4}{{\\left(x^{2} + y^{2} + 1\\right)}^{2}} \\mathrm{d} y\\otimes \\mathrm{d} y$$" ], "text/plain": [ "g = 4/(x^2 + y^2 + 1)^2 dx⊗dx + 4/(x^2 + y^2 + 1)^2 dy⊗dy" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g = M.metric()\n", "g.set(iota.pullback(h))\n", "g[1,1].factor(); g[2,2].factor() # simplifications\n", "g.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The corresponding Levi-Civita connection is computed automatically:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": [ "nab = g.connection()\n", "nab.set_immutable()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since we have found the desired Levi-Civita connection, we want to compute the associated curvature forms and store them in a Python list:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "cmatrix_U = [[nab.curvature_form(i,j,eU) for j in TM.irange()]\n", " for i in TM.irange()]\n", "cmatrix_V = [[nab.curvature_form(i,j,eV) for j in TM.irange()]\n", " for i in TM.irange()]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Fortunately, the curvature form matrices are already skew-symmetric:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 1} = 0\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 1} = 0$$" ], "text/plain": [ "curvature (1,1) of connection nabla_g w.r.t. Coordinate frame (U, (∂/∂x,∂/∂y)) = 0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 2} = \\left( \\frac{4}{x^{4} + y^{4} + 2 \\, {\\left(x^{2} + 1\\right)} y^{2} + 2 \\, x^{2} + 1} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 2} = \\left( \\frac{4}{x^{4} + y^{4} + 2 \\, {\\left(x^{2} + 1\\right)} y^{2} + 2 \\, x^{2} + 1} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "curvature (1,2) of connection nabla_g w.r.t. Coordinate frame (U, (∂/∂x,∂/∂y)) = 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dx∧dy" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 1} = \\left( -\\frac{4}{x^{4} + y^{4} + 2 \\, {\\left(x^{2} + 1\\right)} y^{2} + 2 \\, x^{2} + 1} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 1} = \\left( -\\frac{4}{x^{4} + y^{4} + 2 \\, {\\left(x^{2} + 1\\right)} y^{2} + 2 \\, x^{2} + 1} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "curvature (2,1) of connection nabla_g w.r.t. Coordinate frame (U, (∂/∂x,∂/∂y)) = -4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dx∧dy" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 2} = 0\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 2} = 0$$" ], "text/plain": [ "curvature (2,2) of connection nabla_g w.r.t. Coordinate frame (U, (∂/∂x,∂/∂y)) = 0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in range(TM.rank()):\n", " for j in range(TM.rank()):\n", " show(cmatrix_U[i][j].display())" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 1} = 0\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 1} = 0$$" ], "text/plain": [ "curvature (1,1) of connection nabla_g w.r.t. Coordinate frame (V, (∂/∂xp,∂/∂yp)) = 0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 2} = \\left( \\frac{4}{{x'}^{4} + {y'}^{4} + 2 \\, {\\left({x'}^{2} + 1\\right)} {y'}^{2} + 2 \\, {x'}^{2} + 1} \\right) \\mathrm{d} {x'}\\wedge \\mathrm{d} {y'}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^1_{\\ \\, 2} = \\left( \\frac{4}{{x'}^{4} + {y'}^{4} + 2 \\, {\\left({x'}^{2} + 1\\right)} {y'}^{2} + 2 \\, {x'}^{2} + 1} \\right) \\mathrm{d} {x'}\\wedge \\mathrm{d} {y'}$$" ], "text/plain": [ "curvature (1,2) of connection nabla_g w.r.t. Coordinate frame (V, (∂/∂xp,∂/∂yp)) = 4/(xp^4 + yp^4 + 2*(xp^2 + 1)*yp^2 + 2*xp^2 + 1) dxp∧dyp" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 1} = \\left( -\\frac{4}{{x'}^{4} + {y'}^{4} + 2 \\, {\\left({x'}^{2} + 1\\right)} {y'}^{2} + 2 \\, {x'}^{2} + 1} \\right) \\mathrm{d} {x'}\\wedge \\mathrm{d} {y'}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 1} = \\left( -\\frac{4}{{x'}^{4} + {y'}^{4} + 2 \\, {\\left({x'}^{2} + 1\\right)} {y'}^{2} + 2 \\, {x'}^{2} + 1} \\right) \\mathrm{d} {x'}\\wedge \\mathrm{d} {y'}$$" ], "text/plain": [ "curvature (2,1) of connection nabla_g w.r.t. Coordinate frame (V, (∂/∂xp,∂/∂yp)) = -4/(xp^4 + yp^4 + 2*(xp^2 + 1)*yp^2 + 2*xp^2 + 1) dxp∧dyp" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 2} = 0\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Omega^2_{\\ \\, 2} = 0$$" ], "text/plain": [ "curvature (2,2) of connection nabla_g w.r.t. Coordinate frame (V, (∂/∂xp,∂/∂yp)) = 0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in range(TM.rank()):\n", " for j in range(TM.rank()):\n", " show(cmatrix_V[i][j].display())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hence we can put them into a dictionary and apply the algorithm:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}e(T\\mathbb{S}^2, \\nabla_{g}) = \\left( \\frac{2}{\\pi + \\pi x^{4} + \\pi y^{4} + 2 \\, \\pi x^{2} + 2 \\, {\\left(\\pi + \\pi x^{2}\\right)} y^{2}} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}e(T\\mathbb{S}^2, \\nabla_{g}) = \\left( \\frac{2}{\\pi + \\pi x^{4} + \\pi y^{4} + 2 \\, \\pi x^{2} + 2 \\, {\\left(\\pi + \\pi x^{2}\\right)} y^{2}} \\right) \\mathrm{d} x\\wedge \\mathrm{d} y$$" ], "text/plain": [ "e(TS^2, nabla_g) = 2/(pi + pi*x^4 + pi*y^4 + 2*pi*x^2 + 2*(pi + pi*x^2)*y^2) dx∧dy" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cmatrices = {eU: cmatrix_U, eV: cmatrix_V}\n", "e_class_form = e_class.get_form(nab, cmatrices)\n", "e_class_form.display_expansion()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We want to compute the Euler characteristic of $\\mathbb{S}^2$ now. This can be achieved by integrating the top form over $\\mathbb{S}^2$. But since $U$ and $\\mathbb{S}^2$ differ only by a point and therefore a set of measure zero, it is enough to integrate over the subset $U$:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}2\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}2$$" ], "text/plain": [ "2" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "integrate(integrate(e_class_form[2][[1,2]].expr(), x, -infinity, infinity).simplify_full(), y, -infinity, infinity)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have eventually obtained the Euler characteristic of $\\mathbb{S}^2$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### $\\hat{A}$-Class of Lorentzian Foliation of Berger Spheres" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We consider the space of unit quaternions $\\mathbb{S}^3 \\subset \\mathbb{R}^4 \\cong \\mathbb{H}$, where $\\mathbb{H}$ is endowed with the canonical basis $(\\mathbf{1}, \\mathbf{i}, \\mathbf{j}, \\mathbf{k})$. It turns out that $\\mathbb{S}^3$ admits a global frame $(\\varepsilon_1, \\varepsilon_2, \\varepsilon_3)$ so that we observe $\\mathbb{S}^3$ to be a parallelizable manifold.\n", "\n", "We introduce the following smooth family of so-called *Berger metrics*:\n", "\\begin{align*}\t\n", "\tg_t = a(t)^{2} \\; \\varepsilon^{1}\\otimes \\varepsilon^{1} +\\varepsilon^{2}\\otimes \\varepsilon^{2} +\\varepsilon^{3}\\otimes \\varepsilon^{3}.\n", "\\end{align*}\n", "\n", "This family can be used to define a globally hyperbolic manifold $M=\\mathbb{R} \\times \\mathbb{S}^3$ equipped with the Lorentzian metric $g = - {\\mathrm{d} t}^2 + g_t$ and hence foliated by Berger spheres.\n", "\n", "In the following we compute the $\\hat{A}$-form of the corresponding Levi-Civita connection $\\nabla_g$. We start the computation by declaring the Lorentzian manifold first:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4-dimensional Lorentzian manifold M\n" ] } ], "source": [ "M = Manifold(4, 'M', structure='Lorentzian'); print(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We cover $M$ by two open subsets defined as $U := \\mathbb{R} \\times \\left( \\mathbb{S}^3 \\setminus \\{ -\\mathbf{1} \\} \\right)$ and $V := \\mathbb{R} \\times \\left( \\mathbb{S}^3 \\setminus \\{ \\mathbf{1} \\} \\right)$:" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": [ "U = M.open_subset('U'); V = M.open_subset('V')\n", "M.declare_union(U,V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need to impose coordinates on $M$ and use stereographic projections with respect to the foliated 3-sphere:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{lcl} {t'} & = & t \\\\ {x'} & = & \\frac{x}{x^{2} + y^{2} + {z}^{2}} \\\\ {y'} & = & \\frac{y}{x^{2} + y^{2} + {z}^{2}} \\\\ {z'} & = & \\frac{{z}}{x^{2} + y^{2} + {z}^{2}} \\end{array}\\right.\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\begin{array}{lcl} {t'} & = & t \\\\ {x'} & = & \\frac{x}{x^{2} + y^{2} + {z}^{2}} \\\\ {y'} & = & \\frac{y}{x^{2} + y^{2} + {z}^{2}} \\\\ {z'} & = & \\frac{{z}}{x^{2} + y^{2} + {z}^{2}} \\end{array}\\right.$$" ], "text/plain": [ "tp = t\n", "xp = x/(x^2 + y^2 + z^2)\n", "yp = y/(x^2 + y^2 + z^2)\n", "zp = z/(x^2 + y^2 + z^2)" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stereoN. = U.chart()\n", "stereoS. = V.chart(\"tp:t' xp:x' yp:y' zp:z'\")\n", "N_to_S = stereoN.transition_map(stereoS,\n", " (t, x/(x^2+y^2+z^2),\n", " y/(x^2+y^2+z^2),\n", " z/(x^2+y^2+z^2)),\n", " intersection_name='W',\n", " restrictions1= x^2+y^2+z^2!=0,\n", " restrictions2= xp^2+yp^2+zp^2!=0)\n", "W = U.intersection(V)\n", "S_to_N = N_to_S.inverse()\n", "N_to_S.display()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "From above, we know that $M$ admits a global frame $(\\varepsilon_0, \\varepsilon_1, \\varepsilon_2, \\varepsilon_3)$:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(U, \\left(\\varepsilon_{0},\\varepsilon_{1},\\varepsilon_{2},\\varepsilon_{3}\\right)\\right)\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(U, \\left(\\varepsilon_{0},\\varepsilon_{1},\\varepsilon_{2},\\varepsilon_{3}\\right)\\right)$$" ], "text/plain": [ "Vector frame (U, (E_0,E_1,E_2,E_3))" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E = M.vector_frame('E', latex_symbol=r'\\varepsilon')\n", "E_U = E.restrict(U); E_U" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The vector field $\\varepsilon_0$ is simply given by $\\frac{\\partial}{\\partial t}$. To obtain the global vector frame $(\\varepsilon_1, \\varepsilon_2, \\varepsilon_3)$ on $\\mathbb{S}^3$ in stereographic coordinates, a computation within Sage is performed in the [this](https://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S3_vectors.ipynb) Jupyter-Notebook. This is done by embedding $\\mathbb{S}^3$ into $\\mathbb{R}^4 \\cong \\mathbb{H}$, endowing it with the quaternionic structure. This eventually leads to:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "E_U[0][:] = [1,0,0,0]\n", "E_U[1][:] = [0, (x^2-y^2-z^2+1)/2, x*y+z, x*z-y]\n", "E_U[2][:] = [0, x*y-z, (1-x^2+y^2-z^2)/2, x+y*z] \n", "E_U[3][:] = [0, x*z+y, y*z-x, (1-x^2-y^2+z^2)/2]" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{0} = \\frac{\\partial}{\\partial t }\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{0} = \\frac{\\partial}{\\partial t }$$" ], "text/plain": [ "E_0 = ∂/∂t" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{1} = \\left( \\frac{1}{2} \\, x^{2} - \\frac{1}{2} \\, y^{2} - \\frac{1}{2} \\, {z}^{2} + \\frac{1}{2} \\right) \\frac{\\partial}{\\partial x } + \\left( x y + {z} \\right) \\frac{\\partial}{\\partial y } + \\left( x {z} - y \\right) \\frac{\\partial}{\\partial {z} }\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{1} = \\left( \\frac{1}{2} \\, x^{2} - \\frac{1}{2} \\, y^{2} - \\frac{1}{2} \\, {z}^{2} + \\frac{1}{2} \\right) \\frac{\\partial}{\\partial x } + \\left( x y + {z} \\right) \\frac{\\partial}{\\partial y } + \\left( x {z} - y \\right) \\frac{\\partial}{\\partial {z} }$$" ], "text/plain": [ "E_1 = (1/2*x^2 - 1/2*y^2 - 1/2*z^2 + 1/2) ∂/∂x + (x*y + z) ∂/∂y + (x*z - y) ∂/∂z" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{2} = \\left( x y - {z} \\right) \\frac{\\partial}{\\partial x } + \\left( -\\frac{1}{2} \\, x^{2} + \\frac{1}{2} \\, y^{2} - \\frac{1}{2} \\, {z}^{2} + \\frac{1}{2} \\right) \\frac{\\partial}{\\partial y } + \\left( y {z} + x \\right) \\frac{\\partial}{\\partial {z} }\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{2} = \\left( x y - {z} \\right) \\frac{\\partial}{\\partial x } + \\left( -\\frac{1}{2} \\, x^{2} + \\frac{1}{2} \\, y^{2} - \\frac{1}{2} \\, {z}^{2} + \\frac{1}{2} \\right) \\frac{\\partial}{\\partial y } + \\left( y {z} + x \\right) \\frac{\\partial}{\\partial {z} }$$" ], "text/plain": [ "E_2 = (x*y - z) ∂/∂x + (-1/2*x^2 + 1/2*y^2 - 1/2*z^2 + 1/2) ∂/∂y + (y*z + x) ∂/∂z" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{3} = \\left( x {z} + y \\right) \\frac{\\partial}{\\partial x } + \\left( y {z} - x \\right) \\frac{\\partial}{\\partial y } + \\left( -\\frac{1}{2} \\, x^{2} - \\frac{1}{2} \\, y^{2} + \\frac{1}{2} \\, {z}^{2} + \\frac{1}{2} \\right) \\frac{\\partial}{\\partial {z} }\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\varepsilon_{3} = \\left( x {z} + y \\right) \\frac{\\partial}{\\partial x } + \\left( y {z} - x \\right) \\frac{\\partial}{\\partial y } + \\left( -\\frac{1}{2} \\, x^{2} - \\frac{1}{2} \\, y^{2} + \\frac{1}{2} \\, {z}^{2} + \\frac{1}{2} \\right) \\frac{\\partial}{\\partial {z} }$$" ], "text/plain": [ "E_3 = (x*z + y) ∂/∂x + (y*z - x) ∂/∂y + (-1/2*x^2 - 1/2*y^2 + 1/2*z^2 + 1/2) ∂/∂z" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for i in M.irange():\n", " show(E_U[i].display())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To ensure evaluations in this particular frame, we must communicate the change-of-frame formula to Sage:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "P = U.automorphism_field()\n", "for i in M.irange():\n", " for j in M.irange():\n", " P[j,i] = E_U[i][j]" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "U.set_change_of_frame(stereoN.frame(), E_U, P)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The subset $U$ differs from $M$ only by a one dimensional slit, and is therefore dense in $M$. As we know that $\\left(\\varepsilon_{0},\\varepsilon_{1},\\varepsilon_{2},\\varepsilon_{3}\\right)$ defines a \\emph{global} frame, its components can be easily and uniquely extended to all of $M$. For this, we use the method add_comp_by_continuation:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [], "source": [ "for i in M.irange():\n", " E[i].add_comp_by_continuation(stereoS.frame(), W)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And again, we declare the change of frame:" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "P = V.automorphism_field()\n", "for i in M.irange():\n", " for j in M.irange():\n", " P[j,i] = E.restrict(V)[i][j]" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [], "source": [ "V.set_change_of_frame(stereoS.frame(), E.restrict(V), P)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to reduce the computation time, we examine the $\\hat{A}$-class on the open subset $U \\subset M$ first. The final result can be obtained by continuation. For this purpose we define the tangent bundle over $U$:" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tangent bundle TU over the Open subset U of the 4-dimensional Lorentzian manifold M\n" ] } ], "source": [ "TU = U.tangent_bundle(); print(TU)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the $\\hat{A}$-class is already predefined:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\hat{A}(TU)\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\hat{A}(TU)$$" ], "text/plain": [ "Characteristic class A^ of multiplicative type associated to 1/2*sqrt(x)/sinh(1/2*sqrt(x)) on the Tangent bundle TU over the Open subset U of the 4-dimensional Lorentzian manifold M" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = TU.characteristic_class('AHat'); A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Its holomorphic function is given by:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{\\sqrt{x}}{2 \\, \\sinh\\left(\\frac{1}{2} \\, \\sqrt{x}\\right)}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{\\sqrt{x}}{2 \\, \\sinh\\left(\\frac{1}{2} \\, \\sqrt{x}\\right)}$$" ], "text/plain": [ "1/2*sqrt(x)/sinh(1/2*sqrt(x))" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.function()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are ready to define the Berger metric, at least on the subset $U$:" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [], "source": [ "a = function('a')" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}g = -\\varepsilon^{0}\\otimes \\varepsilon^{0} + a\\left(t\\right)^{2} \\varepsilon^{1}\\otimes \\varepsilon^{1} +\\varepsilon^{2}\\otimes \\varepsilon^{2} +\\varepsilon^{3}\\otimes \\varepsilon^{3}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}g = -\\varepsilon^{0}\\otimes \\varepsilon^{0} + a\\left(t\\right)^{2} \\varepsilon^{1}\\otimes \\varepsilon^{1} +\\varepsilon^{2}\\otimes \\varepsilon^{2} +\\varepsilon^{3}\\otimes \\varepsilon^{3}$$" ], "text/plain": [ "g = -E^0⊗E^0 + a(t)^2 E^1⊗E^1 + E^2⊗E^2 + E^3⊗E^3" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g = U.metric()\n", "g.add_comp(E_U)[0, 0] = - 1\n", "g.add_comp(E_U)[1, 1] = a(t)^2\n", "g.add_comp(E_U)[2, 2] = 1\n", "g.add_comp(E_U)[3, 3] = 1\n", "g.display(E_U)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The corresponding connection is automatically computed by Sage:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [], "source": [ "nab = g.connection(); nab\n", "nab.set_immutable()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we perform the computation of the $\\hat{A}$-form with respect to this connection $\\nabla_g$:" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\hat{A}(TU, \\nabla_{g}) = 1 + \\left( \\frac{4 \\, {\\left(a\\left(t\\right)^{3} - a\\left(t\\right)\\right)} \\frac{\\partial\\,a}{\\partial t} - \\frac{\\partial\\,a}{\\partial t} \\frac{\\partial^2\\,a}{\\partial t ^ 2}}{24 \\, \\pi^{2}} \\right) \\varepsilon^{0}\\wedge \\varepsilon^{1}\\wedge \\varepsilon^{2}\\wedge \\varepsilon^{3}\$" ], "text/latex": [ "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\hat{A}(TU, \\nabla_{g}) = 1 + \\left( \\frac{4 \\, {\\left(a\\left(t\\right)^{3} - a\\left(t\\right)\\right)} \\frac{\\partial\\,a}{\\partial t} - \\frac{\\partial\\,a}{\\partial t} \\frac{\\partial^2\\,a}{\\partial t ^ 2}}{24 \\, \\pi^{2}} \\right) \\varepsilon^{0}\\wedge \\varepsilon^{1}\\wedge \\varepsilon^{2}\\wedge \\varepsilon^{3}$$" ], "text/plain": [ "A^(TU, nabla_g) = 1 + 1/24*(4*(a(t)^3 - a(t))*d(a)/dt - d(a)/dt*d^2(a)/dt^2)/pi^2 E^0∧E^1∧E^2∧E^3" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A_form = A.get_form(nab) # long time\n", "A_form.display_expansion(E_U, stereoN)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To attain $\\hat{A}(TM, \\nabla_g)$ in all given coordinates, we still have to extend the result onto $M$. With respect to the global frame $(\\varepsilon_0, \\varepsilon_1,\\varepsilon_2,\\varepsilon_3)$, the form $\\hat{A}(TU, \\nabla_g)$ only depends on the global coordinate $t$. This makes the continuation trivial. Besides, for the most part, one is interested in characteristic forms outside a set of measure zero. Hence, we terminate our calculation at this point." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.4.rc1", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.10" } }, "nbformat": 4, "nbformat_minor": 2 }