#!/usr/bin/env python # coding: utf-8 # # Sage多様体演習 Sage manifold tutorial # # このワークシートはSageMathにおける微分可能多様体の取り扱いについての簡単な紹介です。以下で紹介するツールは[SageManifolds](https://sagemanifolds.obspm.fr/) プロジェクト (version 1.2, included in SageMath 8.2).を通じて実装されました。 # ipnyb形式のワークシートファイルは[ここ](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Notebooks/SM_tutorial.ipynb) からダウンロード可能です。このワークシートを実行するには、コマンド`sage -n jupyter`などを使ってSageMathのJupyterノートブックインタフェースを起動する必要があります。 # # [訳注:この日本語版翻訳は山本 昇によって作成されました。翻訳者へのご連絡は、https://souran.kek.jp/kss/top/ を経由して、 職員情報詳細ページ内の「メール送信」リンクをご利用ください。この翻訳版作成にあたり、東海大学理学部北林さんには貴重なコメントをいただきました。この場を借りてお礼申しあげます。 # (2023/05/02追記:原文の更新を反映しました。)] # # This notebook provides a short introduction to differentiable manifolds in SageMath. The tools described # below have been implemented through the [SageManifolds](https://sagemanifolds.obspm.fr/) project. # # Click [here](https://raw.githubusercontent.com/sagemanifolds/SageManifolds/master/Notebooks/SM_tutorial.ipynb) to download the worksheet file (ipynb format). To run it, you must start SageMath with the Jupyter notebook, via the command `sage -n jupyter` # # [Note for Japanese version.: this document was translated into Japanese by Noboru Yamamoto. You can reach him through https://souran.kek.jp/kss/top/. "Staff Detail Information" page includes a link "send email". The translator thanks Prof. Kitabayashi of Tokai University for his valuable comments on the draft of the documents.] # このワークシートはSageMathのバージョン 9.2 (あるいはそれ以降)を必要としています、それ以前のバージョンではSageManifoldsの全ての機能が利用可能というわけではないからです。 [訳注:このjupyter notebookはSageMath 9.8 を使って実行しています。] # # This notebook is valid for version 9.2 or higher of SageMath: # In[1]: version() # 最初に、ノートブックが結果をLaTexを使った数式表示で表示するようにします。 # # First we set up the notebook to display mathematical objects using LaTeX rendering: # In[2]: get_ipython().run_line_magic('display', 'latex') # ## 多様体の定義 Defining a manifold # # 例として、 $\mathbb{R}$上の3次元の微分可能多様体を定義します。 # # As an example let us define a differentiable manifold of dimension 3 over $\mathbb{R}$: # In[3]: M = Manifold(3, 'M', latex_name=r'\mathcal{M}', start_index=1) # - 最初の引数、`3`, は多様体の次元です。SageManifoldsでは任意の正の整数を指定できます。 # - 2番目の引数, `'M'`, は多様体の名前を与える文字列です。この名前は = 記号の左辺にあるシンボルの名前(ここでは`M`)と # 異なっていても構いません。左辺のシンボル名はコンピュータメモリのなかの多様体オブジェクトを参照しています。一方、 # 引数であたえる名前は、多様体に与えられた数学的な名前です。 # - 省略可能な引数, `latex_name=r'\mathcal{M}'`, はこの多様体をLaTeXで表示する際に使う名前を指定します。 # 最初の引用符の前の 'r' に注意してください。:これはこの文字列が *raw* 文字列であることを示しています。 # それによって文字列`\mathcal`中のバックスラッシュ '\\' は通常の文字として取り扱われます( '\\\\' としてエスケープする必要がないということです)。 # この引数(`latex_name`)が省略された場合は、第2引数に与えられた名前(ここでは`M`です)が使われます。 # - 次の省略可能な引数`start_index=1`は多様体のテンソル成分の指標の範囲を指定しています。これを1とすることは指標の範囲が$\{1,2,3\}$であることを示しています。この引数の既定値は `start_index=0` です。 # # - The first argument, `3`, is the manifold dimension. In SageManifolds, it can be any # positive integer. # - The second argument, `'M'`, is a string defining the manifold's name; it may be # different from the symbol set on the left-hand side of the = sign (here `M`): the latter # stands for a mere Python variable, which refers to the manifold object in the computer # memory, while the string `'M'` is the mathematical symbol chosen for the manifold. # - The optional argument `latex_name=r'\mathcal{M}'` sets the LaTeX # symbol to display the manifold. Note the letter 'r' in front on the first quote: # it indicates that the string is a *raw* one, so that the backslash character # in `\mathcal` is considered as an ordinary character (otherwise, the backslash is # used to escape some special characters). If the argument `latex_name` is not # provided by the user, it is set to the string used as the second argument (here `'M'`) # - The optional argument `start_index=1` defines the range of indices to be used for # tensor components on the manifold: setting it to 1 means that indices will range # in $\{1,2,3\}$. The default value is `start_index=0`. # # 規定のベースフィールド(基底)は$\mathbb{R}$であることに注意してください。もし、 # `field='complex'`,が与えられていれば、複素数体$\mathbb{C}$を基底として持つ # 多様体が定義されます。[[list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/manifold.html#sage.manifolds.manifold.Manifold) を参照のこと] # # Note that the default base field is $\mathbb{R}$. If we would have used the optional # argument `field='complex'`, we would have defined a manifold over $\mathbb{C}$. See the # [list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/manifold.html#sage.manifolds.manifold.Manifold) for more details. # # Mを要求すると、そのLaTexのシンボルとして表示されます。 # # If we ask for M, it is displayed via its LaTeX symbol: # In[4]: M # 代わりに `print` 関数を使うと、簡潔な記述が表示されます。 # # If we use the `print` function instead, we get a short description of the object: # In[5]: print(M) # `type` コマンドを使うと、`M`に対応するPythonオブジェクトのタイプ(`DifferentiableManifold_with_category`)が表示できます。 # #

Via the command type, we get the type of the Python object corresponding to M (here the Python class DifferentiableManifold_with_category):

# In[6]: print(type(M)) # category()関数を使って、多様体`M`のカテゴリーを調べます。この例では、この多様体の # カテゴリーは$\mathbb{R}$の上の滑らかな多様体であることがわかります。 # # We can also ask for the category of M and see that it is the category of smooth manifolds over $\mathbb{R}$: # In[7]: category(M) # 多様体の指標(を表すgeneator)は `irange()` メソッドで生成されます。この指標はfor-ループなどで使われます。 # #

The indices on the manifold are generated by the method irange(), to be used in loops:

# In[8]: [i for i in M.irange()] # `start_index` パラメータが明示的に指定されていない場合、多様体の指標は 0 からはじまります、例えばこの例のように(0,1,2) の範囲となります。 # #

If the parameter start_index had not been specified, the default range of the indices would have been $\{0,1,2\}$ instead:

# In[9]: M0 = Manifold(3, 'M', r'\mathcal{M}') [i for i in M0.irange()] # ## 多様体上の座標系(chart)の定義:Defining a chart on the manifold # まずは、多様体 $\mathcal{M}$ は一つの座標系で覆われると仮定します(そうでない場合は以下で議論されます)。 # 座標系は次のように宣言されます。 #

Let us assume that the manifold $\mathcal{M}$ can be covered by a single chart (other cases are discussed below); the chart is declared as follows:

# In[10]: X. = M.chart() # 上式の左辺にある`.` は Pythonの変数 `x`, `y` and `z`が座標系の軸名として使われることを意味します。 # これにより、座標軸を名前で指定することが可能になります。 # # The writing `.` in the left-hand side means that the Python variables `x`, `y` and `z` are set to the three coordinates of the chart. This allows one to refer subsequently to the coordinates by their names. # # この例では、関数 `chart()` は引数をもっていません。この場合には、座標の名前は、`x`, `y` と `z` (即ち、左辺の `<...>` 演算子で与えられた名前)になります。また座標の範囲は $(-\infty,+\infty)$ となります。それ以外の座標の名前やその範囲を指定する場合には `chart()` にそれらを引数として与えなければなりません。座標名と異なる LaTex で使われる名前を指定する場合も同様です。(以下にそのような例が示されます。) # # In this example, the function `chart()` has no arguments, which implies that the coordinate symbols will be `x`, `y` and `z` (i.e. exactly the characters set in the `<...>` operator) and that each coordinate range is $(-\infty,+\infty)$. For other cases, an argument must be passed to `chart()`  to specify the coordinate symbols and range, as well as the LaTeX symbol of a coordinate if the latter is different from the coordinate name (an example will be provided below). # 座標系は座標系が覆う開集合(ここでは多様体自身)と座標の組で表示されます。 #

