如何利用Gurobi建立储能充放电模型?

利用Gurobi对储能进行建模

利用Gurobi求解电力系统的优化问题,在构建储能的充放电过程时遇到问题。
定义变量:

ESS = model.addVars(1, T, vtype=GRB.CONTINUOUS, name="ESS")
for t in range(T):
    ESS[0, t].setAttr(GRB.Attr.LB, -100)  # 小于0放电
 ESS[0, t].setAttr(GRB.Attr.UB, 100)  # 大于0充电
SOC = model.addVars(1, T, lb=0.2, ub=1.0, vtype=GRB.CONTINUOUS, name="SOC") 

约束条件按照下面的方式构建可以求解:

for t in range(T):
 if t == 0:
        model.addConstr(SOC[0, 0] == SOC_init, name="initial_soc")
 else:
        model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] / 400, name="charge_soc")

约束条件按照下面这个方式设置则无法求解:

for t in range(T):
 if t == 0:
        model.addConstr(SOC[0, 0] == SOC_init, name="initial_soc")
 else:
       if ESS[0, t] >= 0.0:
             model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] * 0.95 / 400, name="charge_soc")
        else:
             model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] / (0.95 * 400), name="discharge_soc")

实际充放电模型是下面这种方式,如何可以解决这个问题?

该回答引用ChatGPT GPT-4

运行结果

img

img

代码如下


import gurobipy as gp
from gurobipy import GRB

# 参数设置
T = 24
SOC_init = 0.5

# 创建模型
model = gp.Model("energy_storage")

# 定义变量
ESS = model.addVars(1, T, vtype=GRB.CONTINUOUS, name="ESS")
for t in range(T):
    ESS[0, t].setAttr(GRB.Attr.LB, -100)  # 小于0放电
    ESS[0, t].setAttr(GRB.Attr.UB, 100)   # 大于0充电
SOC = model.addVars(1, T, lb=0.2, ub=1.0, vtype=GRB.CONTINUOUS, name="SOC")

# 定义条件变量,表示充电状态
is_charging = model.addVars(1, T, vtype=GRB.BINARY, name="is_charging")

# 添加约束
for t in range(T):
    if t == 0:
        model.addConstr(SOC[0, 0] == SOC_init, name="initial_soc")
    else:
        # 充电状态约束
        charge_expr = SOC[0, t] - (SOC[0, t - 1] + ESS[0, t] * 0.95 / 400)
        model.addGenConstrIndicator(is_charging[0, t], 1, charge_expr, GRB.EQUAL, 0)

        # 放电状态约束
        discharge_expr = SOC[0, t] - (SOC[0, t - 1] + ESS[0, t] / (0.95 * 400))
        model.addGenConstrIndicator(is_charging[0, t], 0, discharge_expr, GRB.EQUAL, 0)

        # 充放电状态约束
        model.addGenConstrIndicator(is_charging[0, t], 1, ESS[0, t], GRB.GREATER_EQUAL, 0)

# 添加目标函数(请根据您的问题自定义目标函数)
model.setObjective(0, GRB.MINIMIZE)

# 求解模型
model.optimize()

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:

在您提供的第二种约束条件中,存在一个分支条件,即当 ESS[0, t] 大于等于0时,使用一个充电的系数 0.95,当 ESS[0, t] 小于0时,使用一个放电系数 1/0.95。这种非线性的约束条件使得模型变得复杂,导致无法求解。

为了避免这个问题,您可以将充电和放电的系数抽象出来,作为两个变量,然后在模型中引入新的约束条件来限制这两个变量的取值。例如:

charge_coeff = model.addVar(lb=0.0, ub=1.0, name="charge_coeff")
discharge_coeff = model.addVar(lb=0.0, ub=1.0, name="discharge_coeff")

for t in range(T):
    if t == 0:
        model.addConstr(SOC[0, 0] == SOC_init, name="initial_soc")
    else:
        model.addConstr(SOC[0, t] == SOC[0, t - 1] + (ESS[0, t] * charge_coeff - ESS[0, t] / discharge_coeff) / 400, name="charge_discharge_soc")

然后,您可以添加新的约束条件来限制充电和放电系数的取值:

model.addConstr(charge_coeff + discharge_coeff == 1, name="charge_discharge_coeff_sum")
model.addConstr(charge_coeff >= 0.95, name="min_charge_coeff")
model.addConstr(discharge_coeff >= 1/0.95, name="min_discharge_coeff")

这些约束条件将确保充电和放电系数的总和为 1,并且保证充电系数不小于 0.95,放电系数不小于 1/0.95。这样,您的模型就可以被解决了。

如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

以下内容部分参考ChatGPT模型:
问题的关键在于约束条件的设置。第一个约束条件设置是正确的,它保证了储能SOC的变化由充电和放电决定,而SOC的初始值由用户指定。第二个约束条件设置则存在问题,因为Gurobi在处理带有条件分支的约束条件时可能会出现问题。要解决这个问题,可以考虑将条件分支的约束条件转化为等价的线性规划形式。

