5

主な目標

地域暖房ネットワークの感度分析。

アプローチ

  1. AixLib および BuildingSystem ライブラリを使用したシステムの Modelica モデル (Dymola 内)

  2. モデルを FMU コシミュレーションとしてエクスポート

  3. SALib (感度分析 Python ライブラリ) を使用してサンプルを定義します (パラメーター スイープ)

  4. PyFMI を使用して、個々のサンプルすべてに対して Python の for ループでモデルを実行します (複数のプロセッサでシミュレーションを実行するために、JobLib を使用して for ループを並列化します)。

  5. 分散ベースの感度分析を実行する 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)

Python スクリプトからプロットを出力する ここに画像の説明を入力

アップデート

さらにいくつかのテストを行ったところ、次のことがわかりました。

FMU が Dymola と JModelica のどちらからエクスポートされたかによって、動作が異なります。

Dymola からエクスポートされた FMU を使用する:

  • load_fmuforループから行を取り出すとうまくいくようです
  • load_fmuforループにない場合でも、クラッシュすることがあります
  • コマンドが正常に動作するように見える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 を使用する:

私の質問:

FMU モデルを異なるパラメーターで何度もシミュレートするループを実行する正しい理由は何ですか?

model.reset()を使用する場合と使用しない場合の違いは何model.instatiate()ですか?

付属品

model.reset()これは、for ループがある場合とない場合 の違いを示すプロットです。ここに画像の説明を入力

JModelica からエクスポートされた FMU (ライセンスは必要ありません) は、http ://www.jmodelica.org/27925#comment-6668 からダウンロードできます。

4

2 に答える 2

5

Dymola FMU の正しい方法 (おそらく他のベンダーの FMU も同様) は、for ループの外で fmi/fmi2Instantiate を呼び出すことです。FMU がバイナリ エクスポート ライセンスなしでエクスポートされた場合、これらの関数はメモリを割り当て、ライセンス チェックを実行します。fmiResetSlave/fmi2Reset を呼び出すと、新しいメモリ割り当てなしで FMU をインスタンス化された状態にリセットできます。

  • fmiInstantiateSlave/fmi2Instantiate

    シミュレーションに使用できる FMU インスタンスを作成すると、複数の呼び出しによって複数のインスタンスが作成され、それぞれに新しいメモリ割り当てと適切な削除が必要になります。

  • fmiReset

    インスタンス化後、fmiInitializeSlave/fmi2Intialize が呼び出される前の状態にインスタンスをリセットします。これは高速であり、新しい動的メモリ割り当てを必要としないため、ケースで使用する必要があります。

さらに、古い Dymola バージョンでは、バイナリ エクスポートなしでエクスポートされた Dymola FMU のライセンス チェックで、fmiFreeSalveInstance/fmi2FreeInstance を呼び出すときにメモリ リークが発生する場合があります。通常、FMU を終了するときにプログラムを終了するため、これはほとんどの場合問題になりません。forループ内でFMUをインスタンス化すると、これは深刻になり、メモリは最終的に終了します。Dymola サポートに連絡すると、フィックスパックを入手できるはずです。

于 2017-11-22T13:07:45.050 に答える
1

私にはメモリの問題のように見えます。Win タスク マネージャーでの実行中に、割り当てられたメモリを確認できますか? ところで、FMU (クロスポストから) には DYMOLA_RUNTIME_LICENSE が必要です。これにより、複製が Dymola ユーザーのみに制限されます。

于 2017-11-18T13:51:27.820 に答える