风光互补制氢合成氨这个方向,这几年在新能源圈子里的讨论度一直很高。原因很直白:风电光伏天生波动大,直接并网冲击不小,但要是把多余的电拿来制氢,再把氢和氮合成氨,就相当于把不稳定的电能变成了稳定可控的化学能,无论是储存、运输还是后续作为化工原料,都顺畅得多。不过这套系统的容量怎么配、运行怎么调度,是个典型的两层优化难题——配太大,设备闲置浪费;配太小,风光大发时又没法充分利用。我之前复现过不少类似的容量优化论文,这篇“并_离网风光互补制氢合成氨系统容量-调度优化分析”的Python复现,算是其中比较有代表性、也适合练手的一个。
P.S. 老规矩,这个标题里的“并_离网”指的是系统可以工作在并网和离网两种模式。很多论文会把这两种模式分开建模,复现时最大的工作量往往不在优化算法本身,而在设备模型的搭建和两种模式切换逻辑的处理上。这篇文章会按照我自己复现时的思路,从系统建模、数学公式、求解器实现到实际踩过的坑,完整过一遍,给后面想在这个方向动手的朋友做个参考。
1. 系统整体设计与建模思路拆解
1.1 系统架构与能量流梳理
先把这个系统里面都有什么捋清楚。一套典型的风光互补制氢合成氨系统,你可以把它理解成一个完全围绕“电—氢—氨”这条主线运转的微型综合能源系统。
电气侧:风电、光伏是主力电源,蓄电池负责短时缓冲,电解槽是主要用电负荷,同时系统还接了一个可选的并网点。热词里提到的Python,在整个复现里主要扮演“建模+求解”的角色,后面会细说。
化工侧:电解槽产出的氢气进储氢罐,空分装置提供氮气,氢气和氮气按3比1的摩尔比进入合成氨装置生成氨,产物进液氨储罐。储能侧除了蓄电池,还有储氢罐这个“化学储能”,两者配合能覆盖从秒级到小时级的能量平衡需求。
这套架构放在并网模式下的逻辑其实很简单:电网就像一个无限大的“缓冲池”,发多了可以卖,发少了可以买。但离网模式才是真正考验系统设计的地方——所有时刻的能量平衡都必须由系统内部的电源、储能和负荷自己解决。
复现的第一步,是把这套物理架构转成可计算的能量流拓扑。我处理的方式是把所有设备都抽象成带效率系数的“能量转换节点”,整个系统看成一个带约束的能量路由网络:
- 风光出力经过各自的转换效率后汇入直流母线
- 母线电量按“先保基础负荷、再供电解槽、多余充蓄电池、再多余考虑并网(并网模式)”的优先级进行分配
- 电解槽消耗电能和水,产出氢气和氧气
- 氢气进储氢罐,罐内氢气与空分来的氮气混合进入合成氨单元
- 合成氨单元的输出进入液氨储罐,作为系统的最终产品
清楚这个能量流之后,后续所有建模工作就有的放矢了。特别提醒一下,很多刚开始复现的朋友会忽略“氧气副产品”的处理,实际工程里氧气也有收益,但大多数论文模型里直接忽略或按放空处理,复现时建议遵循论文假设,不要自行加复杂度。
1.2 两种运行模式的关键区别:并网 vs 离网
“并_离网”是这个问题里最有意思、也最容易被忽略的部分。不少复现者一上来就只盯着容量优化,结果忽略了两种模式的本质区别,导致模型约束条件不完整,算出来结果自然对不上。
并网模式(Grid-connected mode)下,系统与电网存在功率交换。这意味着:
- 电网可以“兜底”:风光不出力、蓄电池放空时,电解槽和合成氨负荷可以靠购电维持运行
- 电网可以“吸纳”:风光大发、蓄电池充满、氢罐也满时,多余电量可以卖给电网获得收益
- 系统内部的“电量平衡”约束变为包含购售电项的扩展形式,母线不一定每时每刻都“自给自足”
离网模式(Islanded mode)下,系统与电网完全断开。这意味着:
- 所有负荷必须由风光和蓄电池共同承担,存在严格的实时功率平衡约束
- 若风光出力不足且蓄电池电量耗尽,系统只能被迫削减负荷(比如降功率运行电解槽或直接停槽)
- 系统设计冗余度需要更高,否则供电可靠性很难保证
复现时,这两套约束一般通过一个0-1二进制变量来切换。通常的做法是:在容量优化的上层问题中,以投资成本最低为目标,同时决策系统的装机容量;在下层调度问题中,固定容量方案,分别计算两种模式下的运行成本或可靠性指标。如果你的论文里两种模式是分开建模的,那么代码里也应当分开写约束,而不是试图用一套约束统一处理,否则非线性会特别离谱。
2. 数学建模:目标函数、决策变量与核心约束
2.1 通用建模框架:这种问题到底在优化什么
这类容量-调度联合优化,本质上是一个双层优化问题。上层做“容量规划决策”,回答“风、光、蓄、电解槽、储氢、合成氨各配多大”;下层做“运行调度决策”,回答“在给定容量下,每个时刻各设备怎么出力”。
用通俗的话来比喻,上层是“开厂前定设备采购清单”,下层是“设备买回来后每天怎么排产”。这两个问题互相咬合:设备配得少,下层调度再优化也没法满足负荷需求;设备配得多,下层调度再省钱也抵不掉投资成本。所以在复现中,上下层必须作为一个整体交替迭代求解。
一个常见的目标函数形式如下:
min 总成本 = 年化投资成本 + 年运行维护成本 + 购电成本 - 售电收益 - 氨产品收益其中年化投资成本是把各设备的初始投资按寿命期折成每年等额支付;运行维护成本一般按装机容量的百分比估算;购电成本仅在并网模式下存在;售电收益和氨产品收益是系统的收入项,分别体现了并网卖电和离网卖氨的经济来源差异。
紧跟着目标函数的是约束条件。容量约束(各设备容量不能超过规划上限)、功率平衡约束(任一时刻电源总出力等于负荷总需求)、储能SOC递推约束(蓄电池和储氢罐的时变平衡)、爬坡约束(设备出力变化速率限制)、运行上下限约束等等,一个都不能少。
2.2 风光出力建模:从气象数据到功率时序
风光出力时序是整个优化的“输入边界”,如果这块儿算得不合理,后面所有优化结果都不可信。
风电出力模型常用如下功率曲线关系:
P_wt(t) = 0, v(t) < v_in 或 v(t) > v_out P_rated * (v(t) - v_in) / (v_rated - v_in), v_in ≤ v(t) < v_rated P_rated, v_rated ≤ v(t) ≤ v_out而光伏出力则采用:
P_pv(t) = η_pv * S_pv * I(t) * (1 - k_temp * (T_cell(t) - 25))其中 I(t) 是水平面太阳辐照度,T_cell(t) 是电池板温度,k_temp 是温度系数。复现时一般直接取全年8760小时的实测气象数据或者典型年数据。
这里有个特别容易踩的坑:时间分辨率。很多论文用的是8760小时(1小时间隔),但实际上风电和光伏的波动在分钟级更明显,尤其是离网模式下,1小时的调度尺度过粗,会低估系统对储能的需求。复现时建议先用8760小时数据跑通全流程,如果计算资源允许,再尝试把风光出力数据降采样到15分钟粒度,观察结果变化。
2.3 电解槽与合成氨单元的建模细节
电解槽模型是电氢耦合的核心环节。工程上常用效率法或U-I特性曲线法建模。效率法简单直接:
m_H2(t) = η_el * P_el(t) / HHV_H2这里的 HHV_H2 是氢的高热值(约 39.4 kWh/kg),η_el 是电解槽综合效率。注意,这里用的P_el是电解槽消耗的直流电功率。碱性电解槽一般有最低运行负荷限制(比如最低下限为额定功率的10%-20%),否则产气纯度不达标,这一条在优化模型中要体现。
合成氨单元本质上是一个化工反应器,但在这个层面的优化模型里通常不细究反应动力学,而是用一个“氢氨转换效率”来简化。按反应式 N₂ + 3H₂ → 2NH₃,产出1吨氨需要约0.176吨氢,但由于反应不完全和循环气损失,实际耗氢量会略高。很多论文直接写成:
m_NH3(t) = η_syn * m_H2_to_syn(t) / stoichiometric_ratio这里的 stoichiometric_ratio 大约是 3:1 的摩尔比换算成质量比,η_syn 是合成回路的氢利用率,一般取0.8-0.9之间。复现时建议仔细看原文用的哪个值,不同的取值对合成氨的产量影响是线性的,但会直接影响经济性最优解。
储氢罐的建模和蓄电池的SOC递推非常相似:
SOC_H2(t+1) = SOC_H2(t) + (m_H2_prod(t) - m_H2_to_syn(t)) * Δt上限是储氢容量,下限一般可以放空,但实际工程中为了保护设备会设置最低压力对应的最低储量。
3. Python代码实现:从数据准备到求解器落地
3.1 准备工作:环境、依赖库和项目结构
先交代一下环境。我在复现时用的是Python 3.9,主要依赖库如下:
- numpy / pandas:处理气象数据和整理时序结果
- matplotlib:绘图
- scipy:如果涉及非线性优化或曲线拟合
- pyomo:建模优化问题的标准工具,支持多种求解器后端
- gurobipy:或者直接调Gurobi求解器(如果是学术许可)
安装建议直接用pip一把梭:
pip install numpy pandas matplotlib scipy pyomo求解器方面,如果只是跑通流程,用开源免费的GLPK就够。但说实话,处理这种小时级全年数据 + 双层迭代的大规模MILP问题,GLPK会比较吃力,我自己实际操作中效果最好的是Gurobi,其次是CBC。如果遇到求解太慢,优先检查是不是模型里的Big-M参数取太大,这个后面会专门说。
项目文件结构我习惯这样组织:
project/ ├── data/ │ ├── wind_speed.csv │ ├── solar_irradiance.csv │ └── load_profile.csv ├── src/ │ ├── models.py # 设备模型(风机、光伏、电解槽、储能等) │ ├── optimization.py # 双层优化主逻辑 │ ├── scheduling.py # 下层调度模型 │ └── utils.py # 数据处理和绘图工具 ├── results/ └── main.py3.2 关键代码模块逐段解析
数据加载与预处理
import pandas as pd import numpy as np def load_meteorological_data(wind_file, solar_file): df_wind = pd.read_csv(wind_file, index_col=0, parse_dates=True) df_solar = pd.read_csv(solar_file, index_col=0, parse_dates=True) df = pd.concat([df_wind, df_solar], axis=1) df.columns = ['wind_speed', 'irradiance'] df = df.resample('H').mean() # 统一到小时级 return df这里resample('H')这一步很重要。不同来源的气象数据粒度可能不一致,必须统一到调度时间尺度才能喂进优化模型。
风光出力计算
def wind_power(wind_speed, v_in=3, v_rated=12, v_out=25, P_rated=1.0): P = np.zeros_like(wind_speed, dtype=float) mask1 = (wind_speed >= v_in) & (wind_speed < v_rated) mask2 = (wind_speed >= v_rated) & (wind_speed <= v_out) P[mask1] = P_rated * (wind_speed[mask1] - v_in) / (v_rated - v_in) P[mask2] = P_rated return P def pv_power(irradiance, eta_pv=0.18, S=1.0, k_temp=0.004, T_cell=25): return eta_pv * S * irradiance * (1 - k_temp * (T_cell - 25))单机功率曲线算出来后,别忘了乘以装机台数/面积。在优化模型里,这里其实是决策变量(装机容量)乘单位容量出力系数,这么处理就可以把非线性问题线性化。
Pyomo建模核心:容量与调度双层框架
上层模型用Pyomo定义决策变量,典型写法:
from pyomo.environ import * model = ConcreteModel() # 决策变量:各设备容量 model.N_wt = Var(domain=NonNegativeReals, bounds=(0, 50)) # 风机数量 model.S_pv = Var(domain=NonNegativeReals, bounds=(0, 50000)) # 光伏面积 m2 model.E_bat = Var(domain=NonNegativeReals, bounds=(0, 10000)) # 蓄电池容量 kWh ...下层调度模型需要传入上层给定的容量参数,再建一个独立的子问题:
def build_scheduling_model(profile, capacities): model = ConcreteModel() model.T = Set(initialize=range(8760)) # 决策变量:各时刻各设备的出力、储能状态等 model.P_buy = Var(model.T, domain=NonNegativeReals) # 购电功率 model.P_sell = Var(model.T, domain=NonNegativeReals) # 售电功率 model.P_el = Var(model.T, domain=NonNegativeReals) # 电解槽功率 model.SOC_bat = Var(model.T, domain=NonNegativeReals) # 电池SOC ...两层叠起来就是迭代循环:上层给一组容量候选值 → 下层求解最优调度 → 把下层求得的最小运行成本返回给上层 → 上层算总成本 → 更新容量决策。高级求解器可以直接把两层捏成一个混合整数线性规划(MILP)来整体求解,但对于刚上手的朋友,我建议先写“穷举容量候选 + 固定容量调度优化”的两步法,逻辑清晰,调试方便。
3.3 求解器选型与求解效率对比:实际试过的方案
直接说结论,这个双层问题我在复现时试过三种方案:
| 方案 | 求解方法 | 速度 | 适用规模 | 备注 |
|---|---|---|---|---|
| 穷举法+LP调度 | 遍历候选容量组合,每个组合解一个LP | 较慢 | 容量维度少时 | 简单直观,适合验证模型正确性 |
| 启发式算法+LP | PSO/GA搜索容量,内层LP算调度 | 中等 | 中等规模 | 可处理非线性目标,论文常用 |
| 全MILP单层化 | 容量和调度变量同时求解 | 快 | 线性化后的大规模MILP | 需要商业求解器支撑 |
让我印象很深的是,第一次跑全MILP时,变量数量直接爆到几十万个,Gurobi默认参数解到2%的MIP gap就要半小时。后来做了两件事明显提速:一是把蓄电池的SOC递推约束做了“滚动时域绑定”,二是把Big-M的M从 1e6 精细到各变量的实际物理上限,半小时的求解时间直接缩到五分钟以内。
所以想给复现提效的朋友,第一优先级是调Big-M参数,第二优先级才是换求解器。
4. 调度策略与并/离网切换逻辑的实现
4.1 并网模式下的最优经济调度
并网模式下,系统调度本质上是一个含购售电的价格响应问题。电价低时多购电制氢(相当于储氢),电价高时减少购电甚至卖电。这里面有一个非常关键的“套利”逻辑:氢气作为可储存的化学能,它本身就是一种“长时储能介质”——电价低谷时把电能变成氢存起来,电价高峰时可以(如果配置了燃料电池)再变回电,或者直接卖氢产品获得收益。
写代码时,并网模式只需修改功率平衡约束:
ΣP_renewable(t) + P_bat_discharge(t) + P_buy(t) = P_load(t) + P_el(t) + P_bat_charge(t) + P_sell(t)注意,等式两边同时存在的 P_buy 和 P_sell 在物理上不可能同时为正,但数学上如果没有互斥约束,求解器可能会算出又买又卖这种荒唐解。所以必须加一个互补约束:
model.P_buy[t] <= M * model.u_buy[t] model.P_sell[t] <= M * (1 - model.u_buy[t]) model.u_buy[t] = Binary()这个“购售电互斥”约束是我见过新手最容易漏的约束之一,漏掉之后求解器确实能快速收敛到最优解,但结果毫无物理意义。
4.2 离网模式下的供电可靠性与负荷削减
离网模式的调度目标需要改变。因为没有电网兜底,严格的自平衡约束意味着只需要调整功率平衡方程——去掉购售电项:
ΣP_renewable(t) + P_bat_discharge(t) = P_load(t) + P_el(t) + P_bat_charge(t)但残酷的地方在于,如果某个时段风光出力极低、蓄电池又没电,这个方程无解。那怎么办?两个选择:
一是添加虚拟的“负荷削减”变量(或者说弃电/切负荷变量),允许模型在极端场景下削减部分负荷,但在目标函数中给一个很高的惩罚系数。这样模型会自动权衡:是多配风光储来避免削减,还是接受偶尔的削减来节省投资。
二是强制系统“永不缺电”,那容量规划结果会特别浪费,经济性会很差。大多数论文采用前一种带惩罚的处理方式。
从实现角度,我推荐在约束中引入松弛变量:
model.curtailment = Var(model.T, domain=NonNegativeReals) def power_balance_rule(model, t): return ( P_renewable[t] + P_bat_discharge[t] + model.curtailment[t] >= P_load[t] + P_el[t] + P_bat_charge[t] )在目标函数里给curtailment配一个特别大的惩罚系数。这么处理后,极端场景下系统会被允许短暂切负荷,但优化结果会“尽量”避免这种情况发生——因为你切一次负荷损失的钱,可能比多装几块光伏板还贵。
4.3 并/离网切换的时间粒度与模式选择策略
复现时还要考虑一个实际问题:系统按什么频率切换并/离网状态?是全年固定一种模式,还是根据季节、电价、风光资源动态切换?
我复现的那篇论文里做的是“模式单独优化”:分别对并网和离网两种模式做容量+调度优化,最后比较两种结果的经济性差异。这种处理方式的好处是逻辑简单,结果便于对比分析;缺点是没考虑“同一个系统年内动态切换”的可能。
如果你想做得更细,可以引入一个“运行模式决策变量”,让模型自己决定每个时段是在并网还是离网模式。但这会引入大量二进制变量和模式之间转换的约束,求解难度上升快,速度会明显变慢。复现阶段,我的建议还是先按论文原始设定来,论文说“分别优化”,你就分开跑,论文说“动态切换”,再做切换逻辑。
5. 常见坑与调试经验:这些坑我基本都踩过
5.1 数学建模层面的通病
储能初始SOC设错。很多复现代码直接把蓄电池和储氢罐的初始SOC设为0,导致系统前十几个小时一直在“充电恢复SOC”阶段,调度结果完全失真。正确做法是让模型跑完整个周期后要求最终SOC不低于初始SOC,或者直接采用“循环调度”假设,取典型日而非连续全年数据。我踩过一回,在离网模式下,初始SOC设为0时,系统会第一个小时就疯狂买电充电,导致容量优化结果偏大。
风光装机容量取值区间不当。容量优化的上限如果设得太小,最优解会卡在边界上,得出来的“最优容量”其实没意义。建议先跑一次不含容量约束的松弛模型,看看自然最优解落在什么量级,再给容量设一个比自然解大20%-30%的上限。
没有考虑设备启停损耗。电解槽频繁启停在工程上是不现实的,冷启动需要较长时间预热,而且会加速极板衰减。如果在模型里完全不加启停次数限制,求解器可能给出“10分钟启停一次”这种荒谬的方案。一个简单做法是加最大启停次数约束,或者加一个最小连续运行时间约束。
5.2 代码实现层面的细节坑
Pyomo中索引变量与numpy数组混用。Pyomo的Var对象不能直接跟numpy的数组做广播运算,必须通过Constraint或Expression来包装。我刚开始写的时候,总是习惯性地想用model.P_el[t] * np.array(...),直接报TypeError,后来全部改成逐t写约束才解决。
求解器数值公差导致功率不平衡。Gurobi默认的可行域公差是1e-6,但重构后的松弛变量可能让结果里出现“名义上平衡但实际负负荷”的情况。解决方法是在求解完成后做一层“后处理校验”,把结果残差大于1e-3 kWh的时刻标记出来,回头检查是不是Big-M选太大导致的数值问题。
时间索引不对齐。如果气象数据是从某月1日0点开始,而调度周期是从1点开始,整体错位一小时,最终的全年电量统计就会失真。这种错位问题肉眼很难发现,我建议在数据预处理阶段统一处理,比如全部归一化到东八区整点,再用pandas的reindex对齐时间轴。
5.3 离网模式特有的“假收敛”问题
离网模式下,因为加入了“切负荷惩罚”这个松弛项,MILP求解器可能会很“聪明”地找到一个投机取巧的解:大量切负荷,几乎不配置电源和储能,总成本极低,接近0——看起来是“全局最优”,实际上是模型在作弊。
怎么防止?两个办法:
- 把切负荷惩罚系数设到足够大,大到任何合理的容量配置方案下,只要发生一小时切负荷,该方案成本就劣于多装一台风机。这个数值没有标准答案,建议用“切负荷电量 × 负荷价值”来估算。
- 对所有设备容量设置下限。比如蓄电池容量至少是日均负荷的X%,风光容量至少覆盖平均负荷的Y%。这样即便模型想偷懒,空间也有限。
我在调试时发现,惩罚系数从10元/kWh增加到100元/kWh,最优容量的风机数量会明显变化。所以文献里如果给了惩罚值,最好严格照用;如果文献没给,做参数敏感性分析时给出2-3个档位的结果对比,是论文审稿人比较认可的做法。
6. 结果分析与灵敏度讨论:从复现到真正理解
6.1 结果可视化:用图表讲清楚结论
复现完成之后,最重要的就是把结果可视化出来,否则一堆Excel表格和数据没人愿意看。我一般画四张核心图:
一是系统能量平衡时序图。横轴是全年8760小时,纵轴是功率,把风电出力、光伏出力、蓄电池充放电、电解槽功耗、购售电功率画在一起,直观看到不同季节的能量盈余和亏缺时段。
二是蓄电池SOC和储氢罐氢量变化图。这张图最有用的一点是能看出储能设备是否“空闲”——如果SOC常年保持在50%附近一动不动,说明这个容量配置冗余了,可以考虑减小储能配置来省成本。
三是不同容量方案下的成本构成堆叠图。把投资成本、运维成本、购电成本、售电收益、氨收益分别画成堆叠柱状图,一眼看出最优方案是靠什么赚钱的。
四是两种模式的成本对比雷达图。把并网和离网两种模式分别计算出的几个关键指标做个对比,比如单位制氢成本、系统自给率、弃电率、单位氨生产成本,非常直观。
6.2 容量结果对关键参数的灵敏度分析
跑完基准场景之后,一定要做灵敏度分析,这是复现论文和实际工程最有价值的一环。至少做这几个参数的灵敏度:
- 风光资源年利用小时数:如果年利用小时数下降20%,最优容量组合变化大不大?如果不大,说明系统设计比较稳健。
- 电解槽效率和单位投资成本:这两个参数直接影响最终的制氢成本,做双参数敏感性分析画个热力图,效果很好。
- 氢氨市场价格:如果氨价下跌30%,合成氨系统是否还有经济性?这个直接决定项目能否生存。
灵敏度分析的实现很简单,就是改参数重跑模型而已。但要注意:每次重跑都要记录求解器和迭代次数,如果某个参数变化后求解难度突然剧增,说明该参数对应的约束在该区间出现了退化(degeneracy),这时候要检查约束是不是写松了。
6.3 从复现到改进:后续还能做什么
复现这事儿吧,跑通别人的论文只是第一步。真正有意思的是跑通之后你自己的扩展方向。我自己想过的几个方向,供大家参考:
一是把数据中心或者铝冶炼这种高耗能负荷引入系统,形成“绿电-绿氢-绿氨-高载能产业”的协同优化,这种综合能源系统是目前比较热的方向。
二是引入电加热器或热泵来回收电解槽和合成氨反应器的废热,将热-电-氢耦合进同一个模型。系统热力学效率会提升,但模型的非线性和变量规模也会显著增长。
三是考虑季节性储氢。当前模型里储氢罐的容量一般是按日或周的调节需求来配置的,如果允许跨季节储氢,系统对冬季风光枯期的应对能力会大幅提升,但储氢罐的成本模型会更加复杂。
四是把不确定性优化引入调度层。风电光伏预测误差客观存在,用随机优化或鲁棒优化替代确定性优化,得到的容量配置会更贴近工程实际。这个方向在后续研究中非常值得投入。
7. 复现全过程总结与实操心得
把这个项目从头到尾走一遍之后,我自己有几个比较深的体会。
第一,给一个论文做Python复现,别急着上来就写代码。先把论文里的数学公式全部手推一遍,搞清楚每个变量对应物理量、每个约束的物理含义,再动手建模。我自己犯过的最大的错,就是漏看了论文里“合成氨回路氢气利用率0.85”的假设,导致结果怎么调都对不上。后来一句一句对公式才发现问题。
第二,也是很多代码经验不足的朋友容易忽略的一点:MILP模型的“求解成功”并不等于“结果可用”。每次求解完成后,一定要检查求解器返回的Status字段,确认是最优解还是可行解;同时检查MIP gap是否在接受范围内。如果gap大,宁可多等一会儿,也不要拿一个次优解去做分析。
第三,现有公开代码版本质量参差不齐,一键跑通的情况并不常见。复现过程中“把别人的代码改到自己能跑”和“自己从头实现一遍”所获得的理解深度是天壤之别。我强烈建议哪怕你看过别人的代码,也一定要自己完整地重写一遍核心模块——只有自己写一遍,那些“为什么约束要这么写”“为什么参数要这么取”才会长在脑子里。
第四,做双模式对比时,不要只比较成本数字,要比运行行为差异。比如并网模式下系统的电解槽利用小时数明显高于离网模式,因为电网兜底让系统可以更稳定地供氢;而离网模式下储氢罐的容量需求是并网模式的2-3倍,因为缺乏电网缓冲之后,氢气必须充当“跨小时能量搬运工”。这些规律比单纯一个经济性对比更有洞察力,写进论文里往往是加分项。
最后再分享一个小技巧。如果你在跑模型时发现离网模式下的最优解反复震荡,怎么调参数都不收敛,可以试着把蓄电池的初始SOC设为满电量。这样模型在早期时段就不用一边满足负荷一边辛辛苦苦给电池充电,数值稳定性会好很多。等模型跑通了,再回到初始SOC为零的设定来做正式结果——这个小技巧我自己屡试不爽,建议你也试试。