主要目标
区域供热网络的敏感性分析。
方法
使用AixLib和BuildingSystem库的系统的Modelica模型(在Dymola中)
将模型导出为FMU协同模拟
使用SALib(灵敏度分析python库)定义样本(参数扫描)
使用PyFMI在Python的for循环中为所有单个样本运行模型(并且可以使用JobLib并行化for循环以在多个处理器上执行模拟)
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-Initilisation例程失败。
有时我们得到:
FMUException:加载二进制文件时出错。无法加载DLL:Für Diesen Befehl istnichtgenügendSpeicherverfügbar。
翻译:此命令有内存不足。
在大约650次模拟运行后发生错误。 这不取决于模拟是否在较小的循环块中执行,这些循环块一个接一个地重新运行,或者如果一个单循环遍历所有模拟。通过重新启动python控制台/进程,可以再次运行新的模拟。
工作环境:
Windows 10,Python 2.7,使用pip安装的PyFMI(不是JModelica),Jupyther笔记本上的Python编码(在Mozilla Firefox上)
我们只有python和PyFMI的基本知识,并且真的在努力解决这个错误!
附件
下面你可以找到
Modelica模型用于从Dymola导出协同仿真FMU(使用CVode)
Python代码为py文件
python代码的输出散点图。
我还在JModelica论坛上发了帖子,你可以直接下载文件(FMU,Jupyter笔记本等): http://www.jmodelica.org/27925
Modelica模型
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
行似乎正常工作load_fmu
,有时候也是如此
崩溃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循环中(但速度较慢)load_fmu
命令model.reset()
或model.instatiate()
命令
for-loop(与Dymola FMU相反) - >为什么?? 我的问题:
执行循环的原因是什么,它使用不同的参数多次模拟FMU模型?
使用model.reset()
,model.instatiate()
或其中之一有什么区别?
附件
这是一个图表,显示了for循环与model.reset()
之间的区别。
从JModelica导出的FMU(不需要任何许可证)可以在此处下载:http://www.jmodelica.org/27925#comment-6668
答案 0 :(得分:4)
Dymola FMU的正确方式(可能与其他供应商的FMU相同)将在for循环之外调用fmi / fmi2Instantiate。如果在没有二进制导出许可证的情况下导出FMU,这些功能将分配内存并执行许可证检查。通过调用fmiResetSlave / fmi2Reset,您可以将FMU重置为实例化状态,而无需新的内存分配。
fmiInstantiateSlave / fmi2Instantiate
创建一个可用于模拟的FMU实例,多个调用将创建多个实例,每个实例都需要新内存分配和正确删除。
fmiReset
在实例化之后和调用fmiInitializeSlave / fmi2Intialize之前将实例重置为状态。这个更快,不需要新的动态内存分配,应该在你的情况下使用。
此外,在调用fmiFreeSalveInstance / fmi2FreeInstance时,在没有二进制导出的情况下导出的Dymola FMU的许可检查可能会泄漏旧Dymola版本中的内存。这在大多数情况下不是问题,因为您通常在终止FMU时终止程序。通过在for循环中实例化你的FMU,这变得严重,你的记忆将最终结束。 如果您联系Dymola支持,则应提供修订包。
答案 1 :(得分:1)
对我来说,这看起来像是一个记忆问题。您可以在Win任务管理器中运行期间观察分配的内存吗? 顺便说一下,你的FMU(来自你的邮件)需要一个DYMOLA_RUNTIME_LICENSE,它只能将复制限制为Dymola用户。