An Industrial Application: Controlling the Drum Boiler

Design and analysis of a control system for the drum boiler illustrates a practical application of concepts presented in Advanced Numerical Methods. First, the stability of the model is investigated by computing its poles and time-domain responses. After verifying the controllability of the model, a family of LQR controllers is designed. The characteristics of each LQR controller are plotted to identify the controller that provides a good compromise between improving the damping factor of the model and the size of the feedback gains. Next a controller is designed via the feedback stabilization method using as guidelines the closed-loop poles of the already-designed LQR controller. A state estimator is then constructed and the estimated states are used to implement the controller.

The State-Space Model of a Drum Boiler

Make sure the application is loaded.

<< NumericalControlMethods`

Load the collection of test examples.

<< NumericalControlMethods`Examples`

This state-space model of a drum boiler has a maximum steam flow of about 350 t/h and a drum pressure of 140 bar around an operating point of 90% full load.

ss = DrumBoiler[]

The states of the system represent, respectively, the drum pressure (bar), the drum liquid level (m), the drum liquid temperature (degrees Celsius), the riser wall temperature (degrees Celsius), and the steam quality (percent). The inputs are the heat flow to the risers (kJ/s) and the feedwater flow (kg/s). The measured quantities (output of the system) are the drum pressure (bar) and the drum liquid level (m).

System Responses, Stability, and Poles

Start with a quick review of the system’s time-domain behaviors. First the open-loop poles of the system are computed.

These are the open-loop poles of the system.

poles = 
      Eigenvalues[ss[[1]]]

This is a measure of the damping factor of the system.

Max[Re[poles]]

The system is marginally stable with damping factor α = 0. Therefore, the input disturbances would not necessarily decay and, at resonance, the output response may become unbounded. This is verified by computing the time responses.

Oscillations in the heat flow to the risers near the nominal value are used to compute the output responses of the open-loop system that is initially at rest. The oscillation frequency corresponds to one of the stable poles.

u0 = {Sin[Im[poles[[3]]] t], 
        0}

These are the resulting variations in the drum pressure (solid line) and in the drum liquid level (dashed line). Note that the disturbances do not decay over time.

SimulationPlot[ss, u0, {t, 1000}, 
        PlotStyle -> {Thickness[ .001], Dashing[{ .015}]}];

The resonance occurs when the system is excited with a signal whose frequency corresponds to the marginally stable eigenvalue, which in the system is λ = 0. Therefore, it has no imaginary part and the resonance frequency is 0 (a constant disturbance).

This adds a constant 0.01 kg/s disturbance to the feedwater flow in the previous input signal.

u = u0 + {0, 0.01};

The system resonates and the drum liquid level grows without a bound.

SimulationPlot[ss, u, {t, 1000}, 
        PlotStyle -> {Thickness[ .001], Dashing[{ .015}]}, 
        PlotRange -> All];

Obviously, such behavior of the open-loop system is undesirable and needs to be improved by a proper control loop.

Testing the Controllability

To design a feedback controller, the controllability of the system is explored using the function ControllerHessenbergForm.

This is the controller-Hessenberg form of the system.

NumberForm[ControllerHessenbergForm[ss], 3]

The system is controllable with the tolerance (10^(-4)).

Controllable[ss, 
      ControllabilityTest -> FullRankControllerHessenbergBlocks, 
      Tolerance -> (10^(-4))]

The system, however, is not controllable if a greater tolerance must be attained.

Controllable[ss, 
      ControllabilityTest -> FullRankControllerHessenbergBlocks, 
      Tolerance -> (10^(-3))]

In general, a system is uncontrollable with tolerance tol if there exists a perturbation with a norm less than or equal to tol that makes the perturbed system uncontrollable. Larger feedback gains are necessary to stabilize a controllable system that is close to an uncontrollable state. In the example, the system becomes uncontrollable for relatively small tolerances somewhere between (10^(-3)) and (10^(-4)).

The Design of the LQR Controller

Since the damping of the open-loop system is low, a controller that increases the damping of the system is needed. With Advanced Numerical Methods, the feedback controller can be designed using several different approaches, such as solving the LQR problem, using constrained feedback stabilization, or implementing the pole assignment approach. This section illustrates the LQR design. For the experiment, Q is a symmetrical matrix constructed from the output matrix of the system and R is an identity matrix multiplied by a scalar coefficient ρ. Evaluation of how different choices of the coefficient ρ affect the performance of the closed-loop system completes the process.

These are the weighting matrices needed for the LQR design.

q = 
      Transpose[ss[[3]]] . 
        ss[[3]]

r = ρ IdentityMatrix[CountInputs[ss]]

The LQR gains with control weight ρ range from ρ = (10^(-6)) (cheap control) to ρ = (10^2) (minimum energy control). The underlying Riccati equation is solved using Newton method.

rhos = Table[(10^i), {i, -6, 2, 0.5}];

lqcontrollers = (LQRegulatorGains[ss, q, 
                r /. ρ -> #1, 
                SolveMethod -> Newton] &) /@ rhos;

This displays the poles of the closed-loop system with varying ρ.

Block[{$DisplayFunction = Identity, 
            len = Length[lqcontrollers]}, 
Table[
            ListPlot[
{Re[#], Im[#]} & /@ 
                Flatten[
                  Eigenvalues[
                    ss[[1]] - 
                      ss[[2]] . 
                        lqcontrollers[[
                          r]]]], 
PlotStyle -> {PointSize[0.02], Hue[r/len]}, 
              AxesLabel -> {TraditionalForm[σ], 
                  TraditionalForm[j ω]}, 
              PlotRange -> {{-0.28, 0.01}, 
                  Automatic}
], {r, 
              len}]
] // Show;

Make sure LogLinearListPlot is available.

<< Graphics`Graphics`

Varying ρ changes the damping factor of the closed-loop system. Increasing ρ improves the stability of the closed-loop system. However, changes in the damping factor are not significant when ρ is either very low or very high.

\(\(LogLinearListPlot[
        Transpose[{rhos, \((Max[
                    Re[Eigenvalues[
                        ss[[1]] - 
                          ss[[2]] . #1]]] &)\) /@ lqcontrollers}], 
        AxesLabel -> {"ρ", "α(ρ)"}, 
        PlotJoined -> True, Frame -> True];\)\)

This graph shows how varying ρ changes the norm of the feedback gain matrix. The LQR gains are high when ρ is small.

\(\(LogLogListPlot[
        Transpose[{rhos, \((MatrixNorm[#1, 2] &)\) /@ lqcontrollers}], 
        AxesLabel -> {"ρ", \*""\[LeftDoubleBracketingBar]k(ρ)(Subscript[\[RightDoubleBracketingBar], 2])""}, 
        PlotJoined -> True];\)\)

These are the closed-loop system output responses for various feedback matrices. For convenience, the original open-loop system is represented as a closed-loop system with a dummy (zero) feedback.

responses = (OutputResponse[StateFeedbackConnect[ss, #1], 
                u, {t, 1000}] &) /@ 
          Append[lqcontrollers, 
            Table[0, {CountInputs[ss]}, {CountStates[ss]}]];

In the following plots, the closed-loop responses are represented by colored graphs and the open-loop responses are represented by thick black graphs.

len = Length[lqcontrollers];

pstyles = 
        Append[Table[Hue[c/len], {c, 1, len}], 
          Thickness[0.008]];

These are the output responses of the original and closed-loop systems. From the spectrum, the designer can choose a feedback that brings about suitable values of the drum pressure and the drum liquid level.

Plot[Evaluate[First /@ responses], {t, 0, 1000}, 
        PlotRange -> All, PlotStyle -> pstyles, 
        PlotLabel -> "Drum Pressure"];

Plot[Evaluate[Last /@ responses], {t, 0, 1000}, 
        PlotRange -> All, PlotStyle -> pstyles, 
        PlotLabel -> "Drum Liquid Level"];

The Controller Design Using Constrained Feedback Stabilization

Selected for further experiments is a controller in the middle of the list lqcontrollers that adequately improves the damping factor and yet avoids extremely large feedback gains. In effect, this choice provides a reasonable compromise between the settling time of the system and the sensitivity of the feedback to the noise.

This selects the controller in the middle of the list.

klqr = 
      lqcontrollers[[
        Floor[Length[rhos]/2]]]

This is a norm of the feedback gains.

MatrixNorm[klqr]

A measure of the noise sensitivity of the feedback is computed.

MatrixNorm[klqr]*
      MatrixConditionNumber[
        Eigenvectors[
          ss[[1]] - 
            ss[[2]] . klqr]]

These are the closed-loop poles for the selected feedback matrix.

clplqr = 
      Eigenvalues[
        ss[[1]] - 
          ss[[2]] . klqr]

This is a measure of the damping factor of the closed-loop system.

Max[Re[%]]

This finds a state feedback controller such that the closed-loop system will have the same damping factor as the system obtained by the LQR design.

k = 
      StateFeedbackGains[ss, DampingFactorRegion[%], 
        Method -> PartialLyapunovShift]

This feedback gain norm is smaller than the one provided by the LQR design with a comparable damping factor.

MatrixNorm[k]

The sensitivity of the feedback is also smaller.

MatrixNorm[k]*
      MatrixConditionNumber[
        Eigenvectors[
          ss[[1]] - 
            ss[[2]] . k]]

Here are the closed-loop poles with the computed feedback.

clp = 
      Eigenvalues[
        ss[[1]] - 
          ss[[2]] . k]

The Observer Design

Any feedback design requires knowledge of state variables. Thus it is necessary to estimate the state variables (design an observer) using the inputs, measured outputs, and the system matrices. The first step in designing an observer is to determine whether the system is observable. This is accomplished by using the function ObserverHessenbergForm.

This is the observer-Hessenberg form of the system.

ObserverHessenbergForm[ss]

Since the superdiagonal blocks of the observer-Hessenberg form are nonsingular, the system is observable.

Observable[ss, 
      ObservabilityTest -> FullRankObserverHessenbergBlocks, 
      Tolerance -> (10^(-3))]

The first two outputs of the system permit direct measurement of two state variables in the system. Thus a reduced-order state estimator of order 3 is constructed. The state estimator poles are chosen in such a way that the state estimator performance is no worse than that of the closed-loop system with feedback obtained earlier.

This chooses the poles of the state estimator.

observerpoles = {-0.06, -0.05, -0.011};

The reduced-order state estimator of order 3 is constructed using the block version of the recursive bidiagonal scheme.

observer = 
        ReducedOrderEstimator[ss, observerpoles, 
          Method -> RecursiveBlockBidiagonal];

NumberForm[Chop[observer], 3]

The observer is connected to the system. An implementation of the general approach, shown in the figure below, includes a dummy identity block I that allows construction of the closed-loop system using only the elementary interconnecting functions.

The system has two inputs.

p = CountInputs[ss]

This connects the all-pass block in parallel to the system ss.

ss1  =  
      ParallelConnect[TransferFunction[IdentityMatrix[p]], ss, 
        Table[{i, i}, {i, p}], {}]

The controller consists of the serially connected observer and the feedback gains block.

controller  =  
        SeriesConnect[observer, TransferFunction[k]];

NumberForm[%, 3]

This closes the feedback loop and deletes the outputs of the dummy system.

css = 
        DeleteSubsystem[FeedbackConnect[ss1, controller], {}, 
          Range[p]];

The eigenvalues of the combined system are the union of the eigenvalues of the closed-loop system and the state estimator. This property is known as separation property.

The separation property is verified.

Sort[Eigenvalues[css[[1]]]] - 
        Sort[Join[
            Eigenvalues[
              ss[[1]] - 
                ss[[2]] . k], 
            Eigenvalues[
              observer[[1]]]]]  //  
      Chop

Finally, compare the performance of closed-loop systems that use exact and approximated knowledge of the state variables. The approximation is obtained by the reduced-order state estimator.

This is the Bode plot for the second input of the closed-loop systems. The exact and reduced-order designs are represented as solid and dashed lines, correspondingly. The systems possess comparable frequency responses.

DisplayTogetherGraphicsArray[
        BodePlot[Subsystem[StateFeedbackConnect[ss, k], {2}]], 
        BodePlot[Subsystem[css, {2}], 
          PlotStyle -> {{Dashing[{ .02}]}, {Dashing[{ .01,  .025}], 
                Thickness[ .01]}}]];

This chooses the random initial conditions.

x0 = Table[Random[], {CountStates[ss]}];

These are the output responses of the open-loop system for the input signal and the above initial conditions.

SimulationPlot[ss, u, {t, 500}, InitialConditions -> x0, 
        PlotRange -> All];

These are the output responses of the closed-loop system with the exact (solid lines) and reduced-order state estimator (dashed lines) control law designs.

DisplayTogether[
        SimulationPlot[StateFeedbackConnect[ss, k], u, {t, 500}, 
          InitialConditions -> x0, PlotRange -> All], 
        SimulationPlot[css, u, {t, 500}, 
          InitialConditions -> 
            Join[x0, Table[0, {CountStates[observer]}]], 
          PlotRange -> All, 
          PlotStyle -> {{Dashing[{ .02}]}, {Dashing[{ .01,  .025}]}}]];

These plots show that the responses obtained by using exact states and estimated states match closely as time increases (that is, as t approaches infinity).