The chart is displayed as a pair formed by the open set covered by it (here the whole manifold) and the coordinates:

# In[11]: print(X) # In[12]: X # それぞれの座標値は指標を使って入手できます。指標の指定方法は多様体の定義時の設定(`start_index=1`)に従います。 # #

The coordinates can be accessed individually, by means of their indices, following the convention defined by start_index=1 in the manifold's definition:

# In[13]: X[1] # In[14]: X[2] # In[15]: X[3] # 座標の全体は`[:]` 演算子を使って取得します。 #

The full set of coordinates is obtained by means of the operator [:]:

# In[16]: X[:] # 座標系定義で使った `` 演算子のおかげで、それぞれの座標をこの名前を使って直接取り扱えます。 # # Thanks to the operator `` used in the chart declaration, each coordinate can be accessed directly via its name: # In[17]: z is X[3] # 座標は SageMath の記号表現になっています。 # # Coordinates are SageMath symbolic expressions: # In[18]: print(type(z)) # ### 座標の関数 : Functions of the chart coordinates # # 実数値をもつ座標の関数 (数学的にいえば、**座標の終域で定義された関数**) は チャートの`function()` メソッドを使って生成されます。 # #

Real-valued functions of the chart coordinates (mathematically speaking, functions defined on the chart codomain) are generated via the method function() acting on the chart:

# In[19]: f = X.function(x+y^2+z^3) f # In[20]: f.display() # In[21]: f(1,2,3) # これらの関数は、SageManiforldsのクラス `ChartFunction` (実際には、そのサブクラス`𝙲𝚑𝚊𝚛𝚝𝙵𝚞𝚗𝚌𝚝𝚒𝚘𝚗𝚁𝚒𝚗𝚐_𝚠𝚒𝚝h_𝚌𝚊𝚝𝚎𝚐𝚘𝚛𝚢.𝚎𝚕𝚎𝚖𝚎𝚗t_𝚌𝚕𝚊𝚜𝚜`)に属しています。 # # They belong to the class `ChartFunction` (actually the subclass `𝙲𝚑𝚊𝚛𝚝𝙵𝚞𝚗𝚌𝚝𝚒𝚘𝚗𝚁𝚒𝚗𝚐_𝚠𝚒𝚝h_𝚌𝚊𝚝𝚎𝚐𝚘𝚛𝚢.𝚎𝚕𝚎𝚖𝚎𝚗t_𝚌𝚕𝚊𝚜𝚜`): # In[22]: print(type(f)) # そしてこの`ChartFunction`クラスに属する関数は、標準的な SageMath の記号的関数とは全ての演算で自動的簡約化の振る舞いが異なっています。例えば、二つの記号的関数の和: # #

and differ from SageMath standard symbolic functions by automatic simplifications in all operations. For instance, adding the two symbolic functions

# In[23]: f0(x,y,z) = cos(x)^2 ; g0(x,y,z) = sin(x)^2 # は、次の結果になります。 # #

results in

# In[24]: f0 + g0 # 一方、`ChartFunction` クラスに属する関数は自動的に簡約化されます。 # #

while the sum of the corresponding functions in the class ChartFunction is automatically simplified:

# In[25]: f1 = X.function(cos(x)^2) ; g1 = X.function(sin(x)^2) f1 + g1 # 同じ結果を記号的関数でも得るためには、`simplify_trig()` メソッドを使います。 # #

To get the same output with symbolic functions, one has to invoke the method simplify_trig():

# In[26]: (f0 + g0).simplify_trig() # 違いは表示方法にもあります。記号関数 `f0` を表示させると、 # #

Another difference regards the display; if we ask for the symbolic function f0, we get:

# In[27]: f0 # となりますが、座標関数 `f1` を表示させると、座標表示だけが表示されます。 # #

while if we ask for the chart function f1, we get only the coordinate expression:

# In[28]: f1 # `f0` の場合と同じような表示を望む場合には、 `display()` メソッドを使います。 # #

To get an output similar to that of f0, one should call the method display():

# In[29]: f1.display() # `expr()`メソッドは基になる記号表現を返すことを覚えておいてください。 # Note that the method `expr()` returns the underlying symbolic expression: # In[30]: f1.expr() # In[31]: print(type(f1.expr())) # ### 多様体への二つ目の座標系の導入:Introducing a second chart on the manifold # # まず、多様体$\mathcal{M}$の部分集合を考えましょう。たとえば、$\{y=0, x\geq 0\}$ で定義される領域の補集合 $U$ です( # `(y!=0, x<0)` は $y\not=0$ OR $x<0$を意味していることに注意。$y\not=0$ AND $x<0$ は`[y!=0, x<0]`となる。)。 # # Let us first consider an open subset of $\mathcal{M}$, for instance the complement $U$ of the region defined by $\{y=0, x\geq 0\}$ (note that `(y!=0, x<0)` stands for $y\not=0$ OR $x<0$; the condition $y\not=0$ AND $x<0$ would have been written `[y!=0, x<0]` instead): # In[32]: U = M.open_subset('U', coord_def={X: (y!=0, x<0)}) # 開部分集合$U$に制限された座標系 `X` を `X_U`と呼ぶことにします。 # # Let us call `X_U` the restriction of the chart `X` to the open subset $U$: # In[33]: X_U = X.restrict(U) X_U # $U$上の別の座標系、 $(r,\theta,\phi)$、を 導入します。 # #

We introduce another chart on $U$, with spherical-type coordinates $(r,\theta,\phi)$:

# In[34]: Y. = U.chart(r'r:(0,+oo) th:(0,pi):\theta ph:(0,2*pi):\phi') Y # ここでは関数 `chart()` は引数を持っています。それはraw文字列でLaTexのシンボルを含んでいます。また、この文字列には座標の(既定値の$(-\infty, +\infty)$とは異なる)範囲指定が含まれています。フィールドは`:`で区切られており、座標は空白文字で区切られています。 座標$r$については、LaTexシンボルを指定していないので、下限と上限の二つだけが指定されています。LaTexシンボルは出力の際に使われます。 # #

The function chart() has now some argument; it is a string, which contains specific LaTeX symbols, hence the prefix 'r' to it (for raw string). It also contains the coordinate ranges, since they are different from the default value, which is $(-\infty, +\infty)$. For a given coordinate, the various fields are separated by the character ':' and a space character separates the coordinates. Note that for the coordinate $r$, there are only two fields, since the LaTeX symbol has not to be specified. The LaTeX symbols are used for the outputs:

# In[35]: th, ph # In[36]: Y[2], Y[3] # Sageが使っている座標の条件は、`assumptions()`メソッドを使って確認することができます。 # #

The declared coordinate ranges are now known to Sage, as we may check by means of the command assumptions():

# In[37]: assumptions() # これらの条件は、表現の簡約化の際に使われます。 # #

They are used in simplifications:

# In[38]: simplify(abs(r)) # $r >0$ と仮定されているので、$\mathrm{abs}(r)$ は $r$ に簡約されます。 # In[39]: simplify(abs(x)) # no simplification occurs since x can take any value in R # $x$ は$R$の負の値を含むどんな値でも取ることができますから、$\mathrm{abs}(x)$ は簡約できません。 # 座標 $Y$が宣言されたあとで、さらに 遷移写像を指定することで、$Y$の$X_U$への関係を完全に特定することができます。 #

After having been declared, the chart Y can be fully specified by its relation to the chart X_U, via a transition map:

# In[40]: transit_Y_to_X = Y.transition_map(X_U, [r*sin(th)*cos(ph), r*sin(th)*sin(ph), r*cos(th)]) transit_Y_to_X # In[41]: transit_Y_to_X.display() # `set_inverse()` メソッドを用いることで、遷移写像の逆写像を指定することができます。 # #

The inverse of the transition map can be specified by means of the method set_inverse():

# In[42]: transit_Y_to_X.set_inverse(sqrt(x^2+y^2+z^2), atan2(sqrt(x^2+y^2),z), atan2(y, x)) # 導かれた逆写像は、それと元の写像を組み合わせることで検証できます。 # 左辺と右辺がそれぞれに対応しています。 # 上の結果が示しているように、thとphの検証が失敗したと報告されているのは、 # arctan2が関係する表式の単純化が不十分であることに起因しています。 # # A check of the provided inverse is performed by composing # it with the original transition map, on the left and # on the right respectively. As indicated, the reported failure for th and ph is actually due to a lack of # simplification of expressions involving arctan2 . # We have then # In[43]: transit_Y_to_X.inverse().display() # この段階で、多様体のアトラス( `user atlas`であって最大アトラスではありません)は三つの座標系を含んでいます。 # #

