首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Pyomo储能系统调度优化

Pyomo储能系统调度优化
EN

Stack Overflow用户
提问于 2022-03-03 15:55:02
回答 1查看 634关注 0票数 0

我试图为使用pyomo的储能系统创建一个模型优化。利用家庭对kWh的需求和电价,我希望在适当的时候将电池的充放电成本降到最低。我已经为1年的数据建立了一个工作模型,并且该模型能够找到一个最优的解决方案(参见下面的代码)。然而,当我尝试在三个月内(比方说从10月到12月)找到一个模型时,pyomo返回时有一个终止条件,“未绑定”,但我不知道为什么。

1年数据的模型

代码语言:javascript
运行
复制
#Battery parameters
battery_capacity = 252
total_energy = 13.1
usable_energy = 12.4 
nominal_voltage = 51.8
ratio = total_energy/usable_energy
power = usable_energy / ratio
nominal_current = usable_energy / nominal_voltage * 1000
recharging_hours = battery_capacity/nominal_current
battery_level_threshold = 0

model = pyo.ConcreteModel()
#Set time period
model.T = pyo.Set(initialize=pyo.RangeSet(len(df_2021)),ordered=True)

#PARAMETERS:
model.b_efficiency  = pyo.Param(initialize=0.9)
model.b_min_cap = pyo.Param(initialize=0)
model.b_max_cap = pyo.Param(initialize=12.4)
model.b_charge_power = pyo.Param(initialize=power)
model.b_discharge_power = pyo.Param(initialize=power)

model.spot_prices = pyo.Param(model.T,initialize=dict(enumerate(df_2021["Price/kWh"],1)),within=pyo.Any)
model.demand = pyo.Param(model.T, initialize=dict(enumerate(df_2021["Demand"],1)),within=pyo.Any)
#Variables : also the variable has to  be indexed with the time T
model.b_soc = pyo.Var(model.T, domain = pyo.NonNegativeReals, bounds = (model.b_min_cap, model.b_max_cap))
model.b_discharge = pyo.Var(model.T, domain = pyo.NonNegativeReals)
model.b_charge = pyo.Var(model.T, domain = pyo.NonNegativeReals)
model.elect_purchased = pyo.Var(model.T, domain = pyo.NonNegativeReals)

#CONSTRAINTS
#Purchase constraint
def purchase_constraint(model,t):
    return model.elect_purchased[t] >= model.demand[t] - model.b_discharge[t] + model.b_charge[t]

#State of charge constraint
def soc_constraint(model,t):
    if t == model.T.first():
        return model.b_soc[t] == model.b_max_cap / 2 #- model.b_discharge[t] + model.b_charge[t]
    else: 
        return model.b_soc[t] == model.b_soc[t-1] - model.b_discharge[t-1] + model.b_charge[t-1]
#Discharge and charge constraints
def discharge_constraint_1(model,t):
    """ Maximum discharge rate within a single hour """
    return model.b_discharge[t] <= model.b_discharge_power    
def discharge_constraint_2(model,t):<br/>
    """ Sets the maximum energy available to be discharged as the SOC - minimum SOC """
    return model.b_discharge[t] <= model.b_soc[t] - model.b_min_cap

def charge_constraint_1(model,t):
    """ Maximum charge rate within a single hour """
    return model.b_charge[t] <= model.b_charge_power 

def charge_constraint_2(model,t):<br/>
    """ Sets the maximum energy available to be cahrge as the SOC max """
    return model.b_charge[t]  <= model.b_max_cap - model.b_soc[t]

model.purchase_c = pyo.Constraint(model.T, rule = purchase_constraint)
model.soc_c = pyo.Constraint(model.T, rule = soc_constraint)<br/>
model.discharge_c1 = pyo.Constraint(model.T,rule = discharge_constraint_1)
model.discharge_c2 = pyo.Constraint(model.T,rule = discharge_constraint_2)
model.charge_c1 = pyo.Constraint(model.T,rule = charge_constraint_1)
model.charge_c2 = pyo.Constraint(model.T,rule = charge_constraint_2)

#OBJECTIVE 
expr = sum(model.elect_purchased[t] * model.spot_prices[t] for t in model.T)
model.objective = pyo.Objective(rule = expr, sense = pyo.minimize)    
opt = pyo.SolverFactory('cbc',executable='/usr/bin/cbc')
results = opt.solve(model)
results.write()

结果1年数据

找到了最优解。

但是,当我更改数据集时,使用相同的模型结构和约束,pyomo找不到解决方案。

3个月模型

代码语言:javascript
运行
复制
#Battery parameters
battery_capacity = 252
total_energy = 13.1
usable_energy = 12.4 
nominal_voltage = 51.8
ratio = total_energy/usable_energy
power = usable_energy / ratio
nominal_current = usable_energy / nominal_voltage * 1000
recharging_hours = battery_capacity/nominal_current
battery_level_threshold = 0

model = pyo.ConcreteModel()
#Set time period
model.T = pyo.Set(initialize=pyo.RangeSet(len(df_2021)),ordered=True)

