Python スクリプティング
1. はじめに
OghmaNano では、Python スクリプティングはディスク上のシミュレーション設定ファイルを直接編集し、
その後シミュレーションエンジン(oghma_core.exe)を呼び出してモデルを実行することで動作します。
このセクションでは、このワークフローを詳しく説明します。
2. Python でシミュレーションファイルを実行する
OghmaNano シミュレーションは、単一の JSON 設定ファイル
sim.json によって完全に定義されます。
このファイルには、デバイス構造、
材料パラメータ、数値設定、および出力設定を含む、シミュレーションの完全な状態が含まれています。
多くの場合、sim.json はシミュレーションディレクトリ内に通常ファイルとしてすでに存在しています。
Python から OghmaNano を駆動する場合、スクリプトは Python 標準の
json ライブラリを使用して sim.json をメモリに読み込み、1 つ以上のパラメータを変更し、
更新した JSON をディスクへ書き戻します。
重要なのは、Python スクリプトをシミュレーションディレクトリを作業ディレクトリとして実行しなければならないことです。すなわち、
sim.json(および
sim.oghma)を含むディレクトリです。
これは oghma_core.exe が起動されるディレクトリです。
JSON ファイルが更新されたら、スクリプトは oghma_core.exe を
その同じディレクトリから 起動します。
シミュレーションエンジンは常に現在の作業ディレクトリから入力ファイルを読み込むため、
作業ディレクトリが正しくないと、シミュレーションは失敗するか誤ったモデルを実行します。
この責務の分離は意図的かつ明示的なものです: Python はシミュレーションの中で 何を 変更するかを定義する責任を持ち、 OghmaNano は現在のディレクトリに存在するファイルを使って物理を 実行する 責任を持ちます。
以下の例は、このプロセスを示しています。sim.json を読み込み、最初のデバイス層のキャリア
移動度を変更し、更新した設定をディスクへ書き戻し、その後
シミュレーションディレクトリからシミュレーションを実行します。
import json
import os
import sys
f=open('sim.json') #sim.json ファイルを開く
lines=f.readlines()
f.close()
lines="".join(lines) #テキストを Python の json オブジェクトへ変換する
data = json.loads(lines)
#値を編集する(どの値を編集するか判断する助けとして
# Firefox を json ビューアとして使ってください)
# 今回は layer 1 の移動度を編集しています
data['epitaxy']['segment1']['shape_dos']['mue_y']=1.0
#json オブジェクトを文字列に戻す
jstr = json.dumps(data, sort_keys=False, indent='\t')
#ディスクへ書き戻す
f=open('sim.json',"w")
f.write(jstr)
f.close()
#oghma_core を使ってシミュレーションを実行する
os.system("oghma_core.exe")
sim.json 内のシミュレーションが J–V 曲線を実行するように設定されている場合、OghmaNano は
シミュレーションディレクトリに PCE、フィルファクタ、\(J_{sc}\) および
\(V_{oc}\) のような量を含む出力ファイルを書き出します。
以下の例は、JSON 出力ファイルを読み込み、 \(V_{oc}\) の値を別のテキストファイルへ追記する方法を示しています。
f=open('sim_info.dat')
lines=f.readlines()
f.close()
lines="".join(lines)
data = json.loads(lines)
f=open('out.dat',"a")
f.write(str(data["Voc"])+"\n");
f.close()
3. より複雑なシミュレーション
多くのスクリプティングワークフローでは、同じベースシミュレーションを異なるパラメータ 値で複数回実行し、各実行を独自のディレクトリ内に分離して保持したいはずです。これが出力を整理し、 結果を誤って上書きするのを避ける最も単純な方法です。
以下の例では、4 つの移動度
(1e-5、1e-6、1e-7、1e-8)に対応するディレクトリの集合を作成します。各ディレクトリに対して、次を行います:
- ディレクトリを作成します(存在しない場合)。
- 現在の
sim.jsonをそのディレクトリへコピーします。 - コピーされた
sim.jsonを編集して目標移動度を設定します。 - 作業ディレクトリをそのディレクトリへ変更します。
- そのディレクトリでソルバーを実行し、その実行に固有の出力を生成します。
このパターンは OghmaNano におけるバッチスクリプティングの基礎です:1 実行あたり 1 ディレクトリ、1 実行あたり 1 設定ファイル、 そして各パラメータ値に対して整理された出力フォルダです。
import json
import os
import shutil
# スクリプトはベースシミュレーションディレクトリで開始する必要があります
# (すなわち参照 sim.json を含むディレクトリ)。
base_dir = os.getcwd()
mobilities = [1e-5, 1e-6, 1e-7, 1e-8]
for mu in mobilities:
# 読みやすく並び順も整うディレクトリ名を作成する
run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
os.makedirs(run_dir, exist_ok=True)
# ベースの sim.json を実行ディレクトリへコピーする
src_sim = os.path.join(base_dir, "sim.json")
dst_sim = os.path.join(run_dir, "sim.json")
shutil.copyfile(src_sim, dst_sim)
# コピーした sim.json を読み込み、そのコピー内の移動度を編集する
f = open(dst_sim)
lines = f.readlines()
f.close()
lines = "".join(lines)
data = json.loads(lines)
# 値を編集する:最初のデバイス層の移動度を設定する
data['epitaxy']['segment1']['shape_dos']['mue_y'] = mu
jstr = json.dumps(data, sort_keys=False, indent='\t')
f = open(dst_sim, "w")
f.write(jstr)
f.close()
# 実行ディレクトリへ移動し、そこでソルバーを実行する
os.chdir(run_dir)
# コマンドが "augment.nano" の場合は、以下の文字列を置き換えてください。
os.system("oghma_core.exe")
# 次の実行のためにベースディレクトリへ戻る
os.chdir(base_dir)
実行後、各ディレクトリにはその移動度値に対応する出力が含まれます。 次のセクションでは、このスクリプトを拡張して各実行から主要な結果を収集し、 単一の要約ファイルへ集約します。
逆移動度に対する \(V_{oc}\) のプロット
複数のシミュレーションを別々のディレクトリで実行した後、通常の次のステップは、各実行から重要な指標を抽出し、
傾向を可視化することです。一般的な例として、JSON 出力ファイル(sim_info.dat)から
開放電圧 \(V_{oc}\) を読み取り、
逆移動度 \(1/\mu\) に対してプロットする方法があります。
以下のスクリプトは、一連の実行ディレクトリ(例えば mu_1e-05、mu_1e-06、...)
を走査し、各ディレクトリに対して次を行います:
sim_info.datを JSON として読み込みます。Vocを抽出します。- そのディレクトリに対応する移動度を用いて \(1/\mu\) を計算します。
- 小さな要約ファイル(
voc_vs_inv_mobility.dat)を書き出します。 - \(V_{oc}\) vs \(1/\mu\) をプロットします。
import json
import os
# 任意:プロット用(matplotlib が必要)
import matplotlib.pyplot as plt
base_dir = os.getcwd()
# 移動度は、以前に生成した実行ディレクトリと一致している必要があります
mobilities = [1e-5, 1e-6, 1e-7, 1e-8]
inv_mu = []
vocs = []
for mu in mobilities:
run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
info_path = os.path.join(run_dir, "sim_info.dat")
# JSON 出力ファイルを読み込み、Voc を抽出する
f = open(info_path)
lines = f.readlines()
f.close()
lines = "".join(lines)
data = json.loads(lines)
voc = data["Voc"]
inv_mu.append(1.0 / mu)
vocs.append(voc)
# 小さな要約表をディスクへ書き出す
out = open("voc_vs_inv_mobility.dat", "w")
out.write("# inv_mobility(1/mu) Voc(V)\n")
for x, y in zip(inv_mu, vocs):
out.write(f"{x:.6e} {y}\n")
out.close()
# 逆移動度に対して Voc をプロットする
plt.plot(inv_mu, vocs, "o-")
plt.xlabel("Inverse mobility (1/μ)")
plt.ylabel("Open-circuit voltage Voc (V)")
plt.title("Voc vs inverse mobility")
plt.grid(True)
plt.tight_layout()
plt.show()
📺 関連動画
以下の動画では、Python スクリプティングを使用して OghmaNano を駆動する方法を示しています。
注: 動画で示されている API と内部スクリプティングインターフェースは現在では非推奨であり、
保守が困難であることが分かったため、もはや同梱されていません。現在推奨されるワークフローは、外部 Python
スクリプトを使用して JSON シミュレーションファイルを直接編集し、その後で oghma_core.exe を呼び出す方法です。この方法は
より単純で、より堅牢であり、保守もしやすいです。動画は全体的なワークフローや典型的なユースケースを理解するうえでは依然として有用ですが、
最新の方法については上記の手順に従ってください。