Search code examples
modelica

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


I have a model where some parameters are functions of other parameters, which is OK. The particularity is that the formula to be used depend on a choice (another parameter). I.e. I have a pipes assembly and starting from some parameters (diameter, pitch and number of pipes), I want to characterise the external flow (hydraulic-diameter, ...). But the "character" depends on the assembly shape (triangular or square in my case). Here follows a code example:

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

I know I could do it parameter by parameter with an "inline" statement as follows:

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

Since it is always the same condition, I would like to use a single if block (like in the example). However, the syntax is wrong and I do not understand why. I could also use repleaceble components, but I think that simpler approach (use of 'if') should exist...


Solution

  • If-statements can only occur in algorithms (and equation sections). There are conditional declarations - but they are so restricted that they cannot be used for this.

    However, you can do it in another way, by having the computations in a function - and returning a parameter record.

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

    Assuming the two last statements of the if/else-branches should the same they could be moved after the end. You might also used named parameters for the function call - to reduce the risk of errors.

    The downside is that the names are slightly longer, and that you have to manually order the statements in the function due to dependencies.

    I would personally also change pattern to an enumeration.