Double Tank Switched System

Main.DoubleTank History

Hide minor edits - Show changes to output

March 29, 2023, at 07:31 PM by 10.37.206.234 -
Changed lines 77-78 from:
(:toggle hide solution button show="Double Tank Source":)
(:div id=solution:)
to:
(:toggle hide solution2 button show="Double Tank Source":)
(:div id=solution2:)
March 29, 2023, at 06:47 PM by 10.35.117.248 -
Changed lines 5-6 from:
%width=550px%Attach:double_tank.png
to:
(:html:)
<iframe width="560" height="315" src="https://www
.youtube.com/embed/B3czMBhUrN4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
(:htmlend:)

Added lines 130-131:

%width=550px%Attach:double_tank.png
March 29, 2023, at 05:47 PM by 10.35.117.248 -
Changed line 71 from:
The tight set point track leads to valve chatter as small adjustments are made to keep the level at the constant value. This has several potential negative consequences including wearing out the valve with excessive travel and frequent upstream disturbances in pressure and flow. For surge tanks, a more common approach is to keep the level within a specified range such as 2.8 to 3.2. An [[https://apmonitor.com/do/index.php/Main/ControllerObjective|l1-norm objective]] is implemented with the dead-band region to avoid valve chatter and inlet flow fluctuations.
to:
The tight set point track leads to valve chatter as small adjustments are made to keep the level at the constant value. This has several potential negative consequences including wearing out the valve with excessive travel and frequent upstream disturbances in pressure and flow. For surge tanks, a more common approach is to keep the level within a specified range such as 2.8 to 3.2. An [[https://apmonitor.com/do/index.php/Main/ControllerObjective|l1-norm objective]] is implemented with the dead-band region to avoid valve chatter and inlet flow fluctuations. The simulation is extended to 50 minutes to observe the dead-band tracking.
March 29, 2023, at 05:46 PM by 10.35.117.248 -
Added lines 65-122:
plt.grid(); plt.legend(); plt.tight_layout()
plt.savefig('double_tank.png',dpi=300)
plt.show()
(:sourceend:)
(:divend:)

The tight set point track leads to valve chatter as small adjustments are made to keep the level at the constant value. This has several potential negative consequences including wearing out the valve with excessive travel and frequent upstream disturbances in pressure and flow. For surge tanks, a more common approach is to keep the level within a specified range such as 2.8 to 3.2. An [[https://apmonitor.com/do/index.php/Main/ControllerObjective|l1-norm objective]] is implemented with the dead-band region to avoid valve chatter and inlet flow fluctuations.

%width=550px%Attach:double_tank_solution2.png

(:toggle hide solution button show="Double Tank Source":)
(:div id=solution:)
(:source lang=python:)
import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO

m = GEKKO(remote=True)

# Add 0.01 as first step
m.time = np.insert(np.linspace(0,50,101),1,0.01)

# change solver options
m.solver_options = ['minlp_gap_tol 0.001',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 100',\
                    'minlp_branch_method 1',\
                    'minlp_integer_tol 0.001',\
                    'minlp_integer_leaves 0',\
                    'minlp_maximum_iterations 200']

SP = 3

last = m.Param(np.zeros(102))
last.value[-1] = 1

sigma=m.MV(value=1,lb=1,ub=2,integer=True)
sigma.STATUS = 1; sigma.DCOST=1e-5
x1 = m.Var(value=2)
x2 = m.CV(value=2); x2.STATUS=1
x2.SPLO = SP-0.2; x2.SPHI = SP+0.2

m.Equations([x1.dt() == sigma - m.sqrt(x1),\
            x2.dt() == m.sqrt(x1) - m.sqrt(x2)])

m.options.IMODE = 6
m.options.NODES = 2
m.options.SOLVER = 1
m.options.MV_TYPE = 0
m.solve()

plt.figure(1)
plt.step(m.time,sigma.value,'r-',label=r'$\sigma$ (1/2)')
plt.plot(m.time,x1.value,'k-',label=r'$x_1$')
plt.plot([0,m.time[-1]],[x2.SPHI,x2.SPHI],'b:',label=r'$SP_{HI}$')
plt.plot(m.time,x2.value,'g-',label=r'$x_2$')
plt.plot([0,m.time[-1]],[x2.SPLO,x2.SPLO],'b:',label=r'$SP_{LO}$')
plt.xlabel('Time'); plt.ylabel('Levels')
March 29, 2023, at 05:21 PM by 10.35.117.248 -
Changed lines 9-12 from:
{$\begin{aligned}\min_\sigma \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, \text{dt} \\ \text{subject to} \quad & \frac{dx_1}{dt} = c_{\sigma(t)}-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}

The parameters are {`k_1=2`}, {`k_2=3`}, {`c_1=1`}, and {`c_2=2`}. The two states ''x'' are the fluid levels in the upper and a lower tank. The flow into the upper tank is either {`c_1`} or {`c_2`}, the upper tank flows into the lower tank, and the lower tank flow exits the system. The objective of the optimal control problem is for the lower tank to reach the setpoint {`k_2`} during the optimization window of 10 time units.
to:
{$\begin{aligned}\min_\sigma \quad & \int_{0}^{T} (x_2-SP)^2 \, \text{dt} \\ \text{subject to} \quad & \frac{dx_1}{dt} = \sigma(t)-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}

The set point is {`SP=3`}. The two states ''x'' are the fluid levels in the upper and a lower tank. The flow into the upper tank is either 1 or 2, the upper tank flows into the lower tank, and the lower tank flow exits the system. The objective of the optimal control problem is for the lower tank to reach the setpoint {`SP`} during the optimization window of 10 minutes.
Changed lines 37-39 from:
k1 = 2
k2
= 3
to:
SP = 3
Changed line 52 from:
             x3 == m.integral(k1*(x2-k2)**2)])
to:
             x3 == m.integral((x2-SP)**2)])
March 26, 2023, at 02:48 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{aligned}\text{minimize} \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, \text{dt} \\ \text{subject to} \quad & \frac{dx_1}{dt} = c_{\sigma(t)}-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
to:
{$\begin{aligned}\min_\sigma \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, \text{dt} \\ \text{subject to} \quad & \frac{dx_1}{dt} = c_{\sigma(t)}-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
March 26, 2023, at 02:47 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{aligned}\text{minimize} \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, dt \\ \text{subject to} \quad & \frac{dx_1}{dt} = c_{\sigma(t)}-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
to:
{$\begin{aligned}\text{minimize} \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, \text{dt} \\ \text{subject to} \quad & \frac{dx_1}{dt} = c_{\sigma(t)}-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
March 26, 2023, at 02:46 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{aligned}\text{minimize} \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, dt \\ \text{subject to} \quad & \dot{x}_1 = c_{\sigma(t)}-\sqrt{x_1} \\ & \dot{x}_2 = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
to:
{$\begin{aligned}\text{minimize} \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, dt \\ \text{subject to} \quad & \frac{dx_1}{dt} = c_{\sigma(t)}-\sqrt{x_1} \\ & \frac{dx_2}{dt} = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
March 26, 2023, at 02:44 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{array}{lll} \min_{\sigma} &  \int_{0}^{T} & k_1(x_2-k_2)^2  dt\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\&  x(0) & = (2,2)^T \\ \sigma(t) & \in \{1,2\} \quad & \textrm{for} t \in[0,T] \end{array}$}
to:
{$\begin{aligned}\text{minimize} \quad & \int_{0}^{T} k_1(x_2-k_2)^2 \, dt \\ \text{subject to} \quad & \dot{x}_1 = c_{\sigma(t)}-\sqrt{x_1} \\ & \dot{x}_2 = \sqrt{x_1}-\sqrt{x_2} \\ & x(0) = \begin{pmatrix} 2 \\ 2 \end{pmatrix} \\ & \sigma(t) \in \{1,2\} \quad \text{for } t \in [0,T] \end{aligned}$}
March 26, 2023, at 02:43 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{array}{lll} \min_{\sigma} &  \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \quad &\text{for } t\in[0,T]\\ \end{array}$}
to:
{$\begin{array}{lll} \min_{\sigma} &  \int_{0}^{T} & k_1(x_2-k_2)^2  dt\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \quad & \textrm{for} t \in[0,T] \end{array}$}
March 26, 2023, at 02:40 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{array}{llll} \min_{\sigma} &  \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \quad &\text{for } t\in[0,T]\\ \end{array}$}
to:
{$\begin{array}{lll} \min_{\sigma} &  \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \quad &\text{for } t\in[0,T]\\ \end{array}$}
March 26, 2023, at 02:39 AM by 136.36.4.38 -
Changed line 9 from:
{$\begin{array}{llll} \min_{\sigma} & \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \qquad &\text{for } t\in[0,T]\\ \end{array}$}
to:
{$\begin{array}{llll} \min_{\sigma} &  \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \quad &\text{for } t\in[0,T]\\ \end{array}$}
March 26, 2023, at 02:37 AM by 136.36.4.38 -
Changed line 9 from:
{$ \begin{array}{llll} \min_{\sigma} &  \displaystyle \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \qquad &\text{for } t\in[0,T]\\ \end{array} $}
to:
{$\begin{array}{llll} \min_{\sigma} & \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \qquad &\text{for } t\in[0,T]\\ \end{array}$}
March 26, 2023, at 02:36 AM by 136.36.4.38 -
Added lines 1-80:
(:title Double Tank Switched System:)
(:keywords optimization, switched system, binary, optimal control, benchmark, nonlinear control, dynamic optimization, engineering optimization, Python, GEKKO, differential, algebraic, modeling language:)
(:description Double tank switched system solved with Python Gekko.:)

%width=550px%Attach:double_tank.png

A double tank is an example of a switching system where the input to the upper tank can be one of two flows. The upper tank drains to the lower tank and the lower tank drains to a reservoir. The flow to the upper tank is the manipulated variable to meet a lower tank target level. A higher upper tank level leads to a higher flowrate into the lower tank. The dynamics of the two levels are described by two differential equations.

{$ \begin{array}{llll} \min_{\sigma} &  \displaystyle \int_{0}^{T} & k_1(x_2-k_2)^2  \; \text{d}t\\ \mbox{s.t.} &  \dot{x}_1 & = c_{\sigma(t)}-\sqrt{x_1} \\ &  \dot{x}_2 & = \sqrt{x_1}-\sqrt{x_2} \\[  &  x(0) & = (2,2)^T \\ &  \sigma(t) & \in \{1,2\} \qquad &\text{for } t\in[0,T]\\ \end{array} $}

The parameters are {`k_1=2`}, {`k_2=3`}, {`c_1=1`}, and {`c_2=2`}. The two states ''x'' are the fluid levels in the upper and a lower tank. The flow into the upper tank is either {`c_1`} or {`c_2`}, the upper tank flows into the lower tank, and the lower tank flow exits the system. The objective of the optimal control problem is for the lower tank to reach the setpoint {`k_2`} during the optimization window of 10 time units.

%width=550px%Attach:double_tank_solution.png

(:toggle hide solution button show="Double Tank Source":)
(:div id=solution:)
(:source lang=python:)
import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO

m = GEKKO(remote=False)

# Add 0.01 as first step
# 0,0.01,0.1,0.2,0.3,...9.9,10.0)
m.time = np.insert(np.linspace(0,10,201),1,0.01)

# change solver options
m.solver_options = ['minlp_gap_tol 0.001',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 100',\
                    'minlp_branch_method 1',\
                    'minlp_integer_tol 0.001',\
                    'minlp_integer_leaves 0',\
                    'minlp_maximum_iterations 200']

k1 = 2
k2 = 3

last = m.Param(np.zeros(202))
last.value[-1] = 1

sigma=m.MV(value=1,lb=1,ub=2,integer=True)
sigma.STATUS = 1
x1 = m.Var(value=2)
x2 = m.Var(value=2)
x3 = m.Var(value=0)

m.Minimize(last*x3)

m.Equations([x1.dt() == sigma - m.sqrt(x1),\
            x2.dt() == m.sqrt(x1) - m.sqrt(x2),\
            x3 == m.integral(k1*(x2-k2)**2)])

m.options.IMODE = 6
m.options.NODES = 3
m.options.SOLVER = 1
m.options.MV_TYPE = 0
m.solve()

plt.figure(1)
plt.step(m.time,sigma.value,'r-',label=r'$\sigma$ (1/2)')
plt.plot(m.time,x1.value,'k-',label=r'$x_1$')
plt.plot(m.time,x2.value,'g-',label=r'$x_2$')
plt.xlabel('Time'); plt.ylabel('Values')
plt.grid(); plt.legend(); plt.tight_layout()
plt.savefig('double_tank.png',dpi=300)
plt.show()
(:sourceend:)
(:divend:)

----

%width=200px%Attach:gekko.png

The [[https://gekko.readthedocs.io/en/latest/|Gekko Optimization Suite]] is a machine learning and optimization package in Python for mixed-integer and differential algebraic equations.

📄 [[https://apmonitor.com/wiki/index.php/Main/APMonitorReferences|Gekko Publication and References]]

The GEKKO package is available in Python with '''pip install gekko'''. There are [[https://apmonitor.com/wiki/index.php/Main/GekkoPythonOptimization|additional example problems]] for equation solving, optimization, regression, dynamic simulation, model predictive control, and machine learning.