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)
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.
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()
The cspline object is given data for the range
t=0
tot=50
but it accesses values fort=-10
tot=40
. The error is because of extrapolation from the cubic spline. You can generate spline data in the ranget=-theta_ub
tot=50
to avoid extrapolation problems.