如何通过估计/调整参数R0,R1,R2,C1,C2在Python中将模拟数据与电池的实验数据匹配

问题描述

我目前正在使用 Python 对电池进行参数优化。我有一个实验数据和来自 Python 电池模拟的数据。我的任务是以这样的方式调整电池参数;模拟数据应与实验数据相符。 enter image description here

模拟数据的方程为:Voltage = Vocv-R0It-R1It*exp(-t/R1C1)-R2It*exp(-t/R2C2) 其中,R0,R1,R2,C1,C2 需要调整/估计。

我有 Vocv、It 和 t 的值。

我取了R0=0.0000001,R1= 0.0000001,R2=0.0000001,C1= 3e-07,C2=3e-07的初始值

因为,数据框很大;我将为这些值提供一个示例。

Vocv = [4.19856,4.19856,4.19855,4.19854,4.19853,4.19852,4.19852]
t=     [10.8648,10.8855,10.906,10.926,10.9467,10.9671,10.9872,11.0079,11.0272,11.0473,11.0679]
It=    [299688,299689,299697,299703,299693,299695,299688,299696,299691,299694]
Vmeas= [4.1265,4.12649,4.12648,4.12647,4.12646,4.126,4.12645]

实验数据示例如下:

Vmeas2=[4.152166666666667,4.151833333333333,4.1505,4.1495,4.151666666666666,4.149,4.149166666666667,4.153333333333333,4.150333333333333,4.150833333333333]
Time2 = [32.5958,32.6559,32.7161,32.7762,32.8363,32.8965,32.9566,33.0167,33.0769,33.137,33.1972]

我对编程很陌生,请建议如何使用 GEKKO 或任何其他优化器解决此问题。

编辑:我在建议之后尝试过的代码: 因为,我的主要目标是Vmeas=Vmeas2,通过调整/估计 R0-R2、C1&C2。

Voltage = m.CV(Vmeas2); Voltage.FSTATUS = 1
Vocv = m.Param(Vocv); t = m.Param(t); It = m.Param(It)
R0,R2 = m.Array(m.FV,3,value=1e-7,lb=1e-8,ub=1e-15)
C1,C2 = m.Array(m.FV,2,value=3e-7,ub=3e-15)
R0.STATUS=1; R1.STATUS=1; R2.STATUS=2
C1.STATUS=1; C2.STATUS=1
Time2 = m.Param(Time2)
#t.value = Time2

m.Equation(Voltage==Vocv-R0*It \
                        -R1*It*m.exp(-(t/R1)*C1) \
                        -R2*It*m.exp(-(t/R2)*C2))
#t.value = Time2
m.options.IMODE = 2
m.solve(disp=False)

plt.subplot(2,1,2)
plt.title('Experimental')
plt.plot(Voltage.value,'bo',label='Predicted')
plt.plot(Vmeas2,'rx',label='Measured')
plt.legend(); plt.ylabel('Value')
plt.show()
print('R0: ' + str(R0.value[0]))
print('R1: ' + str(R1.value[0]))
print('R2: ' + str(R2.value[0]))
print('C1: ' + str(C1.value[0]))
print('C2: ' + str(C2.value[0]))

然而,不想要的错误来了:

line 71,in <module>
    m.solve(disp=False)

  File "/gekko/gekko.py",line 2227,in solve
    self.load_JSON()

  File "/gekko/gk_post_solve.py",line 50,in load_JSON
    vp.__dict__[o] = data[vp.name][o]

KeyError: 'p12'

解决方法

Gekko 有 regression to fit experimental data 的模式 (IMODE=2)。有更多关于带有 nonlinear regression example application 的参数回归的信息。这是您提供的简化数据集的解决方案。

regression fit

from gekko import GEKKO

# fit parameters
m = GEKKO(remote=False)
Vocv = [4.19856,4.19856,4.19855,4.19854,\
        4.19854,4.19853,4.19852,4.19852]
t=     [10.8648,10.8855,10.906,10.926,10.9467,10.9671,\
        10.9872,11.0079,11.0272,11.0473,11.0679]
It=    [299688,299689,299697,299703,299693,299695,\
        299688,299696,299691,299694]
Vmeas= [4.1265,4.12649,4.12648,4.12647,\
        4.12647,4.12646,4.126,4.12645]
Voltage = m.CV(Vmeas); Voltage.FSTATUS = 1
Vocv = m.Param(Vocv); t = m.Param(t); It = m.Param(It)
R0,R1,R2 = m.Array(m.FV,3,value=1e-7,lb=1e-8)
C1,C2 = m.Array(m.FV,2,value=3e-7,lb=1e-8)
R0.STATUS=1; R1.STATUS=1; R2.STATUS=2
C1.STATUS=1; C2.STATUS=1
m.Equation(Voltage==Vocv-R0*It \
                        -R1*It*m.exp(-(t/R1)*C1) \
                        -R2*It*m.exp(-(t/R2)*C2))
m.options.IMODE = 2
m.solve(disp=False)

import matplotlib.pyplot as plt
plt.figure(1,figsize=(8,6))
plt.subplot(2,1,1)
plt.title('Fit')
plt.plot(Voltage.value,'bo',label='Predicted')
plt.plot(Vmeas,'rx',label='Measured')
plt.legend(); plt.ylabel('Value')
plt.ylim([min(Vmeas)-0.01,max(Vmeas)+0.01])

print('R0: ' + str(R0.value[0]))
print('R1: ' + str(R1.value[0]))
print('R2: ' + str(R2.value[0]))
print('C1: ' + str(C1.value[0]))
print('C2: ' + str(C2.value[0]))

# test fit on experimental data,if different length than fitting
#  then create a new model with the same variables and equations but
#  use the values for R0-R2 and C1,C2.
Vmeas2= [4.152166666666667,4.151833333333333,4.1505,\
         4.1495,4.151666666666666,4.149,4.149166666666667,4.153333333333333,4.150333333333333,\
         4.150833333333333]
Time2 = [32.5958,32.6559,32.7161,32.7762,32.8363,32.8965,\
        32.9566,33.0167,33.0769,33.137,33.1972]
t.value = Time2
m.options.IMODE = 2
m.solve(disp=False)

plt.subplot(2,2)
plt.title('Experimental')
plt.plot(Voltage.value,label='Predicted')
plt.plot(Vmeas2,label='Measured')
plt.legend(); plt.ylabel('Value')
plt.show()

也许更多的数据会产生更好的拟合。