【问题标题】:Getting error while estimating parameter for a battery using GEKKO in python在 python 中使用 GEKKO 估计电池参数时出错
【发布时间】:2021-09-14 12:15:51
【问题描述】:

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

应用GEKKO方法前的结果:

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

代码:

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

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

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

预期结果:

【问题讨论】:

    标签: python scipy battery gekko


    【解决方案1】:

    尝试为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
    

    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.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);  R1.STATUS=1
    R2 = 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 以缩短求解时间,因为模型中没有微分方程。

    【讨论】:

    • 我已经编辑了我的问题并采用了不同的初始值 R0、R1、R2、C1 和 C2,但是,它没有减少错误,而是采用相同的值而不是优化。
    • 求解器是否报告了成功的解决方案?您可能需要添加参数界限或提供更好的初始条件来找到全局(非局部)最优值。
    • 我认为求解器正在给出解决方案,但是它只采用参数边界的 'lb' 值,并没有真正最小化错误。我给出了最好的初始值,但仍然不太合适。
    • 尝试降低参数 lb 的值,如果需要,甚至让它变为负值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2020-09-26
    • 1970-01-01
    相关资源
    最近更新 更多