You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

解决CO₂-H₂反应动力学NLP模拟中非物理结果及速率常数异常问题的技术问询

解决CO₂-H₂反应动力学NLP模拟中非物理结果及速率常数异常问题的技术问询

我最近在研究CO₂和H₂反应体系的动力学问题,模拟温度升高时反应混合物的变化。我用Gekko工具来求解这个非线性规划(NLP)模型,但遇到了两个棘手的问题:一是模拟结果出现了非物理的情况,特别是CO的浓度变成了负值;二是当我调整了反应方程的形式后,拟合效果有所提升,但得到的动力学速率常数k却都是接近零的噪声值。有没有大佬能给我一些改进代码的建议呀?万分感谢!

当前模拟结果展示

  • 反应体系浓度模拟与测量值对比(出现CO浓度负值):
    反应体系浓度模拟与测量值对比
  • 物种相对浓度模拟结果:
    物种相对浓度模拟结果
  • 调整方程后速率常数结果(k值接近零):
    调整方程后速率常数结果

方程调整后的情况

当我改用如下形式的单一反应方程时,拟合效果好了很多,但得到的动力学速率常数k都是接近零的噪声值:

m.Equation(0 == -(k1 * S * CO2 * H2 * (1 - ((CO * H2O) / (CO2 * H2)) / K1eq_param)))

完整模拟代码

import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt
import csv

CH4_meas = np.array([0.1361,0.1885,0.2481,0.3341,0.4266]) # and further values...
CO_meas = np.array([0.0281,0.0376,0.0476,0.0628,0.0817])
H2O_meas = np.array([0.1201,0.234,0.3821,0.5821,0.8274])
H2_meas = np.array([62.6176,62.3346,62.0223,61.7904,61.5901])
CO2_meas = np.array([30.4669,30.3408,30.3541,30.3541,30.2984])


K1eq = np.array([0.01690,0.01881,0.02088,0.02312,0.02555])
K2eq = np.array([5.7990E+08,3.3957E+08,2.0132E+08,1.2079E+08,7.3315E+07])
K3eq = np.array([9.7992E+06,6.3860E+06,4.2031E+06,2.7930E+06,1.8732E+06])


CH4_values = []
CO_values = []
H2O_values = []
H2_values = []
CO2_values = []
k1_values = []
k2_values = []
k3_values = []
S=25

for i in range(len(CH4_meas)):
    m = GEKKO(remote=False)

    # Initial guess for the rate constants, but when I set lb=0, no solution can be found
    k1 = m.FV(value=0.0025, lb=None, ub=None)
    k2 = m.FV(value=0.0025, lb=None, ub=None)
    k3 = m.FV(value=0.2, lb=None, ub=None)
    k1.STATUS = 1
    k2.STATUS = 1
    k3.STATUS = 1

    # Controlled Variables (CV) with measurement normalization
    CH4 = m.CV(CH4_meas[i] / (H2_meas[0] + CO2_meas[0]))
    CO = m.CV(CO_meas[i] / (H2_meas[0] + CO2_meas[0]))
    H2O = m.CV(H2O_meas[i] / (H2_meas[0] + CO2_meas[0]))
    H2 = m.CV(H2_meas[i] / (H2_meas[0] + CO2_meas[0]))
    CO2 = m.CV(CO2_meas[i] / (H2_meas[0] + CO2_meas[0]))    
    CH4.FSTATUS = 1
    CO.FSTATUS = 1
    H2O.FSTATUS = 1
    H2.FSTATUS = 1
    CO2.FSTATUS = 1

    # Parameters
    K1eq_param = m.Param(value=K1eq[i])
    K2eq_param = m.Param(value=K2eq[i])
    K3eq_param = m.Param(value=K3eq[i])

    # Steady-state equations
    m.Equation(CO2 == -(k1 * S * CO2 * H2 * (1 - ((CO * H2O) / (CO2 * H2)) / K1eq_param)) - k3 * S * CO2 * (1 - ((CH4 * H2O**2) / (CO2 * H2**4)) / K3eq_param))
    m.Equation(H2 == -(k1 * S * CO2 * H2 * (1 - ((CO * H2O) / (CO2 * H2)) / K1eq_param) - 3 * k2 * S * CO * (1 - ((CH4 * H2O) / (CO * H2**3)) / K2eq_param) - 4 * k3 * S * CO2 * (1 - ((CH4 * H2O**2) / (CO2 * H2**4)) / K3eq_param)))
    m.Equation(CO == (k1 * S * CO2 * H2 * (1 - ((CO * H2O) / (CO2 * H2)) / K1eq_param) - k2 * S * CO * (1 - ((CH4 * H2O) / (CO * H2**3)) / K2eq_param)))
    m.Equation(H2O == (k1 * S * CO2 * H2 * (1 - ((CO * H2O) / (CO2 * H2)) / K1eq_param) + k2 * S * CO * (1 - ((CH4 * H2O) / (CO * H2**3)) / K2eq_param) + k3 * S * CO2 * (1 - ((CH4 * H2O**2) / (CO2 * H2**4)) / K3eq_param)))
    m.Equation(CH4 == (k2 * S * CO * (1 - ((CH4 * H2O) / (CO * H2**3)) / K2eq_param) + k3 * S * CO2 * (1 - ((CH4 * H2O**2) / (CO2 * H2**4)) / K3eq_param)))

    # Objective function for regression fitting
    m.Obj((CH4.value - CH4_meas[i])**2 + (CO.value - CO_meas[i])**2 + (H2O.value - H2O_meas[i])**2 +
           (H2.value - H2_meas[i])**2 + (CO2.value - CO2_meas[i])**2)
  

    # Set the mode for steady-state optimization
    m.options.IMODE = 3  # Steady-state optimization
    m.options.EV_TYPE = 1 #2 = Sum of squared error, 1 = Sum of absoluted error

    m.options.MAX_ITER = 300
    m.options.OTOL = 1e-6
    m.options.RTOL = 1e-6

    # Solve the model
    m.solve(disp=True)

    # Store results
    CH4_values.append(CH4.value[0])
    CO_values.append(CO.value[0])
    H2O_values.append(H2O.value[0])
    H2_values.append(H2.value[0])
    CO2_values.append(CO2.value[0])
    k1_values.append(k1.value[0])
    k2_values.append(k2.value[0])
    k3_values.append(k3.value[0])
    
    print("k1 = " + str(k1.value[0]))
    print("k2 = " + str(k2.value[0]))
    print("k3 = " + str(k3.value[0]))


