主要目标
区域供热网络的敏感性分析。
方法
使用 AixLib 和 BuildingSystem 库的系统 Modelica 模型(在 Dymola 中)
将模型导出为 FMU 联合仿真
使用 SALib(敏感性分析 python 库)定义样本(参数扫描)
使用 PyFMI 在 Python 中的 for 循环中为所有单个样本运行模型(并并行化 for 循环,可能使用 JobLib 在多个处理器上执行模拟)
SALib 执行基于方差的敏感性分析 ( http://salib.readthedocs.io/en/latest/basics.html#an-example )
第一步
Ishigami 函数的简单 modelica 模型(不依赖于时间)。该功能常用于测试敏感性分析方法(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 次模拟运行之后。这不取决于模拟是在较小的循环块中执行的,这些循环块是一个接一个地重新运行的,还是一个单独的 for 循环贯穿所有模拟。通过重新启动 python 控制台/进程,可以再次运行新的模拟。
工作环境:
Windows 10、Python 2.7、使用 pip(不是 JModelica)安装的 PyFMI、Jupyther notebook 上的 Python 编码(在 Mozilla Firefox 上)
我们只有 python 和 PyFMI 的基本知识,并且真的在为这个错误而苦苦挣扎!
附件
您可以在下面找到
用于从 Dymola 导出协同仿真 FMU 的 Modelica 模型(使用 CVode)
Python 代码作为 py 文件
python代码的输出散点图。
我还在JModelica论坛发了一个帖子,可以直接下载文件(FMU、Jupyter notebook等): 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:
- 从for循环中取出这
load_fmu
条线似乎有效 - 即使
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:
- 即使
load_fmu
在 for 循环内也能正常工作(但速度较慢) - 此经验与第 5.4.2 章 ( http://www.jmodelica.org/api-docs/usersguide/2.1/ch05s04.html#d0e1854 ) 中JModelica 文档中给出的示例不对应,其中
load_fmu
命令在 for -环形 - for 循环中需要命令
model.reset()
or (与 Dymola FMU 相反) -> 为什么?model.instatiate()
我的问题:
执行循环的正确原因是什么,该循环以不同的参数多次模拟 FMU 模型?
model.reset()
using或model.instatiate()
none 和有什么区别?
附件
model.reset()
这是一个图表,显示了带有和不带有它
的 for 循环之间的区别。
从 JModelica 导出的 FMU(不需要任何许可证)可以在这里下载:http ://www.jmodelica.org/27925#comment-6668