3

我想将 Modelica 模型导出为 FMU 以使用 Dymola 2014 进行协同仿真。我计划使用 pyfmi 完成协同仿真。

为了测试这一点,我试图模拟通过两个流体边界之间的管道的流体流动。我希望将流体源的压力作为模型的输入。我的计划是在外部计算这个压力,并在每个时间步输入 Modelica 模型。

我的所有标准库组件的初始模型是:

model SE_BVP "BVP for stack exchange."
  inner Modelica.Fluid.System system;
  Modelica.Fluid.Pipes.StaticPipe pipe(
    redeclare package Medium = Modelica.Media.Air.MoistAir,
    length=1,
    diameter=1);
  Modelica.Fluid.Sources.Boundary_pT boundary1(nPorts=1, redeclare package
    Medium = Modelica.Media.Air.MoistAir);
  Modelica.Fluid.Sources.Boundary_pT boundary(nPorts=1, redeclare package Medium=
    Modelica.Media.Air.MoistAir, use_p_in=true);
  Modelica.Blocks.Interfaces.RealInput p_in1;

equation
   connect(pipe.port_b, boundary1.ports[1]);
   connect(boundary.ports[1], pipe.port_a);
   connect(boundary.p_in, p_in1);
end SE_BVP;

然后我将其包装在两个测试模型中:

model SE_BVP_test_1
 Real preVal = 101335;
 SE_BVP SE_BVP_1;

equation
 SE_BVP_1.p_in1 = preVal;

end SE_BVP_test_1; 

并使用参数类型,这是根据@Thierry 的建议完成的

model SE_BVP_test_2
  parameter Real preVal = 101335;
  SE_BVP SE_BVP_1;

equation
  SE_BVP_1.p_in1 = preVal;

end SE_BVP_test_2; 

运行这些模型给了我相同的结果:

没有变量类型。

带参数输入

两种模型都在 Dymola 中工作。

现在我希望加载 fmu 并使用 pyfmi 进行模拟,所以我编写了这个脚本:

  import pyfmi
  import numpy as np
  import pylab as P
  import os

  # Define the FMU to test
  fmuDirNam = "SE_BVP_Test_1"  # CS 2.0 type FMU
  fmuNam = fmuDirNam + ".fmu"

  # Define the input var
  inVar = "preVal"

  # Get the path to the FMU
  curr_dir = os.path.dirname(os.path.abspath(__file__))
  par_dir = os.path.dirname(curr_dir)
  path_to_fmu = os.path.join(par_dir, "projectFMUs", fmuDirNam)

  # Load the model
  model = pyfmi.load_fmu(os.path.join(path_to_fmu, fmuNam))

失败并给我以下错误:

