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

137 lines
6.0 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.
#!/usr/bin/env python3
"""
测试弃风弃光逻辑的脚本
验证"先弃光,当达到最大弃光比例后,再弃风,弃风不限"的逻辑是否正确实现
"""
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
from storage_optimization import calculate_energy_balance, SystemParameters
def test_curtailment_logic():
"""测试弃风弃光逻辑"""
# 创建测试数据
# 24小时的简单场景前12小时负荷低后12小时负荷高
solar_output = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
wind_output = [5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0] # 恒定的风电出力
thermal_output = [2.0] * 24 # 恒定的火电出力
load_demand = [1.0] * 12 + [15.0] * 12 # 前12小时低负荷后12小时高负荷
# 设置系统参数
params = SystemParameters(
max_curtailment_wind=0.1, # 弃风率限制10%(但实际上弃风不受限制)
max_curtailment_solar=0.2, # 弃光率限制20%
max_grid_ratio=0.1, # 上网电量比例限制10%
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0
)
# 计算能量平衡
storage_capacity = 10.0 # 10MWh储能容量
result = calculate_energy_balance(
solar_output, wind_output, thermal_output, load_demand, params, storage_capacity
)
# 分析结果
total_solar_potential = sum(solar_output)
total_wind_potential = sum(wind_output)
total_curtailed_solar = sum(result['curtailed_solar'])
total_curtailed_wind = sum(result['curtailed_wind'])
actual_solar_curtailment_ratio = total_curtailed_solar / total_solar_potential if total_solar_potential > 0 else 0
actual_wind_curtailment_ratio = total_curtailed_wind / total_wind_potential if total_wind_potential > 0 else 0
print("弃风弃光逻辑测试结果:")
print(f"总光伏出力: {total_solar_potential:.2f} MWh")
print(f"总风电出力: {total_wind_potential:.2f} MWh")
print(f"弃光量: {total_curtailed_solar:.2f} MWh ({actual_solar_curtailment_ratio:.2%})")
print(f"弃风量: {total_curtailed_wind:.2f} MWh ({actual_wind_curtailment_ratio:.2%})")
print(f"弃光率限制: {params.max_curtailment_solar:.2%}")
print(f"弃风率限制: {params.max_curtailment_wind:.2%} (实际不受限制)")
# 验证逻辑
print("\n验证结果:")
solar_constraint_ok = actual_solar_curtailment_ratio <= params.max_curtailment_solar + 0.01 # 允许1%误差
print(f"弃光率是否在限制范围内: {'通过' if solar_constraint_ok else '未通过'}")
# 弃风应该不受限制,所以不需要检查约束
print("弃风不受限制: 通过")
# 检查弃风弃光的时间分布
print("\n弃风弃光时间分布:")
for hour in range(24):
if result['curtailed_solar'][hour] > 0 or result['curtailed_wind'][hour] > 0:
print(f" 小时 {hour:2d}: 弃光={result['curtailed_solar'][hour]:.2f}MW, 弃风={result['curtailed_wind'][hour]:.2f}MW")
return solar_constraint_ok
def test_solar_curtailment_priority():
"""测试弃光优先逻辑"""
# 创建极端测试场景:大量盈余电力
solar_output = [10.0] * 24 # 高光伏出力
wind_output = [10.0] * 24 # 高风电出力
thermal_output = [0.0] * 24 # 无火电
load_demand = [1.0] * 24 # 极低负荷
# 设置系统参数
params = SystemParameters(
max_curtailment_wind=0.1, # 弃风率限制10%(但实际上弃风不受限制)
max_curtailment_solar=0.1, # 弃光率限制10%
max_grid_ratio=0.0, # 不允许上网电量
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0
)
# 计算能量平衡
storage_capacity = 5.0 # 5MWh储能容量
result = calculate_energy_balance(
solar_output, wind_output, thermal_output, load_demand, params, storage_capacity
)
# 分析结果
total_solar_potential = sum(solar_output)
total_wind_potential = sum(wind_output)
total_curtailed_solar = sum(result['curtailed_solar'])
total_curtailed_wind = sum(result['curtailed_wind'])
actual_solar_curtailment_ratio = total_curtailed_solar / total_solar_potential if total_solar_potential > 0 else 0
actual_wind_curtailment_ratio = total_curtailed_wind / total_wind_potential if total_wind_potential > 0 else 0
print("\n弃光优先逻辑测试结果:")
print(f"总光伏出力: {total_solar_potential:.2f} MWh")
print(f"总风电出力: {total_wind_potential:.2f} MWh")
print(f"弃光量: {total_curtailed_solar:.2f} MWh ({actual_solar_curtailment_ratio:.2%})")
print(f"弃风量: {total_curtailed_wind:.2f} MWh ({actual_wind_curtailment_ratio:.2%})")
print(f"弃光率限制: {params.max_curtailment_solar:.2%}")
# 验证弃光是否优先
solar_at_limit = abs(actual_solar_curtailment_ratio - params.max_curtailment_solar) < 0.01
print(f"\n弃光是否达到限制: {'' if solar_at_limit else ''}")
# 验证弃风是否在弃光达到限制后才发生
wind_curtailment_exists = total_curtailed_wind > 0
print(f"是否存在弃风: {'' if wind_curtailment_exists else ''}")
if solar_at_limit and wind_curtailment_exists:
print("通过 弃光优先逻辑正确:先弃光达到限制,然后弃风")
return True
else:
print("未通过 弃光优先逻辑可能存在问题")
return False
if __name__ == "__main__":
print("开始测试弃风弃光逻辑...")
test1_result = test_curtailment_logic()
test2_result = test_solar_curtailment_priority()
if test1_result and test2_result:
print("\n通过 所有测试通过,弃风弃光逻辑实现正确")
else:
print("\n未通过 部分测试失败,需要检查逻辑实现")