Skip to content
LIBRARY
Examples.CSTRMPCExample.md

Examples.CSTRMPCExample ​

CSTR concentration control with ACADOSMPC, translated from the DyadControlSystems CSTR tutorial: the concentration of B is driven to 0.6 by the feed and the cooling heat flow with a pure penalty on the control increments (Q2 = 0, Q3 as in the tutorial's difference cost), hard input bounds and soft upper bounds on the reactor and jacket temperatures. The tutorial's collocation transcription, exact Hessian and L1 slack penalty have no counterpart here; acados integrates the model with a 3-stage Gauss-Legendre IRK scheme and the state bounds are quadratically soft. The tutorial's variable scaling corresponds to x_scale and u_scale, which this example leaves at their defaults, since the controller converges without them. Verified in test/test_acados_tutorials.jl.

Usage ​

MPCComponents.Examples.CSTRMPCExample()

Variables ​

NameDescriptionUnits
CbConcentration of B–
TrReactor temperature–
TkJacket temperature–
FFeed–
QdotHeat flow–
flagacados status–

Behavior ​

Behavior of this component cannot be rendered because it includes path variables.

Source ​

dyad
"""
CSTR concentration control with `ACADOSMPC`, translated from the DyadControlSystems CSTR tutorial: the
concentration of B is driven to 0.6 by the feed and the cooling heat flow with a pure penalty on the
control increments (`Q2 = 0`, `Q3` as in the tutorial's difference cost), hard input bounds and soft
upper bounds on the reactor and jacket temperatures. The tutorial's collocation transcription, exact
Hessian and L1 slack penalty have no counterpart here; acados integrates the model with a 3-stage
Gauss-Legendre IRK scheme and the state bounds are quadratically soft. The tutorial's variable scaling
corresponds to `x_scale` and `u_scale`, which this example leaves at their defaults, since the
controller converges without them. Verified in `test/test_acados_tutorials.jl`.
"""
example component CSTRMPCExample
  periodicclock = DiscreteComponents.PeriodicClock(dt = 0.005) {
    "Dyad": {"placement": {"diagram": {"x1": 470, "x2": 570, "y1": 480, "y2": 580}}}
  }
  plant = MPCComponents.Examples.CSTRPlant() {
    "Dyad": {"placement": {"diagram": {"x1": 720, "x2": 820, "y1": 270, "y2": 370}}}
  }
  "Samplers of the four state variables"
  s = [DiscreteComponents.Sampler() for i in 1:4] {
    "Dyad": {"placement": {"diagram": {"x1": 570, "x2": 470, "y1": 720, "y2": 820}}}
  }
  sr = DiscreteComponents.Sampler() {
    "Dyad": {"placement": {"diagram": {"x1": 160, "x2": 260, "y1": 230, "y2": 330}}}
  }
  "Holds of the feed and the heat flow"
  zoh = [DiscreteComponents.ZeroOrderHold() for i in 1:2] {
    "Dyad": {"placement": {"diagram": {"x1": 474, "x2": 574, "y1": 274, "y2": 374}}}
  }
  "Concentration reference for B"
  ref = BlockComponents.Sources.Constant(k = 0.6) {
    "Dyad": {"placement": {"diagram": {"x1": 10, "x2": 110, "y1": 230, "y2": 330}}}
  }
  mpc = MPCComponents.ACADOSMPC(dynamics = plant, inputs = ["F", "Qdot"], state_variables = ["Ca", "Cb", "Tr", "Tk"], outputs = ["Cb"], Ts = 0.005, Np = 30, Q1 = diagonal([1.0]), Q2 = diagonal([0.0, 0.0]), penalize_increments = true, Q3 = diagonal([5e-6, 2.5e-9]), umin = [5.0, -8500.0], umax = [100.0, 0.0], constrained = ["Tr", "Tk"], constrained_max = [142.0, 140.0], integrator = ACADOSIntegrator.IRK(), integrator_stages = 3, u_guess = [10.0, -1000.0]) {
    "Dyad": {"placement": {"diagram": {"x1": 340, "x2": 440, "y1": 311, "y2": 411}}}
  }
  "Concentration of B"
  variable Cb::Real
  "Reactor temperature"
  variable Tr::Real
  "Jacket temperature"
  variable Tk::Real
  "Feed"
  variable F::Real
  "Heat flow"
  variable Qdot::Real
  "acados status"
  variable flag::Real
relations
  Cb = plant.Cb
  Tr = plant.Tr
  Tk = plant.Tk
  F = mpc.u[1]
  Qdot = mpc.u[2]
  flag = mpc.exitflag
  connect(plant.Ca_out, s[1].u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 940, "y": 284}, {"x": 940, "y": 770}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.Cb_out, s[2].u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 309}, {"x": 900, "y": 770}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.Tr_out, s[3].u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 860, "y": 330}, {"x": 860, "y": 770}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.Tk_out, s[4].u) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 825, "y": 770}], "E": 2}], "path": {}}}
  connect(ref.y, sr.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "path": {}}}
  connect(s[1].y, mpc.x[1], periodicclock.y) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 280, "y": 770}, {"x": 280, "y": 361}], "E": 2},
        {"S": 2, "M": [{"x": 335, "y": 530}], "E": 3}
      ],
      "path": {}
    }
  }
  for i in 2:4
    connect(s[i].y, mpc.x[i])
  end
  connect(sr.y, mpc.r[1]) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 320, "y": 280}, {"x": 320, "y": 326}], "E": 2}],
      "path": {}
    }
  }
  for i in 1:2
    connect(mpc.u[i], zoh[i].u)
  end
  connect(zoh[1].y, plant.F)
  connect(zoh[2].y, plant.Qdot)
