Files
multi_energy_complementarity/advanced_visualization.py
dmy 02b2fdc309 1.可以读excel文件
2.可以计算8760小时
2025-12-25 19:56:21 +08:00

260 lines
9.5 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-25
"""
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
from datetime import datetime, timedelta
from storage_optimization import optimize_storage_capacity, SystemParameters
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
def create_comprehensive_plot(solar_output, wind_output, thermal_output, load_demand, result, params):
"""
创建综合可视化图表
Args:
solar_output: 24小时光伏出力曲线 (MW)
wind_output: 24小时风电出力曲线 (MW)
thermal_output: 24小时火电出力曲线 (MW)
load_demand: 24小时负荷曲线 (MW)
result: 优化结果字典
params: 系统参数
"""
hours = np.arange(24)
# 创建大型图形
fig = plt.figure(figsize=(16, 12))
fig.suptitle('多能互补系统储能容量优化分析', fontsize=18, fontweight='bold')
# 创建网格布局
gs = fig.add_gridspec(3, 3, hspace=0.3, wspace=0.3)
# === 主要图表:发电和负荷 ===
ax1 = fig.add_subplot(gs[0, :])
# 绘制各发电类型
ax1.fill_between(hours, 0, thermal_output, alpha=0.7, color='blue', label='火电')
ax1.fill_between(hours, thermal_output,
[thermal_output[i] + wind_output[i] for i in range(24)],
alpha=0.7, color='green', label='风电')
ax1.fill_between(hours, [thermal_output[i] + wind_output[i] for i in range(24)],
[thermal_output[i] + wind_output[i] + solar_output[i] for i in range(24)],
alpha=0.7, color='orange', label='光伏')
# 绘制负荷曲线
ax1.plot(hours, load_demand, 'r-', linewidth=3, label='负荷需求')
ax1.set_xlabel('时间 (小时)')
ax1.set_ylabel('功率 (MW)')
ax1.set_title('24小时发电与负荷平衡')
ax1.legend(loc='upper right')
ax1.grid(True, alpha=0.3)
ax1.set_xlim(0, 23)
# === 储能充放电功率 ===
ax2 = fig.add_subplot(gs[1, 0])
charge_power = result['charge_profile']
discharge_power = [-x for x in result['discharge_profile']]
ax2.bar(hours, charge_power, color='green', alpha=0.7, label='充电')
ax2.bar(hours, discharge_power, color='red', alpha=0.7, label='放电')
ax2.set_xlabel('时间 (小时)')
ax2.set_ylabel('功率 (MW)')
ax2.set_title('储能充放电功率')
ax2.legend()
ax2.grid(True, alpha=0.3)
ax2.axhline(y=0, color='black', linestyle='-', linewidth=0.5)
# === 储能状态 ===
ax3 = fig.add_subplot(gs[1, 1])
storage_soc = result['storage_profile']
ax3.plot(hours, storage_soc, 'b-', linewidth=2, marker='o')
ax3.fill_between(hours, 0, storage_soc, alpha=0.3, color='blue')
ax3.set_xlabel('时间 (小时)')
ax3.set_ylabel('储能容量 (MWh)')
ax3.set_title(f'储能状态 (容量: {result["required_storage_capacity"]:.1f} MWh)')
ax3.grid(True, alpha=0.3)
ax3.set_ylim(bottom=0)
# === 弃风弃光 ===
ax4 = fig.add_subplot(gs[1, 2])
curtailed_wind = result['curtailed_wind']
curtailed_solar = result['curtailed_solar']
ax4.bar(hours, curtailed_wind, color='lightblue', alpha=0.7, label='弃风')
ax4.bar(hours, curtailed_solar, color='yellow', alpha=0.7, label='弃光')
ax4.set_xlabel('时间 (小时)')
ax4.set_ylabel('功率 (MW)')
ax4.set_title('弃风弃光功率')
ax4.legend()
ax4.grid(True, alpha=0.3)
# === 能量饼图 ===
ax5 = fig.add_subplot(gs[2, 0])
# 计算总能量
total_gen = sum(thermal_output) + sum(wind_output) + sum(solar_output)
total_load = sum(load_demand)
total_curtailed = sum(curtailed_wind) + sum(curtailed_solar)
total_grid = sum(result['grid_feed_in'])
# 能量分配
energy_data = [total_load, total_curtailed, total_grid]
energy_labels = [f'负荷\n({total_load:.1f} MWh)',
f'弃风弃光\n({total_curtailed:.1f} MWh)',
f'上网电量\n({total_grid:.1f} MWh)']
colors = ['red', 'orange', 'green']
ax5.pie(energy_data, labels=energy_labels, colors=colors, autopct='%1.1f%%', startangle=90)
ax5.set_title('能量分配')
# === 发电构成饼图 ===
ax6 = fig.add_subplot(gs[2, 1])
gen_data = [sum(thermal_output), sum(wind_output), sum(solar_output)]
gen_labels = [f'火电\n({gen_data[0]:.1f} MWh)',
f'风电\n({gen_data[1]:.1f} MWh)',
f'光伏\n({gen_data[2]:.1f} MWh)']
gen_colors = ['blue', 'green', 'orange']
ax6.pie(gen_data, labels=gen_labels, colors=gen_colors, autopct='%1.1f%%', startangle=90)
ax6.set_title('发电构成')
# === 关键指标文本 ===
ax7 = fig.add_subplot(gs[2, 2])
ax7.axis('off')
# 显示关键指标
metrics_text = f"""
关键指标
─────────────
所需储能容量: {result['required_storage_capacity']:.1f} MWh
储能效率: {params.storage_efficiency:.1%}
弃风率: {result['total_curtailment_wind_ratio']:.1%}
弃光率: {result['total_curtailment_solar_ratio']:.1%}
上网电量比例: {result['total_grid_feed_in_ratio']:.1%}
能量平衡: {'' if result['energy_balance_check'] else ''}
最大储能状态: {max(storage_soc):.1f} MWh
最小储能状态: {min(storage_soc):.1f} MWh
"""
ax7.text(0.1, 0.5, metrics_text, fontsize=11, verticalalignment='center',
fontfamily='SimHei', bbox=dict(boxstyle='round', facecolor='lightgray', alpha=0.8))
# 保存图片
plt.savefig('comprehensive_analysis.png', dpi=300, bbox_inches='tight')
plt.close()
print("综合分析图表已保存为 'comprehensive_analysis.png'")
def create_time_series_plot(solar_output, wind_output, thermal_output, load_demand, result):
"""
创建时间序列图表,模拟真实的时间轴
"""
# 创建时间轴
base_time = datetime(2025, 1, 1, 0, 0, 0)
times = [base_time + timedelta(hours=i) for i in range(24)]
fig, ax = plt.subplots(figsize=(14, 8))
# 绘制发电和负荷
ax.plot(times, load_demand, 'r-', linewidth=3, label='负荷需求')
ax.plot(times, thermal_output, 'b-', linewidth=2, label='火电出力')
ax.plot(times, wind_output, 'g-', linewidth=2, label='风电出力')
ax.plot(times, solar_output, 'orange', linewidth=2, label='光伏出力')
# 计算总发电量
total_generation = [thermal_output[i] + wind_output[i] + solar_output[i] for i in range(24)]
ax.plot(times, total_generation, 'k--', linewidth=1.5, alpha=0.7, label='总发电量')
# 设置时间轴格式
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
ax.xaxis.set_major_locator(mdates.HourLocator(interval=2))
ax.set_xlabel('时间')
ax.set_ylabel('功率 (MW)')
ax.set_title('多能互补系统24小时发电曲线 (时间序列)')
ax.legend(loc='upper right')
ax.grid(True, alpha=0.3)
# 旋转时间标签
plt.setp(ax.xaxis.get_majorticklabels(), rotation=45)
plt.tight_layout()
plt.savefig('time_series_curves.png', dpi=300, bbox_inches='tight')
plt.close()
print("时间序列图表已保存为 'time_series_curves.png'")
def main():
"""主函数"""
# 示例数据
solar_output = [0.0] * 6 + [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] * 6
wind_output = [2.0, 3.0, 4.0, 3.0, 2.0, 1.0] * 4
thermal_output = [5.0] * 24
load_demand = [3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 18.0,
16.0, 14.0, 12.0, 10.0, 8.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 2.0]
# 系统参数
params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.2,
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0
)
# 计算最优储能容量
print("正在计算最优储能容量...")
result = optimize_storage_capacity(
solar_output, wind_output, thermal_output, load_demand, params
)
print("\n=== 优化结果 ===")
print(f"所需储能总容量: {result['required_storage_capacity']:.2f} MWh")
print(f"弃风率: {result['total_curtailment_wind_ratio']:.3f}")
print(f"弃光率: {result['total_curtailment_solar_ratio']:.3f}")
print(f"上网电量比例: {result['total_grid_feed_in_ratio']:.3f}")
print(f"能量平衡校验: {'通过' if result['energy_balance_check'] else '未通过'}")
# 创建各种图表
print("\n正在生成可视化图表...")
# 1. 基础曲线图已在main.py中实现
print("1. 基础系统运行曲线图")
# 2. 综合分析图
print("2. 综合分析图表")
create_comprehensive_plot(solar_output, wind_output, thermal_output, load_demand, result, params)
# 3. 时间序列图
print("3. 时间序列图表")
create_time_series_plot(solar_output, wind_output, thermal_output, load_demand, result)
print("\n=== 所有图表生成完成 ===")
print("生成的文件:")
print("- system_curves.png: 基础系统运行曲线")
print("- comprehensive_analysis.png: 综合分析图表")
print("- time_series_curves.png: 时间序列图表")
if __name__ == "__main__":
main()