EffectiveMass.py ダウンロード/コピー

EffectiveMass.py をダウンロード

EffectiveMass.py
EffectiveMass.py
  1"""
  2概要:
  3    バンド構造から有効質量と運動量空間の波数kの関係を計算します。
  4詳細説明:
  5    このスクリプトは、CSVファイルからバンド構造データ(運動量空間の波数kとエネルギーE)を読み込みます。
  6    読み込んだデータを用いて、エネルギーの運動量空間の波数kに対する二階微分を計算し、そこから有効質量を導出します。
  7    有効質量の計算では、異なる差分幅(nskip)を使用して二階微分を評価し、結果をプロットに表示します。
  8    計算された有効質量の逆数が特定の閾値を超えた場合、プロット上でデータの連続性を分断する処理が含まれます。
  9    最終的なプロットは、有効質量と運動量空間の波数kの関係を示します。
 10主な機能:
 11    - CSVファイルからのバンド構造データの読み込み
 12    - エネルギーの二階微分に基づいた有効質量の計算
 13    - 異なる差分幅での有効質量計算の比較
 14    - matplotlibによる結果のグラフ表示
 15関連リンク:
 16    EffectiveMass_usage
 17"""
 18import sys
 19import numpy as np
 20from numpy import sqrt, exp, sin, cos, tan, pi
 21import numpy.linalg as LA 
 22import csv
 23from matplotlib import pyplot as plt
 24
 25
 26#===================================
 27# physical constants
 28#===================================
 29pi   = 3.14159265358979323846
 30pi2  = 2.0 * pi
 31h    = 6.6260755e-34    # Js";
 32hbar = 1.05459e-34      # "Js";
 33c    = 2.99792458e8     # m/s";
 34e    = 1.60218e-19      # C";
 35e0   = 8.854418782e-12; # C<sup>2</sup>N<sup>-1</sup>m<sup>-2</sup>";
 36kB   = 1.380658e-23     # JK<sup>-1</sup>";
 37me   = 9.1093897e-31    # kg";
 38R    = 8.314462618      # J/K/mol
 39a0   = 5.29177e-11      # m";
 40
 41
 42#===================================
 43# parameters
 44#===================================
 45a = 4.0e-10 #m
 46
 47infile = 'band.csv'
 48cutline = 1
 49
 50#===================================
 51# figure configuration
 52#===================================
 53fontsize        = 12
 54legend_fontsize = 8
 55
 56
 57#=============================
 58# other functions
 59#=============================
 60def savecsv(outfile, header, datalist):
 61    """
 62    概要:
 63        リストのリスト形式のデータをCSVファイルに保存します。
 64    詳細説明:
 65        指定されたファイル名でCSVファイルを開き、ヘッダー行を書き込んだ後、datalistの各要素を列として、
 66        行ごとにデータを書き込みます。ファイル書き込みに失敗した場合はエラーメッセージを表示します。
 67    引数:
 68        :param outfile: 出力するCSVファイルのパスとファイル名。
 69        :type outfile: str
 70        :param header: CSVファイルのヘッダー行の文字列のリスト。
 71        :type header: list of str
 72        :param datalist: 出力するデータを含むリストのリスト。各内部リストは1つの列に対応します。
 73                         例: [[col1_data1, col1_data2], [col2_data1, col2_data2]]
 74    戻り値:
 75        :returns: なし
 76        :rtype: None
 77    """
 78    try: 
 79        print("Write to [{}]".format(outfile))
 80        f = open(outfile, 'w')
 81    except:
 82#    except IOError:
 83        print("Error: Can not write to [{}]".format(outfile))
 84    else:
 85        fout = csv.writer(f, lineterminator='\n')
 86        fout.writerow(header)
 87#        fout.writerows(data)
 88        for i in range(0, len(datalist[0])):
 89            a = []
 90            for j in range(len(datalist)):
 91                a.append(datalist[j][i])
 92            fout.writerow(a)
 93        f.close()
 94
 95
 96def read_csv(fname):
 97    """
 98    概要:
 99        指定されたCSVファイルから数値データを読み込みます。
100    詳細説明:
101        CSVファイルをオープンし、最初の行をラベルとして読み込みます。
102        残りの行から2列のデータを浮動小数点数として読み取り、それぞれのリストに格納します。
103        数値変換に失敗した行は警告メッセージを表示してスキップします。
104    引数:
105        :param fname: 読み込むCSVファイルのパスとファイル名。
106        :type fname: str
107    戻り値:
108        :returns: 1列目のラベル文字列、2列目のラベル文字列、1列目のデータリスト、2列目のデータリストのタプル。
109        :rtype: tuple of (str, str, list of float, list of float)
110    """
111    x = []
112    y = []
113    with open(fname) as f:
114        fin = csv.reader(f)
115        labels = next(fin)
116        xlabel = labels[0]
117        ylabel = labels[1]
118        for row in fin:
119            try:
120                x.append(float(row[0]))
121                y.append(float(row[1]))
122            except:
123                print("Warning: Invalid float data [{}] or [{}]".format(row[0], row[1]))
124
125    return xlabel, ylabel, x, y
126
127
128def main():
129    """
130    概要:
131        有効質量と運動量空間の波数kの関係を計算し、結果をプロットします。
132    詳細説明:
133        `infile` で指定されたCSVファイルからバンド構造データ(運動量空間の波数kとエネルギーE)を読み込みます。
134        波数kの差分dkとエネルギーEを用いて、エネルギーの運動量空間の波数kに対する二階微分を計算し、
135        そこから有効質量を導出します。
136        異なる差分幅(nskip = 1とnskip = 4)で二階微分を計算し、それぞれ有効質量を求めます。
137        有効質量の逆数 abs(minv) が 1.0e20 以下の場合は、有効質量のデータとして None を格納し、
138        プロット上でデータの連続性を分断します (cutline が 1 の場合)。
139        また、有効質量の符号が反転した場合もプロットを分断します。
140        最終的に、計算された有効質量を電子の静止質量 me で正規化し、
141        matplotlib を用いて運動量空間の波数kに対する正規化有効質量をプロットし、表示します。
142    引数:
143        :param なし: この関数は引数を取りません。
144    戻り値:
145        :returns: なし
146        :rtype: None
147    """
148    klabel, Elabel, k, E = read_csv(infile)
149    print("k=", k)
150    print("E=", E)
151
152    nk = len(k)
153    dk = k[1] - k[0]
154
155    km = hbar * hbar * (pi2 / a)**2.0
156    nskip = 1
157    xk  = []
158    ymc = []
159    signprev = None
160    print("")
161    print("Differentiate for nskip = ", nskip)
162    print("i    E[i-1]  E[i]    E[i+1]  1.0/m*")
163    for i in range(nskip, nk - nskip, nskip):
164        d2Edk2c = (E[i+nskip] + E[i-nskip] - 2 * E[i]) * e / pow(nskip * dk, 2.0)
165        minv = d2Edk2c / km
166        print(i, E[i-1], E[i], E[i+1], minv)
167        if abs(minv) <= 1.0e20:  # << 1.0/me ~ 1e30 
168            if cutline:
169                xk.append(k[i])
170                ymc.append(None)
171            signprev = -signprev
172            continue
173        else:
174            m = km / d2Edk2c
175
176        if signprev is None:
177            signprev = m
178        elif signprev * m < 0.0:
179            if cutline:
180                xk.append(k[i])
181                ymc.append(None)
182            signprev = m
183
184        xk.append(k[i])
185        ymc.append(m / me)
186
187    nskip = 4
188    xk2  = []
189    ymc2 = []
190    signprev = None
191    print("")
192    print("Differentiate for nskip = ", nskip)
193    print("i    E[i-1]  E[i]    E[i+1]  1.0/m*")
194    for i in range(nskip, nk - nskip, nskip):
195        d2Edk2c = (E[i+nskip] + E[i-nskip] - 2 * E[i]) * e / pow(nskip * dk, 2.0)
196        minv = d2Edk2c / km
197        print(i, E[i-1], E[i], E[i+1], minv)
198        if abs(minv) <= 1.0e20:  # << 1.0/me ~ 1e30 
199            if cutline:
200                xk2.append(k[i])
201                ymc2.append(None)
202            signprev = -signprev
203            continue
204        else:
205            m = km / d2Edk2c
206
207        if signprev is None:
208            signprev = m
209        elif signprev * m < 0.0:
210            if cutline:
211                xk2.append(k[i])
212                ymc2.append(None)
213            signprev = m
214
215        xk2.append(k[i])
216        ymc2.append(m / me)
217
218    plt.plot(xk,  ymc,  linewidth = 0.5, marker = 'o', markersize = 1.0, label = 'nskip = 1')
219    plt.plot(xk2, ymc2, linewidth = 0.5, marker = 'o', markersize = 1.0, label = 'nskip = 2')
220    plt.xlabel(klabel)
221    plt.ylabel("m$_e$ / m$_e^0$")
222    plt.xlim([-0.5, 0.5])
223#    plt.ylim([-0.5, 0.5])
224    plt.tight_layout()
225    
226    plt.pause(0.1)
227    print("Press ENTER to exit>>", end = '')
228    input()
229
230
231if __name__ == "__main__":
232    main()