氢储能热电联供微电网优化调度:Matlab建模与求解实战
2026/9/16 1:18:16 网站建设 项目流程

做微电网优化调度这几年,我在论坛里看到最多的提问就是:氢储能热电联供微电网的文献模型看懂了,公式也能抄下来,可一到Matlab落地就卡住——变量怎么定义、约束怎么拼、求解器怎么选、结果曲线怎么读,每一步都在踩坑。说实话,我自己第一次跑通这套流程也花了不少时间,网上资料多半只给结论不给过程。所以这篇干脆按项目实践的方式,把基于氢储能的热电联供型微电网优化调度方法完整展开:从系统架构、设备建模、数学优化模型到Matlab代码实现,带你把一条链路走通。

这套方法能解决的问题很具体:园区或台区里同时有电负荷和热负荷,又装了风光、热电联产机组和氢储能设备时,怎么安排每台设备各时段的出力,才能让日运行成本最低、尽可能利用清洁能源。适合电力系统方向的研究生做开题或算例验证,也适合做综合能源项目的工程师拿来找建模思路。下面内容不涉及太高深的算法,核心是把模型搭对、把代码跑通、把结果读明白。

1. 氢储能热电联供微电网:为什么要做优化调度

1.1 氢储能解决的是能量在时间上的“错配”

微电网里的光伏和风电出力看天吃饭,白天光照强、晚上风大,和负荷曲线往往对不上。比如北方园区冬季夜间热负荷高、电负荷低,但风电往往在夜间大发,多余的电没处去就只能弃掉;白天电价高、负荷高,又得从电网买高价电。这种“时间错配”正是储能的用武之地。

锂电池储能适合做小时级的能量搬移,但要想把能量从夜间搬到白天、甚至跨天跨周存储,氢储能是更合适的方案。它通过电解槽把富余电力变成氢气存进储氢罐,等负荷高峰或电价高峰时再用燃料电池发电,发电过程中的余热还可以回收供热。氢储能相当于给微电网装了一个“能量蓄水池”,既消纳了可再生能源,又能在高价时段替代外购电,一举两得。

1.2 热电联供让“电、热、氢”三条能量线耦合在一起

单纯做电储能调度,模型只有一条电功率平衡线,问题难度低一个量级。但贴上“热电联供”标签后,系统里就有电负荷和热负荷两条平衡线,而且它们不是独立的:CHP机组发电的同时产生热量,发电功率和热功率之间存在耦合关系;燃料电池放电时产生的余热也可以回收参与供热。再加上电解槽消耗电能制氢、储氢罐存储能量、燃料电池耗氢发电,整个系统形成了“电—氢—热”的闭环能量流。

这就要求调度模型必须同时考虑电、热、氢三个能量载体。CHP机组不能只看电力经济性,还要考虑热负荷是否被满足;燃料电池是否出力,不仅取决于电价,还取决于它回收的余热能替代多少燃气锅炉的热量。这种耦合关系让“热电联供型”微电网比纯电微电网复杂得多,也更有实际工程意义——现实中综合能源园区基本都是这种多能互补形态。

所以做这件事的核心价值在于:在满足电负荷和热负荷的前提下,通过优化每台设备的出力计划,把一次能源消耗和购电成本压到最低,同时最大限度消纳风光出力。说通俗点,就是每天开机前先算一笔账:今天每台设备怎么开、开多少、充多少氢、放多少电,才能最省钱。

2. 设备建模:把物理设备翻译成约束和参数

调度优化不是拿真实设备直接调,而是把每台设备的运行特性抽象成数学模型,再交给求解器计算。设备建模的粒度不需要很精细,但必须抓住影响调度的关键约束。

2.1 风光出力:预测曲线直接作为边界输入

光伏和风电在日前调度中通常视为不可控电源,出力由预测曲线给定。做优化调度时,直接把预测值作为已知参数放进电功率平衡等式里,不需要额外建立物理模型。

实际项目中风光预测值一般来自数值天气预报加统计修正,或者简单点就用典型日曲线。如果你后面想做随机优化或鲁棒优化,可以把预测功率加上预测误差的置信区间,生成多个场景再做两阶段随机规划。但初学阶段先把确定性调度跑通,再往随机方向扩展,思路会更加清晰。

2.2 电解槽与储氢罐:制氢侧的边界条件

电解槽是氢储能系统的“充电器”,输入电功率,输出氢气。简化建模时关注三点:功率上下限、电转氢效率、运行特性。