At this stage, the manifold's atlas (the "user atlas", not the maximal atlas!) contains three charts:

# In[44]: M.atlas() # 多様体に最初に定義された座標系は既定の座標系とみなされます。既定座標系はあとで、`set_default_chart()`メソッドを使って変更できます。 # #

The first chart defined on the manifold is considered as the manifold's default chart (it can be changed by the method set_default_chart()):

# In[45]: M.default_chart() # 各々の開部分空間は各自のアトラスを持っています。開部分空間はそれ自身でも多様体であるからです。 #

Each open subset has its own atlas (since an open subset of a manifold is a manifold by itself):

# In[46]: U.atlas() # In[47]: U.default_chart() # In[48]: Y.plot(X,color={r:'red', th:'green', ph:'blue'}) # `Y.plot(X)` コマンドを使って、座標系$Y$を座標系$X$を使って表示することができます。このコマンドは、座標系$Y$で一定の座標値を持つ線を、座標系$X$に基づく"直交フレーム"中に表示します。 # # We can draw the chart $Y$ in terms of the chart $X$ via the command `Y.plot(X)`, which shows the lines of constant coordinates from the $Y$ chart in a "Cartesian frame" based on the $X$ coordinates: # In[49]: Y.plot(X, color={r:'blue', th:'green', ph:'red'}, aspect_ratio=1) # コマンド`plot()`は多くのオプションを持っています。オプションを使い、描画される座標線の数、スタイル、色、そして座標の範囲などを指定します。 # (参照:[list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/chart.html#sage.manifolds.chart.RealChart.plot)): # # The command plot() allows for many options, to control the number of coordinate lines to be drawn, their style and color, as well as the coordinate ranges (cf. the [list of all options](http://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/chart.html#sage.manifolds.chart.RealChart.plot)): # In[50]: Y.plot(X, ranges={r:(1,2), th:(0,pi/2)}, number_values=4, color={r:'blue', th:'green', ph:'red'}, aspect_ratio=1) # 逆に、(制限された)座標系 $X|_{U}$ を座標系$Y$を使って表示することも可能です。この場合、座標系 $X$ の全てを表示することはできません、なぜなら $X$ の定義域(ドメイン)は $Y$ のそれより広いからです。 # #

Conversly, the chart $X|_{U}$ can be plotted in terms of the chart $Y$ (this is not possible for the whole chart $X$ since its domain is larger than that of chart $Y$):

# In[51]: graph = X_U.plot(Y,color={x:'blue',y:'green', z:'red'}) show(graph, axes_labels=['r','theta','phi']) # オプションを追加してすることで、グラフを見やすくできます。 # In[52]: graph = X_U.plot(Y, ranges={x:(0,2), y:(0,2),z:(0,2), r:(0,5), th:(0,pi/2), ph:(0, 2*pi) }, number_values=4, color={x:'blue',y:'green', z:'red'}) show(graph, axes_labels=['r','theta','phi']) # ## 多様体上の点 :Points on the manifold # # 多様体$\mathcal{M}$上の点は、与えられた座標系での座標を使って定義されます。 # #

A point on $\mathcal{M}$ is defined by its coordinates in a given chart:

# In[53]: p = M.point((1,2,-1), chart=X, name='p') ; print(p) ; p # $X=(\mathcal{M}, (x,y,z))$ は既定の座標系ですから、その名前を省略することが可能です。 #

Since $X=(\mathcal{M}, (x,y,z))$ is the manifold's default chart, its name can be omitted:

# In[54]: p = M.point((1,2,-1), name='p') ; print(p) ; p # もちろんpは多様体$\mathcal{M}$中の点です。 #

Of course, $p$ belongs to $\mathcal{M}$:

# In[55]: p in M # この点は$U$の中の点でもあります。 # #

It is also in $U$:

# In[56]: p in U # 実際、点$p$の座標 $y$ は 0 ではありません ( $y\not=0$ ):(Uは $ y!=0 || x<0 $で定義された開領域) # #

Indeed the coordinates of $p$ have $y\not=0$:

# In[57]: p.coord(X) # ここで、$X$は$\mathcal{M}$の既定座標系であることから `coord()` にわたす引数では、省略可能であることに注意してください。 # #

Note in passing that since $X$ is the default chart on $\mathcal{M}$, its name can be omitted in the arguments of coord():

# In[58]: p.coord() # $p$の座標値は、座標系を点$p$に作用させることによっても得ることができます(座標系の定義により!): # #

The coordinates of $p$ can also be obtained by letting the chart acting of the point (from the very definition of a chart!):

# In[59]: X(p) # 別の点 $q$ を $y = 0$ and $x \geq 0$を満たす一つの点として定義します。 #

Let $q$ be a point with $y = 0$ and $x \geq 0$:

# In[60]: q = M.point((1,0,2), name='q') # $q$は$U$には属しません。 # #

This time, the point does not belong to $U$:

# In[61]: q in U # 従って、点$q$の座標系$Y=(U, (r,\theta,\phi))$ での座標値を求めることはできません。 #

Accordingly, we cannot ask for the coordinates of $q$ in the chart $Y=(U, (r,\theta,\phi))$:

# In[62]: try: q.coord(Y) except ValueError as exc: print("Error: " + str(exc)) # しかし、点$p$については可能です。 # #

but we can for point $p$:

# In[63]: p.coord(Y) # In[64]: Y(p) # 点は比較可能です。: #

Points can be compared:

# In[65]: q == p # In[66]: p1 = U.point((sqrt(3)*sqrt(2), pi-atan(sqrt(5)), atan(2)), chart=Y) p1 == p # SageMathの用語では、点は それが定義された多様体を **親(parents)** として持つ **要素(elements)** です。 #

In SageMath's terminology, points are elements, whose parents are the manifold on which they have been defined:

# In[67]: p.parent() # In[68]: q.parent() # In[69]: p1.parent() # ## スカラー場:Scalar fields # ***スカラー場*** は微分可能な写像 $U \longrightarrow \mathbb{R}$ のことです。ここで $U$ は多様体$\mathcal{M}$の開部分集合です。 # スカラー場はその定義域を覆う座標系を使った式で定義されます。一般には、一つ以上の座標系が定義域全体を覆うためには必要となります。 # # A **scalar field** is a differentiable map $U \to \mathbb{R}$, where $U$ is an open subset of $\mathcal{M}$. # # A scalar field is defined by its expressions in terms of charts covering its domain (in general more than one chart is necessary to cover all the domain): # In[70]: f = U.scalar_field({X_U: x+y^2+z^3}, name='f') ; print(f) # 座標で書かれた表式は、座標系をキーとしたPythonの辞書型データ`{X_U: x+y^2+z^3}`として渡されます。 # この例では、辞書には一つの座標系しかありませんので、次のような表現も可能です。 # #

The coordinate expressions of the scalar field are passed as a Python dictionary, with the charts as keys, hence the writing {X_U: x+y^2+z^3}.

#

Since in the present case, there is only one chart in the dictionary, an alternative writing is

# In[71]: f = U.scalar_field({X_U:x+y^2+z^3}, name='f') print(f) # $X_U$ は定義域 ($U$) の既定の座標系ですので、上記の表現では省略可能です。 # #

Since X_U is the domain's default chart, it can be omitted in the above declaration:

# In[72]: f = U.scalar_field(x+y^2+z^3, name='f') ; print(f) # スカラー場は定義域となる多様体から実数体への写像ですから、それは点に対して働き、座標値に対して働くものではありません。 # As a mapping $U\subset\mathcal{M}\longrightarrow\mathbb{R}$, a scalar field acts on points, not on coordinates: # In[73]: f(p) # スカラー場の`display()` メソッドは与えられた座標系でのスカラー場の表現を表示します。 # # The method `display()` provides the expression of the scalar field in terms of a given chart: # In[74]: f.display(X_U) # 引数なしで呼び出された場合、`display()`メソッドは 定義域 $U$ の上で定義された全ての座標系について、座標表現を表示します。 # (但し*副座標系*,即ち制限された副定義域のみで定義された座標系は除きます。) # # If no argument is provided, the method `display()` shows the coordinate expression of the scalar field in all the charts defined on the domain (except for *subcharts*, i.e. the restrictions of some chart to a subdomain): # In[75]: f.display() # スカラー場 $f$の 座標$(r,\theta,\phi)$ での表現はユーザによって与えられたものではなく、座標系の遷移写像で定義された座標変換のルールを使って自動的に導出されていることに注意してください。 # #

