pvfit_simple.py ドキュメント
1. プログラム概要
pvfit_simple.py は、太陽電池の電流-電圧特性を一ダイオードモデル(Single-Diode Model, SDM)でフィッティングするための簡易ツールです。
主な目的は、測定IVデータから以下の5つのモデルパラメータを抽出することです。
パラメータ |
意味 |
単位 |
|---|---|---|
|
ダイオード逆飽和電流 |
A |
|
ダイオード理想因子 |
無次元 |
|
光生成電流 |
A |
|
直列抵抗 |
Ω |
|
シャント抵抗 |
Ω |
このスクリプトは、入力CSVファイルからIVデータを読み込み、必要に応じて初期値推定を行い、scipy.optimize.minimize によりパラメータを最適化します。
実行モードは以下の3種類です。
モード |
内容 |
|---|---|
|
IVデータから初期パラメータを推定し、CSVへ保存 |
|
初期パラメータまたは既存CSVを用いてSDMフィッティングを実行 |
|
指定済みパラメータでIVカーブを計算・表示 |
処理の大まかな流れは以下です。
コマンドライン引数を解析する。
入力CSVから
DataValue行を読み込み、電圧Vと電流Iを抽出する。電圧昇順にソートし、
xmin,xmaxが指定されていれば範囲を制限する。initモードでは初期パラメータを推定する。fitモードでは対数電流誤差を目的関数としてパラメータを最適化する。最終IVカーブを線形スケールと対数スケールで表示する。
パラメータCSVを保存する。
2. 使用されている電気特性モデル
2.1 一ダイオードモデルの符号規約
このコードでは、外部端子電圧を V、ダイオード・シャント枝にかかる内部電圧を Vd、ダーク電流成分を Idark、最終的な端子電流を I として扱います。
実装上の最終出力電流は次式です。
ここで、IPV は正の光生成電流として扱われます。そのため、照明下の短絡電流は通常負側に出ます。
コード上では、まず Idark を未知数として数値的に解き、その後で IPV を差し引いて総電流を得ています。
2.2 熱電圧
ダイオード指数項には、理想因子を含む熱電圧が使われます。
ここで、
記号 |
コード上の変数 |
意味 |
|---|---|---|
\(n\) |
|
ダイオード理想因子 |
\(k_B\) |
|
ボルツマン定数 |
\(T\) |
|
温度 K |
\(q\) |
|
電気素量 |
実装で使われる定数は以下です。
2.3 内部電圧と直列抵抗
コードでは、ダーク電流 Idark による直列抵抗電圧降下を考慮して、内部電圧 Vd を次式で定義しています。
ここで、Rs は直列抵抗です。
注意点として、一般的な太陽電池SDMでは、端子電流 I を用いて \(V_d = V + I R_s\) のように書かれることもあります。しかし、この実装では Idark を未知数として解く形になっており、コード上の式は上記の形です。
2.4 ダーク電流方程式
model() 関数では、Idark が以下の非線形方程式を満たすように brentq で根を求めています。
Vd を代入すると、解くべき方程式は以下です。
この方程式を各電圧点ごとに解きます。
2.5 最終的なIVモデル式
根探索で得た Idark から、最終的な計算電流は次式で与えられます。
したがって、全体としては次の暗黙方程式で表せます。
ただし、右辺の指数項とシャント項に現れる未知量は I そのものではなく、コード内部で解かれる Idark です。
2.6 指数オーバーフロー対策
指数関数の引数は以下のようにクリップされています。
これは、np.exp() のオーバーフローを避けるためです。
2.7 根探索の探索範囲
各電圧点で Idark を求める際、探索範囲は以下の値を基準に設定されます。
そして、brentq の探索区間は以下です。
ここで、
です。
根が見つからない場合は、フォールバックとして以下の近似値を返します。
3. パラメータ抽出の数式
3.1 初期パラメータ推定の全体
--mode init では、測定IVデータから以下の初期値を作ります。
パラメータ |
初期値の決め方 |
|---|---|
|
固定初期値 \(1.0 \times 10^{-10}\) |
|
固定初期値 1.5 |
|
V=0近傍の多項式近似から推定 |
|
固定初期値 10.0 |
|
負電圧領域の微分値から推定 |
|
固定初期値 0.5 |
|
|
この初期値は、物理的に厳密な最終値ではなく、フィッティングを開始するための値です。
3.2 重複電圧の除去
初期値推定では、まず重複する電圧値を取り除きます。
np.unique(V, return_index=True) により、各電圧値の最初のデータ点が使われます。
3.3 短絡電流 ISC の近似
V=0 に最も近い点のインデックスを idx_v0 とし、その前後最大7点を用いて3次多項式をフィットします。
この多項式を \(V=0\) で評価した値が短絡電流の近似になります。
実装上は、IPV を正値として扱うため、以下の式で初期値を設定します。
ここで、
です。
3.4 シャント抵抗 Rsh の初期推定
負電圧領域が存在する場合、電流の数値微分を使って Rsh を推定します。
まず、数値微分を計算します。
コードでは np.gradient(uI, uV) が使われます。
負電圧領域の最初の微分値を使い、以下のようにシャント抵抗を推定します。
負電圧領域が存在しない場合は、次の固定値が使われます。
注意点として、この簡易版では負電圧領域全体の線形回帰ではなく、負電圧領域における最初の勾配値のみを使用しています。そのため、ノイズが大きいデータでは Rsh の初期値が不安定になる可能性があります。
3.5 I0 と ndiode の初期値
I0 と ndiode は、初期値推定ではデータから抽出されず、固定初期値として設定されます。
これらは fit モードで自由パラメータとして最適化できます。ただし、--fix I0 ndiode のように指定した場合は固定されます。
3.6 Rs の初期値
Rs は、初期値推定ではデータから抽出されず、固定初期値として設定されます。
この値も fit モードで最適化されます。
3.7 フィッティング目的関数
フィッティングでは、線形電流値ではなく、絶対電流の常用対数を使って残差平方和を最小化します。
測定電流を \(I_{\mathrm{meas},i}\)、モデル電流を \(I_{\mathrm{calc},i}\) とすると、目的関数は以下です。
ここで、
です。
この目的関数により、電流が桁で大きく変化するIV特性でも、低電流領域と高電流領域の両方を扱いやすくしています。
ただし、符号情報は目的関数内では絶対値により失われます。符号反転付近やゼロクロス近傍では注意が必要です。
3.8 最適化変数の変換
ndiode 以外のパラメータは、常用対数空間で最適化されます。
ndiode 以外のパラメータについて、最適化変数を \(x_p\) とすると、実パラメータは以下で復元されます。
対象は以下です。
パラメータ |
最適化空間 |
|---|---|
|
\(\log_{10}(I0)\) |
|
\(\log_{10}(IPV)\) |
|
\(\log_{10}(Rs)\) |
|
\(\log_{10}(Rsh)\) |
|
線形値 |
初期最適化ベクトルは以下です。
ただし、抵抗系パラメータには EPS_R、電流系パラメータには EPS_I が下限として使われます。
3.9 固定パラメータ
--fix で指定されたパラメータ、およびパラメータCSVの optid=0 のパラメータは、最適化ベクトルから除外されます。
固定集合を \(F\) とすると、最適化対象は以下です。
3.10 開回路電圧 VOC の抽出
フィッティング後、最適化されたパラメータでIVカーブを再計算し、電流がゼロになる電圧を多項式根として推定します。
まず、電圧グリッドを作ります。
次に、モデル電流 \(I(V_{\mathrm{grid}})\) を計算し、3次多項式近似します。
開回路電圧は以下を満たす根です。
複数の実根がある場合は、データ平均電圧に最も近い根が採用されます。実根がない場合は線形補間が使われます。
3.11 短絡電流 ISC の抽出
フィッティング後の短絡電流は、最適化されたモデルを \(V=0\) で評価して得られます。
コードでは以下に相当します。
model(0, I0, ndiode, IPV, Rs, Rsh, temperature)[0]
3.12 パラメータ誤差の推定
フィッティング後、有限差分ヤコビ行列を使ってパラメータ誤差を推定します。
モデルの対数電流を次のように定義します。
最適化変数 \(x_j\) に対するヤコビ行列は有限差分で近似されます。
実装では、
です。
残差分散の推定量は以下です。
ここで、\(N\) はデータ点数、\(P\) は自由パラメータ数です。
共分散行列は、擬似逆行列を用いて以下で推定されます。
各最適化変数の標準誤差は以下です。
ndiode は線形スケールなので、そのまま標準誤差として報告されます。
一方、対数空間で最適化されたパラメータは、以下の誤差伝播式で元スケールに変換されます。
3.13 モデル曲線の信頼性区間
モデル曲線の対数スケール標準偏差は以下で計算されます。
プロットでは、モデル電流の絶対値に対して以下の上下限が描画されます。
線形プロットでは、np.sign(I_final) を掛けて符号を維持します。
4. 必要ライブラリ
4.1 標準ライブラリ
ライブラリ |
用途 |
|---|---|
|
コマンドライン引数解析 |
|
CSVファイル読み書き |
|
数学関数用。ただし現行コードでは実質未使用 |
|
ファイル存在確認 |
|
異常終了処理 |
|
例外時のトレースバック表示 |
|
入力ファイル名から出力CSV名を生成 |
4.2 非標準ライブラリ
ライブラリ |
用途 |
|---|---|
|
配列処理、数値微分、多項式近似、対数計算 |
|
IVカーブ描画 |
|
パラメータ最適化 |
|
非線形方程式の根探索 |
インストール例は以下です。
pip install numpy matplotlib scipy
5. 入力ファイル
5.1 入力CSV形式
入力ファイルはCSV形式です。read_data() は、DataName 行が出現した後の DataValue 行をIVデータとして読み込みます。
DataValue 行では、以下の列が使われます。
CSV列番号 |
内容 |
|---|---|
0列目 |
|
1列目 |
電圧 V |
2列目 |
電流 I |
また、以下のメタデータがあれば記録時刻として読み取ります。
条件 |
読み取り内容 |
|---|---|
0列目が |
|
1列目が |
|
2列目 |
|
5.2 入力データ例
MetaData,TestRecord.RecordTime,2026-01-01 12:00:00
DataName,Voltage,Current
DataValue,-0.2,-1.20e-3
DataValue,0.0,-1.00e-3
DataValue,0.5,2.00e-4
DataValue,0.8,1.50e-2
5.3 読み込み時の処理
読み込まれたデータは、以下の処理を受けます。
DataValue行から電圧と電流を数値変換する。電圧
Vの昇順にソートする。--xminが指定されていれば、それ未満の電圧を除外する。--xmaxが指定されていれば、それより大きい電圧を除外する。有効なデータがない場合は
ValueErrorを発生させる。
6. 出力ファイル
6.1 パラメータCSV
入力ファイル名をもとに、以下の名前でパラメータCSVが保存されます。
入力ファイルのstem + "-parameters.csv"
例として、入力が sample.csv の場合は以下です。
sample-parameters.csv
CSV列は以下です。
列名 |
内容 |
|---|---|
|
パラメータ名 |
|
パラメータ値 |
|
1なら自由パラメータ、0なら固定 |
|
推定標準誤差 |
保存される主な行は以下です。
行 |
内容 |
|---|---|
|
逆飽和電流 |
|
ダイオード理想因子 |
|
光生成電流 |
|
直列抵抗 |
|
シャント抵抗 |
|
開回路電圧推定値 |
|
短絡電流推定値 |
|
対数電流残差平方和。 |
6.2 プロット表示
このスクリプトは画像ファイルを保存せず、matplotlib で画面表示します。
表示されるプロットは以下の2種類です。
プロット |
内容 |
|---|---|
線形スケール |
測定電流とモデル電流 |
対数スケール |
|
fit モードでは、フィッティング中にも指定間隔でプロットが更新されます。
7. 関数・クラス一覧
7.1 クラス
このスクリプトにはクラス定義はありません。
7.2 グローバル定数・変数
名前 |
初期値 |
用途 |
|---|---|---|
|
|
ボルツマン定数 |
|
|
電気素量 |
|
|
フィッティング対象パラメータ一覧 |
|
|
対数電流計算のゼロ回避 |
|
|
抵抗値のゼロ回避 |
7.3 関数一覧
関数名 |
引数 |
戻り値 |
動作 |
副作用 |
|---|---|---|---|---|
|
|
|
入力CSVからIVデータを読み込み、電圧順にソート |
ファイル読み込み、情報を標準出力 |
|
|
|
パラメータCSVを読み込む |
ファイル読み込み |
|
|
なし |
パラメータ・誤差・RSSをCSV保存 |
ファイル書き込み |
|
|
根の推定値 |
多項式近似により指定値に対応するxを推定 |
なし |
|
|
モデル電流配列 |
一ダイオードモデルを数値的に解く |
根探索失敗時に近似値を返す |
|
|
RSS |
対数電流残差平方和を計算 |
なし |
|
|
ヤコビ行列 |
有限差分で対数モデル電流の偏微分を計算 |
なし |
|
|
|
共分散行列からパラメータ誤差と曲線標準偏差を推定 |
警告表示の可能性 |
|
|
なし |
線形・対数IVプロットを描画 |
グラフ描画 |
|
|
|
最適化を実行し結果を保存 |
プロット表示、CSV保存、標準出力 |
|
|
|
初期値を推定またはCSVから読み込む |
CSV読み込みの可能性 |
|
なし |
なし |
CLI実行全体を制御 |
ファイル読み書き、プロット表示、標準出力 |
8. コマンドライン引数
引数 |
型 |
デフォルト |
意味 |
|---|---|---|---|
|
choice |
|
|
|
str |
|
|
|
str |
|
入力IV CSVファイル |
|
float |
|
セル温度 K |
|
float |
なし |
使用する最小電圧 |
|
float |
なし |
使用する最大電圧 |
|
float |
なし |
|
|
float |
なし |
|
|
float |
なし |
|
|
float |
なし |
|
|
float |
なし |
|
|
list[str] |
空リスト |
固定するパラメータ名 |
|
int |
|
非線形最小二乗近似用点数。ただし現行コードでは実質未使用 |
|
int |
|
フィット中のコンソール出力間隔 |
|
int |
|
フィット中のプロット更新間隔 |
9. Usage
9.1 初期パラメータを作成する
python pvfit_simple.py --mode init --infile sample.csv
この実行では、sample.csv を読み込み、初期パラメータを推定して以下を保存します。
sample-parameters.csv
9.2 フィッティングを実行する
python pvfit_simple.py --mode fit --infile sample.csv
この実行では、sample-parameters.csv が存在すれば読み込み、存在しなければ初期値を自動生成してフィッティングします。
9.3 電圧範囲を指定してフィットする
python pvfit_simple.py --mode fit --infile sample.csv --xmin -0.2 --xmax 1.0
この実行では、-0.2 V から 1.0 V の範囲だけを使用してフィッティングします。
9.4 一部パラメータを固定する
python pvfit_simple.py --mode fit --infile sample.csv --fix ndiode Rs
この実行では、ndiode と Rs は固定され、それ以外のパラメータのみが最適化されます。
9.5 パラメータを手動指定してシミュレーションする
python pvfit_simple.py --mode sim --infile sample.csv --I0 1e-10 --ndiode 1.5 --IPV 1e-3 --Rs 5 --Rsh 1e5
この実行では、指定したパラメータによりIVカーブを計算して表示します。
10. 具体的な実行例
10.1 初期値生成からフィットまでの典型例
まず初期値を作成します。
python pvfit_simple.py --mode init --infile cell_iv.csv
この時点で、以下が作成されます。
cell_iv-parameters.csv
次にフィッティングを実行します。
python pvfit_simple.py --mode fit --infile cell_iv.csv --temperature 300 --method Nelder-Mead
この実行では、以下が行われます。
cell_iv.csvからIVデータを読み込む。cell_iv-parameters.csvから初期パラメータを読み込む。固定指定されていないパラメータを最適化する。
各電圧点で
brentqによりSDMの暗黙方程式を解く。対数電流残差平方和を最小化する。
最終パラメータ、誤差、
VOC_est,ISC_est,RSS_logyをCSVへ保存する。最終IVカーブを線形・対数プロットで表示する。
10.2 低電圧側だけでRshを重視する例
python pvfit_simple.py --mode fit --infile cell_iv.csv --xmin -0.3 --xmax 0.2
この場合、読み込み後に -0.3 V から 0.2 V のデータだけが残ります。低電圧領域の挙動を重視したフィットになりますが、高電圧側のダイオード指数領域を十分に含まないため、I0 や ndiode の推定は不安定になる可能性があります。
11. import方法
このファイルはスクリプトとして実行することを主目的としていますが、関数単位で import して利用することもできます。
import pvfit_simple
または以下のように必要な関数だけを import できます。
from pvfit_simple import model, read_data
11.1 API利用例
import numpy as np
from pvfit_simple import model
V = np.linspace(-0.2, 1.0, 200)
I = model(
V,
I0=1e-10,
ndiode=1.5,
IPV=1e-3,
Rs=5.0,
Rsh=1e5,
temperature=300.0,
)
12. main scriptとして実行した場合
このファイルには、以下のmain script判定があります。
if __name__ == "__main__":
try:
main()
except Exception:
traceback.print_exc()
sys.exit(1)
スクリプトとして実行した場合は、main() が呼ばれます。
main() の動作は以下です。
argparseによりコマンドライン引数を読む。read_data()で入力CSVを読む。入力ファイル名からパラメータCSV名を作る。
get_initial_params()で初期値を取得する。init,fit,simの各モードに分岐する。最終モデル電流を計算する。
線形・対数IVプロットを表示する。
例外が発生した場合は、トレースバックを表示して終了コード1で終了します。
13. 注意点・制限事項
13.1 符号規約に注意
この実装では、最終電流が以下で定義されます。
そのため、照明下の短絡電流は負値として出ることが想定されています。別の装置や解析ソフトで電流符号が逆の場合は、入力データの符号を確認してください。
13.2 目的関数は電流の絶対値を使う
目的関数では以下が使われます。
したがって、電流の符号そのものはフィッティング指標に直接反映されません。ゼロクロス近傍や符号反転を含むデータでは、物理的に妥当でないフィットでもRSSが小さくなる可能性があります。
13.3 初期値推定は簡易的
IPV はV=0近傍の3次多項式、Rsh は負電圧領域の最初の数値微分値から推定されます。
以下のような場合、初期値が不安定になる可能性があります。
V=0近傍のデータ点が少ない
負電圧領域のデータがない
ノイズが大きい
ダブルスイープでヒステリシスが強い
電圧重複点が多い
13.4 Rs は初期値推定されない
この簡易版では、Rs はデータから推定されず、初期値10Ωから開始されます。高電圧領域のデータが不足している場合、Rs の最適化は不安定になる可能性があります。
13.5 I0 と ndiode も初期推定されない
I0 と ndiode はそれぞれ以下の固定初期値から開始します。
暗電流領域のデータが不足している場合、これらのパラメータは他のパラメータと強く相関し、推定が不安定になります。
13.6 境界条件は設定されていない
minimize() には明示的な bounds が設定されていません。ndiode は線形空間で最適化されるため、最適化手法や初期値によっては物理的に不適切な値になる可能性があります。
13.7 nlsq_points は現行コードでは実質未使用
CLI引数として --nlsq_points は定義されていますが、現行実装では初期値推定やフィット処理に実質的には使われていません。将来拡張用の引数と考えられます。
13.8 画像ファイルは保存されない
最終プロットは画面表示のみです。PNGやPDFとして保存する処理はコードからは確認できません。
13.9 Excel出力はない
この簡易版では、Excelファイルへの保存処理はありません。出力ファイルはパラメータCSVのみです。
13.10 brentq が失敗した場合の近似
各電圧点で根探索が失敗すると、以下の近似式が使われます。
この場合、ダイオード電流や直列抵抗の影響は反映されません。大量の点で根探索に失敗する場合、フィット結果の信頼性は低下します。
14. コードから確認できない事項
以下はコードからは確認できません。
入力CSVの正式な装置仕様
電圧・電流の単位が必ずV/Aであることの外部保証
面積正規化電流密度への変換機能
温度依存パラメータの物理モデル
Rs, Rsh, I0, ndiode の外部境界制約
プロット画像の保存機能
複数ファイル一括解析機能
TFE, FN, SCLC などの追加輸送メカニズム