Seebeck2.py ダウンロード/コピー
Seebeck2.py
Seebeck2.py
1"""
2概要:
3 Seebeck係数と温度から有効質量を推定するスクリプトです。
4詳細説明:
5 G.J. Snyder, A. Pereyra and R. Gurunathan, Adv. Funct. Mater. 32, 2112772 (2022)
6 の論文に記載された手法に基づいて、Seebeck係数から有効質量を推定します。
7 本スクリプトは、フェルミ積分やバンド構造の計算を含む複数のモードをサポートし、
8 材料の熱電特性、特にゼーベック係数、電気伝導率、移動度、ローレンツ数、力率、ZT値を計算、
9 シミュレーション、および実験データへのフィッティングを行います。
10 Hall係数やHall因子、Hall移動度の計算も行います。
11主な機能:
12 - 基本関数 (フェルミ・ディラック分布、フェルミ積分) の計算とプロット。
13 - 熱電特性 (Seebeck係数、電気伝導率、移動度、熱伝導率、力率、ZT値) の計算とプロット。
14 - Hall特性 (Hall係数、Hall因子、Hall移動度) の計算とプロット。
15 - 実験データへのパラメータフィッティング (有効質量、平均自由行程因子)。
16 - 温度依存性のシミュレーション。
17 - ローレンツ数と電子熱伝導率の計算。
18 - Hall因子とドリフト移動度、キャリア濃度の計算。
19関連リンク:
20 Seebeck2_usage
21"""
22import os
23import sys
24import openpyxl
25from math import exp, sqrt, log, gamma
26import numpy as np
27#from numpy import arange
28from scipy import optimize # newton関数はscipy.optimizeモジュールに入っている
29from scipy.interpolate import interp1d
30from matplotlib import pyplot as plt
31from scipy import optimize # newton関数はscipy.optimizeモジュールに入っている
32from scipy.optimize import minimize
33
34
35from tklib.tkutils import terminate, getarg, getintarg, getfloatarg, safe_getelement, validate_error
36from tklib.tkutils import pint, pfloat, sort_lists
37from tklib.tkinifile import tkIniFile
38from tklib.tkvariousdata import tkVariousData
39from tklib.tksci.tksci import pi, h, hbar,c, e, kB, me
40from tklib.tksci.tkmatrix import make_matrix1, make_matrix2
41from tklib.tkapplication import tkApplication
42
43from tklib.tktransport.tkTransport import read_datafile, FermiIntegral_x2
44from tklib.tktransport.tkTransport import FermiIntegral_fast as FermiIntegral
45
46try:
47 import tklib.tktransport.tkfermi_integral
48 from tklib.tktransport.tkfermi_integral import FermiIntegral_fast as FermiIntegral_fast_new, fermi_integral_type
49except:
50 FermiIntegral_fast_new = None
51
52from tklib.tktransport.tkTransport import integrate_Simpson_list, fe, fh, meff2NC_FEA, meff2DC0_FEA, BMShift_FEA
53from tklib.tktransport.tkWeightedMobility import weighted_mobility, weighted_mobility_new, weighted_mobility_exact
54from tklib.tktransport.tkTransport import LorentzNumber_FEA
55from tklib.tktransport.tkDOS_FEA import integrate_Simpson, integrate_Simpson_list, tkDOS
56from tklib.tktransport.tkmobility_tau import tkMobility, split_optstr
57
58
59#================================
60# Global variables
61#================================
62Debug = 0
63
64if FermiIntegral_fast_new:
65 fermi_integral_type = tkfermi_integral.fermi_integral_type
66else:
67 fermi_integral_type = "build-in"
68
69L_FEA = LorentzNumber_FEA
70
71#mode: 'basic', 'prop', 'Hall', 'init', 'sim', 'fit', 'T', 'calL', 'calF'
72mode = 'sim'
73
74infile = 'SnSeTe-S-Hall.xlsx'
75T_label = r'^T[\s|\(|\[|$]'
76sigma_label = r'^sigma[$|\S]?.*$'
77n_label = r'^N[$|\S]?.*$'
78mu_label = r'^mu[$|\s|\(\[]?.*$'
79S_label = r'^S[$|\s|\(\[]?.*$'
80
81outxlsFjfile = "Fj.xlsx"
82outxlsfFDfile = "fFD.xlsx"
83outxlsPropfile = "properties.xlsx"
84outxlsSLfile = "S-L.xlsx"
85outcsvFitfile = ""
86outcsvLfile = ""
87
88parameterfile = None
89parameterbkfile = None
90outxlsfile = None
91
92# Calculation ranges for mode = 'basic'
93# x = E / kB / T
94xmin_basic = -20.0
95xmax_basic = 20.0
96nx_basic = 401
97xstep_basic = (xmax_basic - xmin_basic) / (nx_basic - 1)
98
99# Calculation ranges for mode = 'prop'
100# x = E / kB / T
101xmin = -30.0
102xmax = 250.0
103nx = 281
104xstep = (xmax - xmin) / (nx - 1)
105
106# Seebeck coefficient
107Smin = 0.0
108Smax = 1.0e-3 # V/K
109nS = 101
110Sstep = (Smax - Smin) / (nS - 1)
111
112# N range
113Nmin = 1.0e15 # cm-3
114Nmax = 1.0e22 # cm-3
115nN = 101
116
117# T range
118T0 = 300.0 # K
119Tmin = 300.0
120Tmax = 800.0
121nT = 6
122
123# read from DOSCAR
124dos = tkDOS()
125dos.meeff = 0.3
126#dos.mheff = 1.0
127#dos.EV = 0.0
128dos.EC = 0.0
129#dos.EA = 0.05 # Acceptor level, eV
130#dos.NA = 0.0e17
131#dos.ED = 1.05 # Donor level
132#dos.ND = 0.0e17
133#dos.EF0 = 0.0 # initial EF to find EF
134
135
136#移動度パラメータ
137mobility = tkMobility()
138# For debug purpose. 1 will use 3-terms polynomial for the inverse of mobility
139mobility.debug = 0
140mobility.use_simple = 0
141#mobility.use_simple = 1
142# charge, effective mass, scattering factor
143mobility.charge = 1.0 # in e, 1.0 for hole, -1.0 for electron
144mobility.meff = dos.meeff # in me
145mobility.rfac = 0.5 # tau = (meff/2)^0.5 * l0(T) * E^(r-0.5)
146mobility.l0 = 1.0e-8 # m
147
148# Lattice thermal conductivity
149klatt = 5.0 # W/m/K
150
151# EF range for mode = 'EF'
152#dEFmin = -1.0 # measured from EV, eV
153#dEFmax = 1.0 # measured from EC, eV
154#dos.nEF = 50
155#dos.Estep = 0.01 # Integration step, eV
156
157epsEF = 1.0e-5
158
159label_sample = None
160xsample = None
161label_S = None
162yS = None
163label_sigma = None
164ysigma = None
165label_N = None
166yN = None
167label_mu = None
168ymu = None
169
170ysigmaini = None
171ymuini = None
172ySini = None
173
174# 最適化パラメータの初期値
175varname = ["meff", "l0"]
176varunit = [ "me", "m"]
177ai0 = []
178optid = [ 1, 1]
179
180
181app = None
182
183
184#=============================================
185# scipy.optimize.minimizeで使うアルゴリズム
186#=============================================
187#nelder-mead Downhill simplex
188#powell Modified Powell
189#cg conjugate gradient (Polak-Ribiere method)
190#bfgs BFGS法
191#newton-cg Newton-CG
192#trust-ncg 信頼領域 Newton-CG 法
193#dogleg 信頼領域 dog-leg 法
194#L-BFGS-B’ (see here)
195#TNC’ (see here)
196#COBYLA’ (see here)
197#SLSQP’ (see here)
198#trust-constr’(see here)
199#dogleg’ (see here)
200#trust-exact’ (see here)
201#trust-krylov’ (see here)
202method = "nelder-mead"
203#method = 'cg'
204#method = 'powell'
205#method = 'bfgs'
206
207maxiter = 1000
208tol = 1.0e-4
209h_diff = 1.0e-3
210outputinterval = 1
211
212Nmin_fit = '*'
213Nmax_fit = '*'
214sigmamin_fit = '*'
215sigmamax_fit = '*'
216
217#=============================
218# Graph configuration
219#=============================
220fig = None
221figsize = (12, 8)
222figsize_sim = (10, 6)
223figsize_small = (8, 6)
224figsize_FD = (8, 6)
225fontsize = 18
226legend_fontsize = 8
227graphupdateinterval = 10
228
229
230#=============================
231# Treat argments
232#=============================
233def parameter_list():
234 """
235 概要:
236 現在の移動度パラメータのリストを返します。
237 戻り値:
238 :returns: 有効質量と平均自由行程プレファクタのタプル。
239 :rtype: tuple
240 """
241 return mobility.meff, mobility.l0
242
243def set_parameters(ai):
244 """
245 概要:
246 引数として与えられた値に基づいて、有効質量と平均自由行程のパラメータを設定します。
247 詳細説明:
248 dos.meeff、dos.NC、dos.DC0、mobility.meff、mobility.l0 を更新し、
249 さらに散乱パラメータを再設定します。
250 引数:
251 :param ai: 設定するパラメータのリスト。最初の要素は有効質量、2番目の要素は平均自由行程プレファクタです。
252 :type ai: list
253 """
254 global dos, mobility
255
256 dos.meeff = ai[0]
257 dos.NC = meff2NC_FEA(dos.meeff, T0)
258 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
259 mobility.meff = ai[0]
260 if len(ai) > 1:
261# print("ai1=", ai[1])
262 mobility.l0 = ai[1]
263 mobility.set_scattering_parameters()
264# print("l0=", mobility.l0)
265
266def read_parameters(path):
267 """
268 概要:
269 指定されたINIファイルからパラメータを読み込み、グローバル変数に設定します。
270 詳細説明:
271 ファイルが存在しない場合は処理をスキップします。
272 主に有効質量、平均自由行程プレファクタ、電荷、散乱因子、EC、T0などの値を読み込みます。
273 引数:
274 :param path: パラメータファイルへのパス。
275 :type path: str
276 """
277 global ai0, optid, T0
278
279 ini = tkIniFile()
280 inf = ini.ReadAll(path, AddSection = 0)
281 if inf is None:
282 return
283
284 ai0 = list(ai0)
285 keylist = ["meff", "l0"]
286 for i in range(2):
287 key = keylist[i]
288 str = inf.get(key, None)
289 val, id = split_optstr(str)
290 if val is not None:
291 ai0[i] = val
292 optid[i] = id
293
294 mobility.meff = pfloat(ai0[0])
295 dos.meeff = pfloat(ai0[0])
296 mobility.l0 = pfloat(ai0[1])
297
298 mobility.charge = pfloat(safe_getelement(inf, "charge", mobility.charge))
299 mobility.rfac = pfloat(safe_getelement(inf, "rfac", mobility.rfac))
300 dos.EC = pfloat(safe_getelement(inf, "EC", dos.EC))
301
302 T0 = pfloat(safe_getelement(inf, "T0", T0))
303
304def save_parameters(path, ai, args):
305 """
306 概要:
307 パラメータと引数を指定されたINIファイルに保存します。
308 引数:
309 :param path: 保存先のINIファイルへのパス。
310 :type path: str
311 :param ai: 保存する最適化パラメータのリスト。
312 :type ai: list
313 :param args: 追加で保存する引数の辞書。
314 :type args: dict
315 """
316 ini = tkIniFile(path)
317 for key in args.keys():
318 ini.WriteString('Preferences', key, args[key])
319
320 for i in range(len(ai)):
321 ini.WriteString('Parameters', varname[i], "{}:{}".format(ai[i], optid[i]))
322
323def save_parameterfile(ai = ai0, S2 = ''):
324 """
325 概要:
326 現在のパラメータとS2値をパラメータファイルに保存します。
327 引数:
328 :param ai: 保存する最適化パラメータのリスト。デフォルトはai0です。
329 :type ai: list
330 :param S2: 最小二乗法によるフィッティング結果のS2値。デフォルトは空文字列です。
331 :type S2: str
332 """
333 save_parameters(parameterfile, ai,
334 {"infile": infile, "T0": T0,
335 "charge": mobility.charge, "rfac": mobility.rfac,
336 "EC": dos.EC, "NC": dos.NC, "DC0": dos.DC0,
337 "S2": S2})
338
339def print_parameters(ai = None):
340 """
341 概要:
342 現在のパラメータの値をコンソールに出力します。
343 引数:
344 :param ai: 出力するパラメータのリスト。Noneの場合、グローバル変数ai0が使用されます。
345 :type ai: list or None
346 """
347 if ai is None:
348 ai = ai0
349 for i in range(len(varname)):
350 print(" {:10s}: {:14.8g} {:6} optid={}".format(varname[i], ai[i], varunit[i], optid[i]))
351
352def usage(app):
353 """
354 概要:
355 スクリプトのコマンドライン引数の使用方法を表示します。
356 引数:
357 :param app: アプリケーションオブジェクト。
358 :type app: tklib.tkapplication.tkApplication
359 """
360 print("")
361 print("Usage: Variables in () are optional")
362 print(" (i) python {} basic".format(sys.argv[0]))
363 print(" Plot basic functions")
364 print(" (ii) python {} prop T meff r l0 kappa_latt".format(sys.argv[0]))
365 print(" meff in me0, l0 in m, kappa_latt in W/m/K")
366 print(" Plot Seebeck related properties")
367 print(" ex: python {} basic {} {} {} {} {}".format(sys.argv[0], T0, dos.meeff, mobility.rfac, mobility.l0, klatt))
368 print(" (ii') python {} Hall T meff r l0".format(sys.argv[0]))
369 print(" Plot Hall related properties")
370 print(" ex: python {} Hall {} {} {} {}".format(sys.argv[0], T0, dos.meeff, mobility.rfac, mobility.l0))
371 print(" (iii) python {} init infile".format(sys.argv[0]))
372 print(" Create .in file")
373 print(" (iv) python {} sim infile T meff r l0".format(sys.argv[0]))
374 print(" Calculate weighted mobility etc from input file")
375 print(" Plot Jonker / Pisarenko plots")
376 print(" ex: python {} sim {} {} {} {} {}".format(sys.argv[0], infile, T0, dos.meeff, mobility.rfac, mobility.l0))
377 print(" (v) python {} fit T meff r l0".format(sys.argv[0]))
378 print(" Fit to Jonker / Pisarenko plots")
379 print(" ex: python {} fit {} {} {} {} {}".format(sys.argv[0], infile, T0, mobility.meff, mobility.rfac, mobility.l0))
380 print(" (vi) python {} T infile Tmin Tmax nT".format(sys.argv[0]))
381 print(" Simulate T dependences")
382 print(" ex: python {} fit {} {} {} {}".format(sys.argv[0], infile, Tmin, Tmax, nT))
383 print(" (vii) python {} calL infile meff r l0 ".format(sys.argv[0]))
384 print(" Calculate L and kappa,e from T, Ne and sigma")
385 print(" ex: python {} calL {} {} {} {}".format(sys.argv[0], infile, dos.meeff, mobility.rfac, mobility.l0))
386 print(" (viii) python {} calF infile meff r l0 T_label n_label mu_label sigma_label".format(sys.argv[0]))
387 print(" Calculate FHall from T, Ne and mu")
388 print(" ex: python {} calF {} {} {} {} {} {} {}".format(sys.argv[0], infile, dos.meeff, mobility.rfac, mobility.l0,
389 T_label, n_label, mu_label, sigma_label))
390
391def updatevars():
392 """
393 概要:
394 コマンドライン引数に基づいて、グローバル変数を更新します。
395 詳細説明:
396 スクリプトの実行モード (basic, prop, Hall, init, sim, fit, T, calL, calF, help, usage) に応じて、
397 入力ファイル、ラベル、温度、有効質量、散乱因子、平均自由行程プレファクタなどのパラメータを設定します。
398 無効なモードが指定された場合はエラーで終了します。
399 """
400 global mode, infile, outxlsxfile, parameterfile, parameterbkfile
401 global T_label, n_label, mu_label, sigma_label, S_label
402 global mobility, dos, klatt
403 global T0, Tmin, Tmax, nT
404 global ai0, optid
405 global method, tol, maxiter, h_diff
406 global Nmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fit
407
408 argv = sys.argv
409# if len(argv) == 1:
410# usage()
411# exit()
412
413 mode = getarg( 1, mode)
414 if mode == 'basic':
415 pass
416 elif mode == 'prop':
417 T0 = getfloatarg(2, T0)
418 dos.meeff = getfloatarg(3, dos.meeff)
419 mobility.rfac = getfloatarg(4, mobility.rfac)
420 mobility.l0 = getfloatarg(5, mobility.l0)
421 klatt = getfloatarg(6, klatt)
422 elif mode == 'Hall':
423 T0 = getfloatarg(2, T0)
424 dos.meeff = getfloatarg(3, dos.meeff)
425 mobility.rfac = getfloatarg(4, mobility.rfac)
426 mobility.l0 = getfloatarg(5, mobility.l0)
427 elif mode == 'init':
428 infile = getarg (2, infile)
429 elif mode == 'sim':
430 infile = getarg ( 2, infile)
431 T_label = getarg ( 3, T_label)
432 n_label = getarg ( 4, n_label)
433 mu_label = getarg ( 5, mu_label)
434 sigma_label = getarg ( 6, sigma_label)
435 S_label = getarg ( 7, S_label)
436 T0 = getfloatarg( 8, T0)
437 dos.meeff = getfloatarg( 9, dos.meeff)
438 mobility.rfac = getfloatarg(10, mobility.rfac)
439 mobility.l0 = getfloatarg(11, mobility.l0)
440 elif mode == 'fit':
441 infile = getarg (2, infile)
442 T_label = getarg (3, T_label)
443 n_label = getarg (4, n_label)
444 mu_label = getarg (5, mu_label)
445 sigma_label = getarg (6, sigma_label)
446 S_label = getarg (7, S_label)
447 T0 = getfloatarg(8, T0)
448 dos.meeff = getfloatarg(9, dos.meeff)
449 mobility.rfac = getfloatarg(10, mobility.rfac)
450 mobility.l0 = getfloatarg(11, mobility.l0)
451 method = getarg (12, method)
452 tol = getfloatarg(13, tol)
453 maxiter = getintarg (14, maxiter)
454 Nmin_fit = getarg (15, Nmin_fit)
455 Nmax_fit = getarg (16, Nmax_fit)
456 sigmamin_fit = getarg (17, sigmamin_fit)
457 sigmamax_fit = getarg (18, sigmamax_fit)
458 elif mode == 'T':
459 infile = getarg (2, infile)
460 Tmin = getfloatarg(3, Tmin)
461 Tmax = getfloatarg(4, Tmax)
462 nT = getintarg (5, nT)
463 elif mode == 'calL' or mode == 'calF':
464 infile = getarg (2, infile)
465 T_label = getarg (3, T_label)
466 n_label = getarg (4, n_label)
467 mu_label = getarg (5, mu_label)
468 sigma_label = getarg (6, sigma_label)
469 dos.meeff = getfloatarg(7, dos.meeff)
470 mobility.rfac = getfloatarg(8, mobility.rfac)
471 mobility.l0 = getfloatarg(9, mobility.l0)
472 elif mode == 'help' or mode == 'usage':
473 app.terminate("", usage = usage, pause = True)
474 else:
475 app.terminate("Error in updatevars(): Invalid mode {}".format(mode), usage = usage, pause = True)
476
477 mobility.meff = dos.meeff
478 mobility.set_scattering_parameters(mobility.l0, mobility.rfac)
479
480 ai0 = parameter_list()
481
482
483def basic():
484 """
485 概要:
486 フェルミ・ディラック分布とフェルミ積分の基本計算を実行し、結果をファイルに出力し、プロットします。
487 詳細説明:
488 x軸を E / kB / T として、電子のフェルミ・ディラック分布、正孔のフェルミ・ディラック分布、
489 -df/dx、およびそれらの近似値を計算します。
490 また、フェルミ積分 F_r(x) (r=0, 0.5, 1.0, 1.5, 2.0) の値を計算し、理論値 (exp(x) * Gamma(r+1)) と比較します。
491 計算結果はoutxlsfFDfileとoutxlsFjfileに保存され、matplotlibでプロットされます。
492 """
493 global mobility, dos
494
495 print("")
496 print("mode:", mode)
497
498 print("")
499 print("Fermi-Dirac distribution")
500 xx = []
501 yfFD = []
502 yfFDh = []
503 ymdfdx = []
504 yfFDapprox = []
505 print("{:8}\t{:12}\t{:12}\t{:12}\t{:12}".format("x=E/kBT", "fFDe(exact)", "fFDe(approx)", "fFDh(exact)", "-df/dx"))
506 for i in range(nx_basic):
507 x = xmin_basic + i * xstep_basic
508 xx.append(x)
509 fFD = 1.0 / (exp(x) + 1.0)
510 fFDh = 1.0 / (exp(-x) + 1.0)
511 mdfdx = fFD * fFDh
512 fFDa = 0.5 - 0.25 * x + 1.0 / 48.0 * x**3 - 1.0 / 64.0 * x**5
513
514 yfFD.append(fFD)
515 yfFDh.append(fFDh)
516 ymdfdx.append(mdfdx)
517 yfFDapprox.append(fFDa)
518
519 print("{:8.4g}\t{:12.4g}\t{:12.4g}\t{:12.4g}\t{:12.4g}".format(x, fFD, fFDa, fFDh, mdfdx))
520
521 print("")
522 print("Fermi integrals")
523 yF00 = []
524 yF05 = []
525 yF10 = []
526 yF15 = []
527 yF20 = []
528 yG00 = []
529 yG05 = []
530 yG10 = []
531 yG15 = []
532 yG20 = []
533 print("{:12}\t{:12}\t{:12}\t{:12}\t{:12}\t{:12}\t{:12}".format("x=EF/kBT", "F0", "F1/2", "F1", "F3/2", "F2" "exp(x)", "Gamma(1)"))
534 for i in range(nx_basic):
535 x = xx[i]
536 for j in range(3):
537 eta = j / 2.0
538 y0 = FermiIntegral(x, j)
539 y1 = FermiIntegral_x2(x, j)
540 validate_error(y0, y1, 2.0e-6, "Error in basic() for F{}: ".format(eta))
541
542 yF00.append(FermiIntegral(x, 0.0))
543 yF05.append(FermiIntegral(x, 0.5))
544 yF10.append(FermiIntegral(x, 1.0))
545 yF15.append(FermiIntegral(x, 1.5))
546 yF20.append(FermiIntegral(x, 2.0))
547 yG00.append(exp(x) * gamma(1.0))
548 yG05.append(exp(x) * gamma(1.5))
549 yG10.append(exp(x) * gamma(2.0))
550 yG15.append(exp(x) * gamma(2.5))
551 yG20.append(exp(x) * gamma(3.0))
552 if i % 10 == 0:
553 print("{:12.4g}\t{:12.4g}\t{:12.4g}\t{:12.4g}\t{:12.4g}\t{:12.4g}\t{:12.4g}"
554 .format(x, yF00[i], yF05[i], yF10[i], yF15[i], yF20[i], yG00[i]))
555
556 print("")
557 print("Save data to [{}]".format(outxlsfFDfile))
558 tkVariousData().to_excel(outxlsfFDfile, ["x=E/kBT", "fFD(exact)", "fFD(approx)", "fFDh(exact)", "-df/dx"],
559 [xx, yfFD, yfFDapprox, yfFDh, ymdfdx])
560
561 print("Save data to [{}]".format(outxlsFjfile))
562 tkVariousData().to_excel(outxlsFjfile, ["x=EF/kBT", "F0", "F1/2", "F1", "F3/2", "F2", "exp(x)*G(1)",
563 "exp(x)*G(1.5)", "exp(x)*G(2)", "exp(x)*G(2.5)", "exp(x)*G(3)"],
564 [xx, yF00, yF05, yF10, yF15, yF20, yG00, yG05, yG10, yG15, yG20])
565
566
567#=============================
568# グラフの表示
569#=============================
570 print("")
571
572 fig = plt.figure(figsize = figsize_FD)
573
574 ax2 = fig.add_subplot(2, 1, 1)
575 ax3 = fig.add_subplot(2, 1, 2)
576
577 ax2.plot(xx, yfFD, label = '$f_{FD,e}(exact)$', linestyle = '-', color = 'black', linewidth = 0.5)
578 ax2.plot(xx, yfFDh, label = '$f_{FD,h}(exact)$', linestyle = '-', color = 'blue', linewidth = 0.5)
579 ax2.plot(xx, yfFDapprox, label = '$f_{FD}(approx)$', linestyle = '-', color = 'green', linewidth = 0.5)
580 ax2.plot(xx, ymdfdx, label = '$-df/dx$', linestyle = 'dashed', color = 'red', linewidth = 0.5)
581 ax2.set_xlabel("$x=(E-E_F)/k_BT$ (eV)", fontsize = fontsize)
582 ax2.set_ylabel("$f_{FD}$, $-df/dx$", fontsize = fontsize)
583 ax2.set_xlim([-10.0, 10.0])
584 ax2.set_ylim([-0.1, 1.1])
585 ax2.legend(fontsize = legend_fontsize)
586 ax2.tick_params(labelsize = fontsize)
587
588 ax3.plot(xx, yF00, label = '$F_0$', linestyle = '-', color = 'black', linewidth = 0.5)
589 ax3.plot(xx, yF05, label = '$F_{1/2}$', linestyle = '-', color = 'red', linewidth = 0.5)
590 ax3.plot(xx, yF10, label = '$F_1$', linestyle = '-', color = 'blue', linewidth = 0.5)
591 ax3.plot(xx, yF15, label = '$F_{3/2}$', linestyle = '-', color = 'purple', linewidth = 0.5)
592 ax3.plot(xx, yF20, label = '$F_2$', linestyle = '-', color = 'green', linewidth = 0.5)
593 ax3.plot(xx, yG00, label = r'$e^x$$\Gamma(1)$', linestyle = '', marker = 'o', markerfacecolor = 'black', markersize = 1)
594 ax3.plot(xx, yG05, label = r'$e^x$$\Gamma(3/2)$', linestyle = '', marker = 'o', markerfacecolor = 'red', markersize = 1)
595 ax3.plot(xx, yG10, label = r'$e^x$$\Gamma(2)$', linestyle = '', marker = 'o', markerfacecolor = 'blue', markersize = 1)
596 ax3.plot(xx, yG15, label = r'$e^x$$\Gamma(5/2)$', linestyle = '', marker = 'o', markerfacecolor = 'purple', markersize = 1)
597 ax3.plot(xx, yG20, label = r'$e^x$$\Gamma(3)$', linestyle = '', marker = 'o', markerfacecolor = 'green', markersize = 1)
598 ax3.set_xlabel("$x=E_F/k_BT$ (eV)", fontsize = fontsize)
599 ax3.set_ylabel("$F_r$", fontsize = fontsize)
600 ax3.set_xlim([-10.0, 10.0])
601 ax3.set_ylim([1.0e-5, 0.1e4])
602 ax3.set_yscale('log')
603 ax3.legend(fontsize = legend_fontsize)
604 ax3.tick_params(labelsize = fontsize)
605
606 plt.tight_layout()
607 plt.pause(0.1)
608
609 app.terminate("", pause = True)
610
611def Hall():
612 """
613 概要:
614 ホール係数、ホール因子、ホール移動度などのHall特性を計算し、結果をファイルに出力し、プロットします。
615 詳細説明:
616 指定された温度T0と有効質量meff、散乱因子rfac、平均自由行程プレファクタl0に基づいて、
617 フェルミ準位の掃引に対するキャリア濃度、電気伝導率、移動度、 Hall係数、Hall因子、Hall移動度を計算します。
618 計算結果はoutxlsPropfileに保存され、matplotlibでプロットされます。
619 """
620 print("")
621 print("Carrier:")
622 print(" q={} e".format(mobility.charge))
623 print(" meff={}me".format(dos.meeff))
624 dos.NC = meff2NC_FEA(dos.meeff, T0)
625 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
626 if mobility.charge < 0.0:
627 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
628 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
629 else:
630 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
631 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
632 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
633 print(" mean free path prefactor: l0={} m".format(mobility.l0))
634
635 print("")
636 print(f"Calculat Hall coefficient, Hall factor, and Hall mobility at {T0} K")
637 xx = []
638 yEF = []
639 yNe = []
640 ysigma = []
641 ymu = []
642 ytau = []
643 yRH0 = []
644 yRH = []
645 yFH = []
646 yNe_Hall = []
647 ymu_Hall = []
648 print("{:>8} {:>8} {:>12} {:>12} {:>12} {:>12} {:>12}"
649 .format("x=EF/kBT", "EF(eV)", "N(cm^-3)", "sigma(S/cm)", "mu(cm2/Vs)", "FH", "RH(m^3/C"))
650 for i in range(nx):
651 x = xmin + i * xstep
652 EF = x * kB * T0 / e
653
654 inf = dos.cal_Hall_properteis(T0, EF, mobility, validate_error_str = 'Error in properteis()')
655
656 sigma = inf["sigma"]
657 Ne = inf["n"]
658 mu = inf["mu"]
659 tau = inf["<tau>"]
660 FH = inf["FH"]
661 RH = inf["RH"]
662 RH0 = inf["RH0"]
663 n_Hall = inf["nHall"]
664 mu_Hall = inf["muHall"]
665
666 xx.append(x)
667 yEF.append(EF)
668 yNe.append(Ne)
669 ysigma.append(sigma)
670 ymu.append(mu)
671 ytau.append(tau)
672 yRH0.append(RH0)
673 yRH.append(RH)
674 yFH.append(FH)
675 yNe_Hall.append(n_Hall)
676 ymu_Hall.append(mu_Hall)
677
678 if i % 10 == 0:
679 print("{:8.3g} {:8.3g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g}"
680 .format(x, EF, yNe[i], ysigma[i], ymu[i], yFH[i], yRH[i]))
681
682 print("")
683 print("Save data to [{}]".format(outxlsPropfile))
684 tkVariousData().to_excel(outxlsPropfile, ["x=EF/kBT", "EF(eV)", "N(cm^-3)", "sigma(S/cm)", "mu(cm2/Vs)", "FH", "RH(m^3/C"],
685 [xx, yEF, yNe, ysigma, ymu, yFH, yRH])
686
687
688#=============================
689# グラフの表示
690#=============================
691 print("")
692 fig = plt.figure(figsize = figsize)
693
694 axtau = fig.add_subplot(3, 3, 1)
695 axNe = fig.add_subplot(3, 3, 2)
696 axsigma = fig.add_subplot(3, 3, 3)
697 axmu = fig.add_subplot(3, 3, 4)
698 aRH = fig.add_subplot(3, 3, 5)
699 aFH = fig.add_subplot(3, 3, 6)
700 aNeRH = fig.add_subplot(3, 3, 7)
701 aNeFH = fig.add_subplot(3, 3, 8)
702
703 axsigma.set_title("$T_0$={} K $m^*$={}$m_e$ r={} $k_l$$_a$$_t$$_t$={} W/m/K".format(T0, dos.meeff, mobility.rfac, klatt))
704
705 axtau.plot(xx, ytau, label = '$\\tau(EF)$', linestyle = '-', color = 'red', linewidth = 0.5)
706# axtau.plot(xx, ytauavg, label = '<$\\tau$>', linestyle = '-', color = 'blue', linewidth = 0.5)
707 axtau.set_xlabel("$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
708 axtau.set_ylabel("$\\tau$ (fs)", fontsize = fontsize)
709 axtau.set_ylim([0.0, max(ytau) * 1.1])
710 axtau.legend(fontsize = legend_fontsize, loc = 'best')
711 axtau.tick_params(labelsize = fontsize)
712
713 axNe.plot(xx, yNe, label = '$N_e$', linestyle = '-', color = 'red', linewidth = 1.0)
714 axNe.plot(xx, yNe_Hall, label = '$N_e$$_{,Hall}$', linestyle = '-', color = 'blue', linewidth = 1.0)
715 axNe.set_xlabel("$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
716 axNe.set_ylabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
717 axNe.set_yscale('log')
718 axNe.legend(fontsize = legend_fontsize, loc = 'best')
719 axNe.tick_params(labelsize = fontsize)
720
721# axsigma.plot(xx, ysigma, label = r'$\sigma$', linestyle = '-', color = 'red', linewidth = 1.0)
722 axsigma.plot(yNe_Hall, ysigma, label = r'$\sigma$', linestyle = '-', color = 'red', linewidth = 1.0)
723# axsigma.set_xlabel(r"$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
724 axsigma.set_xlabel(r"$N_e$$_{,Hall}$ (cm$^{-3}$)", fontsize = fontsize)
725 axsigma.set_ylabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
726 axsigma.set_xscale('log')
727 axsigma.set_yscale('log')
728 axsigma.set_xlim([1.0e10, 1.0e23])
729 axsigma.legend(fontsize = legend_fontsize, loc = 'best')
730 axsigma.tick_params(labelsize = fontsize)
731
732# axmu.plot(xx, ymu, label = r'$\mu$', linestyle = '-', color = 'red', linewidth = 1.0)
733 axmu.plot(yNe_Hall, ymu, label = r'$\mu$', linestyle = '-', color = 'red', linewidth = 1.0)
734# axmu.plot(xx, ymu_Hall, label = r'$\mu$$_{,Hall}$', linestyle = '-', color = 'blue', linewidth = 1.0)
735 axmu.plot(yNe_Hall, ymu_Hall, label = r'$\mu$$_{,Hall}$', linestyle = '-', color = 'blue', linewidth = 1.0)
736# axmu.set_xlabel(r"$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
737 axmu.set_xlabel(r"$N_e$$_{,Hall}$ (cm$^{-3}$)", fontsize = fontsize)
738 axmu.set_ylabel(r"$\mu$ (cm$^2$/V/s)", fontsize = fontsize)
739 axmu.set_xscale('log')
740 axmu.set_xlim([1.0e10, 1.0e23])
741 axmu.legend(fontsize = legend_fontsize, loc = 'best')
742 axmu.tick_params(labelsize = fontsize)
743
744# aRH.plot(xx, yRH0, label = r'$R_H$$_0$=$1/e/N_e$', linestyle = '-', color = 'red', linewidth = 1.0)
745 aRH.plot(yNe_Hall, yRH0, label = r'$R_H$$_0$=$1/e/N_e$', linestyle = '-', color = 'red', linewidth = 1.0)
746# aRH.plot(xx, yRH, label = r'$R_H$$_{,Hall}$', linestyle = '-', color = 'blue', linewidth = 1.0)
747 aRH.plot(yNe_Hall, yRH, label = r'$R_H$$_{,Hall}$', linestyle = '-', color = 'blue', linewidth = 1.0)
748# aRH.set_xlabel(r"$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
749 aRH.set_xlabel(r"$N_e$$_{,Hall}$ (cm$^{-3}$)", fontsize = fontsize)
750 aRH.set_ylabel(r"$R_H$ (cm$^3$/C)", fontsize = fontsize)
751 aRH.set_xscale('log')
752 aRH.set_yscale('log')
753 aRH.set_xlim([1.0e10, 1.0e23])
754 aRH.legend(fontsize = legend_fontsize, loc = 'best')
755 aRH.tick_params(labelsize = fontsize)
756
757# aFH.plot(xx, yFH, label = r'$F_{Hall}$', linestyle = '-', color = 'red', linewidth = 1.0)
758 aFH.plot(yNe_Hall, yFH, label = r'$F_{Hall}$', linestyle = '-', color = 'red', linewidth = 1.0)
759# aFH.set_xlabel(r"$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
760 aFH.set_xlabel(r"$N_e$$_{,Hall}$ (cm$^{-3}$)", fontsize = fontsize)
761 aFH.set_ylabel("$F_H$", fontsize = fontsize)
762 aFH.set_xscale('log')
763 aFH.set_xlim([1.0e10, 1.0e23])
764 aFH.legend(fontsize = legend_fontsize, loc = 'best')
765 aFH.tick_params(labelsize = fontsize)
766
767 aNeRH.plot(yNe_Hall, yRH, label = r'$R_H$$_{,Hall}$', linestyle = '-', color = 'red', linewidth = 1.0)
768 aNeRH.set_xlabel(r"$N_e$$_{,Hall}$ (cm$^{-3}$)", fontsize = fontsize)
769 aNeRH.set_ylabel(r"$R_H$ (cm$^3$/C)", fontsize = fontsize)
770 aNeRH.set_xscale('log')
771 aNeRH.set_yscale('log')
772 aNeRH.set_xlim([1.0e10, 1.0e23])
773# aNeRH.set_ylim([min(yRH) * 0.5, min(yRH) * 1.0e3])
774# aNeRH.legend(fontsize = legend_fontsize, loc = 'best')
775 aNeRH.tick_params(labelsize = fontsize)
776
777 aNeFH.plot(yNe_Hall, yFH, label = r'$N_e$', linestyle = '-', color = 'red', linewidth = 1.0)
778 aNeFH.set_xlabel(r"$N_e$$_{,Hall}$ (cm$^{-3}$)", fontsize = fontsize)
779 aNeFH.set_ylabel(r"$F_H$ (cm$^{-3}$)", fontsize = fontsize)
780 aNeFH.set_xscale('log')
781 aNeFH.set_xlim([1.0e10, 1.0e23])
782# aNeFH.legend(fontsize = legend_fontsize, loc = 'best')
783 aNeFH.tick_params(labelsize = fontsize)
784
785 plt.tight_layout()
786 plt.pause(0.1)
787
788 app.terminate("", pause = True)
789
790def properties():
791 """
792 概要:
793 Seebeck係数に関連する熱電特性を計算し、結果をファイルに出力し、プロットします。
794 詳細説明:
795 指定された温度T0と有効質量meff、散乱因子rfac、平均自由行程プレファクタl0、格子熱伝導率klattに基づいて、
796 フェルミ準位の掃引に対するキャリア濃度、電気伝導率、移動度、Seebeck係数、電子熱伝導率、
797 全熱伝導率、ローレンツ数、力率、ZT値を計算します。
798 また、非縮退および縮退近似でのSeebeck係数も計算し、比較します。
799 計算結果はoutxlsPropfileに保存され、matplotlibでプロットされます。
800 """
801 global mobility, dos
802
803 print("")
804 print("mode:", mode)
805 print("T={} K".format(T0))
806 print("meff:", dos.meeff)
807 dos.NC = meff2NC_FEA(dos.meeff, T0)
808 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
809 if mobility.charge < 0.0:
810 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
811 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
812 else:
813 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
814 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
815 print(" scattering factor in tau(E) prop to E^(r-0.5) (non-degenerated) r={}".format(mobility.rfac))
816 print("Lorentz number")
817 print(" Free electron model: {:12.8g} Wohm/K^2".format(L_FEA))
818 print("Mean free path prefactor: l0={} m".format(mobility.l0))
819 print("Lattice thermal conductivity: klatt={} W/K".format(klatt))
820
821 print("")
822 print("Properties")
823 xx = []
824 xx_tau = []
825 yEF = []
826 yNe = []
827 ysigma = []
828 ymu = []
829 ytau = []
830 ytauavg = []
831 yS = []
832 ySndeg = []
833 ySdeg = []
834 ykappa = []
835 ykappatot = []
836 yL = []
837 yLapprox = []
838 yPF = []
839 yZT = []
840 print("{:>8} {:>8} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12}"
841 .format("x=EF/kBT", "EF(eV)", "N(cm^-3)", "sigma(S/cm)", "mu(cm2/Vs)", "<tau>(fs)",
842 "S(uV/K)", "Snon-deg", "Sdeg", "kappa,e(W/m/K)", "kappa,tot", "L(Wohm/K^2)", "Lapprox", "PF(uW/cm/K^2)", "ZT"))
843 for i in range(nx):
844 x = xmin + i * xstep
845 EF = x * kB * T0 / e
846
847# print("T=", T0)
848 sigma, n, mu, tau_avg, S, kappa, kappa_tot, L, PF, ZT, inf \
849 = dos.cal_transport_properteis(T0, EF, mobility, klatt, validate_error_str = 'Error in properteis()')
850
851# Relaxation time tau(EF)
852 if EF <= 0.0:
853 tau = None
854 else:
855 tau = mobility.tau(T0, EF) * 1.0e15 # fs, E in eV
856 if EF > 0.0:
857 xx_tau.append(x)
858 ytau.append(tau)
859
860 Sndeg = dos.cal_S_nondegenerated_from_Ne(n, mobility.rfac, charge = mobility.charge) * 1.0e6 # uV/K
861 Sdeg = dos.cal_S_degenerated_from_Ne(T0, n, mobility.rfac, charge = mobility.charge) * 1.0e6 # uV/K
862
863# Approximated Lorentz number
864 Lapprox = dos.cal_LorentzNumber_from_S_approximate(S)
865
866 xx.append(x)
867 yEF.append(EF)
868 yNe.append(n)
869 ysigma.append(sigma)
870 ymu.append(mu)
871 ytauavg.append(tau_avg)
872 yS.append(S)
873 ySndeg.append(Sndeg)
874 ySdeg.append(Sdeg)
875 ykappa.append(kappa)
876 ykappatot.append(kappa + klatt)
877 yL.append(L)
878 yLapprox.append(Lapprox)
879 yPF.append(PF)
880 yZT.append(ZT)
881 if i % 10 == 0:
882 print("{:8.3g} {:8.3g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g}"
883 .format(x, EF, n, sigma, mu, tau_avg, S, Sndeg, Sdeg, kappa, kappa_tot, L, Lapprox, PF, ZT))
884
885 print("")
886 print("Save data to [{}]".format(outxlsPropfile))
887 tkVariousData().to_excel(outxlsPropfile, ["x=EF/kBT", "EF(eV)", "N(cm^-3)", "sigma(S/cm)", "mu(cm2/Vs)", "<tau>(fs)",
888 "S(uV/K)", "Snon-deg", "Sdeg", "kappa,e(W/m/K)", "kappa,tot(W/m/K)", "L(Wohm/K^2)", "Lapprox", "PF(uW/cm/K^2)", "ZT"],
889 [xx, yEF, yNe, ysigma, ymu, ytauavg, yS, ySndeg, ySdeg, ykappa, ykappatot, yL, yLapprox, yPF, yZT])
890
891
892#=============================
893# グラフの表示
894#=============================
895 print("")
896 maxS = max(yS)
897 minS = min(yS)
898 if maxS > 0.0:
899 maxS *= 1.2
900 else:
901 maxS = 0.0
902 if minS > 0.0:
903 minS = 0.0
904 else:
905 minS *= 2.0
906
907 fig = plt.figure(figsize = figsize)
908
909 axtau = fig.add_subplot(3, 4, 1)
910 axNe = fig.add_subplot(3, 4, 2)
911 axsigma = fig.add_subplot(3, 4, 3)
912 axmu = fig.add_subplot(3, 4, 4)
913 axS = fig.add_subplot(3, 4, 5)
914 axke = fig.add_subplot(3, 4, 6)
915 axPF = fig.add_subplot(3, 4, 7)
916 axZT = fig.add_subplot(3, 4, 8)
917 axL1 = fig.add_subplot(3, 4, 9)
918 axL2 = fig.add_subplot(3, 4, 10)
919 axLS = fig.add_subplot(3, 4, 11)
920
921 axsigma.set_title(r"$T_0$={} K $m^*$={}$m_e$ r={} $k_l$$_a$$_t$$_t$={} W/m/K".format(T0, dos.meeff, mobility.rfac, klatt))
922
923 axtau.plot(xx_tau, ytau, label = '$\\tau(EF)$', linestyle = '-', color = 'red', linewidth = 0.5)
924 axtau.plot(xx, ytauavg, label = '<$\\tau$>', linestyle = '-', color = 'blue', linewidth = 0.5)
925 axtau.set_xlabel("$E$ (eV)", fontsize = fontsize)
926 axtau.set_ylabel("$\\tau$ (fs)", fontsize = fontsize)
927 axtau.set_ylim([0.0, max(ytau) * 1.1])
928 axtau.legend(fontsize = legend_fontsize, loc = 'best')
929 axtau.tick_params(labelsize = fontsize)
930
931 axNe.plot(xx, yNe, label = '$N_e$', linestyle = '-', color = 'red', linewidth = 1.0)
932 axNe.set_xlabel("$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
933 axNe.set_ylabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
934 axNe.set_yscale('log')
935 axNe.legend(fontsize = legend_fontsize, loc = 'best')
936 axNe.tick_params(labelsize = fontsize)
937
938# axsigma.plot(xx, ysigma, label = r'$\sigma$', linestyle = '-', color = 'red', linewidth = 1.0)
939 axsigma.plot(yNe, ysigma, label = r'$\sigma$', linestyle = '-', color = 'red', linewidth = 1.0)
940# axsigma.set_xlabel(r"$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
941 axsigma.set_xlabel(r"$N_e$ (cm$^{-3}$)", fontsize = fontsize)
942 axsigma.set_ylabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
943 axsigma.set_xscale('log')
944 axsigma.set_yscale('log')
945 axsigma.legend(fontsize = legend_fontsize, loc = 'best')
946 axsigma.tick_params(labelsize = fontsize)
947
948# axmu.plot(xx, ymu, label = '$\\mu$', linestyle = '-', color = 'red', linewidth = 1.0)
949 axmu.plot(yNe, ymu, label = '$\\mu$', linestyle = '-', color = 'red', linewidth = 1.0)
950# axmu.set_xlabel("$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
951 axmu.set_xlabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
952 axmu.set_ylabel("$\\mu$ (cm$^2$/V/s)", fontsize = fontsize)
953 axmu.set_xscale('log')
954 axmu.legend(fontsize = legend_fontsize, loc = 'best')
955 axmu.tick_params(labelsize = fontsize)
956
957 axke.plot(yNe, ykappa, label = '$\\kappa$$_e$', linestyle = '-', color = 'red', linewidth = 1.0)
958 axke.set_xlabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
959# axke.set_xlabel("$x=(E_F-E_C)/k_BT$ (eV)", fontsize = fontsize)
960 axke.set_ylabel("$\\kappa$$_e$ (W/m/K)", fontsize = fontsize)
961 axke.set_xscale('log')
962 axke.set_yscale('log')
963 axke.legend(fontsize = legend_fontsize, loc = 'best')
964 axke.tick_params(labelsize = fontsize)
965
966 axS.plot(yNe, yS, label = '$S$', linestyle = '-', color = 'black', linewidth = 1.0)
967 axS.plot(yNe, ySndeg, label = '$S_{non-deg}$', linestyle = 'dashed', color = 'red', linewidth = 0.5)
968 axS.plot(yNe, ySdeg, label = '$S_{deg}$', linestyle = 'dashed', color = 'blue', linewidth = 0.5)
969 axS.set_xlabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
970 axS.set_ylabel(r"$S$ ($\mu$V/K)", fontsize = fontsize)
971 axS.set_xscale('log')
972 axS.set_ylim([minS, maxS])
973 axS.legend(fontsize = legend_fontsize, loc = 'best')
974 axS.tick_params(labelsize = fontsize)
975
976 axPF.plot(yNe, yPF, label = '$PF$', linestyle = '-', color = 'black', linewidth = 1.0)
977 axPF.set_xlabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
978 axPF.set_ylabel(r"$PF$ ($\mu$W/cm/K$^2$)", fontsize = fontsize)
979 axPF.set_xscale('log')
980 axPF.legend(fontsize = legend_fontsize, loc = 'best')
981 axPF.tick_params(labelsize = fontsize)
982
983 axZT.plot(yNe, yZT, label = '$ZT$', linestyle = '-', color = 'black', linewidth = 1.0)
984 axZT.set_xlabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
985 axZT.set_ylabel("$ZT$", fontsize = fontsize)
986 axZT.set_xscale('log')
987 axZT.legend(fontsize = legend_fontsize, loc = 'best')
988 axZT.tick_params(labelsize = fontsize)
989
990# axL1.plot(xx, yL, label = 'L(cal)', linestyle = '-', linewidth = 0.5)
991 axL1.plot(yNe, yL, label = 'L(cal)', linestyle = '-', linewidth = 0.5)
992 axL1.plot([min(xx), max(xx)], [L_FEA, L_FEA], label = 'L(FEA deg)', linestyle = '-', color = 'red', linewidth = 0.5)
993# axL1.set_xlabel("$x=(E_F-E_C)/k_B/T$", fontsize = fontsize)
994 axL1.set_xlabel(r"$N_e$ (cm$^{-3}$)", fontsize = fontsize)
995 axL1.set_ylabel(r"$L=\kappa_e/\sigma/T$ (W$\Omega$/K$^2$)", fontsize = fontsize)
996 axL1.set_ylim([0.0, 3.2e-8])
997 axL1.legend(fontsize = legend_fontsize, loc = 'best')
998 axL1.tick_params(labelsize = fontsize)
999
1000 axL2.plot(yNe, yL, label = 'L(cal)', linestyle = '-', linewidth = 0.5)
1001 axL2.plot([min(yNe), max(yNe)], [L_FEA, L_FEA], label = 'L(FEA deg)', linestyle = '-', color = 'red', linewidth = 0.5)
1002 axL2.set_xlabel(r"$N_e$ (cm$^{-3}$)", fontsize = fontsize)
1003 axL2.set_ylabel(r"$L=\kappa_e/\sigma/T$ (W$\Omega$/K$^2$)", fontsize = fontsize)
1004 axL2.set_xscale('log')
1005 axL2.set_xlim([1.0e10, 1.0e23])
1006 axL2.set_ylim([0.0, 3.2e-8])
1007 axL2.legend(fontsize = legend_fontsize, loc = 'best')
1008 axL2.tick_params(labelsize = fontsize)
1009
1010 axLS.plot(yS, yL, label = 'L(cal)', linestyle = '-', color = 'red', linewidth = 1.0)
1011 axLS.plot(yS, yLapprox, label = 'L(approx, r=0)', linestyle = '-', color = 'blue', linewidth = 0.5)
1012 axLS.plot([min(yS), max(yS)], [L_FEA, L_FEA], label = 'L(FEA deg)', linestyle = '-', color = 'red', linewidth = 0.5)
1013 axLS.set_xlabel(r"$S$ ($\mu$V/K)", fontsize = fontsize)
1014 axLS.set_ylabel(r"$L=\kappa_e/\sigma/T$ (W$\Omega$/K$^2$)", fontsize = fontsize)
1015 axLS.set_ylim([0.0, 3.2e-8])
1016 axLS.legend(fontsize = legend_fontsize, loc = 'best')
1017 axLS.tick_params(labelsize = fontsize)
1018
1019 plt.tight_layout()
1020 plt.pause(0.1)
1021
1022 app.terminate("", pause = True)
1023
1024def recover_parameters(ais, optid, aidef0):
1025 """
1026 概要:
1027 最適化されたパラメータのサブセットから完全なパラメータリストを再構築します。
1028 引数:
1029 :param ais: 最適化されたパラメータのサブセット。
1030 :type ais: list
1031 :param optid: 各パラメータが最適化対象かどうかを示すIDのリスト (1は最適化対象、0は固定)。
1032 :type optid: list
1033 :param aidef0: デフォルトのパラメータ値のリスト。
1034 :type aidef0: list
1035 戻り値:
1036 :returns: 再構築された完全なパラメータリスト。
1037 :rtype: list
1038 """
1039 aidef = list(aidef0).copy()
1040
1041 ai = []
1042 c = 0
1043 for i in range(len(optid)):
1044 if optid[i] == 1:
1045 ai.append(ais[c])
1046 c += 1
1047 else:
1048 ai.append(aidef[i])
1049
1050 return ai
1051
1052def choose_parameters(ais0, optid):
1053 """
1054 概要:
1055 完全なパラメータリストから最適化対象のパラメータのみを抽出します。
1056 引数:
1057 :param ais0: 完全なパラメータリスト。
1058 :type ais0: list
1059 :param optid: 各パラメータが最適化対象かどうかを示すIDのリスト (1は最適化対象、0は固定)。
1060 :type optid: list
1061 戻り値:
1062 :returns: 最適化対象のパラメータのみを含むリスト。
1063 :rtype: list
1064 """
1065 ais = list(ais0).copy()
1066
1067 ai = []
1068 c = 0
1069 for i in range(len(optid)):
1070 if optid[i] == 1:
1071 ai.append(ais[i])
1072
1073 return ai
1074
1075def calS2_sigma(ai):
1076 """
1077 概要:
1078 与えられたパラメータで計算された電気伝導率と実験データの偏差の二乗和 (S2) を計算します。
1079 詳細説明:
1080 主にmobility.l0のフィッティングに用いられます。有効質量はdos.meeffから設定されます。
1081 入力データのNmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fitに基づいてフィッティング範囲を限定します。
1082 各データ点に対してEFを計算し、そこから電気伝導率sigmafinを計算し、実験値との二乗誤差を評価します。
1083 引数:
1084 :param ai: フィッティングするパラメータのリスト。ここではmobility.l0が対象です。
1085 :type ai: list
1086 戻り値:
1087 :returns: 電気伝導率の二乗和S2。
1088 :rtype: float
1089 """
1090 global mu, dos, ysigma
1091
1092 aiorg = parameter_list()
1093
1094 ainew = [ai[0]]
1095 if ainew[0] <= 0.0:
1096 ainew[0] = 1.0e-4
1097
1098 set_parameters([mobility.meff, ainew[0]])
1099
1100 S2 = 0.0
1101 ndata = len(ysigma)
1102 eps = 1.0e-300
1103 for i in range(ndata):
1104 S = yS[i]
1105 sigma = ysigma[i]
1106 n = yN[i]
1107 mu = ymu[i]
1108
1109 if Nmin_fit is not None and n < Nmin_fit:
1110 continue
1111 if Nmax_fit is not None and Nmax_fit < n:
1112 continue
1113 if sigmamin_fit is not None and sigma < sigmamin_fit:
1114 continue
1115 if sigmamax_fit is not None and sigmamax_fit < sigma:
1116 continue
1117
1118 EFfin, diffEF, flag = dos.EF_from_electrondensity(n, T0, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1119 if not flag:
1120 terminate("Error in callback(): EF calculation did not converge. diffEF={} eps={} in {} iteration"
1121 .format(diffEF, epsEF, maxiter))
1122
1123 sigmafin, nfin, mufin, tau_avg, Sfin, kappa, kappa_tot, L, PF, ZT, inf \
1124 = dos.cal_transport_properteis(T0, EFfin, mobility, klatt, validate_error_str = 'Error in fit()')
1125# print("m,l0=", mobility.meff, mobility.l0)
1126# print(" sigma=", i, ysigma[i], sigmafin)
1127
1128 dlogsigma = ysigma[i] - sigmafin
1129# dlogsigma = log(ysigma[i]+eps) - log(sigmafin+eps)
1130 S2 += dlogsigma * dlogsigma
1131
1132 S2 /= (ndata - 1)
1133
1134 set_parameters(aiorg)
1135# print("S2=", S2)
1136
1137 return S2
1138
1139def calS2_S(ai):
1140 """
1141 概要:
1142 与えられたパラメータで計算されたSeebeck係数と実験データの偏差の二乗和 (S2) を計算します。
1143 詳細説明:
1144 主に有効質量meffのフィッティングに用いられます。
1145 入力データのNmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fitに基づいてフィッティング範囲を限定します。
1146 各データ点に対してEFを計算し、そこからSeebeck係数Sfinを計算し、実験値との二乗誤差を評価します。
1147 引数:
1148 :param ai: フィッティングするパラメータのリスト。ここではdos.meeffが対象です。
1149 :type ai: list
1150 戻り値:
1151 :returns: Seebeck係数の二乗和S2。
1152 :rtype: float
1153 """
1154 global mu, dos, ysigma
1155 global method, tol, maxiter, h_diff
1156 global Nmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fit
1157
1158 aiorg = parameter_list()
1159
1160 ainew = [ai[0]]
1161 if ainew[0] <= 0.0:
1162 ainew[0] = 1.0e-4
1163
1164 set_parameters(ainew)
1165# print_parameters()
1166# print("m=", dos.meeff, dos.NC, dos.DC0)
1167
1168 S2 = 0.0
1169 ndata = len(ysigma)
1170 eps = 1.0e-300
1171 for i in range(ndata):
1172 S = yS[i]
1173 sigma = ysigma[i]
1174 n = yN[i]
1175 mu = ymu[i]
1176
1177 if Nmin_fit is not None and n < Nmin_fit:
1178 continue
1179 if Nmax_fit is not None and Nmax_fit < n:
1180 continue
1181 if sigmamin_fit is not None and sigma < sigmamin_fit:
1182 continue
1183 if sigmamax_fit is not None and sigmamax_fit < sigma:
1184 continue
1185
1186 EFfin, diffEF, flag = dos.EF_from_electrondensity(n, T0, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1187 if not flag:
1188 app.terminate("Error in callback(): EF calculation did not converge. diffEF={} eps={} in {} iteration"
1189 .format(diffEF, epsEF, maxiter), usage = usage, pause = True)
1190
1191 sigmafin, nfin, mufin, tau_avg, Sfin, kappa, kappa_tot, L, PF, ZT, inf \
1192 = dos.cal_transport_properteis(T0, EFfin, mobility, klatt, validate_error_str = 'Error in fit()')
1193
1194 dlogS = yS[i] - Sfin
1195 """
1196 if yS[i] <= 0.0:
1197 dlogS = log(-yS[i]+eps) - log(-Sfin+eps)
1198 else:
1199 dlogS = log(yS[i]+eps) - log(Sfin+eps)
1200 """
1201 S2 += dlogS * dlogS
1202
1203 S2 /= (ndata - 1)
1204
1205 set_parameters(aiorg)
1206
1207 return S2
1208
1209# First derivatives to be used e.g. for cg method
1210# Approximate by forward difference method with the delta h = h_diff
1211def diff1_sigma(ai):
1212 """
1213 概要:
1214 電気伝導率の二乗和S2に対するパラメータの1階微分を数値的に計算します (forward difference)。
1215 詳細説明:
1216 最適化アルゴリズム (e.g., 共役勾配法) で使用される勾配の計算に使用されます。
1217 計算されたS2_sigmaの各パラメータに対する微分値を返します。
1218 引数:
1219 :param ai: 評価するパラメータのリスト。
1220 :type ai: list
1221 戻り値:
1222 :returns: S2_sigmaに対する各パラメータの1階微分の配列。
1223 :rtype: numpy.ndarray
1224 """
1225 n = len(ai)
1226 f0 = calS2_sigma(ai)
1227 df = np.empty(n)
1228 for i in range(n):
1229 aii = ai
1230 aii[i] = ai[i] + h_diff
1231 df[i] = (calS2_sigma(aii) - f0) / h_diff
1232 return df
1233
1234def diff1_S(ai):
1235 """
1236 概要:
1237 Seebeck係数の二乗和S2に対するパラメータの1階微分を数値的に計算します (forward difference)。
1238 詳細説明:
1239 最適化アルゴリズム (e.g., 共役勾配法) で使用される勾配の計算に使用されます。
1240 計算されたS2_Sの各パラメータに対する微分値を返します。
1241 引数:
1242 :param ai: 評価するパラメータのリスト。
1243 :type ai: list
1244 戻り値:
1245 :returns: S2_Sに対する各パラメータの1階微分の配列。
1246 :rtype: numpy.ndarray
1247 """
1248 n = len(ai)
1249 f0 = calS2_S(ai)
1250 df = np.empty(n)
1251 for i in range(n):
1252 aii = ai
1253 aii[i] = ai[i] + h_diff
1254 df[i] = (calS2_S(aii) - f0) / h_diff
1255 return df
1256
1257def plot(fig, yn, ysigma, ymu, yS, ysigmaini, ymuini, ySini,
1258 ysigmafin = None, ymufin = None, ySfin = None):
1259 """
1260 概要:
1261 PisarenkoプロットとJonkerプロットを表示します。
1262 詳細説明:
1263 実験データ、初期計算値、および最終計算値をそれぞれN vs Sとsigma vs Sの形でプロットします。
1264 フィッティングの進行状況を視覚的に確認するために使用されます。
1265 引数:
1266 :param fig: matplotlibのFigureオブジェクト。
1267 :type fig: matplotlib.figure.Figure
1268 :param yn: キャリア濃度 N のリスト。
1269 :type yn: list
1270 :param ysigma: 電気伝導率 sigma のリスト。
1271 :type ysigma: list
1272 :param ymu: 移動度 mu のリスト。
1273 :type ymu: list
1274 :param yS: Seebeck係数 S のリスト。
1275 :type yS: list
1276 :param ysigmaini: 初期計算された電気伝導率 sigma のリスト。
1277 :type ysigmaini: list
1278 :param ymuini: 初期計算された移動度 mu のリスト。
1279 :type ymuini: list
1280 :param ySini: 初期計算されたSeebeck係数 S のリスト。
1281 :type ySini: list
1282 :param ysigmafin: 最終計算された電気伝導率 sigma のリスト (任意)。
1283 :type ysigmafin: list or None
1284 :param ymufin: 最終計算された移動度 mu のリスト (任意)。
1285 :type ymufin: list or None
1286 :param ySfin: 最終計算されたSeebeck係数 S のリスト (任意)。
1287 :type ySfin: list or None
1288 """
1289 global plt
1290 global graphupdateinterval
1291
1292 plt.clf()
1293
1294 ax1 = fig.add_subplot(1, 2, 1)
1295 ax2 = fig.add_subplot(1, 2, 2)
1296 plt.title(infile, fontsize = fontsize)
1297
1298 Srange = [min(yS) * 0.9, max(yS) * 1.1]
1299 yn2, ySi2 = sort_lists([yn, ySini])
1300 ins1 = ax1.plot(yn, yS, label = 'Pisarenko(obs)', linestyle = 'none', marker = 'o', markerfacecolor = 'blue', markeredgecolor = 'blue')
1301 ins2 = ax1.plot(yn2, ySi2, label = 'Pisarenko(ini)', linestyle = '-', color = 'blue', linewidth = 0.5)
1302# ins2 = ax1.plot(yn, ySini, label = 'Pisarenko(ini)', linestyle = '-', color = 'blue', linewidth = 0.5)
1303 if ysigmafin:
1304 yn2, ySf2 = sort_lists([yn, ySini])
1305 ins3 = ax1.plot(yn2, ySf2, label = 'Pisarenko(fin)', linestyle = '-', color = 'red')
1306# ins3 = ax1.plot(yn, ySfin, label = 'Pisarenko(fin)', linestyle = '-', color = 'red')
1307 ax1.set_xscale('log')
1308 ax1.set_ylim([0.0, Srange[1]])
1309 ax1.set_xlabel(r'$N_e$ (cm$^{-3}$)', fontsize = fontsize)
1310 ax1.set_ylabel(r'S ($\mu$V/K)', fontsize = fontsize)
1311 ax1.legend(fontsize = legend_fontsize, loc = 'upper center') #loc = 'best')
1312 ax1.tick_params(labelsize = fontsize)
1313
1314 ysi, ySi = sort_lists([ysigmaini, ySini])
1315 ins1 = ax2.plot(ysigma, yS, label = 'Jonker(obs)', linestyle = 'none', marker = 'o', markerfacecolor = 'blue', markeredgecolor = 'blue')
1316 ins2 = ax2.plot(ysi, ySi, label = 'Jonker(ini)', linestyle = '-', color = 'blue', linewidth = 0.5)
1317# ins2 = ax2.plot(ysigmaini, ySini, label = 'Jonker(ini)', linestyle = '-', color = 'blue', linewidth = 0.5)
1318 if ysigmafin:
1319 ysf, ySf = sort_lists([ysigmafin, ySfin])
1320 ins3 = ax2.plot(ysf, ySf, label = 'Jonker(fin)', linestyle = '-', color = 'red')
1321# ins3 = ax2.plot(ysigmafin, ySfin, label = 'Jonker(fin)', linestyle = '-', color = 'red')
1322 ax2.set_xscale('log')
1323 ax2.set_ylim([0.0, Srange[1]])
1324 ax2.set_xlabel(r'$\sigma$ (S/cm)', fontsize = fontsize)
1325 ax2.set_ylabel(r'S ($\mu$V/K)', fontsize = fontsize)
1326 ax2.legend(fontsize = legend_fontsize, loc = 'upper center') #loc = 'best')
1327 ax2.tick_params(labelsize = fontsize)
1328
1329 plt.tight_layout()
1330 plt.pause(0.01)
1331
1332
1333# Callback function for scipy.optimize.minimize()
1334# Print variables every iteration, and update graph for every graphupdateinterval iterationsおt
1335iter = 0
1336def callback(fig, S2):
1337 """
1338 概要:
1339 scipy.optimize.minimizeのコールバック関数として、最適化の進行状況を出力し、グラフを更新します。
1340 詳細説明:
1341 指定された出力間隔でパラメータとS2値をコンソールに表示し、
1342 指定されたグラフ更新間隔でJonkerプロットとPisarenkoプロットを更新します。
1343 これにより、フィッティングプロセスのリアルタイムな監視が可能になります。
1344 引数:
1345 :param fig: matplotlibのFigureオブジェクト。
1346 :type fig: matplotlib.figure.Figure
1347 :param S2: 現在のS2値 (二乗和)。
1348 :type S2: float
1349 """
1350 global iter, graphupdateinterval
1351 global outputinterval
1352 global dos, mu
1353 global ysigma
1354 global method, tol, maxiter, h_diff
1355 global Nmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fit
1356
1357 if iter % outputinterval == 0:
1358 print("callback {:04d}: {:10.4g} {:10.4g} S2={:10.6g}".format(iter, mobility.meff, mobility.l0, S2))
1359
1360 if iter % graphupdateinterval == 0:
1361 ndata = len(ysigma)
1362 ysigmafin = []
1363 ymufin = []
1364 ySfin = []
1365 for i in range(ndata):
1366 S = yS[i]
1367 sigma = ysigma[i]
1368 n = yN[i]
1369 mu = ymu[i]
1370
1371 if Nmin_fit is not None and n < Nmin_fit:
1372 continue
1373 if Nmax_fit is not None and Nmax_fit < n:
1374 continue
1375 if sigmamin_fit is not None and sigma < sigmamin_fit:
1376 continue
1377 if sigmamax_fit is not None and sigmamax_fit < sigma:
1378 continue
1379
1380 EFfin, diffEF, flag = dos.EF_from_electrondensity(n, T0, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1381 if not flag:
1382 app.terminate("Error in callback(): EF calculation did not converge. diffEF={} eps={} in {} iteration"
1383 .format(diffEF, epsEF, maxiter), usage = usage, pause = True)
1384
1385 sigmafin, nfin, mufin, tau_avg, Sfin, kappa, kappa_tot, L, PF, ZT, inf \
1386 = dos.cal_transport_properteis(T0, EFfin, mobility, klatt, validate_error_str = 'Error in fit()')
1387
1388 ysigmafin.append(sigmafin)
1389 ymufin.append(mufin)
1390 ySfin.append(Sfin)
1391
1392 plot(fig, yN, ysigma, ymu, yS, ysigmaini, ymuini, ySini, ysigmafin, ymufin, ySfin)
1393
1394 iter += 1
1395
1396def callback_S(fig, xk):
1397 """
1398 概要:
1399 Seebeck係数のフィッティングのためのコールバック関数です。
1400 詳細説明:
1401 calS2_Sを呼び出してS2を計算し、現在のパラメータを更新してから、
1402 共通のコールバック関数callbackを呼び出して進行状況を表示します。
1403 引数:
1404 :param fig: matplotlibのFigureオブジェクト。
1405 :type fig: matplotlib.figure.Figure
1406 :param xk: 現在の最適化パラメータ (meff)。
1407 :type xk: numpy.ndarray
1408 """
1409 S2 = calS2_S(xk)
1410 ainew = [xk[0]]
1411 set_parameters(ainew)
1412
1413 callback(fig, S2)
1414
1415def callback_sigma(fig, xk):
1416 """
1417 概要:
1418 電気伝導率のフィッティングのためのコールバック関数です。
1419 詳細説明:
1420 calS2_sigmaを呼び出してS2を計算し、現在のパラメータを更新してから、
1421 共通のコールバック関数callbackを呼び出して進行状況を表示します。
1422 引数:
1423 :param fig: matplotlibのFigureオブジェクト。
1424 :type fig: matplotlib.figure.Figure
1425 :param xk: 現在の最適化パラメータ (l0)。
1426 :type xk: numpy.ndarray
1427 """
1428 global iter, graphupdateinterval
1429 global outputinterval
1430 global dos, mu
1431 global ysigma
1432
1433 S2 = calS2_sigma(xk)
1434 ainew = [mobility.meff, xk[0]]
1435 set_parameters(ainew)
1436
1437 callback(fig, S2)
1438
1439def construct_lists(label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu):
1440 """
1441 概要:
1442 入力データのリストを正規化または補完します。
1443 詳細説明:
1444 sampleラベルまたはxsampleがNoneの場合、連番で補完します。
1445 sigma、N、muのいずれかがNoneの場合、他の利用可能なデータから計算を試みます。
1446 引数:
1447 :param label_sample: サンプルデータのラベル。
1448 :type label_sample: str or None
1449 :param xsample: サンプルデータのリスト。
1450 :type xsample: list
1451 :param label_S: Seebeck係数のラベル。
1452 :type label_S: str
1453 :param yS: Seebeck係数のリスト。
1454 :type yS: list
1455 :param label_sigma: 電気伝導率のラベル。
1456 :type label_sigma: str or None
1457 :param ysigma: 電気伝導率のリスト。
1458 :type ysigma: list
1459 :param label_N: キャリア濃度のラベル。
1460 :type label_N: str or None
1461 :param yN: キャリア濃度のリスト。
1462 :type yN: list
1463 :param label_mu: 移動度のラベル。
1464 :type label_mu: str or None
1465 :param ymu: 移動度のリスト。
1466 :type ymu: list
1467 戻り値:
1468 :returns: 正規化または補完されたラベルとデータリストのタプル。
1469 :rtype: tuple
1470 """
1471 ndata = len(yS)
1472 if label_sample is None:
1473 label_sample = 'sample'
1474 xsample = []
1475 for i in range(ndata):
1476 xsample.append(i + 1)
1477 if label_sigma is None:
1478 ysigma = []
1479 for i in range(ndata):
1480 ysigma.append(None)
1481 if label_N is None:
1482 yN = []
1483 for i in range(ndata):
1484 if ymu is not None:
1485 yN.append(None)
1486 else:
1487 yN.append(ysigma[i] / e / ymu[i])
1488 if label_mu is None:
1489 ymu = []
1490 for i in range(ndata):
1491 if yN[i] is not None:
1492 ymu.append(None)
1493 else:
1494 ymu.append(ysigma[i] / e / yN[i])
1495
1496 return label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu
1497
1498def fit():
1499 """
1500 概要:
1501 実験データに対して熱電パラメータのフィッティングを行います。
1502 詳細説明:
1503 入力ファイルからSeebeck係数、電気伝導率、キャリア濃度、移動度のデータを読み込みます。
1504 指定された温度T0と初期パラメータ(meff, rfac, l0)に基づいて初期計算を行います。
1505 scipy.optimize.minimize を使用して、主に有効質量(meff)と平均自由行程プレファクタ(l0)をフィッティングし、
1506 計算値が実験データに最もよく合うように最適化します。
1507 フィッティング結果はパラメータファイルとExcelファイルに保存され、グラフで可視化されます。
1508 フィッティング範囲はNmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fitで指定できます。
1509 """
1510 global fig
1511 global label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu
1512 global ysigmaini, ymuini, ySini
1513 global method, tol, maxiter, h_diff
1514 global Nmin_fit, Nmax_fit, sigmamin_fit, sigmamax_fit
1515
1516 print("infile :", infile)
1517 print(" T_label : ", T_label)
1518 print(" S_label : ", S_label)
1519 print(" n_label : ", n_label)
1520 print(" mu_label : ", mu_label)
1521 print(" sigma_label: ", sigma_label)
1522 print("")
1523 print(f"T0: {T0} K")
1524 print("Carrier:")
1525 print(" q={} e".format(mobility.charge))
1526 print(" meff={}me".format(dos.meeff))
1527 dos.NC = meff2NC_FEA(dos.meeff, T0)
1528 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
1529 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
1530 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
1531 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
1532 print(" mean free path prefactor: l0={} m".format(mobility.l0))
1533 print("")
1534 print( "Fitting condition")
1535 print(f" method : {method}")
1536 print(f" tol : {tol}")
1537 print(f" maxiter: {maxiter}")
1538 print(f" h_diff: {h_diff}")
1539 print(f" outputinterval: {outputinterval}")
1540 print(f" N range : {Nmin_fit} - {Nmax_fit} cm^-3")
1541 print(f" sigma range: {sigmamin_fit} - {sigmamax_fit} S/cm")
1542 def set_default_range(var):
1543 if var == '' or var == '*':
1544 return None
1545 return pfloat(var, defval = None)
1546
1547 Nmin_fit = set_default_range(Nmin_fit)
1548 Nmax_fit = set_default_range(Nmax_fit)
1549 sigmamin_fit = set_default_range(sigmamin_fit)
1550 sigmamax_fit = set_default_range(sigmamax_fit)
1551
1552 if '***' in method:
1553 app.terminate(f"***Error: Choose method", pause = True)
1554
1555 if '***' in S_label:
1556 app.terminate(f"***Error: Choose S_label", pause = True)
1557 if '***' in n_label:
1558 app.terminate(f"***Error: Choose n_label", pause = True)
1559 if '***' in mu_label:
1560 app.terminate(f"***Error: Choose mu_label", pause = True)
1561
1562 if 'uV' in S_label or 'micro' in S_label or 'mV' in S_label:
1563 app.terminate(f"***Error: The unit of S must be 'V/K' but given by [{S_label}]", pause = True)
1564
1565 print("")
1566 print("Read S data from {}".format(infile))
1567
1568 datafile = tkVariousData(infile)
1569 labels, datalist = datafile.Read_minimum_matrix(close_fp = True, usage = usage)
1570 label_S, yS = datafile.FindDataArray(S_label, flag = 'i')
1571# Convert V/K to uV/K
1572 for i in range(len(yS)):
1573 yS[i] *= 1.0e6
1574 label_sigma, ysigma = datafile.FindDataArray(sigma_label, flag = 'i')
1575 label_N, yN = datafile.FindDataArray(n_label, flag = 'i')
1576 label_mu, ymu = datafile.FindDataArray(mu_label, flag = 'i')
1577 label_sample, xsample = labels[0], datalist[0]
1578
1579 ndata = len(yS)
1580 print("ndata(all): ", ndata)
1581 ndata_fit = 0
1582 print("data to be fitted")
1583 print(f"{'sample':15} {'n(cm-3)':12} {'mu(cm2/Vs)':10} {'sigma(S/cm)':10} {'S(uV/K)':10}")
1584 for i in range(ndata):
1585 sigma = ysigma[i]
1586 n = yN[i]
1587 if Nmin_fit is not None and n < Nmin_fit:
1588 continue
1589 if Nmax_fit is not None and Nmax_fit < n:
1590 continue
1591 if sigmamin_fit is not None and sigma < sigmamin_fit:
1592 continue
1593 if sigmamax_fit is not None and sigmamax_fit < sigma:
1594 continue
1595
1596 print(f"{xsample[i]:15} {n:12.4g} {ymu[i]:10.4g} {sigma:10.4g} {yS[i]:10.4g}")
1597
1598 print("")
1599 print("Calculate initial values")
1600 print_parameters()
1601 yEFini = []
1602 ysigmaini = []
1603 ymuini = []
1604 ySini = []
1605 print("{:>8} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12} {:>12}"
1606 .format("EF(eV)", "Ne(cm-3)", "sigma(S/cm)", "mu(cm2/Vs)", "S(uV/K)", "Ne,ini", "sigma,ini", "mu,ini", "S,ini"))
1607 for i in range(ndata):
1608 sample = xsample[i]
1609 S = yS[i]
1610 sigma = ysigma[i]
1611 n = yN[i]
1612 mu = ymu[i]
1613
1614 EFini, diffEF, flag = dos.EF_from_electrondensity(n, T0, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1615 if not flag:
1616 app.terminate("Error in fit(): EF calculation did not converge. diffEF={} eps={} in {} iteration".format(diffEF, epsEF, maxiter),
1617 usage = usage, pause = True)
1618
1619# x = (EF - doc.EC) * e / kB / T0
1620 sigmaini, nini, muini, tau_avg, Sini, kappa, kappa_tot, L, PF, ZT, inf = \
1621 dos.cal_transport_properteis(T0, EFini, mobility, klatt, validate_error_str = 'Error in fit()')
1622
1623 yEFini.append(EFini)
1624 ysigmaini.append(sigmaini)
1625 ymuini.append(muini)
1626 ySini.append(Sini)
1627
1628 print("{:8.3g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g}"
1629 .format(EFini, n, sigma, mu, S, nini, sigmaini, muini, Sini))
1630
1631#=============================
1632# グラフの表示
1633#=============================
1634 print("")
1635 print("plot")
1636 fig = plt.figure(figsize = figsize_sim)
1637
1638 plot(fig, yN, ysigma, ymu, yS, ysigmaini, ymuini, ySini)
1639
1640#=============================
1641# Optimization
1642#=============================
1643 print("")
1644 print("Nonlinear least-squares fitting for effective mass by ", method)
1645 print(" tol=", tol)
1646 ai = [mobility.meff]
1647 ret = minimize(calS2_S, ai, method = method, jac = diff1_S, tol = tol, callback = lambda xk: callback_S(fig, xk),
1648 options = {'maxiter':maxiter, "disp":True})
1649 if method == 'nelder-mead':
1650 simplex = ret['final_simplex']
1651 ai = simplex[0][0]
1652 fmin = ret['fun']
1653 aifin = [ai[0], mobility.l0] #ai0[1]]
1654 set_parameters(aifin)
1655 print("Optimized at S2={:12.6g}:".format(fmin))
1656 print_parameters(parameter_list())
1657
1658 print("")
1659 print("Nonlinear least-squares fitting for l0 by ", method)
1660 print(" tol=", tol)
1661 ai_sigma = [mobility.l0]
1662 print("meff(ini)=", mobility.meff)
1663# ret = minimize(calS2_S, ai_sigma, method = method, jac = diff1_sigma, tol = tol, callback = lambda xk: callback_sigma(fig, xk),
1664 ret = minimize(calS2_sigma, ai_sigma, method = method, jac = diff1_sigma, tol = tol, callback = lambda xk: callback_sigma(fig, xk),
1665 options = {'maxiter':maxiter, "disp":True})
1666 if method == 'nelder-mead':
1667 simplex = ret['final_simplex']
1668 ai_sigma = simplex[0][0]
1669 fmin = ret['fun']
1670 aifin = [mobility.meff, ai_sigma[0]]
1671 set_parameters(aifin)
1672 print("Optimized at S2={:12.6g}:".format(fmin))
1673# print_parameters()
1674 print_parameters(parameter_list())
1675
1676 print("")
1677 print("Calculate final values")
1678 print_parameters(parameter_list())
1679 yEFfin = []
1680 ysigmafin = []
1681 ySfin = []
1682 print("{:>8} {:>12} {:>12} {:>12} {:>12} {:>12}"
1683 .format("EF(eV)", "Ne(cm-3)", "sigma(S/cm)", "mu(cm2/Vs)", "S(uV/K)", "S,fin"))
1684 for i in range(ndata):
1685 sample = xsample[i]
1686 S = yS[i]
1687 sigma = ysigma[i]
1688 n = yN[i]
1689 mu = ymu[i]
1690
1691 EFfin, diffEF, flag = dos.EF_from_electrondensity(n, T0, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1692 if not flag:
1693 app.terminate("Error in fit(): EF calculation did not converge. diffEF={} eps={} in {} iteration".format(diffEF, epsEF, maxiter),
1694 usage = usage, pause = True)
1695
1696 sigmafin, nfin, mufin, tau_avg, Sfin, kappa, kappa_tot, L, PF, ZT, inf \
1697 = dos.cal_transport_properteis(T0, EFfin, mobility, klatt, validate_error_str = 'Error in fit()')
1698
1699 mufin = sigmafin / sigma / mufin
1700 sigmafin = e * nfin * mufin
1701
1702 yEFfin.append(EFfin)
1703 ysigmafin.append(sigmafin)
1704 ySfin.append(Sfin)
1705 print("{:8.3g} {:12.4g} {:12.4g} {:12.4g} {:12.4g} {:12.4g}"
1706 .format(EFfin, n, sigma, mu, S, Sfin))
1707
1708 print("")
1709 print("Save final parameters to [{}]".format(parameterfile))
1710 save_parameterfile(ai = aifin, S2 = fmin)
1711
1712 print("Save fitting data to [{}]".format(outxlsfile))
1713 tkVariousData().to_excel(outxlsfile, ["EF(eV)", "Ne(cm-3)", "sigma(S/cm)", "mu(cm2/Vs)", "S(uV/K)", "S,fin"],
1714 [yEFfin, yN, ysigma, ymu, yS, ySfin])
1715
1716 app.terminate("", pause = True)
1717
1718def sim():
1719 """
1720 概要:
1721 熱電特性とHall特性のシミュレーションを行い、結果をファイルとグラフに出力します。
1722 詳細説明:
1723 入力ファイルからSeebeck係数、電気伝導率、キャリア濃度、移動度、温度のデータを読み込みます。
1724 指定されたパラメータ (T0, meff, rfac, l0) を用いて、実験データ点における加重移動度を計算します。
1725 さらに、指定されたキャリア濃度範囲NminからNmaxまでを掃引し、
1726 Seebeck係数、電気伝導率、移動度、Hall係数、Hall因子、Hall移動度などの特性を計算します。
1727 計算結果はパラメータファイルとExcelファイルに保存され、PisarenkoプロットとJonkerプロットを含むグラフで可視化されます。
1728 """
1729 global label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu
1730 global Nmin, Nmax
1731
1732 print("")
1733 print("infile :", infile)
1734 print(" T_label : ", T_label)
1735 print(" S_label : ", S_label)
1736 print(" n_label : ", n_label)
1737 print(" mu_label : ", mu_label)
1738 print(" sigma_label: ", sigma_label)
1739 print(f"T0 : {T0} K")
1740 print("Carrier:")
1741 print(" q={} e".format(mobility.charge))
1742 print(" meff={}me".format(dos.meeff))
1743 dos.NC = meff2NC_FEA(dos.meeff, T0)
1744 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
1745 if mobility.charge < 0.0:
1746 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
1747 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
1748 else:
1749 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
1750 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
1751 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
1752 print(" mean free path prefactor: l0={} m".format(mobility.l0))
1753
1754 if '***' in S_label:
1755 app.terminate(f"***Error: Choose S_label", pause = True)
1756 if '***' in n_label:
1757 app.terminate(f"***Error: Choose n_label", pause = True)
1758 if '***' in mu_label:
1759 app.terminate(f"***Error: Choose mu_label", pause = True)
1760
1761 if 'uV' in S_label or 'micro' in S_label or 'mV' in S_label:
1762 print("")
1763 print(f"***Error: The unit of S must be 'V/K' but given by [{S_label}]")
1764 app.terminate(pause = True)
1765
1766 print("")
1767 print("Read S data from {}".format(infile))
1768 datafile = tkVariousData(infile)
1769 labels, datalist = datafile.Read_minimum_matrix(close_fp = True, usage = usage)
1770 label_S, yS = datafile.FindDataArray(S_label, flag = 'i')
1771# Convert V/K to uV/K
1772 for i in range(len(yS)):
1773 yS[i] *= 1.0e6
1774 label_sigma, ysigma = datafile.FindDataArray(sigma_label, flag = 'i')
1775 label_N, yN = datafile.FindDataArray(n_label, flag = 'i')
1776 label_mu, ymu = datafile.FindDataArray(mu_label, flag = 'i')
1777 label_sample, xsample = labels[0], datalist[0]
1778 if T_label == '' or '***' in T_label:
1779 label_T = 'T(K)'
1780 yT = []
1781 for i in range(len(xsample)):
1782 yT.append(T0)
1783 else:
1784 label_T, yT = datafile.FindDataArray(T_label, flag = 'i')
1785
1786# print("x=", xsample)
1787 ndata = len(yS)
1788 print("ndata(all): ", ndata)
1789# print("xsample=", label_sample, xsample)
1790# print("yS=", label_S, yS)
1791# print("ysigma=", label_sigma, ysigma)
1792 print(f"{'sample':15} {'n(cm-3)':12} {'mu(cm2/Vs)':10} {'sigma(S/cm)':10} {'S(uV/K)':10}")
1793 for i in range(ndata):
1794 sigma = ysigma[i]
1795 n = yN[i]
1796 print(f"{xsample[i]:15} {n:12.4g} {ymu[i]:10.4g} {sigma:10.4g} {yS[i]:10.4g}")
1797
1798
1799 print("")
1800 print("Weighted mobility")
1801 ysigma_w = []
1802 yn_w = []
1803 ymu_w = []
1804 ymu_w0 = []
1805 yEF = []
1806 if yN[0] is not None:
1807 print("{:>10}\t{:>8}\t{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>15}\t{:>15}"
1808 .format("sample", "T(K)", "EF(eV)", "S(uV/K)", "sigma(S/cm)", "mu(cm2/Vs)", "Ne(cm-3)", "sigma_w", "mu_w(cm2/Vs)", "mu_w*(me/m*)^(3/2)", "n_w(cm-3)"))
1809 else:
1810 print("{:>10}\t{:>10}\t{:>10}\t{:>10}".format("sample", "EF(eV)", "S(uV/K)", "sigma(S/cm)"))
1811 for i in range(ndata):
1812 sample = xsample[i]
1813 S = yS[i]
1814 sigma = ysigma[i]
1815 n = yN[i]
1816 mu = ymu[i]
1817 T = yT[i]
1818 print(f"sample={sample} S={S} uV/K sigma={sigma} S/cm")
1819 mu_w, n_w, sign, carriertype = weighted_mobility(sigma / 0.01, S * 1.0e-6, T0)
1820 mu_w *= 1.0 * 1.0e4 # cm2/Vs
1821 mu_w0 = mu_w * pow(mobility.meff, -1.5)
1822 n_w *= 1.0e-6 # cm^-3
1823 sigma_w = e * n_w * mu_w
1824
1825 if n is not None:
1826 EF, diffEF, flag = dos.EF_from_electrondensity(n, T, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1827 else:
1828 EF, diffEF, flag = dos.EF_from_electronSeebeck(S, T, mobility, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
1829 if not flag:
1830 app.terminate("Error in sim(): EF calculation did not converge. diffEF={} eps={} in {} iteration".format(diffEF, epsEF, maxiter),
1831 usage = usage, pause = True)
1832# print("n=", n, EF)
1833
1834 ysigma_w.append(sigma_w)
1835 yn_w.append(n_w)
1836 ymu_w.append(mu_w)
1837 ymu_w0.append(mu_w0)
1838 yEF.append(EF)
1839 if n is not None:
1840 print("{:10.4g}\t{:8.3g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:15.4g}\t{:15.4g}"
1841 .format(sample, T, EF, S, sigma, mu, n, sigma_w, mu_w, mu_w0, n_w))
1842 else:
1843 print("{:10.4g}\t{:8.3g}\t{:10.4g}\t{:10.4g}\t{:10.4g}".format(sample, T, EF, S, sigma))
1844
1845 Nmin_data = min(yN)
1846 Nmax_data = max(yN)
1847 if Nmin_data < Nmin:
1848 Nmin = Nmin_data
1849 if Nmax < Nmax_data:
1850 Nmax = Nmax_data
1851
1852 lnNmin = log(Nmin)
1853 lnNmax = log(Nmax)
1854 lnNstep = (lnNmax - lnNmin) / (nN - 1)
1855 print("")
1856 print("N range: {:10.4g} - {:10.4g} cm-3, {:10.4g} step in ln(N), nN={}".format(Nmin, Nmax, lnNstep, nN))
1857 xNsim = []
1858 xsigmasim = []
1859 yScal = []
1860 ySsim_nondeg = []
1861 ySsim_deg = []
1862 print("{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}"
1863 .format("N(cm-3)", "EF(eV)", "S,cal(uV/K)", "S,non-deg(uV/K)", "S,deg(uV/K)", "sigma,cal(S/cm)", "Ne,cal(cm-3)", "mu,cal(cm2/Vs)"))
1864 for iN in range(nN):
1865 lnN = lnNmin + lnNstep * iN
1866 N = exp(lnN)
1867# print("N=", N, dos.NC)
1868 if N < dos.NC:
1869 EF = kB * T0 * log(N / dos.NC) / e
1870 else:
1871 EF = BMShift_FEA(N, dos.DC0)
1872
1873 sigma, n, mu, tau_avg, S, kappa, kappa_tot, L, PF, ZT, inf \
1874 = dos.cal_transport_properteis(T0, EF, mobility, klatt, validate_error_str = 'Error in sim()')
1875
1876 Sndeg = dos.cal_S_nondegenerated_from_Ne(n, mobility.rfac, charge = mobility.charge) * 1.0e6 # uV/K
1877 Sdeg = dos.cal_S_degenerated_from_Ne(T0, n, mobility.rfac, charge = mobility.charge) * 1.0e6 # uV/K
1878
1879 xNsim.append(n)
1880 xsigmasim.append(sigma)
1881 yScal.append(S)
1882 ySsim_nondeg.append(Sndeg)
1883 ySsim_deg.append(Sdeg)
1884 print("{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}"
1885 .format(N, EF, S, Sndeg, Sdeg, sigma, n, mu))
1886
1887 print("")
1888 print("Save parameters to [{}]".format(parameterfile))
1889 save_parameterfile(S2 = '')
1890
1891 print("")
1892 print("Save data to [{}]".format(outxlsfile))
1893 if yN[0] is not None:
1894 tkVariousData().to_excel(outxlsfile, ["sample", 'S(uV/K)', 'sigma(S/cm)', 'mu(cm2/Vs)', 'N(cm-3)', "sigma_w", "mu_w", "mu_w*(me/m*)^(3/2)", "n_w"],
1895 [xsample, yS, ysigma, ymu, yN, ysigma_w, ymu_w, ymu_w0, yn_w])
1896 else:
1897 tkVariousData().to_excel(outxlsfile, ["sample", 'S(uV/K)', 'sigma(S/cm)'], [xsample, yS, ysigma])
1898
1899#=============================
1900# グラフの表示
1901#=============================
1902 print("")
1903 fig = plt.figure(figsize = figsize_sim)
1904
1905 ax1 = fig.add_subplot(2, 2, 1)
1906 ax1b = ax1.twinx()
1907 ax2 = fig.add_subplot(2, 2, 2)
1908 ax4 = fig.add_subplot(2, 2, 3)
1909 ax4b = ax4.twinx()
1910 ax3 = fig.add_subplot(2, 2, 4)
1911
1912 maxS = max(yS)
1913 minS = min(yS)
1914 if maxS > 0.0:
1915 maxS *= 2.0
1916 else:
1917 maxS = 0.0
1918 if minS > 0.0:
1919 minS = 0.0
1920 else:
1921 minS *= 2.0
1922
1923 ins1 = ax1.plot( xsample, yS, label = 'S', linestyle = '-', linewidth = 1.0, color = 'red', marker = 'o', markersize = 5.0)
1924 ins2 = ax1b.plot(xsample, ysigma, label = r'$\sigma$', linestyle = '-', linewidth = 1.0, color = 'blue', marker = '^', markersize = 10.0)
1925 ins3 = ax1b.plot(xsample, ysigma_w, label = r'$\sigma_w$', linestyle = 'dashed', linewidth = 0.5, color = 'green', marker = '+', markersize = 15.0, markerfacecolor = 'green')
1926 ax1.set_xlabel("sample", fontsize = fontsize)
1927 ax1.set_ylabel(r"S (K/$\mu$V)", fontsize = fontsize)
1928 ax1b.set_ylabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
1929# ax1.set_ylim([minS, maxS])
1930# h1a, l1a = ax1.get_legend_handles_labels()
1931# h1b, l1b = ax1b.get_legend_handles_labels()
1932# ax1.legend(h1a + h1b, l1a + h1b, fontsize = legend_fontsize, loc = 0)
1933 ins = ins1 + ins2 + ins3
1934 ax1.legend(ins, [l.get_label() for l in ins], fontsize = legend_fontsize, loc = 'upper center') #loc = 'best')
1935# ax1.legend(loc = 0)
1936# ax1b.legend(loc = 0)
1937 ax1.tick_params(labelsize = fontsize)
1938 ax1b.tick_params(labelsize = fontsize)
1939
1940 if yN[0] is not None:
1941 ins1 = ax4.plot( xsample, ymu, label = r'$\mu$', linestyle = '-', color = 'red', linewidth = 0.5, marker = 'o', markersize = 10.0)
1942 ins2 = ax4.plot( xsample, ymu_w, label = r'$\mu_w$', linestyle = 'dashed', color = 'red', linewidth = 0.5, marker = '^', markersize = 5.0)
1943 ins3 = ax4.plot( xsample, ymu_w0, label = r'$\mu_w^0$', linestyle = 'dashed', color = 'red', linewidth = 0.5, marker = '+', markersize = 5.0)
1944 ins4 = ax4b.plot(xsample, yN, label = '$N_e$', linestyle = '-', color = 'blue', linewidth = 0.5, marker = 'o', markersize = 10.0)
1945 ins5 = ax4b.plot(xsample, yn_w, label = '$N_{e,w}$', linestyle = 'dashed', color = 'blue', linewidth = 0.5, marker = '^', markersize = 5.0)
1946 ax4.set_xlabel("sample", fontsize = fontsize)
1947 ax4.set_ylabel(r"$\mu$ (cm$^2$/V/s)", fontsize = fontsize)
1948 ax4b.set_ylabel(r"$N_e$ (cm$^{-3}$)", fontsize = fontsize)
1949# ax4.set_ylim([minS, maxS])
1950 ax4b.set_yscale('log')
1951 ins = ins1 + ins2 + ins3 + ins4 + ins5
1952 ax4.legend(ins, [l.get_label() for l in ins], fontsize = legend_fontsize, loc = 'best')
1953 ax4.tick_params(labelsize = fontsize)
1954 ax4b.tick_params(labelsize = fontsize)
1955
1956 ax2.plot(ysigma, yS, label = 'Jonker plot', linestyle = '', color = 'red', marker = 'o', markersize = 5.0)
1957 ax2.plot(xsigmasim, yScal, label = 'S,cal', linestyle = '-', color = 'red', linewidth = 1.0)
1958 ax2.plot(xsigmasim, ySsim_nondeg, label = 'S,sim,nondeg', linestyle = 'dashed', color = 'blue', linewidth = 0.5)
1959 ax2.plot(xsigmasim, ySsim_deg, label = 'S,sim,deg', linestyle = 'dashed', color = 'green', linewidth = 0.5)
1960 ax2.set_xlabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
1961 ax2.set_ylabel(r"S ($\mu$V/K)", fontsize = fontsize)
1962 ax2.set_xscale('log')
1963 ax2.set_ylim([minS, maxS])
1964 ax2.legend(fontsize = legend_fontsize, loc = 'best')
1965 ax2.tick_params(labelsize = fontsize)
1966
1967 if yN[0] is not None:
1968 ax3.plot(yN, yS, label = 'Pisarenko plot', linestyle = '', marker = 'o', markersize = 5.0)
1969 ax3.plot(xNsim, yScal, label = 'S,cal', linestyle = '-', color = 'red', linewidth = 1.0)
1970 ax3.plot(xNsim, ySsim_nondeg, label = 'S,sim,nondeg', linestyle = 'dashed', color = 'blue', linewidth = 0.5)
1971 ax3.plot(xNsim, ySsim_deg, label = 'S,sim,deg', linestyle = 'dashed', color = 'green', linewidth = 0.5)
1972 ax3.set_xlabel(r"$N$ (cm$^{-3}$)", fontsize = fontsize)
1973 ax3.set_ylabel(r"S ($\mu$V/K)", fontsize = fontsize)
1974 ax3.set_xscale('log')
1975 ax3.set_ylim([minS, maxS])
1976 ax3.legend(fontsize = legend_fontsize, loc = 'best')
1977 ax3.tick_params(labelsize = fontsize)
1978
1979 plt.tight_layout()
1980 plt.pause(0.1)
1981
1982 app.terminate("", pause = True)
1983
1984def init():
1985 """
1986 概要:
1987 入力データファイルを読み込み、初期の熱電パラメータファイルを作成します。
1988 詳細説明:
1989 指定された入力ファイルからSeebeck係数、電気伝導率、キャリア濃度、移動度のデータを読み込み、
1990 基本的な情報を表示します。
1991 Seebeck係数の符号に基づいてキャリアの種類 (正孔または電子) を自動的に判断し、
1992 mobility.chargeを設定します。
1993 現在のパラメータはparameterfileに保存されます。
1994 """
1995 print("")
1996 print("Carrier:")
1997 print(" q={} e".format(mobility.charge))
1998 print(" meff={}me".format(dos.meeff))
1999 dos.NC = meff2NC_FEA(dos.meeff, T0)
2000 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
2001 if mobility.charge < 0.0:
2002 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2003 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2004 else:
2005 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2006 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2007 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
2008 print(" mean free path prefactor: l0={} m".format(mobility.l0))
2009
2010 if 'uV' in S_label or 'micro' in S_label or 'mV' in S_label:
2011 print("")
2012 print(f"***Error: The unit of S must be 'V/K' but given by [{S_label}]")
2013 app.terminate(pause = True)
2014
2015 print("")
2016 print("Read S data from {}".format(infile))
2017 label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu \
2018 = read_datafile(infile, usage = usage)
2019# Convert V/K to uV/K
2020 for i in range(len(yS)):
2021 yS[i] *= 1.0e6
2022
2023 ndata = len(xsample)
2024 print("ndata: ", ndata)
2025
2026 if yN[0] is not None:
2027 print("{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>10}"
2028 .format("sample", "S(uV/K)", "sigma(S/cm)", "mu(cm2/Vs)", "Ne(cm-3)"))
2029 else:
2030 print("{:>10}\t{:>10}\t{:>10}".format("sample", "S(uV/K)", "sigma(S/cm)"))
2031 for i in range(ndata):
2032 sample = xsample[i]
2033 S = yS[i]
2034 sigma = ysigma[i]
2035 n = yN[i]
2036 mu = ymu[i]
2037 if n is not None:
2038 print("{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}".format(sample, S, sigma, mu, n))
2039 else:
2040 print("{:10.4g}\t{:10.4g}\t{:10.4g}".format(sample, S, sigma))
2041
2042 if yS[0] > 0.0:
2043 mobility.charge = 1.0
2044 elif yS[0] < 0.0:
2045 mobility.charge = -1.0
2046 for i in range(1, ndata):
2047 if yS[i] * mobility.charge < 0.0:
2048 app.terminate("Error in init(): S data include both positive and negative values: S[{}}={}, S[{}]={}".format(0, yS[0], i, yS[i]),
2049 usage = usage, pause = True)
2050
2051 print("")
2052 print("Save parameters to [{}]".format(parameterfile))
2053 save_parameterfile(S2 = '')
2054
2055def calL():
2056 """
2057 概要:
2058 温度、Hallキャリア濃度、電気伝導率のデータから電子のローレンツ数と熱伝導率を計算します。
2059 詳細説明:
2060 入力ファイルから温度、Hallキャリア濃度、電気伝導率のデータを読み込みます。
2061 指定された有効質量meff、散乱因子rfac、平均自由行程プレファクタl0に基づいて、
2062 各データ点におけるフェルミ準位EF、電子のローレンツ数L、および電子熱伝導率kappa_eを計算します。
2063 結果はコンソールとExcelファイルに出力され、グラフで可視化されます。
2064 """
2065 print("")
2066 print("Carrier:")
2067 print(" q={} e".format(mobility.charge))
2068 print(" meff={}me".format(dos.meeff))
2069 dos.NC = meff2NC_FEA(dos.meeff, T0)
2070 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
2071 if mobility.charge < 0.0:
2072 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2073 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2074 else:
2075 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2076 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2077 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
2078 print(" mean free path prefactor: l0={} m".format(mobility.l0))
2079
2080 print("")
2081 print("Read T, Ne, and sigma data from {}".format(infile))
2082 datafile = tkVariousData(infile)
2083 labels, datalist = datafile.Read_minimum_matrix(close_fp = True, usage = usage)
2084# print("labels: ", labels)
2085# ncol = len(datalist)
2086# print("ncol: ", ncol)
2087 label_T, xT = datafile.FindDataArray(r'^T[\s|\(|\[|$]', flag = 'i')
2088 label_sigma, ysigma = datafile.FindDataArray(r'^sigma[$|\S]?.*$', flag = 'i')
2089 label_N, yN = datafile.FindDataArray(r'^N[$|\S]?.*$', flag = 'i')
2090 ndata = len(xT)
2091 print("ndata: ", ndata)
2092# print("xT=", label_T, xT)
2093# print("ysigma=", label_sigma, ysigma)
2094# print("yN=", label_N, yN)
2095
2096 print("Calculat EF, L and kappa,e")
2097 yEF = []
2098 yL = []
2099 ykappa = []
2100 print("kappa,e=sigma,obs*L,cal*T")
2101 print("{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}"
2102 .format("T(K)", "EF(eV)", "sigma(S/cm)", "Ne(cm^-3)", "L(Wohm/K^2)", "kappa,e"))
2103 for i in range(len(xT)):
2104 T = xT[i]
2105 n = yN[i]
2106 s = ysigma[i]
2107
2108 if n is not None:
2109 EF, diffEF, flag = dos.EF_from_electrondensity(n, T, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
2110 if not flag:
2111 app.terminate("Error in calL(): EF calculation did not converge. diffEF={} eps={} in {} iteration".format(diffEF, epsEF, maxiter),
2112 usage = usage, pause = True)
2113# print("n=", n, EF)
2114
2115 sigma, n, mu, tau_avg, S, kappa, kappa_tot, L, PF, ZT, inf \
2116 = dos.cal_transport_properteis(T, EF, mobility, klatt, validate_error_str = 'Error in properteis()')
2117
2118 kappa = L * s / 0.01 * T
2119
2120 yEF.append(EF)
2121 yL.append(L)
2122 ykappa.append(kappa)
2123
2124 print("{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}"
2125 .format(xT[i], EF, ysigma[i], yN[i], L, kappa))
2126
2127 header, ext = os.path.splitext(infile)
2128 filebody = os.path.basename(header)
2129 outxlsLfile = f'{filebody}-L-me{dos.meeff}-r{mobility.rfac}.xlsx'
2130 print("")
2131 print("Save data to [{}]".format(outxlsLfile))
2132 tkVariousData().to_excel(outxlsLfile, ["T(K)", "EF,cal(eV)", "sigma,obs(S/cm)", "Ne,obs(cm^-3)", "L,cal(Wohm/K^2)", "kappa,e,cal=sigma,obs*L,cal*T(W/m/K)"],
2133 [xT, yEF, ysigma, yN, yL, ykappa])
2134
2135#=============================
2136# グラフの表示
2137#=============================
2138 print("")
2139 fig = plt.figure(figsize = figsize_sim)
2140
2141 if min(xT) == max(xT):
2142 xX = yN
2143 xlabel = '$N$ (cm$^{-3}$)'
2144 xscale = 'log'
2145 else:
2146 xX = xT
2147 xlabel = '$T$ (K)'
2148 xscale = 'linear'
2149
2150 axEF = fig.add_subplot(2, 2, 1)
2151 axNe = fig.add_subplot(2, 2, 2)
2152 axsigma = axNe.twinx()
2153 axL = fig.add_subplot(2, 2, 3)
2154 axkappa = axL.twinx()
2155 axkappa = fig.add_subplot(2, 2, 4)
2156
2157 axEF.plot(xX, yEF, label = 'EF(cal)', linestyle = '-', linewidth = 1.0, marker = 'o', markersize = 5.0)
2158 axEF.set_xlabel(xlabel, fontsize = fontsize)
2159 axEF.set_ylabel("$E_F$ (eV)", fontsize = fontsize)
2160 axEF.set_xscale(xscale)
2161 axEF.legend(fontsize = legend_fontsize, loc = 'best')
2162 axEF.tick_params(labelsize = fontsize)
2163
2164 ins1 = axNe.plot (xX, yN, label = '$N_e$(obs)', linestyle = '-', linewidth = 1.0, color = 'red', marker = 'o', markersize = 5.0)
2165 ins2 = axsigma.plot(xX, ysigma, label = r'$\sigma$(obs)', linestyle = 'dashed', linewidth = 1.0, color = 'blue', marker = 's', markersize = 5.0)
2166 axNe.set_xlabel(xlabel, fontsize = fontsize)
2167 axNe.set_ylabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
2168 axNe.set_xscale(xscale)
2169 axNe.set_yscale('log')
2170 axsigma.set_ylabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
2171 axsigma.set_yscale('log')
2172 ins = ins1 + ins2
2173 axNe.legend(ins, [l.get_label() for l in ins], fontsize = legend_fontsize, loc = 'best')
2174 axNe.tick_params(labelsize = fontsize)
2175 axsigma.tick_params(labelsize = fontsize)
2176
2177 axL.plot(xX, yL, label = 'L(cal)', linestyle = '-', linewidth = 1.0, marker = 'o', markersize = 5.0)
2178 axL.set_xlabel(xlabel, fontsize = fontsize)
2179 axL.set_ylabel(r"$L$ (W$\Omega$/K$^2$)", fontsize = fontsize)
2180 axL.set_xscale(xscale)
2181 axL.legend(fontsize = legend_fontsize, loc = 'best')
2182 axL.tick_params(labelsize = fontsize)
2183
2184 axkappa.plot(xX, ykappa, label = r'$\kappa_e$(cal)', linestyle = '-', linewidth = 1.0, marker = 'o', markersize = 5.0)
2185 axkappa.set_xlabel(xlabel, fontsize = fontsize)
2186 axkappa.set_ylabel(r"$\kappa_e$=$\sigma$$L$$T$ (W/m/K)", fontsize = fontsize)
2187 axkappa.set_xscale(xscale)
2188 axkappa.set_yscale('log')
2189 axkappa.legend(fontsize = legend_fontsize, loc = 'best')
2190 axkappa.tick_params(labelsize = fontsize)
2191
2192 plt.tight_layout()
2193 plt.pause(0.1)
2194
2195 app.terminate("", pause = True)
2196
2197def calF():
2198 """
2199 概要:
2200 温度、Hallキャリア濃度、Hall移動度のデータからHall因子、ドリフトキャリア濃度、ドリフト移動度を計算します。
2201 詳細説明:
2202 入力ファイルから温度、Hallキャリア濃度、Hall移動度、電気伝導率のデータを読み込みます。
2203 指定された有効質量meff、散乱因子rfac、平均自由行程プレファクタl0に基づいて、
2204 各データ点におけるフェルミ準位EF、Hall因子FH、ドリフトキャリア濃度ndrift、およびドリフト移動度mudriftを計算します。
2205 結果はコンソールとExcelファイルに出力され、グラフで可視化されます。
2206 """
2207 print("")
2208 print("infile :", infile)
2209 print("T_label : ", T_label)
2210 print("n_label : ", n_label)
2211 print("mu_label : ", mu_label)
2212 print("sigma_label: ", sigma_label)
2213 print("Carrier:")
2214 print(" q={} e".format(mobility.charge))
2215 print(" meff={}me".format(dos.meeff))
2216 dos.NC = meff2NC_FEA(dos.meeff, T0)
2217 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
2218 if mobility.charge < 0.0:
2219 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2220 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2221 else:
2222 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2223 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2224 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
2225 print(" mean free path prefactor: l0={} m".format(mobility.l0))
2226
2227 print("")
2228 print("Read T, Ne, and sigma data from {}".format(infile))
2229 datafile = tkVariousData(infile)
2230 labels, datalist = datafile.Read_minimum_matrix(close_fp = True, usage = usage)
2231 label_T, xT = datafile.FindDataArray(T_label, flag = 'i')
2232 label_sigma, ysigma = datafile.FindDataArray(sigma_label, flag = 'i')
2233 label_N, yN = datafile.FindDataArray(n_label, flag = 'i')
2234 label_mu, ymu = datafile.FindDataArray(mu_label, flag = 'i')
2235
2236 ndata = len(xT)
2237 print("ndata: ", ndata)
2238
2239 print("")
2240 print("Calculat EF, FH, mu_drift, and Ne")
2241 yEF = []
2242 yFH = []
2243 yRH = []
2244 yndrift = []
2245 ymudrift = []
2246 print("kappa,e=sigma,obs*L,cal*T")
2247 print("{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}"
2248 .format("T(K)", "EF(eV)", "sigma(S/cm)", "Ne,Hall(obs)", "mu,Hall(obs)", "Ne(cm-3)", "mu,drift(cm2/Vs)", "FH", "RH(cm3/C)"))
2249 for i in range(len(xT)):
2250 T = xT[i]
2251 n = yN[i]
2252 s = ysigma[i]
2253
2254 if n is not None:
2255 EF, diffEF, flag = dos.EF_from_electrondensity(n, T, EF0 = 0.0, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
2256 if not flag:
2257 app.terminate("Error in calF(): EF calculation did not converge. diffEF={} eps={} in {} iteration".format(diffEF, epsEF, maxiter),
2258 usage = usage, pause = True)
2259
2260# sigma, n, mu, tau_avg, S, kappa, kappa_tot, L, PF, ZT, inf \
2261# = dos.cal_transport_properteis(T, EF, mobility, klatt, validate_error_str = 'Error in properteis()')
2262 inf = dos.cal_Hall_properteis(T0, EF, mobility, validate_error_str = 'Error in properteis()')
2263 FH = inf["FH"]
2264 RH = inf["RH"]
2265 RH0 = inf["RH0"]
2266 n_drift = inf["nHall"]
2267 mu_drift = inf["muHall"]
2268
2269 yEF.append(EF)
2270 yFH.append(FH)
2271 yRH.append(RH)
2272 yndrift.append(yN[i] * FH)
2273 ymudrift.append(ymu[i] / FH)
2274
2275 print("{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}"
2276 .format(xT[i], EF, ysigma[i], yN[i], ymu[i], yndrift[i], ymudrift[i], FH, RH))
2277
2278 header, ext = os.path.splitext(infile)
2279 filebody = os.path.basename(header)
2280 outxlsLfile = f'{filebody}-FH-me{dos.meeff}-r{mobility.rfac}.xlsx'
2281 print("")
2282 print("Save data to [{}]".format(outxlsLfile))
2283 tkVariousData().to_excel(outxlsLfile, ["T(K)", "EF,cal(eV)", "sigma,obs(S/cm)", "Ne,Hall(obs)(cm-3)", "mu,Hall(obs)(cm2/Vs)",
2284 "Ne=Ne,Hall*FH(cm-3)", "mu,drift=mu,Hall/FH(cm2/Vs)", "FH", "RH(cm3/C)"],
2285 [xT, yEF, ysigma, yN, ymu, yndrift, ymudrift, yFH, yRH])
2286
2287#=============================
2288# グラフの表示
2289#=============================
2290 print("")
2291 fig = plt.figure(figsize = figsize_sim)
2292
2293 if min(xT) == max(xT):
2294 xX = yN
2295 xlabel = '$N$ (cm$^{-3}$)'
2296 xscale = 'log'
2297 else:
2298 xX = xT
2299 xlabel = '$T$ (K)'
2300 xscale = 'linear'
2301
2302 axEF = fig.add_subplot(2, 3, 1)
2303 axsigma = fig.add_subplot(2, 3, 2)
2304 axNe = fig.add_subplot(2, 3, 3)
2305 axmu = fig.add_subplot(2, 3, 4)
2306 axFH = fig.add_subplot(2, 3, 5)
2307 axRH = fig.add_subplot(2, 3, 6)
2308
2309 axEF.plot(xX, yEF, label = 'EF(cal)', linestyle = '-', linewidth = 1.0, marker = 'o', markersize = 5.0)
2310 axEF.set_xlabel(xlabel, fontsize = fontsize)
2311 axEF.set_ylabel("$E_F$ (eV)", fontsize = fontsize)
2312 axEF.set_xscale(xscale)
2313 axEF.legend(fontsize = legend_fontsize, loc = 'best')
2314 axEF.tick_params(labelsize = fontsize)
2315
2316 axsigma.plot(xX, ysigma, label = r'$\sigma$(obs)', linestyle = 'dashed', linewidth = 1.0, color = 'blue', marker = 's', markersize = 5.0)
2317 axsigma.set_xlabel(xlabel, fontsize = fontsize)
2318 axsigma.set_ylabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
2319 axsigma.set_xscale(xscale)
2320 axsigma.set_yscale('log')
2321 axsigma.legend(fontsize = legend_fontsize, loc = 'best')
2322 axsigma.tick_params(labelsize = fontsize)
2323
2324 axNe.plot (xX, yN, label = '$N_e$$_{,Hall}(obs)', linestyle = '-', linewidth = 1.0, color = 'red', marker = 'o', markersize = 5.0)
2325 axNe.plot (xX, yndrift, label = '$N_e$$_{,drift}$(obs)', linestyle = '-', linewidth = 0.5, color = 'green', marker = '^', markersize = 3.0)
2326 axNe.set_xlabel(xlabel, fontsize = fontsize)
2327 axNe.set_ylabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
2328 axNe.set_xscale(xscale)
2329 axNe.set_yscale('log')
2330 axNe.legend(fontsize = legend_fontsize, loc = 'best')
2331 axNe.tick_params(labelsize = fontsize)
2332
2333 axmu.plot(xX, ymu, label = r'$\mu_{Hall}$(obs)', linestyle = '-', linewidth = 1.0, color = 'red', marker = 'o', markersize = 5.0)
2334 axmu.plot(xX, ymudrift, label = r'$\mu_{drift}$(obs)', linestyle = '-', linewidth = 0.5, color = 'green', marker = '^', markersize = 3.0)
2335 axmu.set_xlabel(xlabel, fontsize = fontsize)
2336 axmu.set_ylabel(r"$\mu$ (cm$^2$/Vs)", fontsize = fontsize)
2337 axmu.set_xscale(xscale)
2338 axmu.legend(fontsize = legend_fontsize, loc = 'best')
2339 axmu.tick_params(labelsize = fontsize)
2340
2341 axFH.plot(xX, yFH, label = '$F_{Hall}$', linestyle = '-', linewidth = 1.0, color = 'blue', marker = 'o', markerfacecolor = 'blue', markersize = 3.0)
2342 axFH.set_xlabel(xlabel, fontsize = fontsize)
2343 axFH.set_ylabel("$F_{Hall}$", fontsize = fontsize)
2344 axFH.set_xscale(xscale)
2345 axFH.legend(fontsize = legend_fontsize, loc = 'best')
2346 axFH.tick_params(labelsize = fontsize)
2347
2348 axRH.plot(xX, yRH, label = '$R_H$', linestyle = '-', linewidth = 1.0, color = 'blue', marker = 'o', markerfacecolor = 'blue', markersize = 3.0)
2349 axRH.set_xlabel(xlabel, fontsize = fontsize)
2350 axRH.set_ylabel("$R_H$ (cm$^3$/C)", fontsize = fontsize)
2351 axRH.set_xscale(xscale)
2352 axRH.set_yscale('log')
2353 axRH.legend(fontsize = legend_fontsize, loc = 'best')
2354 axRH.tick_params(labelsize = fontsize)
2355
2356 plt.tight_layout()
2357 plt.pause(0.1)
2358
2359 app.terminate("", pause = True)
2360
2361def T():
2362 """
2363 概要:
2364 温度とキャリア濃度に対する熱電特性の依存性をシミュレートします。
2365 詳細説明:
2366 入力ファイルからSeebeck係数、電気伝導率、キャリア濃度、移動度などのデータを読み込みます。
2367 指定された温度範囲 (TminからTmax) とキャリア濃度範囲 (NminからNmax) に対して、
2368 Seebeck係数、電気伝導率、移動度、電子熱伝導率、力率、ZT値、フェルミ準位を計算します。
2369 計算結果はコンソールと複数のExcelファイルに保存され、グラフで可視化されます。
2370 """
2371 global label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu
2372
2373 print("")
2374 print("Carrier:")
2375 print(" q={} e".format(mobility.charge))
2376 print(" meff={}me".format(dos.meeff))
2377 dos.NC = meff2NC_FEA(dos.meeff, T0)
2378 dos.DC0 = meff2DC0_FEA(dos.meeff, T0)
2379 if mobility.charge < 0.0:
2380 print(" NC={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2381 print(" DC={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2382 else:
2383 print(" NV={:10.4g} cm^-3 at {} K".format(dos.NC, T0))
2384 print(" DV={:10.4g} cm^-3 at {} K".format(dos.DC0, T0))
2385 print(" scattering factor (non-degenerated) r={}".format(mobility.rfac))
2386 print(" mean free path prefactor: l0={} m".format(mobility.l0))
2387
2388 print("")
2389 print("Read S data from {}".format(infile))
2390 label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu \
2391 = read_datafile(infile, usage = usage)
2392 label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu \
2393 = construct_lists(label_sample, xsample, label_S, yS, label_sigma, ysigma, label_N, yN, label_mu, ymu)
2394 print("x=", xsample)
2395 ndata = len(xsample)
2396 print("ndata: ", ndata)
2397
2398 if yN[0] is not None:
2399 print("{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>10}\t{:>10}"
2400 .format("sample", "EF(eV)", "S(uV/K)", "sigma(S/cm)", "mu(cm2/Vs)", "Ne(cm-3)"))
2401 else:
2402 print("{:>10}\t{:>10}\t{:>10}\t{:>10}".format("sample", "EF(eV)", "S(uV/K)", "sigma(S/cm)"))
2403 for i in range(ndata):
2404 sample = xsample[i]
2405 S = yS[i]
2406 sigma = ysigma[i]
2407 n = yN[i]
2408 mu = ymu[i]
2409 if n is not None:
2410 print("{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}".format(sample, S, sigma, mu, n))
2411 else:
2412 print("{:10.4g}\t{:10.4g}\t{:10.4g}".format(sample, S, sigma))
2413
2414 Nmin_data = min(yN)
2415 Nmax_data = max(yN)
2416 if Nmin_data < Nmin:
2417 Nmin = Nmin_data
2418 if Nmax < Nmax_data:
2419 Nmax = Nmax_data
2420 print("")
2421 print(f"Plot N range: {Nmin:12.4g} - {Nmax:12.4g}")
2422
2423 lnNmin = log(Nmin)
2424 lnNmax = log(Nmax)
2425 lnNstep = (lnNmax - lnNmin) / (nN - 1)
2426 print("")
2427 print("N range: {:10.4g} - {:10.4g} cm-3, {:10.4g} step in ln(N), nN={}".format(Nmin, Nmax, lnNstep, nN))
2428 xEFcal = make_matrix2(nT, nN, 0.0)
2429 xNsim = make_matrix2(nT, nN, 0.0)
2430 ysigmasim = make_matrix2(nT, nN, 0.0)
2431 ymusim = make_matrix2(nT, nN, 0.0)
2432 yScal = make_matrix2(nT, nN, 0.0)
2433 ykappacal = make_matrix2(nT, nN, 0.0)
2434 yPFcal = make_matrix2(nT, nN, 0.0)
2435 yZTcal = make_matrix2(nT, nN, 0.0)
2436 Tstep = (Tmax - Tmin) / (nT - 1)
2437 for iT in range(nT):
2438 T = Tmin + iT * Tstep
2439 dos.NC = meff2NC_FEA(dos.meeff, T)
2440 dos.DC0 = meff2DC0_FEA(dos.meeff, T)
2441
2442 print("{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}\t{:10}"
2443 .format("T(K)", "N(cm-3)", "EF(eV)", "S,cal(uV/K)", "sigma,cal(S/cm)", "Ne,cal(cm-3)", "mu,cal(cm2/Vs)", "kappa,e,cal(W/m/K)", "PF(uW/cm/K^2)", "ZT"))
2444 for iN in range(nN):
2445 lnN = lnNmin + lnNstep * iN
2446 N = exp(lnN)
2447# print("N=", N, dos.NC)
2448 if N < dos.NC:
2449 EF = kB * T0 * log(N / dos.NC) / e
2450 else:
2451 EF = BMShift_FEA(N, dos.DC0)
2452
2453 EF, diffEF, flag = dos.EF_from_electrondensity(N, T, EF0 = EF, dEF = 0.01, dump = 0.0, epsEF = epsEF, maxiter = 100)
2454 if not flag:
2455 app.terminate("Error in sim(): EF calculation did not converge. diffEF={} eps={} in {} iteration".format(diffEF, epsEF, maxiter),
2456 usage = usage, pause = True)
2457
2458 sigma, n, mu, tau_avg, S, kappa, kappa_tot, L, PF, ZT, inf \
2459 = dos.cal_transport_properteis(T, EF, mobility, klatt, validate_error_str = 'Error in sim()')
2460
2461 xEFcal[iT][iN] = EF
2462 xNsim[iT][iN] = n
2463 ysigmasim[iT][iN] = sigma
2464 ymusim[iT][iN] = mu
2465 yScal[iT][iN] = S
2466 ykappacal[iT][iN] = kappa
2467 yPFcal[iT][iN] = PF
2468 yZTcal[iT][iN] = ZT
2469 print("{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}"
2470 .format(T, N, EF, S, sigma, n, mu, kappa, PF, ZT))
2471
2472 print("")
2473 print("Save parameters to [{}]".format(parameterfile))
2474 save_parameterfile(S2 = '')
2475
2476
2477 print("")
2478 labels = ["N(cm-3)"] + ["{:.4g} K".format(Tmin + iT * Tstep) for iT in range(nT)]
2479 header, ext = os.path.splitext(infile)
2480 filebody = os.path.basename(header)
2481 xlsfile = filebody + '-EF.xlsx'.format(T)
2482 print("Save data to [{}]".format(xlsfile))
2483# print("labels=", labels)
2484# print("datalist=", [xNsim[0]])# + [xEFcal[iT] for iT in range(nT)])
2485 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + xEFcal) #[xEFcal[iT] for iT in range(nT)])
2486 xlsfile = filebody + '-sigma.xlsx'.format(T)
2487 print("Save data to [{}]".format(xlsfile))
2488 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + ysigmasim)
2489 xlsfile = filebody + '-mu.xlsx'.format(T)
2490 print("Save data to [{}]".format(xlsfile))
2491 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + ymusim)
2492 xlsfile = filebody + '-S.xlsx'.format(T)
2493 print("Save data to [{}]".format(xlsfile))
2494 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + yScal)
2495 xlsfile = filebody + '-kappa.xlsx'.format(T)
2496 print("Save data to [{}]".format(xlsfile))
2497 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + ykappacal)
2498 xlsfile = filebody + '-PF.xlsx'.format(T)
2499 print("Save data to [{}]".format(xlsfile))
2500 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + yPFcal)
2501 xlsfile = filebody + '-ZT.xlsx'.format(T)
2502 print("Save data to [{}]".format(xlsfile))
2503 tkVariousData().to_excel(xlsfile, labels, [xNsim[0]] + yZTcal)
2504
2505#=============================
2506# グラフの表示
2507#=============================
2508 print("")
2509 fig = plt.figure(figsize = figsize)
2510
2511 axSsobs = fig.add_subplot(3, 3, 1)
2512 axSsobsb = axSsobs.twinx()
2513 axmuNobs = fig.add_subplot(3, 3, 2)
2514 axmuNobsb = axmuNobs.twinx()
2515 axNs = fig.add_subplot(3, 3, 3)
2516 axNmu = fig.add_subplot(3, 3, 4)
2517 axNS = fig.add_subplot(3, 3, 5)
2518 axNkappa = fig.add_subplot(3, 3, 6)
2519 axNPF = fig.add_subplot(3, 3, 7)
2520 axNZT = fig.add_subplot(3, 3, 8)
2521 axNEF = fig.add_subplot(3, 3, 9)
2522
2523 maxS = max(yS)
2524 minS = min(yS)
2525 if maxS > 0.0:
2526 maxS *= 1.2
2527 else:
2528 maxS = 0.0
2529 if minS > 0.0:
2530 minS = 0.0
2531 else:
2532 minS *= 1.2
2533
2534 ins1 = axSsobs.plot (xsample, yS, label = 'S', linestyle = '-', linewidth = 1.0, color = 'red', marker = 'o', markersize = 5.0)
2535 ins2 = axSsobsb.plot(xsample, ysigma, label = r'$\sigma$', linestyle = '-', linewidth = 1.0, color = 'blue', marker = '^', markersize = 10.0)
2536 axSsobs.set_xlabel("sample", fontsize = fontsize)
2537 axSsobs.set_ylabel(r"S (K/$\mu$V)", fontsize = fontsize)
2538 axSsobsb.set_ylabel(r"$\sigma$ (S/cm)", fontsize = fontsize)
2539 ins = ins1 + ins2
2540 axSsobs.legend(ins, [l.get_label() for l in ins], fontsize = legend_fontsize, loc = 'upper center') #loc = 'best')
2541 axSsobs.tick_params(labelsize = fontsize)
2542 axSsobsb.tick_params(labelsize = fontsize)
2543
2544 if yN[0] is not None:
2545 ins1 = axmuNobs.plot( xsample, ymu, label = r'$\mu$', linestyle = '-', color = 'red', linewidth = 0.5, marker = 'o', markersize = 10.0)
2546 ins2 = axmuNobsb.plot(xsample, yN, label = '$N_e$', linestyle = '-', color = 'blue', linewidth = 0.5, marker = 'o', markersize = 10.0)
2547 axmuNobs.set_xlabel("sample", fontsize = fontsize)
2548 axmuNobs.set_ylabel(r"$\mu$ (cm$^2$/V/s)", fontsize = fontsize)
2549 axmuNobsb.set_ylabel("$N_e$ (cm$^{-3}$)", fontsize = fontsize)
2550 axmuNobsb.set_yscale('log')
2551 ins = ins1 + ins2
2552 axmuNobs.legend(ins, [l.get_label() for l in ins], fontsize = legend_fontsize, loc = 'best')
2553 axmuNobs.tick_params(labelsize = fontsize)
2554 axmuNobsb.tick_params(labelsize = fontsize)
2555
2556 if yN[0] is not None:
2557 axNs.plot( yN, ysigma, label = r'$\sigma_{,obs}$', linestyle = '', marker = 'o', markersize = 5.0)
2558 axNmu.plot(yN, ymu, label = '$N_e$$_{,obs}$', linestyle = '', marker = 'o', markersize = 5.0)
2559 axNS.plot( yN, yS, label = '$S_{obs}$', linestyle = '', marker = 'o', markersize = 5.0)
2560 for iT in range(nT):
2561 T= Tmin + iT * Tstep
2562 axNs.plot( xNsim[iT], ysigmasim[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2563 axNmu.plot( xNsim[iT], ymusim[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2564 axNS.plot( xNsim[iT], yScal[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2565 axNkappa.plot(xNsim[iT], ykappacal[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2566 axNPF.plot( xNsim[iT], yPFcal[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2567 axNZT.plot( xNsim[iT], yZTcal[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2568 axNEF.plot( xNsim[iT], xEFcal[iT], label = '{:8.2f} K'.format(T), linestyle = '-', linewidth = 0.5)
2569 axNs.set_xlabel( r"$N$ (cm$^{-3}$)", fontsize = fontsize)
2570 axNmu.set_xlabel(r"$N$ (cm$^{-3}$)", fontsize = fontsize)
2571 axNS.set_xlabel( r"$N$ (cm$^{-3}$)", fontsize = fontsize)
2572 axNkappa.set_xlabel( "$N$ (cm$^{-3}$)", fontsize = fontsize)
2573 axNPF.set_xlabel( r"$N$ (cm$^{-3}$)", fontsize = fontsize)
2574 axNZT.set_xlabel( r"$N$ (cm$^{-3}$)", fontsize = fontsize)
2575 axNEF.set_xlabel( r"$N$ (cm$^{-3}$)", fontsize = fontsize)
2576 axNs.set_ylabel( r"$\sigma$ (S/cm)", fontsize = fontsize)
2577 axNmu.set_ylabel(r"$\mu$ (cm$^2$/V/s)", fontsize = fontsize)
2578 axNS.set_ylabel( "S (V/K)", fontsize = fontsize)
2579 axNkappa.set_ylabel( r"$\kappa$$_{,e}$ (W/m/K)", fontsize = fontsize)
2580 axNPF.set_ylabel( r"PF ($\mu$W/cm/K$^2$)", fontsize = fontsize)
2581 axNZT.set_ylabel( "ZT", fontsize = fontsize)
2582 axNEF.set_ylabel( "$E_F$", fontsize = fontsize)
2583 axNs.set_xscale('log')
2584 axNmu.set_xscale('log')
2585 axNS.set_xscale('log')
2586 axNkappa.set_xscale('log')
2587 axNPF.set_xscale('log')
2588 axNZT.set_xscale('log')
2589 axNEF.set_xscale('log')
2590 axNs.set_yscale('log')
2591 axNkappa.set_yscale('log')
2592 axNs.legend(fontsize = legend_fontsize, loc = 'best')
2593 axNmu.legend(fontsize = legend_fontsize, loc = 'best')
2594 axNS.legend(fontsize = legend_fontsize, loc = 'best')
2595 axNkappa.legend(fontsize = legend_fontsize, loc = 'best')
2596 axNPF.legend(fontsize = legend_fontsize, loc = 'best')
2597 axNZT.legend(fontsize = legend_fontsize, loc = 'best')
2598 axNEF.legend(fontsize = legend_fontsize, loc = 'best')
2599
2600 plt.tight_layout()
2601 plt.pause(0.1)
2602
2603 app.terminate("", pause = True)
2604
2605
2606def main():
2607 """
2608 概要:
2609 スクリプトの主要な実行フローを制御します。
2610 詳細説明:
2611 アプリケーションの初期化、ログファイルのリダイレクト、コマンドライン引数に基づく変数の更新、
2612 パラメータファイルの読み書き、および選択されたモードに応じた各種計算関数の呼び出しを行います。
2613 電子構造および輸送パラメータの情報を出力します。
2614 """
2615 global app
2616 global parameterfile, parameterbkfile, outxlsfile, outxlsPropfile
2617 global outxlsfFDfile, outxlsFjfile
2618
2619 app = tkApplication()
2620 logfile = app.replace_path(infile)
2621 print(f"Open logfile [{logfile}]")
2622 app.redirect(targets = ["stdout", logfile], mode = 'w')
2623
2624 updatevars()
2625
2626 parameterfile = app.replace_path(infile, template = ["{dirname}", "{filebody}.in"])
2627 parameterbkfile = app.replace_path(infile, template = ["{dirname}", "{filebody}.in.bak"])
2628 outxlsfile = app.replace_path(infile, template = ["{dirname}", "{filebody}-Seebeck-{mode}.xlsx"], ext_dict = {"mode": mode})
2629 outxlsPropfile = app.replace_path(infile, template = ["{dirname}", "{filebody}-properties-{mode}.xlsx"], ext_dict = {"mode": mode})
2630
2631 outxlsfFDfile = app.replace_path(infile, template = ["{dirname}", "fFD.xlsx"])
2632 outxlsFjfile = app.replace_path(infile, template = ["{dirname}", "Fj.xlsx"])
2633
2634 print("")
2635 print("mode: ", mode)
2636 print("infile : {}".format(infile))
2637 print("out xlsx file : {}".format(outxlsfile))
2638 print("parameter file : {}".format(parameterfile))
2639 print("parameter backup file: {}".format(parameterbkfile))
2640 print("")
2641
2642 print("")
2643 print("Read [{}]".format(parameterfile))
2644 read_parameters(parameterfile)
2645# check args again to use given parameters
2646 updatevars()
2647
2648 print("")
2649 print("Electronic structure")
2650# print(f"Eg={dos.EC - dos.EV} eV")
2651# print(f"EV={dos.EV} eV")
2652 print(f"EC={dos.EC} eV")
2653# print(f"EA={dos.EA} eV")
2654# print(f"NA={dos.NA} cm^-3")
2655# print(f"ED={dos.ED} eV")
2656# print(f"ND={dos.ND} cm^-3")
2657# print(f"mh_eff={dos.mheff} me_0")
2658 print(f"me_eff={dos.meeff} me_0")
2659 print(f"Initial parameter")
2660 print(f" EF0={dos.EF0} eV")
2661 print("Transport parameters")
2662 print(f"charge={mobility.charge} e")
2663 print(f"meff={mobility.meff} me_0")
2664 print(f"rfac={mobility.rfac}")
2665 print(f"l0 ={mobility.l0} m")
2666
2667 if mode == 'basic':
2668 basic()
2669 elif mode == 'prop':
2670 properties()
2671 elif mode == 'Hall':
2672 Hall()
2673 elif mode == 'init':
2674 init()
2675 elif mode == 'sim':
2676 sim()
2677 elif mode == 'fit':
2678 fit()
2679 elif mode == 'T':
2680 T()
2681 elif mode == 'calL':
2682 calL()
2683 elif mode == 'calF':
2684 calF()
2685 else:
2686 app.terminate("Error in main: Invalide mode [{}]".format(mode), usage = usage, pause = True)
2687
2688if __name__ == "__main__":
2689 main()