将模型实例化为参数时的固定属性

Fixed attribute when instantiating a model as parameter

我想将一个复杂模型实例化为另一个模型中的参数,并在初始方程部分对其进行初始化,就像我能够对任何 Real 参数所做的那样。对于一个简单的 Real 参数,我只写

parameter Real y(fixed = true);

表示y应该在初始化时使用初始方程(待定义...)计算。但是对于复杂的模型我不能这样做,即

parameter ComplexModel m(fixed = true);

不编译。例如考虑以下平面模型

model FlatModel
  parameter Real x = 4;
  parameter Real y(fixed = false);
  Real z;
  // ... + many other model elements
initial equation
  y*y = x;
  // ... + many other equations
equation
  z*z = 4*x;
end FlatModel;

此处隐式解 y=2 是在初始化时计算的,而解 z=4 是以时间相关的方式计算的(至少在原则上,尽管有可能的优化......)。但是两者代表的是基本相同的二次关系,所以我想把这个方程封装成一个单独的模型(注意不是每个这样的方程组都像这个例子一样简单):

model ComplexModel 
  Real x(fixed = false);
  Real y(fixed = false);
equation
  y * y = x;
end ComplexModel;

并尝试这样使用它:

  model RefactoredFlatModel
    parameter Real x = 4;
    parameter Real y(fixed = false);
    Real z;
    parameter ComplexModel mStatic;
    ComplexModel mDynamic;
  initial equation
    mStatic.x = x;
    y = mStatic.y;
  equation
    mDynamic.x = 4*x;
    z = mDynamic.y;
  end RefactoredFlatModel;

但这似乎不起作用(编译器报告系统过度确定)。检查编译器展平的模型显示原因:

class FixedTests.RefactoredFlatModel
  parameter Real x = 4.0;
  parameter Real y(fixed = false);
  Real z;
  parameter Real mStatic.x(fixed = false);
  parameter Real mStatic.y(fixed = false);
  Real mDynamic.x(fixed = false);
  Real mDynamic.y(fixed = false);
initial equation
  mStatic.x = x;
  y = mStatic.y;
equation
  mStatic.y ^ 2.0 = mStatic.x;
  mDynamic.y ^ 2.0 = mDynamic.x;
  mDynamic.x = 4.0 * x;
  z = mDynamic.y;
end FixedTests.RefactoredFlatModel;

所以 mStatic.y ^ 2.0 = mStatic.x 被放到(时间相关的)方程部分而不是我想要的初始方程部分。很明显,该模型是超定的,因为它试图及时求解 mStatic.y,尽管 mStatic.y 是一个参数,因此是时不变的。

有没有办法告诉modelica编译器将方程式变成参数实例的初始方程式?因为否则无法隐式定义复杂模型的参数实例。

编辑 (2019-02-30): 不要使用这个 'solution'。根据 tbeu 的回答,它违反了语言标准。 OpenModelica 允许,但不应该。


我终于找到了部分解决方案。如果我通过在 initial equationequation 部分中使用条件来声明 ComplexModel,我可以让它工作 - 不知何故。

model ComplexModel
  parameter Boolean fixed = true;
  Real x(fixed = false);
  Real y(fixed = false);
initial equation
  if not fixed then
    y * y = x;
  end if;
equation
  if fixed then
    y * y = x;
  end if;
end ComplexModel;

通过在模型 RefactoredFlatModel 中替换(来自问题)行

parameter ComplexModel mStatic;

来自

parameter ComplexModel mStatic (fixed = false);

生成的平面模型最终变成了

class AdvancedMultiBody.FixedTests.RefactoredFlatModel
  parameter Real x = 4.0;
  parameter Real y(fixed = false);
  Real z;
  parameter Boolean mStatic.fixed = false;
  parameter Real mStatic.x(fixed = false);
  parameter Real mStatic.y(fixed = false);
  parameter Boolean mDynamic.fixed = true;
  Real mDynamic.x(fixed = false);
  Real mDynamic.y(fixed = false);
initial equation
  mStatic.y ^ 2.0 = mStatic.x;
  mStatic.x = x;
  y = mStatic.y;
equation
  mDynamic.y ^ 2.0 = mDynamic.x;
  mDynamic.x = 4.0 * x;
  z = mDynamic.y;
end AdvancedMultiBody.FixedTests.RefactoredFlatModel;

即我已经以一种可以从外部控制的方式成功地将 mStatic.y 的等式转换为 initial equation 部分。好消息是 ComplexModel 现在已完全封装,并且可以根据我的问题的要求分配 'attribute' fixed = false。

糟糕的是我必须在 ComplexModel 中写两次基本方程 y*y=x。在更复杂的方程系统的情况下,这可能是错误的来源。并且:我认为如果有人为 ComplexModel 的非参数实例编写 fixed=false 语法可能会被滥用(导致时间相关方程消失,这与 fixed=false 对原子数据类型的含义完全不同)。

我多么希望有一种语言功能可以自动且一致地执行所有这些操作,但似乎没有。

从 Modelica 规范 v3.4 开始,这是无效的 Modelica,因为前缀 parameter 不能与专门的 class model.

一起使用

有一些建议可以改进此行为(并满足您的要求),请参阅 https://github.com/modelica/ModelicaSpecification/issues/2311 and its source https://github.com/modelica/ModelicaStandardLibrary/issues/1860

您在问题中建议的代码几乎可以工作。您只需要省略 mStatic 的参数前缀并在常规方程部分分配其变量即可。

model RefactoredFlatModel
  parameter Real x=4;
  parameter Real y(fixed=false);
  Real z;
  ComplexModel mStatic;
  ComplexModel mDynamic;
initial equation 
  y = mStatic.y;
equation 
  // The assignment is needed to have enough equations, even though its static
  mStatic.x = x;

  mDynamic.x = 4*x;
  z = mDynamic.y;
end RefactoredFlatModel;

参数也可以从常规变量分配到初始方程部分。所以你不需要模型 mStatic 的参数前缀。 但是mStatic的方程也必须定义在连续时间段,因此我们必须将方程mStatic.x = x移动到方程部分