首页 > 解决方案 > 如何通过 OMPython 在重新声明语句中修改组件的值

问题描述

我需要能够通过 Python 修改 Modelica 包/模型的内容,用于自动仿真等。大多数情况下,这适用于 OMPython,但有一个我无法解决的特殊问题:

考虑这两个文件:1)example.mo(一个Modelica包)

package Example "Example Package"
  model Component "A component with some settings"
    parameter Real value=100 "Some value";
    replaceable BasicSensor sensor "Replaceable sensor" annotation (
        Placement(transformation(extent={{-10,-10},{10,10}})),
        __Dymola_choicesAllMatching=true);
    annotation (Icon(graphics={Rectangle(extent={{-40,40},{40,-40}}, lineColor={28,
                108,200})}));
  end Component;

  model System "A system with a component"
    Component component(value=50, redeclare SpecialSensor sensor(sensitivity=10))
      "Modified component"
      annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
    annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
          coordinateSystem(preserveAspectRatio=false)));
  end System;

  model BasicSensor
    parameter Real sensitivity=1 "Some value";
    annotation (Icon(coordinateSystem(preserveAspectRatio=false), graphics={
            Ellipse(extent={{-40,40},{40,-40}}, lineColor={28,108,200})}),
        Diagram(coordinateSystem(preserveAspectRatio=false)));
  end BasicSensor;

  model SpecialSensor
    extends BasicSensor;
    annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
          coordinateSystem(preserveAspectRatio=false)));
  end SpecialSensor;
end Example;

2) test.py(一个 Python 脚本)

"""Python test script for replacing information in modelica models."""
from OMPython import OMCSessionZMQ
omc = OMCSessionZMQ()
cmds = [
    'loadFile("example.mo")',
    'setComponentModifierValue(Example.System, component.value, $Code(=200))',
    # 'setComponentModifierValue(Example.System, component.sensor.sensitivity, $Code(=20))',
    'saveModel("example_edit.mo", Example)',
    ]
for cmd in cmds:
    answer = omc.sendExpression(cmd)
    print(cmd, answer)

在 Modelica 中,我们有一个“系统”,其中包含一个“组件”,而该组件又包含一个可替换的“传感器”。使用 Python 脚本,我可以正确修改“component.value”。运行脚本会产生以下结果文件 example_edit.mo(仅显示有更改的部分):

model System "A system with a component"
    Component component(value = 200, redeclare SpecialSensor sensor(sensitivity = 10)) "Modified component" annotation(
      Placement(transformation(extent = {{-10, -10}, {10, 10}})));
    annotation(
      Icon(coordinateSystem(preserveAspectRatio = false)),
      Diagram(coordinateSystem(preserveAspectRatio = false)));
  end System;

根据需要,“component.value”已从 50 更改为 200。

但是,我不知道如何更改重新声明的传感器的“灵敏度”。天真的方法是 python 脚本中的注释行。如果我们包括那条线,被替换的传感器就会从生成的模型中消失

model System "A system with a component"
    Component component(value = 200) "Modified component" annotation(
      Placement(transformation(extent = {{-10, -10}, {10, 10}})));
    annotation(
      Icon(coordinateSystem(preserveAspectRatio = false)),
      Diagram(coordinateSystem(preserveAspectRatio = false)));
  end System;

最后,实际问题: 如何将“灵敏度”更改为 20 以达到以下预期结果?(通过 OMPython 界面,而不是使用正则表达式或类似的黑客。)

model System "A system with a component"
    Component component(value = 200, redeclare SpecialSensor sensor(sensitivity = 20)) "Modified component" annotation(
      Placement(transformation(extent = {{-10, -10}, {10, 10}})));
    annotation(
      Icon(coordinateSystem(preserveAspectRatio = false)),
      Diagram(coordinateSystem(preserveAspectRatio = false)));
  end System;

问候和非常感谢!

标签: pythonmodelicaopenmodelica

解决方案


通过 openmodelica.org 的反馈,我意识到 OpenModelica 当前(1.14.1)不完全支持这些重新声明语句。因此,想要的结果显然还不可能。它似乎计划用于 1.16.0。

请参阅openmodelica.org 上的问题路线图以供将来参考。这也可能是跟踪的正确票证

编辑:

使用 OpenModelica v1.17.0-dev-326-g94acb25482(64 位)的当前开发版本,以下 Python 代码允许设置重新声明语句并回答原始问题:

"""Python test script for replacing information in modelica models."""
from OMPython import OMCSessionZMQ
omc = OMCSessionZMQ()
cmds = [
    'loadFile("example.mo")',   
    'removeElementModifiers(Example.System, "component", false)',
    'setElementModifierValue(Example.System, component.sensor, $Code((redeclare SpecialSensor sensor(sensitivity = 20))))',
    'setElementModifierValue(Example.System, component.value, $Code(=200))',
    'saveModel("example_edit.mo", Example)',
    ]
for cmd in cmds:
    answer = omc.sendExpression(cmd)
    print(cmd, ':', answer)

这将创建所需的输出:

  model System "A system with a component"
    Component component(value = 200, redeclare SpecialSensor sensor(sensitivity = 20)) "Modified component" annotation(
      Placement(transformation(extent = {{-10, -10}, {10, 10}})));
    annotation(
      Icon(coordinateSystem(preserveAspectRatio = false)),
      Diagram(coordinateSystem(preserveAspectRatio = false)));
  end System;

但是,当前似乎removeElementModifiers()需要该命令,因为没有它...

"""Python test script for replacing information in modelica models."""
from OMPython import OMCSessionZMQ
omc = OMCSessionZMQ()
cmds = [
    'loadFile("example.mo")',   
    # 'removeElementModifiers(Example.System, "component", false)',
    'setElementModifierValue(Example.System, component.sensor, $Code((redeclare SpecialSensor sensor(sensitivity = 20))))',
    'setElementModifierValue(Example.System, component.value, $Code(=200))',
    'saveModel("example_edit.mo", Example)',
    ]
for cmd in cmds:
    answer = omc.sendExpression(cmd)
    print(cmd, ':', answer)

...redeclare SpecialSensor输出中缺少该部分:

  model System "A system with a component"
    Component component(value = 200) "Modified component" annotation(
      Placement(transformation(extent = {{-10, -10}, {10, 10}})));
    annotation(
      Icon(coordinateSystem(preserveAspectRatio = false)),
      Diagram(coordinateSystem(preserveAspectRatio = false)));
  end System;

推荐阅读