You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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()

代码修改说明

  1. 来水建模:将原rain Generator改为reservoir inflow,用p_set固定时段来水量,设置dispatch='fix'确保来水全部注入水库,不会直接进入电网
  2. 水库配置:设置固定的e_nom和e_initial,移除e_nom_extendable,锁定水库容量参数
  3. 涡轮配置:设置固定的p_nom,移除p_nom_extendable,限制涡轮最大出力
  4. 可视化补充:增加水库库容变化图表,直观观察水库能量动态平衡

修复后的效果

  • 涡轮发电功率被限制在额定出力范围内
  • 来水正确注入水库,不会被误计为电网发电量
  • 初始库容生效,水库库容随来水和发电动态变化
  • 优化逻辑符合单水库多时段调度的预期

内容的提问来源于stack exchange,提问作者user23789054

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:18:12