【Python演算処理】単位トーラス(Unit Torus)を巡る数理①平坦トーラス(Flat Torus)との往復

以下の投稿では**複素平面**(Complex Plane)上における円周群の概念と**等速円運動**(Constant Velocity Circular Motion)に共通する数理について調べました。
[等速円運動についての物理学と数学の立場の違い?](https://qiita.com/ochimusha01/items/d5526764c7d1199671df)
![image.png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419112449.png)
![image.png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419112912.png)
今度は座標系全体に目を向けてみましょう。

#トーラス座標系(<font color=blue>Torus coordinate system</font>)なる概念の登場。

この投稿は主に以下を参照しています。
[【超わかる】オイラーの公式を見て！聞いて！感じるンゴ！](https://www.gachitan.com/entry/eulers_formula)

①まずは**両側無限実数列**(Both-sides Real Sequence)$Z_n$とその**指数写像**(Exponential Map)たる**片側無限実数列**(One-side Real Sequence)$e^n$の関係から出発する。自明の場合として$Z_n$は$e^n$の**対数写像**(Logarithm Map)となる。
[リー環の指数写像 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%BC%E7%92%B0%E3%81%AE%E6%8C%87%E6%95%B0%E5%86%99%E5%83%8F)

>解析学の通常の指数関数はリー群Gが正の実数の乗法群（そのリー環は実数全体のなす加法群）のときの指数写像という特別な場合である。リー群の指数写像は通常の指数関数の性質と類似の多くの性質を満たすが、しかしながら、多くの重要な面において異なりもする。

[行列指数関数(Matrix Exponential=行列乗) - Wikipedia](https://ja.wikipedia.org/wiki/%E8%A1%8C%E5%88%97%E6%8C%87%E6%95%B0%E9%96%A2%E6%95%B0)
[行列の対数(Logarithm of a Matrix) - Wikipedia](https://ja.wikipedia.org/wiki/%E8%A1%8C%E5%88%97%E3%81%AE%E5%AF%BE%E6%95%B0)

>対数を持つ**正方行列**(Square Matrix,行要素数と列要素数が一致する正方行列)はいずれかの**リー群**に属し、かつ、その対数はその**リー群**に付随する**リー代数**の元に対応するため、行列の対数函数の研究は**リー理論**につながる。**指数写像**は行列の指数関数で与えられるが、その逆写像は一般に多価となる。対数写像は**リー群**Gを付随するリー代数gへ写す。

[【数理考古学】常用対数表(Table of Common Logarithms)を使った計算](https://qiita.com/ochimusha01/items/b7ce3c7d86ab39263c68)

>**実軸**(Real Axis)における**乗除算**はその**対数写像**において**加減算**に置き換えられる。

それぞれの関数の**定義域**(関数y=f(x)における独立変数xの値)と**値域**(関数y=f(x)における従属変数yの値)の関係は以下。

```math
Z_n(n=-\infty→-1→0→1→+\infty)=(-\infty,…,-1,…,0,…,1,…,+\infty)\\
e^n(n=-\infty→-1→0→1→+\infty)=(0,…,e^{-1},…,1,…,e^1,…,\infty)
```
[【数理考古学】とある実数列(Real Sequance)の規定例②等比数列から乗法群へ](https://qiita.com/ochimusha01/items/58afced6ea8bebf391c7)

```math
-\infty→0\\
-1→e^{-1}(0.3678794)\\
0→1\\
1→e^1(2.718282)\\
+\infty→\infty
```
これを「**正の実軸上の半直線上に写る元の定義域**」は実数直線の任意の点αと考える。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419134706.png)

②すると「**負の実軸上の半直線上に写る元の定義域**」は$α+iπ$とイメージされる。**オイラーの等式**(Eulerian Identity)$e^{πi}=-1$の世界。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419141023.png)

③「**正の虚軸上の半直線上に写る元の定義域**」は$α+i\frac{π}{2}$ないしは$α-3i\frac{π}{2}$とイメージされる。分枝点切断を行わない座標系では両者が同値となる。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419141128.png)

④「**正の虚軸上の半直線上に写る元の定義域**」は$α+3i\frac{π}{2}$ないしは$α-i\frac{π}{2}$とイメージされる。分枝点切断を行わない座標系では両者が同値となる。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419141217.png)

これはまさに**複素平面**を**トーラス座標系**として捉える発想に他なりません。
[【Python演算処理】単位トーラス(Unit Torus)を巡る数理②トーラス群の設定](https://qiita.com/ochimusha01/items/6836c3f63dfd4d62b6b1)
![image,gif](https://camo.qiitausercontent.com/81de4aef460cce87f94ac7f0a8b8b440df12200c/68747470733a2f2f63646e2d616b2e662e73742d686174656e612e636f6d2f696d616765732f666f746f6c6966652f6f2f6f6368696d7573686130312f32303231303432332f32303231303432333031313033392e676966)
![image,gif](https://camo.qiitausercontent.com/68d10549970eb2b6d70e222d12b2f399474696b0/68747470733a2f2f63646e2d616b2e662e73742d686174656e612e636f6d2f696d616765732f666f746f6c6966652f6f2f6f6368696d7573686130312f32303231303432332f32303231303432333030353535382e676966)
![image,gif](https://camo.qiitausercontent.com/656161795f936725eefe8f1ef0481fb35a25b654/68747470733a2f2f63646e2d616b2e662e73742d686174656e612e636f6d2f696d616765732f666f746f6c6966652f6f2f6f6368696d7573686130312f32303231303432332f32303231303432333031303733382e676966)

確かにトーラス構造を平たく伸ばして「(上下左右の端同士がつながってるコンピューターRPGのワールドマップの様な)**平面トーラス**」に変換するとこうした座標演算が可能となるのです。こうして展開された平面トーラスは、大半径/小半径それぞれを単位1と置いた場合、それぞれ2π倍の広がりを持つ方形となります。
[【ドラクエ1】ワールドマップ（世界地図）とマップ一覧](https://kamigame.jp/%E3%83%89%E3%83%A9%E3%82%AF%E3%82%A81/%E3%83%9E%E3%83%83%E3%83%97/index.html)
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419143927.png)
この座標系における垂直移動は、外側から見るとこう見えます。
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210423/20210423080305.gif)
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210423/20210423075227.gif)
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210423/20210423080220.gif)

```python
%matplotlib nbagg
import math as m
import cmath as c
import numpy as num
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation

#円柱データ作成
c0=num.linspace(0,m.pi*120,1201,endpoint = True)
s0=[]
for nm in range(len(c0)):
    s0.append(complex(m.cos(c0[nm]),m.sin(c0[nm])))
s1=num.array(s0)
z0=num.linspace(-1,1,1201,endpoint = True)

#「曲率」を計算
cv0=num.linspace(-1,1,1201,endpoint = True)
cv1=num.sqrt(1-cv0**2)

#トーラス計算
s2=s1*(1+cv1)
s3=s1*(1-cv1)

#小半径追加
MiHz0=num.linspace(-1,1,61,endpoint = True)
MiHz=MiHz0[::-1]
MiPx=1+num.sqrt(1-MiHz**2)
MiMx=1-num.sqrt(1-MiHz**2)
MiBx=num.sqrt(1-MiHz**2)
MiHy=num.repeat(0,61)

#小半径アニメーション(元図形)
MiAh1=num.linspace(-1,1,31,endpoint =True)
MiAh2=num.linspace(-1,1,31,endpoint = False)
MiAh3=num.concatenate([MiAh1, MiAh2[::-1]])
MiAh=num.concatenate([MiAh3[14:61], MiAh3[0:13]])
MiAv1=1-num.sqrt(1-MiAh1**2)
MiAv2=1+num.sqrt(1-MiAh2[::-1]**2)
MiAv3=num.concatenate([MiAv2, MiAv1])
MiAv=num.concatenate([MiAv3[14:61], MiAv3[0:13]])

#小半径アニメーション(回転)
MiAvC0=[]
for nm in range(len(MiAv)):
    MiAvC0.append(complex(MiAv[nm],0))
MiAvC=num.array(MiAvC0) 

#単位円データ作成
u0=num.linspace(0,m.pi*2,61,endpoint = True)
u1=[]
for nm in range(len(u0)):
    u1.append(complex(m.cos(u0[nm]),m.sin(u0[nm])))
uc=num.array(u1)
uz0=num.repeat(-1,61)
uz1=num.repeat(-0,61)
uz2=num.repeat(1,61)

#グラフ表示
plt.style.use('default')
fig = plt.figure()
ax = Axes3D(fig)
Tcode=num.linspace(0,m.pi*2,61,endpoint =True)
#描画関数定義
def unit_cylinder(n):
    plt.cla()
    #断面計算
    MiAvD0=[]
    for nm in range(len(MiAvC)):
        MiAvD0.append(c.rect(MiAv[nm],Tcode[n]))
    MiAvD=num.array(MiAvD0) 
    MiBvD0=[]
    for nm in range(len(MiBx)):
        MiBvD0.append(c.rect(MiBx[nm],Tcode[n]))
    MiBvD=num.array(MiBvD0)
    MiCvD0=[]
    for nm in range(len(MiHz)):
        MiCvD0.append(c.rect(2,Tcode[n]))
    MiCvD=num.array(MiCvD0)
    #軌跡計算
    Orb_r=abs(MiAvD[n])
    Orb0=[]
    for nm in range(len(MiCvD)):
        Orb0.append(c.rect(Orb_r,Tcode[nm]))
    Orbv=num.array(Orb0)
    Orbh=num.repeat(MiAh[n],61)
    #断面1計算
    MiAvD10=[]
    for nm in range(len(MiAvC)):
        MiAvD10.append(c.rect(MiAv[nm],Tcode[0]))
    MiAvD1=num.array(MiAvD10) 
    MiBvD10=[]
    for nm in range(len(MiBx)):
        MiBvD10.append(c.rect(MiBx[nm],Tcode[0]))
    MiBvD1=num.array(MiBvD10)
    MiCvD10=[]
    for nm in range(len(MiHz)):
        MiCvD10.append(c.rect(2,Tcode[0]))
    MiCvD1=num.array(MiCvD10)  
    #円柱描画
    ax.plot(s2.real,s2.imag,z0,color="gray",lw=0.5)
    ax.plot(s3.real,s3.imag,z0,color="gray",lw=0.5)
    #単位円描画
    ax.plot(uc.real,uc.imag,uz1,color="blue",lw=1)
    #中心線描画
    ax.plot([0,0],[0,0],[-1,1],color="black",lw=1)
    #分割原点
    ax.plot([0,MiCvD1[0].real],[0,MiCvD1[0].imag],[-1,-1],color="green",lw=1)
    ax.plot([0,uc[0].real],[0,uc[0].imag],[0,0],color="blue",lw=1)
    ax.plot([uc[0].real,MiCvD1[0].real],[uc[0].imag,MiCvD1[0].imag],[0,0],color="green",lw=1)
    ax.plot([uc[0].real,uc[0].real],[uc[0].imag,uc[0].imag],[-1,1],color="green",lw=1)    
    ax.plot([uc[0].real,MiAvD1[0].real],[uc[0].imag,MiAvD1[0].imag],[0,MiAh[0]],color="green",lw=1)
    ax.plot([0,MiCvD1[0].real],[0,MiCvD1[0].imag],[1,1],color="green",lw=1)
    ax.plot([MiCvD1[0].real,MiCvD1[0].real],[MiCvD1[0].imag,MiCvD1[0].imag],[-1,1],color="green",lw=1)
    ax.plot(MiAvD1.real,MiAvD1.imag,MiAh,color="green",lw=1)
    ax.plot(MiBvD1.real,MiBvD1.imag,MiHz,color="blue",lw=1)
    #アニメーション描画
    ax.plot([0,MiCvD[n].real],[0,MiCvD[n].imag],[-1,-1],color="black",lw=1)
    ax.plot([0,uc[n].real],[0,uc[n].imag],[0,0],color="blue",lw=1)
    ax.plot([uc[n].real,MiCvD[n].real],[uc[n].imag,MiCvD[n].imag],[0,0],color="black",lw=1)
    ax.plot([uc[n].real,uc[n].real],[uc[n].imag,uc[n].imag],[-1,1],color="black",lw=1)    
    ax.plot([uc[n].real,MiAvD[n].real],[uc[n].imag,MiAvD[n].imag],[0,MiAh[n]],color="red",lw=1)
    ax.plot([0,MiCvD[n].real],[0,MiCvD[n].imag],[1,1],color="black",lw=1)
    ax.plot([MiCvD[n].real,MiCvD[n].real],[MiCvD[n].imag,MiCvD[n].imag],[-1,1],color="black",lw=1)
    ax.plot(MiAvD.real,MiAvD.imag,MiAh,color="red",lw=1)
    ax.plot(MiBvD.real,MiBvD.imag,MiHz,color="blue",lw=1)
    #軌跡描画
    ax.plot(Orbv.real,Orbv.imag,Orbh,color="red",lw=1)
    #諸元追加
    ax.set_ylim([-2.1,2.1])
    ax.set_xlim([-2.1,2.1])
    ax.set_zlim([-2.1,2.1])
    ax.set_title("Unit Cylinder")
    ax.set_xlabel("Real")
    ax.set_ylabel("Imaginal")
    ax.set_zlabel("Cycle")
    # グラフを回転
    ax.view_init(elev=25, azim=45)

Tcode=num.linspace(0,m.pi*2,61,endpoint =True)
#Time_code0=num.arange(0,360,6) 
#Time_code=Time_code0[::-1] 
#unit_cylinder(15)
#plt.show()

ani = animation.FuncAnimation(fig, unit_cylinder, interval=50,frames=len(Time_code))
ani.save("output620.gif", writer="pillow")
```
この軌道をアイロンでも掛けたかの様に真っ直ぐ伸ばすと**円筒座標系**(Cylindrical Coordinate System)における以下の動きに対応する訳ですね。
[【Python演算処理】単位円筒を巡る数理](https://qiita.com/ochimusha01/items/fd8e51940b5e0e1a28c5)
![image.gif](https://qiita-user-contents.imgix.net/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2Fo%2Fochimusha01%2F20210412%2F20210412045910.gif?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=9ae2ac04cd4ef7c4581a8acc7d18278d)
![image.gif](https://qiita-user-contents.imgix.net/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2Fo%2Fochimusha01%2F20210412%2F20210412050306.gif?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=ea9db788f5fc6fd7d0ac7975e0c5a630)
この辺りの詳細については、以下で詳しく解説されています。
[四元数を用いた三次元回転計算の幾何学的意味](https://qiita.com/HMMNRST/items/0a4ab86ed053c770ff6a)

#一般の円座標系との共通点。
この投稿も主に以下を参照しています。
[【超わかる】オイラーの公式を見て！聞いて！感じるンゴ！](https://www.gachitan.com/entry/eulers_formula)

トーラス座標系も円座標同様に写像元に加えられるスカラー加減算の影響を受ける訳ですが、こちらはむしろ頭を切り替えて円座標が**極座標系**(Polar Coordinates System)では**半径**(Radius)rθ(2次元)、rφθ(3次元)と表される数理に拠って考える方がイメージしやすいかもしれません。

①元写像が実数軸の原点で交わる場合、単位スケールそのまま。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419151248.png)
②元写像が実数軸の原点より左(すなわちマイナス方向の位置)で交わる場合、縮小。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419151416.png)
③元写像が実数軸の原点より右(すなわち＋方向の位置)で交わる場合、拡大。
![image,png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419151508.png)

さらに与えられる**演算**が**傾き**(Slope)の要素を含む場合、円ではなく螺旋を描きます。これについては円描画関数$-1^n=±i^{2x}$を中心と考える方式に頭を切り替えた方が遥かにイメージしやすいでしょう。
![image.png](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210419/20210419161720.png)
[【数理考古学】とある実数列(Real Sequance)の規定例②等比数列から乗法群へ](https://qiita.com/ochimusha01/items/58afced6ea8bebf391c7)
**0>公比>-1の等比数列の場合**…どんどん振幅の幅が狭まっていく。
![image.gif](https://staging-qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn-ak.f.st-hatena.com%252Fimages%252Ffotolife%252Fo%252Fochimusha01%252F20210103%252F20210103073903.gif%3Fixlib%3Drb-1.2.2%26auto%3Dformat%26gif-q%3D60%26q%3D75%26w%3D1400%26fit%3Dmax%26s%3D2443c0415ca516c290cfe6ddd5832ffc?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=10845b4115237de6ba7b4cc1b146d4e7)
**公比<-1の等比数列の場合**…どんどん振幅の幅が広がっていく。
![image.gif](https://staging-qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn-ak.f.st-hatena.com%252Fimages%252Ffotolife%252Fo%252Fochimusha01%252F20210103%252F20210103074600.gif%3Fixlib%3Drb-1.2.2%26auto%3Dformat%26gif-q%3D60%26q%3D75%26w%3D1400%26fit%3Dmax%26s%3D3ce133cd477e79e307768d3db551a7fe?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=d3410d7e6b0849f05b28a239fae71a11)
どうやらこの辺りの数理はトーラス座標系の拡張形たる**円筒座標系**(Cylindrical coordinate system)をさらに**円錐座標系**(Conical Coordinate System)に発展させる際に鍵となってきそうです。

そんな感じで以下続報…