Search code examples
modelicadymolaopenmodelicajmodelica

Repeated components with pattern dependent parameters


Imagine there is a repeating pattern of components (e.g., dynamic pipe) which has a parameter (e.g., length) which will change depending on where in the pattern it resides. I proposed that it might be possible by omitting the "each" prefix before the parameter of interest.

For example. Lets take a n pipes and add them to the model in the following way:

parameter Integer n;
Modelica.Fluid.Pipes.DynamicPipe[n] pipe;

For a very simple example lets specify that we want the length of the 1st pipe in the pattern to have some length (length_1) and all others to have length_n. My thought is that it may be possible to put an if statement when defining the parameter in the following way such that length_1 is assigned to the n=1 pipe component and all others get assigned length_n:

parameter Integer n;
Modelica.Fluid.Pipes.DynamicPipe[n] pipe(
length=if n<2 then length_1 else cat(1,length_1,fill(length_n,n-1)));

A simple model in the framework mentioned is presented below:

model Test

  parameter Integer n(min=1);
  parameter Modelica.SIunits.Length length_1 = 0.1;
  parameter Modelica.SIunits.Length length_n = 0.2;

  Modelica.Fluid.Pipes.DynamicPipe[n] pipe(
    redeclare each package Medium = Modelica.Media.Water.StandardWater,
    each modelStructure=Modelica.Fluid.Types.ModelStructure.av_b,
    each diameter=1,
    length=if n==1 then length_1 else cat(1,length_1,fill(length_n,n-1)));

  Modelica.Fluid.Sources.Boundary_pT boundary(
    nPorts=1,
    redeclare package Medium = Modelica.Media.Water.StandardWater,
    p=100000,
    T=293.15);

  Modelica.Fluid.Sources.MassFlowSource_T boundary1(
    nPorts=1,
    redeclare package Medium = Modelica.Media.Water.StandardWater,
    m_flow=1,
    T=293.15);

  inner Modelica.Fluid.System system(m_flow_start=1, T_start=293.15);

equation 
if n == 1 then
  connect(boundary1.ports[1], pipe[1].port_a);
  connect(boundary.ports[1], pipe[1].port_b);

else

  connect(boundary1.ports[1], pipe[1].port_a);
  for i in 1:n-1 loop
    connect(pipe[i].port_b, pipe[i+1].port_a);
  end for;

  connect(boundary.ports[1], pipe[n].port_b);
end if;

end Test;

As it stands the model does not work. I am not sure if the way in which the if statement is constructed is in error or if this is simply not allowable (which may be the case if my interpretation of the "each" prefix is in error).

Any thoughts?


Solution

  • First of all thanks to matth for pointing me towards the pendulum example from Mike Tiller's book.

    Below, are two possible ways of modifying the code to achieve a repeated component pattern where the parameters change in some predetermined fashion. The error was associated with how the array for length was being defined.

    Option #1:

    Replaced

    length=if n==1 then length_1 else cat(1,length_1,fill(length_n,n-1))
    

    with

    length={if i==1 then length_1 else length_n for i in 1:n}
    

    Option #2:

    Inserted

    final parameter Modelica.SIunits.Length[n] 
                    lengths_pipe = {if i==1 then length_1 else length_n for i in 1:n};
    

    and replaced

    ... length=lengths_pipe 
    

    Below is the complete working code using the second option:

    model Test
    
      parameter Integer n(min=1)=2;
      parameter Modelica.SIunits.Length length_1 = 0.1;
      parameter Modelica.SIunits.Length length_n = 0.2;
    
      final parameter Modelica.SIunits.Length[n] lengths_pipe = {if i==1 then length_1 else length_n for i in 1:n};
    
      Modelica.Fluid.Pipes.DynamicPipe[n] pipe(
        redeclare each package Medium = Modelica.Media.Water.StandardWater,
        each modelStructure=Modelica.Fluid.Types.ModelStructure.av_b,
        each diameter=1,
        length=lengths_pipe);
    
      Modelica.Fluid.Sources.Boundary_pT boundary(
        nPorts=1,
        redeclare package Medium = Modelica.Media.Water.StandardWater,
        p=100000,
        T=293.15);
    
      Modelica.Fluid.Sources.MassFlowSource_T boundary1(
        nPorts=1,
        redeclare package Medium = Modelica.Media.Water.StandardWater,
        m_flow=1,
        T=293.15);
    
      inner Modelica.Fluid.System system(m_flow_start=1, T_start=293.15);
    
    equation 
    if n == 1 then
      connect(boundary1.ports[1], pipe[1].port_a);
      connect(boundary.ports[1], pipe[1].port_b);
    
    else
    
      connect(boundary1.ports[1], pipe[1].port_a);
      for i in 1:n-1 loop
        connect(pipe[i].port_b, pipe[i+1].port_a);
      end for;
    
      connect(boundary.ports[1], pipe[n].port_b);
    end if;
    
      annotation (uses(Modelica(version="3.2.1")));
    end Test;