#PARAMETERS:
model.b_efficiency  = pyo.Param(initialize=0.9)
model.b_min_cap = pyo.Param(initialize=0)
model.b_max_cap = pyo.Param(initialize=12.4)
model.b_charge_power = pyo.Param(initialize=power)
model.b_discharge_power = pyo.Param(initialize=power)

model.spot_prices = pyo.Param(model.T,initialize=dict(enumerate(df_2021["Price/kWh"],1)),within=pyo.Any)
model.demand = pyo.Param(model.T, initialize=dict(enumerate(df_2021["Demand"],1)),within=pyo.Any)
#Variables : also the variable has to  be indexed with the time T
model.b_soc = pyo.Var(model.T, domain = pyo.NonNegativeReals, bounds = (model.b_min_cap, model.b_max_cap))
model.b_discharge = pyo.Var(model.T, domain = pyo.NonNegativeReals)
model.b_charge = pyo.Var(model.T, domain = pyo.NonNegativeReals)
model.elect_purchased = pyo.Var(model.T, domain = pyo.NonNegativeReals)

#CONSTRAINTS
#Purchase constraint
def purchase_constraint(model,t):
    return model.elect_purchased[t] >= model.demand[t] - model.b_discharge[t] + model.b_charge[t]

#State of charge constraint
def soc_constraint(model,t):
    if t == model.T.first():
        return model.b_soc[t] == model.b_max_cap / 2 #- model.b_discharge[t] + model.b_charge[t]
    else: 
        return model.b_soc[t] == model.b_soc[t-1] - model.b_discharge[t-1] + model.b_charge[t-1]
#Discharge and charge constraints
def discharge_constraint_1(model,t):
    """ Maximum discharge rate within a single hour """
    return model.b_discharge[t] <= model.b_discharge_power    
def discharge_constraint_2(model,t):<br/>
    """ Sets the maximum energy available to be discharged as the SOC - minimum SOC """
    return model.b_discharge[t] <= model.b_soc[t] - model.b_min_cap

def charge_constraint_1(model,t):
    """ Maximum charge rate within a single hour """
    return model.b_charge[t] <= model.b_charge_power 

def charge_constraint_2(model,t):<br/>
    """ Sets the maximum energy available to be cahrge as the SOC max """
    return model.b_charge[t]  <= model.b_max_cap - model.b_soc[t]

model.purchase_c = pyo.Constraint(model.T, rule = purchase_constraint)
model.soc_c = pyo.Constraint(model.T, rule = soc_constraint)<br/>
model.discharge_c1 = pyo.Constraint(model.T,rule = discharge_constraint_1)
model.discharge_c2 = pyo.Constraint(model.T,rule = discharge_constraint_2)
model.charge_c1 = pyo.Constraint(model.T,rule = charge_constraint_1)
model.charge_c2 = pyo.Constraint(model.T,rule = charge_constraint_2)

#OBJECTIVE 
expr = sum(model.elect_purchased[t] * model.spot_prices[t] for t in model.T)
model.objective = pyo.Objective(rule = expr, sense = pyo.minimize)    
opt = pyo.SolverFactory('cbc',executable='/usr/bin/cbc')
results = opt.solv

Pyomo返回

代码语言:javascript
运行
复制
WARNING: Loading a SolverResults object with a warning status into
    model.name="unknown";
      - termination condition: unbounded
      - message from solver: <undefined>
# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem: 
- Name: unknown
  Lower bound: None
  Upper bound: inf
  Number of objectives: 1
  Number of constraints: 16993
  Number of variables: 11329
  Number of nonzeros: 2832
  Sense: minimize
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver: 
- Status: warning
  User time: -1.0
  System time: 0.45
  Wallclock time: 0.58
  Termination condition: unbounded
  Termination message: Model was proven to be unbounded.
  Statistics: 
    Branch and bound: 
      Number of bounded subproblems: 0
      Number of created subproblems: 0
    Black box: 
      Number of iterations: 0
  Error rc: 0
  Time: 0.6151924133300781

由于两次运行之间唯一的变化是数据的长度,所以我不知道在哪里查找错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-04 17:16:30

考虑到模型在某些数据上工作,而不是在备用数据源上工作,我们显然可以将重点放在数据集上(没有显示出来)。

我们在错误报告中有一个很大的线索,即问题是无界。这意味着,在极小化问题的情况下,没有什么可以阻止目标函数跑向无穷远,或负无穷大。那么,让我们来看看你的目标函数。你是:

代码语言:javascript
运行
复制
sum(demand[t] * price[t] for t in T)

demand变量的域设置为非负实数(good),而price[t]是从数据中读取的参数,并且正在最小化。因此,只有当数据中有一个(或多个)负价格时,才能避免负无穷大,然后求解者就会对此采取行动,而demand将是无界的。

所以,梳理一下你的数据集。如果你在使用熊猫,只要用逻辑搜索价格< 0的行,你可能会找到至少一个。然后,您将不得不决定这是一个错误,还是现实中有一个负的价格(在某些系统中可能发生),如果它是合法的,您将不得不施加一些其他限制,以限制模型在这种情况下。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71340036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档