Opened 5 years ago

Last modified 3 years ago

#5813 new defect

Improve selection of start attributes for alias variables

Reported by: Francesco Casella Owned by: Francesco Casella
Priority: critical Milestone:
Component: Backend Version:
Keywords: Cc: Karim Adbdelhak, Andreas Heuermann, Adrian Pop, Per Östlund, Philip Hannebohm, adrien.guironnet@…, Rüdiger Franke

Description (last modified by Francesco Casella)

The selection of start attributes in alias variable sets is a crucial issue: oftentimes one element of the alias variable set has a carefully user-selected value, while the other ones have default values. It is of paramount importance that the user-selected value is used by the back-end, e.g. to set up the initial guess of iterative solvers, and that this value is not overridden by other less relevant defaults.

This issue has been well-known in the Modelica community for a long time, and actually brought to Section 8.6.2 of the Modelica specification. However, it seems to me that the criterion put forward there doesn't cover all the cases satisfactorily. This leads to the detection of start value conflicts which aren't really there, or (worse) to the selection of the wrong start values, which is what I am constantly experiencing with steam power plant models.

Consider the following examples

package Aliases
  type Temperature = Real(start = 300, unit="K");
  type Power = Real(unit="W");

  connector Port
    Temperature T;
    flow Power Q;
  end Port;

  model TemperatureSource
    parameter Temperature Tstart = 320;
    Temperature T1;
    Temperature T2(start = 310);
    Temperature T3(start = Tstart);
    Port port;
  equation
    port.T = T1;
    T1 = T2;
    T2 = T3;
    T1+1e-6*sin(T1) = 300 "Implicit equation on T1";
  end TemperatureSource;
  
  model PowerSource
    parameter Temperature Tstart = 320;
    Port port;
    Temperature T1;
    Temperature T2(start = 330);
    Temperature T3(start = Tstart);
  equation
    port.T = T1;
    T1 = T2;
    T2 = T3;
    port.Q - (port.T-300) = sin(time);
  end PowerSource;

  model WrappedTemperatureSource
    parameter Temperature Tstart = 345;
    Port port;
    TemperatureSource ts(Tstart = Tstart);
  equation
    connect(ts.port, port);
  end WrappedTemperatureSource;  
  
  model WrappedPowerSource
    parameter Temperature Tstart = 345;
    Port port;
    PowerSource ps(Tstart = Tstart);
  equation
    connect(ps.port, port);
  end WrappedPowerSource;  
  
  model System1
    TemperatureSource ts;
    PowerSource ps;
  equation
    connect(ts.port,ps.port);
  end System1;
  
  model System2
    TemperatureSource ts(Tstart = 350);
    PowerSource ps;
  equation
    connect(ts.port,ps.port);
  end System2;
  
  model System3
    TemperatureSource ts(T1(start = 360));
    PowerSource ps;
  equation
    connect(ts.port,ps.port);
  end System3;
  
  model System4
    WrappedTemperatureSource ts(Tstart = 370);
    PowerSource ps;
  equation
    connect(ts.port,ps.port);
  end System4;
  
  model System5
    TemperatureSource ts;
    WrappedPowerSource ps(Tstart = 380);
  equation
    connect(ts.port, ps.port);
  end System5;

  model System6
    WrappedTemperatureSource ts(ts(T1(start = 390)));
    WrappedPowerSource ps(Tstart = 400);
  equation
    connect(ts.port, ps.port);
  end System6;
end Aliases;

At the end of the day, after alias elimination, each of these models has two unknowns: a power flow and a temperature. Everything else are aliases.

As an end-user and library developer, I would like the following start values to be selected for the temperature:

  • System1: 320
  • System2: 350
  • System3: 360
  • System4: 370
  • System5: 380
  • System6: 390

As far as I understand, the current rules of Section 8.6.2 do not guarantee these choices are taken. In fact, with the current 1.16.0-dev version of OMC, I get:

  • System1: 330
  • System2: 330
  • System3: 330
  • System4: 330
  • System5: 300
  • System6: 330

which is never the value I would expect. I haven't checked with Dymola yet, but I suspect the results will be similar.

We should

  1. figure out rules to guarantee those choices are made
  2. understand how to collect the relevant information in the frontend and pass it to the backend
  3. promote a discussion with the MAP-LIB and MAP-LANG projects to standardize the solution

Regarding point 1, I have some loosely formulated requirements, but they need to be formalized into actual rules for the compiler

  • type defaults have the lowest priority, they should only be used if there are no other start value specification overriding them
  • start values set by modifications when instantiating components should have higher priority than start values set by default binding equations in component declarations
  • the priority of start values given by parameters should be determined on the basis of where the actual parameter value is specified
  • direct specifications of the start value from the top level of the model to be simulated via nested modifiers should have the precedence over the other start values specified insied the lower-level components
  • even in case the parameters are evaluated, the priority information should be computed by the frontend (particularly when evaluating parameters!) and then passed along to the backend, in order to be able to make the correct choices when performing alias elimination

Any ideas/comments?

Attachments (1)

Aliases.mo (2.5 KB ) - added by Francesco Casella 5 years ago.

Download all attachments as: .zip

Change History (14)

comment:1 by Francesco Casella, 5 years ago

Description: modified (diff)

comment:2 by Francesco Casella, 5 years ago

Description: modified (diff)

by Francesco Casella, 5 years ago

