5

主要目标

区域供热网络的敏感性分析。

方法

  1. 使用 AixLib 和 BuildingSystem 库的系统 Modelica 模型(在 Dymola 中)

  2. 将模型导出为 FMU 联合仿真

  3. 使用 SALib(敏感性分析 python 库)定义样本(参数扫描)

  4. 使用 PyFMI 在 Python 中的 for 循环中为所有单个样本运行模型(并并行化 for 循环,可能使用 JobLib 在多个处理器上执行模拟)

  5. 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)

python脚本的输出图 在此处输入图像描述

更新

我做了一些更多的测试,这就是我发现的:

根据 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:

我的问题:

执行循环的正确原因是什么,该循环以不同的参数多次模拟 FMU 模型?

model.reset()using或model.instatiate()none 和有什么区别?

附件

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 实例,多次调用将创建多个实例,每个实例都需要新的内存分配和正确删除。

  • 重置

    在实例化之后和调用 fmiInitializeSlave/fmi2Intialize 之前将您的实例重置为状态。这更快,不需要新的动态内存分配,应该在您的情况下使用。

此外,在调用 fmiFreeSalveInstance/fmi2FreeInstance 时,未进行二进制导出的 Dymola FMU 导出的许可证检查可能会泄漏旧 Dymola 版本中的内存。在大多数情况下,这不是问题,因为您通常会在终止 FMU 时终止程序。通过在 for 循环中实例化你的 FMU,这变得很严重,你的记忆最终会结束。如果您联系 Dymola 支持,则应该可以使用修订包。

于 2017-11-22T13:07:45.050 回答
1

对我来说,这似乎是一个内存问题。在 Win 任务管理器中运行时,你能观察到分配的内存吗?顺便说一句,您的 FMU(来自您的交叉帖子)需要 DYMOLA_RUNTIME_LICENSE,这将复制仅限于 Dymola 用户。

于 2017-11-18T13:51:27.820 回答