Modelica:如何使用可更换组件?

Modelica:如何使用可更换组件?,modelica,Modelica,我试图建立一个模型,可以使用两个不同的组件(取自现有的库)在同一范围内:特别是一个带有热交换器的系统;这种热交换器可以基于不同的技术,例如管道或板 然后我想定义一个带有默认可替换交换机的模型,并说明可以使用哪些其他技术 这是我尝试的一个非常简单的例子: package Test // Component 1 original definition in the library model COMP1 parameter Real p1=1 ""; Real v "";

我试图建立一个模型,可以使用两个不同的组件(取自现有的库)在同一范围内:特别是一个带有热交换器的系统;这种热交换器可以基于不同的技术,例如管道或板

然后我想定义一个带有默认可替换交换机的模型,并说明可以使用哪些其他技术

这是我尝试的一个非常简单的例子:

package Test

  // Component 1 original definition in the library
  model COMP1
    parameter Real p1=1 "";
    Real v "";
  equation 
    v=p1*time;
  end COMP1;

  // Component 2 original definition in the library
  model COMP2
    parameter Real p2=1 "";
    Real v "";
  equation 
    v=p2*time;
  end COMP2;

  // Main module (system)
  model MAIN
    parameter Real pm=100 "";
    Real vm "";

    // Redefinition of the component modifing the default values
    model call1 = COMP1(p1=10);
    model call2 = COMP2(p2=20);

    replaceable call1 OBJ
    annotation(choices(
            choice(redeclare call1 OBJ "Default"),
            choice(redeclare call2 OBJ "Variant")));

  equation 
    vm = OBJ.v+pm;
  end MAIN;

  // Application model, using the main model
  model APP
    MAIN mAIN;
  end APP;

end Test;
模型应用程序已成功运行。但是,如果我打开APP.mAIN的参数并更改OBJ(选择“Default”或“Variant”),这将导致修改APP模型,如下所示:

  model APP
    MAIN mAIN(redeclare call1 OBJ "Default");
  end APP;
model MAIN
  parameter Real pm=100 "";
  Real vm "";

  replaceable COMP1 OBJ
  annotation(choices(
          choice(redeclare Test.COMP1 OBJ(p1=10) "Default"),
          choice(redeclare Test.COMP2 OBJ(p2=10) "Variant")));
equation 
  vm = OBJ.v+pm;
end MAIN;
我得到以下错误:

Component type specifier call1 not found

我不明白我做错了什么,请帮助。

与错误相关的问题发生了,因为您没有在选项注释中使用正确的类路径

如果在
应用程序
中选择“默认”,则会得到以下代码:

model APP
  MAIN mAIN(redeclare call1 OBJ "Default");
end APP;
这里我们看到类路径
call1
无效。应用程序只能使用相对类路径
MAIN.call1
或绝对类路径
Test.MAIN.call1
访问
call1
。 因此,您可以使用以下注释解决此问题:

  replaceable call1 OBJ
  annotation(choices(
          choice(redeclare MAIN.call1 OBJ "Default"),
          choice(redeclare MAIN.call2 OBJ "Variant")));
然而,在Dymola中,显然由于
MAIN
中的本地类定义,在修改默认值的组件重新定义下,模型仍然没有检查。 在这里创建新类
call1
call2
。这可能是一个Dymola错误,因为它在OpenModelica中工作——但新类不是必需的。相反,您可以使用原始类并在
redeclare
语句中使用修饰符方程设置参数,如下所示:

  model APP
    MAIN mAIN(redeclare call1 OBJ "Default");
  end APP;
model MAIN
  parameter Real pm=100 "";
  Real vm "";

  replaceable COMP1 OBJ
  annotation(choices(
          choice(redeclare Test.COMP1 OBJ(p1=10) "Default"),
          choice(redeclare Test.COMP2 OBJ(p2=10) "Variant")));
equation 
  vm = OBJ.v+pm;
end MAIN;
现在该模型适用于无选择和“默认”,但当选择“Variant”时,Dymola抱怨重新声明的类不包含与原始类相同的变量。 这是使用可替换类时的限制之一(同样,OpenModelica对此没有问题,但Dymola警告您这不符合Modelica语言规范)

替代方法:带有接口的MSL样式 我建议像Modelica库通常那样创建接口模型(例如,使用
Modelica.Electrical.Analog.Interfaces.OnePort
):

  • 您可以创建一个
    部分
    基本模型,该模型包含所有变体的所有通用内容,称为接口
  • 这些变体扩展了接口和现有库的一个模型
  • 使用变量的类实例化其中一个变量,并使用constrainedby将重新声明约束到接口
  • 您现在可以使用注释choicesAllMatching自动创建选项注释,而不是手动创建选项注释
这就是您的示例的样子。第三方组件
COMP1
COMP2
被移动到包
ReadOnlyLibrary

package Test
  // Original definition of Component 1 and 2 in the external library
  package ReadOnlyLibrary
    model COMP1
      parameter Real p1=1 "";
      Real v "";
    equation 
      v=p1*time;
    end COMP1;

    model COMP2
      parameter Real p2=1 "";
      Real v "";
    equation 
      v=p2*time;
    end COMP2;
  end ReadOnlyLibrary;

  // Interface and variants with modified default values
  partial model Call_Interface
    Real v "";
  end Call_Interface;

  model Call1 "Default"
    extends Call_Interface;
    extends ReadOnlyLibrary.COMP1(p1=10);
  end Call1;

  model Call2 "Variant"
    extends Call_Interface;
    extends ReadOnlyLibrary.COMP2(p2=20);
  end Call2;

  // Main module (system)
  model Main
    parameter Real pm=100 "";
    Real vm "";

    replaceable Test.Call1 OBJ constrainedby Test.Call_Interface annotation (choicesAllMatching);

  equation 
    vm = OBJ.v+pm;
  end Main;

  // Application model, using the main model
  model App
    Main main annotation (Placement(transformation(extent={{-12,10},{8,30}})));
  end App;
end Test;

这很好,除了最后一个例子。我会在Call_接口中使用“Real v”,并且我不会将ReadOnlyLibrary.COMP1作为Call1中的子组件,而是直接将内容放在其中。我会将COMP1更改为从接口继承,因此不会有v的本地声明。但是,我同意,没有组件方法很难做到这一点,而且在Call1和使用choicesAllMatching中仍然有默认值。但也可以使用多重继承,即“ModelCall1扩展Call_接口;扩展ReadOnlyLibrary.COMP1(p1=10);EndCall1”;现在的例子是多重继承方法。但我没有更新COMP1,因为我假设现有库无法编辑。是的,这是必要的,因为否则Main的约束变量将不会检查。您可以使用checkModel(“Test.Main”,constraint=true)在Dymola中对此进行检查;实际上,有人可以根据Call_接口制作一个新的“Comp3”,但如果没有“Real v”,重新定义使用Comp3将无法翻译。