3

To simulate the dead-time in the FOPDT model using the GEKKO package, I used the Gekko 'cspline' function to make the time-shifting operation smoother.
It works well when the input changes after the length of dead-time. (eg. The input changes at t=15 when dead-time=10)
enter image description here

However, when the input changes before the length of dead-time (eg. The input changes at t=5 when dead-time=10), it looks like the cspline function overly extrapolates the input value. Please give some suggestions to avoid this problem.
enter image description here

from gekko import GEKKO
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

tf = 50 
npt = 51 
t = np.linspace(0,tf,npt)
u1 = np.zeros(npt)
u1[5:] = 5

m = GEKKO(remote=True)
m.time = t 
time = m.Var(0)
m.Equation(time.dt()==1)

K1 = m.FV(1,lb=0,ub=1);      K1.STATUS=1
tau1 = m.FV(5, lb=1,ub=300);  tau1.STATUS=1
theta1 = m.FV(10, lb=2,ub=30); theta1.STATUS=1

uc1 = m.Var(u1) 
tc1 = m.Var(t) 
m.Equation(tc1==time-theta1)
m.cspline(tc1,uc1,t,u1,bound_x=False)

yp1 = m.Var()
m.Equation(yp1.dt() == -yp1/tau1 + K1*uc1/tau1) 

m.options.IMODE=4
m.solve()

print('K1: ', K1.value[0])
print('tau1: ',  tau1.value[0])
print('theta1: ', theta1.value[0])
print('')

plt.figure()
plt.subplot(2,1,1)
plt.plot(t,u1)
plt.legend([r'u1'])
plt.ylabel('Input')
plt.subplot(2,1,2)
plt.plot(t,yp1)
plt.legend([r'y1'])
plt.ylabel('Output')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()
Junho Park
  • 997
  • 4
  • 12
  • If the dead-time is static then I recommend a discrete state space form instead. This is implemented as `m.delay()` in Gekko. Here are more details: https://apmonitor.com/wiki/index.php/Apps/TimeDelay and https://apmonitor.com/wiki/index.php/Apps/DiscreteStateSpace – John Hedengren Dec 12 '20 at 15:05

1 Answers1

1

The cspline object is given data for the range t=0 to t=50 but it accesses values for t=-10 to t=40. The error is because of extrapolation from the cubic spline. You can generate spline data in the range t=-theta_ub to t=50 to avoid extrapolation problems.

Cspline extrapolation

from gekko import GEKKO
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

theta_ub = 30
tf = 50

m = GEKKO(remote=True)
m.time = np.linspace(0,tf,tf+1)
time = m.Param(m.time)

K1 = m.FV(1,lb=0,ub=1)
tau1 = m.FV(5,lb=1,ub=300)
theta1 = m.FV(10,lb=2,ub=theta_ub)

u_step = [0 if ti<=5 else 5 for ti in m.time]
uc1 = m.Var() 
tc1 = m.Var()
m.Equation(tc1==time-theta1)

# for cspline
t1 = np.linspace(-theta_ub,tf,500)
u1 = [0 if ti<=5 else 5 for ti in t1]
m.cspline(tc1,uc1,t1,u1,bound_x=False)

yp1 = m.Var()
m.Equation(tau1*yp1.dt()+yp1==K1*uc1) 

m.options.IMODE=4
m.solve()

print('K1: ', K1.value[0])
print('tau1: ',  tau1.value[0])
print('theta1: ', theta1.value[0])
print('')

plt.figure()
plt.subplot(2,1,1)
plt.plot(t1,u1,label='Unshifted Input')
plt.plot(m.time,uc1,label='Shifted Spline')
plt.xlim([0,tf])
plt.legend()
plt.ylabel('Input')
plt.subplot(2,1,2)
plt.plot(m.time,yp1)
plt.legend([r'y1'])
plt.ylabel('Output')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()
John Hedengren
  • 12,068
  • 1
  • 21
  • 25