制氢功率约束可以写成:

P_el_min <= P_el(t) <= P_el_max

单位时间内制得的氢气折算成能量:

E_produce(t) = P_el(t) * eta_el * dt

eta_el 是电解槽综合效率,工程上取 0.6~0.75 比较常见。注意这里的效率已经把整流损耗、电解槽本体损耗都折算进去了。

储氢罐的建模核心是能量状态转移约束,也就是每个时段的储氢量等于上一时段储氢量加上产氢量、减去耗氢量:

S_h2(t+1) = S_h2(t) + eta_el * P_el(t) * dt - P_fc(t) / eta_fc * dt

同时储氢量要满足容量上下限,且很多调度问题要求日循环,也就是调度周期结束时储氢量和初始时刻一致:

0 <= S_h2(t) <= Cap_h2 S_h2(T+1) == S_h2(1)

这里的储氢量统一用能量单位kWh表示,省去氢气质量、压力、温度等复杂换算,工程上够用。

2.3 燃料电池与CHP机组:放能侧的出力与余热

燃料电池是氢储能系统的“放电器”,把氢气转化成电能和热能。发电功率范围约束:

0 <= P_fc(t) <= P_fc_max

耗氢功率等于发电功率除以发电效率:

E_consume(t) = P_fc(t) / eta_fc * dt

燃料电池的余热回收是热电联供的关键。假设余热功率与发电功率近似成正比:

H_fc(t) = R_hp * P_fc(t)

量化关系需要看设备参数,一般小型燃料电池热电比R_hp在0.8~1.2之间,即发1kW电大约能回收0.8~1.2kW热。

CHP机组(热电联产机组)的建模类似但更关键。它同时产电和产热,简化模型常常假设热电比恒定:

H_chp(t) = c_ht * P_chp(t)

c_ht取值在1.0~1.8之间,具体取决于机组类型。注意这个假设把电热耦合变成了线性关系,CHP机组在某一时刻的发电功率定了,热输出也就定了,电和热两个决策变量实际上只剩一个自由度。

2.4 燃气锅炉与电网联络线:兜底与交互

燃气锅炉是热负荷的兜底热源,CHP和燃料电池的余热不够时由它补齐。锅炉模型最简单:

0 <= P_boiler(t) <= P_boiler_max

热输出直接等于输入天然气热值乘以锅炉效率,燃料成本按天然气价格计算。锅炉建得越简单越好,它只是辅助热源,不参与能量耦合。

电网联络线约束则限制系统与外电网的功率交换:

0 <= P_buy(t) <= P_grid_max 0 <= P_sell(t) <= P_grid_max

这里还有一个工程上的细节:理论上购电和售电不能同时发生。但由于售电价格通常低于购电价格,成本最小化的目标函数会自动避免同时买卖,所以很多模型里不加显式约束。除非你设置了奇怪的售电补贴价格,否则没必要徒增复杂度。

3. 优化调度数学模型:目标函数与约束条件

设备模型搭好之后,把所有等式和不等式汇总,就形成了完整的优化问题。

3.1 目标函数:把成本拆清楚

目标函数是日运行成本最小,主要包含四项:

  • CHP机组的燃料成本:c_gas * P_chp(t) / eta_chp * dt
  • 燃气锅炉的燃料成本:c_gas * P_boiler(t) / eta_boiler * dt
  • 电网购电成本:price_buy(t) * P_buy(t) * dt
  • 设备运维成本:c_om * (P_chp + P_fc + P_el + P_boiler) * dt

售电收入作为负成本放进目标函数:price_sell(t) * P_sell(t) * dt。

这里有个容易绕晕的点:为什么燃料电池发电不计算燃料成本?因为氢气来自自家电解槽,而电解槽消耗的电量已经在电功率平衡和购电成本中体现了。换句话说,氢储能的成本经过风光发电、电解制氢、燃料电池放电这条链路“转了一圈”,最终沉淀在购电成本和弃电量上。如果模型涉及外部购氢,那就要额外加购氢成本项。

3.2 全部约束与变量速查

为了便于对照,我把一个标准算例里的决策变量和约束整理成表。决策变量是各时段的设备出力,以24小时调度为例,变量维度如下:

