完成基本功能。
This commit is contained in:
202
main.py
Normal file
202
main.py
Normal file
@@ -0,0 +1,202 @@
|
||||
"""
|
||||
多能互补系统储能容量优化可视化程序
|
||||
|
||||
该程序绘制负荷曲线、发电曲线和储能出力曲线,直观展示系统运行状态。
|
||||
|
||||
作者: iFlow CLI
|
||||
创建日期: 2025-12-25
|
||||
"""
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
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 plot_system_curves(solar_output, wind_output, thermal_output, load_demand, result):
|
||||
"""
|
||||
绘制系统运行曲线
|
||||
|
||||
Args:
|
||||
solar_output: 光伏出力曲线 (MW) - 支持24小时或8760小时
|
||||
wind_output: 风电出力曲线 (MW) - 支持24小时或8760小时
|
||||
thermal_output: 火电出力曲线 (MW) - 支持24小时或8760小时
|
||||
load_demand: 负荷曲线 (MW) - 支持24小时或8760小时
|
||||
result: 优化结果字典
|
||||
"""
|
||||
hours = np.arange(len(solar_output))
|
||||
data_length = len(solar_output)
|
||||
|
||||
# 确定图表标题和采样率
|
||||
if data_length == 8760:
|
||||
title_suffix = " (全年8760小时)"
|
||||
# 对于全年数据,我们采样显示(每6小时显示一个点)
|
||||
sample_rate = 6
|
||||
sampled_hours = hours[::sample_rate]
|
||||
sampled_solar = solar_output[::sample_rate]
|
||||
sampled_wind = wind_output[::sample_rate]
|
||||
sampled_thermal = thermal_output[::sample_rate]
|
||||
sampled_load = load_demand[::sample_rate]
|
||||
sampled_storage = result['storage_profile'][::sample_rate]
|
||||
sampled_charge = result['charge_profile'][::sample_rate]
|
||||
sampled_discharge = result['discharge_profile'][::sample_rate]
|
||||
else:
|
||||
title_suffix = " (24小时)"
|
||||
sampled_hours = hours
|
||||
sampled_solar = solar_output
|
||||
sampled_wind = wind_output
|
||||
sampled_thermal = thermal_output
|
||||
sampled_load = load_demand
|
||||
sampled_storage = result['storage_profile']
|
||||
sampled_charge = result['charge_profile']
|
||||
sampled_discharge = result['discharge_profile']
|
||||
|
||||
# 创建图形
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(14, 12))
|
||||
fig.suptitle('多能互补系统24小时运行曲线', fontsize=16, fontweight='bold')
|
||||
|
||||
# === 第一个子图:发电和负荷曲线 ===
|
||||
ax1.plot(sampled_hours, sampled_load, 'r-', linewidth=2, label='负荷需求')
|
||||
ax1.plot(sampled_hours, sampled_thermal, 'b-', linewidth=2, label='火电出力')
|
||||
ax1.plot(sampled_hours, sampled_wind, 'g-', linewidth=2, label='风电出力')
|
||||
ax1.plot(sampled_hours, sampled_solar, 'orange', linewidth=2, label='光伏出力')
|
||||
|
||||
# 计算总发电量
|
||||
total_generation = [sampled_thermal[i] + sampled_wind[i] + sampled_solar[i] for i in range(len(sampled_thermal))]
|
||||
ax1.plot(sampled_hours, total_generation, 'k--', linewidth=1.5, alpha=0.7, label='总发电量')
|
||||
|
||||
ax1.set_xlabel('时间 (小时)')
|
||||
ax1.set_ylabel('功率 (MW)')
|
||||
ax1.set_title(f'发电与负荷曲线{title_suffix}')
|
||||
ax1.legend(loc='upper right')
|
||||
ax1.grid(True, alpha=0.3)
|
||||
ax1.set_xlim(0, max(sampled_hours))
|
||||
|
||||
# === 第二个子图:储能充放电曲线 ===
|
||||
discharge_power = [-x for x in sampled_discharge] # 放电显示为负值
|
||||
|
||||
ax2.bar(sampled_hours, sampled_charge, color='green', alpha=0.7, label='充电功率')
|
||||
ax2.bar(sampled_hours, discharge_power, color='red', alpha=0.7, label='放电功率')
|
||||
|
||||
ax2.set_xlabel('时间 (小时)')
|
||||
ax2.set_ylabel('功率 (MW)')
|
||||
ax2.set_title(f'储能充放电功率{title_suffix}')
|
||||
ax2.legend(loc='upper right')
|
||||
ax2.grid(True, alpha=0.3)
|
||||
ax2.set_xlim(0, max(sampled_hours))
|
||||
ax2.axhline(y=0, color='black', linestyle='-', linewidth=0.5)
|
||||
|
||||
# === 第三个子图:储能状态曲线 ===
|
||||
ax3.plot(sampled_hours, sampled_storage, 'b-', linewidth=1, marker='o', markersize=2)
|
||||
ax3.fill_between(sampled_hours, 0, sampled_storage, alpha=0.3, color='blue')
|
||||
|
||||
ax3.set_xlabel('时间 (小时)')
|
||||
ax3.set_ylabel('储能容量 (MWh)')
|
||||
ax3.set_title(f'储能状态 (总容量: {result["required_storage_capacity"]:.2f} MWh){title_suffix}')
|
||||
ax3.grid(True, alpha=0.3)
|
||||
ax3.set_xlim(0, max(sampled_hours))
|
||||
ax3.set_ylim(bottom=0)
|
||||
|
||||
# 调整布局
|
||||
plt.tight_layout()
|
||||
|
||||
# 保存图片
|
||||
plt.savefig('system_curves.png', dpi=300, bbox_inches='tight')
|
||||
plt.close() # 关闭图形,不显示窗口
|
||||
|
||||
# 打印统计信息
|
||||
print("\n=== 系统运行统计 ===")
|
||||
print(f"所需储能总容量: {result['required_storage_capacity']:.2f} MWh")
|
||||
print(f"最大储能状态: {max(result['storage_profile']):.2f} MWh")
|
||||
print(f"最小储能状态: {min(result['storage_profile']):.2f} MWh")
|
||||
print(f"总充电量: {sum(result['charge_profile']):.2f} MWh")
|
||||
print(f"总放电量: {sum(result['discharge_profile']):.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}")
|
||||
|
||||
|
||||
def generate_yearly_data():
|
||||
"""生成8760小时的示例数据"""
|
||||
# 基础日模式
|
||||
daily_solar = [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
|
||||
daily_wind = [2.0, 3.0, 4.0, 3.0, 2.0, 1.0] * 4
|
||||
daily_thermal = [5.0] * 24
|
||||
daily_load = [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]
|
||||
|
||||
# 添加季节性变化
|
||||
import random
|
||||
random.seed(42)
|
||||
|
||||
yearly_solar = []
|
||||
yearly_wind = []
|
||||
yearly_thermal = []
|
||||
yearly_load = []
|
||||
|
||||
for day in range(365):
|
||||
# 季节性因子(夏季光伏更强,冬季负荷更高)
|
||||
season_factor = 1.0 + 0.3 * np.sin(2 * np.pi * day / 365)
|
||||
|
||||
for hour in range(24):
|
||||
# 添加随机变化
|
||||
solar_variation = 1.0 + 0.2 * (random.random() - 0.5)
|
||||
wind_variation = 1.0 + 0.3 * (random.random() - 0.5)
|
||||
load_variation = 1.0 + 0.1 * (random.random() - 0.5)
|
||||
|
||||
yearly_solar.append(daily_solar[hour] * season_factor * solar_variation)
|
||||
yearly_wind.append(daily_wind[hour] * wind_variation)
|
||||
yearly_thermal.append(daily_thermal[hour])
|
||||
yearly_load.append(daily_load[hour] * (2.0 - season_factor) * load_variation)
|
||||
|
||||
return yearly_solar, yearly_wind, yearly_thermal, yearly_load
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
import sys
|
||||
|
||||
# 检查命令行参数
|
||||
use_yearly_data = len(sys.argv) > 1 and sys.argv[1] == '--yearly'
|
||||
|
||||
if use_yearly_data:
|
||||
print("生成8760小时全年数据...")
|
||||
solar_output, wind_output, thermal_output, load_demand = generate_yearly_data()
|
||||
print(f"数据长度: {len(solar_output)} 小时")
|
||||
else:
|
||||
print("使用24小时示例数据...")
|
||||
# 示例数据
|
||||
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("正在绘制系统运行曲线...")
|
||||
plot_system_curves(solar_output, wind_output, thermal_output, load_demand, result)
|
||||
|
||||
print("\n曲线图已保存为 'system_curves.png'")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user