import sys
import time
from math import exp, sqrt
import numpy as np
from scipy import integrate # 数値積分関数 integrateを読み込む
from scipy import optimize # newton関数はscipy.optimizeモジュールに入っている
from matplotlib import pyplot as plt
"""
金属のEFの温度依存性を数値積分とNewton法で計算。
近似式と比較。
Calculate EF(T) for metal using numerical integration and the Newton method,
and compare with the approximation formula
"""
# constants
pi = 3.14159265358979323846
h = 6.6260755e-34 # Js";
hbar = 1.05459e-34 # "Js";
c = 2.99792458e8 # m/s";
e = 1.60218e-19 # C";
kB = 1.380658e-23 # JK-1";
me = 9.1093897e-31 # kg";
# spin, effective mass, electron density
S = 1.0 / 2.0
m = 1.0
N = 5.0e22 # cm^-3
# Temperature range
Tmin = 0 # K
Tmax = 4000
Tstep = 200
nT = int((Tmax - Tmin) / Tstep + 1)
# integration will be performed in the range
# from EF - nrange * kBT to EF + nrange * kBT
nrange = 6.0
# Relative accuracy of the quad functin
eps = 1.0e-8
# Treat argments
argv = sys.argv
if len(argv) >= 2:
N = float(argv[1])
if len(argv) >= 3:
m = float(argv[2])
D0 = (2.0 * S + 1.0) * 2.0 * pi * pow(2.0*m, 1.5) / h / h / h # m^-3J^-1.5
D0 *= 1.0e-6 * pow(e, 1.5) # m^-3J^-1.5 => cm-3eV^-1.5
# Density-Of-States function
def De(E):
global D0
if E < 0.0:
return 0.0
return D0 * sqrt(E)
# Fermi-Dirac distribution function
def fe(E, T, EF):
global e, kB
if T == 0.0:
if E < EF:
return 1.0
else:
return 0.0
return 1.0 / (exp((E - EF) * e / kB / T) + 1.0)
# Define the function to be integrated
def Defe(E, T, EF):
return De(E) * fe(E, T, EF)
# Calculate electron density with a given EF
# For E < EF - dE, use the analytical integration
# For E > EF - dE, use the numerical integration with quad
# The upper limit of integration is determined as EF + dE
def Ne(T, EF, dE):
global D0, eps
(Emin, Emax) = (0.0, EF - dE)
Ne1 = 2.0 / 3.0 * D0 * (pow(Emax, 1.5) - pow(Emin, 1.5))
(Emin, Emax) = (EF - dE, EF + dE)
if Emin < 0.0:
Emin = 0.0
ret = integrate.quad(lambda E: Defe(E, T, EF), Emin, Emax, epsrel = eps)
return Ne1 + ret[0]
# Calculate EF base on
# the charge neutrality (electron number) condition, Ne(T, EF, dE) - N = 0,
# using the Newton method with the initial value EF0
def CalEF(N, T, EF0, dE):
global D0
if T == 0.0:
return pow(1.5 / D0 * N, 2.0 / 3.0) # eV
EF = optimize.newton(lambda EF: Ne(T, EF, dE) - N, EF0)
return EF
def main():
global m, D0
print("m = %g me" % (m))
m *= me
# Calculate the prefactor of De(E)
D0 = (2.0 * S + 1.0) * 2.0 * pi * pow(2.0*m, 1.5) / h / h / h # m^-3J^-1.5
D0 *= 1.0e-6 * pow(e, 1.5) # m^-3J^-1.5 => cm-3eV^-1.5
print("")
# EF at 0 K, to be used for the initial value of the Newton method
EF0 = pow(1.5 / D0 * N, 2.0 / 3.0) # eV
N0 = Ne(0.0, EF0, 0.0)
print("EF at 0K = ", EF0, " eV")
print("Ne at 0K = ", N0, " cm-3")
print("")
xT = []
yEF = []
yEFa = []
EFprev = EF0
print(" T(K) \t EF(eV) \tEFapprox(eV)\tNcheck(cm-3)")
for i in range(nT):
T = Tmin + i * Tstep
kBTe = kB * T / e
# Calculate the range of numerical integration
dE = nrange * kBTe
EF = CalEF(N, T, EFprev, dE)
Ncheck = Ne(T, EF, dE)
Ndiff = 1.0 / 2.0 * D0 * pow(EF0, -1.0 / 2.0)
EFapprox = EF0 - pi * pi / 6.0 * pow(kBTe, 2.0) * Ndiff / De(EF0)
xT.append(T)
yEF.append(EF)
yEFa.append(EFapprox)
print("%8.4f\t%10.6f\t%10.6f\t%16.6g" % (T, EF, EFapprox, Ncheck))
EFprev = EF
#=============================
# Plot graphs
#=============================
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot(xT, yEF, label = 'EF(exact)')
ax1.plot(xT, yEFa, label = 'EF(approx)', color = 'red')
ax1.set_xlabel("T (K)")
ax1.set_ylabel("EF (eV)")
ax1.legend()
plt.pause(0.1)
print("Press ENTER to exit>>", end = '')
input()
if __name__ == '__main__':
main()