决策变量含义维度
P_chpCHP发电功率(kW)1×24
P_boiler锅炉热功率(kW)1×24
P_el电解槽输入电功率(kW)1×24
P_fc燃料电池输出电功率(kW)1×24
P_buy / P_sell购电/售电功率(kW)1×24
S_h2储氢罐能量状态(kWh)1×25
约束名称数学表达式作用
电功率平衡P_pv + P_wt + P_chp + P_fc + P_buy = P_load + P_el + P_sell保证发用电实时平衡
热功率平衡H_chp + H_fc + P_boiler = H_load保证热负荷被满足
氢储能动态S_h2(t+1) = S_h2(t) + eta_el·P_el·dt - P_fc/eta_fc·dt刻画储氢量变化
设备出力上下限各设备功率在区间内反映设备物理边界
储氢量上下限0 ≤ S_h2 ≤ Cap_h2防止储氢罐过充放
初始末状态S_h2(1) = S_h2(T+1)保证日循环

这些约束里最容易出错的是电功率平衡等式。注意P_el是负荷侧消耗,应该在等号右侧;P_sell也是输出侧(卖给电网),同样在右侧。很多人第一次建模把P_el加到左边,结果有功平衡永远不满足,求解器直接报不可行。

3.3 为什么工程上偏爱“线性模型”

熟悉优化的朋友可能会问:燃料电池效率、CHP热电比都不是严格常数,为什么不建非线性模型?

原因很实际:线性规划(LP)和混合整数线性规划(MILP)求解速度快、全局收敛、商业求解器成熟,适合工程落地。非线性规划(NLP)用fmincon这类工具,对初值敏感,容易陷入局部最优,而且一旦模型规模变大,求解时间不可控。

工程上通常把效率曲线、热电比做分段线性化处理,或者直接取典型工况下的常数值。说句实话,对一个日前调度问题,精度差异完全在可接受范围内,但求解稳定性的提升是巨大的。模型跑得通、跑得稳,比模型精确到小数点后三位重要得多。

4. Matlab实现:从数学模型到可运行代码

4.1 工具链选型与版本说明

Matlab里做优化调度有几种常见组合:

工具链适用场景说明
MATLAB优化工具箱 + linprog纯线性LP模型自带,无需第三方,适合基础算例
MATLAB优化工具箱 + intlinprog带0-1变量的MILP模型自带,可处理启停等逻辑约束
YALMIP + Gurobi/CPLEX大中型LP/MILP,扩展性强学术免费,求解效率高,推荐
fmincon / 遗传算法非线性模型初值敏感,慎用于大模型

我的建议是直接用YALMIP建模,求解器先用LinProg跑通,再按需切换到Gurobi。YALMIP的语法和数学公式几乎一一对应,写起来不容易出错,而且后续加二进制变量、二次目标都不用大改结构。版本方面,我测试用的是R2023a,R2019b以上都没问题,核心是装了Optimization Toolbox,第三方求解器按需配置。

4.2 完整代码骨架

下面这段代码是完整可运行的最小骨架,24时段日前调度,LP模型,目标为日运行成本最小:

