增加正负显示购电量。

This commit is contained in:
dmy
2025-12-26 01:44:08 +08:00
parent 1fc5f03d89
commit 65be7e52dd

206
main.py
View File

@@ -11,6 +11,8 @@ import matplotlib
matplotlib.use('TkAgg') # 设置为TkAgg后端以支持图形窗口显示
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from datetime import datetime
from storage_optimization import optimize_storage_capacity, SystemParameters
from excel_reader import read_excel_data, create_excel_template, analyze_excel_data
@@ -54,6 +56,7 @@ def plot_system_curves(solar_output, wind_output, thermal_output, load_demand, r
sampled_storage = result['storage_profile'][::sample_rate]
sampled_charge = result['charge_profile'][::sample_rate]
sampled_discharge = result['discharge_profile'][::sample_rate]
sampled_grid_feed_in = result['grid_feed_in'][::sample_rate]
else:
title_suffix = " (24小时)"
sampled_hours = hours
@@ -64,9 +67,10 @@ def plot_system_curves(solar_output, wind_output, thermal_output, load_demand, r
sampled_storage = result['storage_profile']
sampled_charge = result['charge_profile']
sampled_discharge = result['discharge_profile']
sampled_grid_feed_in = result['grid_feed_in']
# 创建图形
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(14, 12))
# 创建图形4个子图
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=(14, 16))
fig.suptitle('多能互补系统24小时运行曲线', fontsize=16, fontweight='bold')
# === 第一个子图:发电和负荷曲线 ===
@@ -111,6 +115,31 @@ def plot_system_curves(solar_output, wind_output, thermal_output, load_demand, r
ax3.set_xlim(0, max(sampled_hours))
ax3.set_ylim(bottom=0)
# === 第四个子图:购电量和上网电量曲线 ===
# 直接使用原始数据:正值表示上网电量,负值表示购电量
grid_power = sampled_grid_feed_in
# 绘制电网交互电量(正值上网,负值购电)
colors = ['brown' if x >= 0 else 'purple' for x in grid_power]
ax4.bar(sampled_hours, grid_power, color=colors, alpha=0.7, label='电网交互电量')
# 添加零线
ax4.axhline(y=0, color='black', linestyle='-', linewidth=0.5)
# 添加图例说明
from matplotlib.patches import Patch
legend_elements = [
Patch(facecolor='brown', alpha=0.7, label='上网电量 (+)'),
Patch(facecolor='purple', alpha=0.7, label='购电量 (-)')
]
ax4.legend(handles=legend_elements, loc='upper right')
ax4.set_xlabel('时间 (小时)')
ax4.set_ylabel('功率 (MW)')
ax4.set_title(f'电网交互电量{title_suffix} (正值:上网, 负值:购电)')
ax4.grid(True, alpha=0.3)
ax4.set_xlim(0, max(sampled_hours))
# 调整布局
plt.tight_layout()
@@ -146,6 +175,173 @@ def plot_system_curves(solar_output, wind_output, thermal_output, load_demand, r
print(f"弃光率: {result['total_curtailment_solar_ratio']:.3f}")
print(f"上网电量比例: {result['total_grid_feed_in_ratio']:.3f}")
# 计算购电和上网电量统计
total_grid_feed_in = sum(result['grid_feed_in'])
total_grid_purchase = sum(-x for x in result['grid_feed_in'] if x < 0) # 购电量
total_grid_feed_out = sum(x for x in result['grid_feed_in'] if x > 0) # 上网电量
print(f"\n=== 电网交互统计 ===")
if total_grid_feed_in >= 0:
print(f"净上网电量: {total_grid_feed_in:.2f} MWh")
else:
print(f"净购电量: {-total_grid_feed_in:.2f} MWh")
print(f"总购电量: {total_grid_purchase:.2f} MWh")
print(f"总上网电量: {total_grid_feed_out:.2f} MWh")
def export_results_to_excel(solar_output, wind_output, thermal_output, load_demand, result, params, filename=None):
"""
将优化结果导出到Excel文件
Args:
solar_output: 光伏出力曲线 (MW)
wind_output: 风电出力曲线 (MW)
thermal_output: 火电出力曲线 (MW)
load_demand: 负荷曲线 (MW)
result: 优化结果字典
params: 系统参数
filename: 输出文件名如果为None则自动生成
"""
if filename is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"storage_optimization_results_{timestamp}.xlsx"
print(f"\n正在导出结果到Excel文件: {filename}")
# 准备数据
hours = list(range(1, len(solar_output) + 1))
# 分离购电和上网电量
grid_purchase = []
grid_feed_out = []
for power in result['grid_feed_in']:
if power < 0:
grid_purchase.append(-power) # 购电,转换为正值
grid_feed_out.append(0)
else:
grid_purchase.append(0)
grid_feed_out.append(power) # 上网电量
# 创建主要数据DataFrame
data_df = pd.DataFrame({
'小时': hours,
'光伏出力(MW)': solar_output,
'风电出力(MW)': wind_output,
'火电出力(MW)': thermal_output,
'总发电量(MW)': [solar_output[i] + wind_output[i] + thermal_output[i] for i in range(len(solar_output))],
'负荷需求(MW)': load_demand,
'储能充电(MW)': result['charge_profile'],
'储能放电(MW)': result['discharge_profile'],
'储能状态(MWh)': result['storage_profile'],
'弃风量(MW)': result['curtailed_wind'],
'弃光量(MW)': result['curtailed_solar'],
'购电量(MW)': grid_purchase,
'上网电量(MW)': grid_feed_out
})
# 创建统计信息DataFrame
total_grid_feed_in = sum(result['grid_feed_in'])
total_grid_purchase = sum(-x for x in result['grid_feed_in'] if x < 0) # 购电量
total_grid_feed_out = sum(x for x in result['grid_feed_in'] if x > 0) # 上网电量
stats_df = pd.DataFrame({
'指标': [
'所需储能总容量',
'最大储能状态',
'最小储能状态',
'总充电量',
'总放电量',
'弃风率',
'弃光率',
'上网电量比例',
'能量平衡校验',
'净购电量/净上网电量',
'总购电量',
'总上网电量',
'容量限制是否达到'
],
'数值': [
f"{result['required_storage_capacity']:.2f} MWh",
f"{max(result['storage_profile']):.2f} MWh",
f"{min(result['storage_profile']):.2f} MWh",
f"{sum(result['charge_profile']):.2f} MWh",
f"{sum(result['discharge_profile']):.2f} MWh",
f"{result['total_curtailment_wind_ratio']:.3f}",
f"{result['total_curtailment_solar_ratio']:.3f}",
f"{result['total_grid_feed_in_ratio']:.3f}",
"通过" if result['energy_balance_check'] else "未通过",
f"{-total_grid_feed_in:.2f} MWh" if total_grid_feed_in < 0 else f"{total_grid_feed_in:.2f} MWh",
f"{total_grid_purchase:.2f} MWh",
f"{total_grid_feed_out:.2f} MWh",
"" if result['capacity_limit_reached'] else ""
]
})
# 创建系统参数DataFrame
params_df = pd.DataFrame({
'参数名称': [
'最大弃风率',
'最大弃光率',
'最大上网电量比例',
'储能效率',
'放电倍率',
'充电倍率',
'最大储能容量'
],
'参数值': [
params.max_curtailment_wind,
params.max_curtailment_solar,
params.max_grid_ratio,
params.storage_efficiency,
params.discharge_rate,
params.charge_rate,
params.max_storage_capacity if params.max_storage_capacity is not None else "无限制"
],
'单位': [
"比例",
"比例",
"比例",
"效率",
"C-rate",
"C-rate",
"MWh"
]
})
# 写入Excel文件
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
# 写入主要数据
data_df.to_excel(writer, sheet_name='运行数据', index=False)
# 写入统计信息
stats_df.to_excel(writer, sheet_name='统计结果', index=False)
# 写入系统参数
params_df.to_excel(writer, sheet_name='系统参数', index=False)
# 创建说明工作表
description_df = pd.DataFrame({
'项目': [
'文件说明',
'生成时间',
'数据长度',
'数据内容',
'注意事项'
],
'内容': [
'多能互补系统储能容量优化结果',
datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
f"{len(solar_output)} 小时",
'包含发电、负荷、储能、弃风弃光、购电上网等完整数据',
'负值表示购电,正值表示上网电量'
]
})
description_df.to_excel(writer, sheet_name='说明', index=False)
print(f"结果已成功导出到: {filename}")
return filename
def generate_yearly_data():
"""生成8760小时的示例数据"""
@@ -313,6 +509,12 @@ def main():
print("正在绘制系统运行曲线...")
plot_system_curves(solar_output, wind_output, thermal_output, load_demand, result, show_window, display_only)
# 导出结果到Excel
try:
export_results_to_excel(solar_output, wind_output, thermal_output, load_demand, result, params)
except Exception as e:
print(f"导出Excel文件失败{str(e)}")
if display_only:
print("\n正在显示图形窗口...")
elif show_window: