赠与读者
做科研,涉及到一个深在的思想系统,需要科研者逻辑缜密,踏实认真,但是不能只是努力,很多时候借力比努力更重要,然后还要有仰望星空的创新点和启发点。建议读者按目录次序逐一浏览,免得骤然跌入幽暗的迷宫找不到来时的路,它不足为你揭示全部问题的答案,但若能解答你胸中升起的一朵朵疑云,也未尝不会酿成晚霞斑斓的别一番景致,万一它给你带来了一场精神世界的苦雨,那就借机洗刷一下原来存放在那儿的“躺平”上的尘埃吧。
或许,雨过云收,神驰的天地更清朗.......
01
[摘 要]为有效削减可再生能源发电出力的波动性,提升可再生能源的整体利用效能,本研究创新性地设计了一种集并网与离网功能于一体的风光互补制氢合成氨系统。该系统以实现年度收益最大化为核心目标,在构建过程中,充分考量了系统内的电平衡、氢平衡以及与电网的交互作用等关键运行约束条件,进而建立了容量配置与调度优化的综合模型。研究以内蒙古某地区实际的风光出力数据作为模型输入,通过深入分析风光容量的配比关系,系统探究了不同风光容量配比对系统技术经济性能的具体影响。研究结果显示:经过科学的容量配置与精细的调度优化,并/离网风光互补制氢合成氨系统能够在风光出力多变的情境下,灵活切换工作模式,有效平抑风光出力的波动,确保合成氨设备能够稳定且高效地运行,其中并网型系统的综合性能优于离网型系统。在具体案例区域中,随着风电装机容量的逐步提升,系统所需配置的电解槽与储氢罐容量先呈现下降趋势,后转为上升,当风电与光伏的装机容量相近或相等时,系统的经济效率达到较高水平。
[关 键 词]风光互补系统;绿色合成氨;容量与调度优化;风光容量配比研究
[Abstract] To effectively mitigate the volatility of renewable-generation output and raise overall renewable-energy utilization, this study proposes an innovative wind–solar hybrid ammonia-synthesis system that can operate both on- and off-grid. With annual profit maximization as the primary objective, the development explicitly accounts for key operational constraints such as electricity balance, hydrogen balance and grid interaction, and establishes an integrated model for capacity sizing and dispatch optimization. Actual wind and solar power data from a region in Inner Mongolia are fed into the model. By examining different wind-to-PV capacity ratios, the work quantifies their technico-economic impacts. Results show that, after scientific sizing and fine-grained dispatch, the on-/off-grid wind–solar ammonia system can switch operating modes flexibly under variable renewable output, effectively smooth fluctuations and keep the ammonia synthesis unit running stably and efficiently; the grid-connected configuration outperforms the off-grid one. In the case-study region, as wind capacity increases the required electrolyzer and hydrogen-storage capacities first decline and then rise, reaching an economic optimum when installed wind and PV capacities are approximately equal.
[Keywords] wind–solar hybrid system; green ammonia; capacity and dispatch optimization; wind-to-PV capacity ratio

