我目前正在建立一个简单的优化工具的电池存储。在t中,电池由Q_charget加载,即从电网Q_elt提取的电能乘以效率因子eta_charge。
放电功率Q_discharget乘以效率因子eta_discharge,给出了需求Q_demandt。需求概况在一年中的每一个小时都是众所周知的。
电池SOC(t)定义为前一时间的充电状态+功率输入-功率输出。未考虑任何损失。
在t=0的电荷状态应该等于所考虑的周期的最后一个小时。
充放电不能同时发生。
充放电有最小和最大限值。
知道一年中每小时的电价,目标函数将决定何时收费,从而使购买成本降到最低。需求是内部使用的,不卖电。
Demandt是已知的(从导入)。Pricet是已知的(从导入)。
这是密码。
model = pyo.ConcreteModel()
##Parameters
tot_time=8760 #Hours in a year
model.T=pyo.Set(initialize=[t for t in range(0,tot_time)])
model.EtaCharge=pyo.Param(initialize=1.0, mutable=True) #-
model.PMinCharge=0 #MW
model.PMaxCharge=2 #MW
model.EtaDischarge=pyo.Param(initialize=1.0, mutable=True) #-
model.PMinDischarge=2 #MW
model.PMaxDischarge=4 #MW
model.S0=pyo.Param(initialize=0.0, mutable=True) #MWh SOC at t=0
##Variables
model.QEl = pyo.Var(model.T, within=NonNegativeReals, initialize=0)
model.QCharge= pyo.Var(model.T, within=NonNegativeReals)
model.QDischarge= pyo.Var(model.T, within=NonNegativeReals)
model.Charge=pyo.Var(model.T, within = pyo.Binary)
model.Discharge=pyo.Var(model.T, within = pyo.Binary)
model.SOC=pyo.Var(model.T, bounds=(0,100)) #Size of the battery limited to 100 MWh
##Constraints
model.C1 = pyo.ConstraintList()
model.C2 = pyo.ConstraintList()
model.C3 = pyo.ConstraintList()
model.C4 = pyo.ConstraintList()
model.C5 = pyo.ConstraintList()
model.C6 = pyo.ConstraintList()
model.C7 = pyo.ConstraintList()
for t in model.T:
model.C1.add(model.QEl[t] * model.EtaCharge == model.QCharge[t])
model.C2.add(model.QDischarge[t] * model.EtaDischarge == Demand[t])
model.C3.add(model.Charge[t] + model.Discharge[t] <= 1)
model.C4.add(model.QCharge[t] >= model.PMinCharge*model.Charge[t])
model.C5.add(model.QCharge[t] <= model.PMaxCharge*model.Charge[t])
model.C6.add(model.QDischarge[t] >= model.PMinDischarge*model.Discharge[t])
model.C7.add(model.QDischarge[t] <= model.PMaxDischarge*model.Discharge[t])
def SOC_storage(model,t):
if t == 0:
return (model.SOC[t] == model.S0+ model.QCharge[t]-model.QDischarge[t])
else:
return (model.SOC[t] == model.SOC[t-1] + model.QCharge[t] - model.QDischarge[t])
model.C8 = pyo.Constraint(model.T,rule = SOC_storage)
model.C9 = pyo.Constraint(expr = model.S0 == model.SOC[len(tot_time)-1])
##Objective
model.objective = pyo.Objective(expr = sum(model.QEl[t]*Price[t] for t in model.T), sense = pyo.minimize)
opt=SolverFactory('glpk')
results = opt.solve(model, tee = True)
model.write("myfile_lp.lp", io_options={'symbolic_solver_labels':True})
results.solver.status
results.solver.termination_condition
model.pprint()
value(model.objective)实际上,代码运行很顺利。然而,我如何能够插入条件,不购买电力(Charget=0)只有在特定的时间?假设电池不能每天8点到15点之间充电?我试过:
day_stop=np.arange(8,15,1) # Index of hours When we don't charge
week_stop= np.concatenate([day_stop+24*j for j in range(0,7)]) # Index of hours When we don't charge for the first week
year_stop = np.concatenate([week_stop+168*j for j in range(0,52)]) # Index of hours When we don't charge for the all year
def NoCharge(model,t):
if t in year_stop :
return model.Charge[t]==0
else:
return Constraint.Skip
model.C10 = pyo.Constraint(model.T,rule = NoCharge)运行代码后的所有变量都等于零或零。我是否以错误的方式提出约束?
你知道如何更好地制定最新的约束条件吗?非常感谢你的帮助!
发布于 2022-09-05 16:17:37
您使用NoCharge函数的方法似乎是正确的。没有数据就很难排除故障。所以..。我编造了一些。
一些建议:
E 210检查解决程序状态E 111之前的E 212评估您的模型。我敢打赌,当你在约束条件中加上这个模型是不可行的时,我赌5美元。因此,在解决问题时,您可能需要放宽充放电限制。
编辑...我想起了另外几件事..。先让它起作用,然后考虑一下这些.
,您可能可以消除一个充放电二进制变量,因为它们是相互排斥的(由约束强制执行)。所以charge = 1 - discharge是真的,允许电荷等于零,所以“空闲”包含在内。您只需在需要时包含两个二进制文件中的一个,并在需要时使用"1 -“结构。您可能想要添加另一个电源,并在需求>可以产生什么以及电池无法跟上的情况下对其进行成本计算。添加一个“开销”电源变量并将其添加到您的OBJ中是很容易的,只需付出一些小小的代价。这将使您的模型更具弹性,从而帮助您保持模型的可行性。如果您的模型执行速度变慢,您可能应该将您的时间步骤增加到2,4,……小时或直接将“夜间时间”放入一大块,以减小的大小
无论如何,下面的工作和产生的结果。我使用了您的C10约束,您可以切换它和C11,看看它是否在输出中工作。C11与C10是冗余的,只显示了一个备用结构.你可以任意使用。
代码:
import pyomo.environ as pyo
model = pyo.ConcreteModel()
##Parameters
tot_time=10 #Hours in a year
Demand = [0, 2, 3, 0, 0, 3, 3, 0, 0, 3]
Price = [0.5 for t in range(tot_time)]
model.T=pyo.Set(initialize=[t for t in range(0,tot_time)])
model.EtaCharge=pyo.Param(initialize=1.0, mutable=True) #-
model.PMinCharge=0 #MW
model.PMaxCharge=5 #MW
model.EtaDischarge=pyo.Param(initialize=1.0, mutable=True) #-
model.PMinDischarge=2 #MW
model.PMaxDischarge=4 #MW
model.S0=pyo.Param(initialize=10, mutable=True) #MWh SOC at t=0
##Variables
model.QEl = pyo.Var(model.T, within=pyo.NonNegativeReals, initialize=0)
model.QCharge= pyo.Var(model.T, within=pyo.NonNegativeReals)
model.QDischarge= pyo.Var(model.T, within=pyo.NonNegativeReals)
model.Charge=pyo.Var(model.T, within = pyo.Binary)
model.Discharge=pyo.Var(model.T, within = pyo.Binary)
model.SOC=pyo.Var(model.T, bounds=(0,100)) #Size of the battery limited to 100 MWh
##Constraints
model.C1 = pyo.ConstraintList()
model.C2 = pyo.ConstraintList()
model.C3 = pyo.ConstraintList()
model.C4 = pyo.ConstraintList()
model.C5 = pyo.ConstraintList()
model.C6 = pyo.ConstraintList()
model.C7 = pyo.ConstraintList()
for t in model.T:
model.C1.add(model.QEl[t] * model.EtaCharge == model.QCharge[t])
model.C2.add(model.QDischarge[t] * model.EtaDischarge == Demand[t])
model.C3.add(model.Charge[t] + model.Discharge[t] <= 1)
model.C4.add(model.QCharge[t] >= model.PMinCharge*model.Charge[t])
model.C5.add(model.QCharge[t] <= model.PMaxCharge*model.Charge[t])
model.C6.add(model.QDischarge[t] >= model.PMinDischarge*model.Discharge[t])
model.C7.add(model.QDischarge[t] <= model.PMaxDischarge*model.Discharge[t])
def SOC_storage(model,t):
if t == 0:
return (model.SOC[t] == model.S0 + model.QCharge[t] - model.QDischarge[t])
else:
return (model.SOC[t] == model.SOC[t-1] + model.QCharge[t] - model.QDischarge[t])
model.C8 = pyo.Constraint(model.T,rule = SOC_storage)
model.C9 = pyo.Constraint(expr = model.S0 == model.SOC[tot_time-1])
def NoCharge(model,t):
if t in no_charge_zone :
return model.Charge[t]==0
else:
return pyo.Constraint.Skip
no_charge_zone = [7, 8]
model.C10 = pyo.Constraint(model.T,rule = NoCharge)
# The below C11 is redundant with C10... It just shows a different approach.
# I think this is cleaner.... Just make a subset from your "prohibited" time periods
# and pass that in...
def NoCharge2(model, t):
return model.Charge[t] == 0
model.C11 = pyo.Constraint(no_charge_zone, rule=NoCharge2)
##Objective
model.objective = pyo.Objective(expr = sum(model.QEl[t]*Price[t] for t in model.T), sense = pyo.minimize)
opt=pyo.SolverFactory('glpk')
results = opt.solve(model, tee = True)
#model.write("myfile_lp.lp", io_options={'symbolic_solver_labels':True})
results.solver.status
results.solver.termination_condition
#model.pprint()
model.Charge.display()
model.SOC.display()
#print(pyo.value(model.objective))输出:
INTEGER OPTIMAL SOLUTION FOUND
Time used: 0.0 secs
Memory used: 0.1 Mb (87515 bytes)
Writing MIP solution to '/var/folders/rt/5gc2md7s7y5bw8ddt74tz5vw0000gp/T/tmpi82nq7rg.glpk.raw'...
154 lines were written
Charge : Size=10, Index=T
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 1.0 : 1 : False : False : Binary
1 : 0 : 0.0 : 1 : False : False : Binary
2 : 0 : 0.0 : 1 : False : False : Binary
3 : 0 : 1.0 : 1 : False : False : Binary
4 : 0 : 1.0 : 1 : False : False : Binary
5 : 0 : 0.0 : 1 : False : False : Binary
6 : 0 : 0.0 : 1 : False : False : Binary
7 : 0 : 0.0 : 1 : False : False : Binary
8 : 0 : 0.0 : 1 : False : False : Binary
9 : 0 : 0.0 : 1 : False : False : Binary
SOC : Size=10, Index=T
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : 14.0 : 100 : False : False : Reals
1 : 0 : 12.0 : 100 : False : False : Reals
2 : 0 : 9.0 : 100 : False : False : Reals
3 : 0 : 14.0 : 100 : False : False : Reals
4 : 0 : 19.0 : 100 : False : False : Reals
5 : 0 : 16.0 : 100 : False : False : Reals
6 : 0 : 13.0 : 100 : False : False : Reals
7 : 0 : 13.0 : 100 : False : False : Reals
8 : 0 : 13.0 : 100 : False : False : Reals
9 : 0 : 10.0 : 100 : False : False : Realshttps://stackoverflow.com/questions/73610201
复制相似问题