具体来说,可以将充电和放电分别用两个变量表示,例如chargedischarge,然后根据chargedischarge的正负关系设置不同的约束条件。例如,当charge为正时,可以设置约束条件ESS[0,t] == chargeSOC[0,t] == SOC[0,t-1] + charge * 0.95 / 400;当discharge为正时,可以设置约束条件ESS[0,t] == -dischargeSOC[0,t] == SOC[0,t-1] - discharge * 0.95 * 400。这样就将条件分支的约束条件转化为等价的线性规划形式,可以避免Gurobi在处理约束条件时出现问题。

下面是具体的代码实现:

charge = model.addVars(1, T, vtype=GRB.CONTINUOUS, name="charge")
discharge = model.addVars(1, T, vtype=GRB.CONTINUOUS, name="discharge")

for t in range(T):
    if t == 0:
        model.addConstr(SOC[0, 0] == SOC_init, name="initial_soc")
    else:
        model.addConstr(charge[0,t] >= 0)
        model.addConstr(discharge[0,t] >= 0)
        model.addConstr(charge[0,t] + discharge[0,t] == ESS[0,t])
        model.addConstr(SOC[0,t] == SOC[0,t-1] + charge[0,t] * 0.95 / 400 - discharge[0,t] * 0.95 * 400)

如果我的建议对您有帮助、请点击采纳、祝您生活愉快

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
实际的充放电模型可能会更复杂(例如考虑电池的电化学效率、老化等因素),但是您提供的模型可以作为初步的模型进行优化。目前给出您提供的模型和约束,但在优化过程中如果出现问题,您可能需要进一步调整模型和约束。

首先,在您的模型中,变量ESS表示电池在每个时刻的充放电量。变量SOC表示电池在每个时刻的剩余容量。接下来,定义约束条件:

  1. ESS的值必须小于等于电池当前剩余容量SOC:
    model.addConstr(ESS[0, t] <= SOC[0, t], "upper_bound")

  2. ESS的值必须小于等于电池的最大容量100:
    model.addConstr(ESS[0, t] <= 100, "capacity_upper_bound")

  3. ESS的值必须大于等于电池的最小容量-100:
    model.addConstr(ESS[0, t] >= -100, "capacity_lower_bound")

  4. SOC的值必须小于等于电池最大容量100:
    model.addConstr(SOC[0, t] <= 100, "capacity_upper_bound")

  5. SOC的值必须大于等于电池最小容量20:
    model.addConstr(SOC[0, t] >= 20, "capacity_lower_bound")

  6. 如果ESS为正数,则表示充电,SOC会随之增加:
    model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] / efficiency_coefficient, "charge")

  7. 如果ESS为负数,则表示放电,SOC会随之减少:
    model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] * efficiency_coefficient, "discharge")

其中,efficiency_coefficient是电池的充放电效率系数,可以通过实际测试获得。

下面是完整的代码示例:

from gurobipy import *

# 创建模型
model = Model("energy_storage")

# 定义时间步长
T = 24

# 定义变量
ESS = model.addVars(1, T, vtype=GRB.CONTINUOUS, name="ESS")
for t in range(T):
    ESS[0, t].setAttr(GRB.Attr.LB, -100)  # 小于0放电
    ESS[0, t].setAttr(GRB.Attr.UB, 100)  # 大于0充电
SOC = model.addVars(1, T, lb=0.2, ub=1.0, vtype=GRB.CONTINUOUS, name="SOC")

# 定义约束条件
for t in range(T):
    # ESS的值必须小于等于电池当前剩余容量SOC
    model.addConstr(ESS[0, t] <= SOC[0, t], "upper_bound")

    # ESS的值必须小于等于电池的最大容量100
    model.addConstr(ESS[0, t] <= 100, "capacity_upper_bound")

    # ESS的值必须大于等于电池的最小容量-100
    model.addConstr(ESS[0, t] >= -100, "capacity_lower_bound")

    # SOC的值必须小于等于电池最大容量100
    model.addConstr(SOC[0, t] <= 100, "capacity_upper_bound")

    # SOC的值必须大于等于电池最小容量20
    model.addConstr(SOC[0, t] >= 20, "capacity_lower_bound")

    # 如果ESS为正数,则表示充电,SOC会随之增加
    model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] / efficiency_coefficient, "charge")

    # 如果ESS为负数,则表示放电,SOC会随之减少
    model.addConstr(SOC[0, t] == SOC[0, t - 1] + ESS[0, t] * efficiency_coefficient, "discharge")

# 目标函数
model.setObjective(sum(ESS[0, t] * price[t] for t in range(T)), GRB.MINIMIZE)

# 求解
model.optimize()

# 输出结果
for t in range(T):
    print("Time: {}, SOC: {:.2f}, ESS: {:.2f}".format(t + 1, SOC[0, t].x, ESS[0, t].x))

注意,在实际模型中,您需要定义价格向量来表达不同时刻的电力价格。在目标函数中,电池的充放电量被乘以相应时刻的电力价格,最小化总成本。
如果我的回答解决了您的问题,请采纳!

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^