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

时间:2019-01-31 16:30:39

标签: modelica

我有一个模型,其中某些参数是其他参数的函数,可以。特殊之处在于要使用的公式取决于选择(另一个参数)。 即我有一个管道组件,并从一些参数(直径,节距和管道数)开始,我想表征外部流量(液压直径,...)。但是“字符”取决于装配体的形状(在我的情况下为三角形或正方形)。 下面是一个代码示例:

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";

我知道我可以通过以下“内联”语句逐个参数地完成此操作:

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块(如示例中所示)。但是,语法错误,我不明白为什么。 我也可以使用可补充组件,但是我认为应该存在更简单的方法(使用'if')...

2 个答案:

答案 0 :(得分:3)

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分支的最后两个语句应该相同,则它们可以在结束后移动。您可能还会在函数调用中使用命名参数-以减少出错的风险。

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

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

答案 1 :(得分:0)

您也可以这样做:

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; 

每个参数的整行会很长。