【问题标题】:OpenModelica - I am trying to run a book example but having inner-outer issuesOpenModelica - 我正在尝试运行一个书籍示例,但存在内部问题
【发布时间】:2013-11-19 09:58:29
【问题描述】:

我正在运行 OpenModelica 并尝试运行 Modelica 物理建模简介中的示例。我已将示例 9.1 - 9.4 复制到一个包中。该文件现在看起来像这样:

    package gravityPackage
  //Test of gravity taken from Intro to Physical modeling with Modelica
  //
  //
  //
  //
  //
  model ParticleField
    inner function gravity = TwoBodyField;
    Particle p1(x_init = {2,-2,0}, v_init = {0.7,0,0});
    Particle p2(x_init = {0,0.5,0}, v_init = {-1,-1,0});
    Particle p3(x_init = {0.5,2,0}, v_init = {-1,-0.5,0});
  end ParticleField;
  function TwoBodyField
    extends GravityField;
  protected
    Modelica.SIunits.Position b1[3],b2[3];
    Modelica.SIunits.Velocity n1[3],n2[3];
  algorithm
    b1:={0,0,0};
    b2:={0,1,0};
    n1:=-(x - b1) / sqrt((x - b1) * (x - b1));
    n2:=-(x - b2) / sqrt((x - b2) * (x - b2));
    g:=n1 / ((x - b1) * (x - b1)) + n2 / ((x - b2) * (x - b2));
  end TwoBodyField;
  partial function GravityField
    input Modelica.SIunits.Position x[3];
    output Modelica.SIunits.Acceleration g[3];
  end GravityField;
  model Particle
    parameter Modelica.SIunits.Position x_init[3];
    parameter Modelica.SIunits.Velocity v_init[3];
  protected
    outer function gravity = GravityField;
    //outer function gravity=ParticleField;
    //outer function gravity=TwoBodyField;
    Modelica.SIunits.Position x[3](start = x_init);
    Modelica.SIunits.Velocity v[3](start = v_init);
    Modelica.SIunits.Acceleration a[3];
  equation
    v = der(x);
    a = der(v);
    a = gravity(x);
  end Particle;
end gravityPackage;

但是,如果我去 OMShell 并尝试运行它,我会得到:

    >> loadFile("gravityPackage.mo")
true


>> simulate(gravityPackage.ParticleField) 
record SimulationResult
    resultFile = "",
    simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 0.000001, method = 'dassl', fileNamePrefix = 'gravityPackage.ParticleField', options = '', outputFormat = 'mat', variableFilter = '.*', measureTime = false, cflags = '', simflags = ''",
    messages = "Simulation failed for model: gravityPackage.ParticleField
[gravityPackage.mo:34:11-34:42:writable] Warning: No corresponding 'inner' declaration found for class gravity declared as 'outer '.
 Continuing flattening by only considering the 'outer' class declaration.
[gravityPackage.mo:43:5-43:19:writable] Error: Failed to instantiate equation 
a = gravity(x);.
Error: Error occurred while flattening model gravityPackage.ParticleField
",
    timeFrontend = 0.0,
    timeBackend = 0.0,
    timeSimCode = 0.0,
    timeTemplates = 0.0,
    timeCompile = 0.0,
    timeSimulation = 0.0,
    timeTotal = 0.0
end SimulationResult;

>> 

所以,很明显,我没有得到正确的范围。所有的代码,除了包,都是直接从书中复制过来的。我相信该软件包对于将其放入单个文件中是必要的(尽管我尝试了其他一些方法但没有成功)。 任何建议表示赞赏。

谢谢,

【问题讨论】:

  • 嗨@Adam,我想开始学习modellica,你所说的这本书是否可以作为电子书免费提供?
  • OpenModelica 的新前端现已修复此问题,请参阅 ticket

标签: simulation modeling modelica


【解决方案1】:

