5

I want to instantiate a complex model as a parameter in another model and initialize it within the initial equation section, like I am able to do with any Real parameter. For a simple Real parameter I would just write

parameter Real y(fixed = true);

indicating that y should be computed at initialization time by using initial equations (to be defined...). But I can't do that for a complex model, i.e.

parameter ComplexModel m(fixed = true);

does not compile. Consider for example the following flat model

model FlatModel
  parameter Real x = 4;
  parameter Real y(fixed = false);
  Real z;
  // ... + many other model elements
initial equation
  y*y = x;
  // ... + many other equations
equation
  z*z = 4*x;
end FlatModel;

Here the implicit solution y=2 is computed at initialization time whereas the solution z=4 is computed in a time dependent manner (at least in principle, possible optimizations notwithstanding...). But both represent basically the same quadratic relationship, so I want to encapsulate this equation into a separate model (note that not every such equation system is as simple as in this example):

model ComplexModel 
  Real x(fixed = false);
  Real y(fixed = false);
equation
  y * y = x;
end ComplexModel;

and try to use it this way:

  model RefactoredFlatModel
    parameter Real x = 4;
    parameter Real y(fixed = false);
    Real z;
    parameter ComplexModel mStatic;
    ComplexModel mDynamic;
  initial equation
    mStatic.x = x;
    y = mStatic.y;
  equation
    mDynamic.x = 4*x;
    z = mDynamic.y;
  end RefactoredFlatModel;

But this doesn't seem to work (compiler reports overdertermined system). Checking the model flattened by the compiler shows why:

class FixedTests.RefactoredFlatModel
  parameter Real x = 4.0;
  parameter Real y(fixed = false);
  Real z;
  parameter Real mStatic.x(fixed = false);
  parameter Real mStatic.y(fixed = false);
  Real mDynamic.x(fixed = false);
  Real mDynamic.y(fixed = false);
initial equation
  mStatic.x = x;
  y = mStatic.y;
equation
  mStatic.y ^ 2.0 = mStatic.x;
  mDynamic.y ^ 2.0 = mDynamic.x;
  mDynamic.x = 4.0 * x;
  z = mDynamic.y;
end FixedTests.RefactoredFlatModel;

So mStatic.y ^ 2.0 = mStatic.x is put to the (time dependent) equation section instead of the initial equation section, where I wanted it to be. It is clear that the model is overdetermined because it tries to solve for mStatic.y in time although mStatic.y is a parameter and thus is time invariant.

Is there any way to tell the modelica compiler to turn equations into initial equations for parameter instances? Because otherwise it is not possible to define parameter instances of complex models implicitly.

oliver
  • 2,771
  • 15
  • 32

3 Answers3

3

As of Modelica Specification v3.4, this is invalid Modelica, since the prefix parameter must not be used with the specialized class model.

There are some proposals to improve this behavior (and meet your requirement), see https://github.com/modelica/ModelicaSpecification/issues/2311 and its source https://github.com/modelica/ModelicaStandardLibrary/issues/1860.

tbeu
  • 1,235
  • 7
  • 12
  • 1
    Are you saying that instatiating models as parameters is illegal in general (irrespective of some hypothetical attribute "fixed")? Then I find it pretty confusing that OpenModelica (as the reference implementation so to say) allows it. – oliver Feb 19 '19 at 16:35
  • And if you allow me that little complaint: it is hard to understand, why you can express a pretty basic concept (solving a static system of equations) perfectly well in flat modelica (existence and uniqueness of nonlinear static solutions is a problem, but it is also in flat modelica), but you can't use object orientation there. It's like Modelica has gone only halfway towards object orientation. – oliver Feb 19 '19 at 16:45
  • 1
    Yes, it is illegal Modelica and should be rejected by OpenModelica. – tbeu Feb 19 '19 at 19:02
0

Edit (2019-02-30): Don't use this 'solution'. According to tbeu's answer it violates the language standard. OpenModelica allows it, but it shouldn't.


I have finally found a partial solution. If I declare ComplexModel by using conditionals in the initial equation and equation sections, I can make it work - somehow.

model ComplexModel
  parameter Boolean fixed = true;
  Real x(fixed = false);
  Real y(fixed = false);
initial equation
  if not fixed then
    y * y = x;
  end if;
equation
  if fixed then
    y * y = x;
  end if;
end ComplexModel;

By replacing in the model RefactoredFlatModel (from the question) the line

parameter ComplexModel mStatic;

by

parameter ComplexModel mStatic (fixed = false);

the resulting flat model finally becomes

class AdvancedMultiBody.FixedTests.RefactoredFlatModel
  parameter Real x = 4.0;
  parameter Real y(fixed = false);
  Real z;
  parameter Boolean mStatic.fixed = false;
  parameter Real mStatic.x(fixed = false);
  parameter Real mStatic.y(fixed = false);
  parameter Boolean mDynamic.fixed = true;
  Real mDynamic.x(fixed = false);
  Real mDynamic.y(fixed = false);
initial equation
  mStatic.y ^ 2.0 = mStatic.x;
  mStatic.x = x;
  y = mStatic.y;
equation
  mDynamic.y ^ 2.0 = mDynamic.x;
  mDynamic.x = 4.0 * x;
  z = mDynamic.y;
end AdvancedMultiBody.FixedTests.RefactoredFlatModel;

i.e. I have successfully juggled the equation for mStatic.y to the initial equation section in a way that can be controlled from the outside. The good thing is that the ComplexModel is now fully encapsulated and can be assigned the 'attribute' fixed = false, as demanded in my question.

The bad thing is that I have to write the underlying equation y*y=x twice inside ComplexModel. In case of more sophisticated equation systems this might be a source of error. And: I think the syntax could be abused If someone writes fixed=false for a non-parameter instance of ComplexModel (causes the time dependent equation to vanish which is quite different from what fixed=false means for atomic data types).

Somehow I wish there was a language feature that does all this automatically and consistently, but there doesn't seem to be.

oliver
  • 2,771
  • 15
  • 32
0

The code you suggested in your question almost works. You only have to leave out the parameter prefix for mStatic and assign its variables in the regular equation section.

model RefactoredFlatModel
  parameter Real x=4;
  parameter Real y(fixed=false);
  Real z;
  ComplexModel mStatic;
  ComplexModel mDynamic;
initial equation 
  y = mStatic.y;
equation 
  // The assignment is needed to have enough equations, even though its static
  mStatic.x = x;

  mDynamic.x = 4*x;
  z = mDynamic.y;
end RefactoredFlatModel;

Parameters can be assigned in initial equations sections from regular variables as well. So you do not need the parameter prefix for the model mStatic. However, the equations of mStatic must also be defined in the continuous time section, hence we have to move the equation mStatic.x = x to the equation section.

marco
  • 5,944
  • 10
  • 22
  • the intention behind using the parameter prefix on the variable was to enable the user interface to show the variable in the parameterization dialog. When working purely with textual models this might seem irrelevant but to me it is important. I'm not sure if your proposal works around that or not... – oliver Apr 07 '19 at 06:56
  • 1
    So you want to show ComplexModel mStatic in the gui then? You can provoke that by adding `annotation(Dialog)` to it (but in OpenModelica its not of much use, as it only shows a text box for it. In Dymola you get a sub-menu to set all its parameters). Or do you simply want to pass parameters to mStatic? You can do that as always. – marco Apr 08 '19 at 06:33