# Surge Tank Control Using Discrete Control Set MPC

This example shows how to use a linear MPC controller with both continuous- and discrete-set control actions to control the level of a surge tank in Simulink®.

### Overview

Many petrochemical processes include surge capacity to insulate downstream operations from upsets in upstream flows. This example considers a liquid surge tank supplied by two pumps.

• Pump 1 is variable-speed and can deliver a flow rate between 0 and 100 L/min. The rate of change of the flow rate is limited to 50 L/min per minute.

• Pump 2 is on-off and delivers 100 L/min when it is on.

This system also has a continuously adjustable valve that regulates the tank discharge to accommodate a downstream process.

```mdl = 'ReservoirMPC'; open_system(mdl) ``` The control objective is to use the two pumps (manipulated variables) to maintain the tank volume at its setpoint when the discharge valve introduces a disturbance to the surge tank (measured disturbance).

When downstream demand is constant, pump 1 controls the surge tank level, ideally keeping it near 50%. When a disturbance occurs, both pumps can go into action to maintain the tank volume between 25% and 75% during the transient time. When downstream demand is high, however, Pump 2 must turn on.

In summary, the MPC controller manages the two pumps such that:

• The tank level stays near 50% when demand is constant.

• The tank level stays within the ideal range when Pump 2 turns on and off. Rapid Pump 2 on-off cycling is undesirable.

### Create Linear Plant from Nonlinear Surge Tank Model

In the Simulink model, the surge tank model is in the Reservoir subsystem. It implements the following equations.

• `dV/dt = Qin - Qout`, where `V` is the tank volume between 0 and 100 (percent)

• `Qin = Q1 + Q2`, the sum of the two pump flow rates (L/min)

• `Qout = 0.2*sqrt(2)*X*sqrt(V)`, the discharge rate (L/min)

• `X`, the discharge valve, which can open between 0 and 100 (percent)

The plant starts running at its nominal steady-state operating point: pump 1 runs at 70 L/min, pump 2 is off, the discharge valve is at 35%, and the tank volume is at 50%. Create a linear model of the tank at this operating point. This model has three inputs: the manipulated variables `Q1` and `Q2`, and the measured disturbance|X|.

```plant = ss(-0.7,[1 1 -2],1,[0 0 0]); plant = setmpcsignals(plant,'MV',[1 2],'MD',3); ```

### Design MPC Controller with Continuous and Discrete Control Actions

Create a linear MPC controller with a sample time of one second, default prediction and control horizons, and default cost function weights.

```Ts = 1; MPCobj = mpc(plant,Ts); ```
```-->The "PredictionHorizon" property is empty. Assuming default 10. -->The "ControlHorizon" property is empty. Assuming default 2. -->The "Weights.ManipulatedVariables" property is empty. Assuming default 0.00000. -->The "Weights.ManipulatedVariablesRate" property is empty. Assuming default 0.10000. -->The "Weights.OutputVariables" property is empty. Assuming default 1.00000. ```

Set the nominal values for the controller to match the steady-state operating point.

```MPCobj.Model.Nominal.U = [70; 0; 35]; MPCobj.Model.Nominal.Y = 50; MPCobj.Model.Nominal.X = 50; MPCobj.Model.Nominal.DX = 0; ```

Choose the `MVRate` weights such that the controller adjusts pump 1 in preference to pump 2. That is, the controller penalizes pump 2 adjustments less than pump 1 adjustments.

```MPCobj.Weights.MVrate = [0.1 0.2]; ```

Specify safety bounds on the continuous input and output signals.

```MPCobj.OV.Min = 0; MPCobj.OV.Max = 100; MPCobj.MV(1).Min = 0; MPCobj.MV(1).Max = 100; MPCobj.MV(1).RateMin = -50; MPCobj.MV(1).RateMax = 50; ```

Since pump 2 has two discrete settings (0 and 100 L/min), specify a discrete set in the `Type` property of this controller. Depending on your application, the `Type` property can also be `binary` or `integer`.

```MPCobj.MV(2).Type = [0 100]; ```

### Simulate Closed-Loop Response with Discharge Disturbance

The simulation begins at the nominal condition. At t = 5, the discharge rate ramps up until pump 1 is at its full capacity and pump 2 must turn on. Pump 2 turns on at t = 12. Pump 1 must then decrease as rapidly as possible to keep the level in bounds, then establish a new steady-state operating point. At t = 60, the discharge begins to ramp down to the nominal state. The MPC controller keeps the volume within the ideal range, and pump 2 does not exhibit rapid cycling.

```sim(mdl) open_system([mdl '/Volume']) ```
```-->Converting model to discrete time. -->Assuming output disturbance added to measured output channel #1 is integrated white noise. -->The "Model.Noise" property is empty. Assuming white noise on each measured output. ans = Simulink.SimulationOutput: tout: [106x1 double] SimulationMetadata: [1x1 Simulink.SimulationMetadata] ErrorMessage: [0x0 char] ``` The following figure shows the flow rates from two pumps.

```open_system([mdl '/Pumps']) ``` `As expected, the MPC controller turns pump 2 on and off.`
```bdclose(mdl) % close simulink model. ```