本文聚焦于内蒙古特定区域,精心打造了兼具并网与离网功能的风光制氢合成氨系统。在深入考量运行调度优化策略的前提下,构建了一个以系统收益最大化为导向的目标函数优化模型。通过细致剖析风光容量配比,深入探究了其对并网型与离网型系统技术经济层面的影响,并得出以下关键结论。
1)所构建的并/离网风光制氢合成氨系统,在历经各设备科学合理的容量配置后,展现出了良好的经济性。同时,借助系统运行调度优化分析,该系统能够在风光出力条件各异的情况下,灵活且合理地切换工作状态,确保合成氨设备实现稳定、持续的生产作业,并显著提升了可再生能源的利用效率。
2)经系统容量调度优化分析发现,并网型系统在综合性能上更胜一筹。具体而言,离网型系统的合成氨平准化成本高达3807.16元/t,较并网型系统高出15.77%。这一差异主要源于离网型系统需配置更大容量的电解槽和储氢罐,同时还需配备蓄电池,从而增加了成本。
3)在本文所研究的内蒙古特定区域内,对于并网型系统而言,当风电装机容量略高于光伏装机容量时,系统的经济性能达到最优状态;而对于离网型系统,当风光容量相近或相等时,系统的经济性能最为出色。
为积极应对全球气候变化的严峻挑战,2016年,全球主要国家携手签署了《巴黎气候协定》,达成了应对气候变化的共同意志,并共同规划了二氧化碳减排的具体路径。中国亦于2020年郑重宣布,将力争于2030年前实现碳达峰,2060年前达成碳中和的宏伟“双碳”目标。在此背景下,大力发展风能、太阳能等可再生能源,成为实现“双碳”目标、推动能源体系转型发展的核心策略与坚实支撑[1-3]。
2022年3月,中国国家发展和改革委员会与国家能源局携手发布了《氢能产业发展中长期规划(2021—2035年)》[4],清晰界定了氢能在中国能源结构调整与产业升级中的战略定位,同时明确了“构建清洁、低碳、低成本的多元制氢体系,优先发展可再生能源制氢,严格限制化石能源制氢”的发展导向。据预测,至2050年,氢能在中国能源消费中的占比将达到10%[5],有望引领人类能源体系的深刻变革,推动第三次能源革命的到来。
“绿氢”,作为二次能源的佼佼者,其潜在应用领域广泛,涵盖化工、冶金、交通、天然气掺氢、氢储能等多个行业[6]。当前,中国的氢能消费主要集中于合成氨、合成甲醇等石化领域作为工业原料,其中合成氨产业的氢气消耗量占据全国氢气总消耗量的37%[7]。利用风光等可再生能源发电生产“绿氢”,以替代“灰氢”作为化工原料合成氨(renewable power to ammonia,RePtA),已成为中国电力和化工行业碳减排的重要突破口[8-9]。然而,风能、太阳能等可再生能源具有显著的波动性、间歇性和随机性,导致风光发电出力亦呈现出较大的不稳定性。在并网型RePtA系统并网过程中,这可能引发供电电压和频率的不稳定,进而造成严重的弃风弃光现象。而对于离网型RePtA系统,风光发电出力的直接作用可能导致电解制氢设备频繁启停、寿命缩短等问题[10]。
针对RePtA系统的上述挑战,已有众多学者展开了深入探索。Richard等人[11]构建了可再生能源制氢合成氨系统的优化算法模型,深入研究了可再生能源波动对RePtA系统设计规模及经济性的影响,发现可再生能源电价、电解槽成本、哈伯-博世法操作负载以及可再生能源比例是影响系统经济性的关键因素。安光禄等[12]则从氨的季节性需求出发,构建了以系统年总成本最小化为优化目标的可再生能源合成氨系统优化设计模型,确定了系统的最优容量配置与操作计划。林今等[13]搭建了风光电解水制氢合成氨系统模型,对比分析了电网调峰型、电网友好型以及工艺离网型系统的绿氨成本及适用场景,指出近期应发展电网友好型RePtA系统,远期则应转向工艺离网型RePtA系统。李晨鹏等[14]则建立了无碳氨成本计算方法和煤电机组氨煤混燃平准化电力成本经济模型,评估了未来使用可再生能源生产的无碳氨在氨煤混燃机组中的实际应用技术经济性。尽管上述研究在RePtA系统的容量配置、运行优化以及技术经济性方面取得了有价值成果,但针对风光互补发电系统对并网型与离网型系统技术经济影响的研究仍显不足。而风光互补发电系统,正是利用风光互补的特性,对RePtA系统的容量配置与调度优化产生着重要影响。
鉴于此,本文通过构建并/离网风光互补制氢合成氨系统,以系统收益最大化为目标函数,对系统各设备的容量及运行策略进行优化,同时深入探究风光容量配比对并/离网风光互补制氢合成氨系统技术经济性的影响。
02
运行视频:
链接:
https://pan.baidu.com/s/1Tzys9HVgynX_xsAffQETng?pwd=yb8j
提取码: yb8j
--来自百度网盘超级会员v6的分享
文件结构
optimal_python/
├── generate_all_results.py # 主运行脚本,生成所有结果
├── show_results.py # 查看优化结果
├── config.py # 系统参数配置
├── requirements.txt # Python依赖包
├── data/
│ └── System_Data.xlsx # 系统数据(风光出力、电价等)
├── models/
│ ├── electrolyzer.py # 电解槽模型
│ ├── hydrogen_storage.py # 储氢罐模型
│ ├── battery.py # 蓄电池模型
│ └── ammonia_synthesis.py # 合成氨装置模型
├── solvers/
│ ├── base_optimizer.py # 优化器基类
│ ├── ongrid_optimizer.py # 并网型系统优化求解器
│ └── offgrid_optimizer.py # 离网型系统优化求解器
├── utils/
│ ├── data_loader.py # 数据加载模块
│ ├── visualization.py # 可视化函数
│ └── fonts/
│ └── SimHei.ttf # 中文字体文件
└── results/
├── figures/ # 生成的图表(11张PNG)
├── ongrid_dispatch_results.xlsx # 并网型调度结果
├── offgrid_dispatch_results.xlsx # 离网型调度结果
└── optimization_results.xlsx # 容量配比分析结果
环境要求
-
Python 3.8 或更高版本 -
Gurobi 优化器
安装步骤
1. 安装Python依赖
pip install -r requirements.txt
2. 安装Gurobi
-
下载地址:https://www.gurobi.com/downloads/ -
安装最新版本(推荐 Gurobi 10.0 或更高)
3. 获取许可证
-
学术用户:https://www.gurobi.com/academia/academic-program-and-licenses/ -
商业用户:购买商业许可证
4. 安装Gurobi Python接口
pip install gurobipy
5. 激活许可证
grbgetkey xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # 使用你的许可证密钥
6. 验证安装
import gurobipy as gp
print(gp.gurobi.version()) # 应显示版本号
运行方法
-
进入 optimal_python目录 -
运行主脚本: python generate_all_results.py
查看结果
python show_results.py
输出结果
运行完成后,将在 results/ 目录下生成:
-
11张图表(图2a-5b: 调度结果,图6-8: 容量配比分析) -
3个Excel表(并网调度、离网调度、配比分析)
03
"""
生成所有优化结果和图表的主脚本
"""
import os
import sys
import pandas as pd
# 检查当前目录
if os.path.basename(os.getcwd()) != 'optimal_python':
print('请在optimal_python目录下运行此脚本')
sys.exit(1)
sys.path.insert(0, os.getcwd())
from utils.data_loader import DataLoader
from solvers.ongrid_optimizer import OnGridOptimizer
from solvers.offgrid_optimizer import OffGridOptimizer
from utils.visualization import (
plot_power_balance_ongrid,
plot_hydrogen_balance,
plot_power_balance_offgrid,
setup_chinese_font
)
import matplotlib.pyplot as plt
print('='*80)
print('生成所有优化结果和图表')
print('='*80)
print('\n本脚本将生成:')
print(' 1. 详细调度结果(8760小时)')
print(' 2. 电力平衡和氢平衡图(图2-5)')
print(' 3. 容量配比分析结果')
print(' 4. 容量配比对比图(图6-8)')
print('='*80)
response = input('\n是否继续?(y/n): ')
if response.lower() != 'y':
print('已取消')
sys.exit(0)
# 创建结果目录
os.makedirs('results', exist_ok=True)
os.makedirs('results/figures', exist_ok=True)
# ============================================================================
# 第1步:生成详细调度结果(用于图2-5)
# ============================================================================
print('\n' + '='*80)
print('第1步:生成详细调度结果')
print('='*80)
# 1.1 并网型调度结果
print('\n[1.1] 并网型系统(风电600MW + 光伏600MW)...')
data_loader_on = DataLoader()
optimizer_on = OnGridOptimizer(data_loader_on)
optimizer_on.set_fixed_capacities(wind_capacity=600, solar_capacity=600)
optimizer_on.build_model()
success_on = optimizer_on.solve(time_limit=900, mip_gap=0.02, verbose=False)
if success_on:
dispatch_data = optimizer_on.results['dispatch']
df_ongrid = pd.DataFrame(dispatch_data)
ongrid_file = os.path.join('results', 'ongrid_dispatch_results.xlsx')
df_ongrid.to_excel(ongrid_file, index=False)
print(f' 已保存: {ongrid_file} ({df_ongrid.shape[0]}行 x {df_ongrid.shape[1]}列)')
else:
print(' 失败: 并网型优化失败')
sys.exit(1)
# 1.2 离网型调度结果(使用最优配比600+600)
print('\n[1.2] 离网型系统(风电600MW + 光伏600MW)...')
data_loader_off = DataLoader()
optimizer_off = OffGridOptimizer(data_loader_off)
optimizer_off.set_fixed_capacities(wind_capacity=600, solar_capacity=600)
optimizer_off.build_model()
success_off = optimizer_off.solve(time_limit=900, mip_gap=0.02, verbose=False)
if success_off:
dispatch_data = optimizer_off.results['dispatch']
df_offgrid = pd.DataFrame(dispatch_data)
offgrid_file = os.path.join('results', 'offgrid_dispatch_results.xlsx')
df_offgrid.to_excel(offgrid_file, index=False)
print(f' 已保存: {offgrid_file} ({df_offgrid.shape[0]}行 x {df_offgrid.shape[1]}列)')
else:
print(' 失败: 离网型优化失败')
sys.exit(1)
# ============================================================================
# 第2步:生成电力平衡和氢平衡图(图2-5)
# ============================================================================
print('\n' + '='*80)
print('第2步:生成电力平衡和氢平衡图(图2-5)')
print('='*80)
setup_chinese_font()
figures_dir = os.path.join('results', 'figures')
# 2.1 并网型图表
print('\n[2.1] 并网型系统图表...')
plot_power_balance_ongrid(df_ongrid, 0, 168,
os.path.join(figures_dir, '图2a_并网型大风季电力平衡.png'))
plot_power_balance_ongrid(df_ongrid, 4368, 4368+168,
os.path.join(figures_dir, '图2b_并网型小风季电力平衡.png'))
plot_hydrogen_balance(df_ongrid, 0, 168,
os.path.join(figures_dir, '图3a_并网型大风季氢平衡.png'), system_mode='ongrid')
plot_hydrogen_balance(df_ongrid, 4368, 4368+168,
os.path.join(figures_dir, '图3b_并网型小风季氢平衡.png'), system_mode='ongrid')
print(' 已生成图2a, 2b, 3a, 3b')
# 2.2 离网型图表
print('\n[2.2] 离网型系统图表...')
plot_power_balance_offgrid(df_offgrid, 0, 168,
os.path.join(figures_dir, '图4a_离网型大风季电力平衡.png'))
plot_power_balance_offgrid(df_offgrid, 4368, 4368+168,
os.path.join(figures_dir, '图4b_离网型小风季电力平衡.png'))
plot_hydrogen_balance(df_offgrid, 0, 168,
os.path.join(figures_dir, '图5a_离网型大风季氢平衡.png'), system_mode='offgrid')
plot_hydrogen_balance(df_offgrid, 4368, 4368+168,
os.path.join(figures_dir, '图5b_离网型小风季氢平衡.png'), system_mode='offgrid')
print(' 已生成图4a, 4b, 5a, 5b')
# ============================================================================
# 第3步:容量配比分析
# ============================================================================
print('\n' + '='*80)
print('第3步:容量配比分析')
print('='*80)
import numpy as np
# 配比参数(与MATLAB一致)
wind_caps = np.arange(150, 1200 + 150, 150)
solar_caps = 1200 - wind_caps
# 并网型和离网型使用相同配比
wind_capacities_ongrid = wind_caps
solar_capacities_ongrid = solar_caps
wind_capacities_offgrid = wind_caps
solar_capacities_offgrid = solar_caps
results_ongrid = []
results_offgrid = []
# 3.1 并网型分析
print(f'\n[3.1] 并网型分析({len(wind_capacities_ongrid)}个配比)...')
for i, (wind_cap, solar_cap) in enumerate(zip(wind_capacities_ongrid, solar_capacities_ongrid)):
print(f' [{i+1}/{len(wind_capacities_ongrid)}] 风电={wind_cap:.0f}MW, 光伏={solar_cap:.0f}MW', end=' ')
try:
data_loader = DataLoader()
optimizer = OnGridOptimizer(data_loader)
optimizer.set_fixed_capacities(wind_capacity=wind_cap, solar_capacity=solar_cap)
optimizer.build_model()
success = optimizer.solve(time_limit=600, mip_gap=0.02, verbose=False)
if success:
cap = optimizer.results['capacity']
econ = optimizer.results['economics']
results_ongrid.append({
'风电容量_MW': wind_cap,
'光伏容量_MW': solar_cap,
'电解槽容量_Nm3_h': cap['电解槽容量_Nm3_h'],
'储氢罐容量_kg': cap['储氢罐容量_kg'],
'合成氨产能_ton_year': cap['合成氨产能_ton_year'],
'年化总成本_万元': econ['年化总成本_万元'],
'年产氨量_吨': econ['年产氨量_吨'],
'单位氨成本_元_吨': econ['单位氨成本_元_吨'],
})
print(f'成本={econ["单位氨成本_元_吨"]:.2f}元/t')
else:
raise Exception("求解失败")
except Exception as e:
print(f'失败: {str(e)}')
results_ongrid.append({
'风电容量_MW': wind_cap, '光伏容量_MW': solar_cap,
'电解槽容量_Nm3_h': np.nan, '储氢罐容量_kg': np.nan,
'合成氨产能_ton_year': np.nan, '年化总成本_万元': np.nan,
'年产氨量_吨': np.nan, '单位氨成本_元_吨': np.nan,
})
# 3.2 离网型分析
print(f'\n[3.2] 离网型分析({len(wind_capacities_offgrid)}个配比)...')
for i, (wind_cap, solar_cap) in enumerate(zip(wind_capacities_offgrid, solar_capacities_offgrid)):
print(f' [{i+1}/{len(wind_capacities_offgrid)}] 风电={wind_cap:.0f}MW, 光伏={solar_cap:.0f}MW', end=' ')
try:
data_loader = DataLoader()
optimizer = OffGridOptimizer(data_loader)
optimizer.set_fixed_capacities(wind_capacity=wind_cap, solar_capacity=solar_cap)
optimizer.build_model()
success = optimizer.solve(time_limit=600, mip_gap=0.02, verbose=False)
if success:
cap = optimizer.results['capacity']
econ = optimizer.results['economics']
results_offgrid.append({
'风电容量_MW': wind_cap,
'光伏容量_MW': solar_cap,
'电解槽容量_Nm3_h': cap['电解槽容量_Nm3_h'],
'储氢罐容量_kg': cap['储氢罐容量_kg'],
'蓄电池容量_MWh': cap['蓄电池容量_MWh'],
'合成氨产能_ton_year': cap['合成氨产能_ton_year'],
'年化总成本_万元': econ['年化总成本_万元'],
'年产氨量_吨': econ['年产氨量_吨'],
'单位氨成本_元_吨': econ['单位氨成本_元_吨'],
})
print(f'成本={econ["单位氨成本_元_吨"]:.2f}元/t')
else:
raise Exception("求解失败")
except Exception as e:
import traceback
print(f'失败: {str(e)}')
print(traceback.format_exc())
results_offgrid.append({
'风电容量_MW': wind_cap, '光伏容量_MW': solar_cap,
'电解槽容量_Nm3_h': np.nan, '储氢罐容量_kg': np.nan,
'蓄电池容量_MWh': np.nan, '合成氨产能_ton_year': np.nan,
'年化总成本_万元': np.nan, '年产氨量_吨': np.nan,
'单位氨成本_元_吨': np.nan,
})
# 3.3 保存容量配比分析结果
print('\n[3.3] 保存容量配比分析结果...')
df_ratio_ongrid = pd.DataFrame(results_ongrid)
df_ratio_offgrid = pd.DataFrame(results_offgrid)
results_file = os.path.join('results', 'optimization_results.xlsx')
with pd.ExcelWriter(results_file, engine='openpyxl') as writer:
df_ratio_ongrid.to_excel(writer, sheet_name='并网型_容量配比分析', index=False)
df_ratio_offgrid.to_excel(writer, sheet_name='离网型_容量配比分析', index=False)
print(f' 已保存: {results_file}')
# ============================================================================
# 第4步:生成容量配比对比图(图6-8)
# ============================================================================
print('\n' + '='*80)
print('第4步:生成容量配比对比图(图6-8)')
print('='*80)
# 图6:电解槽容量
fig, ax = plt.subplots(figsize=(12, 6))
x_axis = np.arange(1, len(df_ratio_ongrid) + 1)
ax.plot(x_axis, df_ratio_ongrid['电解槽容量_Nm3_h']/1000,
marker='o', linewidth=2.5, markersize=8, label='并网型', color='#4472C4')
ax.plot(x_axis, df_ratio_offgrid['电解槽容量_Nm3_h']/1000,
marker='s', linewidth=2.5, markersize=8, label='离网型', color='#ED7D31')
# 设置x轴刻度标签
xtick_labels = [f"风:{int(row['风电容量_MW'])} 光:{int(row['光伏容量_MW'])}"
for _, row in df_ratio_ongrid.iterrows()]
ax.set_xticks(x_axis)
ax.set_xticklabels(xtick_labels, fontsize=9)
ax.set_xlabel('风光容量配比/MW', fontsize=14)
ax.set_ylabel('电解槽容量/(千Nm3/h)', fontsize=14)
ax.grid(True, alpha=0.3, linestyle='--')
ax.legend(loc='upper right', fontsize=12, frameon=True, shadow=True)
ax.tick_params(labelsize=11)
plt.tight_layout()
plt.savefig(os.path.join(figures_dir, '图6_风光配比对电解槽容量影响.png'), dpi=300, bbox_inches='tight')
plt.close()
print(' 已保存: 图6_风光配比对电解槽容量影响.png')
# 图7:储氢罐容量
fig, ax = plt.subplots(figsize=(12, 6))
x_axis = np.arange(1, len(df_ratio_ongrid) + 1)
ax.plot(x_axis, df_ratio_ongrid['储氢罐容量_kg']/1000,
marker='o', linewidth=2.5, markersize=8, label='并网型', color='#4472C4')
ax.plot(x_axis, df_ratio_offgrid['储氢罐容量_kg']/1000,
marker='s', linewidth=2.5, markersize=8, label='离网型', color='#ED7D31')
# 设置x轴刻度标签
xtick_labels = [f"风:{int(row['风电容量_MW'])} 光:{int(row['光伏容量_MW'])}"
for _, row in df_ratio_ongrid.iterrows()]
ax.set_xticks(x_axis)
ax.set_xticklabels(xtick_labels, fontsize=9)
ax.set_xlabel('风光容量配比/MW', fontsize=14)
ax.set_ylabel('储氢罐容量/(吨)', fontsize=14)
ax.grid(True, alpha=0.3, linestyle='--')
ax.legend(loc='upper right', fontsize=12, frameon=True, shadow=True)
ax.tick_params(labelsize=11)
plt.tight_layout()
plt.savefig(os.path.join(figures_dir, '图7_风光配比对储氢罐容量影响.png'), dpi=300, bbox_inches='tight')
plt.close()
print(' 已保存: 图7_风光配比对储氢罐容量影响.png')
# 图8:合成氨成本
fig, ax = plt.subplots(figsize=(12, 6))
x_axis = np.arange(1, len(df_ratio_ongrid) + 1)
ax.plot(x_axis, df_ratio_ongrid['单位氨成本_元_吨'],
marker='o', linewidth=2.5, markersize=8, label='并网型', color='#4472C4')
ax.plot(x_axis, df_ratio_offgrid['单位氨成本_元_吨'],
marker='s', linewidth=2.5, markersize=8, label='离网型', color='#ED7D31')
# 标注最优点
valid_ongrid = df_ratio_ongrid['单位氨成本_元_吨'].notna()
valid_offgrid = df_ratio_offgrid['单位氨成本_元_吨'].notna()
if valid_ongrid.any():
ongrid_min_idx = df_ratio_ongrid.loc[valid_ongrid, '单位氨成本_元_吨'].idxmin()
ax.plot(ongrid_min_idx + 1, df_ratio_ongrid.loc[ongrid_min_idx, '单位氨成本_元_吨'],
marker='*', markersize=15, color='red', zorder=5)
ax.annotate(f'最优点\n({df_ratio_ongrid.loc[ongrid_min_idx, "风电容量_MW"]:.0f} MW, '
f'{df_ratio_ongrid.loc[ongrid_min_idx, "单位氨成本_元_吨"]:.0f} 元/t)',
xy=(ongrid_min_idx + 1, df_ratio_ongrid.loc[ongrid_min_idx, '单位氨成本_元_吨']),
xytext=(20, 30), textcoords='offset points', fontsize=10, ha='left',
bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.7),
arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0'))
if valid_offgrid.any():
offgrid_min_idx = df_ratio_offgrid.loc[valid_offgrid, '单位氨成本_元_吨'].idxmin()
ax.plot(offgrid_min_idx + 1, df_ratio_offgrid.loc[offgrid_min_idx, '单位氨成本_元_吨'],
marker='*', markersize=15, color='red', zorder=5)
ax.annotate(f'最优点\n({df_ratio_offgrid.loc[offgrid_min_idx, "风电容量_MW"]:.0f} MW, '
f'{df_ratio_offgrid.loc[offgrid_min_idx, "单位氨成本_元_吨"]:.0f} 元/t)',
xy=(offgrid_min_idx + 1, df_ratio_offgrid.loc[offgrid_min_idx, '单位氨成本_元_吨']),
xytext=(20, -40), textcoords='offset points', fontsize=10, ha='left',
bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.7),
arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0'))
# 设置x轴刻度标签
xtick_labels = [f"风:{int(row['风电容量_MW'])} 光:{int(row['光伏容量_MW'])}"
for _, row in df_ratio_ongrid.iterrows()]
ax.set_xticks(x_axis)
ax.set_xticklabels(xtick_labels, fontsize=9)
ax.set_xlabel('风光容量配比/MW', fontsize=14)
ax.set_ylabel('合成氨平准化成本/(元/吨)', fontsize=14)
ax.grid(True, alpha=0.3, linestyle='--')
ax.legend(loc='upper right', fontsize=12, frameon=True, shadow=True)
ax.tick_params(labelsize=11)
plt.tight_layout()
plt.savefig(os.path.join(figures_dir, '图8_风光配比对合成氨成本影响.png'), dpi=300, bbox_inches='tight')
plt.close()
print(' 已保存: 图8_风光配比对合成氨成本影响.png')
04
文章中一些内容引自网络,会注明出处或引用为参考文献,难免有未尽之处,如有不妥,请随时联系删除。
[1]邓振宇,周家辉,徐钢,等.并/离网风光互补制氢合成氨系统容量-调度优化分析[J].热力发电, 2024, 53(9):136-146.
05

