Skip to content

Commit

Permalink
Trac #30804: Add Spheres smoothly embedded in Euclidean Space to Mani…
Browse files Browse the repository at this point in the history
…fold Catalog

See #30189.

The current catalog only provides spheres of dimension two. A
comprehensive and faster version will be added here.

Features:

- spherical and stereographic coordinates
- orientation
- radius and barycenter can be stated
- link to minimal triangulation in `homology` module
- initialized embedding such that extrinsic quantities can be derived

Follow-Ups:

- make `S^1`, `S^3` and `S^7` parallelizable
- Hopf coordinates on `S^3`
- link to Lie group structure on `S^1` and `S^3`

URL: https://trac.sagemath.org/30804
Reported by: gh-mjungmath
Ticket author(s): Michael Jung
Reviewer(s): Eric Gourgoulhon, Travis Scrimshaw
  • Loading branch information
Release Manager committed Nov 22, 2020
2 parents 2cd4f82 + caa9d5f commit 96df693
Show file tree
Hide file tree
Showing 5 changed files with 1,252 additions and 135 deletions.
2 changes: 2 additions & 0 deletions src/doc/en/reference/manifolds/euclidean_space.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ Euclidean Spaces and Vector Calculus

sage/manifolds/differentiable/examples/euclidean

sage/manifolds/differentiable/examples/sphere

sage/manifolds/operators
3 changes: 3 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ REFERENCES:
.. [Ber1987] \M. Berger, *Geometry I*, Springer (Berlin) (1987);
:doi:`10.1007/978-3-540-93815-6`
.. [Ber1987a] \M. Berger, *Geometry II*, Springer (Berlin) (1987);
:doi:`10.1007/978-3-540-93816-3`
.. [Ber1991] \C. Berger, "Une version effective du théorème de
Hurewicz", https://tel.archives-ouvertes.fr/tel-00339314/en/.
Expand Down
137 changes: 2 additions & 135 deletions src/sage/manifolds/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- :class:`~sage.manifolds.differentiable.examples.euclidean.EuclideanSpace`: Euclidean space
- :class:`~sage.manifolds.differentiable.examples.real_line.RealLine`: real line
- :class:`~sage.manifolds.differentiable.examples.real_line.OpenInterval`: open interval on the real line
- :func:`Sphere`: sphere embedded in Euclidean space
- :class:`~sage.manifolds.differentiable.examples.sphere.Sphere`: sphere embedded in Euclidean space
- :func:`Torus`: torus embedded in Euclidean space
- :func:`Minkowski`: 4-dimensional Minkowski space
- :func:`Kerr`: Kerr spacetime
Expand All @@ -35,6 +35,7 @@
_lazy_import('sage.manifolds.differentiable.examples.real_line', 'OpenInterval')
_lazy_import('sage.manifolds.differentiable.examples.real_line', 'RealLine')
_lazy_import('sage.manifolds.differentiable.examples.euclidean', 'EuclideanSpace')
_lazy_import('sage.manifolds.differentiable.examples.sphere', 'Sphere')

