Как сопоставить смоделированные данные с экспериментальными данными батареи в Python путем оценки / настройки параметров (R0, R1, R2, C1, C2)

В настоящее время я работаю над оптимизацией параметров батареи с помощью Python. У меня есть экспериментальные данные и данные моделирования батареи на Python. Моя задача - настроить параметры батареи таким образом, чтобы: смоделированные данные должны соответствовать экспериментальным данным. введите здесь описание изображения

Уравнение для смоделированных данных: Voltage = Vocv-R0It-R1It*exp(-t/R1C1)-R2It*exp(-t/R2C2) где, R0, R1, R2, C1, C2 необходимо скорректировать / оценить.

У меня есть значение Vocv, It и т. Д.

Я взял начальное значение R0=0.0000001, R1= 0.0000001, R2=0.0000001, C1= 3e-07, C2=3e-07

Поскольку фрейм данных огромен; Я дам образец для этих значений.

Vocv = [4.19856,4.19856,4.19855,4.19855,4.19855,4.19854,4.19854,4.19853,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,299695,299691,299694]
Vmeas= [4.1265,4.12649,4.12649,4.12648,4.12648,4.12647,4.12647,4.12646,4.126,4.12646,4.12645]

И образец экспериментальных данных ниже:

Vmeas2=[4.152166666666667,4.151833333333333,4.1505,4.1495,4.151666666666666,4.149,4.149166666666667,4.1495,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,R1,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,lb=1e-8, 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'

person N_T    schedule 22.06.2021    source источник


Ответы (1)


В Gekko есть режим (IMODE=2) для регрессии для соответствия экспериментальным данным. Дополнительную информацию о регрессии параметров можно найти в приложении пример нелинейной регрессии. Вот решение с предоставленным вами сокращенным набором данных.

регрессионное соответствие

from gekko import GEKKO

# fit parameters
m = GEKKO(remote=False)
Vocv = [4.19856,4.19856,4.19855,4.19855,4.19855,4.19854,\
        4.19854,4.19853,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,299695,299691,299694]
Vmeas= [4.1265,4.12649,4.12649,4.12648,4.12648,4.12647,\
        4.12647,4.12646,4.126,4.12646,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.1495,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,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()

Возможно, большее количество данных даст лучшее соответствие.

person John Hedengren    schedule 23.06.2021
comment
Спасибо, сэр, за ответ. Я пытаюсь подогнать экспериментальные данные, как вы предложили, однако получаю некоторую нежелательную ошибку. Код: Voltage = m.CV(Vmeas2); Voltage.FSTATUS = 1 Ошибка: line 62, in <module> m.solve(disp=False) line 2227, in solve self.load_JSON() line 70, in load_JSON vp.__dict__[o] = data[vp.name][o] KeyError: 'v2' - person N_T; 23.06.2021
comment
Я попробовал сделать это по-другому, однако код, который я редактировал выше, также получил некоторую нежелательную ошибку. Я не могу понять, в чем дело. Буду признателен за помощь. - person N_T; 23.06.2021
comment
Похоже, вы пытаетесь переопределить Voltage после того, как оно уже объявлено. Если вы хотите протестировать на разных экспериментальных результатах, попробуйте создать новую модель с m2 = GEKKO() и повторите уравнения с m2.Equation(), m2.Array() и т. Д., Но используйте значения из подгонки. - person John Hedengren; 23.06.2021
comment
Если после попытки вы все еще получаете сообщение об ошибке, создайте новый вопрос со своим кодом. - person John Hedengren; 23.06.2021
comment
Я создал новую проблему: stackoverflow.com/questions/68116432/ - person N_T; 24.06.2021