"""
バンド構造をプロットするためのユーティリティ関数を提供するモジュール。
概要:
このモジュールは、バンド構造計算の結果を可視化するための関数を定義します。
詳細説明:
tkbandstructureモジュールは、主に`plot_band`関数を提供し、
k点経路に沿った電子エネルギーのバンド構造をグラフとして描画します。
フェルミ準位、HOMO/LUMO準位、価電子帯端/伝導帯端などの重要なエネルギー準位を
補助線として表示する機能や、占有率に応じてバンドの色を調整する機能も備えています。
また、k点経路上の高対称点などの境界を縦線とラベルで示すことができます。
関連リンク:
:doc:`tkbandstructure_usage`
"""
import numpy as np
from numpy import sin, cos, tan, arccos, arcsin, arctan, sqrt, exp, log, pi
from tklib.tkobject import tkObject
from tklib.tkutils import IsDir, IsFile, SplitFilePath
from tklib.tkutils import terminate, pint, pfloat, getarg, getintarg, getfloatarg
from tklib.tkutils import SplitFilePath, GetList
from tklib.tkre import DelQuote, DelSpace
import tklib.tkre
# バンド構造をプロット
# xk: プロットするk点の蓄積距離のリスト
# yE: E(xk[i])。入れ子になったリストで構わない
# ktotallist: k点境界における、最初のk点からの距離の和のリスト
# ktotal_namelist: k点境界における、k点の名称
[ドキュメント]
def plot_band(plt, axis, ISPIN, xk, yEup, yEdn, Erange, occups = None, occdns = None,
ktotallist = None, ktotal_namelist = None,
nmax = 1.0, EV = None, EC = None, EF = None, EHOMO = None, ELUMO = None,
EVlabel = '$E_V$', EClabel = '$E_C$', EFlabel = '$E_F$',
EHOMOlabel = '$E_{HOMO}$', ELUMOlabel = '$E_{LUMO}$',
marker = 'o', linestyle = '', color = 'black', linewidth = 0.3,
markersize = 2.0, markeredgewidth = 0.5,
legendloc = 'best',
fontsize = 16, labelsize = 12, legend_fontsize = 12):
"""
電子バンド構造をプロットする。
概要:
与えられたk点の情報とエネルギー値に基づいてバンド構造をグラフに描画する。
詳細説明:
この関数は、k点経路に沿った電子エネルギーのバンド構造をプロットします。
フェルミ準位、HOMO/LUMO準位、価電子帯端/伝導帯端などの補助線を
グラフ上に表示できます。
`occupts` および `occdns` が指定された場合、バンドの占有率に応じて
色を濃淡で表現し、電子の占有状況を視覚的に示します。
`ktotallist` と `ktotal_namelist` を使用して、k点経路上の重要な点
(例: 高対称点)に縦線を引き、対応するラベルをX軸に表示します。
:param plt: matplotlib.pyplot モジュールオブジェクト。グラフ全体の操作に使用。
:type plt: module
:param axis: matplotlib.axes.Axes オブジェクト。バンド構造を描画するサブプロット。
:type axis: matplotlib.axes.Axes
:param ISPIN: スピン偏極計算の場合2、それ以外は1。2の場合、downスピンバンドを区別してプロット。
:type ISPIN: int
:param xk: プロットするk点の蓄積距離のリスト。
:type xk: list[float]
:param yEup: 各k点におけるupスピン(または非スピン偏極)のエネルギー値のリスト。`yEup[ik][iE]` の形式。
:type yEup: list[list[float]]
:param yEdn: 各k点におけるdownスピンのエネルギー値のリスト (ISPIN=2の場合のみ)。`yEdn[ik][iE]` の形式。
:type yEdn: list[list[float]]
:param Erange: Y軸のエネルギー表示範囲 `[E_min, E_max]`。
:type Erange: list[float, float]
:param occups: upスピン(または非スピン偏極)の各バンドの占有率。占有率に応じて色を変化させるために使用。デフォルトはNone。
:type occups: list[list[float]], optional
:param occdns: downスピンの各バンドの占有率 (ISPIN=2の場合のみ)。占有率に応じて色を変化させるために使用。デフォルトはNone。
:type occdns: list[list[float]], optional
:param ktotallist: k点経路の特定の境界(高対称点など)における、最初のk点からの距離の和のリスト。これらの位置に縦線が引かれる。デフォルトはNone。
:type ktotallist: list[float], optional
:param ktotal_namelist: `ktotallist` に対応するk点境界の名称リスト。X軸の目盛りラベルとして使用。デフォルトはNone。
:type ktotal_namelist: list[str], optional
:param nmax: 占有率の最大値。占有率を正規化して色を決定するために使用される。デフォルトは1.0。
:type nmax: float, optional
:param EV: 価電子帯端エネルギー (eV)。補助線としてプロット。デフォルトはNone。
:type EV: float, optional
:param EC: 伝導帯端エネルギー (eV)。補助線としてプロット。デフォルトはNone。
:type EC: float, optional
:param EF: フェルミ準位エネルギー (eV)。補助線としてプロット。デフォルトはNone。
:type EF: float, optional
:param EHOMO: HOMOエネルギー準位 (eV)。補助線としてプロット。デフォルトはNone。
:type EHOMO: float, optional
:param ELUMO: LUMOエネルギー準位 (eV)。補助線としてプロット。デフォルトはNone。
:type ELUMO: float, optional
:param EVlabel: `EV` の凡例ラベル。デフォルトは`'$E_V$'`。
:type EVlabel: str, optional
:param EClabel: `EC` の凡例ラベル。デフォルトは`'$E_C$'`。
:type EClabel: str, optional
:param EFlabel: `EF` の凡例ラベル。デフォルトは`'$E_F$'`。
:type EFlabel: str, optional
:param EHOMOlabel: `EHOMO` の凡例ラベル。デフォルトは`'$E_{HOMO}$'`。
:type EHOMOlabel: str, optional
:param ELUMOlabel: `ELUMO` の凡例ラベル。デフォルトは`'$E_{LUMO}$'`。
:type ELUMOlabel: str, optional
:param marker: バンドをプロットする際のマージンのスタイル。デフォルトは`'o'`。
:type marker: str, optional
:param linestyle: バンドをプロットする際の線種。デフォルトは`''` (線なし)。
:type linestyle: str, optional
:param color: バンドの基本色。占有率による色分けがない場合に使用。デフォルトは`'black'`。
:type color: str, optional
:param linewidth: バンドの線の太さ。デフォルトは0.3。
:type linewidth: float, optional
:param markersize: マーカーのサイズ。デフォルトは2.0。
:type markersize: float, optional
:param markeredgewidth: マーカーの縁の太さ。デフォルトは0.5。
:type markeredgewidth: float, optional
:param legendloc: 凡例の位置。デフォルトは`'best'`。
:type legendloc: str, optional
:param fontsize: 軸ラベルのフォントサイズ。デフォルトは16。
:type fontsize: int, optional
:param labelsize: 目盛りラベルのフォントサイズ。この引数は現在コード内で直接使用されていませんが、Docstringとして定義されています。デフォルトは12。
:type labelsize: int, optional
:param legend_fontsize: 凡例のフォントサイズ。デフォルトは12。
:type legend_fontsize: int, optional
:returns: None。この関数はグラフを描画し、明示的な値を返しません。
:rtype: None
"""
# 表示範囲は決め打ち
xlim = [min(xk), max(xk)]
axis.set_xlim(xlim)
axis.set_ylim(Erange)
# print("tkbandstructre.plot_band: Plot EV etc")
if EV is not None:
axis.plot(xlim, [EV, EV], label = EVlabel, linestyle = 'dashed', linewidth = 0.5, color = 'red')
if EC is not None:
axis.plot(xlim, [EC, EC], label = EClabel, linestyle = 'dashed', linewidth = 0.5, color = 'red')
if EF is not None:
axis.plot(xlim, [EF, EF], label = EFlabel, linestyle = 'dashed', linewidth = 0.5, color = 'blue')
if EHOMO is not None:
axis.plot(xlim, [EHOMO, EHOMO], label = EHOMOlabel, linestyle = 'dashed', linewidth = 0.5, color = 'green')
if ELUMO is not None:
axis.plot(xlim, [ELUMO, ELUMO], label = ELUMOlabel, linestyle = 'dashed', linewidth = 0.5, color = 'green')
# print("tkbandstructre.plot_band: Plot band structure")
# バンド構造をプロット
# 色の濃淡を表現するために16進数文字のリストを準備
convchar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
# print("k point names:", ktotal_namelist)
if occups is None:
axis.plot(xk, yEup, linestyle = linestyle, color = color, linewidth = linewidth,
marker = marker, markerfacecolor = 'none', markeredgecolor = 'black',
markeredgewidth = markeredgewidth, markersize = markersize)
if ISPIN == 2:
axis.plot(xk, yEdn, linestyle = linestyle, color = color, linewidth = linewidth,
marker = marker, markerfacecolor = 'none', markeredgecolor = 'red',
markeredgewidth = markeredgewidth, markersize = markersize)
else:
for ik in range(len(xk)):
for iE in range(len(yEup[ik])):
ne = occups[ik][iE]
if ne < 0.0:
ne = 0.0
elif ne > nmax:
ne = nmax
idx = int((nmax - ne) / nmax * 15)
color = convchar[idx] * 6
axis.plot(xk[ik], yEup[ik][iE], linestyle = 'none', color = '#' + color, linewidth = linewidth,
marker = marker, markerfacecolor = "#" + color, markeredgecolor = 'black',
markeredgewidth = markeredgewidth, markersize = markersize)
if ISPIN == 2:
ne = occdns[ik][iE]
if ne < 0.0:
ne = 0.0
elif ne > nmax:
ne = nmax
idx = int((nmax - ne) / nmax * 15)
color = 'ff' + convchar[idx]*4
axis.plot(xk[ik], yEdn[ik][iE], linestyle = 'none', color = '#' + color, linewidth = linewidth,
marker = marker, markerfacecolor = "#" + color, markeredgecolor = 'red',
markeredgewidth = markeredgewidth, markersize = markersize)
if ktotallist is not None:
# Γ点、BZ境界の縦線を引く
for i in range(1, len(ktotallist)):
axis.plot([ktotallist[i-1], ktotallist[i-1]], Erange,
linestyle = '-', color = 'black', linewidth = 0.5)
# k軸の目盛りにk点の名称を表示する
# グラフ枠が一つであれば plt.xtics()で設定できる
# axisに対しては、.setpでattributeを直接書き換える必要があるらしい
plt.setp(axis, xticks = ktotallist, xticklabels = ktotal_namelist)
axis.set_xlabel("$k$", fontsize = fontsize)
axis.set_ylabel("$E$ (eV)", fontsize = fontsize)
if EV is not None or EC is not None or EF is not None:
axis.legend(fontsize = legend_fontsize, loc = legendloc)
axis.tick_params(labelsize = fontsize)