FMIL: module = FMI2XML, log level = 2: XML element 
'Real': could not parse value for real attribute  
 'start'='pipMod.pipe.flowModel.states[1].p/(gasConstant_Unique7( 
      Modelica.Media.Air.MoistAir.ThermodynamicState(     
 p =

FMIL: module = FMI2XML, log level = 2: XML element 
'Real': could not parse value for   real attribute 
'start'='pipMod.pipe.flowModel.states[2].p/(gasConstant_Unique7(             
Modelica.Media.Air.MoistAir.ThermodynamicState(             
p =

FMIL: module = FMI2XML, log level = 2: XML element 
'Real': could not parse value for real attribute 
'start'='Modelica.Media.Incompressible.TableBased.Polynomials_Temp.evaluate({-4.96717436974791E-11, 5.06626785714286E-08, 1.72937731092437
FMIL: module = FMI2XML, log level = 2: XML element 'Real': could not parse value for real attribute 
'start'='Modelica.Media.Incompressible.TableBased.Polynomials_Temp.evaluate({-4.96717436974791E-11, 5.06626785714286E-08, 1.72937731092437

FMIL: module = FMI2XML, log level = 1: No model structure information available. 
Cannot continue.

FMIL: module = FMI2XML, log level = 1: Parse error at line 2703:
parsing aborted

从追溯:

pyfmi.fmi.FMUException: The XML-could not be read. Parse error at line 2703:
parsing aborted

鉴于模型在 Dymola 中正确模拟,什么可能导致此解析错误?

  • 我也尝试使用 CS 1.0 导出并引发相同的异常,尽管这次读取 fmu 的模块不同。

  • 我认为通过同时删除inputparameter标签会出现一些神秘的变量问题,但没有。即使使用 parameter标签,Test_2我也会引发相同的异常(CS 2.0)。

摘要:Dymola 2014、python 2.7.x、FMI for CO-simulation 2.0

4

5 回答 5

4

@RwardBound:如果您想在模拟期间更改参数,那么我会建议使用 FMI 2.0 而不是 FMI 1.0 FMU。FMI 2.0 支持此功能。例如,最新版本的 Dymola 能够生成此类 FMU。我认为 PyFMI 也支持 FMI 2.0。

一切顺利,蒂埃里

于 2014-08-14T17:10:01.467 回答
3

问题是由于 Dymola 生成的 XML 不正确。标量变量的起始属性必须是一个值,而不是表达式,这一切都符合规范。规范规定,对于真正的标量变量,起始值必须是浮点数,对于整数,起始值应该是 int,依此类推。FMI 1.0 和 FMI 2.0 也是如此(可以在https://fmi-standard.org/downloads阅读规范)。

为了根据标准验证您获得的 FMU 是否正确,有一个名为 Compliance Checker 的工具,也可以在上述站点上使用。如果您遇到这些类型的问题,这是一个很好的工具,可以排除导出工具是问题的原因。

使用 Dymola 2015,可以为模型 SE_BVP_test_1 正确生成 XML,并且可以使用 PyFMI 进行模拟。

于 2014-09-03T09:12:53.570 回答
1

问题在于选择的媒体模型。 Modelica.Media.Air.MoistAir是空气状态的压力和温度耦合模型。因此,流体密度、焓等的初始值是边界压力的函数。在导出到 FMU 期间,start管道内流体的状态变量值作为表达式写入 XML 文件:

<ScalarVariable
   name="SE_BVP_1.pipe.flowModel.rhos[1]"
   valueReference="100663348"
   variability="constant">
<Real
  unit="kg/m3"
  min="0.0"
   start="SE_BVP_1.pipe.flowModel.states[1].p/(gasConstant_Unique7(
     Modelica.Media.Air.MoistAir.ThermodynamicState(
       p = SE_BVP_1.pipe.flowModel.states[1].p,
       T = SE_BVP_1.pipe.flowModel.states[1].T,
       X = {SE_BVP_1.pipe.flowModel.states[1].X[1],
                       SE_BVP_1.pipe.flowModel.states[1].X[2]}
            ))*SE_BVP_1.pipe.flowModel.states[1].T)"/>

将流体更改为Buildings.Media.GasesPTDecoupled.MoistAirUnsaturated删除start值计算并且 XML 读取:

<ScalarVariable
   name="SE_BVP_1.pipe.flowModel.rhos[1]"
          valueReference="100663345"
   variability="fixed">
<Real
  unit="kg/m3"
  min="0.0"/>

pyfmi在解析期间不计算表达式,而是期望一个可以格式化为浮点数的字符串。

于 2014-08-20T08:48:38.733 回答
1

测试 Dymola 模型以便导出为 FMU(或 Modelica 库)的最佳实践是构建一个用于测试的顶级模型。然后,您可以构建专用于导出模型的仿真环境。

我们以一个简单的“除 10/u”模型为例:

model div10
  Modelica.Blocks.Math.Division division;
  Modelica.Blocks.Interfaces.RealInput u(start=10);
equation 
  division.u1 = 10;
  connect(division.u2, u);
end div10;

然后你必须创建这个顶级模型来测试你的div10模型:

   model div10_tester  
      parameter Real default_u = 2.0;
      div10 div10_1;
    equation 
      div10_1.u = default_u;
    end div10_tester;

另一种解决方案可能是使用“dsu.txt”(注意:如果您单独模拟 div10,则 start=10 语句将无效,正如您的错误日志中提到的那样:如果没有“dsu.txt”文件 => 所有输入设置为 0)。但这是非常有限的,因为它只指定了起始值。

于 2014-08-14T12:03:20.443 回答
1

在初始化时解决 input=0 的一种简单方法可能是添加一个 max() 块来将您的输入与一些非​​常小的数字进行比较。

例如:

input = max(a very small positive number, input) if your input is always greater than zero. 

如果您的参数(输入)会切换符号,我相信您足够聪明,可以找到类似的方法来做到这一点。

于 2014-08-14T18:31:37.897 回答