Files
multi_energy_complementarity/scripts/solar_scenarios_demo.py
2025-12-27 10:49:32 +08:00

420 lines
15 KiB
Python
Raw Permalink 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.
"""
光伏优化模块场景演示
该文件展示了光伏优化模块在不同场景下的应用,包括:
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 solar_optimization import optimize_solar_output, export_optimization_results
from storage_optimization import SystemParameters
def scenario_1_typical_day():
"""场景1典型日场景"""
print("=" * 60)
print("场景1典型日场景 - 基础优化示例")
print("=" * 60)
# 典型日数据24小时
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_solar_comparison(result, "典型日场景")
# 导出结果
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_solar_comparison(result, "高负荷场景")
# 导出结果
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_solar_comparison(result, "低负荷场景")
# 导出结果
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_solar_comparison(result, "风光互补场景")
# 导出结果
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]
# 储能受限场景参数
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_solar_comparison(result, "储能受限场景")
# 导出结果
export_optimization_results(result, "scenario_5_storage_limited.xlsx")
return result
def print_scenario_result(scenario_name: str, 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 plot_solar_comparison(result, scenario_name, show_window=True):
"""
绘制光伏出力对比图
Args:
result: 光伏优化结果
scenario_name: 场景名称
show_window: 是否显示图形窗口
"""
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
hours = list(range(len(result.original_solar_output)))
# 创建图形
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))
fig.suptitle(f'{scenario_name} - 光伏优化结果 (系数: {result.optimal_solar_coefficient:.3f})',
fontsize=14, fontweight='bold')
# === 第一个子图:光伏出力对比 ===
ax1.plot(hours, result.original_solar_output, 'b-', linewidth=2,
label='原始光伏出力', alpha=0.7)
ax1.plot(hours, result.optimized_solar_output, 'r-', linewidth=2,
label=f'优化后光伏出力')
ax1.set_xlabel('时间 (小时)')
ax1.set_ylabel('功率 (MW)')
ax1.set_title('光伏出力曲线对比')
ax1.legend(loc='upper right')
ax1.grid(True, alpha=0.3)
ax1.set_xlim(0, max(hours))
# === 第二个子图:电网交换电量组成 ===
categories = ['购电量', '上网电量']
values = [result.grid_purchase, result.grid_feed_in]
colors = ['purple', 'brown']
bars = ax2.bar(categories, values, color=colors, alpha=0.7)
ax2.set_ylabel('电量 (MWh)')
ax2.set_title(f'电网交换电量组成 (总计: {result.min_grid_exchange:.2f} MWh)')
ax2.grid(True, alpha=0.3, axis='y')
# 在柱状图上添加数值标签
for bar, value in zip(bars, values):
height = bar.get_height()
ax2.text(bar.get_x() + bar.get_width()/2., height + height*0.01,
f'{value:.2f}', ha='center', va='bottom', fontweight='bold')
# 调整布局
plt.tight_layout()
# 根据参数决定是否显示图形窗口
if show_window:
try:
plt.show()
except Exception as e:
print(f"无法显示图形窗口:{str(e)}")
else:
plt.close()
def compare_scenarios(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}")
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)
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")
except Exception as e:
print(f"运行场景演示时出错:{str(e)}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()