Opened 5 years ago

Last modified 5 years ago

#5934 new discussion

auxiliary state in der-call

Reported by: Philip Hannebohm Owned by: Lennart Ochel
Priority: high Milestone: Future
Component: Backend Version:
Keywords: Cc: Karim Adbdelhak, Lennart Ochel, Francesco Casella

Description (last modified by Philip Hannebohm)

Currently arguments of the der-call like in der(sin(x)*y) = 1 are differentiated symbolically until single variables are reached, yielding something like

cos(x)*der(x)*y + sin(x)*der(y) = 1

In cases like der(y^x) this may even result in pretty ugly residual equations.

Instead we could introduce an auxiliary variable $aux = sin(x)*y, s.t. der($aux) = 1. I believe Karim has some convincing arguments towards this approach. I'll try to recap them from what I understand:

  1. If x and y appear only algebraically elsewhere, introducing an auxiliary results in fewer states, thus a lower index.
  2. Otherwise (der(x) and der(y) exist elsewhere) the system may need index reduction anyways, because the states x and y are connected somehow. The alias might allow index reduction to pick a better choice.

I personally think differentiating the interior of der(...) is a cool feature. But there may be practical reasons against it.
I have no idea how academic this issue is. Opinions?

Change History (9)

comment:1 by Karim Adbdelhak, 5 years ago

Also i would add to this, that if the the derivative operator is used anywhere it implies that the inside of it is a state. I think otherwise the operator is not used correctly in the first place.

Consider following example:

model M
 Real x,y,z;
equation
 x = sin(time) + z;
 y = cos(time);
 der(x + y^2) = time;
end M;

Right now the inside will be differentiated, and we need to resolve a higher index since it creates two states x and y. The second equation will be differentiated (note that this equation is totally unrelated to our original problem). If we replaced the inside with an auxiliary variable $aux and introduce the extra equation

$aux = x + y^2;

No index reduction is needed. In that example both x and y only appear algebraically, if one of them appears differentiated, e.g the first equation would be

der(x) = sin(time) + z; 

instead, both methods work fine, since in both cases only one extra state will be created. The new attempt would only be problematic if both variables appeared differentiated e.g. the second equation would be

der(y) = cos(time); 

This would yield no index reduction for the current implementation but an index reduction for the auxiliary replacement method. This however would always only contain the created auxilary equation (if any other are involved, index reduction was necessary anyways).

The big advantage of auxiliary replacement is that the worst case has the smaller state set (less constraint equations). With the current implementation, the first case could need differentiation of a lot of unrelated equations to resolve the index problem, whereas the new method could only lead to one extra equation in index reduction problems, which is the auxiliary equation. It kind of postpones the decision of differentiating the inside to index reduction where we have more information if it is actually needed.

Long story short, i strongly approve of this!

@Francesco, @Lennart: Any comments on this? Should be an easy implementation!

Last edited 5 years ago by Karim Adbdelhak (previous) (diff)

comment:2 by Karim Adbdelhak, 5 years ago

Cc: Francesco Casella added
Priority: lowhigh

comment:3 by Bernhard Bachmann, 5 years ago

I agree to the arguments above and support introducing the auxiliary variable. In addition, I would add

stateSelect = StateSelect.avoid

to the attributes of the auxiliary variable, just in case index reduction has to be performed.

in reply to:  3 ; comment:4 by Francesco Casella, 5 years ago

Replying to bachmann:

I agree to the arguments above and support introducing the auxiliary variable. In addition, I would add

stateSelect = StateSelect.avoid

to the attributes of the auxiliary variable, just in case index reduction has to be performed.

Absolutely, otherwise you risk to get back to square one.

in reply to:  4 comment:5 by Karim Adbdelhak, 5 years ago

Replying to casella:

Replying to bachmann:

I agree to the arguments above and support introducing the auxiliary variable. In addition, I would add

stateSelect = StateSelect.avoid

to the attributes of the auxiliary variable, just in case index reduction has to be performed.

Absolutely, otherwise you risk to get back to square one.

It depends on what the user intends by using der() on any expression, but i guess avoid would be the most correct way to put it. It would still be chosen if dynamic state selection can be avoided by that.

in reply to:  3 comment:6 by Philip Hannebohm, 5 years ago

Replying to bachmann:

I agree to the arguments above and support introducing the auxiliary variable. In addition, I would add

stateSelect = StateSelect.avoid

to the attributes of the auxiliary variable, just in case index reduction has to be performed.

Of course, this actually showed me how to look at it, thanks!

Also I've been thinking about a proper start value for $aux, since the initial system still has one equation missing. I mean the way @Karims example is put, there is information missing anyway. Would setting a start value (fixed) for any of the other (algebraic) variables be handled just fine in this setup?

comment:7 by Philip Hannebohm, 5 years ago

Description: modified (diff)

comment:8 by Philip Hannebohm, 5 years ago

Summary: alias state in der-callauxiliary state in der-call

in reply to:  1 comment:9 by Francesco Casella, 5 years ago

Replying to Karim.Abdelhak:

@Francesco, @Lennart: Any comments on this? Should be an easy implementation!

I never thought about such an approach, but it looks good, once you have all the index reduction machinery in place. I actually have "products under the derivative operator" in many of my models, but I already write the model in a way that resembles what Karim would like to do automatically by introducing auxiliary variables, e.g.

partial model foobar
  Real M(stateSelect = StateSelect.avoid);
  Real p(stateSelect = StateSelect.prefer);
  Real T(stateSelect = StateSelect.prefer);
  Real rho;
  Real w_in,w_out;
equation
  der(M) = w_in - w_out;
  M = rho*V;
  E = e*M;
  rho = f_rho(p,T);
  e = f_e(p,T);
end foobar;

so it seems to me that the approach is fine. I'm afraid there's not many test cases (if any) for it in the testsuite, I guess you should add some to make sure we're not overlooking some issues.

One important point: please make sure that the outcome of this manipulation process is clearly understood when using the declarative debugger. From what I understand, it is, but we should test it.

Note: See TracTickets for help on using tickets.