nano_exit

基礎的なことこそ、簡単な例が必要だと思うのです。

二次元ハミルトニアンとパウリ行列

 H = a ( |1><1| - |2><2| + |1><2| + |2><1| )固有値を求める問題をパウリ行列使って解く方法が割と楽しい(サクライでは章末問題になっている)。
これを行列で書くと、

 \displaystyle
  H = a 
  \begin{pmatrix}
  1 &  1 \\
  1 & -1 
  \end{pmatrix}
  = a
  \begin{pmatrix}
  1 &  0 \\
  0 & -1 
  \end{pmatrix}
  + a
  \begin{pmatrix}
  0 &  1 \\
  1 &  0 
  \end{pmatrix} \\
  = a ( \sigma_z + \sigma_x )
  = a \sqrt{2}(  \sigma \cdot \hat{n} )

ただし、 \hat{n} = \frac{1}{\sqrt{2}}(1,0,1)の単位ベクトルである。
せっかくなので、パウリ行列をスピン演算子に直してあげれば、 S_i = \frac{\hbar}{2}\sigma_iより

 \displaystyle H = \sqrt{2} a \frac{2}{\hbar} ( {\bf S} \cdot \hat{n} )

で、変形して何なんだという話であるが、 {\bf S} \cdot \hat{n}固有値 \pm \frac{\hbar}{2}で物理的に明らか( \hat{n}方向を向いたスピンの固有値を表している。なぜそうなるのは自明というよりかは自然(実験事実)からの要請に近い。)であるため、このハミルトニアン固有値 E = \pm \sqrt{2}aであることが行列式を使わずにわかってしまう。

ちなみに固有ベクトルだが、違う章末問題で {\bf S} \cdot \hat{n}固有値を回転行列を使わないで真面目に固有値方程式を解く趣旨のものがあり、そっちも教育的で楽しい。固有値はもうわかっているから展開係数を直接求めるのだが、そういうプロセスはあんまりないなぁとボンヤリ思ったりもした。いずれそれもまとめたい。

ハミルトニアンの行列表示

J.J. Sakuraiのゼミをしていたとき、ハミルトニアンの行列表示について議論になった。

 \displaystyle
  H \doteq
  \begin{pmatrix}
  H_{11} & H_{12} & \cdots & \\
  H_{21} & H_{22} &        & \\
  \vdots &        & \ddots & 
 \end{pmatrix}

Diracのbraketを用いた表示で書けば、

 \displaystyle
  H \doteq
  \begin{pmatrix}
  <1|H|1> & <1|H|2> & \cdots & \\
  <2|H|1> & <2|H|2> &        & \\
  \vdots &        & \ddots & 
 \end{pmatrix}

となる。
Sakuraiだと、イコールではないことを強調して一応 \doteqを用いてはいるものの、結構ポッと出な感もあるし、何よりも <1|H|1>の中の Hは外の Hとどう違うの?とか、もう一回中に代入するってこと?みたいな誤解が起きることが分かった。確かに H \psi(x) = E \psi(x) に直接行列表現ぶち込もうとすると訳分からんことになる。

ポイントは一本の二階微分方程式を解くモードか、微分を含まない連立方程式で解くモードかということだと思っている。

シュレーディンガー方程式から出発して、全然分からん固有状態 \phiを素性が良くわかっている固有状態 \phi_iで展開する(例えば何にも相互作用の無いときの固有状態である平面波とか)。

 \displaystyle
  H |\psi> = E |\psi> \\
  H ( C_1 |\phi_1> + C_2 |\phi_2> + \cdots ) =  E ( C_1 |\phi_1> + C_2 |\phi_2> + \cdots )

ここで、例えば <\psi_1|を左から掛けることで、 H|\psi>にどれだけ \phi_1の情報が含まれているかを見る様なことをすると、

 \displaystyle
 <\phi_1| H |\psi> = <\phi_1| E |\psi> \\
 C_1 <\phi_1|H|\phi_1> + C_2 <\phi_1|H|\phi_2> + \cdots =  E C_1

これを他の状態 <\phi_i|でもやってあげれば、展開係数 C_iに関する連立方程式が出来る。

 \displaystyle
 C_1 <\phi_1|H|\phi_1> + C_2 <\phi_1|H|\phi_2> + \cdots =  E C_1 \\
 C_1 <\phi_2|H|\phi_1> + C_2 <\phi_2|H|\phi_2> + \cdots =  E C_2 \\
  \vdots

