As stated above: I wish to compute the minimum (and/or maximum) of a continuous variable over time. Here is a minimal example to demonstrate:
model MinMaxTest
Real u;
Real u_min(start = 10);
Real u_max(start = -10);
equation
u = sin(time / 180 * Modelica.Constants.pi);
u_min = min(u, u_min);
u_max = max(u, u_max);
annotation(experiment(StartTime = 0, StopTime = 360, Tolerance = 1e-06, Interval = 1));
end MinMaxTest;
u
is the arbitrary continuous variable (for demo purposes a simple sinus wave).
u_min
/u_max
is the minimum/maximum over time.
Obviously the expected result is u_min=-1
and u_max=1
. Unfortunately the simulation crashes with a "Matrix singular!" error. Can anyone direct me how to avoid that?
EDIT 1
I'm using OpenModelica 1.15 (was 1.9.2)
EDIT 2
As I'm quite new to Modelica, I'm struggling to understand the differences between the following approaches:
u_min = if noEvent(u < u_min) then u else pre(u_min);
if noEvent(u < u_min) then u_min = u; else u_min = pre(u_min); end if;
u_min = if noEvent(u < u_min) then u else u_min;
u_min = if u < u_min then u else pre(u_min);
u_min = if u < u_min then u else u_min;
when u < u_min then u_min = u; end when;
u_min + T*der(u_min) = if u <= u_min then u else u_min;
1 and 2 are equivalent and result in the expected behavior.
3 produces the desired result but gives a "Translation Notification" about an "algebraic loop", why?
4 fails in so far, that the resulting u_min
curve is identical to u
?! why?
5 combines 3 and 4.
6 fails to compile with Sorry - Support for Discrete Equation Systems is not yet implemented
7 I'm unclear what the idea behind this is, but it works if T
is of the suggested size.
If I'm understanding the Modelica documentation correctly then 1-5 have in common that exactly one equation is active at all times. noEvent
suppresses event generation at the specified zero crossing. I had the impression that this is mostly an efficiency improvement. Why does leaving it out cause 4 to fail? pre
refers to the previous value of the variable, so I guess that makes sense if we want to keep a variable constant, but why does 7 work without it? My understanding of when
was, that its equation is only active at that precise event, and otherwise keeps the previous value, which is why I tried using it in 6. It seems to work if I compare against constant values (which is of no use for this particular problem).
EDIT3
u_min = smooth(0, if u < u_min then u else pre(u_min));
Interestingly, this works also.
For your initial question, what seems to work correctly for me in OpenModelica is this:
For me that compiles, simulates, and gives the expected results, but also does say "Matrix singular!". On the other hand, if I change the initial declaration for u_max to this:
Then, the "Matrix singular!" goes away.
I don't know why, but that does seems to do the job, and I would suggest is more straightforward then the other options you have listed.