Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 6830d30

Browse files
author
Michael Jung
committed
Trac #27784: Merge trac #28716 into trac #27784
2 parents a331374 + 81e2f60 commit 6830d30

File tree

6 files changed

+313
-75
lines changed

6 files changed

+313
-75
lines changed

src/sage/manifolds/differentiable/manifold.py

Lines changed: 119 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,28 +2786,33 @@ def set_change_of_frame(self, frame1, frame2, change_of_frame,
27862786
for sdom in self._supersets:
27872787
sdom._frame_changes[(frame2, frame1)] = change_of_frame.inverse()
27882788

2789-
def vector_frame(self, symbol=None, latex_symbol=None, dest_map=None,
2790-
from_frame=None, indices=None, latex_indices=None,
2791-
symbol_dual=None, latex_symbol_dual=None):
2789+
def vector_frame(self, *args, **kwargs):
27922790
r"""
27932791
Define a vector frame on ``self``.
27942792
27952793
A *vector frame* is a field on the manifold that provides, at each
27962794
point `p` of the manifold, a vector basis of the tangent space at `p`
27972795
(or at `\Phi(p)` when ``dest_map`` is not ``None``, see below).
27982796
2797+
The vector frame can be defined from a set of `n` linearly independent
2798+
vector fields, `n` being the dimension of ``self``.
2799+
27992800
.. SEEALSO::
28002801
28012802
:class:`~sage.manifolds.differentiable.vectorframe.VectorFrame`
28022803
for complete documentation.
28032804
28042805
INPUT:
28052806
2806-
- ``symbol`` -- (default: ``None``) either a string, to be used as a
2807+
- ``symbol`` -- either a string, to be used as a
28072808
common base for the symbols of the vector fields constituting the
28082809
vector frame, or a list/tuple of strings, representing the individual
2809-
symbols of the vector fields; can be ``None`` only if ``from_frame``
2810+
symbols of the vector fields; can be omitted only if ``from_frame``
28102811
is not ``None`` (see below)
2812+
- ``vector_fields`` -- tuple or list of `n` linearly independent vector
2813+
fields on the manifold ``self`` (`n` being the dimension of ``self``)
2814+
defining the vector frame; can be omitted if the vector frame is
2815+
created from scratch or if ``from_frame`` is not ``None``
28112816
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
28122817
as a common base for the LaTeX symbols of the vector fields
28132818
constituting the vector frame, or a list/tuple of strings,
@@ -2818,8 +2823,8 @@ def vector_frame(self, symbol=None, latex_symbol=None, dest_map=None,
28182823
destination map `\Phi:\ U \rightarrow M`, where `U` is ``self`` and
28192824
`M` is a differentiable manifold; for each `p\in U`, the vector
28202825
frame evaluated at `p` is a basis of the tangent space
2821-
`T_{\Phi(p)}M`; if ``dest_map`` is ``None``, the identity is assumed
2822-
(case of a vector frame *on* `U`)
2826+
`T_{\Phi(p)}M`; if ``dest_map`` is ``None``, the identity map is
2827+
assumed (case of a vector frame *on* `U`)
28232828
- ``from_frame`` -- (default: ``None``) vector frame `\tilde{e}`
28242829
on the codomain `M` of the destination map `\Phi`; the returned
28252830
frame `e` is then such that for all `p \in U`,
@@ -2845,14 +2850,72 @@ def vector_frame(self, symbol=None, latex_symbol=None, dest_map=None,
28452850
28462851
EXAMPLES:
28472852
2848-
Setting a vector frame on a 3-dimensional manifold::
2853+
Defining a vector frame from two linearly independent vector
2854+
fields on a 2-dimensional manifold::
28492855
2850-
sage: M = Manifold(3, 'M')
2851-
sage: X.<x,y,z> = M.chart()
2852-
sage: e = M.vector_frame('e'); e
2853-
Vector frame (M, (e_0,e_1,e_2))
2854-
sage: e[0]
2855-
Vector field e_0 on the 3-dimensional differentiable manifold M
2856+
sage: M = Manifold(2, 'M')
2857+
sage: X.<x,y> = M.chart()
2858+
sage: e0 = M.vector_field(1+x^2, 1+y^2)
2859+
sage: e1 = M.vector_field(2, -x*y)
2860+
sage: e = M.vector_frame('e', (e0, e1)); e
2861+
Vector frame (M, (e_0,e_1))
2862+
sage: e[0].display()
2863+
e_0 = (x^2 + 1) d/dx + (y^2 + 1) d/dy
2864+
sage: e[1].display()
2865+
e_1 = 2 d/dx - x*y d/dy
2866+
sage: (e[0], e[1]) == (e0, e1)
2867+
True
2868+
2869+
If the vector fields are not linearly independent, an error is
2870+
raised::
2871+
2872+
sage: z = M.vector_frame('z', (e0, -e0))
2873+
Traceback (most recent call last):
2874+
...
2875+
ValueError: the provided vector fields are not linearly
2876+
independent
2877+
2878+
Another example, involving a pair vector fields along a curve::
2879+
2880+
sage: R.<t> = RealLine()
2881+
sage: c = M.curve([sin(t), sin(2*t)/2], (t, 0, 2*pi), name='c')
2882+
sage: I = c.domain(); I
2883+
Real interval (0, 2*pi)
2884+
sage: v = c.tangent_vector_field()
2885+
sage: v.display()
2886+
c' = cos(t) d/dx + (2*cos(t)^2 - 1) d/dy
2887+
sage: w = I.vector_field(1-2*cos(t)^2, cos(t), dest_map=c)
2888+
sage: u = I.vector_frame('u', (v, w))
2889+
sage: u[0].display()
2890+
u_0 = cos(t) d/dx + (2*cos(t)^2 - 1) d/dy
2891+
sage: u[1].display()
2892+
u_1 = (-2*cos(t)^2 + 1) d/dx + cos(t) d/dy
2893+
sage: (u[0], u[1]) == (v, w)
2894+
True
2895+
2896+
It is also possible to create a vector frame from scratch, without
2897+
connecting it to previously defined vector frames or vector fields
2898+
(this can still be performed later via the method
2899+
:meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.set_change_of_frame`)::
2900+
2901+
sage: f = M.vector_frame('f'); f
2902+
Vector frame (M, (f_0,f_1))
2903+
sage: f[0]
2904+
Vector field f_0 on the 2-dimensional differentiable manifold M
2905+
2906+
Thanks to the keywords ``dest_map`` and ``from_frame``, one can also
2907+
define a vector frame from one prexisting on another manifold, via a
2908+
differentiable map (here provided by the curve ``c``)::
2909+
2910+
sage: fc = I.vector_frame(dest_map=c, from_frame=f); fc
2911+
Vector frame ((0, 2*pi), (f_0,f_1)) with values on the
2912+
2-dimensional differentiable manifold M
2913+
sage: fc[0]
2914+
Vector field f_0 along the Real interval (0, 2*pi) with values on
2915+
the 2-dimensional differentiable manifold M
2916+
2917+
Note that the symbol for ``fc``, namely `f`, is inherited from ``f``,
2918+
the original vector frame.
28562919
28572920
.. SEEALSO::
28582921
@@ -2862,12 +2925,53 @@ def vector_frame(self, symbol=None, latex_symbol=None, dest_map=None,
28622925
28632926
"""
28642927
from sage.manifolds.differentiable.vectorframe import VectorFrame
2865-
return VectorFrame(self.vector_field_module(dest_map=dest_map,
2928+
# Input processing
2929+
symbol = None
2930+
vector_fields = None
2931+
n_args = len(args)
2932+
if n_args >= 1:
2933+
symbol = args[0]
2934+
if n_args == 2:
2935+
vector_fields = args[1]
2936+
elif n_args > 2:
2937+
raise TypeError("vector_frame() takes at most two positional "
2938+
"arguments")
2939+
latex_symbol = kwargs.pop('latex_symbol', None)
2940+
dest_map = kwargs.pop('dest_map', None)
2941+
from_frame = kwargs.pop('from_frame', None)
2942+
indices = kwargs.pop('indices', None)
2943+
latex_indices = kwargs.pop('latex_indices', None)
2944+
symbol_dual = kwargs.pop('symbol_dual', None)
2945+
latex_symbol_dual = kwargs.pop('latex_symbol_dual', None)
2946+
#
2947+
if vector_fields:
2948+
dest_map0 = vector_fields[0].parent().destination_map()
2949+
if dest_map and dest_map is not dest_map0:
2950+
raise ValueError("incompatible values of destination maps")
2951+
dest_map = dest_map0
2952+
resu = VectorFrame(self.vector_field_module(dest_map=dest_map,
28662953
force_free=True),
28672954
symbol=symbol, latex_symbol=latex_symbol,
28682955
from_frame=from_frame, indices=indices,
28692956
latex_indices=latex_indices, symbol_dual=symbol_dual,
28702957
latex_symbol_dual=latex_symbol_dual)
2958+
if vector_fields:
2959+
linked = False
2960+
try:
2961+
resu._init_from_family(vector_fields)
2962+
except ArithmeticError as err:
2963+
linked = str(err) in ["non-invertible matrix",
2964+
"input matrix must be nonsingular"]
2965+
if linked:
2966+
raise ValueError("the provided vector fields are not "
2967+
"linearly independent")
2968+
# Adding the newly generated changes of frame to the
2969+
# dictionary _frame_changes of self and its supersets:
2970+
for frame_pair, chge in resu._fmodule._basis_changes.items():
2971+
if resu in frame_pair:
2972+
for sdom in self._supersets:
2973+
sdom._frame_changes[frame_pair] = chge
2974+
return resu
28712975

28722976
def _set_covering_frame(self, frame):
28732977
r"""

src/sage/manifolds/differentiable/vector_bundle.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,9 +1309,7 @@ def is_manifestly_trivial(self):
13091309
return True
13101310
return False
13111311

1312-
def local_frame(self, symbol=None, latex_symbol=None, from_frame=None,
1313-
indices=None, latex_indices=None, symbol_dual=None,
1314-
latex_symbol_dual=None, domain=None):
1312+
def local_frame(self, *args, **kwargs):
13151313
r"""
13161314
Define a vector frame on ``domain``, possibly with values in the
13171315
tangent bundle of the ambient domain.
@@ -1354,6 +1352,10 @@ def local_frame(self, symbol=None, latex_symbol=None, from_frame=None,
13541352
vector frame, or a list/tuple of strings, representing the individual
13551353
symbols of the vector fields; can be ``None`` only if ``from_frame``
13561354
is not ``None`` (see below)
1355+
- ``vector_fields`` -- tuple or list of `n` linearly independent vector
1356+
fields on ``domain`` (`n` being the dimension of ``domain``)
1357+
defining the vector frame; can be omitted if the vector frame is
1358+
created from scratch or if ``from_frame`` is not ``None``
13571359
- ``latex_symbol`` -- (default: ``None``) either a string, to be used
13581360
as a common base for the LaTeX symbols of the vector fields
13591361
constituting the vector frame, or a list/tuple of strings,
@@ -1414,16 +1416,17 @@ def local_frame(self, symbol=None, latex_symbol=None, from_frame=None,
14141416
:class:`~sage.manifolds.differentiable.vectorframe.VectorFrame`.
14151417
14161418
"""
1419+
domain = kwargs.pop('domain', None)
14171420
if domain is None:
14181421
domain = self._base_space
1419-
vmodule = domain.vector_field_module(
1420-
dest_map=self._dest_map.restrict(domain),
1421-
force_free=True)
1422-
return vmodule.basis(symbol=symbol, latex_symbol=latex_symbol,
1423-
from_frame=from_frame,
1424-
indices=indices, latex_indices=latex_indices,
1425-
symbol_dual=symbol_dual,
1426-
latex_symbol_dual=latex_symbol_dual)
1422+
dest_map = self._dest_map.restrict(domain)
1423+
if not args and not kwargs:
1424+
# if no argument is provided, the default basis of the
1425+
# base vector field module is returned:
1426+
return domain.vector_field_module(dest_map=dest_map,
1427+
force_free=True).basis()
1428+
kwargs['dest_map'] = dest_map
1429+
return domain.vector_frame(*args, **kwargs)
14271430

14281431
vector_frame = local_frame
14291432

@@ -1568,4 +1571,4 @@ def set_default_frame(self, frame):
15681571
self._base_space.set_default_frame(frame)
15691572
else:
15701573
frame._fmodule.set_default_basis(frame)
1571-
self._def_frame = frame
1574+
self._def_frame = frame

src/sage/manifolds/differentiable/vectorframe.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,29 @@
3434
3535
EXAMPLES:
3636
37-
Defining a vector frame on a 3-dimensional manifold::
37+
Introducing a chart on a manifold automatically endows it with a vector frame:
38+
the coordinate frame associated to the chart::
3839
3940
sage: M = Manifold(3, 'M')
4041
sage: X.<x,y,z> = M.chart()
41-
sage: e = M.vector_frame('e') ; e
42+
sage: M.frames()
43+
[Coordinate frame (M, (d/dx,d/dy,d/dz))]
44+
sage: M.frames()[0] is X.frame()
45+
True
46+
47+
A new vector frame can be defined from a family of 3 linearly independent
48+
vector fields::
49+
50+
sage: e1 = M.vector_field(1, x, y)
51+
sage: e2 = M.vector_field(z, -2, x*y)
52+
sage: e3 = M.vector_field(1, 1, 0)
53+
sage: e = M.vector_frame('e', (e1, e2, e3)); e
4254
Vector frame (M, (e_0,e_1,e_2))
4355
sage: latex(e)
4456
\left(M, \left(e_{0},e_{1},e_{2}\right)\right)
4557
46-
The first frame defined on a manifold is its default frame; in the present
47-
case it is the coordinate frame defined when introducing the chart
48-
``X``::
58+
The first frame defined on a manifold is its *default frame*; in the present
59+
case it is the coordinate frame associated to the chart ``X``::
4960
5061
sage: M.default_frame()
5162
Coordinate frame (M, (d/dx,d/dy,d/dz))
@@ -70,6 +81,13 @@
7081
7182
sage: e[0]
7283
Vector field e_0 on the 3-dimensional differentiable manifold M
84+
sage: e[0].display(X.frame())
85+
e_0 = d/dx + x d/dy + y d/dz
86+
sage: X.frame()[1]
87+
Vector field d/dy on the 3-dimensional differentiable manifold M
88+
sage: X.frame()[1].display(e)
89+
d/dy = x/(x^2 - x + z + 2) e_0 - 1/(x^2 - x + z + 2) e_1
90+
- (x - z)/(x^2 - x + z + 2) e_2
7391
7492
The slice operator ``:`` can be used to access to more than one element::
7593
@@ -81,6 +99,18 @@
8199
Vector field e_1 on the 3-dimensional differentiable manifold M,
82100
Vector field e_2 on the 3-dimensional differentiable manifold M)
83101
102+
Vector frames can be constructed from scratch, without any connection to
103+
previously defined frames or vector fields (the connection can be performed
104+
later via the method
105+
:meth:`~sage.manifolds.differentiable.manifold.DifferentiableManifold.set_change_of_frame`)::
106+
107+
sage: f = M.vector_frame('f'); f
108+
Vector frame (M, (f_0,f_1,f_2))
109+
sage: M.frames()
110+
[Coordinate frame (M, (d/dx,d/dy,d/dz)),
111+
Vector frame (M, (e_0,e_1,e_2)),
112+
Vector frame (M, (f_0,f_1,f_2))]
113+
84114
The index range depends on the starting index defined on the manifold::
85115
86116
sage: M = Manifold(3, 'M', start_index=1)
@@ -152,14 +182,12 @@
152182
153183
The orthonormal frame constructed from the coordinate frame::
154184
155-
sage: change_frame = M.automorphism_field()
156-
sage: change_frame[:] = [[1,0], [0, 1/sin(th)]]
157-
sage: e = b.new_frame(change_frame, 'e') ; e
185+
sage: e = M.vector_frame('e', (b[1], b[2]/sin(th))); e
158186
Vector frame (S^2, (e_1,e_2))
159-
sage: e[1][:]
160-
[1, 0]
161-
sage: e[2][:]
162-
[0, 1/sin(th)]
187+
sage: e[1].display()
188+
e_1 = d/dth
189+
sage: e[2].display()
190+
e_2 = 1/sin(th) d/dph
163191
164192
The change-of-frame automorphisms and their matrices::
165193

0 commit comments

Comments
 (0)