Found an issue with the book? Report it on Github.

In this section, we’ll discuss the topic of hysteresis. This is an
important concept to understand for certain types of modeling. Recall
in our previous discussion of State Event Handling we saw cases where
chattering occurred. In those cases, we were able to use the
`noEvent`

operator to address the issue because the chattering was
purely a response to numerical noise and not triggered by abrupt
changes in behavior.

In this section, we will consider a slightly more extreme case. Consider the following model:

```
model ChatteringControl "A control strategy that will 'chatter'"
type HeatCapacitance=Real(unit="J/K");
type Temperature=Real(unit="K");
type Heat=Real(unit="W");
type Mass=Real(unit="kg");
type HeatTransferCoefficient=Real(unit="W/K");
Boolean heat "Indicates whether heater is on";
parameter HeatCapacitance C=1.0;
parameter HeatTransferCoefficient h=2.0;
parameter Heat Qcapacity=25.0;
parameter Temperature Tamb=285;
parameter Temperature Tbar=295;
Temperature T;
Heat Q;
initial equation
T = Tbar+5;
equation
heat = T<Tbar;
Q = if heat then Qcapacity else 0;
C*der(T) = Q-h*(T-Tamb);
end ChatteringControl;
```

If we simulate this model, we get the following results:

However, the simulation that yields these results takes a very long time to complete. The reason for such poor simulation performance can be better understood by looking at the heater output during the simulation:

What you see is that after around 0.2 seconds, the heater is constantly turning on and off. This happens so frequently, in fact, that you would have to zoom in quite a bit on the plot to see the transitions. With normal scaling, there are so many transitions that the results resemble a filled rectangle.

This is actually a real problem in control systems. If you look carefully at the way the furnace works in your own home, you will see that it does not turn on and off constantly as the temperature goes above and below the desired room temperature you have specified. Instead, it waits until the temperature gets some specified amount above or below the desired temperature before acting.

This “band” that is introduced around the desired temperature is
called hysteresis. The problem with the `ChatteringControl`

model is that it doesn’t have any hysteresis. Instead, it is
constantly turning the heater off and on in response to miniscule
changes in temperature.

The tricky thing about modeling hysteresis is that it is “stateful”.
Determining the behavior of the system depends on what happened in the
past. For this reason, we cannot simply use `if`

statements. The
reason is that `if`

statements consider only the current state of
the system, nothing else. To implement hysteresis, we need to use
`when`

statements. Consider the following model:

```
model HysteresisControl "A control strategy that doesn't chatter"
type HeatCapacitance=Real(unit="J/K");
type Temperature=Real(unit="K");
type Heat=Real(unit="W");
type Mass=Real(unit="kg");
type HeatTransferCoefficient=Real(unit="W/K");
Boolean heat(start=false) "Indicates whether heater is on";
parameter HeatCapacitance C=1.0;
parameter HeatTransferCoefficient h=2.0;
parameter Heat Qcapacity=25.0;
parameter Temperature Tamb=285;
parameter Temperature Tbar=295;
Temperature T;
Heat Q;
initial equation
T = Tbar+5;
heat = false;
equation
Q = if heat then Qcapacity else 0;
C*der(T) = Q-h*(T-Tamb);
when {T>Tbar+1,T<Tbar-1} then
heat = T<Tbar;
end when;
end HysteresisControl;
```

Examining the `when`

statements, we see that the system only responds
when `T>Tbar+1`

becomes true or `T<Tbar-1`

becomes true. **Note
that nothing happens when these expressions become false**. This is
why an `if`

statement won’t work. With an `if`

statement or
`if`

expression, the behavior changes whenever the conditional
expression changes. But with a `when`

statement, the statements in the
`when`

statement become active **only** when the condition becomes
true. If we simulate this model and look at the temperature, we see
that it stays within the hysteresis band of our desired temperature.

More importantly, if we look at the heat output from the system, we see that, unlike our previous example, some time elapses between the heater turning on and the heater turning off.

The logic for implementing hysteresis can be made slightly more
explicit by using an `algorithm`

section (as previous discussed
during our discussion on speed estimation techniques).

```
model HysteresisControlWithAlgorithms "Control using algorithms"
type HeatCapacitance=Real(unit="J/K");
type Temperature=Real(unit="K");
type Heat=Real(unit="W");
type Mass=Real(unit="kg");
type HeatTransferCoefficient=Real(unit="W/K");
Boolean heat "Indicates whether heater is on";
parameter HeatCapacitance C=1.0;
parameter HeatTransferCoefficient h=2.0;
parameter Heat Qcapacity=25.0;
parameter Temperature Tamb=285;
parameter Temperature Tbar=295;
Temperature T;
Heat Q;
initial equation
T = Tbar+5;
heat = false;
equation
Q = if heat then Qcapacity else 0;
C*der(T) = Q-h*(T-Tamb);
algorithm
when T<Tbar-1 then
heat :=true;
end when;
when T>Tbar+1 then
heat :=false;
end when;
end HysteresisControlWithAlgorithms;
```

Note how the two conditional expressions have been broken into two
separate `when`

statements. This makes it explicitly clear what
causes the heat to be turned on and off. These `when`

statements
were placed in an `algorithm`

section because they both assign to
the same variable, `heat`

.