微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在python中使用GEKKO估计电池参数时出错

如何解决在python中使用GEKKO估计电池参数时出错

我正在尝试将模型的模拟结果与实验室的实验结果相匹配。我从这里给出的解决方案中获取了这个想法: enter link description here

应用 GEKKO 方法前的结果:

enter image description here

我希望模拟曲线与实验曲线完全匹配。

代码

m = GEKKO(remote=False)
Vocv = Data.loc[:,'Vocv'].tolist()
Tt=    Data.loc[:,'Tt'].tolist() 
It=    Data.loc[:,'It'].tolist()
Vmeas= Data.loc[:,'Experimental_Voltage(v)']/6000.tolist()
Vocv = m.Param(Vocv); Tt = m.Param(Tt); It = m.Param(It)
##m.time = Tt; time = m.Var(0); m.Equation(time.dt()==1)
    


 R0 = m.FV(lb= 2.448e-07,ub=100); R0.STATUS=1
R1 = m.FV(lb= 3e-07,ub=100);  R1.STATUS=1
R2 = m.FV(lb=3e-07,ub=100); R2.STATUS=1
C1 = m.FV(lb=0.02,ub=1000); C1.STATUS=1
C2 = m.FV(lb=0.02,ub=1000); C2.STATUS=1
ym = m.Param(Vmeas)
yp = m.Var(Vmeas); m.Equation(yp==Vocv+(R0*It) \
                    +(R1*It)*(1-m.exp(-1/(R1*C1))*Tt) \
                    +(R2*It)*(1-m.exp(-1/(R2*C2))*Tt))
m.Minimize((yp-ym)**2)
m.options.IMODE = 2

m.solve(disp=False)

import matplotlib.pyplot as plt
Ex_Time= Data.loc[:,'Experimental_Time(s)']
plt.plot(Ex_Time,Experimental_Voltage/6000)
plt.plot(Tt,yp)
plt.legend([r'$Simulated_Data$',r'$Experimental_Data$'])
plt.ylabel('Voltage')
plt.xlabel('Time')
plt.savefig('sysid.png')
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]))

输出

 R0: 2.448e-07
R1: 3e-07
R2: 3e-07
C1: 0.02
C2: 0.02

编辑: 正如答案中所建议的那样,我已经进行了更改,但得到的结果如下:

enter image description here

它仍然不匹配/重叠实验数据。

预期结果:

enter image description here

解决方法

尝试为 R1R2 设置一个小的正下限以避免等式中被零除:

R1 = m.FV(lb=1e-5,ub=100);  R1.STATUS=1
R2 = m.FV(lb=1e-5,ub=100);  R2.STATUS=1

您提供的示例缺少数据,因此我包含了一些示例数据。这个例子现在收敛到一个解决方案。

R0: 0.058215197521
R1: 1.0089645613e-05
R2: 1.0089645613e-05
C1: 42.633186357
C2: 42.633186357

Voltage solution

from gekko import GEKKO
m = GEKKO(remote=False)
Vocv = [4.1,4.2,4.05,4.15,4.2]
Tt=    [0,1,2,3,4]
It=    [1.2,1.3,1.4,1.1,1.0]
Vmeas= [4.15,4.25,4.25]
Vocv = m.Param(Vocv); Tt = m.Param(Tt); It = m.Param(It)

R0 = m.FV(lb=0,ub=100);     R0.STATUS=1
R1 = m.FV(lb=1e-5,ub=100);  R2.STATUS=1
C1 = m.FV(lb=0,ub=1000);    C1.STATUS=1
C2 = m.FV(lb=0,ub=1000);    C2.STATUS=1

ym = m.Param(Vmeas)
yp = m.Var(Vmeas); m.Equation(yp==Vocv+R0*It \
                        +R1*It*m.exp(-(Tt/R1)*C1) \
                        +R2*It*m.exp(-(Tt/R2)*C2))
m.Minimize((yp-ym)**2)
m.options.IMODE = 2

m.solve(disp=False)

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]))

import matplotlib.pyplot as plt
plt.plot(Tt,yp,'b-o')
plt.plot(Tt,ym,'rx')
plt.ylabel('Voltage')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()

切换到 IMODE=2 以缩短求解时间,因为模型中没有微分方程。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。