添加限制,将电池循环限制为每24小时一次充电和一次放电



此查询是对以下问题的扩展:'@错误:找不到解决方案';在使用gekko进行优化时返回。"ind_ 1";以及";ind_ 2";是长度为8760的列表,包含0s/1。一年中的某些小时可能会获得额外收入,因此这些指标列表用于区分这些小时(在最大化函数中进一步使用我正试图通过将电池周期限制在每24小时MOST 1充电和放电来建立这种模式。作为一种最初的简单化方法,我试图总结每个24小时段的电池指令信号,并将其限制在最多8000千瓦时。你可以在下面找到我的方法:

m = Gekko(remote=False)
#variables
e_battery = m.Var(lb=0, ub=4000, value=2000) #energy in battery at time t, battery size 4 MWh, initial value is 2MWh
command = m.Var(lb=-1000, ub=1000) #command power -1 to 1 (in MW)
e_price = m.Param(value = price) #price is a list of 8760 values
ind_1 = m.Param(value = ind_1) 
ind_2 = m.Param(value = ind_2)
peak_list = m.Param(value = peak_load_list) #list of the monthly peaks (an array of length 8760)
load_list = m.Param(value = load) #hourly electric load
m.time = np.linspace(0,8759, 8760)
m.Equation(e_battery.dt() == command) 
#The next 2 constraints are to ensure that the new load (original load + battery operation) is greater than 0, but less than the peak load for that month
m.Equation(load_list + command >= 0)
m.Equation(load_list + command <= peak_list)
#Here is the code to limit the cycling. "abs(command)" is used since "command" can be negative (discharge) or positive (charge), and a full charge and full discharge will equate to 8000 kWh. 
daily_sum=0
for i in range(8760):
daily_sum += abs(command)
if i%24==0 and i!=0: #when i=0, it's the beginning of the first day so we can skip it
m.Equation(daily_sum <= 8000)
daily_sum = 0 #reset to 0 in preparation for the first hour of the next day
m.Maximize((-command)*(e_price + ind_1*ind1_price + ind_2*ind2_price))
m.options.IMODE = 6
m.solve()

添加循环约束时,将返回以下输出:

--------- APM Model Size ------------
Each time step contains
Objects      :  0
Constants    :  0
Variables    :  373
Intermediates:  0
Connections  :  0
Equations    :  368
Residuals    :  368
Error: At line 1545 of file apm.f90
Traceback: not available, compile with -ftrace=frame or -ftrace=full
Fortran runtime error: Out of memory

这个特定的实现是否使用gekko的框架工作?我是否必须为"0"初始化不同类型的变量;命令";?此外,我还没有找到许多使用for循环求解方程的相关例子,所以我很清楚我的实现可能很好。我很乐意听取任何人的想法和/或建议,谢谢。

二进制变量指示何时到达目的地(e_battery>3999或e_battery<1(。对这些二进制变量进行积分可以指示一天中达到极限的次数。一种可能的解决方案是将二进制变量的积分限制为小于天数。

下面是两个具有软约束和硬约束的示例。测试的时间点数量从8760个减少到120个(5天(。

from gekko import Gekko
import numpy as np
m = Gekko(remote=False)
n = 120 # hours
price=np.ones(n)
e_battery = m.Var(lb=0, ub=4000, value=2000) #energy in battery at time t
# battery size 4 MWh, initial value is 2MWh
command = m.Var(lb=-1000, ub=1000) #command power -1 to 1 (in MW)
e_price = m.Param(value = price) #price is a list of 8760 values
ind_1=1; ind_2=1
ind1_price=1; ind2_price=1
ind_1 = m.Param(value = ind_1) 
ind_2 = m.Param(value = ind_2)
m.time = np.linspace(0,n-1,n)
m.Equation(e_battery.dt() == command)
day = 24
discharge = m.Intermediate(m.integral(m.if3(e_battery+1,1,0)))
charge    = m.Intermediate(m.integral(m.if3(e_battery-3999,0,1)))
x         = np.ones_like(m.time)
for i in range(1,n):
if i%day==0:
x[i] = x[i-1] + 1
else:
x[i] = x[i-1]
limit = m.Param(x)
soft_constraints = True
if soft_constraints:
derr = m.CV(value=0)
m.Equation(derr==limit-discharge)
derr.STATUS = 1
derr.SPHI = 1; derr.WSPHI = 1000
derr.SPLO = 0; derr.WSPLO = 1000
cerr = m.CV(value=0)
m.Equation(cerr==limit-charge)
cerr.STATUS = 1
cerr.SPHI = 1; cerr.WSPHI = 1000
cerr.SPLO = 0; cerr.WSPLO = 1000
else:
# Hard Constraints
m.Equation(charge<=limit)
m.Equation(charge>=limit-1)
m.Equation(discharge<=limit)
m.Equation(discharge>=limit-1)
m.Minimize(command*(e_price + ind_1*ind1_price + ind_2*ind2_price))
m.options.IMODE = 6
m.solve()
import matplotlib.pyplot as plt
plt.figure(figsize=(10,6))
plt.subplot(3,1,1)
plt.plot(m.time,limit.value,'g-.',label='Limit')
plt.plot(m.time,discharge.value,'b:',label='Discharge')
plt.plot(m.time,charge.value,'r--',label='Charge')
plt.legend(); plt.xlabel('Time'); plt.ylabel('Cycles'); plt.grid()
plt.subplot(3,1,2)
plt.plot(m.time,command.value,'k-',label='command')
plt.legend(); plt.xlabel('Time'); plt.ylabel('Command'); plt.grid()
plt.subplot(3,1,3)
plt.plot(m.time,e_battery.value,'g-.',label='Battery Charge')
plt.legend(); plt.xlabel('Time'); plt.ylabel('Battery'); plt.grid()
plt.show()

原始问题中的应用程序内存不足,因为8760个方程在8760个时间步长上同时积分。尝试设置只写一次但在整个帧上有效的方程式。目前的目标功能是尽量减少用电量。您可能需要包含约束或目标函数以满足需求。否则,解决方案是永远不要用电,因为它是最小化的(例如,最大化(-命令((。以下是类似的电网能源基准问题,可能会有所帮助。

相关内容

  • 没有找到相关文章

最新更新