schottky.py ダウンロード/コピー
schottky.py
schottky.py
1"""
2ショットキーダイオードの電流-電圧特性シミュレーションスクリプト。
3
4さまざまなショットキーモデル(単純拡散、拡散、ショットキー障壁低下、トンネル、熱電子電界放出)を用いて、
5ショットキーダイオードのIV特性を計算し、プロットします。
6物理定数や材料パラメータを入力として受け取り、順方向および逆方向バイアスでの電流を数値的に解きます。
7
8関連リンク: :doc:`schottky_usage` (例として示すリンクであり、実際のドキュメントパスは異なる場合があります)
9"""
10import numpy as np
11import math
12import argparse
13import matplotlib.pyplot as plt
14
15# 物理定数
16KB = 1.380649e-23 # ボルツマン定数 [J/K]
17QE = 1.60217663e-19 # 素電荷 [C]
18EPS0 = 8.854187e-12 # 真空の誘電率 [F/m]
19ME = 9.109383e-31 # 電子の静止質量 [kg]
20
21def calculate_params(args):
22 """
23 ショットキーダイオードの主要な物理パラメータを計算します。
24
25 リチャードソン定数、半導体側の有効状態密度とフェルミ準位、
26 ショットキー障壁高さ、内蔵電位、直列抵抗(単位面積あたり)、
27 飽和電流密度などを計算します。
28
29 :param args: コマンドライン引数から解析されたパラメータを含むオブジェクト。
30 :type args: argparse.Namespace
31 :param args.temp: 温度 [K]。
32 :type args.temp: float
33 :param args.men: 電子の有効質量比。
34 :type args.men: float
35 :param args.ecn: 半導体の電子親和力 [eV]。
36 :type args.ecn: float
37 :param args.efm: 金属のフェルミ準位 [eV]。
38 :type args.efm: float
39 :param args.ndn: 半導体のドナー濃度 [cm^-3]。
40 :type args.ndn: float
41 :param args.mun: 電子の移動度 [cm^2/Vs]。
42 :type args.mun: float
43 :param args.dn: 半導体の厚さ [nm]。
44 :type args.dn: float
45 :returns: (飽和電流密度 [A/cm^2], 内蔵電位 [V], ショットキー障壁高さ [eV], 半導体側の有効状態密度 [cm^-3], 直列抵抗(単位面積あたり) [Ω cm^2])
46 :rtype: tuple[float, float, float, float, float]
47 """
48 T = args.temp
49 # リチャードソン定数の計算
50 reff = 1.20173e6 * args.men # A/m2/K2
51 am_cm2 = reff * 1e-4 # A/cm2/K2
52
53 # 半導体側の統計
54 nc = 2.51e19 * (args.men**1.5) * ((T/300)**1.5) # cm-3
55 efn = args.ecn - (KB * T / QE) * math.log(args.ndn / nc)
56
57 # 障壁と内蔵電位
58 phi_b = -(args.ecn - args.efm)
59 v_bi = -(efn - args.efm)
60
61 # 抵抗と飽和電流
62 sigma_n = QE * args.ndn * args.mun
63 rn = 1.0 / sigma_n * args.dn * 1e-7 # ohm cm2
64 rs = rn
65
66 js = am_cm2 * T**2 * math.exp(-QE * phi_b / (KB * T))
67
68 return js, v_bi, phi_b, nc, rs
69
70def calculate_schottky_current(model_type, v_target, temp, mus, ncs, nds, epss, js, phi_b, v_bi, n_diode, rs, area, v_initial, men, n_tunnel):
71 """
72 指定されたモデルに基づき、ショットキーダイオードの電流を計算します。
73
74 ニュートン法を用いて、直列抵抗効果を考慮したダイオード電圧 `v_diode` を数値的に解き、
75 それに対応する電流を求めます。
76 内部関数 `get_current(vd)` は、与えられたダイオード電圧 `vd` に対して、
77 モデルに応じた電流を計算します。モデルには 'Simple', 'Diffusion', 'Schottky' (障壁低下),
78 'Tunneling', 'TFE' (熱電子放出と電界放出) があります。
79
80 :param model_type: 使用するショットキーモデルの種類 ('Simple', 'Diffusion', 'Schottky', 'Tunneling', 'TFE')。
81 :type model_type: str
82 :param v_target: 印加電圧 [V]。
83 :type v_target: float
84 :param temp: 温度 [K]。
85 :type temp: float
86 :param mus: 電子の移動度 [cm^2/Vs]。
87 :type mus: float
88 :param ncs: 半導体の有効状態密度 [cm^-3]。
89 :type ncs: float
90 :param nds: 半導体のドナー濃度 [cm^-3]。
91 :type nds: float
92 :param epss: 半導体の誘電率 [F/m]。
93 :type epss: float
94 :param js: 飽和電流密度 [A/cm^2]。
95 :type js: float
96 :param phi_b: ショットキー障壁高さ [eV]。
97 :type phi_b: float
98 :param v_bi: 内蔵電位 [V]。
99 :type v_bi: float
100 :param n_diode: ダイオードの理想係数。
101 :type n_diode: float
102 :param rs: 直列抵抗 [Ω]。
103 :type rs: float
104 :param area: ダイオードの面積 [cm^2]。
105 :type area: float
106 :param v_initial: ニュートン法の初期ダイオード電圧 [V]。
107 :type v_initial: float
108 :param men: 電子の有効質量比。
109 :type men: float
110 :param n_tunnel: トンネルモデルの理想係数。
111 :type n_tunnel: float
112 :returns: (計算されたダイオード電圧 [V], 計算された電流 [A])
113 :rtype: tuple[float, float]
114 """
115 if v_target == 0: return 0.0, 0.0
116 v_diode = v_initial
117 dv, eps, max_iter = 1e-4, 1e-7, 100
118 vt = (n_diode * KB * temp) / QE
119
120 # 単位換算 (cm -> m)
121 mus_m = mus * 1e-4
122 ncs_m = ncs * 1e6
123 nds_m = nds * 1e6
124
125 # get_current をループの外で定義できるよう vd を引数に取る形式に
126 def get_current(vd):
127 if v_target >= 0.0 or model_type == 'Simple' or (v_bi - vd) < 0:
128 return js * (math.exp(vd / vt) - 1.0) * area
129
130 elif model_type == 'Diffusion':
131 e_max = math.sqrt(2.0 * QE * nds_m * (v_bi - vd) / epss)
132 k_exp = QE * mus_m * ncs_m * e_max * math.exp(-QE * phi_b / (KB * temp))
133 return k_exp * (math.exp(vd / vt) - 1.0) * 1e-4 * area
134
135 elif model_type == 'Schottky':
136 k1 = (QE / epss)**1.5 * math.sqrt(2) / (4.0 * math.pi) * math.sqrt(nds_m) * math.sqrt(v_bi - vd)
137 k_exp = math.exp(QE / (KB * temp) * math.sqrt(k1))
138 return js * k_exp * (math.exp(vd / vt) - 1.0) * area
139
140 elif model_type == 'Tunneling':
141 # 簡易的な指数関数モデル
142 k_tunnel = math.exp(vd / (n_tunnel * 0.026))
143 return js * k_tunnel * (math.exp(vd / vt) - 1.0) * area
144
145 elif model_type == 'TFE':
146 hbar = 1.0545718e-34
147 m_eff = men * ME
148 # E00の計算
149 e00_j = (QE * hbar / 2.0) * math.sqrt(nds_m / (epss * m_eff))
150 e00 = e00_j / QE # [eV]
151 kt_q = (KB * temp) / QE
152 e0 = e00 * (1.0 / math.tanh(e00 / kt_q))
153
154 if vd >= 0:
155 # 順方向:傾きが 1/e0 になる
156 return js * (math.exp(vd / e0) - 1.0) * area
157 else:
158 # 逆方向:電界による障壁の薄層化を考慮(簡易WKB)
159 # 電界が強くなる(vdがマイナスに大きくなる)ほど指数関数的に増大させる
160 e_max = math.sqrt(2.0 * QE * nds_m * (v_bi - vd) / epss)
161 # 補正項:E00が大きくなる(ドーピングが高い)ほど透過率が爆発的に増える
162 tunnel_factor = math.exp(abs(vd) * (e00 / kt_q)**2)
163 return js * tunnel_factor * (math.exp(vd / e0) - 1.0) * area
164 return 0
165
166 for _ in range(max_iter):
167 im = get_current(v_diode - dv)
168 ip = get_current(v_diode + dv)
169
170 v_total = 0.5 * ((v_diode - dv + im * rs) + (v_diode + dv + ip * rs))
171 if abs(v_total - v_target) < eps:
172 return v_diode, 0.5 * (im + ip)
173
174 dv_dv = ((v_diode + dv + ip * rs) - (v_diode - dv + im * rs)) / (2.0 * dv)
175 v_diode += (v_target - v_total) / dv_dv
176
177 return v_diode, get_current(v_diode)
178
179def main():
180 """
181 コマンドライン引数に基づいてショットキーダイオードのIV特性シミュレーションを実行し、結果をプロットします。
182
183 `argparse` を使用して入力パラメータを解析し、`calculate_params` で基本パラメータを計算した後、
184 `calculate_schottky_current` を繰り返し呼び出してIV曲線を生成します。
185 最後にMatplotlibで結果を可視化します。
186
187 :returns: なし
188 :rtype: None
189 """
190 parser = argparse.ArgumentParser(description='ショットキーダイオードの電流-電圧特性をシミュレートします。')
191 parser.add_argument('--model', choices=['Simple', 'Diffusion', 'Schottky', 'Tunneling', 'TFE'], default='Simple',
192 help='使用するショットキーモデル。')
193 parser.add_argument('--temp', type=float, default=300.0,
194 help='温度 [K]。')
195 parser.add_argument('--area', type=float, default=0.01,
196 help='ダイオードの面積 [cm^2]。')
197 parser.add_argument('--efm', type=float, default=4.4,
198 help='金属のフェルミ準位 [eV]。')
199 parser.add_argument('--ecn', type=float, default=4.05,
200 help='半導体の電子親和力 [eV]。')
201 parser.add_argument('--ndn', type=float, default=1.0e16,
202 help='半導体のドナー濃度 [cm^-3]。')
203 parser.add_argument('--mun', type=float, default=1500.0,
204 help='電子の移動度 [cm^2/Vs]。')
205 parser.add_argument('--eps_r', type=float, default=11.9,
206 help='比誘電率。')
207 parser.add_argument('--dn', type=float, default=1000.0,
208 help='半導体の厚さ [nm]。')
209 parser.add_argument('--men', type=float, default=0.19,
210 help='電子の有効質量比。')
211 # トンネルモデル用のパラメータを追加
212 parser.add_argument('--n_tunnel', type=float, default=2.0,
213 help='トンネルモデルの理想係数。')
214 parser.add_argument('--v0', type=float, default=-2.0,
215 help='印加電圧の開始値 [V]。')
216 parser.add_argument('--v1', type=float, default=1.0,
217 help='印加電圧の終了値 [V]。')
218 parser.add_argument('--step', type=float, default=0.02,
219 help='印加電圧のステップサイズ [V]。')
220 args = parser.parse_args()
221
222 # パラメータ計算
223 js, v_bi, phi_b, ncs, rs_unit = calculate_params(args)
224 epss = args.eps_r * EPS0
225 rs = rs_unit / args.area
226
227 v_apps = np.arange(args.v0, args.v1 + args.step, args.step)
228 currents = []
229 v_prev = args.v0 * 0.2
230
231 for v_app in v_apps:
232 v_d, i = calculate_schottky_current(
233 args.model, v_app, args.temp, args.mun, ncs, args.ndn, epss,
234 js, phi_b, v_bi, 1.0, rs, args.area, v_prev,
235 args.men, args.n_tunnel # 不足していた引数を追加
236 )
237 currents.append(i)
238 v_prev = v_d
239
240 # 結果表示
241 print(f"Model : {args.model}")
242 print(f"Barrier phiB: {phi_b:.4f} eV")
243 print(f"V_bi : {v_bi:.4f} V")
244 print(f"Js : {js:.6e} A/cm2")
245
246 # グラフ表示
247 plt.figure(figsize=(8, 6))
248 plt.semilogy(v_apps, np.abs(currents), label=f'{args.model} model')
249 plt.xlabel("Applied Voltage [V]")
250 plt.ylabel("|Current| [A]")
251 plt.grid(True, which='both', alpha=0.3)
252 plt.legend()
253 plt.title(f"Schottky Diode IV Characteristics ({args.model})")
254 plt.show()
255
256if __name__ == "__main__":
257 main()