def Minkowski(positive_spacelike=True, names=None):
"""
Expand Down Expand Up @@ -86,140 +87,6 @@ def Minkowski(positive_spacelike=True, names=None):
g[1,1], g[2,2], g[3,3] = sgn, sgn, sgn
return M

def Sphere(dim=None, radius=1, names=None, stereo2d=False, stereo_lim=None):
"""
Generate a sphere embedded in Euclidean space.
The shortcut operator ``.<,>`` can be used to specify the coordinates.
INPUT:
- ``dim`` -- (optional) the dimension of the sphere; if not specified,
equals to the number of coordinate names
- ``radius`` -- (default: ``1``) radius of the sphere
- ``names`` -- (default: ``None``) name of the coordinates,
automatically set by the shortcut operator
- ``stereo2d`` -- (default: ``False``) if ``True``, defines only the
stereographic charts, only implemented in 2d
- ``stereo_lim`` -- (default: ``None``) parameter used to restrict the
span of the stereographic charts, so that they don't cover the whole
sphere; valid domain will be ``x**2 + y**2 < stereo_lim**2``
OUTPUT:
- Riemannian manifold
EXAMPLES::
sage: S.<th, ph> = manifolds.Sphere()
sage: S
2-dimensional Riemannian submanifold S embedded in the Euclidean
space E^3
sage: S.atlas()
[Chart (S, (th, ph))]
sage: S.metric().display()
gamma = dth*dth + sin(th)^2 dph*dph
sage: S = manifolds.Sphere(2, stereo2d=True) # long time
sage: S # long time
2-dimensional Riemannian submanifold S embedded in the Euclidean
space E^3
sage: S.metric().display() # long time
gamma = 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dx*dx
+ 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dy*dy
"""
from sage.functions.trig import cos, sin, atan, atan2
from sage.functions.other import sqrt
from sage.symbolic.constants import pi
from sage.misc.misc_c import prod
from sage.manifolds.manifold import Manifold
from sage.manifolds.differentiable.examples.euclidean import EuclideanSpace

if dim is None:
if names is None:
raise ValueError("either the names or the dimension must be specified")
dim = len(names)
else:
if names is not None and dim != len(names):
raise ValueError("the number of coordinates does not match the dimension")

if stereo2d:
if dim != 2:
raise NotImplementedError("stereographic charts only "
"implemented for 2d spheres")
E = EuclideanSpace(3, names=("X", "Y", "Z"))
S2 = Manifold(dim, 'S', ambient=E, structure='Riemannian')
U = S2.open_subset('U')
V = S2.open_subset('V')
stereoN = U.chart(names=("x", "y"))
x, y = stereoN[:]
stereoS = V.chart(names=("xp", "yp"))
xp, yp = stereoS[:]
if stereo_lim is not None:
stereoN.add_restrictions(x**2+y**2 < stereo_lim**2)
stereoS.add_restrictions(xp**2+yp**2 < stereo_lim**2)

stereoN_to_S = stereoN.transition_map(stereoS,
(x / (x**2 + y**2), y / (x**2 + y**2)), intersection_name='W',
restrictions1=x**2 + y**2 != 0, restrictions2=xp**2+yp**2!=0)
stereoN_to_S.set_inverse(xp / (xp**2 + yp**2), yp / (xp**2 + yp**2),
check=False)
W = U.intersection(V)
stereoN_W = stereoN.restrict(W)
stereoS_W = stereoS.restrict(W)
A = W.open_subset('A', coord_def={stereoN_W: (y != 0, x < 0),
stereoS_W: (yp != 0, xp < 0)})
stereoN_A = stereoN_W.restrict(A)
if names is None:
names = tuple(["phi_{}:(0,pi)".format(i) for i in range(dim - 1)] +
["phi_{}:(-pi,pi):periodic".format(dim - 1)])
else:
names = tuple([names[i] + ":(0,pi)" for i in range(dim - 1)] +
[names[dim - 1] + ":(-pi,pi):periodic"])
spher = A.chart(names=names)
th, ph = spher[:]
spher_to_stereoN = spher.transition_map(stereoN_A, (sin(th)*cos(ph) / (1-cos(th)),
sin(th)*sin(ph) / (1-cos(th))))
spher_to_stereoN.set_inverse(2*atan(1/sqrt(x**2+y**2)), atan2(-y, -x)+pi,
check=False)
stereoN_to_S_A = stereoN_to_S.restrict(A)
stereoN_to_S_A * spher_to_stereoN # generates spher_to_stereoS
stereoS_to_N_A = stereoN_to_S.inverse().restrict(A)
spher_to_stereoN.inverse() * stereoS_to_N_A # generates stereoS_to_spher

coordfunc1 = [sin(th)*cos(ph), sin(th)*sin(ph), cos(th)]
coordfunc2 = [2*x/(1+x**2+y**2), 2*y/(1+x**2+y**2), (x**2+y**2-1)/(1+x**2+y**2)]
coordfunc3 = [2*xp/(1+xp**2+yp**2), 2*yp/(1+xp**2+yp**2),(1-xp**2-yp**2)/(1+xp**2+yp**2)]
imm = S2.diff_map(E, {(spher, E.default_chart()): coordfunc1,
(stereoN, E.default_chart()): coordfunc2,
(stereoS, E.default_chart()): coordfunc3})
S2.set_embedding(imm)
S2.induced_metric()

return S2

if dim != 2:
raise NotImplementedError("only implemented for 2 dimensional spheres")

E = EuclideanSpace(3, symbols='X Y Z')
M = Manifold(dim, 'S', ambient=E, structure='Riemannian')
if names is None:
names = tuple(["phi_{}:(0,pi)".format(i) for i in range(dim-1)] +
["phi_{}:(-pi,pi):periodic".format(dim-1)])
else:
names = tuple([names[i]+":(0,pi)"for i in range(dim - 1)] +
[names[dim-1]+":(-pi,pi):periodic"])
C = M.chart(names=names)
M._first_ngens = C._first_ngens
phi = M._first_ngens(dim)[:]
coordfunc = ([radius * prod(sin(phi[j]) for j in range(dim))] +
[radius * cos(phi[i]) * prod(sin(phi[j]) for j in range(i))
for i in range(dim)])
imm = M.diff_map(E, coordfunc)
M.set_embedding(imm)
M.induced_metric()
return M

def Kerr(m=1, a=0, coordinates="BL", names=None):
"""
Generate a Kerr spacetime.
Expand Down
69 changes: 69 additions & 0 deletions src/sage/manifolds/differentiable/examples/euclidean.py
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,75 @@ def dist(self, p, q):
d2 += dx*dx
return sqrt(d2)