metadata {"Dyad": {"doc": {"behavior": false}}}
end
Flattened Source
dyad
"""
CSTR concentration control with `ACADOSMPC`, translated from the DyadControlSystems CSTR tutorial: the
concentration of B is driven to 0.6 by the feed and the cooling heat flow with a pure penalty on the
control increments (`Q2 = 0`, `Q3` as in the tutorial's difference cost), hard input bounds and soft
upper bounds on the reactor and jacket temperatures. The tutorial's collocation transcription, exact
Hessian and L1 slack penalty have no counterpart here; acados integrates the model with a 3-stage
Gauss-Legendre IRK scheme and the state bounds are quadratically soft. The tutorial's variable scaling
corresponds to `x_scale` and `u_scale`, which this example leaves at their defaults, since the
controller converges without them. Verified in `test/test_acados_tutorials.jl`.
"""
example component CSTRMPCExample
  periodicclock = DiscreteComponents.PeriodicClock(dt = 0.005) {
    "Dyad": {"placement": {"diagram": {"x1": 470, "x2": 570, "y1": 480, "y2": 580}}}
  }
  plant = MPCComponents.Examples.CSTRPlant() {
    "Dyad": {"placement": {"diagram": {"x1": 720, "x2": 820, "y1": 270, "y2": 370}}}
  }
  "Samplers of the four state variables"
  s = [DiscreteComponents.Sampler() for i in 1:4] {
    "Dyad": {"placement": {"diagram": {"x1": 570, "x2": 470, "y1": 720, "y2": 820}}}
  }
  sr = DiscreteComponents.Sampler() {
    "Dyad": {"placement": {"diagram": {"x1": 160, "x2": 260, "y1": 230, "y2": 330}}}
  }
  "Holds of the feed and the heat flow"
  zoh = [DiscreteComponents.ZeroOrderHold() for i in 1:2] {
    "Dyad": {"placement": {"diagram": {"x1": 474, "x2": 574, "y1": 274, "y2": 374}}}
  }
  "Concentration reference for B"
  ref = BlockComponents.Sources.Constant(k = 0.6) {
    "Dyad": {"placement": {"diagram": {"x1": 10, "x2": 110, "y1": 230, "y2": 330}}}
  }
  mpc = MPCComponents.ACADOSMPC(dynamics = plant, inputs = ["F", "Qdot"], state_variables = ["Ca", "Cb", "Tr", "Tk"], outputs = ["Cb"], Ts = 0.005, Np = 30, Q1 = diagonal([1.0]), Q2 = diagonal([0.0, 0.0]), penalize_increments = true, Q3 = diagonal([5e-6, 2.5e-9]), umin = [5.0, -8500.0], umax = [100.0, 0.0], constrained = ["Tr", "Tk"], constrained_max = [142.0, 140.0], integrator = ACADOSIntegrator.IRK(), integrator_stages = 3, u_guess = [10.0, -1000.0]) {
    "Dyad": {"placement": {"diagram": {"x1": 340, "x2": 440, "y1": 311, "y2": 411}}}
  }
  "Concentration of B"
  variable Cb::Real
  "Reactor temperature"
  variable Tr::Real
  "Jacket temperature"
  variable Tk::Real
  "Feed"
  variable F::Real
  "Heat flow"
  variable Qdot::Real
  "acados status"
  variable flag::Real
relations
  Cb = plant.Cb
  Tr = plant.Tr
  Tk = plant.Tk
  F = mpc.u[1]
  Qdot = mpc.u[2]
  flag = mpc.exitflag
  connect(plant.Ca_out, s[1].u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 940, "y": 284}, {"x": 940, "y": 770}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.Cb_out, s[2].u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 309}, {"x": 900, "y": 770}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.Tr_out, s[3].u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 860, "y": 330}, {"x": 860, "y": 770}], "E": 2}],
      "path": {}
    }
  }
  connect(plant.Tk_out, s[4].u) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 825, "y": 770}], "E": 2}], "path": {}}}
  connect(ref.y, sr.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "path": {}}}
  connect(s[1].y, mpc.x[1], periodicclock.y) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 280, "y": 770}, {"x": 280, "y": 361}], "E": 2},
        {"S": 2, "M": [{"x": 335, "y": 530}], "E": 3}
      ],
      "path": {}
    }
  }
  for i in 2:4
    connect(s[i].y, mpc.x[i])
  end
  connect(sr.y, mpc.r[1]) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 320, "y": 280}, {"x": 320, "y": 326}], "E": 2}],
      "path": {}
    }
  }
  for i in 1:2
    connect(mpc.u[i], zoh[i].u)
  end
  connect(zoh[1].y, plant.F)
  connect(zoh[2].y, plant.Qdot)
metadata {"Dyad": {"doc": {"behavior": false}}}
end


Test Cases ​

No test cases defined.

  • Examples

  • Experiments

  • Analyses