基于PyPSA的单国家多时段水库水电优化代码问题咨询
PyPSA单水库多时段优化:关键属性配置与运行异常修复
核心问题梳理
当前代码存在以下关键问题:
- 未配置水库容量、涡轮额定出力、初始库容这些核心参数
- 用
p_nom_extendable=True导致涡轮出力无限制,水库容量被优化器自由调整 - 对降雨(来水)的建模逻辑有误,导致其被误计入电网发电量
关键属性的正确配置方法
1. 水库容量与初始库容
通过Store组件设置:
e_nom:固定水库总容量(单位:MWh)e_initial:设置初始库容(单位:MWh),或用e_initial_pu设置初始库容占总容量的比例(0-1区间)- 移除
e_nom_extendable=True,避免优化器随意调整水库容量
2. 涡轮额定出力
通过Link组件设置:
p_nom:固定涡轮最大出力(单位:MW)- 移除
p_nom_extendable=True,确保涡轮发电功率被限制在额定值内
3. 来水量(降雨)
来水是注入水库的能量,需通过连接到reservoir母线的Generator建模:
p_set:直接设置每个时段的来水量(单位:MW,对应1小时时段的MWh值)- 若用
p_max_pu,需配合p_nom计算实际来水量,同时设置dispatch='fix'确保来水全部注入水库
修正后的完整代码
import pypsa import pandas as pd import numpy as np import matplotlib.pyplot as plt country = "South Africa" network = pypsa.Network() # 设置4个小时的优化时段 network.set_snapshots(pd.date_range("2016-01-01 00:00", "2016-01-01 03:00", freq="h")) # 电网母线(承担负荷与其他电源连接) network.add("Bus", country, carrier="AC") # 水库专用母线(用于能量平衡:来水-发电=库容变化) network.add("Bus", "reservoir bus", carrier="reservoir") # -------------------------- # 1. 配置来水量(降雨):注入水库的能量 # -------------------------- # 每个时段来水量(MW,对应1小时即MWh) inflow_mw = [50, 100, 300, 200] network.add( "Generator", "reservoir inflow", bus="reservoir bus", carrier="inflow", p_set=inflow_mw, # 固定来水量,全部注入水库 marginal_cost=0, dispatch='fix' # 强制全部调度,确保来水不浪费 ) # -------------------------- # 2. 配置水库:容量与初始库容 # -------------------------- network.add( "Store", "reservoir storage", bus="reservoir bus", e_nom=10000, # 水库总容量10000 MWh e_initial=5000, # 初始库容5000 MWh(或用e_initial_pu=0.5表示50%库容) e_cyclic=False, # 若不需要期末库容等于初始,设为False;循环调度设为True ) # -------------------------- # 3. 配置涡轮机:额定出力与效率 # -------------------------- network.add( "Link", "hydro turbine", bus0="reservoir bus", bus1=country, efficiency=0.85, # 涡轮发电效率:水库能量转电网能量的比例 p_nom=800, # 涡轮最大出力800 MW capital_cost=0, ) # -------------------------- # 其他电源配置(保留原逻辑) # -------------------------- marginal_costs = {"Wind": 0, "Coal": 80, "Gas": 130, "Oil": 180} power_plant_p_nom = { "South Africa": {"Wind": 400, "Coal": 1000, "Gas": 1000, "Oil": 300} } for tech in power_plant_p_nom[country]: network.add( "Generator", f"{country} {tech}", bus=country, p_nom=power_plant_p_nom[country][tech], marginal_cost=marginal_costs[tech], p_max_pu=([0.2, 0.8, 0.5, 0.7] if tech == "Wind" else 1), ) # -------------------------- # 负荷配置(保留原逻辑) # -------------------------- loads = {"South Africa": 1500} network.add( "Load", f"{country} load", bus=country, p_set=loads[country] + np.array([-700, 700, -1000, 1000]) ) # 运行优化 network.optimize() # -------------------------- # 结果输出与可视化 # -------------------------- print("优化目标值:", network.objective) # 各电源发电出力 network.generators_t.p.plot.area(figsize=(9, 4)) plt.title("各电源发电出力") plt.tight_layout() # 涡轮发电出力 network.links_t.p0.plot(figsize=(9, 4), lw=3) plt.title("涡轮发电出力") plt.tight_layout() # 水库库容变化 network.stores_t.e.plot(figsize=(9, 4), lw=3) plt.title("水库库容变化") plt.tight_layout() # 输出关键结果 print("\n负荷消耗:") print(network.loads_t.p) print("\n电源调度:") print(network.generators_t.p) print("\n涡轮出力:") print(network.links_t.p0) print("\n节点边际电价:") print(network.buses_t.marginal_price) plt.show()
代码修改说明
- 来水建模:将原
rainGenerator改为reservoir inflow,用p_set固定时段来水量,设置dispatch='fix'确保来水全部注入水库,不会直接进入电网 - 水库配置:设置固定的
e_nom和e_initial,移除e_nom_extendable,锁定水库容量参数 - 涡轮配置:设置固定的
p_nom,移除p_nom_extendable,限制涡轮最大出力 - 可视化补充:增加水库库容变化图表,直观观察水库能量动态平衡
修复后的效果
- 涡轮发电功率被限制在额定出力范围内
- 来水正确注入水库,不会被误计为电网发电量
- 初始库容生效,水库库容随来水和发电动态变化
- 优化逻辑符合单水库多时段调度的预期
内容的提问来源于stack exchange,提问作者user23789054
相关产品推荐
相关产品推荐