这是 OpenModelica 中的一个错误。 如果是内部组件或类,它应该可以正常工作,但不能用于函数。

我添加了一个关于它的错误报告,我们将修复它: https://trac.openmodelica.org/OpenModelica/ticket/2467

现在您可以使用内部/外部包,应该可以正常工作。

package gravityPackage

package Functions
  function TwoBodyField
    extends GravityField;
  protected
    Modelica.SIunits.Position b1[3],b2[3];
    Modelica.SIunits.Velocity n1[3],n2[3];
  algorithm
    b1:={0,0,0};
    b2:={0,1,0};
    n1:=-(x - b1) / sqrt((x - b1) * (x - b1));
    n2:=-(x - b2) / sqrt((x - b2) * (x - b2));
    g:=n1 / ((x - b1) * (x - b1)) + n2 / ((x - b2) * (x - b2));
  end TwoBodyField;

  partial function GravityField
    input Modelica.SIunits.Position x[3];
    output Modelica.SIunits.Acceleration g[3];
  end GravityField;

end Functions;

model ParticleField
    inner package funcs = Functions;
    Particle p1(x_init = {2,-2,0}, v_init = {0.7,0,0});
    Particle p2(x_init = {0,0.5,0}, v_init = {-1,-1,0});
    Particle p3(x_init = {0.5,2,0}, v_init = {-1,-0.5,0});
  end ParticleField;

  model Particle
    parameter Modelica.SIunits.Position x_init[3];
    parameter Modelica.SIunits.Velocity v_init[3];
  protected
    outer package funcs = Functions;
    function gravity = funcs.TwoBodyField;
    //outer function gravity=ParticleField;
    //outer function gravity=TwoBodyField;
    Modelica.SIunits.Position x[3](start = x_init);
    Modelica.SIunits.Velocity v[3](start = v_init);
    Modelica.SIunits.Acceleration a[3];
  equation
    v = der(x);
    a = der(v);
    a = gravity(x);
  end Particle;

end gravityPackage;

【讨论】:

    【解决方案2】:

    好的,所以我认为这里的问题是您正在尝试使用动态范围(即innerouter)将函数“传递”到实例树上。我还没有阅读关于这一点的规范,但我认为这不会奏效。原因是innerouter 通常与被实例化的事物(变量、模型等)结合使用。

    所以要理解的是,概念上constant 变量和function 定义都没有实例化。能够将function 视为实例(一等值)有几个有用的结果,但它也引入了一些语义上的复杂性。在该语言的最新版本中已经完成了尝试将函数视为一等公民的工作。主要用例是将函数作为参数传递给其他函数。但我认为这些新语义无法使函数真正成为一流的值(如您的示例所示)。但是,这可能是 OpenModelica 的问题。我不能肯定地说。

    您可以解决此问题的一种方法是使用可替换和重新声明。所以在你的Particle 模型中,像这样定义gravity

    public
      replaceable function gravity = GravityField;
    

    然后,实例化如下:

    model ParticleField
      Particle p1(x_init = {2,-2,0}, v_init = {0.7,0,0}, redeclare function gravity = TwoBodyField);
      Particle p2(x_init = {0,0.5,0}, v_init = {-1,-1,0}, redeclare function gravity = TwoBodyField);
      Particle p3(x_init = {0.5,2,0}, v_init = {-1,-0.5,0}, redeclare function gravity = TwoBodyField);
    end ParticleField;
    

    注意,我没有测试过这个解决方案。例如,您的Particle 模型可能需要partial 限定符(因为您必须将gravity 覆盖为非partial 实现)。

    希望对你有帮助。

    【讨论】:

    • Adrian 提出了另一种包。但是,我想添加一条额外的评论。就个人而言,我尽量避免内在和外在。使用重新声明更加灵活。例如,您可以选择为不同的粒子指定不同的功能。对于此示例,这可能没有意义,但在许多情况下确实如此。
    猜你喜欢
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多