Description of the problem
The core equation of the Modelica.Blocks.Nonlinear.SlewRateLimiter block reads:
|
if strict then |
|
der(y) = smooth(1, (if noEvent(val<Falling) then Falling else if noEvent(val>Rising) then Rising else val)); |
|
else |
|
der(y) = if val<Falling then Falling else if val>Rising then Rising else val; |
|
end if; |
This is likely inspired by the code of the Limiter block
|
if strict then |
|
if homotopyType == Types.LimiterHomotopy.NoHomotopy then |
|
y = smooth(0, noEvent(if u > uMax then uMax else if u < uMin then uMin else u)); |
|
else |
|
y = homotopy(actual = smooth(0, noEvent(if u > uMax then uMax else if u < uMin then uMin else u)), |
|
simplified=simplifiedExpr); |
|
end if; |
|
else |
|
if homotopyType == Types.LimiterHomotopy.NoHomotopy then |
|
y = smooth(0,if u > uMax then uMax else if u < uMin then uMin else u); |
|
else |
|
y = homotopy(actual = smooth(0,if u > uMax then uMax else if u < uMin then uMin else u), |
|
simplified=simplifiedExpr); |
|
end if; |
|
end if; |
In the case of the Limiter block, the strict = true version makes sense when the block output should never exceed the upper and lower limit, e.g. to avoid division-by-zero, sqrt-neg-number or log-neg-number issues. Regular event detection necessarily implies computing out-of-bounds values during the solver iterations to find the root of the zero-crossing functions, so it is necessary to disable event detection to avoid that; luckily, since the noEvent expression is continuous, this can be done without too much damage for the ODE integrator.
The SlewRateLimiter block also has a strict = true version that disables event generation and introduces the smooth() operator. Unfortunately, in this case the expression on the RHS of the differential equation is not continuously differentiable, as it is incorrectly declared by the smooth() operator; in fact, when the input undergoes large enough step changes, that expression is discontinuous, as demonstrated by this simple MWE:
model TestSlewRate
Modelica.Blocks.Nonlinear.SlewRateLimiter slewRateLimiter(Rising = 300, Td = 0.03);
Modelica.Blocks.Sources.Step step(height = 1e5, startTime = 100);
equation
connect(step.y, slewRateLimiter.u);
annotation(
uses(Modelica(version = "4.1.0")),
experiment(StartTime = 0, StopTime = 500, Tolerance = 1e-06, Interval = 10));
end TestSlewRate;
As F. Cellier very clearly discusses in Chapter 9.2 of the book Continuous System Modelling, relying on error estimation and step-size adaption algorithms to handle discontinuous variables without explicit event handling is not a good idea and can lead to completely wrong results. On the other hand, if the output of the derivative block has a derivative that slightly exceeds the given limits during the iterations to find the roots of the zc-function generating the event, nothing harmful happens.
Suggested solution
Based on the analyis reported above I would deprecate the strict = true behaviour, by moving the strict parameter to a Deprecated tab and changing the code to
der(y) = if val<Falling then Falling else if val>Rising then Rising else val;
if strict then
assert("strict = true is deprecated and has no effect in this version of the library; the strict parameter will be removed in future versions of the library", AssertionLevel.warning);
end if;
Description of the problem
The core equation of the
Modelica.Blocks.Nonlinear.SlewRateLimiterblock reads:ModelicaStandardLibrary/Modelica/Blocks/Nonlinear.mo
Lines 206 to 210 in e653d4f
This is likely inspired by the code of the
LimiterblockModelicaStandardLibrary/Modelica/Blocks/Nonlinear.mo
Lines 25 to 39 in e653d4f
In the case of the
Limiterblock, thestrict = trueversion makes sense when the block output should never exceed the upper and lower limit, e.g. to avoid division-by-zero, sqrt-neg-number or log-neg-number issues. Regular event detection necessarily implies computing out-of-bounds values during the solver iterations to find the root of the zero-crossing functions, so it is necessary to disable event detection to avoid that; luckily, since the noEvent expression is continuous, this can be done without too much damage for the ODE integrator.The
SlewRateLimiterblock also has astrict = trueversion that disables event generation and introduces thesmooth()operator. Unfortunately, in this case the expression on the RHS of the differential equation is not continuously differentiable, as it is incorrectly declared by thesmooth()operator; in fact, when the input undergoes large enough step changes, that expression is discontinuous, as demonstrated by this simple MWE:As F. Cellier very clearly discusses in Chapter 9.2 of the book Continuous System Modelling, relying on error estimation and step-size adaption algorithms to handle discontinuous variables without explicit event handling is not a good idea and can lead to completely wrong results. On the other hand, if the output of the derivative block has a derivative that slightly exceeds the given limits during the iterations to find the roots of the zc-function generating the event, nothing harmful happens.
Suggested solution
Based on the analyis reported above I would deprecate the
strict = truebehaviour, by moving thestrictparameter to a Deprecated tab and changing the code to