参数定义部分是否可以有一个 if 块(不仅仅是语句)?

Is it possible to have an if block (not just a statement) in the parameters definition section?

我有一个模型,其中一些参数是其他参数的函数,这没问题。特殊之处在于要使用的公式取决于选择(另一个参数)。 IE。我有一个管道组件,从一些参数(直径、间距和管道数量)开始,我想表征外部流量(水力直径,...)。但是 "character" 取决于装配形状(在我的例子中是三角形或正方形)。 下面是一个代码示例:

parameter Modelica.SIunits.Diameter Dext=0.11 "Pipe external diameter";
parameter Integer Ntubes=1 "Number of pipes in parallel";
parameter Real P2D=1.3 "Pitch to diameter ratio";

parameter String pattern="square" "Pipes pattern" annotation(choices(choice="square",choice="triangle"));

if pattern=="square" then
  parameter Modelica.SIunits.Area Asub = Dext^2 * (P2D^2 - Modelica.Constants.pi/4) "Subchannel Cross Section Area";
  parameter Integer NtE = integer((Ntubes * Modelica.Constants.pi * Dext^2 / (4 * Asub)) + 0.5) "Number of pipes for same cross area";
  parameter Real hcCorr = Dext*Ntubes/(Dh*NtE) "Heat Exchange Correction";
elseif pattern=="triangle" then
  parameter Modelica.SIunits.Area Asub = Dext^2 * ((P2D^2 * sqrt(3)) - Modelica.Constants.pi/2)/2 "Subchannel Cross Section Area"; //2 (6/3rd) triangles for each pipe
  parameter Integer NtE = integer((Ntubes * Modelica.Constants.pi * Dext^2 / (4 * Asub)) + 0.5) "Number of pipes for same cross area";
  parameter Real hcCorr = Dext*Ntubes/(Dh*NtE) "Heat Exchange Correction";
end if;
parameter Modelica.SIunits.Diameter Dh = sqrt(Asub*Ntubes*4/(Modelica.Constants.pi*NtE)) "hydraulic diameter of external area";

我知道我可以使用如下 "inline" 语句逐个参数地执行此操作:

parameter Modelica.SIunits.Area Asub = if pattern=="square" then Dext^2 * (P2D^2 - Modelica.Constants.pi/4) elseif pattern=="triangle" then Dext^2 * ((P2D^2 * sqrt(3)) - Modelica.Constants.pi/2)/2 else 0 "Subchannel Cross Section Area";

因为它始终是相同的条件,所以我想使用单个 if 块(如示例中所示)。但是,语法错误,我不明白为什么。 我也可以使用 repleaceble 组件,但我认为应该存在更简单的方法(使用 'if')...

If 语句只能出现在算法(和方程部分)中。 有条件声明 - 但它们非常受限制,不能用于此目的。

但是,您可以通过另一种方式来实现,即在函数中进行计算并返回参数记录。

  record Geo
    Modelica.SIunits.Area Asub;
    Integer NtE;
    Real hcCorr;
    Modelica.SIunits.Diameter Dh;
  end Geo;

  function computeGeo
    input String pattern;
    input Modelica.SIunits.Diameter Dext;
    input Integer Ntubes;
    input Real P2D;
    output Geo geo;
  algorithm 
    if pattern=="square" then
      geo.Asub :=Dext^2*(P2D^2 - Modelica.Constants.pi/4)   "Subchannel Cross Section Area";
      geo.NtE :=integer((Ntubes*Modelica.Constants.pi*Dext^2/(4*geo.Asub)) + 0.5)         "Number of pipes for same cross area";
      geo.Dh :=sqrt(geo.Asub*Ntubes*4/(Modelica.Constants.pi*geo.NtE));
      geo.hcCorr :=Dext*Ntubes/(geo.Dh*geo.NtE) "Heat Exchange Correction";
    elseif pattern == "triangle" then
      geo.Asub :=Dext^2*((P2D^2*sqrt(3)) - Modelica.Constants.pi/2)/2     "Subchannel Cross Section Area"; //2 (6/3rd) triangles for each pipe
      geo.NtE :=integer((Ntubes*Modelica.Constants.pi*Dext^2/(4*geo.Asub)) + 0.5)         "Number of pipes for same cross area";
      geo.Dh := sqrt(geo.Asub*Ntubes*4/(Modelica.Constants.pi*geo.NtE));
      geo.hcCorr :=Dext*Ntubes/(geo.Dh*geo.NtE) "Heat Exchange Correction";
    end if;
  end computeGeo;

  parameter Modelica.SIunits.Diameter Dext=0.11 "Pipe external diameter";
  parameter Integer Ntubes=1 "Number of pipes in parallel";
  parameter Real P2D=1.3 "Pitch to diameter ratio";

  parameter String pattern="square" "Pipes pattern" annotation(choices(choice="square",choice="triangle"));
  parameter Geo geo=computeGeo(pattern, Dext, Ntubes, P2D);

假设 if/else-branches 的最后两个语句应该相同,它们可以在结束后移动。您还可以为函数调用使用命名参数 - 以减少出错的风险。

缺点是名称稍长,并且由于依赖关系,您必须手动对函数中的语句进行排序。

我个人也会将模式更改为枚举。

您还可以:

parameter Boolean bool = true;
parameter Real x = if bool then 1 else 0;

以你的例子给Asub:

parameter Modelica.SIunits.Area Asub = if pattern=="square" then EXPR1 elseif pattern=="triangle" then EXPR2 else EXPR3; 

每个参数的整行会变得相当长。