%% 数据定义 T = 24; dt = 1; % 时段长度,小时 P_load = [40 35 30 28 30 35 45 58 65 68 70 72 68 65 66 67 70 75 72 65 58 52 46 42]; H_load = [50 45 42 40 38 40 50 55 45 40 38 35 36 35 34 35 40 50 55 45 40 38 40 50]; P_pv = [0 0 0 0 0 0 2 10 20 28 32 34 33 30 24 15 8 2 0 0 0 0 0 0]; P_wt = [25 24 22 20 18 16 15 14 16 18 20 21 20 19 18 16 15 17 20 22 23 24 25 26]; price_buy = 0.8 * ones(1, T); price_buy(8:11) = 1.2; price_buy(18:21) = 1.1; % 分时电价 price_sell = 0.4 * ones(1, T); % 上网电价 %% 设备参数 P_chp_max = 50; P_chp_min = 5; eta_chp = 0.35; c_ht = 1.5; P_el_max = 20; P_el_min = 0; eta_el = 0.65; P_fc_max = 30; P_fc_min = 0; eta_fc = 0.5; R_hp = 1.0; P_boiler_max = 40; eta_boiler = 0.9; P_grid_max = 50; c_gas = 0.35; c_om = 0.02; Cap_h2 = 150; S_h2_0 = 75; %% 决策变量 P_chp = sdpvar(1, T); P_boiler = sdpvar(1, T); P_el = sdpvar(1, T); P_fc = sdpvar(1, T); P_buy = sdpvar(1, T); P_sell = sdpvar(1, T); S_h2 = sdpvar(1, T+1); H_fc = R_hp * P_fc; H_chp = c_ht * P_chp; %% 约束 C = []; % 电功率平衡:发电+购电 = 负荷+电解槽+售电 C = [C, P_pv + P_wt + P_chp + P_fc + P_buy == P_load + P_el + P_sell]; % 热功率平衡:CHP余热+燃料电池余热+锅炉热 = 热负荷 C = [C, H_chp + H_fc + P_boiler == H_load]; % 氢储能动态约束 C = [C, S_h2(2:T+1) == S_h2(1:T) + dt * (eta_el * P_el - P_fc / eta_fc)]; C = [C, 0 <= S_h2 <= Cap_h2]; C = [C, S_h2(1) == S_h2_0]; C = [C, S_h2(T+1) == S_h2_0]; % 设备出力上下限 C = [C, P_chp_min <= P_chp <= P_chp_max]; C = [C, P_el_min <= P_el <= P_el_max]; C = [C, P_fc_min <= P_fc <= P_fc_max]; C = [C, 0 <= P_boiler <= P_boiler_max]; C = [C, 0 <= P_buy <= P_grid_max]; C = [C, 0 <= P_sell <= P_grid_max]; %% 目标函数:燃料成本 + 购电成本 + 运维成本 - 售电收入 fuel_chp = c_gas * P_chp / eta_chp * dt; fuel_boiler = c_gas * P_boiler / eta_boiler * dt; om_cost = c_om * (P_chp + P_fc + P_el + P_boiler) * dt; objective = sum(fuel_chp + fuel_boiler + om_cost ... + price_buy .* P_buy * dt - price_sell .* P_sell * dt); %% 求解 ops = sdpsettings('solver', 'linprog', 'verbose', 0); optimize(C, objective, ops); %% 结果提取 P_chp_opt = value(P_chp); P_boiler_opt = value(P_boiler); P_el_opt = value(P_el); P_fc_opt = value(P_fc); P_buy_opt = value(P_buy); P_sell_opt = value(P_sell); S_h2_opt = value(S_h2);

代码结构不复杂,核心逻辑和第二节的数学公式一一对应。跑通后可以直接用figure; plot看各设备出力曲线,检查平衡关系是否合理。我建议把电功率平衡的残差也打印出来,很多问题一眼就能看出来。

4.3 从LP扩展到MILP:接入0-1变量的思路

上面的模型是纯LP,因为所有约束都是线性的、决策变量连续。但实际工程中有些逻辑必须用0-1变量表达,比如机组启停状态、购售电互斥、最小开停机时间。

举个例子,如果你严格禁止购电和售电同时发生,可以引入二进制变量y(t)

y = binvar(1, T); C = [C, P_buy <= P_grid_max * y]; C = [C, P_sell <= P_grid_max * (1 - y)];

当y=1时允许购电,售电功率被强制为0;反之亦然。模型从LP变成MILP,求解器切换成intlinprog或Gurobi即可:

ops = sdpsettings('solver', 'gurobi', 'verbose', 0);

从纯LP到MILP,代码改动极小,但能表达的工程约束丰富很多。建议先把LP版本跑通、结果调合理,再逐步加0-1变量,这样排查问题时能快速定位是哪一类约束出了问题。

5. 典型算例仿真与调度结果解读

5.1 算例参数与场景设置

我按北方某园区微电网的典型日数据搭了一个算例,设备参数如下表:

设备参数数值
CHP机组功率范围 / 发电效率 / 热电比5-50 kW / 0.35 / 1.5
电解槽功率范围 / 电转氢效率0-20 kW / 0.65
燃料电池功率范围 / 发电效率 / 热电比0-30 kW / 0.50 / 1.0
储氢罐容量 / 初始储氢量150 kWh / 75 kWh
燃气锅炉功率上限 / 热效率40 kW / 0.90
电网交互购售电功率上限50 kW

电负荷峰值约75kW,出现在傍晚;热负荷峰值55kW,出现在夜间8点;光伏中午峰值34kW,风电夜间出力较高。分时电价设计了峰平谷三段。

这套参数运行下来,目标函数值就是一个具体的日运行成本数值。你拿去跑自己的数据时,重点看调度曲线的相对关系,不要纠结绝对值。

5.2 调度曲线里能读到什么

优化结果跑出来后,我一般先看三个东西:储能SOC曲线、燃料电池出力和购电曲线。

