Zero-Crossing Detection
A variable-step solver dynamically adjusts the time step size, causing it to increase when a variable is changing slowly and to decrease when the variable changes rapidly. This behavior causes the solver to take many small steps in the vicinity of a discontinuity because the variable is rapidly changing in this region. This improves accuracy but can lead to excessive simulation times.
Simulink® uses a technique known as zero-crossing detection to accurately locate a discontinuity without resorting to excessively small time steps. Usually this technique improves simulation run time, but it can cause some simulations to halt before the intended completion time.
Simulink uses two algorithms for this purpose: nonadaptive and adaptive. For information about these techniques, see Zero-Crossing Algorithms.
Effect of Excessive Zero Crossing Detection in Simulation
This example demonstrates the effect of excessive zero crossings in simulations using the model example_bounce_two_integrators
, which models the dynamics of a bouncing ball using two Integrator blocks. For performance reasons, the Second-Order Integrator block is recommended over the use of two separate Integrator blocks, where possible. For an example that shows how to model the dynamics of a bouncing ball using the Second-Order Integrator block, see Simulation of Bouncing Ball.
Open the model example_bounce_two_integrators
.
mdl = "example_bounce_two_integrators";
open_system(mdl)
To see the effect of excessive zero-crossing detection, configure the model to use the nonadaptive zero-crossing detection algorithm.
To open the Configuration Parameters dialog box, in the Simulink® Toolstrip, on the Modeling tab, under Setup, click Model Settings.
In the Solver pane of the Configuration parameters dialog box, expand Solver details.
In the solver details, under Zero-crossing options, set the Algorithm parameter to
Nonadaptive
.Click OK.
Alternatively, use the set_param
function to set the ZeroCrossAlgorithm
parameter to Nonadaptive
.
set_param(mdl,ZeroCrossAlgorithm="Nonadaptive")
Simulate the model through a stop time of 20 seconds.
nonadaptive = sim(mdl,StopTime="20");
Plot the position and the velocity of the bouncing ball. The maximum height and maximum velocity decrease with each bounce.
nonadaptivePosition = getElement(nonadaptive.yout,"Position").Values; nonadaptiveVelocity = getElement(nonadaptive.yout,"Velocity").Values; tiledlayout(2,1) ax1 = nexttile; plot(nonadaptivePosition) grid(ax1,"on") title("Nonadaptive Zero-Crossing Detection Algorithm Results") ax2 = nexttile; plot(nonadaptiveVelocity) grid(ax2,"on") title("")
Plot only the last second of simulation results. In the last second of the simulation, the velocity value approaches zero.
tiledlayout(2,1) ax1 = nexttile; plot(nonadaptivePosition) grid(ax1,"on") title("Nonadaptive Zero-Crossing Detection Algorithm Results") axis([19 20 0 0.11]) ax2 = nexttile; plot(nonadaptiveVelocity) grid(ax2,"on") title("") axis([19 20 -1.5 1.5])
As the position and velocity values approach zero, the time between bounces decreases. Each time the ball bounces, both the position and velocity signals have zero crossings. The zero crossings become more frequent as the time between bounces decreases.
Simulate the model again. This time, simulate through a stop time of 25 seconds to see how the nonadaptive zero-crossing algorithm handles the increased frequency of zero crossings in the simulation. Enable the CaptureErrors
parameter to ensure the sim
function returns results even if the frequent zero crossings cause a runtime error in the simulation.
nonadaptive25 = sim(mdl,StopTime="25",CaptureErrors="on");
To see why the simulation stopped, check the execution information in the simulation metadata.
st = nonadaptive25.SimulationMetadata.ExecutionInfo.StopEventDescription
st = 'Simulink will stop the simulation of model 'example_bounce_two_integrators' because the 2 zero crossing signal(s) identified below caused 1000 consecutive zero crossing events in time interval between 20.357636989536076 and 20.357636990631594. -------------------------------------------------------------------------------- Number of consecutive zero-crossings : 1000 Zero-crossing signal name : RelopInput Block type : RelationalOperator Block path : 'example_bounce_two_integrators/Compare To Zero/Compare' -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- Number of consecutive zero-crossings : 500 Zero-crossing signal name : x Lower Saturation Block type : Integrator Block path : 'example_bounce_two_integrators/Position' -------------------------------------------------------------------------------- '
The simulation stopped due to a runtime error caused by too many consecutive zero-crossing events at the blocks named Compare To Zero
and Position
in the model.
The nonadaptive zero-crossing detection algorithm brackets every detected zero-crossing event to determine the location of every zero crossing that occurs during simulation. While the nonadaptive algorithm is adequate for many models and simulations, the nonadaptive algorithm can lead to very small intervals between time steps and very slow simulation in systems with a high degree of chattering or Zeno behavior.
The adaptive zero-crossing detection algorithm stops bracketing if the zero-crossing signal value is close enough to zero and if the number of consecutive zero crossings has reached the limit. If the adaptive algorithm disables bracketing due to excessive consecutive zero crossings, by default, the simulation issues a warning about the ignored zero-crossing event.
Try simulating the model through a stop time of 25 seconds using the adaptive zero-crossing detection algorithm. To suppress the warning about ignored zero crossings, set the Ignored zero crossings parameter to none
.
In the Solver pane of the Configuration Parameters dialog box, under Zero-crossing options, set the Algorithm parameter to
Adaptive
.In the Diagnostics pane of the Configuration Parameters dialog box, click the ellipsis to expand the Advanced parameters. Then, set the Ignored zero crossings parameter to
none
.
Alternatively, use the set_param
function to set the ZeroCrossAlgorithm
parameter to Adaptive
and the IgnoredZcDiagnostic
parameter to none
.
set_param(mdl,ZeroCrossAlgorithm="Adaptive",IgnoredZcDiagnostic="none")
Simulate the model again through a stop time of 25 seconds. Enable the CaptureErrors
parameter to ensure the sim
function returns results even if the simulation issues a runtime error due to the frequent zero crossings.
adaptive = sim(mdl,StopTime="25",CaptureErrors="on");
To see why the simulation stopped, check the execution information in the simulation metadata.
st = adaptive.SimulationMetadata.ExecutionInfo.StopEventDescription
st = 'Reached stop time of 25'
The simulation stopped after reaching the stop time of 25 seconds. Plot the position and velocity of the bouncing ball. Through a simulation time of 20 seconds, the results match the results of the 20-second simulation that used the nonadaptive zero-crossing detection algorithm. After 20 seconds, both the position and velocity appear to be zero.
adaptivePosition = getElement(adaptive.yout,"Position").Values; adaptiveVelocity = getElement(adaptive.yout,"Velocity").Values; tiledlayout(2,1) ax1 = nexttile; plot(adaptivePosition) grid(ax1,"on") title("Adaptive Zero-Crossing Detection Algorithm Results") ax2 = nexttile; plot(adaptiveVelocity) grid(ax2,"on") title("")
Plot only the last 5 seconds of the simulation results. The results are more complete and more closely resemble the expected analytical solution to the equations that govern the dynamics of a bouncing ball. The chatter in the results is expected in numerical simulations as the values of system states approach zero.
tiledlayout(2,1) ax1 = nexttile; plot(adaptivePosition) grid(ax1,"on") title("Adaptive Zero-Crossing Detection Algorithm Results") axis([20 25 0 0.01]) ax2 = nexttile; plot(adaptiveVelocity) grid(ax2,"on") title("") axis([20 25 -0.5 0.5])
Preventing Excessive Zero Crossings
Use the following table to prevent excessive zero-crossing errors in your model.
Change Type | Change Procedure | Benefits |
---|---|---|
Increase the number of allowed zero crossings | Increase the value of the Number of consecutive zero crossings. option on the Solver pane in the Configuration Parameters dialog box. | This may give your model enough time to resolve the zero crossing. |
Relax the Signal threshold | Select Adaptive from the Algorithm pull down and increase the value of the Signal threshold option on the Solver pane in the Configuration Parameters dialog box. | The solver requires less time to precisely locate the zero crossing. This can reduce simulation time and eliminate an excessive number of consecutive zero-crossing errors. However, relaxing the Signal threshold may reduce accuracy. |
Use the Adaptive algorithm | Select Adaptive from the Algorithm drop-down on the Solver pane in the Configuration Parameters dialog box. | This algorithm dynamically adjusts the zero-crossing threshold, which improves accuracy and reduces the number of consecutive zero crossings detected. With this algorithm you have the option of specifying both the Time tolerance and the Signal threshold. |
Disable zero-crossing detection for a specific block |
| Locally disabling zero-crossing detection prevents a specific block from stopping the simulation because of excessive consecutive zero crossings. All other blocks continue to benefit from the increased accuracy that zero-crossing detection provides. |
Disable zero-crossing detection for the entire model | Select | This prevents zero crossings from being detected anywhere in your model. A consequence is that your model no longer benefits from the increased accuracy that zero-crossing detection provides. |
If using the | Select a value from the | For more information, see Maximum order. |
Reduce the maximum step size | Enter a value for the | The solver takes steps small enough to resolve the zero crossing. However, reducing the step size can increase simulation time, and is seldom necessary when using the adaptive algorithm. |
How the Simulator Can Miss Zero-Crossing Events
The bounce and double-bounce models, in Simulation of Bouncing Ball and Double Bouncing Ball: Use of Adaptive Zero-Crossing Location show that high-frequency fluctuations about a discontinuity (chattering) can cause a simulation to prematurely halt.
It is also possible for the solver to entirely miss zero crossings if the solver error tolerances are too large. This is possible because the zero-crossing detection technique checks to see if the value of a signal has changed sign after a major time step. A sign change indicates that a zero crossing has occurred, and the zero-crossing algorithm searches for the precise crossing time. However, if a zero crossing occurs within a time step, but the values at the beginning and end of the step do not indicate a sign change, the solver steps over the crossing without detecting it.
The following figure shows a signal that crosses zero. In the first instance, the integrator steps over the event because the sign has not changed between time steps. In the second, the solver detects sign change and therefore detects the zero-crossing event.
Consider the two-integrator implementation of the bounce model.
Profiling of the last 0.5 s of the simulation using the Solver Profiler shows that the simulation detects 44 zero-crossing events at the Compare To Zero block and 22 events at the output of the Position block.
Increase the value of the Relative tolerance parameter to
1e-2
instead of the default 1e-3
. You can
change this parameter in the Solver Details section of the
Solver pane in the Configuration
Parameters dialog box or using set_param
to specify
RelTol
as '1e-2'
.
Profiling the last 0.5 s of the simulation with the new relative tolerance of the solver shows that it detects only 24 zero-crossing events at the Compare To Zero block and 12 events at the output of the Position block.
Zero-Crossing Detection in Blocks
A block can register a set of zero-crossing variables, each of which is a function of a state variable that can have a discontinuity. The zero-crossing function passes through zero from a positive or negative value when the corresponding discontinuity occurs. The registered zero-crossing variables are updated at the end of each simulation step, and any variable that has changed sign is identified as having had a zero-crossing event.
If any zero crossings are detected, the Simulink software interpolates between the previous and current values of each variable that changed sign to estimate the times of the zero crossings, that is, the discontinuities.
Note
The Zero-Crossing detection algorithm can bracket zero-crossing events only
for signals of data type double
.
Blocks That Register Zero Crossings
The following table lists blocks that register zero crossings and explains how the blocks use the zero crossings.
Block | Number of Zero Crossing Detections |
---|---|
One, to detect when the input signal crosses zero in either the rising or falling direction. | |
Two, one to detect when the upper threshold is engaged, and one to detect when the lower threshold is engaged. | |
One, to detect when the signal equals a constant. | |
One, to detect when the signal equals zero. | |
Two, one to detect when the dead zone is entered (the input signal minus the lower limit), and one to detect when the dead zone is exited (the input signal minus the upper limit). | |
One, If an Enable port is inside of a Subsystem block, it provides the capability to detect zero crossings. For details, Using Enabled Subsystems. | |
One, to detect when the input signal has a discontinuity in either the rising or falling direction | |
One, to detect when the input signal has a discontinuity in either the rising or falling direction | |
One or two. If there is no output port, there is only one zero crossing to detect when the input signal hit the threshold value. If there is an output port, the second zero crossing is used to bring the output back to 0 from 1 to create an impulse-like output. | |
One, to detect when the If condition is met. | |
If the reset port is present, to detect when a reset occurs. If the output is limited, there are three zero crossings: one to detect when the upper saturation limit is reached, one to detect when the lower saturation limit is reached, and one to detect when saturation is left. | |
One, for each element of the output vector, to detect when an input signal is the new minimum or maximum. | |
Two, one to detect upper limit and the other to detect lower limit | |
One, to detect when the specified relation is true. | |
One, if the relay is off, to detect the switch-on point. If the relay is on, to detect the switch-off point. | |
Two, one to detect when the upper limit is reached or left, and one to detect when the lower limit is reached or left. | |
Two, one to detect upper limit and the other to detect lower limit | |
Five, two to detect when the state x upper or lower limit is reached, two to detect when the state dx/dt upper or lower limit is reached, and one to detect when a state leaves saturation. | |
One, to detect when the input crosses through zero. | |
One, to detect when the input signal has a discontinuity in either the rising or falling direction | |
One, to detect the step time. | |
One, to detect when the switch condition occurs. | |
One, to detect when the case condition is met. | |
One, If a Triggered port is inside of a Subsystem block, it provides the capability to detect zero crossings. For details, see Using Triggered Subsystems. | |
Two, one for the enable port and one for the trigger port. For details, see: Using Enabled and Triggered Subsystems | |
One, to detect when the input signal has a discontinuity in either the rising or falling direction. |
Note
Zero-crossing detection is also available for a Stateflow® chart that uses continuous-time mode. See Configure a Stateflow Chart for Continuous-Time Simulation (Stateflow) for more information.
Implementation Example: Saturation Block
An example of a Simulink block that registers zero crossings is the Saturation block. Zero-crossing detection identifies these state events in the Saturation block:
The input signal reaches the upper limit.
The input signal leaves the upper limit.
The input signal reaches the lower limit.
The input signal leaves the lower limit.
Simulink blocks that define their own state events are considered to have intrinsic zero crossings. Use the Hit Crossing block to receive explicit notification of a zero-crossing event. See Blocks That Register Zero Crossings for a list of blocks that incorporate zero crossings.
The detection of a state event depends on the construction of an internal
zero-crossing signal. This signal is not accessible by the block diagram. For the
Saturation block, the signal that is used to detect zero crossings for the upper
limit is zcSignal = UpperLimit
- u
, where
u
is the input signal.
Zero-crossing signals have a direction attribute, which can have these values:
rising — A zero crossing occurs when a signal rises to or through zero, or when a signal leaves zero and becomes positive.
falling — A zero crossing occurs when a signal falls to or through zero, or when a signal leaves zero and becomes negative.
either — A zero crossing occurs if either a rising or falling condition occurs.
For the Saturation block upper limit, the direction of the zero crossing is either. This enables the entering and leaving saturation events to be detected using the same zero-crossing signal.