主な目標
地域暖房ネットワークの感度分析。
アプローチ
AixLib および BuildingSystem ライブラリを使用したシステムの Modelica モデル (Dymola 内)
モデルを FMU コシミュレーションとしてエクスポート
SALib (感度分析 Python ライブラリ) を使用してサンプルを定義します (パラメーター スイープ)
PyFMI を使用して、個々のサンプルすべてに対して Python の for ループでモデルを実行します (複数のプロセッサでシミュレーションを実行するために、JobLib を使用して for ループを並列化します)。
分散ベースの感度分析を実行する SALib ( http://salib.readthedocs.io/en/latest/basics.html#an-example )
最初の一歩
石神関数のシンプルなモデリカモデル (時間に依存しない)。この関数は、感度分析方法をテストするためによく使用されます ( https://www.sfu.ca/~ssurjano/ishigami.html )。
Python コード (PyFMI とパラメーター スイープを使用した FMU の読み込みを含む) は正常に動作します。
問題
一定量のシミュレーションの後、エラーが発生します。エラー出力は常に同じに見えるとは限りません。時々私たちは得る
FMUException: バイナリのロード中にエラーが発生しました。DLL を読み込めませんでした: Eine DLL-Initialisierungsroutine ist fehlgeschlagen.
翻訳: DLL 初期化ルーチンが失敗しました。
そして時々私たちは得る:
FMUException: バイナリのロード中にエラーが発生しました。DLL をロードできませんでした: Für diesen Befehl ist nicht genügend Speicher verfügbar.
翻訳:このコマンドに使用できる十分なメモリがありません。
このエラーは、約 650 回のシミュレーション実行後に発生します。これは、シミュレーションが次々と再実行される小さなループ ブロックで実行されるか、またはすべてのシミュレーションで 1 つの for ループが実行されるかに依存しません。Python コンソール/プロセスを再起動すると、新しいシミュレーションを再度実行できます。
作業環境:
Windows 10、Python 2.7、pip (JModelica ではない) を使用してインストールされた PyFMI、Jupyther ノートブック (Mozilla Firefox) での Python コーディング
Python と PyFMI の基本的な知識しかなく、このエラーに本当に苦労しています。
付属品
以下に見つけることができます
Dymola からコシミュレーション FMU をエクスポートするために使用される Modelica モデル (CVode を使用)
py ファイルとしての Python コード
Python コードの散布図を出力します。
ファイルを直接ダウンロードできる JModelica フォーラムにも投稿しました (FMU、Jupyter ノートブックなど): http://www.jmodelica.org/27925
モデリカモデル
model IshigamiFunction
final parameter Real a = 7;
final parameter Real b = 0.05;
parameter Real x1 = 1;
parameter Real x2 = 1;
parameter Real x3 = 1;
Real f;
equation
f = sin(x1) + a * sin(x2)^2 + b * x3^4 * sin(x1);
end IshigamiFunction;
Python コード
import numpy as np
import pylab as pl
from pyfmi import load_fmu
from SALib.sample import saltelli
from SALib.analyze import sobol
from ipywidgets import FloatProgress
from IPython.display import display
n = 100
problem = {
'num_vars': 3,
'names': ['x1', 'x2', 'x3'],
'bounds': [[-np.pi, np.pi],
[-np.pi, np.pi],
[-np.pi, np.pi]]
}
param_values = saltelli.sample(problem, n)
fmu = 'Model\IshigamiFunction\IshigamiFunction.fmu'
n_sim = param_values.shape[0]
# Progress bar
f = FloatProgress(min = 0, max = n_sim, description='Progress:')
display(f)
# Numpy array to save results
y = np.zeros([param_values.shape[0]])
x1 = np.zeros([param_values.shape[0]])
x2 = np.zeros([param_values.shape[0]])
x3 = np.zeros([param_values.shape[0]])
for i, X in enumerate(param_values):
model = load_fmu(fmu)
model.set(problem['names'], X)
res = model.simulate(final_time = 1)
y[i] = res['f'][-1]
x1[i] = res['x1'][-1]
x2[i] = res['x2'][-1]
x3[i] = res['x3'][-1]
f.value += 1
# Scatter plots
fig = pl.figure(figsize=(20, 5))
pl.clf()
pl.subplot(1,3,1)
pl.plot(x1, y, 'or')
pl.ylabel('x1')
pl.xlabel('f')
pl.subplot(1,3,2)
pl.plot(x2, y, 'ob')
pl.ylabel('x2')
pl.xlabel('f')
pl.subplot(1,3,3)
pl.plot(x3, y, 'og')
pl.ylabel('x3')
pl.xlabel('f')
pl.suptitle('Scatter plots')
pl.show()
# Sensitivity analysis
Si = sobol.analyze(problem, y, print_to_console=True)
アップデート
さらにいくつかのテストを行ったところ、次のことがわかりました。
FMU が Dymola と JModelica のどちらからエクスポートされたかによって、動作が異なります。
Dymola からエクスポートされた FMU を使用する:
load_fmu
forループから行を取り出すとうまくいくようですload_fmu
forループにない場合でも、クラッシュすることがあります- コマンドが正常に動作するように見える
model.reset()
前に新しい行を追加するmodel.set(...)
- ある場合とない場合でシミュレートすると結果が異なる
model.reset()
-> なぜ?? model.instantiate()
の代わりにmodel.reset()
-> は機能しません。タスク マネージャーのメモリ使用量は最大で約 350 MB になり、その後FMUException: モデルのインスタンス化に失敗しました。詳細については、ログを参照してください。
log_level=4 のログ ファイル:
FMIL: module = FMILIB, log level = 4: XML specifies FMI standard version 2.0
FMIL: module = FMILIB, log level = 4: Loading 'win32' binary with 'default' platform types
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiInstantiateModel completed
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiInstantiateSlave
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiInstantiateModel completed
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiInstantiateSlave
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetReal: x1 = -1.76101
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetReal: x2 = -2.53414
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetReal: x3 = 0.116583
FMIL: module = Model, log level = 4: [][FMU status:OK] fmi2SetupExperiment: startTime is set to 0
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiEnterSlaveInitializationMode...
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiEnterSlaveInitializationMode completed
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiExitSlaveInitializationMode...
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiExitSlaveInitializationMode completed
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetReal: x1 = -1.76101
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetReal: x2 = -2.53414
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetReal: x3 = 0.116583
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetReal: a = 7
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetReal: b = 0.05
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetReal: f = 1.29856
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.002
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.004
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.006
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiGetDerivatives
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.008
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.01
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.012
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.014
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.016
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.018
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.02
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
...
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.99
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.992
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.994
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.996
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 0.998
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiSetTime to 1
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiDoStep
FMIL: module = Model, log level = 1: [][FMU status:Fatal] The license file was not found. Use the environment variable "DYMOLA_RUNTIME_LICENSE" to specify your Dymola license file.
FMIL: module = Model, log level = 1: [][FMU status:Fatal] Instantiation failed
FMIL: module = Model, log level = 4: [][FMU status:OK] fmiFreeModelInstance
JModelica からエクスポートされた FMU を使用する:
- が for ループ内にある場合でも正常に動作
load_fmu
します (ただし低速) - この経験は、5.4.2 章 ( http://www.jmodelica.org/api-docs/usersguide/2.1/ch05s04.html#d0e1854 )の JModelica ドキュメント内で与えられた例に対応していません
load_fmu
。 -ループ - コマンド
model.reset()
ormodel.instatiate()
は for ループ内で必要です (Dymola FMU とは対照的に) -> なぜ??
私の質問:
FMU モデルを異なるパラメーターで何度もシミュレートするループを実行する正しい理由は何ですか?
model.reset()
を使用する場合と使用しない場合の違いは何model.instatiate()
ですか?
付属品
model.reset()
これは、for ループがある場合とない場合
の違いを示すプロットです。
JModelica からエクスポートされた FMU (ライセンスは必要ありません) は、http ://www.jmodelica.org/27925#comment-6668 からダウンロードできます。