with open('OptimGekko_Methane_RWGS.csv', 'w', newline='') as csvfile:
    csvwriter = csv.writer(csvfile)
    csvwriter.writerow(['T', 'k1', 'k2', 'k3','CO2','H2','CO','H2O','CH4'])
    for i in range(len(k1_values)):
        csvwriter.writerow([time[i], k1_values[i], k2_values[i], k3_values[i], CO2_values[i], H2_values[i],CO_values[i], H2O_values[i], CH4_values[i]])


plt.figure(figsize=(10, 12))


plt.subplot(5, 1, 1)
plt.plot(time[:len(CH4_values)], CH4_values, label='CH4_simul')
plt.plot(time[:len(CH4_meas)], CH4_meas/(30.47+62.62), 'ro', label='CH4_meas')
plt.ylabel('c/c0 (-)')
plt.xlabel('T (°C)')
plt.legend()
plt.grid()
plt.title('CH4')
plt.subplot(5, 1, 2)
plt.plot(time[:len(CO_values)], CO_values, label='CO_simul')
plt.plot(time[:len(CO_meas)], CO_meas/(30.47+62.62), 'ro', label='CO_meas')
plt.ylabel('c/c0 (-)')
plt.xlabel('T (°C)')
plt.legend()
plt.grid()
plt.title('CO')
plt.subplot(5, 1, 3)
plt.plot(time[:len(H2O_values)], H2O_values, label='H2O_simul')
plt.plot(time[:len(H2O_meas)], H2O_meas/(30.47+62.62), 'ro', label='H2O_meas')
plt.ylabel('c/c0 (-)')
plt.xlabel('T (°C)')
plt.legend()
plt.grid()
plt.title('H2O')
plt.subplot(5, 1, 4)
plt.plot(time[:len(H2_values)], H2_values, label='H2_simul')
plt.plot(time[:len(H2_meas)], H2_meas/(30.47+62.62), 'ro', label='H2_meas')
plt.ylabel('c/c0 (-)')
plt.xlabel('T (°C)')
plt.legend()
plt.grid()
plt.title('H2')
plt.subplot(5, 1, 5)
plt.plot(time[:len(CO2_values)], CO2_values, label='CO2_simul')
plt.plot(time[:len(CO2_meas)], CO2_meas/(30.47+62.62), 'ro', label='CO2_meas')
plt.ylabel('c/c0 (-)')
plt.xlabel('T (°C)')
plt.legend()
plt.grid()
plt.title('CO2')

plt.tight_layout()
plt.savefig('Optim_RWGS_CH4.png')
plt.show()

备注:内容来源于stack exchange,提问作者Ronny M

火山引擎 最新活动