J'essaie d'estimer 4 paramètres (kdoc1, kdoc2, S1, S2), en utilisant GEKKO pour résoudre un système d'équations algébriques ordinaires, minimisant la somme des carrés de l'erreur résiduelle entre les valeurs observées et prédites. Je n'obtiens pas un bon ajustement entre les données mesurées et les données prédites, avez-vous une suggestion sur ce que je fais mal dans le code ?
En outre, j'essaie également d'ajouter un autre ensemble de données de mesure. Je veux que le modèle fasse l'estimation des paramètres en utilisant deux ensembles de données mesurées, je dois minimiser la somme des résidus en utilisant les deux ensembles de données. Avez-vous une idée sur la façon de le faire dans le code ?
J'ai déjà ajouté des points supplémentaires pour aider le solveur à converger en utilisant la suggestion suivante python - Mesures peu fréquentes dans Gekko avec des points de simulation supplémentaires - Stack Overflow
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
import math as math
import pandas as pd
#TOC=5.93 mg/L
#M2 C1 5mg/L
#time: [0,0.08333,0.5,1,4,22.61667]; C2 measured: [0,9.33e-5,8.55e-5,8.55e-5,7.77e-5,7.00e-5]
#M4 C1 20mg/l
#time: [0,0.08333,0.5,1,4,22.61667]; C2 measured: [0,2.92e-4,2.72e-4,2.92e-4,2.72e-4,2.14e-4]
#measurements
t_data = [0.08333,0.5,1,4,22.61667]
x_data = [9.33e-5,8.55e-5,8.55e-5,7.77e-5,7.00e-5]
#x_data2 = [2.92e-4,2.72e-4,2.92e-4,2.72e-4,2.14e-4]
df1 = pd.DataFrame({'time':t_data,'x':x_data})
df1.set_index('time', inplace=True)
# simulation time points
df2 = pd.DataFrame({'time':np.linspace(0,25,51)}) #(0,25,51)
df2.set_index('time', inplace=True)
# merge dataframes
df = df2.join(df1,how='outer')
# get True (1) or False (0) for measurement
df['meas'] = (df['x'].values==df['x'].values).astype(int)
# replace NaN with zeros
df0 = df.fillna(value=0)
#Estimator Model
m = GEKKO()
m.time = df.index.values
# adjustable parameters
kdoc1 = m.FV() #m-1h-1
kdoc2 = m.FV() #m-1h-1
S1 = m.FV()
S2 = m.FV()
#State variables
# M (mol/L)
C0 = m.Var(value=8.00e-5)
C1 = m.Var(value=1.36e-3)
C2 = m.Var(value=x_data[0])
C2m = m.Param(df0['x'].values)
meas = m.Param(df0['meas'].values)
m.Minimize(meas*(C2-C2m)**2)
C3 = m.Var(value=0)
C4 = m.Var(value=3.16e-8)
C5 = m.Var(value=3.83e-7)
C6 = m.Var(value=0)
C7 = m.Var(value=0)
C8 = m.Var(value=0)
C9 = m.Var(value=0)
C10 = m.Var(value=0)
C11 = m.Var(value=0)
C12 = m.Var(value=3.21e-3)
TOC = m.Var(value=5.93)#mg-C/L
cC1 = m.Var(value=0)
cC2 = m.Var(value=0)
#temperature ºC
T = 20
#Rate constants
k1 = 2040000000*math.exp(-1887/(273.15+T))*3600
k2 = 138000000*math.exp(-8800/(273.15+T))*3600
k3 = 300000*math.exp(-2010/(273.15+T))*3600
k4 = 0.00000065*3600
k6 = 26700*3600
k7 = 167*3600
k8 = 27700*3600
k9 = 8300*3600
k10 = 0
k5 = 37800000000*math.exp(-2169/(273.15+T))*C4+2.52e25*math.exp(-16860/(273.15+T))*C10+0.87*math.exp(-503/(273.15+T))*C9
r1 = k1 * C0 * C1
r2 = k2 * C2
r3 = k3 * C0 * C2
r4 = k4 * C3
r5 = k5 * C2 * C2
r6 = k6 * C3 * C1* C4
r7 = k7 * C3 * C5
r8 = k8 * C6 * C3
r9 = k9 * C6 * C2
r10 = k10 * C2 * C3
r11 = kdoc1*S1*TOC*C2/12000
r12 = kdoc2*S2*TOC*C0/12000
t = m.Param(value=m.time)
m.Equation(C0.dt()== -r1 + r2 - r3 + r4 + r8 - r12)
m.Equation(C1.dt()== -r1 + r2 + r5 - r6 + r11)
m.Equation(C2.dt()== r1 - r2 - r3 + r4 - r5 + r6 - r9 - r10 - r11)
m.Equation(C3.dt()== r3 - r4 + r5 - r6 - r7 - r8 - r10)
m.Equation(C4.dt()== 0)
m.Equation(C5 == 1e-14/C4)
m.Equation(C6.dt()== r7 - r8 - r9)
m.Equation(C7 == (3.16e-8*C0)/C4)
m.Equation(C1 == (5.01e-10*C8)/C4)
m.Equation(C11 == (5.01e-11*C10)/C4)
m.Equation(C9 == (5.01e-7*C9)/C4)
m.Equation(C10 == C12 - 2*C11 - C5 + C4)
m.Equation(C12.dt()== 0)
m.Equation(TOC.dt()== 0)
m.Equation(cC1 == 17000*C1)
m.Equation(cC2 == 51500*C2)
#Application options
m.options.SOLVER = 1 #APOPT solver
m.options.IMODE = 5 #Dynamic Simultaneous - estimation
m.options.EV_TYPE = 2 #absolute error
m.options.NODES = 5 #collocation nodes (2,5)
if True:
kdoc1.STATUS=1
kdoc2.STATUS=1
S1.STATUS=1
S2.STATUS=1
#Solve
m.solve(disp=False)
#Results
data={'Time (h)':t,'C0 (M)':C0.value,'C1 (M)':C1.value, 'C2 (M)':C2.value,'C3 (M)':C3.value,'C4 (M)':C4.value,'C5 (M)':C5.value,'C6 (M)':C6.value,'C7 (M)':C7.value,'C8 (M)':C8.value,'C9 (M)':C9.value,'C10 (M)':C10.value,'C11 (M)':C11.value,'c12 (M)':C12.value}
dfr = pd.DataFrame(data, columns=['Time (h)','C0 (M)','C1 (M)','C2 (M)','C3 (M)','C4 (M)','C5 (M)','C6 (M)','C7 (M)','C8 (M)','C9 (M)','C10 (M)','C11 (M)','C12 (M)'])
#dfr.to_csv(r'C:\dfestimation.csv', index = False)
print('Solution')
print('kdoc1 = ' + str(kdoc1.value[0]))
print('kdoc2 = ' + str(kdoc2.value[0]))
print('S1 = ' + str(S1.value[0]))
print('S2 = ' + str(S2.value[0]))
plt.figure(1,figsize=(12,8))
plt.subplot(3,1,1)
plt.plot(m.time,C2.value,'bo',label='Predicted')
plt.plot(m.time,df['x'].values,'rs',label='Meas')
plt.plot(m.time,C2.value,label ='C2')
plt.legend(loc='best')
plt.subplot(3,1,2)
plt.plot(m.time,cC2.value,label ='C2')
plt.plot(m.time,cC1.value,label ='C1')
plt.legend(loc='best')
plt.subplot(3,1,3)
plt.plot(m.time,C0.value,label ='C0')
plt.plot(m.time,C1.value,label ='C1')
plt.plot(m.time,C3.value,label ='C3')
plt.plot(m.time,C4.value,label ='C4')
plt.plot(m.time,C5.value,label ='C5')
plt.plot(m.time,C6.value,label ='C6')
plt.plot(m.time,C7.value,label ='C7-')
plt.plot(m.time,C8.value,label ='C8')
plt.plot(m.time,C9.value,label ='C9')
plt.plot(m.time,C10.value,label ='C10')
plt.plot(m.time,C11.value,label ='C11')
plt.plot(m.time,C12.value,label ='C12')
plt.xlabel('time (h)')
plt.ylabel('Concentration (mol/L)')
plt.legend(loc='best')