################################################################# ## クローニッヒ・ペニーモデルのエネルギーバンド ################################################################# import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ###################################### # 物理定数 ###################################### #プランク定数 h = 6.6260896 * 10**-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.10938215 * 10**-31 #電子ボルト eV = 1.60217733 * 10**-19 ###################################### # 物理系の設定 ###################################### #空間刻み間隔 nm = 1E-9 #井戸の形状 d1 = 1.5 * nm d2 = 1.0 * nm #周期 l = d1 + d2 #井戸の深さ V1 = 0 * eV V2 = -10.0 * eV ###################################### # 転送行列の計算 ###################################### def TransferMatrix( k, n = 0 ): #各領域の波数 k1 = np.sqrt(np.complex128( k**2 - 2.0 * me * V1 / hbar**2 )) k2 = np.sqrt(np.complex128( k**2 - 2.0 * me * V2 / hbar**2 )) # 転送行列の定義 T1 = np.zeros((2,2), dtype=np.complex) T2 = np.zeros((2,2), dtype=np.complex) M21 = np.zeros((2,2), dtype=np.complex) M12 = np.zeros((2,2), dtype=np.complex) # 境界 M21[0][0] = (1.0 + 0.0j + k1 / k2) / 2.0 M21[0][1] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][0] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][1] = (1.0 + 0.0j + k1 / k2) / 2.0 M12[0][0] = (1.0 + 0.0j + k2 / k1) / 2.0 M12[0][1] = (1.0 + 0.0j - k2 / k1) / 2.0 M12[1][0] = (1.0 + 0.0j - k2 / k1) / 2.0 M12[1][1] = (1.0 + 0.0j + k2 / k1) / 2.0 T1[0][0] = np.exp( I * k1 * d1 ) T1[0][1] = 0 T1[1][0] = 0 T1[1][1] = np.exp( - I * k1 * d1 ) T2[0][0] = np.exp( I * k2 * d2 ) T2[0][1] = 0 T2[1][0] = 0 T2[1][1] = np.exp( - I * k2 * d2 ) #転送行列の計算 M = M12 @ T2 @ M21 @ T1 for _n in range(n): M = M @ M #転送行列 return M ################################################################# ## クローニッヒ・ペニーのモデルの分散関係 ################################################################# #計算点数 NK = 1000000 #エネルギーの計算範囲 E_min = 1.0/NK E_max = 4.0 #エネルギーの行列 Es = np.linspace(E_min, E_max, NK) #y値配列 ys = [] #Kl値配列と対応するエネルギー配列 Kls = [] EBs = [] #バンド番号 bn = 0 #Kl値配列と対応するエネルギー配列 BandEdgeEs = [] BandCenterEs = [] #バンド番号 BandEdgeNumber = 0 BandCenterNumber = 0 #バンド内フラグ flag_out = True flag_center = False sign = 0 for E in Es: E = E * eV #波数の計算 k = np.sqrt(np.complex128( 2.0 * me * E / hbar**2 )) M = TransferMatrix( k ) y = ( M[0][0] + M[1][1]) / 2.0 ys.append( y.real ) if( abs(y.real) <= 1.0 ): if( flag_out == True ): flag_out = False BandEdgeEs.append( E/eV ) Kls.append([]) EBs.append([]) Kl = np.arccos( y.real ) Kls[ bn ].append( Kl / np.pi ) EBs[ bn ].append( E / eV ) if( sign * y.real/abs(y.real) < 0 ): BandCenterEs.append( E/eV ) sign = y.real/abs(y.real) else: if( flag_out == False ): flag_out = True bn += 1 BandEdgeEs.append( E/eV ) print(BandEdgeEs) print(BandCenterEs) ################################################################# ## 転送行列のトレース ################################################################# plt.title( r"$y=\frac{1}{2}{\rm Tr} (M)$" + u"(" + r"$l=2.5[{\rm nm}]$" + " , " + r"$d=1.0[{\rm nm}]$"+ " , " + r"$V=-10.0[{\rm eV}]$" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$E$" + r"$[{\rm eV}]$" , fontsize=20) plt.ylabel(r"$y(E)$", fontsize=20) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([0, 4]) plt.ylim([-2.5, 2.5]) #壁の描画 plt.hlines([-1], 0, 10, "blue", linestyles='dashed', linewidth = 3 ) plt.hlines([1], 0, 10, "blue", linestyles='dashed', linewidth = 3 ) #トレース値のグラフの描画 plt.plot(Es, ys, linestyle='solid', linewidth = 5) ################################################################# ## クローニッヒ・ペニーのモデルのエネルギーバンド ################################################################# fig2 = plt.figure(figsize=(15, 8)) plt.title( u"クローニッヒ・ペニーモデルのエネルギーバンド(" + r"$l=2.5[{\rm nm}]$" + " , " + r"$d=1.0[{\rm nm}]$"+ " , " + r"$V=-10.0[{\rm eV}]$" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.ylabel(r"$E$" + r"$[{\rm eV}]$" , fontsize=20) plt.xlabel(r"$Kl/\pi$", fontsize=20) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([0, 1]) plt.ylim([0, 4]) #分散関係の描画 for n in range(bn): plt.plot(Kls[n], EBs[n], linewidth = 5, color = colors[0]) #グラフの表示 plt.show()
【第14話】箱型の障壁へ照射した電子パルスの運動【Pythonコピペで量子力学完全攻略マニュアル】
################################################################# ## 箱型障壁へ照射したガウス波束の時間発展 ################################################################# import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ###################################### # 物理定数 ###################################### #プランク定数 h = 6.6260896 * 10**-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.10938215 * 10**-31 #電子ボルト eV = 1.60217733 * 10**-19 ###################################### # 物理系の設定 ###################################### #波束の中心エネルギー E0 = 20.0 * eV #重ね合わせの数 NK = 200 #ガウス分布の幅 sigma = 2 / ( 1.25 * 10**-9 ) #波数の間隔 dk = 10.0 * sigma / NK #ガウス分布の中心波数 k0 = np.sqrt( 2.0 * me * E0 / hbar**2) #計算時間の幅 ts = 0 te = 1000 #時間間隔 dt = 0.05 * 10**-16 #空間刻み間隔 nm = 1E-9 #壁の厚さ d = 0.2 * nm #壁の高さ V1 = 0.0 * eV V2 = 40.0 * eV V3 = 0.0 * eV ###################################### # 反射係数と透過係数を計算する関数定義 ###################################### def ReflectionCoefficient( MM ): return - MM[1][0] / MM[1][1] def TransmissionCoefficient(MM): return (MM[0][0] * MM[1][1] - MM[0][1] * MM[1][0] ) / MM[1][1] def calculateCoefficient( k1, k2, k3 ): #反射係数と透過係数の計算 # 転送行列の定義 M21 = np.zeros((2,2), dtype=np.complex) T2 = np.zeros((2,2), dtype=np.complex) M32 = np.zeros((2,2), dtype=np.complex) # 境界 M21[0][0] = (1.0 + 0.0j + k1 / k2) / 2.0 M21[0][1] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][0] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][1] = (1.0 + 0.0j + k1 / k2) / 2.0 M32[0][0] = (1.0 + 0.0j + k2 / k3) / 2.0 M32[0][1] = (1.0 + 0.0j - k2 / k3) / 2.0 M32[1][0] = (1.0 + 0.0j - k2 / k3) / 2.0 M32[1][1] = (1.0 + 0.0j + k2 / k3) / 2.0 T2[0][0] = np.exp( I * k2 * d ) T2[0][1] = 0 T2[1][0] = 0 T2[1][1] = np.exp( - I * k2 * d ) #転送行列の計算 M31 = M32 @ T2 @ M21; #反射係数と透過係数の計算 rc = ReflectionCoefficient(M31); tc = TransmissionCoefficient(M31); #領域2の係数 A2_p = M21[0][0] * 1.0 + M21[0][1] * rc A2_m = M21[1][0] * 1.0 + M21[1][1] * rc return rc, tc, A2_p, A2_m ###################################### # 波動関数の計算 ###################################### #ガウス波束の初期位置 x0 = -3.0 * nm #描画範囲 x_min = -5.0 * nm x_max = 5.0 * nm #描画区間数 NX = 500 #座標点配列の生成 x1 = np.linspace(x_min, 0, NX) x2 = np.linspace(0, d, 5) x3 = np.linspace(d, x_max, NX) #ガウス波束の値を計算する関数 def Psi( x, t, region ): #波動関数値の初期化 psi = x * (0.0 + 0.0j) #各波数ごとの寄与を足し合わせる for kn in range(NK): #各波数を取得 k = k0 + dk * (kn - NK/2) E = (hbar * k)**2 / (2.0 * me) #波数から各振動数を取得 omega = hbar / (2.0 * me) * k**2 #各領域の波数 k1 = np.sqrt(np.complex128( 2.0 * me * (E - V1) / hbar**2 )) k2 = np.sqrt(np.complex128( 2.0 * me * (E - V2) / hbar**2 )) k3 = np.sqrt(np.complex128( 2.0 * me * (E - V3) / hbar**2 )) #係数の取得 rc, tc, A2_p, A2_m = calculateCoefficient( k1, k2, k3 ) #ガウス分布 Ck = np.exp( - I * k1 * x0 ) * np.exp( -( (k - k0) / (2.0 * sigma) )**2 ) #平面波を足し合わせる if(region == 1): #入射波と反射波と透過波 psi_I = np.exp( I * k1 * x - I * omega * t ) psi_R = rc * np.exp( - I * k1 * x - I * omega * t ) psi += (psi_I + psi_R) * Ck elif(region == 2): psi2_p = A2_p * np.exp( I * k2 * x - I * omega * t ) psi2_m = A2_m * np.exp( - I * k2 * x - I * omega * t ) psi += (psi2_p + psi2_m) * Ck elif(region == 3): psi_T = tc * np.exp( I * k3 * ( x - d ) - I * omega * t ) psi += psi_T * Ck return psi #基準となる振幅を取得 psi_abs = abs(Psi( x0, 0, 1 )) ################################################################# ## ガウス波束の時間発展アニメーションの作成 ################################################################# #アニメーション作成用 ims=[] #各時刻における計算 for tn in range(ts, te + 1): t = dt * tn #波動関数の計算 psi1 = Psi( x1, t, 1 ) / psi_abs psi2 = Psi( x2, t, 2 ) / psi_abs psi3 = Psi( x3, t, 3 ) / psi_abs #各コマを描画 img = plt.plot(x1/nm, psi1.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x1/nm, psi1.imag, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x1/nm, abs(psi1), colors[2], linestyle='solid', linewidth = 5.0) img += plt.plot(x2/nm, psi2.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x2/nm, psi2.imag, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x2/nm, abs(psi2), colors[2], linestyle='solid', linewidth = 5.0) img += plt.plot(x3/nm, psi3.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x3/nm, psi3.imag, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x3/nm, abs(psi3), colors[2], linestyle='solid', linewidth = 5.0) ims.append( img ) #グラフの描画(波動関数) plt.title( u"箱型障壁へ照射したガウス波束の波動関数(" + r"$ E_0 = 20.0 [{\rm eV}], d = 0.2[{\rm nm}], V = 40.0[{\rm eV}] $" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$x\, [{\rm nm}]$", fontsize=30) plt.ylabel(r"$ \psi(x, t) $", fontsize=30) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.12, top = 0.95) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #壁の描画 plt.vlines([0], -0.02, 2.02, "black", linestyles='solid', linewidth = 10 ) plt.vlines([0.2], -0.02, 2.02, "black", linestyles='solid', linewidth = 10 ) plt.hlines([0], -5, 0, "black", linestyles='solid', linewidth = 10 ) plt.hlines([2], 0, 0.2, "black", linestyles='solid', linewidth = 10 ) plt.hlines([0], 0.2, 5, "black", linestyles='solid', linewidth = 10 ) #描画範囲を設定 plt.xlim([x_min/nm, x_max/nm]) plt.ylim([-1.0, 2.0]) #アニメーションの生成 ani = animation.ArtistAnimation(fig, ims, interval=10) #アニメーションの保存 #ani.save("output.html", writer=animation.HTMLWriter()) #ani.save("output.gif", writer="imagemagick") ani.save("output2.mp4", writer="ffmpeg", dpi=300) ################################################################# ## ガウス分布の描画(横軸:エネルギー) ################################################################# fig_gaussian = plt.figure(figsize=(15, 8)) #波数の計算範囲 k_min = k0 - dk * NK / 2.0 k_max = k0 + dk * NK / 2.0 E_min = ( hbar * k_min )**2 / (2.0 * me) / eV E_max = ( hbar * k_max )**2 / (2.0 * me) / eV #波数座標点配列の生成 k = np.linspace(k_min, k_max, NK) E = ( hbar * k )**2 / (2.0 * me) / eV #正規分布 c_n = np.exp( -((k - k0) / (2.0 * sigma))**2 ) #グラフの描画(固有関数) plt.title( u"ガウス分布(正規分布)", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$ E[{\rm eV}] $", fontsize=30) plt.ylabel(r"$ c_n/c_0 $", fontsize=30) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([E_min, E_max]) plt.ylim([0, 1.05]) #波数分布グラフの描画 plt.plot(E, c_n, linestyle='solid', linewidth = 5) #グラフの表示 plt.show()
【第13話】箱型障壁に平面波を照射したときのアニメーション!【Pythonコピペで量子力学完全攻略マニュアル】
############################### ## 箱型障壁へ照射した平面波の時間発展(E = 1.0[eV]) ############################### import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ################ # 物理定数 ################ #プランク定数 h = 6.6260896 * 10**-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.10938215 * 10**-31 #電子ボルト eV = 1.60217733 * 10**-19 ################ # 物理系の設定 ################ #電子のエネルギー E = 1.0 * eV #波数 k1 = np.sqrt(2.0 * me * E / hbar**2 ) #角振動数 omega = E/hbar #1周期 T = 2.0 * np.pi / omega #時間間隔 #dt = 0.2 * 10**-16 dt = T / 100 #時間刻み数 NT = 100 #空間刻み間隔 nm = 1E-9 #壁の厚さ d = 2.0 * nm #壁の高さ V1 = 0 * eV V2 = 0.8 * eV V3 = 0 * eV #描画範囲 x_min = -4.0 * nm x_max = 6.0 * nm #描画区間数 NX = 500 #座標点配列の生成 x1 = np.linspace(x_min, 0, NX) x2 = np.linspace(0, d, NX) x3 = np.linspace(d, x_max, NX) ################ # 反射係数と透過係数を計算する関数定義 ################ def ReflectionCoefficient( MM ): return - MM[1][0] / MM[1][1] def TransmissionCoefficient(MM): return (MM[0][0] * MM[1][1] - MM[0][1] * MM[1][0] ) / MM[1][1] k1 = np.sqrt(np.complex128( 2.0 * me * (E - V1) / hbar**2 )) k2 = np.sqrt(np.complex128( 2.0 * me * (E - V2) / hbar**2 )) k3 = np.sqrt(np.complex128( 2.0 * me * (E - V3) / hbar**2 )) #反射係数と透過係数の計算 # 転送行列の定義 M21 = np.zeros((2,2), dtype=np.complex) T2 = np.zeros((2,2), dtype=np.complex) M32 = np.zeros((2,2), dtype=np.complex) # 境界 M21[0][0] = (1.0 + 0.0j + k1 / k2) / 2.0 M21[0][1] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][0] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][1] = (1.0 + 0.0j + k1 / k2) / 2.0 M32[0][0] = (1.0 + 0.0j + k2 / k3) / 2.0 M32[0][1] = (1.0 + 0.0j - k2 / k3) / 2.0 M32[1][0] = (1.0 + 0.0j - k2 / k3) / 2.0 M32[1][1] = (1.0 + 0.0j + k2 / k3) / 2.0 T2[0][0] = np.exp( I * k2 * d ) T2[0][1] = 0 T2[1][0] = 0 T2[1][1] = np.exp( - I * k2 * d ) #転送行列の計算 M31 = M32 @ T2 @ M21; #反射係数と透過係数の計算 rc = ReflectionCoefficient(M31); tc = TransmissionCoefficient(M31); ############################### ## 透過率と反射率の入射波のエネルギー依存性のグラフ描画 ############################### #領域2の係数 A2_p = M21[0][0] * 1.0 + M21[0][1] * rc A2_m = M21[1][0] * 1.0 + M21[1][1] * rc #アニメーション作成用 ims=[] #各時刻における計算 for tn in range(NT): t = dt * tn #波動関数の計算 #領域1 phi_I = np.exp( I * k1 * x1 - I * omega * t ) phi_R = rc * np.exp( - I * k1 * x1 - I * omega * t ) phi1 = phi_I + phi_R #領域2 phi2_p = A2_p * np.exp( I * k2 * x2 - I * omega * t ) phi2_m = A2_m * np.exp( - I * k2 * x2 - I * omega * t ) phi2 = phi2_p + phi2_m #領域3 phi_T = tc * np.exp( I * k3 * (x3 - d) - I * omega * t ) #各コマを描画 img = plt.plot(x1/nm, phi1.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x1/nm, phi1.imag, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x1/nm, abs(phi1), colors[2], linestyle='solid', linewidth = 5.0) img += plt.plot(x2/nm, phi2.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x2/nm, phi2.imag, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x2/nm, abs(phi2), colors[2], linestyle='solid', linewidth = 5.0) img += plt.plot(x3/nm, phi_T.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x3/nm, phi_T.imag, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x3/nm, abs(phi_T), colors[2], linestyle='solid', linewidth = 5.0) ims.append( img ) #グラフの描画(波動関数) plt.title( u"箱型障壁へ照射した平面波の波動関数(" + r"$ E = 1.0 [{\rm eV}], d = 2.0[{\rm nm}], V = 0.8[{\rm eV}] $" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$x\, [{\rm nm}]$", fontsize=30) plt.ylabel(r"$ \psi(x, t) $", fontsize=30) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.12, top = 0.95) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #壁の描画 plt.vlines([0], -0.05, 2.05, "black", linestyles='solid', linewidth = 10 ) plt.vlines([2], -0.05, 2.05, "black", linestyles='solid', linewidth = 10 ) plt.hlines([0], -5, 0, "black", linestyles='solid', linewidth = 10 ) plt.hlines([2], 0, 2, "black", linestyles='solid', linewidth = 10 ) plt.hlines([0], 2, 6, "black", linestyles='solid', linewidth = 10 ) #描画範囲を設定 plt.xlim([x_min/nm, x_max/nm]) plt.ylim([-2.0, 2.5]) #アニメーションの生成 ani = animation.ArtistAnimation(fig, ims, interval=10) #アニメーションの保存 ani.save("output.html", writer=animation.HTMLWriter()) #ani.save("output.gif", writer="imagemagick") #ani.save("output.mp4", writer="ffmpeg", dpi=300) #グラフの表示 plt.show()
【第12話】箱型障壁に照射したときの反射率と透過率を計算!【Pythonコピペで量子力学完全攻略マニュアル】
################################################################# ## 透過率と反射率の入射波のエネルギー依存性のグラフ描画(E = 1.0[eV]) ################################################################# import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ###################################### # 物理定数 ###################################### #プランク定数 h = 6.6260896 * 10**-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.10938215 * 10**-31 #電子ボルト eV = 1.60217733 * 10**-19 ###################################### # 物理系の設定 ###################################### #空間刻み間隔 nm = 1E-9 #壁の厚さ d = 2.0 * nm #壁の高さ V1 = 0 * eV V2 = 1.0 * eV V3 = 0 * eV ###################################### # 反射係数と透過係数を計算する関数定義 ###################################### def ReflectionCoefficient( MM ): return - MM[1][0] / MM[1][1] def TransmissionCoefficient(MM): return (MM[0][0] * MM[1][1] - MM[0][1] * MM[1][0] ) / MM[1][1] def calculateCoefficient( k1, k2, k3, d): # 転送行列の定義 M21 = np.zeros((2,2), dtype=np.complex) T2 = np.zeros((2,2), dtype=np.complex) M32 = np.zeros((2,2), dtype=np.complex) # 境界 M21[0][0] = (1.0 + 0.0j + k1 / k2) / 2.0 M21[0][1] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][0] = (1.0 + 0.0j - k1 / k2) / 2.0 M21[1][1] = (1.0 + 0.0j + k1 / k2) / 2.0 M32[0][0] = (1.0 + 0.0j + k2 / k3) / 2.0 M32[0][1] = (1.0 + 0.0j - k2 / k3) / 2.0 M32[1][0] = (1.0 + 0.0j - k2 / k3) / 2.0 M32[1][1] = (1.0 + 0.0j + k2 / k3) / 2.0 T2[0][0] = np.exp( I * k2 * d ) T2[0][1] = 0 T2[1][0] = 0 T2[1][1] = np.exp( - I * k2 * d ) #転送行列の計算 M31 = M32 @ T2 @ M21; #反射係数と透過係数の計算 rc = ReflectionCoefficient(M31); tc = TransmissionCoefficient(M31); return rc, tc ################################################################# ## 透過率と反射率の入射波のエネルギー依存性のグラフ描画 ################################################################# #エネルギーの計算範囲 E_min = 0.001 E_max = 3.0 #計算点数 NK = 500 #エネルギーの行列 Es = np.linspace(E_min, E_max, NK) #反射率と透過率の配列 Rs = [] Ts = [] for E in Es: E = E * eV #波数の計算 k1 = np.sqrt(np.complex128( 2.0 * me * (E - V1) / hbar**2 )) k2 = np.sqrt(np.complex128( 2.0 * me * (E - V2) / hbar**2 )) k3 = np.sqrt(np.complex128( 2.0 * me * (E - V3) / hbar**2 )) rc, tc = calculateCoefficient( k1, k2, k3, d) Rs.append( abs(rc)**2 ) Ts.append( abs(tc)**2 ) #グラフの描画(固有関数) plt.title( u"透過率と反射率の入射波のエネルギー依存性のグラフ(壁の厚さ:" + r"$2.0[{\rm nm}]$" + ", 壁の高さ:" + r"$1.0[{\rm eV}]$" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(u"入射波のエネルギー" + r"$[{\rm eV}]$" , fontname="Yu Gothic", fontsize=20, fontweight=1000) plt.ylabel(u"反射率と透過率", fontname="Yu Gothic", fontsize=20, fontweight=1000) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([0, 3]) plt.ylim([0, 1]) #波数分布グラフの描画 plt.plot(Es, Rs, linestyle='solid', linewidth = 5) plt.plot(Es, Ts, linestyle='solid', linewidth = 5) #グラフの表示 plt.show()
【第11話】Q.壁の高さがマイナスの場合、波束の運動はどうなる?【Pythonコピペで量子力学完全攻略マニュアル】
【第10話】Q.中心エネルギーが20[eV]のガウス波束を、中心エネルギーと同じ、20[eV]の壁に衝突させたらどうなるだろう?【Pythonコピペで量子力学完全攻略マニュアル】
【第9話】有限の高さの障壁に向けて照射した電子パルスのアニメーション【Pythonコピペで量子力学完全攻略マニュアル】
############################################################# ## 有限の高さの障壁に向けてガウス波束を照射したときの時間発展(E = 10.0[eV]) ############################################################# import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ####################### # 物理定数 ####################### #プランク定数 h = 6.6260896 * 10**-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.10938215 * 10**-31 #電子ボルト eV = 1.60217733 * 10**-19 ####################### ## 物理系の設定 ####################### #波束の中心エネルギー E0 = 20.0 * eV #重ね合わせの数 NK = 1000 #ガウス分布の幅 sigma = 2 / ( 1.25 * 10**-9 ) #波数の間隔 dk = 10.0 * sigma / NK #ガウス分布の中心波数 k0 = np.sqrt( 2.0 * me * E0 / hbar**2) #空間分割サイズ dx = 1.0 * 10**-9 #空間分割数 NX = 500 #描画範囲 x_min = -10.0 * dx x_max = 10.0 * dx #壁の高さ V = 10.0 * eV #ガウス波束の初期位置 x0 = -7.5 * dx #計算時間の幅 ts = 0 te = 300 #時間間隔 dt = 0.3 * 10**-16 #ガウス波束の値を計算する関数 def Psi( x, t, region ): #波動関数値の初期化 psi = x * (0.0 + 0.0j) #各波数ごとの寄与を足し合わせる for kn in range(NK): #各波数を取得 k1 = k0 + dk * (kn - NK/2) #波数から各振動数を取得 omega = hbar / (2.0 * me) * k1**2 #平面波のエネルギー E = (hbar * k1)**2 / (2.0 * me) #領域IIの波数 k2 = np.sqrt(np.complex128( 2.0 * me * (E - V) / hbar**2 )) #反射係数 rc = ( k1 - k2 ) / ( k1 + k2 ) #透過係数 tc = 2.0 * k1 / ( k1 + k2 ) #入射波と反射波と透過波 phi_I = np.exp( I * k1 * x - I * omega * t ) phi_R = rc * np.exp( - I * k1 * x - I * omega * t ) phi_T = tc * np.exp( I * k2 * x - I * omega * t ) #ガウス分布 Ck = np.exp( - I * k1 * x0 ) * np.exp( -( (k1 - k0) / (2.0 * sigma) )**2 ) #平面波を足し合わせる if(region == 1): psi += (phi_I + phi_R) * Ck elif(region == 2): psi += phi_T * Ck return psi #基準となる振幅を取得 psi_abs = abs(Psi( x0, 0, 1 )) #座標点配列の生成 x1 = np.linspace(x_min, 0, NX) x2 = np.linspace(0, x_max, NX) #アニメーション作成用 ims=[] ### 波束の空間分布の計算 for tn in range(ts, te + 1): #実時間の取得 t = dt * tn #時刻tの波動関数を取得 psi1 = Psi( x1, t, 1 ) psi2 = Psi( x2, t, 2 ) #波動関数の規格化 psi1 /= psi_abs psi2 /= psi_abs #各コマを描画 img = plt.plot(x1/dx, psi1.real, colors[0], linestyle='solid', linewidth = 3.0) img += plt.plot(x1/dx, psi1.imag, colors[1], linestyle='solid', linewidth = 3.0) img += plt.plot(x1/dx, abs(psi1), colors[2], linestyle='solid', linewidth = 3.0) img += plt.plot(x2/dx, psi2.real, colors[3], linestyle='solid', linewidth = 3.0) img += plt.plot(x2/dx, psi2.imag, colors[4], linestyle='solid', linewidth = 3.0) img += plt.plot(x2/dx, abs(psi2), colors[5], linestyle='solid', linewidth = 3.0) #time = plt.text( 8.5, 1.57, "t = " + str(round(t/10**-15, 1)) + r"$[{\rm fs}]$" , ha='left', va='center', fontsize=18) #テキストをグラフに追加 #img.append(time) #アニメーションに追加 ims.append(img) #グラフの描画(波動関数) plt.title( u"有限の高さの障壁に向けて照射したガウス波束の波動関数(" + r"$ E_0 = 20.0 [{\rm eV}] , V = -20.0 [{\rm eV}] $" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel( r"$ x [{\rm nm} ] $", fontsize=30 ) plt.ylabel( r"$ \psi(x,t) $", fontsize=30 ) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.15, top = 0.95) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #壁の描画 plt.vlines([0], +0.025, -1.025, "black", linestyles='solid', linewidth = 10 ) plt.hlines([0], -10, 0, "black", linestyles='solid', linewidth = 10 ) plt.hlines([-1], 0, 10, "black", linestyles='solid', linewidth = 10 ) #描画範囲を設定 plt.xlim([x_min/dx, x_max/dx]) plt.ylim([-1.1, 1.5]) #アニメーションの生成 ani = animation.ArtistAnimation(fig, ims, interval=50) #アニメーションの保存 ani.save("output.html", writer=animation.HTMLWriter()) #ani.save("output.gif", writer="imagemagick") ani.save("output.mp4", writer="ffmpeg", dpi=300) ####################### ## ガウス分布の描画 ####################### fig_gaussian = plt.figure(figsize=(15, 8)) #波数の計算範囲 k_min = k0 - dk * NK / 2.0 k_max = k0 + dk * NK / 2.0 #波数座標点配列の生成 k = np.linspace(k_min, k_max, NK) #正規分布 c_n = np.exp( -((k - k0) / (2.0 * sigma))**2 ) #グラフの描画(固有関数) plt.title( u"ガウス分布(正規分布)", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$ (k_n - \bar{k})/\sigma $", fontsize=30) plt.ylabel(r"$ c_n/c_0 $", fontsize=30) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([(k_min- k0)/sigma, (k_max- k0)/sigma]) plt.ylim([0, 1.05]) #波数分布グラフの描画 plt.plot((k-k0)/sigma, c_n, linestyle='solid', linewidth = 5) #グラフの表示 plt.show()
【第6話】無限に高い障壁へ照射アニメーション【Pythonコピペで量子力学完全攻略マニュアル】
################################################################# ## 無限に高い障壁へ照射した平面波の時間発展(E = 1.0[eV]) ################################################################# import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ###################################### # 物理定数 ###################################### #プランク定数 h = 6.6260896 * 10**-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.10938215 * 10**-31 #電子ボルト eV = 1.60217733 * 10**-19 ###################################### # 物理系の設定 ###################################### #電子のエネルギー E1 = 1.0 * eV #波数 k1 = np.sqrt(2.0 * me * E1 / hbar**2 ) #角振動数 omega1 = E1/hbar #1周期 T1 = 2.0 * np.pi / omega1 #時間間隔 #dt = 0.2 * 10**-16 dt = T1 / 100 #時間刻み数 NT = 1000 #空間刻み間隔 dx = 1E-9 #描画範囲 x_min = -5.0 * dx x_max = 0.0 * dx #描画区間数 NX = 500 #座標点配列の生成 x = np.linspace(x_min, x_max, NX) #アニメーション作成用 ims=[] #各時刻における計算 for tn in range(NT): t = dt * tn #波動関数の計算 phi_I = np.exp( I * k1 * x - I * omega1 * t ) phi_R = np.exp( - I * k1 * x - I * omega1 * t ) phi = phi_I - phi_R #各コマを描画 img = plt.plot(x/dx, phi_I.real, colors[0], linestyle='solid', linewidth = 5.0) img += plt.plot(x/dx, phi_R.real, colors[1], linestyle='solid', linewidth = 5.0) img += plt.plot(x/dx, phi.real, colors[2], linestyle='solid', linewidth = 5.0) ims.append( img ) #グラフの描画(波動関数) plt.title( u"無限に高い障壁へ照射した平面波の波動関数(" + r"$ E = 1.0 [{\rm eV}] $" + u")", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$x\, [{\rm nm}]$", fontsize=30) plt.ylabel(r"$ {\rm Re}\{\psi(x, t)\} $", fontsize=30) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.12, top = 0.95) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #壁の描画 plt.vlines([0], -5, 5, "black", linestyles='solid', linewidth = 10 ) #描画範囲を設定 plt.xlim([x_min/dx, x_max/dx + 0.5]) plt.ylim([-3.1, 3.1]) #アニメーションの生成 ani = animation.ArtistAnimation(fig, ims, interval=10) #アニメーションの保存 #ani.save("output.html", writer=animation.HTMLWriter()) #ani.save("output.gif", writer="imagemagick") ani.save("output.mp4", writer="ffmpeg", dpi=300) #グラフの表示 plt.show()
【第5話】電子パルスの運動アニメーション【Pythonコピペで量子力学完全攻略マニュアル】
################################################################# ## ガウス波束の運動 ################################################################# import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ################################################################# ## 物理定数 ################################################################# #プランク定数 h = 6.62607015 * 1.0E-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.1093837015 * 1.0E-31 #電子ボルト eV = 1.602176634 * 1.0E-19 ################################################################# ## 物理系の設定 ################################################################# #波束の中心エネルギー E_bar = 1.0 * eV #重ね合わせの数 NK = 200 #ガウス分布の幅 sigma = 1.0 / ( 1.25 * 10**-9 ) #波数の間隔 dk = 10.0 * sigma / NK #ガウス分布の中心 k_bar = np.sqrt( 2.0 * me * E_bar / hbar**2) #空間分割サイズ dx = 1.0 * 10**-9 #空間分割数 NX = 500 #計算区間 x_min = -10.0 * dx x_max = 10.0 * dx #計算時間の幅 ts = -100 te = 100 #時間間隔 dt = 4.0 * 10**-16 #ガウス波束の値を計算する関数 def Psi( x, t ): #波動関数値の初期化 psi = x * (0.0 + 0.0j) #各波数ごとの寄与を足し合わせる for kn in range(NK): #各波数を取得 k = k_bar + dk * (kn - NK/2) #波数から各振動数を取得 omega = hbar / (2.0 * me) * k**2 #平面波を足し合わせる psi += np.exp(I * k * x ) * np.exp(- I * omega * t) * np.exp( -( (k - k_bar) / (2.0 * sigma) )**2 ) return psi #基準となる振幅を取得 psi_abs = abs(Psi( 0, 0 )) #座標点配列の生成 x = np.linspace(x_min, x_max, NX) #アニメーション作成用 ims=[] ### 波束の空間分布の計算 for tn in range(ts, te + 1): #実時間の取得 t = dt * tn #時刻t=0の波動関数を取得 psi = Psi( x, t ) #波動関数の規格化 psi /= psi_abs #各コマを描画 img = plt.plot(x/dx, psi.real, colors[0], linestyle='solid', linewidth = 3.0) img += plt.plot(x/dx, psi.imag, colors[1], linestyle='solid', linewidth = 3.0) img += plt.plot(x/dx, abs(psi), colors[2], linestyle='solid', linewidth = 3.0) time = plt.text(8, 1.15, "t = " + str(round(t/10**-15, 1)) + r"$[{\rm fs}]$" , ha='left', va='center', fontsize=18) #テキストをグラフに追加 img.append(time) #アニメーションに追加 ims.append(img) #グラフの描画(波動関数) plt.title( u"ガウス波束の運動", fontsize=20, fontname="Yu Gothic", fontweight=1000 ) plt.xlabel( r"$ x [{\rm nm} ] $", fontsize=30 ) plt.ylabel( r"$ \psi(x,t) $", fontsize=30 ) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.15, top = 0.95) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([x_min/dx, x_max/dx]) plt.ylim([-1.1, 1.1]) #アニメーションの生成 ani = animation.ArtistAnimation(fig, ims, interval=50) #アニメーションの保存 #ani.save("output.html", writer=animation.HTMLWriter()) #ani.save("output.mp4", writer="ffmpeg", dpi=300) ################################################################# ## ガウス分布の描画 ################################################################# fig_gaussian = plt.figure(figsize=(15, 8)) #波数の計算範囲 k_min = k_bar - dk * NK / 2.0 k_max = k_bar + dk * NK / 2.0 #波数座標点配列の生成 k = np.linspace(k_min, k_max, NK) #正規分布 c_n = np.exp( -((k - k_bar) / (2.0 * sigma))**2 ) #グラフの描画(固有関数) plt.title( u"ガウス分布(正規分布)", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$ (k_n - \bar{k})/\sigma $", fontsize=30) plt.ylabel(r"$ c_n/c_0 $", fontsize=30) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([(k_min- k_bar)/sigma, (k_max- k_bar)/sigma]) plt.ylim([0, 1.05]) #波数分布グラフの描画 plt.plot((k-k_bar)/sigma, c_n, linestyle='solid', linewidth = 5) #グラフの表示 plt.show()
【第4話】電子パルスの作り方【Pythonコピペで量子力学完全攻略マニュアル】
################################################################# ## ガウス波束の空間分布 ################################################################# import numpy as np import matplotlib.pyplot as plt #図全体 fig = plt.figure(figsize=(15, 8)) #全体設定 plt.rcParams['font.family'] = 'Times New Roman' #フォント plt.rcParams['font.size'] = 24 #フォントサイズ plt.rcParams["mathtext.fontset"] = 'cm' #数式用フォント #カラーリストの取得 colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] #虚数単位 I = 0.0 + 1.0j ################################################################# ## 物理定数 ################################################################# #プランク定数 h = 6.62607015 * 1.0E-34 hbar = h / (2.0 * np.pi) #電子の質量 me = 9.1093837015 * 1.0E-31 #電子ボルト eV = 1.602176634 * 1.0E-19 ################################################################# ## 物理系の設定 ################################################################# #波束の中心エネルギー E0 = 10.0 * eV #重ね合わせの数 NK = 500 #ガウス分布の幅 sigma = 1.0 / ( 1.25 * 10**-9 ) #波数の間隔 dk = 10.0 * sigma / NK #ガウス分布の中心 k0 = np.sqrt( 2.0 * me * E0 / hbar**2) #空間分割サイズ dx = 1.0 * 10**-9 #空間分割数 NX = 500 #計算区間 x_min = -5.0 * dx x_max = 5.0 * dx #ガウス波束の値を計算する関数 def Psi( x, t ): #波動関数値の初期化 psi = x * (0.0 + 0.0j) #各波数ごとの寄与を足し合わせる for kn in range(NK): #各波数を取得 k = k0 + dk * (kn - NK/2) #波数から各振動数を取得 omega = hbar / (2.0 * me) * k**2 #平面波を足し合わせる psi += np.exp(I * k * x ) * np.exp(- I * omega * t) * np.exp( -( (k - k0) / (2.0 * sigma) )**2 ) return psi #基準となる振幅を取得 psi_abs = abs(Psi( 0, 0 )) #座標点配列の生成 x = np.linspace(x_min, x_max, NX) #時刻t=0の波動関数を取得 psi = Psi( x, 0 ) #波動関数の規格化 psi /= psi_abs #グラフの描画(波動関数) plt.title( u"ガウス波束", fontsize=20, fontname="Yu Gothic", fontweight=1000 ) plt.xlabel( r"$ x [{\rm nm} ] $", fontsize=30 ) plt.ylabel( r"$ \psi(x,0) $", fontsize=30 ) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #描画範囲を設定 plt.xlim([x_min/dx, x_max/dx]) plt.ylim([-1.1, 1.1]) #グラフの描画 plt.plot(x/dx, psi.real, linestyle='solid', linewidth = 5) plt.plot(x/dx, psi.imag, linestyle='solid', linewidth = 5) plt.plot(x/dx, abs(psi), linestyle='solid', linewidth = 5) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.15, top = 0.95) ################################################################# ## ガウス分布の描画 ################################################################# fig_gaussian = plt.figure(figsize=(15, 8)) #波数の計算範囲 k_min = k0 - dk * NK / 2.0 k_max = k0 + dk * NK / 2.0 #波数座標点配列の生成 k = np.linspace(k_min, k_max, NK) #正規分布 C_k = np.exp( -((k - k0) / (2.0 * sigma))**2 ) #グラフの描画(固有関数) plt.title( u"ガウス分布(正規分布)", fontsize=20, fontname="Yu Gothic", fontweight=1000) plt.xlabel(r"$ (k - k_0)/\sigma $", fontsize=30) plt.ylabel(r"$ C(k)/C_0 $", fontsize=30) #罫線の描画 plt.grid(which = "major", axis = "x", alpha = 0.8, linestyle = "-", linewidth = 1) plt.grid(which = "major", axis = "y", alpha = 0.8, linestyle = "-", linewidth = 1) #余白の調整 plt.subplots_adjust(left = 0.1, right = 0.98, bottom=0.15, top = 0.95) #描画範囲を設定 plt.xlim([(k_min- k0)/sigma, (k_max- k0)/sigma]) plt.ylim([0, 1.05]) #波数分布グラフの描画 plt.plot((k-k0)/sigma, C_k, linestyle='solid', linewidth = 5) #グラフの表示 plt.show()