最近、とある興味 *1 から量子力学(とりわけ量子化学)の勉強をしています。
水素原子の電子の軌道を計算すると、s軌道とかp軌道とかd軌道とかの計算が載っていて、対応する図が教科書に載っていたりしますよね。
こういうやつです:
個人的な体験ですが、予備校の頃は先生の影響で「化学」に大ハマりしていました *2。
ここから「Emanの物理学」というサイトの影響で「物理」に目覚め、そこからなぜか「数学」に目覚めて現在に至ります。そういった経緯もあって、化学には大変思い入れがあります。
特にこの水素原子の軌道の図は当時から気になっていて、自分で描いてみたいと思っていました。先日ようやく理解でき、実際に自分で描画できるまでになりました。以下がその画像です:
これはタイトルにもある「球面調和関数」と呼ばれる関数を可視化したものになっているのですが、この図を描くのは私の中でとても感動的な体験でした。
そこで今回の記事では上記の図の描き方を、実際に使ったプログラムを合わせて紹介したいと思います。図を描くにあたって私の中で新しく理解したことも多々ありましたので、そのノウハウも紹介したいと思います。
目次
目次:
今回の内容を理解するには量子力学に関する前提知識が必要です。
そこでセクション1〜3では、球面調和関数の背景として量子力学の基本的なところをざっとおさらいしたいと思います。その上で、水素原子のシュレーディンガー方程式の解として、球面調和関数 が現れることを紹介します。少し長くなりますので、既に内容をご存知の方は、セクション1〜3については適宜飛ばしていただいて問題ありません。
セクション4では、Pythonのmatplotlibを使って球面調和関数を実際に描画した様子を紹介します。一般に、球面調和関数は「複素関数」となってしまうので、「実関数」によって表示することが一般的で、その方法についても議論しています。
記事の一番最後のセクション5では、実際にプロットに使用したプログラムを紹介します。自分で書いてみたい方は活用していただければと思います。
1. 球面調和関数って?
ここでは、球面調和関数の背景として量子力学の基本的なところをざっとおさらいしたいと思います。
このセクションでは、水素原子のシュレーディンガー方程式を解くモチベーションの解説と、水素原子のシュレーディンガー方程式を解くことで今回の主役である球面調和関数が現れることを説明したいと思います。
シュレーディンガー方程式と波動関数
化学は、物質同士の化学反応を扱う学問です。実際の物質同士の反応の原因は、突き詰めていくとミクロな粒子(特に電子)同士の相互作用に還元されます。したがって、こうしたミクロな世界の挙動を統一的に扱う法則が必要になるわけです。
ミクロな世界においては、我々のサイズで行われる物理法則がそのまま適用できるわけではありません。ミクロな世界の粒子が従うのは「量子力学」です。
シュレーディンガー方程式 *3
とは、そんなミクロな世界を司る基本方程式です。電子などのミクロな物質の状態を表す波動関数 があり、それが満たす条件を表した方程式となっています。これを解くと電子の状態がわかるわけですね。
式 の右辺にある はエネルギーを表す実数であり、左辺の はハミルトニアンという線形演算子になっています。式の形だけに着目すると、波動関数にハミルトニアンという線形作用素を作用させると、波動関数が 倍されるという形式となっています。
この形はどこかで見たことがあるのではないでしょうか。典型的な固有値問題ですね!
波動関数 は一般に多粒子の状態を表すこともありますが、ここでは特に電子1粒子の状態を表すものだと考えましょう。3次元に置かれた電子の座標を とすると、波動関数は の関数 だと考えることができます。
このときハミルトニアン は、次のように表されます。
ここで、 は電子の質量、 はディラック定数(、 はプランク定数)、 はポテンシャルです。
要するに
なる方程式を解けば、電子の状態がわかるというわけですね。
特に、波動関数 は複素数の関数ですが、絶対値の二乗 は 電子が にいる確率密度 を表します。つまり、電子が微小体積 内にいる確率は で表されるというわけです。
ただし、 が確率密度であると考えるためには、これを全空間で積分した値が になっている必要があります。すなわち
が成り立つということです。
波動関数 がこのような条件を満たすように、波動関数にあらかじめ定数をかけておくことを 規格化 といいます。これで波動関数の絶対値の二乗が確率密度だと解釈できるようになります。
要するに量子力学によると、電子の位置は確定せず、 が表す確率密度に従って、空間上にぼんやりと存在するのですね。
また、ポテンシャル を変えれば、粒子の置かれる状況は変わるので、状況に応じてさまざまな解を取りうることになります。
水素原子のシュレーディンガー方程式
ところが現実的な問題を考えたときに、この方程式 を解析的に解ける状況は実はかなり限られます。
解くことができる有用な例としては、水素原子 があります。水素原子は、原子核に1個の養子があり、電子が1個回っているという非常に単純な形をしています。この状況下のシュレーディンガー方程式は解析的に解くことができます。
より一般に、「水素様原子」という「正の電荷を持った原子核が1つと電子1個」の状況においても、同様に厳密に解くことができます。登場人物が2個までだったら解けるというわけですね。
もっと一般的に、登場人物が3個以上の状況、たとえば電子が複数ある状況や、原子核が複数ある場合(分子の場合)を考えたくなりますが、そういう状況ではもはや複雑すぎて厳密に解くことができないわけです。
「なんだ、量子力学はその程度のことしかわからないのか」とがっかりするかもしれませんが、そうではありません。厳密には解けなくとも、近似的に応用上有用な結果を得ることもできます。
たとえば、厳密に解ける波動関数を使って、複数の原子核によって構成される分子の軌道を近似的に表すことができたりします。これを 分子軌道法 といいます。この方法では、厳密解として水素原子の解を用いることになります。分子軌道法については、いつかご紹介したいと思っています。
そういった意味でも、水素原子のケースで解くことは「単なる解ける一例」ということに留まらず、重要な意味を持つわけですね。
とはいえ、この水素原子のシュレーディンガー方程式、解くのはまったく簡単ではありません。今回のテーマである球面調和関数は、この水素原子の解を表すのに用いられるので、少し解き方を理解しておくことは重要です。
まず、水素原子は原子核1個と電子1個によって構成されます。原子核を原点におき、電子の位置(座標ベクトル)を で表します。
電子には、原子核との間のクーロン力が掛かっており、そのポテンシャルは原子核からの距離に反比例します。
このポテンシャルは、単純に原点からの距離に依存します。このような条件では、デカルト座標系 を用いるよりも、球面座標系 で表す方が多いです。
- は地球の半径を表す
- は緯度(北緯・南緯)を表す
- は経度(東経・西経)を表す
そこで、シュレーディンガー方程式を球面座標系 によって表すことにします。座標が陽に現れるのはハミルトニアンの部分なので、ここを書き換えることになります。
実際、シュレーディンガー方程式全体は、偏微分の変数変換を用いて次のように書き換えることができます:
おいおい、どんだけ複雑な方程式を解かせるのかと思うかもしれませんが、これで問題ありません。
変数分離
以下、実際に方程式 を解いていくことにします。細かい式変形が続きますが、この節と次の節はだいたい雰囲気がわかれば十分です。
方程式を解くにあたって特に重要なテクニックが 変数分離 です。波動関数は の3変数関数ですが、これを の関数と の関数の積だと考えるのです。
この式を元の方程式に代入することで、「 だけを変数に持つ方程式」と「 だけを変数に持つ方程式」に分離することができるのです。これが変数分離です。
実際、式 に代入すると
となります。 で割って少し整理すると
となります。
面白いことに、式 の左辺は だけの関数であり、右辺は の関数となっています。これを任意の で両立する関数は、定数関数しかありえません。
そこで、その定数を とおくと
という2つの偏微分方程式が得られます。これで変数を と に分離できましたね。
式 の解 を 動径波動関数 といい、式 の解 を 球面調和関数 と言います。
ようやく球面調和関数が出てきましたね!
動径波動関数 の絶対値の2乗は原点(原子核の位置)からの距離 の中でどこに電子が存在しやすいかを表しており、球面調和関数 の絶対値の2乗は方向 のどの方向に電子が存在しやすいかを表しています。
これを掛け合わしたものが波動関数 であり、その絶対値の2乗が空間上の確率密度を表すわけですね。
上の を「動径分布関数」と書いていましたが、「動径波動関数」に修正しました。
動径分布関数 は半径 の球殻に電子がいる確率密度を表す関数 だったようです。
今回の主役は球面調和関数なので、具体的な解を得るために式 を解きたいと思います。
さらに変数分離して
とすると式 は「 の関数 = の関数」の形に変形できるので、やはり定数関数となります。これを とおくと
という2つの式が得られます。
これで一通り変数分離できましたので、解くべき3つの方程式をまとめておきたいと思います。
2. 変数分離した式を解く
方程式を解きやすい形に分離できましたので、あとは1個ずつ解いていくことになります。
この節の内容は結構細かい計算が続きますが、その狙いは計算そのものではありません。方程式を解くに当たって、解には制約が現れ、「量子数」と呼ばれる整数が現れます。これを知ってもらいたいというのが狙いです。
方位角 φ についての方程式 (12) を解く
一番簡単に解けそうなのは式 です。実際
の形をした関数が解となるわけですね。
ただし、ここからが大変重要なポイントなのですが、この形をした関数がすべて解となるわけではありません。今、 は球面座標(地球で言うところの「経度」)を表しているので、周期性があります。すなわち
を満たす必要があるのですね。これが成立するためには、式 において が整数である必要があります。
したがって、整数 として
という形のものが解となるわけですね。この を磁気量子数 といいます。
定数を規格化しておくと( で積分して になるように定数 をとる)
が得られます。
つまり、今やったことを整理すると
が解を持つためには、 は整数 を用いて と表せる必要があり、その解は
と表せるということですね。
における固有値 に対応する解ということになります。
同じ固有値 に対する固有空間は、2次元のベクトル空間となっており、基底 と を用いて線形結合
として表せます。
つまり、上の式 の形の解は、同じ固有空間の基底を「たまたま」選んだものだということになります。本来は、線形結合すべてが解になるわけですが、その中から特別な基底を我々は選んで使っているというわけです。
基底の選び方には特に基準があるわけではないので、別の基底をとっても良いということに注意しましょう。これはあとで「実関数表示」を考えるにあたって必要なものとなります。
極角 θ についての方程式 (11) を解く
(元の式 に を代入したものを掲載しています。)
答えを言ってしまうと、次が方程式 の解となります:
「答えを言ってしまうと」と書いてしまいましたが、私自身はこの方程式 の解き方を知っているわけではありません。参考文献の数式を引用しています。いつか理解できればと思っています。
かなり複雑な関数に見えるかもしれませんが、実はそこまででもないので、じっくり説明していきます。
実際、解の因子を色分けしてみると
となっていて、オレンジ色の部分は単なる係数です。(規格化のための定数となっています。)
パラメータとして が入っていますが、これはやはり式 が解を持つための条件を考えたときに、出てくるものです。
式 には というパラメータがありましたが、( のときと同様)すべての で解を持つわけではありません。実は、整数 を用いて
と表せるときに限り、対応する解 を持つわけです。この を 方位量子数 といいます。
の本体は、実をいうと の部分だけです。 はルジャンドルの陪多項式と呼ばれるもので、定義は次の通りです:
これは複雑に見えますが、具体的に計算してみるとただの多項式(or そのルート)になることがわかるかと思います。
のとき | |
のとき | |
のとき | |
のとき |
これらに を代入して、 で積分したときに になるように係数を決めると、上の が得られるわけですね。
結局、球面調和関数は、整数の組 によって と表され、 と表されるというわけです。
改めて書くと次のように表せます。これが球面調和関数の具体的な形です。
動径 r についての方程式 (8) を解く
(元の式 に を代入したものを掲載しています。)
動径波動関数 についても同様に方程式 を解くことで解が得られます。
方程式 には、エネルギー というパラメータが入っていますが、やはりすべての に対して解を持つわけではありません。これについても、主量子数 という正の整数 に対応する についてのみ解を持つことになります。 は具体的には
という形になります。電子が水素原子にいる以上は、このような形のエネルギーしか取り得ないということを意味します。
これが エネルギーが飛び飛びの値をとる の意味するところです。
また
という関係も成り立つ必要があります。
3. 水素原子の原子軌道
議論がかなり長かったので、一旦まとめます。
量子数 に対応する波動関数を
と表す。 は動径波動関数、 は球面調和関数。
また、各量子数は次のような条件を満たす:
- は正の整数()
- は を満たす非負整数
- は を満たす整数(負の値もとる)
さらに、エネルギー は に対して次のように定まる:
したがって、エネルギーはとびとびの値をとる(これ以外の値をとることができない)。
がエネルギー最小で、 が大きくなるほど、エネルギーは単調増加する。
以上を踏まえて 原子軌道 という概念を導入します。原子軌道は単に 軌道 ということもあります。
水素原子においては、方程式を解く過程で量子数と呼ばれる整数の組が得られ、これらに対応する解しかもたないのでした。すなわち、水素原子の電子の波動関数は、量子数に対応するものしかないということですね。
そこで量子数の条件から、取り得る組み合わせを考えていきましょう。 について考えると、次のようになります:
主量子数 | 取り得る量子数の組 |
---|---|
のとき | の1つ |
のとき | の4つ |
のとき | の9つ |
これらの量子数の組一つ一つを軌道といいます。
エネルギーは、 が最小で、、 と大きくなるにつれて単調増加します。同じ主量子数の軌道においては、エネルギーはすべて等しくなります。
エネルギーの高低を踏まえて、水素原子の軌道を図示したものが次の図となります:
電子は基本的にはエネルギーが低いところに入るのがより安定となります。つまり、水素原子においては、 の状態にいるのが最も安定というわけですね。このような状態(もっとも安定な状態)のことを 基底状態 と言います。
逆に、基底状態よりもエネルギーが高い状態のことを 励起状態 といいます。たとえば、電子に電磁波が当たると、電磁波からエネルギーを受け取って励起状態に移ることがあります。このとき、取りうるエネルギーは のいずれかしかとれません。したがって、エネルギーの差がちょうど電磁波のエネルギーに一致するものしか吸収されないのです。
電磁波のエネルギーは ( は振動数)と表されるので、ちょうど振動数がぴったり一致するものしか吸収できないことが帰結されます。これは実験的事実とも合致します。
今は水素原子そのものを考えていますが、ポテンシャル の の部分を適当に変えれば、原子の個数を増やした原子核を作ることができます。つまり、原子核の電荷が であるような原子における電子 個の挙動を考えることができるわけですね。これが「水素様原子」です。これもまったく同じ軌道を有することになります。
さらに踏み込んで、電子をもっと増やしてみましょう。「電子を一つ一つ増やしていってもあまり状況は変わらないと仮定する」と、任意の原子の状況を再現できそうです。
2個目の電子ももっとも安定な という軌道に入ります。
では、3個目はというと、実は に入ります。面白いことにもっとも安定なはずの には入らないのです。いったいどういうことでしょう?
この背景には、パウリの排他律 という原理があります。
各軌道に対しては、それぞれ2つずつの状態があると考えることができます。これはスピンと呼ばれる、これまで説明しなかった第4の量子数が関係しています。
ここでは詳しく説明できませんが、電子には軌道の他にスピンという状態(上向きと下向きの2種類)があり、同じ軌道・同じスピンの状態をとることができないのです。
このように、軌道が埋まれば電子は上のエネルギーの軌道に入っていきます。同じ主量子数であれば、水素原子においては同じエネルギーでしたが、電子が増えるにつれて少しずつずれが生じてきます。多電子原子のエネルギーはおよそ次のようになります。
ところで、原子軌道にはもう少し馴染み深い表現がありますので、紹介します。
- 主量子数 の1つの軌道:K殻
- 主量子数 の4つの軌道:L殻
- 主量子数 の9つの軌道:M殻
まさに高校化学で習った用語ですね! 各軌道には2個ずつの電子が入ることになるので、「K殻・L殻・M殻にそれぞれ2個・8個・18個の電子が入る」ということになります。高校化学で習ったのは、こういうことだったわけですね。
さらに、方位量子数 に対しても、次のような名前がついています:
- のとき:s軌道
- のとき:p軌道
- のとき:d軌道
特に、主量子数に対応して次の表のような呼び方をします:
(K殻) | 1s軌道 | ー | ー |
---|---|---|---|
(L殻) | 2s軌道 | 2p軌道 | ー |
(M殻) | 3s軌道 | 3p軌道 | 3d軌道 |
エネルギーの図では、このようになります:
4. 球面調和関数の可視化
さて、ここまでで一通りの前提が説明し終わりました。少し長かったですがお疲れ様でした。
ここからが本題なのですが、原子軌道 に対応する波動関数 を可視化したいと思います。
しかしながら、波動関数 は3次元空間の点 に対して複素数を返す関数なので、かなり可視化するのが難しいものです。
そこで、 のことは一回忘れて「どの方向 に対して電子が多く分布しているのか」だけを考えたいと思います。ちょうど、波動関数 は
のように変数分離されており、 を定数だと思えば は一回忘れてしまっても良さそうです。
そこで、球面調和関数 を可視化しよう という発想になるわけです。「どっちの方向に電子が多く分布するのか」ということなので、電子の分布の形をおおよそ捉えることにも繋がるわけですね。こっちの方向に電子が偏っているので反応しやすそうだ、みたいなことがわかるわけです。
また、波動関数の絶対値の2乗は確率密度を表すのでした。したがって、各 について
をプロットしてみたら良さそうですね。
実際にプロットするにあたっては
として、 の値が大きいほど原点からの距離 が遠いところに点がプロットされるように描いてみましょう。
イメージがなかなか難しいと思うので、以下では具体的に描いてみましょう。この記事の最後にPythonのプログラムを載せましたので、自分で確認したい方はぜひご活用ください。
(以下の説明に使う図は、すべて同じプログラムで作成されています。)
l = 0 のとき(s軌道)
このときは、 しかとりませんので
をプロットしてみましょう。
球面調和関数を計算すると
となります。ずいぶんシンプルになりましたね。
よって
ということになります。
右辺は角度に依存しませんので、どちらの方向も偏りなく電子が分布していることになります。原点からの距離が一定値 をとるわけですから、球面ということになりますね。
実際、プロットするとこうなります:
これがs軌道の電子の分布の形状ということになります。勘違いしてはいけないのは、電子が図で表した球面上に張り付いているというわけではないということです。
この図はあくまで「どの方向に電子が多く分布しているのか」を表す図であるからです。原点からの距離には「(角度に対する)相対的な強度の違い」以上の意味はありません。
実際、空間上のどの位置に電子が分布しているのかどうかは、動径波動関数 との積によって決まってきます。
l = 1 のとき(p軌道)
のときは、p軌道というのでした。このとき、 の3つの軌道が存在します。
のときは比較的簡単です。具体的に代入すると
となることがわかります。絶対値の2乗をとって
を考えることになります。
右辺には がないので、 の方向(地球でいうと「経度」)については同じ値をとります。(図形としては回転体)
に対して となるわけですが、 なので「一回凹んでまた戻る」ような図になるはずです。
実際、描画してみるとこうなります:
予想した通りになっているのではないでしょうか。 軸方向にでっぱった「マラカス」みたいな形状ができています。これを 軌道ということにします。
赤と青の2色で色分けされていますが、これは絶対値を取る前の関数 の正負によって分けしています(正の領域は「赤」、負の領域は「青」)。今回は直接関係ありませんが、今後分子軌道を考える上では符号の正負は関係あります。
問題は と についてです。マラカスを 軸方向・ 軸方向に倒したような形状が期待されますが、そのままではそうなりません。
先ほど得られた解に を代入すると
となります。これらの絶対値をとると、どちらも同じ関数になってしまいます。
絶対値の二乗 を上に書いた方法でプロットすると、こうなります:
トーラスのような形状になりました。想定していた図とはちょっと違う感じになりますね。
冒頭で紹介したような図は、「実関数表示」というのを考えたものになります。
を計算したときのことを思い出しましょう。式 において に対応する部分は
になります。これらは固有方程式
の解です。これは固有値 に対応する固有空間の基底として、「たまたま」上の1組を選んだものとなっています。固有空間の中から基底はどのように選んでもよいわけです。
異なる基底をとるイメージ
これを踏まえて、球面調和関数の線形結合
を基底として採用することにしましょう。
計算すると
となります。
元々の表示 が複素関数だったのに対し、式 では 実関数 となっています。基底関数が実関数で表せるわけですから、これは嬉しいですね。式 のことを 実関数表示 と呼びます。
というわけで、実関数表示した球面調和関数の絶対値の二乗を、これまでと同様の方法でプロットしてみましょう。
つまり
をプロットするわけですね。
実際にプロットしたのが次の図です:
左側は 軸方向に「マラカス」みたいな形状ができていますので 軌道、右側は 軸方向なので 軌道といいます。
というわけで、よくあるp軌道の図はこのように書けるわけですね!
l = 2 のとき(d軌道)
d軌道について考えましょう。 のとき、 の5通りとなります。対応する球面調和関数は次の5つです。
については複素関数となっていますので、実関数表示を考えましょう。
については同じ固有空間に属するので、次の線形結合を考えます:
についても同様に次の線形結合を考えます:
そんなわけで、以下の5つの実関数表示をプロットすることになります。
これらの絶対値の二乗をとってプロットすると、次のようになります:
慣習にしたがって、上から順に と呼びます。
これらがd軌道の形ということですね!
5. Pythonのmatplotlibを使ったプログラム
最後に今回作ったプログラムを紹介しましょう。
まず、このプログラムはPython 3を想定して作っています。また、以下の2つのライブラリをインストールする必要があります:
- numpy
- matplotlib
以下が今回描画に使ったプログラムです。
import numpy as np import matplotlib.pyplot as plt import mpl_toolkits.mplot3d.axes3d as axes3d import math # 球面調和関数(ただし、実関数表示したもの) def spherical_harmonics(theta, phi, l, m): if l == 0: if m == 0: # l=0, m=0 return np.sqrt(1.0/(4*np.pi)) if l == 1: if m == 0: # l=1, m=0 return np.sqrt(3.0/(4.0*np.pi)) * np.cos(theta) if m == 1: # l=1, m=+1 return np.sqrt(3.0/(4.0*np.pi)) * np.sin(theta) * np.cos(phi) if m == -1: # l=1, m=+1 return np.sqrt(3.0/(4.0*np.pi)) * np.sin(theta) * np.sin(phi) if l == 2: if m == 0: return np.sqrt(5.0/(16.0*np.pi)) * (3.0*(np.cos(theta)**2) - 1.0) if m == 1: return np.sqrt(15.0/(4.0*np.pi)) * np.cos(theta) * np.sin(theta) * np.cos(phi) if m == -1: return np.sqrt(15.0/(4.0*np.pi)) * np.cos(theta) * np.sin(theta) * np.sin(phi) if m == 2: return np.sqrt(15.0/(16.0*np.pi)) * (np.sin(theta)**2) * np.cos(2*phi) if m == -2: return np.sqrt(15.0/(16.0*np.pi)) * (np.sin(theta)**2) * np.sin(2*phi) names = [["s"], ["p_y", "p_z", "p_x"], ["d_{xy}", "d_{yz}", "d_{z^2}", "d_{zx}", "d_{x^2-y^2}"]] theta, phi = np.linspace(0, np.pi, 40), np.linspace(0, 2 * np.pi, 80) THETA, PHI = np.meshgrid(theta, phi) for l in range(3): for m in range(-l,l+1): fig = plt.figure(figsize=(4.0, 4.0)) ax = fig.add_subplot(1,1,1, projection='3d') # 図のタイトルをイイ感じの場所に ax.set_title("{}".format( names[l][l+m] ), y=-0.15, size = 18) R = spherical_harmonics(THETA, PHI, l, m)**2 X = R * np.sin(THETA) * np.cos(PHI) Y = R * np.sin(THETA) * np.sin(PHI) Z = R * np.cos(THETA) # 軸の設定 ax.set_xlabel("x", size = 14) ax.set_ylabel("y", size = 14) ax.set_zlabel("z", size = 14) # x,y,zの表示範囲を設定 ax.set_xlim3d(-0.25,0.25) ax.set_ylim3d(-0.25,0.25) ax.set_zlim3d(-0.25,0.25) # 色付けのルールを設定 colortuple = ('r','b') COLORS = np.empty(THETA.shape, dtype=str) for y in range(PHI.shape[1]): for x in range(PHI.shape[0]): th = THETA[x,y] ph = PHI[x,y] if spherical_harmonics(th, ph, l, m) > 0: # 球面調和関数の値が正であれば「赤」 COLORS[x, y] = colortuple[0] else: # 球面調和関数の値が負であれば「青」 COLORS[x, y] = colortuple[1] # (l, m) に対応するグラフをプロット plot = ax.plot_surface( X, Y, Z,facecolors=COLORS, rstride=1, cstride=1, linewidth=0, antialiased=False, alpha=0.5) # ファイルを保存する plt.savefig("{}.jpg".format(names[l][l+m]),dpi=240) # グラフを表示 plt.show()
上記のPythonコードを実行すると、同じディレクトリに画像が9枚生成されます。
このプログラムは
- 球面調和関数の定義(spherical_harmonics関数)
- 定義した関数を使ってグラフを描画する
という部分によって構成されています。
球面調和関数の定義の部分についてですが、今回は球面調和関数の手計算による計算結果を直接spherical_harmonics関数内に記述する形を取りました。
これだと一般の について計算できないわけですが、実際ルジャンドル陪多項式を計算するのは結構面倒なのでこのようにしています。
多項式の微分を計算しているだけなので、もう少しがんばればできそうな気もしますが、今回はやめておきます。
書いたあとで気づいたのですが、実はscipyというライブラリでは、球面調和関数 を直接計算してくれる関数があります。
docs.scipy.org
すごいですね! 便利な世の中になったものです。
(ちなみに、ルジャンドル陪多項式自体もscipyで計算できます!)
ただし、scipyで計算されるのは「複素関数」なので、今回やったように実関数に直してあげる必要があります。その点に注意してお使いください。
上記のコードは、グラフごとに画像を1枚ずつ生成するコードでしたが、以下はすべてをまとめて1枚の画像としてプロットするためのコードです。add_subplotをつかって、縦3×横5のグラフを生成するように変更しています。
import numpy as np import matplotlib.pyplot as plt import mpl_toolkits.mplot3d.axes3d as axes3d import math # 球面調和関数(ただし、実関数表示したもの) def spherical_harmonics(theta, phi, l, m): if l == 0: if m == 0: # l=0, m=0 return np.sqrt(1.0/(4*np.pi)) if l == 1: if m == 0: # l=1, m=0 return np.sqrt(3.0/(4.0*np.pi)) * np.cos(theta) if m == 1: # l=1, m=+1 return np.sqrt(3.0/(4.0*np.pi)) * np.sin(theta) * np.cos(phi) if m == -1: # l=1, m=+1 return np.sqrt(3.0/(4.0*np.pi)) * np.sin(theta) * np.sin(phi) if l == 2: if m == 0: return np.sqrt(5.0/(16.0*np.pi)) * (3.0*(np.cos(theta)**2) - 1.0) if m == 1: return np.sqrt(15.0/(4.0*np.pi)) * np.cos(theta) * np.sin(theta) * np.cos(phi) if m == -1: return np.sqrt(15.0/(4.0*np.pi)) * np.cos(theta) * np.sin(theta) * np.sin(phi) if m == 2: return np.sqrt(15.0/(16.0*np.pi)) * (np.sin(theta)**2) * np.cos(2*phi) if m == -2: return np.sqrt(15.0/(16.0*np.pi)) * (np.sin(theta)**2) * np.sin(2*phi) names = [["s"], ["p_y", "p_z", "p_x"], ["d_{xy}", "d_{yz}", "d_{z^2}", "d_{zx}", "d_{x^2-y^2}"]] theta, phi = np.linspace(0, np.pi, 40), np.linspace(0, 2 * np.pi, 80) THETA, PHI = np.meshgrid(theta, phi) fig = plt.figure(figsize=(12.0, 9.0)) for l in range(3): for m in range(-l,l+1): # 3x5のサブプロット(左から順にm=-lからm=lまでプロットする) ax = fig.add_subplot(3,5,3+m+5*l, projection='3d') # 図のタイトルをイイ感じの場所に ax.set_title("{}".format( names[l][l+m] ), y=-0.35) R = spherical_harmonics(THETA, PHI, l, m)**2 X = R * np.sin(THETA) * np.cos(PHI) Y = R * np.sin(THETA) * np.sin(PHI) Z = R * np.cos(THETA) # x,y,zの表示範囲を設定 ax.set_xlim3d(-0.25,0.25) ax.set_ylim3d(-0.25,0.25) ax.set_zlim3d(-0.25,0.25) # 色付けのルールを設定 colortuple = ('r','b') COLORS = np.empty(THETA.shape, dtype=str) for y in range(PHI.shape[1]): for x in range(PHI.shape[0]): th = THETA[x,y] ph = PHI[x,y] if spherical_harmonics(th, ph, l, m) > 0: # 球面調和関数の値が正であれば「赤」 COLORS[x, y] = colortuple[0] else: # 球面調和関数の値が負であれば「青」 COLORS[x, y] = colortuple[1] # (l, m) に対応するグラフをプロット plot = ax.plot_surface( X, Y, Z,facecolors=COLORS, rstride=1, cstride=1, linewidth=0, antialiased=False, alpha=0.5) plt.savefig("Y.jpg",dpi=240) plt.show()
実行すると次のようになります。
これが冒頭で紹介した図ですね!
私もついに球面調和関数を自分で描けるようになったのかと感激しています。
こういう図って、教科書にも載っていますし、誰かしら自分で描いたものを公開している人もいるものなので、「わざわざ自分で作る意味とは?」という感じに思ってしまうかもしれません。
こういうのって、いわゆる「車輪の再発明」だと思います。一般に、車輪の再発明はネガティブなイメージで語られることが多いですが、私はそんなに悪くないと思うのですね。
少なくとも私自身はこれを描いたことで、量子力学に関して理解が深まりました。「実関数表示の意味」については、自分で描いてみなければ一生わからなかったなと思っています。その意味では、自分自身にとっては確実にプラスになっていると思います。
そんなわけで、こういう風に自分で図を描いて理解するという楽しみ方もあるんじゃないかなと思っています。よろしければ、一緒に楽しんでみてください。
それでは今日はこの辺で!
参考文献
最後に、この記事を書くにあたって参考にしたサイト・本をご紹介します。
まずは Emanの物理学 です。このサイトは私が学部の1・2年生の頃に大変お世話になったサイトです。まず電磁気学で分からなかったところをこのサイトで勉強し、そして相対性理論に興味を持ち、量子力学に出会い、・・・と。このサイトのおかげで物理にドハマりすることになりました。
今回直接関連するのは、こちらの「原子の構造」という記事です。学部時代に何回も読んだページでした。
eman-physics.net
もう一つ参考になったのは、こちらの本です。
今回の記事の先にある分子軌道論を勉強するために手に取ったのですが、量子力学の基本的なところから丁寧に解説されていて、とても良い本でした。購入して一気に最初から最後まで夢中になって読んでしまうほど。
近いうちにこの本で勉強した内容を元に、より発展的な話も記事にしたいと思っています。
すでにPythonで球面調和関数の可視化を行っているこちらのページも参考になりました。
takuyaokada.hatenablog.com
*1:そのうちブログでも書きたいと思っています。
*2:その頃のエピソードについては、以前記事にしたことがありました: tsujimotter.hatenablog.com
*3:詳しい人向けにいうと、式 は正確には「時間に依存しないシュレーディンガー方程式」と呼ぶべきものです。本来は、時間 についての一階微分を含む偏微分方程式が本来のシュレーディンガー方程式であり、その解を時刻と座標で「変数分離」して得られたものが式 となります。