ここまで、 H微分方程式シュレーディンガー方程式)のハミルトニアンのままであり、別に変なことはしていない。この連立方程式を行列でまとめて書くと、

 \displaystyle
  \begin{pmatrix}
  <\phi_1|H|\phi_1> & <\phi_1|H|\phi_2> & \cdots & \\
  <\phi_2|H|\phi_1> & <\phi_2|H|\phi_2> &        & \\
  \vdots &        & \ddots & 
 \end{pmatrix}
 \begin{pmatrix}
  C_1 \\
  C_2 \\
  \vdots 
 \end{pmatrix}
  =
  \begin{pmatrix}
  E &   &        & O \\
    & E &        &   \\
  O &   & \ddots & 
 \end{pmatrix}
 \begin{pmatrix}
  C_1 \\
  C_2 \\
  \vdots 
 \end{pmatrix}

という具合になる。
なので、 E,\psiを求める問題が、 E, C_iを求める問題にすり替わり、特に Eを求めたければ C_iは必要なく、

 \displaystyle
  \begin{vmatrix}
  <\phi_1|H|\phi_1> - E & <\phi_1|H|\phi_2>     & \cdots & \\
  <\phi_2|H|\phi_1>     & <\phi_2|H|\phi_2> - E &        & \\
  \vdots                &                       & \ddots & 
 \end{vmatrix}
  = 0

を解きさえすれば良い(これがゼロでない場合には、上の行列に逆行列が存在して、 C_i = 0(つまり \psi = 0)という全然興味のない答えしか得られないため、ゼロ出ないことを条件付ける訳である)。
そうすると、 H微分方程式における具体的な表式は、「行列要素の値が求まっていれば」どうでも良くなり、行列形式で問題を扱って行くときにいちいち違う記号を用いるのは煩雑になる(人によって違う記号を使いだすと多分ヤバい)ので、同じ Hを使っているのだと理解している。
最初の話に戻ると、行列の中の Hは実際のシュレーディンガー方程式の Hで、 \doteqの左側にいる Hはただ Hという記号を使っている行列ということになる。

fortranとpython(読み込み)

fortranユーザーからpythonに移って来ると、ただテキスト編集したいのにも関わらず、fortranの癖に慣れてしまったが故にpythonがなかなか使えるようにならんかったのでちょっと整理。

「ファイルを開いて中身を読んで閉じる」までをfortranpythonで比較。

implicit none
integer, parameter :: INPUT = 10
real(kind(0d0))    :: InputData( 50, 50 ), ...
!----------
InputData
open( INPUT, 'test.inp', status='old' )
do i = 1, 50
  read(INPUT, *) InputData( i, : )
enddo
close( INPUT )

test.inpが 50 x 50 以上のデータを持っていると仮定して、InputDataの配列サイズを指定。
'test.inp'に対応する番号として10(=INPUT)を割り当ててあげてファイルを開き、i行目の各列のデータをreadでInputDataに流し込む。
それを50行目まで繰り返してファイルを閉じる。

f = open( 'test.inp', 'r' )
lines = f.read().split('\n')
f.close()
InputData = []
for i, line in enumrate( lines ):
    temps = line.split(' ')
    while '' in temps: temps.remove('')
    InputData += temps

読み込み形式('r')で'test.inp'を開き、中身をlinesにいきなりリストとして突っ込みファイルは閉じる。.split('\n')によって改行ごとに(つまり各行が)違う要素としてlinesの中に収納されている。lines[0]は一行目全部、lines[1]は二行目全部、といった具合。
それを値として全部ぶつ切りに区別したデータとするため、linesの中の要素line(つまりある一つの行)を空白で区切って(.split(' '))、空白が連続している場合には空の要素''が生まれてしまうためwhile文を使って除いている。
綺麗に区切ったデータをInputDataに突っ込む作業を全ての行に対して行う。


おそらくpythonfortranと同じように読ませようとするとこんな感じになるのではないかと思う。
fortranは「行列」を最初から想定しているような節を感じる。型が決まっているなら、その型にハマる様に最初に設定してしまえばあんまり何も考えなくて済む(その代わり型から外れると酷いが)。
一方でpythonは、一本の長いリストに収納してからグニグニ変形させる。かなり自由が利く分、自分がやりたいことを実践するために出来る方法も多く、結果どうしたら良いかわからなくなることも多かった(ファイルを読み込むだけなのにいくつか方法があるというのも新参者には割とストレスになった。。。)。
とりあえず今はこんな感じで落ち着いているが、もっとスマートな方法が多分あると思う。先は蛇のように長い。。。

奇数次元の虚数について

虚数 iは二次元の正方行列を用いて、


  i_2 =
  \begin{pmatrix}
  0 & -1 \\
  1 &  0 
  \end{pmatrix}

