MIMO DMC that finds the economic optimum and holds it.
A receding-horizon optimizer solves a fresh multivariable QP every control tick, moves your plant toward the economic limits an upstream LP sets, and re-identifies its own process model without ever taking the loop offline.
How the control hierarchy fits together
An economic LP sets targets from current constraints; the edge controller solves a bounded QP every tick and writes only the first move; the OT layer reads back controlled and disturbance variables for the next cycle.
What the controller actually does
Real multivariable optimization at plant tick rate — not a supervisory PID tuner.
A fresh QP every control tick
Each tick solves a box-constrained quadratic program over the full control horizon and applies only the first move — the rest is replanned next tick against the latest measurements, the standard receding-horizon approach.
Hard safety independent of the optimizer
A hard clamp and a heartbeat watchdog sit outside the optimization loop, so a slow or degenerate solve can never push a manipulated variable past its bound.
Re-identifies the process without going offline
Every manipulated variable is dithered with a phase-shifted PRBS sequence and the resulting multivariable model is refit in closed loop — no dedicated step-test window, no lost production.
Full nonlinear extension when the process needs it
The same QP core extends to a full nonlinear program via an augmented Lagrangian method for processes where a linear model isn't a good enough local approximation.
OPC-UA in, OPC-UA out
The same OPC-UA client drives a live plant or a hardware-in-the-loop mock server, so the controller is validated against a realistic plant interface before it ever touches a real one.
ML warm-start, never a bypass
A learned model can seed the optimizer's starting point to converge faster — it never replaces the deterministic QP solve that actually sets the moves.
Live controller-scaling benchmark
The real MIMO DMC control law, timed on this server from a unit loop to a plant-wide network — not example figures.
| Controller size | Decision variables | Solve time | Optimality residual | Status | Run live |
|---|---|---|---|---|---|
| 2 × 4 (unit scale) | 10 | 0.04 ms | 4.55e-16 | Passed | |
| 5 × 10 (process loop) | 25 | 0.04 ms | 4.22e-16 | Passed | |
| 10 × 20 (unit wide) | 100 | 0.41 ms | 8.18e-16 | Passed | |
| 20 × 40 (area wide) | 200 | 11.09 ms | 1.80e-15 | Passed | |
| 50 × 100 (plant wide) | 500 | 59.19 ms | 1.90e-15 | Passed |
Median of 7 repeated solves of the real dmc_move control law, against the 1 s DCS/PLC scan budget — measured on this server, not fabricated.
Scripted from Python
The economic layer that sets the controller's targets, from the flowsim SDK.
from flowsim.sdk import FlowSimClient
client = FlowSimClient()
sim = client.create_simulation("Fractionation area", flowsheet)
client.run(sim["id"])
result = client.optimize(sim["id"], {
"objective": {"kind": "metric", "node": "COL", "name": "reboiler_duty", "sense": "min"},
"decision_vars": [{"node": "COL", "param": "reflux_ratio", "min": 1.5, "max": 4.0}],
}) # the economic optimum the MIMO DMC layer is asked to holdDeploy without a step-testing project
The usual DMC rollout is months of open-loop step tests before a single optimized move. Closed-loop identification collapses that.
Connect the loop
Point the OPC-UA client at your controller tags — manipulated, controlled, and disturbance variables — the same interface used against the mock server in testing.
Identify in closed loop
Dithered PRBS sequences on each manipulated variable let the controller fit its own multivariable model while the plant keeps running — no scheduled step-test downtime.
Turn on the optimizer
The receding-horizon QP starts solving every tick, moving the plant toward the limits the economic LP sets, with the hard clamp and watchdog enforcing bounds independent of the solve.
See it on your own process
Every number on this page comes from a real, converged flowsheet — open the workspace and run one yourself.