Attachment: Aliases.mo added

comment:3 by Francesco Casella, 5 years ago

Milestone: Future1.16.0
Priority: highcritical

comment:4 by Adrian Pop, 5 years ago

As far as I remember we do have the information on where a binding came from: a type or other origin.
Is the startOrigin present in the variable attributes for each type (Integer, Real, etc)
https://github.com/OpenModelica/OpenModelica/blob/master/OMCompiler/Compiler/FrontEnd/DAE.mo#L482
This could be used to avoid the bindings that come from types.

However, I have no idea if this is set properly by the old/new front-ends, one needs to check it.

Last edited 5 years ago by Adrian Pop (previous) (diff)

in reply to:  4 comment:5 by Per Östlund, 5 years ago

Replying to adrpo:

However, I have no idea if this is set properly by the old/new front-ends, one needs to check it.

It's not used by the new frontend, it always just uses the "default" value for DAE.BindingSource when creating the DAE. It does keep track of which scope a binding comes from though, so I think we can check if a start value comes from the declaration by just checking if the component itself is the scope. If that doesn't work for some reason we can just add the information to the bindings themselves. The backend doesn't seem to use this information for anything though.

Edit: I reread what you wrote and realised I'd missed that we also store this information in the DAE.VariableAttribute. That one might be used by the backend, grepping for startOrigin does give a lot of matches in the backend at least.

Last edited 5 years ago by Per Östlund (previous) (diff)

comment:6 by Francesco Casella, 5 years ago

@Karim, @AnHeuermann, it would be good if you could make a quick check of what the DAE.VariableAttribute contains in the six examples I prepared, and see if there is some simple rule that you can provisionally implement that guarantees that most of the values I'd expect are actually selected.

Then, we can see what impact this has on the testsuite ad on the FlexiCaL model. I guess it could be quite positive.

comment:7 by Philip Hannebohm, 5 years ago

Cc: Philip Hannebohm added

comment:8 by Francesco Casella, 4 years ago

Milestone: 1.16.01.17.0

Retargeted to 1.17.0 after 1.16.0 release

comment:9 by Francesco Casella, 4 years ago

Cc: adrien.guironnet@… added
Component: *unknown*Backend

I am currently working on test cases using the PowerGrids library. It is not yet publicly available, but it will soon be, and I can share it if necessary. Initialization is a crucial issue in that library, and handled systematically according to a fundamental principle which is discussed in this paper: start values are relevant only for variables that influence the Jacobian, i.e. that appear in a nonlinear fashion in the residuals.

In the case of power system models, this principle is very useful to avoid the need of setting start values on each and every variable of each and every model, which would be extremely tedious and make the code unnecessarily cumbersome. In particular, no start values are explicitly set for variables that appear in linear models, such as transmission lines and saturation-less transformers. Even in the case that some start values are computed (e.g. those of port variables, which are always computed in the base OnePortAC and TwoPortAC classes), one may not bother to set the power flow parameter values for linear components such as transmission lines or buses, since those values would only affect start attributes of linear variables, that are irrelevant for convergence.

Conversely, models with nonlinear equation are designed so that all variables that appear nonlinearly in them are properly initialized, based on values provided by the power-flow parameters, i.e., voltage magnitude and angle, active and reactive power flows at the component port(s). For those nonlinear components, the power flow parameters are critical, and must be provided correctly.

Unfortunately, alias variable selection is still not up to the task, and it actually leads to generated code for which the initialization problem either does not converge at all, or it does, but in a much longer time than would be reasonable.

At this moment I cannot be more specific because of #5805, which prevents me to inspect the initial values that are actually used in a problem that is taking too long a time to be solved. However, I suspect that in some cases the confidence number criterion (which is not very good, see above) may lead to the selection of the start attribute of a variable appearing linearly in the equation, superseding the start attribute of the nonlinear variable which is most likely the meaningful one.

I need to be more precise in the analysis of my test case, and I'll be able to do that once #5805 is resolved. However, I would propose to introduce a selection heuristic that favours the start attributes of those variables in an alias set that appear nonlinearly in some equations, against those of variables that only appear linearly. This heuristic should probably be made optional at first. If people designed libraries and models according to the criterion of the above-mentioned paper, this would always work, but there may well be some cases where people added a start value on a linear alias, just because the tool at hand picked that variable as representative of the alias set. For sure, this heuristic is crucial for the proper operation of PowerGrids.

comment:10 by Francesco Casella, 4 years ago

Milestone: 1.17.01.18.0

Retargeted to 1.18.0 because of 1.17.0 timed release.

comment:11 by Francesco Casella, 3 years ago

Milestone: 1.18.0

Ticket retargeted after milestone closed

comment:12 by Francesco Casella, 3 years ago

comment:13 by Francesco Casella, 3 years ago

Cc: Rüdiger Franke added

@Karim, @rfranke, it seems that some consensus has beeen reached on how to solve this problem. Hans Olsson proposed an amendment to Section 8.6.2 that should give the expected result in all the cases I had in mind.

@rfranke, you can have a look at my examples in ticket MSL #3008 and see if you like my proposed outcomes.

@Karim, if MSL #3019 is merged in, you can implement those rules in the backend. For sure this will eliminate a lot of warnings about conflicting start values, and I guess it will also improve convergence on a lot of examples.

Note: See TracTickets for help on using tickets.