と書ける。
では、三次元の正方行列で二乗したら単位行列にマイナスの掛かったものが得られるかをボンヤリ考えたところ、


  i_3 =
  \begin{pmatrix}
  0 & 0 & -1 \\
  0 & i &  0 \\
  1 & 0 &  0 
  \end{pmatrix}

しか思いつかんかった。この iを二次元 i_2と思えば、super matrixと解釈して各行列要素が二次元正方行列に拡張出来るから、


  \begin{pmatrix}
  0 & 0 & 0 &  0 & -1 &  0 \\
  0 & 0 & 0 &  0 &  0 & -1 \\
  0 & 0 & 0 & -1 &  0 &  0 \\
  0 & 0 & 1 &  0 &  0 &  0 \\
  1 & 0 & 0 &  0 &  0 &  0 \\
  0 & 1 & 0 &  0 &  0 &  0
\end{pmatrix}

ちゃんと二乗するとマイナス単位行列になる。もちろん、基底を組み替えたものに対応した、


  \begin{pmatrix}
  0 & 0 & 0 &  0 &  0 & -1 \\
  0 & 0 & 0 &  0 & -1 &  0 \\
  0 & 0 & 0 & -1 &  0 &  0 \\
  0 & 0 & 1 &  0 &  0 &  0 \\
  0 & 1 & 0 &  0 &  0 &  0 \\
  1 & 0 & 0 &  0 &  0 &  0
\end{pmatrix}

もちゃんとなるし、どちらかというとこっちの方が帰納的でしっくり来るだろう。

でも、最初の三次元の iを自分自身の i_3で置き換えると無限に行列の次元が増えていく。
世界の自己相似性に奇数次元であることが絡んでいると面白そうだなぁと思った次第である。

2GBの壁

*.f90に対して、64bit対応でcompileする分には問題無いが、それを32bitでcompileしたり、*.fの場合には静的メモリに2GBの制限が付くらしい。

relocation truncated to fit: R_X86_64_32S against *...
additional relocation overflows omitted from the output.

的なerrorが出る。
これを回避するには、compile optionに

-mcmodel=large

を付けると良いらしい。ちなみに-mcmodel=mediumにすると、データへの制限は無くなるが、実行ファイルへの2GBの制限は残るそうな。
しかし、これを付けたところで、大元のgfortranなりifortなりなんなりのライブラリーがこれらによってcompileされてなければそこで詰まる。
最近は数十GB超えのPC(workstation)はほぼ当たり前だし、数値計算用に購入したworkstation or serverなんかは100GBのメモリを超えてることはザラだろうから、この辺融通が効くといいなぁと思う次第である。

コーシー・シュワルツの不等式の幾何学的考察

「シュワルツの不等式」の判別式による導出に関する考察。

ちなみにシュワルツの不等式(ベクトルに)は(クーラントヒルベルトの「数理物理学の方法(上)」参照)
ベクトル \vec{a}, \vec{b}に対して、
 \displaystyle
  \vec{a} \cdot \vec{b} \leq |\vec{a}|^2 |\vec{b}|^2
が成り立つというものである。

ここではベクトルは実ベクトルに限定して話を進める。
 \displaystyle
  |\vec{a} x + \vec{b}|^2 = |\vec{a}|^2 x^2 + 2 \vec{a} {\cdot} \vec{b} x + |\vec{b}|^2 = 0
となる xを求めるときの条件として、 x複素数であることを課すと、 xについての二次方程式の判別式から不等式が得られる。
これを二次元実空間に限定してもうちょっと考える。

 \displaystyle
  |\vec{a} x + \vec{b}|^2 = 0

はつまり、「 \vec{a}を何倍かして \vec{b}に足したらゼロベクトルになるか」ということを聞いているのであって、そんなものは、 \vec{a} \vec{b}がもともと同じ方向の時、つまり線形従属の時しかないじゃん!というのが判別式のノリであり、その線形従属の時にのみ等号が成り立つ。
一方で、 x複素数のときには線形従属でなくてもベクトルの和がゼロになる場合があるということも示している。これは何を意味しているか?

 \vec{a} = (1, 0), \vec{b} = (0, 1)の最も単純な直交ベクトルを考えると、 x ^2 + 1 = 0、つまり x = \pm iである。
虚数をそのまま考えるとキツイが、実は iは二次元行列において90度回転を表している。  iの行列表現 I

 \displaystyle
I =
\begin{pmatrix}
0 & -1 \\
1 &  0
\end{pmatrix}

であり、二乗すると単位行列にマイナスがかかったものがちゃんと得られる。これは正に \theta = 90^{\circ}のときの回転行列に他ならない。
結局、ベクトルを回すという反則技を使えばどんなベクトルでも何倍かして足すとゼロに出来るわけで、まぁそうかという気がする。