Files
multi_energy_complementarity/scripts/solar_optimization_examples.py

542 lines
18 KiB
Python
Raw Normal View History

2025-12-27 10:49:32 +08:00
"""
光伏优化模块场景示例
该文件展示了光伏优化模块在不同场景下的应用包括
1. 典型日场景 - 基础优化示例
2. 高负荷场景 - 夏季高峰用电场景
3. 低负荷场景 - 春秋季低负荷场景
4. 风光互补场景 - 风电和光伏协同优化
5. 储能受限场景 - 储能容量受限情况下的优化
作者: iFlow CLI
创建日期: 2025-12-26
"""
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'src'))
import numpy as np
import matplotlib.pyplot as plt
from typing import List, Dict
from solar_optimization import optimize_solar_output, plot_optimization_results, export_optimization_results
from storage_optimization import SystemParameters
def scenario_1_typical_day():
"""
场景1典型日场景
- 标准24小时负荷曲线
- 适中风光出力
- 常规系统参数
"""
print("=" * 60)
print("场景1典型日场景 - 基础优化示例")
print("=" * 60)
# 典型日光伏出力(中午高峰)
solar_output = [0.0] * 6 + [0.5, 1.0, 2.0, 3.5, 5.0, 6.0, 5.5, 4.0, 2.5, 1.0, 0.5, 0.0] + [0.0] * 6
# 典型日风电出力(夜间和早晨较高)
wind_output = [4.0, 5.0, 4.5, 3.5, 2.5, 2.0, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.0, 3.0, 4.0, 5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0]
# 火电基础出力
thermal_output = [8.0] * 24
# 典型日负荷曲线(早晚高峰)
load_demand = [2.0, 2.5, 3.0, 4.0, 6.0, 9.0, 12.0, 15.0, 18.0, 20.0, 19.0, 18.0,
17.0, 16.0, 18.0, 19.0, 20.0, 18.0, 15.0, 12.0, 8.0, 5.0, 3.0, 2.0]
# 标准系统参数
params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.15,
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0,
rated_thermal_capacity=100.0,
rated_solar_capacity=50.0,
rated_wind_capacity=50.0,
available_thermal_energy=2000.0,
available_solar_energy=400.0,
available_wind_energy=600.0
)
# 执行优化
result = optimize_solar_output(
solar_output, wind_output, thermal_output, load_demand, params
)
# 输出结果
print_scenario_result("典型日场景", result)
# 绘制结果
plot_optimization_results(result, show_window=False)
# 导出结果
filename = export_optimization_results(result, "scenario_1_typical_day.xlsx")
return result
def scenario_2_high_load():
"""
场景2高负荷场景
- 夏季高温空调负荷高
- 白天负荷特别高
- 光伏出力与负荷匹配度较低
"""
print("=" * 60)
print("场景2高负荷场景 - 夏季高峰用电")
print("=" * 60)
# 夏季光伏出力(较强)
solar_output = [0.0] * 5 + [0.8, 1.5, 3.0, 4.5, 6.0, 7.5, 8.0, 7.0, 5.0, 3.0, 1.5, 0.5, 0.0, 0.0] + [0.0] * 5
# 夏季风电出力(相对较低)
wind_output = [2.0, 2.5, 3.0, 2.5, 2.0, 1.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.5, 2.0, 2.5, 3.0, 2.5, 2.0, 1.8, 1.6, 1.4, 1.2, 1.0, 0.8]
# 火电高峰出力
thermal_output = [12.0] * 24
# 夏季高负荷曲线(空调导致白天负荷极高)
load_demand = [3.0, 3.5, 4.0, 5.0, 8.0, 12.0, 18.0, 25.0, 30.0, 32.0, 31.0, 30.0,
29.0, 28.0, 30.0, 31.0, 32.0, 28.0, 22.0, 18.0, 12.0, 8.0, 5.0, 3.0]
# 高负荷场景参数(更宽松的弃风弃光限制)
params = SystemParameters(
max_curtailment_wind=0.15,
max_curtailment_solar=0.15,
max_grid_ratio=0.25,
storage_efficiency=0.85,
discharge_rate=1.2,
charge_rate=1.2,
rated_thermal_capacity=150.0,
rated_solar_capacity=80.0,
rated_wind_capacity=40.0,
available_thermal_energy=3000.0,
available_solar_energy=600.0,
available_wind_energy=400.0
)
# 执行优化
result = optimize_solar_output(
solar_output, wind_output, thermal_output, load_demand, params
)
# 输出结果
print_scenario_result("高负荷场景", result)
# 绘制结果
plot_optimization_results(result, show_window=False)
# 导出结果
filename = export_optimization_results(result, "scenario_2_high_load.xlsx")
return result
def scenario_3_low_load():
"""
场景3低负荷场景
- 春秋季负荷较低
- 光伏出力相对较高
- 容易出现电力盈余
"""
print("=" * 60)
print("场景3低负荷场景 - 春秋季低负荷")
print("=" * 60)
# 春秋季光伏出力(适中)
solar_output = [0.0] * 6 + [1.0, 2.0, 3.5, 5.0, 6.5, 7.0, 6.5, 5.0, 3.5, 2.0, 1.0, 0.0] + [0.0] * 6
# 春秋季风电出力(较好)
wind_output = [5.0, 6.0, 5.5, 4.5, 3.5, 3.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 3.0, 4.0, 5.0, 6.0, 5.5, 5.0, 4.5, 4.0, 3.5, 3.0, 2.5, 2.0]
# 火电基础出力(较低)
thermal_output = [5.0] * 24
# 春秋季低负荷曲线
load_demand = [2.0, 2.2, 2.5, 3.0, 4.0, 6.0, 8.0, 10.0, 12.0, 13.0, 12.5, 12.0,
11.5, 11.0, 12.0, 12.5, 13.0, 11.0, 9.0, 7.0, 5.0, 3.5, 2.5, 2.0]
# 低负荷场景参数(更严格的弃风弃光限制)
params = SystemParameters(
max_curtailment_wind=0.05,
max_curtailment_solar=0.05,
max_grid_ratio=0.1,
storage_efficiency=0.92,
discharge_rate=0.8,
charge_rate=0.8,
rated_thermal_capacity=80.0,
rated_solar_capacity=60.0,
rated_wind_capacity=60.0,
available_thermal_energy=1500.0,
available_solar_energy=500.0,
available_wind_energy=700.0
)
# 执行优化
result = optimize_solar_output(
solar_output, wind_output, thermal_output, load_demand, params
)
# 输出结果
print_scenario_result("低负荷场景", result)
# 绘制结果
plot_optimization_results(result, show_window=False)
# 导出结果
filename = export_optimization_results(result, "scenario_3_low_load.xlsx")
return result
def scenario_4_wind_solar_complement():
"""
场景4风光互补场景
- 风电和光伏出力时间互补性强
- 夜间风电高白天光伏高
- 系统整体平衡性较好
"""
print("=" * 60)
print("场景4风光互补场景 - 风电和光伏协同优化")
print("=" * 60)
# 光伏出力(标准日间模式)
solar_output = [0.0] * 6 + [0.5, 1.5, 3.0, 4.5, 6.0, 7.0, 6.0, 4.5, 3.0, 1.5, 0.5, 0.0] + [0.0] * 6
# 风电出力(与光伏互补,夜间和早晚较高)
wind_output = [8.0, 9.0, 8.5, 7.0, 5.0, 3.0, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 3.0, 5.0, 7.0, 8.0, 8.5, 8.0, 7.5, 7.0, 6.5, 6.0, 5.5, 5.0]
# 火电出力(作为补充)
thermal_output = [6.0] * 24
# 负荷曲线(相对平稳)
load_demand = [4.0, 4.5, 5.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 17.0, 16.5, 16.0,
15.5, 15.0, 16.0, 16.5, 17.0, 15.0, 13.0, 11.0, 9.0, 7.0, 5.0, 4.0]
# 风光互补场景参数
params = SystemParameters(
max_curtailment_wind=0.08,
max_curtailment_solar=0.08,
max_grid_ratio=0.12,
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0,
rated_thermal_capacity=100.0,
rated_solar_capacity=70.0,
rated_wind_capacity=70.0,
available_thermal_energy=1800.0,
available_solar_energy=450.0,
available_wind_energy=800.0
)
# 执行优化
result = optimize_solar_output(
solar_output, wind_output, thermal_output, load_demand, params
)
# 输出结果
print_scenario_result("风光互补场景", result)
# 绘制结果
plot_optimization_results(result, show_window=False)
# 导出结果
filename = export_optimization_results(result, "scenario_4_wind_solar_complement.xlsx")
return result
def scenario_5_storage_limited():
"""
场景5储能受限场景
- 储能容量受限
- 需要更精确的光伏出力调节
- 对电网交换更敏感
"""
print("=" * 60)
print("场景5储能受限场景 - 储能容量受限情况下的优化")
print("=" * 60)
# 标准光伏出力
solar_output = [0.0] * 6 + [1.0, 2.0, 3.0, 4.5, 6.0, 7.0, 6.0, 4.5, 3.0, 2.0, 1.0, 0.0] + [0.0] * 6
# 标准风电出力
wind_output = [3.0, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.0, 3.0, 3.5, 4.0, 3.5, 3.0, 2.8, 2.6, 2.4, 2.2, 2.0, 1.8]
# 火电出力
thermal_output = [7.0] * 24
# 标准负荷曲线
load_demand = [3.0, 3.5, 4.0, 5.0, 7.0, 10.0, 13.0, 16.0, 18.0, 19.0, 18.5, 18.0,
17.5, 17.0, 18.0, 18.5, 19.0, 17.0, 14.0, 11.0, 8.0, 6.0, 4.0, 3.0]
# 储能受限场景参数储能容量限制为50MWh
params = SystemParameters(
max_curtailment_wind=0.12,
max_curtailment_solar=0.12,
max_grid_ratio=0.2,
storage_efficiency=0.88,
discharge_rate=1.5,
charge_rate=1.5,
max_storage_capacity=50.0, # 储能容量受限
rated_thermal_capacity=100.0,
rated_solar_capacity=60.0,
rated_wind_capacity=50.0,
available_thermal_energy=2000.0,
available_solar_energy=480.0,
available_wind_energy=550.0
)
# 执行优化
result = optimize_solar_output(
solar_output, wind_output, thermal_output, load_demand, params
)
# 输出结果
print_scenario_result("储能受限场景", result)
# 绘制结果
plot_optimization_results(result, show_window=False)
# 导出结果
filename = export_optimization_results(result, "scenario_5_storage_limited.xlsx")
return result
def print_scenario_result(scenario_name: str, result):
"""
打印场景优化结果
Args:
scenario_name: 场景名称
result: 优化结果
"""
print(f"\n=== {scenario_name}优化结果 ===")
print(f"最优光伏系数: {result.optimal_solar_coefficient:.3f}")
print(f"最小电网交换电量: {result.min_grid_exchange:.2f} MWh")
print(f" - 购电量: {result.grid_purchase:.2f} MWh")
print(f" - 上网电量: {result.grid_feed_in:.2f} MWh")
print(f"所需储能容量: {result.storage_result['required_storage_capacity']:.2f} MWh")
print(f"优化后弃风率: {result.storage_result['total_curtailment_wind_ratio']:.3f}")
print(f"优化后弃光率: {result.storage_result['total_curtailment_solar_ratio']:.3f}")
print(f"优化后上网电量比例: {result.storage_result['total_grid_feed_in_ratio']:.3f}")
# 分析优化效果
if result.optimal_solar_coefficient > 1.0:
print(f"分析:建议将光伏出力提高 {(result.optimal_solar_coefficient - 1.0) * 100:.1f}% 以减少电网依赖")
elif result.optimal_solar_coefficient < 1.0:
print(f"分析:建议将光伏出力降低 {(1.0 - result.optimal_solar_coefficient) * 100:.1f}% 以避免电力过剩")
else:
print("分析:当前光伏出力已经是最优配置")
def compare_scenarios(results: List[Dict]):
"""
对比不同场景的优化结果
Args:
results: 各场景优化结果列表
"""
print("\n" + "=" * 80)
print("场景对比分析")
print("=" * 80)
scenario_names = [
"典型日场景",
"高负荷场景",
"低负荷场景",
"风光互补场景",
"储能受限场景"
]
# 创建对比表格
print(f"{'场景名称':<12} {'最优系数':<8} {'电网交换(MWh)':<12} {'购电量(MWh)':<10} {'上网电量(MWh)':<12} {'储能容量(MWh)':<12}")
print("-" * 80)
for i, (name, result) in enumerate(zip(scenario_names, results)):
print(f"{name:<12} {result.optimal_solar_coefficient:<8.3f} "
f"{result.min_grid_exchange:<12.2f} {result.grid_purchase:<10.2f} "
f"{result.grid_feed_in:<12.2f} {result.storage_result['required_storage_capacity']:<12.2f}")
# 分析趋势
print("\n=== 趋势分析 ===")
# 找出最优和最差场景
min_exchange_result = min(results, key=lambda x: x.min_grid_exchange)
max_exchange_result = max(results, key=lambda x: x.min_grid_exchange)
min_exchange_idx = results.index(min_exchange_result)
max_exchange_idx = results.index(max_exchange_result)
print(f"电网交换最小场景:{scenario_names[min_exchange_idx]} ({min_exchange_result.min_grid_exchange:.2f} MWh)")
print(f"电网交换最大场景:{scenario_names[max_exchange_idx]} ({max_exchange_result.min_grid_exchange:.2f} MWh)")
# 分析光伏系数趋势
avg_coefficient = sum(r.optimal_solar_coefficient for r in results) / len(results)
print(f"平均最优光伏系数:{avg_coefficient:.3f}")
high_coefficient_scenarios = [name for name, result in zip(scenario_names, results)
if result.optimal_solar_coefficient > avg_coefficient]
low_coefficient_scenarios = [name for name, result in zip(scenario_names, results)
if result.optimal_solar_coefficient < avg_coefficient]
if high_coefficient_scenarios:
print(f"需要提高光伏出力的场景:{', '.join(high_coefficient_scenarios)}")
if low_coefficient_scenarios:
print(f"需要降低光伏出力的场景:{', '.join(low_coefficient_scenarios)}")
def plot_scenario_comparison(results: List[Dict]):
"""
绘制场景对比图表
Args:
results: 各场景优化结果列表
"""
scenario_names = [
"典型日",
"高负荷",
"低负荷",
"风光互补",
"储能受限"
]
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# 创建图形
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))
fig.suptitle('光伏优化场景对比分析', fontsize=16, fontweight='bold')
# 1. 最优光伏系数对比
coefficients = [r.optimal_solar_coefficient for r in results]
bars1 = ax1.bar(scenario_names, coefficients, color='skyblue', alpha=0.7)
ax1.set_ylabel('最优光伏系数')
ax1.set_title('各场景最优光伏系数对比')
ax1.grid(True, alpha=0.3, axis='y')
ax1.axhline(y=1.0, color='red', linestyle='--', alpha=0.7, label='原始系数')
# 添加数值标签
for bar, coeff in zip(bars1, coefficients):
height = bar.get_height()
ax1.text(bar.get_x() + bar.get_width()/2., height + 0.01,
f'{coeff:.3f}', ha='center', va='bottom', fontweight='bold')
# 2. 电网交换电量对比
exchanges = [r.min_grid_exchange for r in results]
purchases = [r.grid_purchase for r in results]
feed_ins = [r.grid_feed_in for r in results]
x = np.arange(len(scenario_names))
width = 0.25
bars2 = ax2.bar(x - width, purchases, width, label='购电量', color='purple', alpha=0.7)
bars3 = ax2.bar(x, feed_ins, width, label='上网电量', color='brown', alpha=0.7)
bars4 = ax2.bar(x + width, exchanges, width, label='总交换电量', color='orange', alpha=0.7)
ax2.set_ylabel('电量 (MWh)')
ax2.set_title('电网交换电量对比')
ax2.set_xticks(x)
ax2.set_xticklabels(scenario_names)
ax2.legend()
ax2.grid(True, alpha=0.3, axis='y')
# 3. 储能容量需求对比
storage_capacities = [r.storage_result['required_storage_capacity'] for r in results]
bars5 = ax3.bar(scenario_names, storage_capacities, color='green', alpha=0.7)
ax3.set_ylabel('储能容量 (MWh)')
ax3.set_title('各场景储能容量需求对比')
ax3.grid(True, alpha=0.3, axis='y')
# 添加数值标签
for bar, capacity in zip(bars5, storage_capacities):
height = bar.get_height()
ax3.text(bar.get_x() + bar.get_width()/2., height + height*0.01,
f'{capacity:.1f}', ha='center', va='bottom', fontweight='bold')
# 4. 弃风弃光率对比
curtailment_winds = [r.storage_result['total_curtailment_wind_ratio'] for r in results]
curtailment_solars = [r.storage_result['total_curtailment_solar_ratio'] for r in results]
bars6 = ax4.bar(x - width/2, curtailment_winds, width, label='弃风率', color='blue', alpha=0.7)
bars7 = ax4.bar(x + width/2, curtailment_solars, width, label='弃光率', color='orange', alpha=0.7)
ax4.set_ylabel('弃风弃光率')
ax4.set_title('各场景弃风弃光率对比')
ax4.set_xticks(x)
ax4.set_xticklabels(scenario_names)
ax4.legend()
ax4.grid(True, alpha=0.3, axis='y')
# 调整布局
plt.tight_layout()
# 保存图片
plt.savefig('solar_optimization_scenario_comparison.png', dpi=300, bbox_inches='tight')
plt.close()
print("场景对比图表已保存为 'solar_optimization_scenario_comparison.png'")
def main():
"""主函数,运行所有场景示例"""
print("光伏优化模块场景示例")
print("运行5个不同场景的优化分析...")
# 运行所有场景
results = []
try:
# 场景1典型日场景
result1 = scenario_1_typical_day()
results.append(result1)
# 场景2高负荷场景
result2 = scenario_2_high_load()
results.append(result2)
# 场景3低负荷场景
result3 = scenario_3_low_load()
results.append(result3)
# 场景4风光互补场景
result4 = scenario_4_wind_solar_complement()
results.append(result4)
# 场景5储能受限场景
result5 = scenario_5_storage_limited()
results.append(result5)
# 对比分析
compare_scenarios(results)
# 绘制对比图表
plot_scenario_comparison(results)
print("\n" + "=" * 80)
print("所有场景示例运行完成!")
print("=" * 80)
print("生成的文件:")
print("- scenario_1_typical_day.xlsx")
print("- scenario_2_high_load.xlsx")
print("- scenario_3_low_load.xlsx")
print("- scenario_4_wind_solar_complement.xlsx")
print("- scenario_5_storage_limited.xlsx")
print("- solar_optimization_scenario_comparison.png")
except Exception as e:
print(f"运行场景示例时出错:{str(e)}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()