Files
multi_energy_complementarity/tests/test_grid_priority.py
2025-12-27 19:15:56 +08:00

216 lines
8.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
测试优先上网逻辑
该程序创建一个测试场景,验证系统是否优先上网而不是弃风弃光。
作者: iFlow CLI
创建日期: 2025-12-26
"""
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'src'))
import pandas as pd
from excel_reader import create_excel_template
from storage_optimization import optimize_storage_capacity, SystemParameters
def create_test_excel():
"""创建测试用的Excel文件有明显的发电盈余"""
# 创建24小时数据其中某些小时有大量盈余
hours = 24
# 设计数据在6-12点有大量光伏出力超过负荷
solar = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.0, 15.0, 20.0, 20.0, 15.0, 10.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
wind = [2.0] * 24 # 稳定的风电
thermal = [3.0] * 24 # 稳定的火电
load = [5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 8.0, 8.0, 9.0, 9.0, 8.0, 8.0, 6.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0]
# 验证长度
print(f"数据长度检查: solar={len(solar)}, wind={len(wind)}, thermal={len(thermal)}, load={len(load)}")
# 设置严格的上网电量限制10%),迫使系统在超出限制时弃风弃光
params = SystemParameters(
max_curtailment_wind=0.15, # 允许15%弃风
max_curtailment_solar=0.15, # 允许15%弃光
max_grid_ratio=0.1, # 严格限制上网电量比例10%
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0,
max_storage_capacity=5.0 # 限制储能容量,增加上网压力
)
# 创建DataFrame
df = pd.DataFrame({
'小时': range(1, hours + 1),
'光伏出力(MW)': solar,
'风电出力(MW)': wind,
'火电出力(MW)': thermal,
'负荷需求(MW)': load
})
# 保存到Excel
filename = 'test_grid_priority.xlsx'
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='数据', index=False)
# 添加参数工作表
parameters_df = pd.DataFrame({
'参数名称': [
'最大弃风率',
'最大弃光率',
'最大上网电量比例',
'储能效率',
'放电倍率',
'充电倍率',
'最大储能容量'
],
'参数值': [
0.15, # 最大弃风率
0.15, # 最大弃光率
0.1, # 最大上网电量比例(严格限制)
0.9, # 储能效率
1.0, # 放电倍率
1.0, # 充电倍率
5.0 # 最大储能容量(限制)
],
'参数说明': [
'允许的最大弃风率0.0-1.0',
'允许的最大弃光率0.0-1.0',
'允许的最大上网电量比例0.0-∞,只限制上网电量)',
'储能充放电效率0.0-1.0',
'储能放电倍率C-rate>0',
'储能充电倍率C-rate>0',
'储能容量上限MWh空表示无限制'
],
'取值范围': [
'0.0-1.0',
'0.0-1.0',
'≥0.0',
'0.0-1.0',
'>0',
'>0',
'>0或空'
],
'默认值': [
'0.1',
'0.1',
'0.2',
'0.9',
'1.0',
'1.0',
'无限制'
]
})
parameters_df.to_excel(writer, sheet_name='参数', index=False)
# 添加说明工作表
description_df = pd.DataFrame({
'项目': ['数据说明', '数据类型', '时间范围', '单位', '注意事项', '参数说明'],
'内容': [
'测试优先上网逻辑的数据',
'24小时电力数据',
'1-24小时',
'MW (兆瓦)',
'所有数值必须为非负数',
'设置了严格的上网电量限制(10%)和储能容量限制(5MWh)'
]
})
description_df.to_excel(writer, sheet_name='说明', index=False)
print(f"测试Excel文件已创建{filename}")
return filename
def test_grid_priority():
"""测试优先上网逻辑"""
print("=== 测试优先上网逻辑 ===\n")
# 创建测试文件
test_file = create_test_excel()
# 从Excel读取数据
from excel_reader import read_excel_data
data = read_excel_data(test_file, include_parameters=True)
solar_output = data['solar_output']
wind_output = data['wind_output']
thermal_output = data['thermal_output']
load_demand = data['load_demand']
params = data['system_parameters']
print("测试数据概况:")
print(f"光伏出力范围: {min(solar_output):.1f} - {max(solar_output):.1f} MW")
print(f"风电出力: {wind_output[0]:.1f} MW (恒定)")
print(f"火电出力: {thermal_output[0]:.1f} MW (恒定)")
print(f"负荷需求范围: {min(load_demand):.1f} - {max(load_demand):.1f} MW")
print(f"\n系统参数:")
print(f"最大上网电量比例: {params.max_grid_ratio}")
print(f"最大储能容量: {params.max_storage_capacity} MWh")
print(f"最大弃风率: {params.max_curtailment_wind}")
print(f"最大弃光率: {params.max_curtailment_solar}")
# 计算总发电量和负荷
total_generation = sum(solar_output) + sum(wind_output) + sum(thermal_output)
total_load = sum(load_demand)
total_surplus = total_generation - total_load
print(f"\n能量平衡:")
print(f"总发电量: {total_generation:.1f} MWh")
print(f"总负荷: {total_load:.1f} MWh")
print(f"总盈余: {total_surplus:.1f} MWh")
# 运行优化
print("\n正在运行储能容量优化...")
result = optimize_storage_capacity(
solar_output, wind_output, thermal_output, load_demand, params
)
# 分析结果
total_grid_feed_in = sum(result['grid_feed_in'])
total_curtailed_wind = sum(result['curtailed_wind'])
total_curtailed_solar = sum(result['curtailed_solar'])
print(f"\n=== 优化结果 ===")
print(f"所需储能容量: {result['required_storage_capacity']:.2f} MWh")
print(f"实际上网电量: {total_grid_feed_in:.2f} MWh")
print(f"上网电量比例: {result['total_grid_feed_in_ratio']:.3f}")
print(f"弃风量: {total_curtailed_wind:.2f} MWh")
print(f"弃光量: {total_curtailed_solar:.2f} MWh")
print(f"弃风率: {result['total_curtailment_wind_ratio']:.3f}")
print(f"弃光率: {result['total_curtailment_solar_ratio']:.3f}")
# 验证优先上网逻辑
max_allowed_grid = total_generation * params.max_grid_ratio
print(f"\n=== 验证优先上网逻辑 ===")
print(f"最大允许上网电量: {max_allowed_grid:.2f} MWh")
print(f"实际上网电量: {total_grid_feed_in:.2f} MWh")
if abs(total_grid_feed_in - max_allowed_grid) < 1.0: # 允许1MW误差
print("[OK] 验证通过:系统优先上网,达到上网电量限制上限")
else:
print("[ERROR] 验证失败:系统未充分利用上网电量限制")
if total_curtailed_wind > 0 or total_curtailed_solar > 0:
print("[OK] 验证通过:在上网电量限制达到后,系统开始弃风弃光")
else:
print("[INFO] 注意:没有弃风弃光,可能盈余电力全部被储能或上网消化")
# 查看具体小时的弃风弃光情况
print(f"\n=== 详细分析(盈余时段) ===")
for hour in range(6, 13): # 6-12点是光伏出力高峰
available = solar_output[hour] + wind_output[hour] + thermal_output[hour]
demand = load_demand[hour]
surplus = available - demand
grid = result['grid_feed_in'][hour]
curtailed = result['curtailed_wind'][hour] + result['curtailed_solar'][hour]
if surplus > 0:
print(f"小时{hour}: 盈余{surplus:.1f}MW -> 上网{grid:.1f}MW + 弃风弃光{curtailed:.1f}MW")
print(f"\n测试完成!")
if __name__ == "__main__":
test_grid_priority()