例えば2p軌道とかのp軌道の場合、一電子状態は以下のどれかに対応する。
(1,u), (1, d), (0, u), (0, d), ( -1, u), ( -1, d)
これを、binary形式、「電子がいる軌道=1」、「電子がいない軌道=0」とすれば、例えば、(1,u)と(1, d)が占有されているとき、
110000
と表すことが出来る。
軌道に電子を足す操作を、バイナリーの操作にそのまま置き換えることが出来るので、電子数と軌道を指定したときの全電子配置を機械的に求めることが出来る。
なので試しにpythonでやってみた。pythonでのbinary演算は以下のサイトを参照した。
Python ビット演算 超入門
以下、関数の説明。
- binary_configuration:軌道角運動量、磁気量子数、スピン(up=1 or down=0)から値を作る。
- check_unoccupied:与えた電子配置bにおいて、(軌道角運動量の)磁気量子数、スピン(up=1 or down=0)に電子がいなければTrueを返す。
- check_unpair:与えた電子配置bにおいて、(軌道角運動量の)磁気量子数にdownスピンを置こうとしたときに、upスピンがいなければTrueを返す。
- check_highest_m:与えた電子配置bにおいて、占有されている軌道の中で最大の磁気量子数を返す。
- add_electron:与えた電子配置のリストの各要素に対して、電子を一つ加えたときに取り得る電子配置を求めて、新しいリストに格納する。
気をつけたところとしては、
- 同じ配置を数えないように、次に足す電子は必ず前の配置の電子の磁気量子数以上の軌道に入れるようにした。
- 電子のペアを作る時には、前の電子がdownスピンの時にのみ作るようにした。
以下ソースコード。
def binary_configuration( l, m, ms ): return 2**( int( 2 * ( m + l ) + ms ) ) def check_unoccupied( b, l, m, ms ): return b & bin_configuration( l, m, ms ) == 0 def check_unpair( b, l, m, ms ): if ms == 0: # down spin return b & bin_configuration( l, m, ms + 1 ) == 0 # check up spin else: return True def check_highest_m( b, l ): highest_m = -l for m in range( -l , l + 1 ): if b & ( 0b11 << 2 * ( m + l ) ) != 0: highest_m = m return highest_m def add_electron( configurations0, l ): configurations = [] if configurations0 == []: for m in range( -l, l + 1 ): for ms in ( 0, 1 ): configurations.append( binary_configuration( l, m, ms ) ) else: for conf0 in configurations0: m0 = check_highest_m( conf0, l ) for m in range( -l, l + 1 ): if m < m0: continue for ms in ( 0, 1 ): if check_unoccupied( conf0, l, m, ms ) \ & check_unpair( conf0, l, m, ms ): configurations.append( conf0 | binary_configuration( l, m, ms ) ) return configurations l = 3 # 0 : s, 1 : p, 2 : d, 3 : f number_electrons = 7 conf = [] for i in range( number_electrons ): conf = add_electron( conf, l ) #print( list( map( bin, conf ) ) ) print( len( conf ) )
試しにGdのに対してやってみたところ、がちゃんと返ってきた。
ここから多重項を求められると楽しそうに思う。