可以处理购电和上网两种情况。
This commit is contained in:
142
example_usage.py
142
example_usage.py
@@ -195,11 +195,26 @@ def plot_results(result, title, solar_output, wind_output, thermal_output, load_
|
||||
ax4.legend()
|
||||
ax4.grid(True)
|
||||
|
||||
# 上网电量
|
||||
# 上网电量/购电量
|
||||
ax5.plot(hours, result['grid_feed_in'], 'orange', linewidth=2)
|
||||
ax5.set_title('上网电量 (MW)')
|
||||
ax5.axhline(y=0, color='black', linestyle='-', linewidth=0.5, alpha=0.5)
|
||||
ax5.fill_between(hours, 0, result['grid_feed_in'],
|
||||
where=[x >= 0 for x in result['grid_feed_in']],
|
||||
alpha=0.3, color='green', label='上网')
|
||||
ax5.fill_between(hours, 0, result['grid_feed_in'],
|
||||
where=[x < 0 for x in result['grid_feed_in']],
|
||||
alpha=0.3, color='red', label='购电')
|
||||
|
||||
# 动态设置标题
|
||||
total_grid = sum(result['grid_feed_in'])
|
||||
if total_grid < 0:
|
||||
ax5.set_title(f'购电量 (总计: {abs(total_grid):.1f} MWh)')
|
||||
else:
|
||||
ax5.set_title(f'上网电量 (总计: {total_grid:.1f} MWh)')
|
||||
|
||||
ax5.set_xlabel('时间 (小时)')
|
||||
ax5.set_ylabel('功率 (MW)')
|
||||
ax5.legend()
|
||||
ax5.grid(True)
|
||||
|
||||
# 能量平衡分析
|
||||
@@ -230,6 +245,93 @@ def plot_results(result, title, solar_output, wind_output, thermal_output, load_
|
||||
plt.show()
|
||||
|
||||
|
||||
def example_5_high_load_grid_purchase_scenario():
|
||||
"""示例5: 高负荷购电场景"""
|
||||
print("\n=== 示例5: 高负荷购电场景 ===")
|
||||
|
||||
# 高负荷场景数据 - 有充电和放电时段
|
||||
solar_output = [0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 9.0, 8.0,
|
||||
7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
|
||||
wind_output = [5.0, 5.5, 6.0, 6.5, 6.0, 5.5, 5.0, 4.5, 4.0, 3.5, 3.0, 2.5,
|
||||
2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 5.5, 5.0, 5.0]
|
||||
|
||||
thermal_output = [8.0] * 24 # 火电基荷
|
||||
|
||||
# 负荷曲线:夜间低负荷(充电时段),白天高负荷(放电和购电时段)
|
||||
load_demand = [10.0, 9.0, 8.0, 7.0, 8.0, 12.0, 18.0, 25.0, 35.0, 42.0, 45.0, 43.0,
|
||||
40.0, 38.0, 35.0, 30.0, 25.0, 20.0, 15.0, 12.0, 11.0, 10.0, 10.0, 10.0]
|
||||
|
||||
# 系统参数 - 允许从电网购电(负的上网电量)
|
||||
params = SystemParameters(
|
||||
max_curtailment_wind=0.05, # 严格的弃风控制
|
||||
max_curtailment_solar=0.02, # 严格的弃光控制
|
||||
max_grid_ratio=-0.3, # 负值表示允许从电网购电,最大购电比例30%
|
||||
storage_efficiency=0.9, # 储能效率90%
|
||||
discharge_rate=2.0, # 2C放电,满足高峰需求
|
||||
charge_rate=1.0, # 1C充电
|
||||
max_storage_capacity=8.0 # 限制储能容量为8MWh,确保储能被充分利用
|
||||
)
|
||||
|
||||
result = optimize_storage_capacity(solar_output, wind_output, thermal_output, load_demand, params, tolerance=0.1)
|
||||
|
||||
print(f"所需储能容量: {result['required_storage_capacity']:.2f} MWh")
|
||||
print(f"储能容量上限: {result['max_storage_limit']:.2f} MWh")
|
||||
print(f"是否达到容量上限: {'是' if result['capacity_limit_reached'] else '否'}")
|
||||
print(f"实际弃风率: {result['total_curtailment_wind_ratio']:.3f} (约束: {params.max_curtailment_wind})")
|
||||
print(f"实际弃光率: {result['total_curtailment_solar_ratio']:.3f} (约束: {params.max_curtailment_solar})")
|
||||
print(f"实际上网电量比例: {result['total_grid_feed_in_ratio']:.3f} (负值表示购电)")
|
||||
print(f"能量平衡校验: {'通过' if result['energy_balance_check'] else '未通过'}")
|
||||
|
||||
# 调试信息
|
||||
total_gen = sum(solar_output) + sum(wind_output) + sum(thermal_output)
|
||||
total_load = sum(load_demand)
|
||||
total_charge = sum(result['charge_profile'])
|
||||
total_discharge = sum(result['discharge_profile'])
|
||||
|
||||
print(f"\n=== 调试信息 ===")
|
||||
print(f"总发电量: {total_gen:.2f} MWh")
|
||||
print(f"总负荷: {total_load:.2f} MWh")
|
||||
print(f"负荷-发电差: {total_load - total_gen:.2f} MWh")
|
||||
print(f"总充电量: {total_charge:.2f} MWh")
|
||||
print(f"总放电量: {total_discharge:.2f} MWh")
|
||||
print(f"储能净变化: {total_discharge - total_charge:.2f} MWh")
|
||||
|
||||
# 计算购电量统计
|
||||
total_grid_feed = sum(result['grid_feed_in'])
|
||||
if total_grid_feed < 0:
|
||||
print(f"总购电量: {abs(total_grid_feed):.2f} MWh")
|
||||
|
||||
# 显示前几个小时的详细情况
|
||||
print(f"\n前6小时详细情况:")
|
||||
print(f"小时 | 发电 | 负荷 | 储能充电 | 储能放电 | 购电")
|
||||
print("-" * 55)
|
||||
for i in range(6):
|
||||
gen = solar_output[i] + wind_output[i] + thermal_output[i]
|
||||
charge = result['charge_profile'][i]
|
||||
discharge = result['discharge_profile'][i]
|
||||
grid = result['grid_feed_in'][i]
|
||||
print(f"{i:2d} | {gen:4.1f} | {load_demand[i]:4.1f} | {charge:7.2f} | {discharge:7.2f} | {grid:5.2f}")
|
||||
|
||||
# 计算最大缺电功率
|
||||
max_deficit = 0
|
||||
for hour in range(24):
|
||||
total_gen = solar_output[hour] + wind_output[hour] + thermal_output[hour]
|
||||
deficit = max(0, load_demand[hour] - total_gen - result['discharge_profile'][hour])
|
||||
max_deficit = max(max_deficit, deficit)
|
||||
|
||||
if max_deficit > 0:
|
||||
print(f"\n最大缺电功率: {max_deficit:.2f} MW")
|
||||
|
||||
return {
|
||||
'result': result,
|
||||
'solar_output': solar_output,
|
||||
'wind_output': wind_output,
|
||||
'thermal_output': thermal_output,
|
||||
'load_demand': load_demand
|
||||
}
|
||||
|
||||
|
||||
def example_4_capacity_limited_scenario():
|
||||
"""示例4: 储能容量限制场景"""
|
||||
print("\n=== 示例4: 储能容量限制场景 ===")
|
||||
@@ -280,54 +382,61 @@ def compare_scenarios():
|
||||
"""比较不同场景的结果"""
|
||||
print("\n=== 场景比较 ===")
|
||||
|
||||
# 运行四个场景
|
||||
# 运行五个场景
|
||||
data1 = example_1_basic_scenario()
|
||||
data2 = example_2_high_renewable_scenario()
|
||||
data3 = example_3_winter_scenario()
|
||||
data4 = example_4_capacity_limited_scenario()
|
||||
data5 = example_5_high_load_grid_purchase_scenario()
|
||||
|
||||
# 比较结果
|
||||
scenarios = ['基础场景', '高可再生能源场景', '冬季场景', '容量限制场景']
|
||||
scenarios = ['基础场景', '高可再生能源场景', '冬季场景', '容量限制场景', '高负荷购电场景']
|
||||
storage_capacities = [
|
||||
data1['result']['required_storage_capacity'],
|
||||
data2['result']['required_storage_capacity'],
|
||||
data3['result']['required_storage_capacity'],
|
||||
data4['result']['required_storage_capacity']
|
||||
data4['result']['required_storage_capacity'],
|
||||
data5['result']['required_storage_capacity']
|
||||
]
|
||||
curtailment_wind = [
|
||||
data1['result']['total_curtailment_wind_ratio'],
|
||||
data2['result']['total_curtailment_wind_ratio'],
|
||||
data3['result']['total_curtailment_wind_ratio'],
|
||||
data4['result']['total_curtailment_wind_ratio']
|
||||
data4['result']['total_curtailment_wind_ratio'],
|
||||
data5['result']['total_curtailment_wind_ratio']
|
||||
]
|
||||
curtailment_solar = [
|
||||
data1['result']['total_curtailment_solar_ratio'],
|
||||
data2['result']['total_curtailment_solar_ratio'],
|
||||
data3['result']['total_curtailment_solar_ratio'],
|
||||
data4['result']['total_curtailment_solar_ratio']
|
||||
data4['result']['total_curtailment_solar_ratio'],
|
||||
data5['result']['total_curtailment_solar_ratio']
|
||||
]
|
||||
grid_feed_in = [
|
||||
data1['result']['total_grid_feed_in_ratio'],
|
||||
data2['result']['total_grid_feed_in_ratio'],
|
||||
data3['result']['total_grid_feed_in_ratio'],
|
||||
data4['result']['total_grid_feed_in_ratio']
|
||||
data4['result']['total_grid_feed_in_ratio'],
|
||||
data5['result']['total_grid_feed_in_ratio']
|
||||
]
|
||||
capacity_limit = [
|
||||
'无',
|
||||
'无',
|
||||
'无',
|
||||
f"{data4['result']['max_storage_limit']:.1f}MWh"
|
||||
f"{data4['result']['max_storage_limit']:.1f}MWh",
|
||||
f"{data5['result']['max_storage_limit']:.1f}MWh"
|
||||
]
|
||||
|
||||
print("\n场景比较结果:")
|
||||
print(f"{'场景':<15} {'储能容量(MWh)':<12} {'容量限制':<10} {'弃风率':<8} {'弃光率':<8} {'上网比例':<8}")
|
||||
print("-" * 75)
|
||||
print(f"{'场景':<15} {'储能容量(MWh)':<12} {'容量限制':<10} {'弃风率':<8} {'弃光率':<8} {'上网/购电':<8}")
|
||||
print("-" * 80)
|
||||
for i, scenario in enumerate(scenarios):
|
||||
limit_reached = "✓" if data4['result']['capacity_limit_reached'] and i == 3 else ""
|
||||
grid_text = f"{grid_feed_in[i]:.3f}" if grid_feed_in[i] >= 0 else f"{grid_feed_in[i]:.3f}↓"
|
||||
limit_reached = "*" if (data4['result']['capacity_limit_reached'] and i == 3) or (data5['result']['capacity_limit_reached'] and i == 4) else ""
|
||||
print(f"{scenario:<15} {storage_capacities[i]:<12.2f} {capacity_limit[i]:<10} {curtailment_wind[i]:<8.3f} "
|
||||
f"{curtailment_solar[i]:<8.3f} {grid_feed_in[i]:<8.3f} {limit_reached}")
|
||||
f"{curtailment_solar[i]:<8.3f} {grid_text:<8} {limit_reached}")
|
||||
|
||||
return data1, data2, data3, data4
|
||||
return data1, data2, data3, data4, data5
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -335,7 +444,7 @@ if __name__ == "__main__":
|
||||
print("=" * 50)
|
||||
|
||||
# 运行示例
|
||||
data1, data2, data3, data4 = compare_scenarios()
|
||||
data1, data2, data3, data4, data5 = compare_scenarios()
|
||||
|
||||
# 绘制图表(如果matplotlib可用)
|
||||
try:
|
||||
@@ -351,6 +460,9 @@ if __name__ == "__main__":
|
||||
plot_results(data4['result'], "容量限制场景储能运行情况",
|
||||
data4['solar_output'], data4['wind_output'],
|
||||
data4['thermal_output'], data4['load_demand'])
|
||||
plot_results(data5['result'], "高负荷购电场景储能运行情况",
|
||||
data5['solar_output'], data5['wind_output'],
|
||||
data5['thermal_output'], data5['load_demand'])
|
||||
except ImportError:
|
||||
print("\n注意: matplotlib未安装,无法绘制图表")
|
||||
print("要安装matplotlib,请运行: pip install matplotlib")
|
||||
|
||||
Reference in New Issue
Block a user