Is there any other elegant way to redeclare both type AND values in nested modelica models

145 Views Asked by At

I have a set of nested models and sub-models, as well as records. Here is the simple example:

package Unnamed1
  record A
    Real a;
  end A;

  record B
    extends A;
    Real b;
  end B;

  record C
    extends B;
    Real c;
  end C;

  model M
    replaceable record Data = A;
    parameter Data data;
  end M;

  model H
    replaceable record Data = A;
    parameter Data data;
    protected
    M m(redeclare replaceable record Data = Data, data=data);
  end H;

  model R
    parameter B bb(b=5, a=2.0);
    parameter A aa(a=4.0);
    parameter C cc(a=0.0, b=0.2, c=0.8);
    H h(redeclare record Data = B, data=bb);
    H g(redeclare record Data = A, data = aa);
    H f(redeclare record Data = C, data = cc);
  end R;
end Unnamed1;

They are 3 sets of nested records (A, B, C), and 3 nested models (R, H, M). I want to pass an instance of a record from R to M through H, with instances having different types. That way of doing I found sounds heavy, passing both type of record AND its content through a different variable. When I have 2 levels, no problem, I can use redeclare that is fine. When I have more than two levels of nested classes (let say 5), I don't know how to pass both Type and instance at the same time. Note, in H, m is protected. Any though on doing in a different way ?

2

There are 2 best solutions below

0
On

One solution I found is by passing a record encapsulating an instance of record (called component in Modelica terminology). The new code is:

package Unnamed1
  record A
    Real a=0.0; // value for Dymola... don't know why yet
  end A;

  record B
    extends A;
    Real b;
  end B;

  record C
    extends B;
    Real c;
  end C;

  model M
    replaceable record Data = A;
    Data data;
  end M;

  model H
    replaceable record Data = A;
    M m(redeclare record Data = Data);
  end H;

  model R
    record AA
        extends A(a=5);
    end AA;

    record BB
        extends B(b=5, a=2.0);
    end BB;

    record CC
      extends C(a=0.0, b=0.2, c=0.8);
    end CC;

    H f(redeclare record Data = AA);
    H g(redeclare record Data = BB);
    H h(redeclare record Data = CC);
  end R;
end Unnamed1;

The main difference being instead of passing a component B parameter B bb(b=5, a=2.0); to the various sub-models, one passes a record BB containing values of B

record BB
    extends B(b=5, a=2.0);
end BB;

One then have to redeclare the record in the sub-classe definition, which can be repetated again and again.

Dummy values have to defined in the base record A, let say a=0.0 for Dymola to accept the code, while OpenModelica and SimulationX does not need it.

0
On

I want to present a slight variation of the other answer and then explain how it is often solved.

The variation is that you can modify value and class in the redeclare without having explicit record declarations.

package Unnamed1
  record A
    parameter Real a;
  end A;

  record B
    extends A;
    parameter Real b;
  end B;

  record C
    extends B;
    parameter Real c;
  end C;

  model M
    replaceable record Data = A;
    parameter Data data;
  end M;

  model H
    replaceable record Data = A;
  protected 
    M m(redeclare replaceable record Data = Data);
  end H;

  model R
    H h(redeclare record Data = B(b=5,a=2.0));
    H g(redeclare record Data = A(a=4.0));
    H f(redeclare record Data = C(a=0, b=0.2, c=0.8));
  end R;
end Unnamed1;

However, when looking inside H we see that even if the model is legal the new parameters cannot be used. Thus a more normal case is that it is a model with some parameters in it leading to:

package Unnamed2
  partial model SO
    output Real y;
  end SO;

  model Constant
    extends SO;
    parameter Real b;
  equation 
    y=b;
  end Constant;

  model Ramp
    extends SO;
    parameter Real b;
    parameter Real k;
  equation 
    y=b+time*k;
  end Ramp;

  model Other
    extends SO;
    parameter Real offset;
  equation 
    y=time+offset;
  end Other;

  model M
    replaceable model Source = SO;
    Source source;
  protected 
    Real x;
  equation 
    der(x)=source.y;
  end M;

  model H
    replaceable model Source = SO;
  protected 
    M m(redeclare replaceable model Source = Source);
  end H;

  model R
    H h(redeclare model Source = Constant(b=5));
    H g(redeclare model Source = Other(offset=4.0));
    H f(redeclare model Source = Ramp(b=0.2, k=0.8));
  end R;
end Unnamed2;