典型结果会呈现这样的特征:夜间风电出力大、电价低,CHP机组维持较低出力满足基础热负荷,多余风电进入电解槽制氢,储氢量缓慢上升。上午电负荷升高、电价进入峰值段,燃料电池开始放电,CHP机组提升出力,购电明显减少。中午光伏大发,如果发电量超过负荷和电解槽吸收能力,多余电力会卖给电网。傍晚热负荷和电负荷双高、电价二次上涨,CHP和燃料电池同时出力,储氢量快速下降。

氢储能的调度规律一句话总结:低谷低价时段制氢蓄能,高峰高价时段放能供热。这就是时间错配的价值。对比不装氢储能的基准方案,日运行成本会下降一块,幅度取决于峰谷价差、风电消纳量和设备容量配比。

5.3 参数敏感性:峰谷价差、储氢容量、热电比

模型跑通之后,强烈建议做几组参数敏感性分析,这是写论文和做项目汇报最容易出效果的环节。

峰谷价差增大时,氢储能的套利空间变大,燃料电池的放电时段会明显增多,购电集中在低谷段,运行成本下降。储氢容量从100kWh增加到200kWh时,储能系统有了更大调节空间,但容量继续往上增长,边际收益会递减,因为制氢的电量总归有限。CHP热电比提高意味着同样的发电量能带出更多热,热平衡中燃气锅炉的出力会降低,天然气消耗减少,但电侧灵活性变差,极端情况下可能出现“为了供热而被迫发电、造成多余电力”的尴尬。

这些分析不需要额外写多少代码,改一个参数重新求解就行。但通过对比规律,你能对整套系统的运行特性有更直观的理解,这也是优化调度项目里最有价值的部分。

6. 常见问题与调试技巧实录

6.1 “Infeasible problem”的快速定位

YALMIP报Infeasible problem是最常见的坑。我自己的排查顺序是固定的:先把储能动态约束和初末状态约束注释掉,看基础电热平衡是否可行;不行就从电平衡开始逐个删等式,找到第一个导致不可行的约束。

单位不统一是隐藏大坑。有人在参数里功率用kW、储氢容量用MWh,结果差三个数量级,约束直接无解。我建议所有数据统一用kW和kWh,电价用元/kWh,时段长度用小时,全程一个单位体系,不要混用。

如果模型带0-1变量,还要检查是否因为互斥约束写错导致可行域为空。比如购售电互斥用了同一个二进制变量但逻辑取反没写对,就会出现某时段只能买不能卖,而系统那段时间恰恰需要卖电的尴尬情况。

6.2 调度曲线抖振、频繁启停与购售电同时出现

结果曲线出现相邻时段功率大幅波动,通常是模型里缺少爬坡约束。真实设备出力不能瞬变,但LP模型不care这个,它只要目标最优,哪怕前一小时满发、后一小时停机也无所谓。解决方法是加爬坡约束:

C = [C, -R_chp <= diff(P_chp) <= R_chp];

R_chp是CHP机组的爬坡速率。另一种情况是购电和售电同时出现在最优解里,这多半是价格设置不合理或者没加互斥约束,参照4.3节的0-1变量处理。

还有一种反直觉的情况:燃料电池在某个时段明明电价不高却还是出力。这时候要回头查热平衡,很可能是热负荷恰好高、燃料电池的余热比燃气锅炉供热更划算。单纯从电侧看问题就会觉得“不合理”,但放到热电联供的整体视角,这个调度决策恰恰是合理的。

6.3 求解时间与工程效率

24时段LP模型linprog秒解,没什么好担心的。但如果扩展到96时段、加上多台机组和大量0-1变量,求解时间就会明显上升。几个实用建议:

  • 用Gurobi或CPLEX替代matlab自带求解器,效率提升非常明显;
  • 设置MIPGap,比如sdpsettings('gurobi.MIPGap', 0.01),允许1%的次优误差换取求解速度;
  • 在循环里跑多次优化时,把建模部分封装成函数,避免重复定义变量导致的yalmip内存堆积;
  • 大数据量时改用sparse矩阵和结构体组织参数,减少内存占用。

最后说个我自己的使用体会。这套模型的价值不在代码本身,而在于把氢储能放到热电联供体系里一起调度的“全局视角”。单纯做电储能调度,两条平衡线基本解耦,难度低一个量级;但把电解槽、燃料电池和CHP放在一块,电、热、氢相互牵制,才是综合能源微电网现实中真正要面对的问题。我建议刚接触这个方向的朋友别急着加复杂算法,先把确定性LP模型跑通、曲线读懂,再去扩展随机优化或强化学习,地基会扎实得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询