参数定义部分是否可以有一个 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;
每个参数的整行会变得相当长。
我有一个模型,其中一些参数是其他参数的函数,这没问题。特殊之处在于要使用的公式取决于选择(另一个参数)。 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;
每个参数的整行会变得相当长。