Note that the expression of $f$ in terms of the coordinates $(r,\theta,\phi)$ has not been provided by the user but has been automatically computed by means of the change-of-coordinate formula declared above in the transition map.

# In[76]: f.display(Y) # 各座標系で、スカラー場は座標の関数(`CoordFunctionSymb` のオブジェクト)として表現されます。このオブジェクトは`coord_function()`メソッドを通じてアクセス可能です。 #

In each chart, the scalar field is represented by a function of the chart coordinates (an object of the type CoordFunctionSymb described above), which is accessible via the method coord_function():

# In[77]: f.coord_function(X_U) # In[78]: f.coord_function(X_U).display() # In[79]: f.coord_function(Y) # In[80]: f.coord_function(Y).display() # "生"の記号的表現は、`expr()`メソッドの戻り値として返されます。 #

The "raw" symbolic expression is returned by the method expr():

# In[81]: f.expr(X_U) # In[82]: f.expr(Y) # In[83]: f.expr(Y) is f.coord_function(Y).expr() # スカラー場は具体的な式ではなく、座標値の関数を用いて定義することも可能です。 #

A scalar field can also be defined by some unspecified function of the coordinates:

# In[84]: h = U.scalar_field(function('H')(x, y, z), name='h') ; print(h) # In[85]: h.display() # In[86]: h.display(Y) # In[87]: h(p) # remember that p is the point of coordinates (1,2,-1) in the chart X_U # $f$の親(parent)は すべての $U$ 上の滑らかなスカラー場からなる集合 $C^\infty(U)$ です。これは$\mathbb{R}$上の 可換代数です。 # #

The parent of $f$ is the set $C^\infty(U)$ of all smooth scalar fields on $U$, which is a commutative algebra over $\mathbb{R}$:

# In[88]: CU = f.parent() ; CU # In[89]: print(CU) # In[90]: CU.category() # 代数$CU$の基礎体となる環は実数体$\mathbb{R}$です。それはSageMathではSymbolic Ring (SR)で表現されます。 # # The base ring of the algebra is the field $\mathbb{R}$, which is represented here by SageMath's Symbolic Ring (`SR`): # In[91]: CU.base_ring() # スカラー場の代数計算は代数構造を通じて定義されます。 # #

Arithmetic operations on scalar fields are defined through the algebra structure:

# In[92]: s = f + 2*h ; print(s) # In[93]: s.display() # ## 接空間:Tangent spaces # # 点 $p$での多様体の接ベクトル空間を次のようにして取り出します。 # #

The tangent vector space to the manifold at point $p$ is obtained as follows:

# In[94]: Tp = M.tangent_space(p) ; Tp # In[95]: print(Tp) # $T_p\, \mathcal{M}$は $\mathbb{R}$上の3次元のベクトル空間です。 # #

