传值

在建立子系统模型时,子系统很经常会包含一些会传递到其自身部件的参数。例如,考虑我们在对基本旋转组件的讨论中使用的以下系统模型:

within ModelicaByExample.Components.Rotational.Examples;
model SMD
  Components.Damper damper2(d=1);
  Components.Ground ground;
  Components.Spring spring2(c=5);
  Components.Inertia inertia2(J=1,
    phi(fixed=true, start=1),
    w(fixed=true, start=0));
  Components.Damper damper1(d=0.2);
  Components.Spring spring1(c=11);
  Components.Inertia inertia1(
    J=0.4,
    phi(fixed=true, start=0),
    w(fixed=true, start=0));
equation
  // ...
end SMD;

有时候,我们会想在不同的上下文中使用这个模型,并改变一些部件参数的值,例如d。我们可以让d成为子系统级别的参数,然后利用修改语句将值通过层次结构传递。结果应是如此:

within ModelicaByExample.Components.Rotational.Examples;
model SMD
  import Modelica.SIunits.*;
  parameter RotationalDampingConstant d;
  Components.Damper damper2(d=d);
  // ...

这里有一个问题。用户可能会去下层改变damper2.d的值,而不在SMD模型修改d参数。要避免d参数和damper2.d参数的不同步(具有不同的值),我们可以使用final限定词将其永久绑定起来:

within ModelicaByExample.Components.Rotational.Examples;
model SMD
  import Modelica.SIunits.*;
  parameter RotationalDampingConstant d;
  Components.Damper damper2(final d=d);
  // ...

通过添加final限定词,我们表明参数damper2.d的值不可以再修改。任何修改必须指向d

用相同方式代替在SMD模型里所有在代码里固定的数值,如下模型会得到很高的可重用性:

within ModelicaByExample.Components.Rotational.Examples;
model SMD
  import Modelica.SIunits.*;

  parameter RotationalDampingConstant d1, d2;
  parameter RotationalSpringConstant c1, c2;
  parameter Inertia J1, J2;
  parameter Angle phi1_init=0, phi2_init=0;
  parameter AngularVelocity w1_init=0, w2_init=0;

  Components.Damper damper2(final d=d2);
  Components.Ground ground;
  Components.Spring spring2(final c=c2);
  Components.Inertia inertia2(
    final J=J2,
    phi(fixed=true, final start=phi2_init),
    w(fixed=true, final start=w2_init));
  Components.Damper damper1(final d=d1);
  Components.Spring spring1(final c=c1);
  Components.Inertia inertia1(
    final J=J1,
    phi(fixed=true, final start=phi1_init),
    w(fixed=true, final start=w1_init));
equation
  // ...
end SMD;

如果我们想用某组特定的参数值,有两种可行的方法。一种方法是扩展上述的参数化模型,并在extends声明包括修改语句,如:

model SpecificSMD
  extends SMD(d2=1, c2=5, J2=1,
              d1=0.5, c1=11, J1=0.4,
              phi1_init=1);

需要注意的是,我们并不需要为phi2_initw1_initw2_init添加修改语句,因为这些参数在声明都带有默认值。一般情况下,只有在参数的默认值适用于绝大部分情况时,才应该设定。这样做的原因在于如果参数没有默认值,大多数的Modelica编译器会生成警告,以提醒你必须进行赋值。但是,如果存在默认值,编译器会默默地使用默认值。如果默认值不合理或不典型,那么你会默默地在模型里引入一个不合理的值。

另一方面,我们回到关于传值的主题。另一个可用的方法将是实例化SMD模型,并在声明的变量使用修改语句去指定参数值,如:

SMD mysmd(d2=1, c2=5, J2=1,
          d1=0.5, c1=11, J1=0.4,
          phi1_init=1);

在下章架构模型之前,我们暂时不会讨论哪种方法更好。