Opened 4 years ago
Closed 3 years ago
#6195 closed defect (fixed)
Assert triggered incorrectly on variable computed with conditional expression
Reported by: | Francesco Casella | Owned by: | Andreas Heuermann |
---|---|---|---|
Priority: | critical | Milestone: | 1.19.0 |
Component: | Run-time | Version: | |
Keywords: | Cc: | Michael Wetter |
Description (last modified by )
Please check Buildings.Electrical.AC.OnePhase.Loads.Examples.ParallelLoads. The model fails at runtime with
LOG_SUCCESS | info | The initialization finished successfully without homotopy method. assert | warning | The following assertion has been violated at time 0.700200 | | | | load_y.y >= 0.0 and load_y.y <= 1.0000000001 assert | error | The power load fraction P (input of the model) must be within [0,1]
Now, load.y
is computed with the following equation
y = offset + (if time < startTime then 0 else if time < (startTime + duration) then (time - startTime)*height/duration else height);
and the upper limit of the assert is the value 1+eps
with eps = 1e-10
defined in Buildings.Electrical.Interfaces.Load
. In order to run the simulation successfully, one needs to increase it to 1e-2. What is interesting is that the transient computing at that point result is apparently not exceeding 1 by more than a much, much smaller value.
This raises the obvious question: why is this assert triggered in the first place?
My rough guess is that the assert is not checked on the accepted step value, which would be within the limits with a very tight tolerance, but is somehow being applied to the value of y
during the process of finding the zero of the zero-crossing function, incorrectly aborting it.
I would recommend to move the assertion checking downstream of the zero-crossing solution, otherwise this kind of errors could happen in a number of cases.
Change History (12)
comment:1 by , 4 years ago
Milestone: | 1.17.0 → 1.18.0 |
---|
follow-up: 4 comment:3 by , 4 years ago
Isn't noEvent
needed here? If-expressions cannot be used reliably since they will not switch until an event: https://specification.modelica.org/master/equations.html#events-and-synchronization
comment:4 by , 4 years ago
Replying to sjoelund.se:
Isn't
noEvent
needed here? If-expressions cannot be used reliably since they will not switch until an event: https://specification.modelica.org/master/equations.html#events-and-synchronization
This would be the case if we had something like y = if x > 0 then sqrt(x) else 0
, where the expression in the first branch becomes invalid when x becomes negative, which could happen while the solver is looking for the exact time of the event, when the zero-crossing function vanishes.
Notice that using noEvent
has a cost in terms of computational workload, because we are passing the solver a function which is not even C1, hence all the error estimations assuming a smooth function will not be very reliable. It is a bit of a brute-force solution.
However, this is not the case here. There is nothing wrong in the load going slightly above 1 during the solution process. I think the assert should be applied only on accepted steps.
Seems to me very much related to #6372. @AnHeuermann, what do you think?
comment:5 by , 4 years ago
Description: | modified (diff) |
---|
comment:6 by , 4 years ago
Cc: | added |
---|
comment:8 by , 3 years ago
Milestone: | → 1.19.0 |
---|
comment:9 by , 3 years ago
@AnHeuermann, some more additional information to pinpoint the issue.
If I simulate with 20 intervals instead of 500, I get:
The following assertion has been violated at time 0.750000 load_y.y >= 0.0 and load_y.y <= 1.0000000001 The power load fraction P (input of the model) must be within [0,1]
So, what seems to be happening is that the load reaches "almost" 1 at time 0.7, but then another step is taken without the event handling being triggered.
Even more interesting is to see what happens with 22 intervals. The following steps are reported: t = 0.045454, t = 0.090909, t = 0.1363636, 0.1818181 (i.e. 1/22, 2/22, 3/22, 4/22). Then, a first event is triggered at t = 0.2, after which we resume with 5/22, 6/22, etc., until t = 15/22 = 0.686868. At this point the simulation aborts with
The following assertion has been violated at time 0.727273 load_y.y >= 0.0 and load_y.y <= 1.0000000001 The power load fraction P (input of the model) must be within [0,1] Integrator attempt to handle a problem with a called assert. The following assertion has been violated at time 0.704545 load_y.y >= 0.0 and load_y.y <= 1.0000000001 The power load fraction P (input of the model) must be within [0,1] model terminate | Simulation terminated by an assert at time: 0.704545
What happens here is pretty clear: the next step at t = 16/22 = 0.727273 is attempted, and of course the assertions is violated because, due to the large time step, the step is wey beyond the event time, i.e. t = 0.7.
Then the solver halves the interval, so it tries (15+1/2)/22 = 0.704545, which is still to far from t = 0.7 to stay within y <= 1.0000000001, and then it just quits.
It seems that we are trying to identify the event time by bisection, which is not particularly efficient but is just fine. However, we should let the solver iterate as many times as it needs to find out the event time without failing. I don't really know why only one iteration is allowed here before giving up.
In fact, it is fine to check for assertions during these iterations, in order to discard invalid points, but I wouldn't even report them on stdout, as they can generate anxiety on the end-user (like the model is numerically problematic or something), when this is absolutely not the case.
comment:11 by , 3 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Reopened because of some regressions, see #6195 on GitHub.
This could very well be the case. Should be the first place to check.
Probably also roughly related to #6201.