Reputation: 45
Use Gekko to fit a numerical ODE solution to data.
Hi everyone! I was wondering, if it is possible to fit coefficients of an ODE using GEKKO. I unsuccessfully tried to replicate the example given here.
This is what I have come up with (but is flawed – and I should perhaps mention that my math skills are unfortunately rather poor):
import numpy as np
from gekko import GEKKO
tspan = [0, 0.1, 0.2, 0.4, 0.8, 1]
Ca_data = [2.0081, 1.5512, 1.1903, 0.7160, 0.2562, 0.1495]
m = GEKKO(remote=False)
t = m.Param(value=tspan)
m.time = t
Ca_m = m.Param(value=Ca_data)
Ca = m.Var()
k = m.FV(value=1.3)
k.STATUS = 1
m.Equation( Ca.dt() == -k * Ca)
m.Obj( ((Ca-Ca_m)**2)/Ca_m )
m.options.IMODE = 2
m.solve(disp=True)
print(k.value[0]) #2.58893455 is the solution
Can someone help me out here? Thank you very much, Martin
(This is my first post here – please be gentle, if I have done something not appropriate.)
Upvotes: 4
Views: 489
Reputation: 14346
Your solution was close but you needed:
Ca
as m.CV()
to use built-in error model instead of m.Var()
and m.Obj
with NODES>=3. Otherwise, the internal nodes of each collocation interval are also matched to the measurements and this gives a slightly wrong answer.EV_TYPE=2
to use a squared error. An absolute value objective EV_TYPE=1
(default) gives a correct but slightly different answer.import numpy as np
from gekko import GEKKO
m = GEKKO(remote=False)
m.time = [0, 0.1, 0.2, 0.4, 0.8, 1]
Ca_data = [2.0081, 1.5512, 1.1903, 0.7160, 0.2562, 0.1495]
Ca = m.CV(value=Ca_data); Ca.FSTATUS = 1 # fit to measurement
k = m.FV(value=1.3); k.STATUS = 1 # adjustable parameter
m.Equation(Ca.dt()== -k * Ca) # differential equation
m.options.IMODE = 5 # dynamic estimation
m.options.NODES = 5 # collocation nodes
m.options.EV_TYPE = 2 # squared error
m.solve(disp=True) # display solver output
print(k.value[0]) # 2.58893455 is the curve_fit solution
The solution is k=2.5889717102
. A plot shows the match to the measured values.
import matplotlib.pyplot as plt # plot solution
plt.plot(m.time,Ca_data,'ro')
plt.plot(m.time,Ca.value,'bx')
plt.show()
There are additional tutorials and course material on parameter estimation with differential and algebraic equation models.
Upvotes: 1