$T_p\, \mathcal{M}$ is a 3-dimensional vector space over $\mathbb{R}$ (represented here by SageMath's Symbolic Ring (SR)) :

# In[96]: print(Tp.category()) # In[97]: Tp.dim() #

$T_p\, \mathcal{M}$のベクトルの基底は点$p$の周りのベクトルフレームから誘導されます。 # #

$T_p\, \mathcal{M}$ is automatically endowed with vector bases deduced from the vector frames defined around the point:

# In[98]: Tp.bases() # 対照的に、点 $q$ については、あらかじめ定義された基底は一つだけです。 $q$ はドメイン $U$ に含まれませんので、$(r,\theta,\phi)$ に関連づけれられていません。 # #

For the tangent space at the point $q$, on the contrary, there is only one pre-defined basis, since $q$ is not in the domain $U$ of the frame associated with coordinates $(r,\theta,\phi)$:

# In[99]: Tq = M.tangent_space(q) Tq.bases() # ランダムな要素: # #

A random element:

# In[100]: v = Tp.an_element() ; print(v) # In[101]: v.display() # In[102]: u = Tq.an_element() ; print(u) # In[103]: u.display() # 上記の簡略化された表現(基底ベクトルに点$p$あるいは$q$の指定がない)から類推されるのとは異なり、$u$と$v$は異なるベクトルです。これらは異なったベクトル空間に属しています。: # #

Note that, despite what the above simplified writing may suggest (the mention of the point $p$ or $q$ is omitted in the basis vectors), $u$ and $v$ are different vectors, for they belong to different vector spaces:

# In[104]: v.parent() # In[105]: u.parent() # とくに $u$と$v$を足し合わせることはできません。 #

In particular, it is not possible to add $u$ and $v$:

# In[106]: try: s = u + v except TypeError as exc: print("Error: " + str(exc)) # ## べクトル場:Vector Fields # 全ての座標系は座標系のドメインの上のベクトルフレームを持っています。これは、`coordinate basis`と呼ばれます、 # #

Each chart defines a vector frame on the chart domain: the so-called coordinate basis:

# In[107]: X.frame() # In[108]: X.frame().domain() # this frame is defined on the whole manifold このフレームは多様体全体で定義されています。 # In[109]: Y.frame() # In[110]: Y.frame().domain() # this frame is defined only on U このフレームは部分多様体 $U$でのみ定義されています。 # `frames()`メソッドによって、与えられた開空間で定義されたフレームのリストが入手可能です。 # #

The list of frames defined on a given open subset is returned by the method frames():

# In[111]: M.frames() # In[112]: U.frames() # In[113]: M.default_frame() # `set_default_frame()`メソッドで別途明示的に指定されない限り、基底の座標系に関連づけられるベクトルフレームが基底のフレームです。 # #

Unless otherwise specified (via the command set_default_frame()), the default frame is that associated with the default chart:

# In[114]: M.default_frame() is M.default_chart().frame() # In[115]: U.default_frame() is U.default_chart().frame() # フレームのそれぞれの要素は指標を使って指定できます。 # #

Individual elements of a frame can be accessed by means of their indices:

# In[116]: e = U.default_frame() ; e2 = e[2] ; e2 # In[117]: print(e2) # 新しいベクトル場を次のようにして、定義できます。 #

We may define a new vector field as follows:

# In[118]: v = e[2] + 2*x*e[3] ; print(v) # In[119]: v.display() # ベクトル場は与えられたベクトルフレームに関する要素を指定することで、定義できます。 # もしベクトルフレームが指定されていない場合には、既定のフレームがもちろん仮定されます。 # #

A vector field can be defined by its components with respect to a given vector frame. When the latter is not specified, the open set's default frame is of course assumed:

# In[120]: v = U.vector_field(name='v') # vector field defined on the open set U v[1] = 1+y v[2] = -x v[3] = x*y*z v.display() # SageMath 8.8 以降では、ベクトルフィールドの成分はそれを宣言する時に設定することができます。従って、上記は次の宣言と等価です。 # # Since version 8.8 of SageMath, it is possible to initialize the components of the vector field while declaring it, so that the above is equivalent to # In[121]: v = U.vector_field(1+y, -x, x*y*z, name='v') # valid only in SageMath 8.8 and higher v.display() # $U$上のベクトル場はSageの **要素(element)** オブジェクトです。その **親(parent)** は $U$上で定義されたベクトル場の$\mathfrak{X}(U)$集合に設定されています。 # #

Vector fields on $U$ are Sage element objects, whose parent is the set $\mathfrak{X}(U)$ of vector fields defined on $U$:

# In[122]: v.parent() # 集合 $\mathfrak{X}(U)$ は$U$で定義されたのスカラー場の可換代数$C^\infty(U)$上のモジュールです。 # #

The set $\mathfrak{X}(U)$ is a module over the commutative algebra $C^\infty(U)$ of scalar fields on $U$:

# In[123]: print(v.parent()) # In[124]: print(v.parent().category()) # In[125]: v.parent().base_ring() # ベクトル場はスカラー場に作用します。 # #

A vector field acts on scalar fields:

# In[126]: f.display() # In[127]: s = v(f) ; print(s) # In[128]: s.display() # In[129]: e[3].display() # In[130]: e[3](f).display() # 設定されていない要素は、0 と仮定されます。 # #

Unset components are assumed to be zero:

# In[131]: w = U.vector_field(name='w') w[2] = 3 w.display() # $U$上のベクトル場は座標系 $(r,\theta,\phi)$ に関係付けられているベクトルフレームで展開することができます。 # #

A vector field on $U$ can be expanded in the vector frame associated with the chart $(r,\theta,\phi)$:

# In[132]: v.display(Y.frame()) # 既定の設定では、要素は既定の座標 $(x,y,z)$ を用いて、表現されます。これらの要素を 別の座標 $(r,\theta,\phi)$ を用いて表現するには、 # `display()`メソッドの2番目の引数として、対応する座標系を指定することが必要です。 # #

By default, the components are expressed in terms of the default coordinates $(x,y,z)$. To express them in terms of the coordinates $(r,\theta,\phi)$, one should add the corresponding chart as the second argument of the method display():

# In[133]: v.display(Y.frame(), Y) # In[134]: for i in M.irange(): show(e[i].display(Y.frame(), Y)) # 既定のフレームに関するテンソル場の要素は、コマンド `[:]` を使うことで、リストとして取り出せます。 # #

The components of a tensor field w.r.t. the default frame can also be obtained as a list, via the command [:]:

# In[135]: v[:] # 別の方法として、`display_comp()`メソッドを使うこともできます。 # #

An alternative is to use the method display_comp():

# In[136]: v.display_comp() # 別のフレームについての要素を取り出すには、`comp()` メソッドを通じて要素を取り出すフレームを指定する必要があります。 # #

To obtain the components w.r.t. to another frame, one may go through the method comp() and specify the frame:

# In[137]: v.comp(Y.frame())[:] # しかしながら、最初の引数にフレームを与える 短縮表現も用意されています。 # #

However a shortcut is to provide the frame as the first argument of the square brackets:

# In[138]: v[Y.frame(), :] # In[139]: v.display_comp(Y.frame()) # 要素は、既定の座標系の座標で表現されます。これらの別の座標系の座標、例えば$(r,\theta,\phi)$、で表現したい時には、 # `[]`の最後の引数として、座標系の名前を与えます。 # #

Components are shown expressed in terms of the default's coordinates; to get them in terms of the coordinates $(r,\theta,\phi)$ instead, add the chart name as the last argument in the square brackets:

# In[140]: v[Y.frame(), :, Y] # あるいは、`display_comp()` の引数に座標系の名前を与えます。 # #

or specify the chart in display_comp():

# In[141]: v.display_comp(Y.frame(), chart=Y) # ベクトル場の成分を座標についての表現ではなく、スカラーフィールドとして取り出すために、二重の括弧 `[[]]` を使います。 # # To get some vector component as a scalar field instead of a coordinate expression, use double square brackets: # In[142]: print(v[[1]]) # In[143]: v[[1]].display() # In[144]: v[[1]].expr(X_U) # ベクトル場は関数オブジェクトを要素として定義することも可能です。 # #

A vector field can be defined with components being unspecified functions of the coordinates:

# In[145]: u = U.vector_field(name='u') u[:] = [function('u_x')(x,y,z), function('u_y')(x,y,z), function('u_z')(x,y,z)] u.display() # In[146]: s = v + u ; s.set_name('s') ; s.display() # ### ある点でのベクトル場の値:Values of vector fields at a given point # 多様体中のある点でのベクトル場の値は`at()`メソッドを通じて入手します。 # #

The value of a vector field at some point of the manifold is obtained via the method at():

# In[147]: vp = v.at(p) ; print(vp) # In[148]: vp.display() # 座標系 $X_U$ = $(x,y,z)$ を使った、点$p$の座標と、ベクトル場$v$の要素は次のようになっていたことを思い出してください。 # #

Indeed, recall that, w.r.t. chart X_U=$(x,y,z)$,  the coordinates of the point $p$ and the components of the vector field $v$ are

# In[149]: p.coord(X_U) # In[150]: v.display(X_U.frame(), X_U) # 記述を簡単にするために、点$p$でのベクトル場の値とベクトル場は同じ記号($v$)を使って表示されています。`set_name()`メソッドを使うことで、 # 表示に使われる記号を変更できます。 # #

Note that to simplify the writing, the symbol used to denote the value of the vector field at point $p$ is the same as that of the vector field itself (namely $v$); this can be changed by the method set_name():

# In[151]: vp.set_name(latex_name='v|_p') vp.display() # もちろん、$v|_p$ は$p$の接ベクトル空間に属しています。 # #

Of course, $v|_p$ belongs to the tangent space at $p$:

# In[152]: vp.parent() # In[153]: vp in M.tangent_space(p) # In[154]: up = u.at(p) ; print(up) # In[155]: up.display() # ## 1-形式: 1-forms # $\mathcal{M}$の1-形式とは、線形形式の場です。例えば、スカラー場の微分は1ー形式です。 # #

A 1-form on $\mathcal{M}$ is a field of linear forms. For instance, it can be the differential of a scalar field:

# In[156]: df = f.differential() ; print(df) # In[157]: df.display() # 上記の表現では、1-形式は座標系 $(x,y,z)$から導かれる基底$(\mathrm{d}x, \mathrm{d}y, \mathrm{d}z)$で展開されています。 # この基底は`coframe()`メソッドで取り出すことが可能です。 # #

In the above writing, the 1-form is expanded over the basis $(\mathrm{d}x, \mathrm{d}y, \mathrm{d}z)$ associated with the chart $(x,y,z)$. This basis can be accessed via the method coframe():

# In[158]: dX = X.coframe() ; dX # 多様体 $M$の上に存在する全ての coframe のリストは `coframes()` メソッドを使って取り出します。 # #

The list of all coframes defined on a given manifold open subset is returned by the method coframes():

# In[159]: M.coframes() # ベクトル場として、多様体上の点 $p$ における微分形式の値は `at()` メソッドで取り出します。 # #

As for a vector field, the value of the differential form at some point on the manifold is obtained by the method at():

# In[160]: dfp = df.at(p) ; print(dfp) # In[161]: dfp.display() # なお、$p$の座標は次のようなものでした。 #

Recall that

# In[162]: p.coord() # 線形形式 $\mathrm{d}f|_p$ は$p$の接ベクトル空間の双対に所属しています。 # #

The linear form $\mathrm{d}f|_p$ belongs to the dual of the tangent vector space at $p$:

# In[163]: dfp.parent() # In[164]: dfp.parent() is M.tangent_space(p).dual() # その結果、線形形式を$p$の接ベクトルに作用させると、実数が結果として得られます。 # #

As such, it is acting on vectors at $p$, yielding a real number:

# In[165]: print(vp) ; vp.display() # In[166]: dfp(vp) # In[167]: print(up) ; up.display() # In[168]: dfp(up) #

The differential 1-form of the unspecified scalar field $h$:

# In[169]: show(h.display()) dh = h.differential() ; dh.display() # 1-形式を何もないところから、定義することもできます。 # #

A 1-form can also be defined from scratch:

# In[170]: om = U.one_form(name='omega', latex_name=r'\omega') print(om) # 与えられたcoframeの要素をあたえることで、この1-形式を特定できます。 # #

It can be specified by providing its components in a given coframe:

# In[171]: om[:] = [x^2+y^2, z, x-z] # components in the default coframe (dx,dy,dz) om.display() # # SageMath 8.8 以降では、1-形式の成分を宣言時に初期化することができます。上記の式は次の式と等価です。 # # Since version 8.8 of SageMath, it is possible to initialize the components of the 1-form while declaring it, so that the above is equivalent to # In[172]: om = U.one_form(x^2+y^2, z, x-z, name='omega', # valid only in latex_name=r'\omega') # SageMath 8.8 and higher om.display() # もちろん、既定のフレームとは異なるフレームでの要素を指定することもできます。 #

Of course, one may set the components in a frame different from the default one:

# In[173]: om[Y.frame(), :, Y] = [r*sin(th)*cos(ph), 0, r*sin(th)*sin(ph)] om.display(Y.frame(), Y) # この場合、coframe $(\mathrm{d}x,\mathrm{d}y,\mathrm{d}z)$での要素は自動的に更新されます。 # #

The components in the coframe $(\mathrm{d}x,\mathrm{d}y,\mathrm{d}z)$ are updated automatically:

# In[174]: om.display() # 元の要素の値に戻してみます。 # #

Let us revert to the values set previously:

# In[175]: om[:] = [x^2+y^2, z, x-z] om.display() # 今度は、coframe $(\mathrm{d}r, \mathrm{d}\theta,\mathrm{d}\phi)$ についての要素は自動的に更新されています。 # #

This time, the components in the coframe $(\mathrm{d}r, \mathrm{d}\theta,\mathrm{d}\phi)$ are those that are updated:

# In[176]: om.display(Y.frame(), Y) # 1-形式は、ベクトル場に作用して、スカラー場を与えます。 # #

A 1-form acts on vector fields, resulting in a scalar field:

# In[177]: print(om(v)) ; om(v).display() # In[178]: print(df(v)) ; df(v).display() # In[179]: om(u).display() # スカラー場$f$から導かれた1ー形式については、次の恒等式が成立します。 # #

In the case of a differential 1-form, the following identity holds:

# In[180]: df(v) == v(f) # 1-形式は、*親*が $U$上で定義された全ての1ー形式からなる$C^\infty(U)$-module $\Omega^{1}(U)$ であるSageの *element* オブジェクトです。 # # 1-forms are Sage *element* objects, whose *parent* is the $C^\infty(U)$-module $\Omega^{1}(U)$ of all 1-forms defined on $U$: # In[181]: df.parent() # In[182]: print(df.parent()) # In[183]: print(om.parent()) # $\Omega^{1}(U)$は自由モジュール $\mathfrak{X}(U)$の双対です。 # # $\Omega^{1}(U)$ is actually the dual of the free module $\mathfrak{X}(U)$: # In[184]: df.parent() is v.parent().dual() # ## 微分形式と外積, 外微分 # 二つの1ー形式の **外積** は `wedge()` メソッドを使って求められます。その結果は 2-形式となります。 # #

Differential forms and exterior calculus

#

The exterior product of two 1-forms is taken via the method wedge() and results in a 2-form:

# In[185]: a = om.wedge(df) ; print(a) ; a.display() # 行列形式での要素の表示: #

A matrix view of the components:

# In[186]: a[:] # 歪対称性から導かれる余分な要素を省き、ゼロでない成分だけを表示します: #

Displaying only the non-vanishing components, skipping the redundant ones (i.e. those that can be deduced by antisymmetry):

# In[187]: a.display_comp(only_nonredundant=True) # 2-形式$\omega\wedge\mathrm{d}f$を コフレーム$(\mathrm{d}r,\mathrm{d}\theta,\mathrm{d}\phi)$ での成分に展開することもできます。 # #

The 2-form $\omega\wedge\mathrm{d}f$ can be expanded on the $(\mathrm{d}r,\mathrm{d}\theta,\mathrm{d}\phi)$ coframe:

# In[188]: a.display(Y.frame(), Y) # $A:=\omega\wedge\mathrm{d}f$ は2-形式として 二組のベクトルに作用させることができ、また歪対称です。 # #

As a 2-form, $A:=\omega\wedge\mathrm{d}f$ can be applied to a pair of vectors and is antisymmetric:

# In[189]: a.set_name('A') print(a(u,v)) ; a(u,v).display() # In[190]: a(u,v) == - a(v,u) # In[191]: a.symmetries() # ある微分形式の **外微分** は以下のように、`exterior_derivative()`メソッドを使って求めます。 # #

The exterior derivative  of a differential form:

# In[192]: dom = om.exterior_derivative() ; print(dom) ; dom.display() # `exterior_derivative()`メソッドを作用させる代わりに、関数 `diff()` を使うこともできます(SageMath 9.2以降で利用可能)。 # # Instead of invoking the method `exterior_derivative()`, one can use the function `diff()` (available in SageMath 9.2 or higher): # In[193]: dom = diff(om) dom # In[194]: da = diff(a) ; print(da) ; da.display() # **外微分** を続けて作用させると、結果は0になります。 # #

The exterior derivative is nilpotent:

# In[195]: ddf = diff(df) ; ddf.display() # In[196]: ddom = diff(dom) ; ddom.display() # ## Lie 微分: Lie derivative # テンソル場のあるベクトル場に関するLie微分は、`lie_derivative()` メソッドを用いて計算します。 # #

The Lie derivative of any tensor field with respect to a vector field is computed by the method lie_derivative(), with the vector field as the argument:

# In[197]: lv_om = om.lie_derivative(v) ; print(lv_om) ; lv_om.display() # In[198]: lu_dh = dh.lie_derivative(u) ; print(lu_dh) ; lu_dh.display() # *Cartanの恒等式*を確かめてみましょう # # 1-形式$\omega$についての*Cartanの恒等式* # $$\mathcal{L}_v \omega = v\cdot \mathrm{d}\omega + \mathrm{d}\langle \omega, v\rangle$$ # 2-形式$\omega$についての*Cartanの恒等式* # $$\mathcal{L}_v A = v\cdot \mathrm{d}A + \mathrm{d}(v\cdot A)$$ # #

Let us check Cartan identity on the 1-form $\omega$:

#

$\mathcal{L}_v \omega = v\cdot \mathrm{d}\omega + \mathrm{d}\langle \omega, v\rangle$

#

and on the 2-form $A$:

#

$\mathcal{L}_v A = v\cdot \mathrm{d}A + \mathrm{d}(v\cdot A)$

# In[199]: om.lie_derivative(v) == v.contract(diff(om)) + diff(om(v)) # In[200]: a.lie_derivative(v) == v.contract(diff(a)) + diff(v.contract(a)) # ベクトル場の別のベクトル場によるLie微分は、二つのベクトル場による **交換子積**(あるいは **交換子**) になります。 # #

The Lie derivative of a vector field along another one is the commutator of the two vectors fields:

# In[201]: v.lie_derivative(u)(f) == u(v(f)) - v(u(f)) # ## 任意の階数のテンソル場:Tensor fields of arbitrary rank # これまでに、次のようなテンソル場をみてきました。 # # - (0,0)形式のテンソル :スカラー場, # - (1,0) 形式のテンソル :ベクトル場, # - (0,1)形式のテンソル :1ー形式あるいは一階の微分形式, # - (0,2)形式で歪対称のテンソル :2ー形式あるいは二階の微分形式. # # より一般に、$(p,q)$型のテンソル場をSageManifoldsに導入することができます。 # 例えば、副多様体$U$上の(1,2)型のテンソル場を次のように宣言します。 # # Up to now, we have encountered tensor fields # # - of type (0,0) (i.e. scalar fields), # - of type (1,0) (i.e. vector fields), # - of type (0,1) (i.e. 1-forms), # - of type (0,2) and antisymmetric (i.e. 2-forms). # # More generally, tensor fields of any type $(p,q)$ can be introduced in SageMath. For instance a tensor field of type (1,2) on the open subset $U$ is declared as follows: # In[202]: t = U.tensor_field(1, 2, name='T') ; print(t) # ベクトルや1-形式と同じように、テンソル場の既定のフレームに関する要素を `[]`演算子を使って設定できます。 # #

As for vectors or 1-forms, the tensor's components with respect to the domain's default frame are set by means of square brackets:

# In[203]: t[1,2,1] = 1 + x^2 t[3,2,1] = x*y*z # 設定されていない要素は0です。 #

Unset components are zero:

# In[204]: t.display() # In[205]: t[:] # 0 でない要素を表示します。 #

Display of the nonzero components:

# In[206]: t.display_comp() # 二重括弧`[[]]`演算子は既定のフレームに関する成分をスカラー場として返します。一方、一重の括弧`[]`演算子はこのスカラー場の既定の座標系についての表現を返します。 #

Double square brackets return the component (still w.r.t. the default frame) as a scalar field, while single square brackets return the expression of this scalar field in terms of the domain's default coordinates:

# In[207]: print(t[[1,2,1]]) ; t[[1,2,1]].display() # In[208]: print(t[1,2,1]) t[1,2,1] # (1,2)型のテンソル場は (1-形式、ベクトル場、ベクトル場)からなる3成分のタプルをスカラー場に写像します。 # #

A tensor field of type (1,2) maps a 3-tuple (1-form, vector field, vector field) to a scalar field:

# In[209]: print(t(om, u, v)) t(om, u, v).display() # ベクトル場や微分形式と同じように、多様体に定義されたどのフレームついてのテンソル場の成分も取り出せます。 # #

As for vectors and differential forms, the tensor components can be taken in any frame defined on the manifold:

# In[210]: t[Y.frame(), 1,1,1, Y] # ## テンソル計算:Tensor calculus # テンソル積$\otimes$ は `*`で示されます。 # #

The tensor product $\otimes$ is denoted by `*`:

# In[211]: print(v.tensor_type()) print(a.tensor_type()) # In[212]: b = v*a print(b) b # テンソル積は、(歪)対称性を保ちます。$A$は2-形式なので、二つの引数(位置0および1)について歪対称です。結果として$b$は最後の二つの引数(位置1および2)について歪対称となります。 # #

The tensor product preserves the (anti)symmetries: since $A$ is a 2-form, it is antisymmetric with respect to its two arguments (positions 0 and 1); as a result, b is antisymmetric with respect to its last two arguments (positions 1 and 2):

# In[213]: a.symmetries() # In[214]: b.symmetries() # 標準的な **テンソル 計算** は実装済みです。 # #

Standard tensor arithmetics is implemented:

# In[215]: s = - t + 2*f* b print(s) # **テンソルの縮約 **は `trace()`メソッドおよび `contract()` メソッドで取り扱われます。例として、テンソル $T$ の最初の二つの引数(位置 0 および 1) について縮約してみましょう。つまり、$c_i = T^k_{\ \, k i}$で与えられるテンソル $c$を構築してみましょう。 # # **Tensor contractions** are dealt with by the methods`trace()` and `contract()`: for instance, let us contract the tensor $T$ w.r.t. its first two arguments (positions 0 and 1), i.e. let us form the tensor $c$ of components $c_i = T^k_{\ \, k i}$: # In[216]: c = t.trace(0,1) print(c) # `trace(0,1)`と入力する代わりに、**指標表記** を使って縮約を指定できます。指標は文字列として`[]`演算子の中に記述されます。 # 文字列中で、"^" は反変指標の前、"_" は共変指標の前、に置かれます。 # # An alternative to the writing `trace(0,1)` is to use the **index notation** to denote the contraction: the indices are given in a string inside the `[]` operator, with `'^'` in front of the contravariant indices and `'_'` in front of the covariant ones: # In[217]: c1 = t['^k_ki'] print(c1) c1 == c # 縮約は繰り返された指標(ここでは $k$ です)について実行されます。それ以外の文字(ここでは $i$ )は任意です。 # # The contraction is performed on the repeated index (here `k`); the letter denoting the remaining index (here `i`) is arbitrary: # In[218]: t['^k_kj'] == c # In[219]: t['^b_ba'] == c # 縮約されない指標については "."(ドット)で置き換え可能です。 # #

It can even be replaced by a dot:

# In[220]: t['^k_k.'] == c # この文字列中ではLaTeX式の指定も可能です。 # #

LaTeX notations are allowed:

# In[221]: t['^{k}_{ki}'] == c # SageMath 9.2以降では、ギリシャ文字を使うことも可能です。 # # as well as Greek letters (only for SageMath 9.2 or higher): # In[222]: t['^μ_μα'] == c # テンソル場 $T$ とベクトル場 $v$ の縮約 $T^i_{\ j k} v^k$ は次のようにして、実行されます。ここで、2は$T$の最後の指標の場所、0は$v$の唯一の指標の場所です。 # #

The contraction $T^i_{\ j k} v^k$ of the tensor fields $T$ and $v$ is taken as follows (2 refers to the last index position of $T$ and 0 to the only index position of v):

# In[223]: tv = t.contract(2, v, 0) print(tv) # 2はTの最後の指標の場所、0は$v$の唯一の指標の場所ですので、上記の表記の簡略版は次のようになります。 # #

Since 2 corresponds to the last index position of $T$ and 0 to the first index position of $v$, a shortcut for the above is

# In[224]: tv1 = t.contract(v) print(tv1) # In[225]: tv1 == tv # `contract()` メソッドに替わって、**指標表記** と 直積演算子 `*` を組み合わせることで、縮約を表現できます。 # #

Instead of contract(), the index notation, combined with the * operator, can be used to denote the contraction:

# In[226]: t['^i_jk']*v['^k'] == tv # 繰り替えされない指標については、`.`で置き換えることができます。 # #

The non-repeated indices can be replaced by dots:

# In[227]: t['^._.k']*v['^k'] == tv # ## 計量構造: Metric structures # 多様体$\mathcal{M}$の**Riemann 計量** はつぎのように宣言されます。 # #

A Riemannian metric on the manifold $\mathcal{M}$ is declared as follows:

# In[228]: g = M.riemannian_metric('g') print(g) # 計量 $g$ は対称な (0,2) 型のテンソル場です。 # #

It is a symmetric tensor field of type (0,2):

# In[229]: g.parent() # In[230]: print(g.parent()) # In[231]: g.symmetries() # 計量は、あるベクトルフレームに関する要素で初期化されます。例えば、 # $\mathcal{M}$の既定のフレームを使って、 #

The metric is initialized by its components with respect to some vector frame. For instance, using the default frame of $\mathcal{M}$:

# In[232]: g[1,1], g[2,2], g[3,3] = 1, 1, 1 g.display() # 別のベクトルフレームに関する成分を表示します。 #

The components w.r.t. another vector frame are obtained as for any tensor field:

# In[233]: g.display(Y.frame(), Y) # もちろん計量は二つのベクトルに作用します。 # #

Of course, the metric acts on vector pairs:

# In[234]: print(g(u,v)) ; g(u,v).display() # 計量 $g$に付随する **Levi-Civita 接続**は、: # #

The Levi-Civita connection associated to the metric $g$:

# In[235]: nabla = g.connection() print(nabla) nabla # 多様体の既定の座標をつかってChristoffel記号を書き出します。 # #

The Christoffel symbols with respect to the manifold's default coordinates:

# In[236]: nabla.coef()[:] # 次に、座標$(r,\theta,\phi)$を使って、Christoffel記号を書き出します。 # #

The Christoffel symbols with respect to the coordinates $(r,\theta,\phi)$:

# In[237]: nabla.coef(Y.frame())[:, Y] # `display()` を使って、見易く表示させて見ます。既定の設定では非零の接続係数のみが表示されます。 # # A nice view is obtained via the method `display()` (by default, only the nonzero connection coefficients are shown): # In[238]: nabla.display(frame=Y.frame(), chart=Y) # 計量の`christoffel_symbols_display()`メソッドを使うこともできます。この関数は(既定の設定では)独立なChristoffel記号だけを表示します。 # # One may also use the method `christoffel_symbols_display()` of the metric, which (by default) displays only the non-redundant Christoffel symbols: # In[239]: g.christoffel_symbols_display(Y) # 接続の共変微分に対する作用。 # #

The connection acting as a covariant derivative:

# In[240]: nab_v = nabla(v) print(nab_v) ; nab_v.display() # Levi-Civita 接続係数として, $\nabla_g$ には捩れ(torsion)がありません。 # #

Being a Levi-Civita connection, $\nabla_g$ is torsion.free:

# In[241]: print(nabla.torsion()) ; nabla.torsion().display() # この例ではさらに、多様体は平坦(フラット, 曲率が0)です。 # #

In the present case, it is also flat:

# In[242]: print(nabla.riemann()) ; nabla.riemann().display() # $g_{rr}$ を $1/(1+r^2)$と変更することで、曲率のある空間を考えましょう。 # #

Let us consider a non-flat metric, by changing $g_{rr}$ to $1/(1+r^2)$:

# In[243]: g[Y.frame(), 1,1, Y] = 1/(1+r^2) g.display(Y.frame(), Y) # 簡単の為に、副多様体$U$の既定の座標系をY=$(U,(r,\theta,\phi))$に変更します。 # #

For convenience, we change the default chart on the domain $U$ to Y=$(U,(r,\theta,\phi))$:

# In[244]: U.set_default_chart(Y) # これによって、 $(r,\theta,\phi)$を使った座標表現を求める際に座標系 $Y$ を指定する必要がありません。 # #

In this way, we do not have to specify Y when asking for coordinate expressions in terms of $(r,\theta,\phi)$:

# In[245]: g.display(Y.frame()) # この計量は双曲空間 $\mathbb{H}^3$の計量だと気がつきます。座標系 $(U,(x,y,z))$についての表現は、次のようになります。 # #

We recognize the metric of the hyperbolic space $\mathbb{H}^3$. Its expression in terms of the chart $(U,(x,y,z))$ is

# In[246]: g.display(X_U.frame(), X_U) # 要素の行列表示の方がより適切かもしれません。 # #

A matrix view of the components may be more appropriate:

# In[247]: g[X_U.frame(), :, X_U] # もともとは $U$でのみ定義されていたこれらの成分を、全体の多様体$\mathcal{M}$までに拡張します。拡張は、座標系 X=$(\mathcal{M},(x,y,z))$ に付随するフレームでの座標表現が同じであることを要求して実行されます。 # #

We extend these components, a priori defined only on $U$, to the whole manifold $\mathcal{M}$, by demanding the same coordinate expressions in the frame associated to the chart X=$(\mathcal{M},(x,y,z))$:

# In[248]: g.add_comp_by_continuation(X.frame(), U, X) g.display() # Levi-Civita接続は、計量 $g$の変更後、自動的に再計算されます。 # #

The Levi-Civita connection is automatically recomputed, after the change in $g$:

# In[249]: nabla = g.connection() # とくに、Christoffel 係数は、異なっています。 #

In particular, the Christoffel symbols are different:

# In[250]: nabla.display(only_nonredundant=True) # In[251]: nabla.display(frame=Y.frame(), chart=Y, only_nonredundant=True) # Rimannテンソルは、今や: #

The Riemann tensor is now

# In[252]: Riem = nabla.riemann() print(Riem) ; Riem.display(Y.frame()) # リーマンテンソルは接続などを明示的に求めることなく、計量$g$から直接算出できます。 # #

Note that it can be accessed directely via the metric, without any explicit mention of the connection:

# In[253]: g.riemann() is nabla.riemann() # **Ricci テンソル** はこのようになります。 # #

The Ricci tensor is

# In[254]: Ric = g.ricci() print(Ric) Ric.display(Y.frame()) # **Weyl テンソル** は: #

The Weyl tensor is:

# In[255]: C = g.weyl() print(C) ; C.display() # 多様体 $\mathcal{M}$ の次元が 3 なので、**Weyl テンソル** は恒等的に0になります。 # 最後に **Ricci スカラ(曲率)** を求めます。 # #

The Weyl tensor vanishes identically because the dimension of $\mathcal{M}$ is 3.

#

Finally, the Ricci scalar is

# In[256]: R = g.ricci_scalar() print(R) ; R.display() #

We recover the fact that $\mathbb{H}^3$ is a Riemannian manifold of constant negative curvature.

# # ## 計量によって引き起こされるテンソル場の変形:Tensor transformations induced by a metric # # もっとも重要な軽量 $g$によって引き起こされるテンソル場の変形は、**musical isomorphism** あるいは **指標の引き上げ** および **指標の引き下げ**と呼ばれるものです。 # #

The most important tensor transformation induced by the metric $g$ is the so-called musical isomorphism, or index raising and index lowering:

# In[257]: print(t) # In[258]: t.display() # In[259]: t.display(X_U.frame(), X_U) # テンソル場 $T$の最後の指標(位置は2)を計量 $g$ について、引き上げます。 # # Raising the last index (position 2) of $T$ with $g$: # In[260]: s = t.up(g, 2) print(t,s) # # 上記の式で引き上げられた指標は反変な指数のうち最後のものになることに注意しましょう。つまり、メソッド`up`が返すテンソル $s$ は # $$ s^{ab}_{\ \ \ \, c} = g^{bi} T^a_{\ \ ic}$$ # です。 # # Note that the raised index becomes the *last* one among the contravariant indices, i.e. the tensor $s$ returned by the method `up` is # $$ s^{ab}_{\ \ \ \, c} = g^{bi} T^a_{\ \ ic}$$ # これについての詳細は[up()の解説](https://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/differentiable/tensorfield.html#sage.manifolds.differentiable.tensorfield.TensorField.up) をご覧ください。 # # See the [up() documentation](https://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/differentiable/tensorfield.html#sage.manifolds.differentiable.tensorfield.TensorField.up) for more details. # $T$の全ての共変な指標(この例では 位置 1と2)を引き上げます。 # #

Raising all the covariant indices of $T$ (i.e. those at the positions 1 and 2):

# In[261]: s = t.up(g) print(s) # In[262]: s = t.down(g) print(s) # # 上記の式で引き下げられた指標は 共変な指標のうち *最初* の指標になることに注意しましょう。 即ち、`down`メソッドが返すテンソル $s$ は、 # $$ s_{abc} = g_{ai} T^i_{\ \ bc}$$ # となります。 # # # Note that the lowered index becomes the *first* one among the covariant indices, i.e. the tensor $s$ returned by the method `down` is # $$ s_{abc} = g_{ai} T^i_{\ \ bc}$$ # # これについての詳細は[down()の解説](https://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/differentiable/tensorfield.html#sage.manifolds.differentiable.tensorfield.TensorField.down) をご覧ください。 # # See the [down() documentation](https://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/differentiable/tensorfield.html#sage.manifolds.differentiable.tensorfield.TensorField.down) for more details. # ## Hodge双対(星印演算子) :Hodge duality # 計量 $g$についての体積 3-形式(Levi-Civita テンソル )は # #

The volume 3-form (Levi-Civita tensor) associated with the metric $g$ is

# In[263]: epsilon = g.volume_form() print(epsilon) epsilon.display() # In[264]: epsilon.display(Y.frame()) # In[265]: print(f) ; f.display() # In[266]: sf = f.hodge_dual(g.restrict(U)) print(sf) sf.display() # 古典的な式$\star f = f\, \epsilon_g$, より正確には$\star f = f\, \epsilon_g|_U$, を確かめてみましょう。 # $f$ は $U$ 上でのみ定義されていることに注意します。 # #

We check the classical formula $\star f = f\, \epsilon_g$, or, more precisely, $\star f = f\, \epsilon_g|_U$ (for $f$ is defined on $U$ only):

# In[267]: sf == f * epsilon.restrict(U) # 1-形式のHodge 双対は、2ー形式 です。(3次元多様体の場合); # The Hodge dual of a 1-form is a 2-form:

# In[268]: print(om) ; om.display() # In[269]: som = om.hodge_dual(g) print(som) ; som.display() # (3次元多様体上では)2ー形式のhodge 双対は 1ー形式になります。 # #

The Hodge dual of a 2-form is a 1-form:

# In[270]: print(a) # In[271]: sa = a.hodge_dual(g) print(sa) sa.display() # 最後に3ー形式のHodge 双対は 0-forms です。 #

Finally, the Hodge dual of a 3-form is a 0-form:

# In[272]: print(da) da.display() # In[273]: sda = da.hodge_dual(g) print(sda) sda.display() # 3次元のリーマン計量に対して、Hodge 双対はidempotent、つまり2回続けて作用させると元に戻ります。 # #

In dimension 3 and for a Riemannian metric, the Hodge star is idempotent:

# In[274]: sf.hodge_dual(g) == f # In[275]: som.hodge_dual(g) == om # In[276]: sa.hodge_dual(g) == a # In[277]: sda.hodge_dual(g.restrict(U)) == da # ## 助けを求める:Getting help # # オブジェクトが呼び出すことのできる関数(メソッドを入手するには、オブジェクトの名前を入力したのち、"."とTABを入力します。 # つまり、`sa.`です。 # # オブジェクトやメソッドについての情報を入手するために、疑問符 `?`をお使いください。 # #

To get the list of functions (methods) that can be called on a object, type the name of the object, followed by a dot and the TAB key, e.g.

#

sa.

#

To get information on an object or a method, use the question mark:

# In[278]: get_ipython().run_line_magic('pinfo', 'nabla') # In[279]: get_ipython().run_line_magic('pinfo', 'g.ricci_scalar') # 二つの疑問符 `??` は **Pythonソースコード** に直接導かれます。(SageMathはオープンソースです、そうでしょう?) # # Using a double question mark leads directly to the **Python source code** (SageMath is **open source**, isn't it?): # In[280]: get_ipython().run_line_magic('pinfo2', 'g.ricci_scalar') # ## さらに先へ:Going further # # [ページ:SageManifolds の例](https://sagemanifolds.obspm.fr/examples.html)をご覧ください。とくに、平行化不能な多様体(スカラー場は少なくとも二つの座標系で定義される必要があり、 # モジュール $\mathfrak{X}(\mathcal{M})$はもはやフリーではなく、 # テンソル場は少なくとも二つのフレームで定義される必要があります) # での使い方については、 # [2-次元 球面](https://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S2.ipynb) # が役に立つでしょう。 # # Christian Bär氏による[チュートリアル ビデオ](https://www.youtube.com/playlist?list=PLnrOCYZpQUuJlnQbQ48zgGk-Ks1t145Yw)もご覧ください。 # # Have a look at the [examples on SageManifolds page](https://sagemanifolds.obspm.fr/examples.html), especially the # [2-dimensional sphere](https://nbviewer.jupyter.org/github/sagemanifolds/SageManifolds/blob/master/Notebooks/SM_sphere_S2.ipynb) for usage on a non-parallelizable manifold (each scalar field has to be defined in at least two coordinate charts, the $C^\infty(\mathcal{M})$-module $\mathfrak{X}(\mathcal{M})$ is no longer free and each tensor field has to be defined in at least two vector frames). # # You may also take a look at the [tutorial videos](https://www.youtube.com/playlist?list=PLnrOCYZpQUuJlnQbQ48zgGk-Ks1t145Yw) by Christian Bär.