def sphere(self, radius=1, center=None, name=None, latex_name=None,
coordinates='spherical', names=None):
r"""
Return an `(n-1)`-sphere smoothly embedded in ``self``.
INPUT:
- ``radius`` -- (default: ``1``) the radius greater than 1 of the sphere
- ``center`` -- (default: ``None``) point on ``self`` representing the
barycenter of the sphere
- ``name`` -- (default: ``None``) string; name (symbol) given to the
sphere; if ``None``, the name will be generated according to the input
- ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote
the sphere; if ``None``, the symbol will be generated according to
the input
- ``coordinates`` -- (default: ``'spherical'``) string describing the
type of coordinates to be initialized at the sphere's creation;
allowed values are
- ``'spherical'`` spherical coordinates (see
:meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.spherical_coordinates`))
- ``'stereographic'`` stereographic coordinates given by the
stereographic projection (see
:meth:`~sage.manifolds.differentiable.examples.sphere.Sphere.stereographic_coordinates`)
- ``names`` -- (default: ``None``) must be a tuple containing
the coordinate symbols (this guarantees the shortcut operator
``<,>`` to function); if ``None``, the usual conventions are used (see
examples in
:class:`~sage.manifolds.differentiable.examples.sphere.Sphere`
for details)
EXAMPLES:
Define a 2-sphere with radius 2 centered at `(1,2,3)` in Cartesian
coordinates::
sage: E3 = EuclideanSpace(3)
sage: c = E3.point((1,2,3), name='c'); c
Point c on the Euclidean space E^3
sage: S2_2 = E3.sphere(radius=2, center=c); S2_2
2-sphere S^2_2(c) of radius 2 smoothly embedded in the Euclidean
space E^3 centered at the Point c
The ambient space is precisely our previously defined Euclidean space::
sage: S2_2.ambient() is E3
True
The embedding into Euclidean space::
sage: S2_2.embedding().display()
iota: S^2_2(c) --> E^3
on A: (theta, phi) |--> (x, y, z) = (2*cos(phi)*sin(theta) + 1,
2*sin(phi)*sin(theta) + 2,
2*cos(theta) + 3)
See :class:`~sage.manifolds.differentiable.examples.sphere.Sphere`
for more examples.
"""
n = self._dim
if n == 1:
raise ValueError('Euclidean space must have dimension of at least 2')
from .sphere import Sphere
return Sphere(n-1, radius=radius, ambient_space=self,
center=center, name=name, latex_name=latex_name,
coordinates=coordinates, names=names)

###############################################################################

class EuclideanPlane(EuclideanSpace):
Expand Down
Loading

0 comments on commit 96df693

Please sign in to comment.