如何通过 OMPython 在重新声明语句中修改组件的值

How to modify a component's value within a redeclare statement via OMPython

我需要能够通过 Python 修改 Modelica package/model 的内容,以进行自动模拟等。大多数情况下这与 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 中,我们有一个 "System",其中包含一个 "Component",而 "Component" 又包含一个可替换的 "sensor"。 使用 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。

但是,我不知道如何更改重新声明的传感器的 "sensitivity"。天真的方法是 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;

最后,正题: 如何通过将 "sensitivity" 更改为 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;

此致,非常感谢!

根据 openmodelica.org 的反馈,我意识到 OpenModelica 目前 (1.14.1) 并不完全支持那些重新声明的语句。因此,想要的结果显然还不可能。似乎计划在 1.16.0.

看到一个question on openmodelica.org and the roadmap for future reference. Also this might be the correct ticket to track.

编辑:

对于 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;