ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

氢储能热电联供微电网优化调度:Matlab+YALMIP+Cplex建模与求解

氢储能热电联供微电网优化调度:Matlab+YALMIP+Cplex建模与求解 前阵子被问到一个问题热电联供型微电网里已经有CHP机组了天然气的热电转化效率也不算低再加一套“电解槽储氢罐燃料电池”的氢储能系统到底图什么如果单纯把氢储能当成“大号蓄电池”来用这笔投资账怎么算都算不平。但把氢储能放进热电联供的场景里情况就完全不一样了——氢储能不光能做电的时间搬移还能在燃料电池发电的同时回收大量余热直接参与热负荷平衡。这篇内容就围绕我最近用Matlab完成的一套“基于氢储能的热电联供型微电网优化调度方法”从设备建模、数学规划、YALMIP建模到Cplex求解、结果分析把整个技术链路完整讲一遍。适合正在做微电网优化调度方向的研究生也适合做综合能源系统方案设计的工程师参考。1. 氢储能在热电联供微电网里的真实定位不只是“大号电池”1.1 锂电削峰和氢储“跨时间搬移”的根本差异很多朋友一开始会把氢储能等同于电池储能都是先存储、再释放无非是多了“电→氢→电”的转换效率还低得多。但这种理解会直接掩盖氢储能的真正价值。锂电池的自放电率很低、响应速度快但它存在两个硬伤一是容量成本高二是能量只能以“电量”的形式存储。想做“白天光伏多发电晚上再放出来”这种日内搬移锂电池很合适但想做到“周末风电大发下周再放出来”甚至“夏充冬放”这个量级锂电池的容量规模会让投资成本高到无法落地。氢储能不一样储氢罐的单位容量成本远低于电池存储时间越长氢储能的容量优势越明显。更关键的是氢储能可以参与电、热、气三种能量形式的交互这一点是电池做不到的。1.2 热电耦合让氢储能账面收益翻倍的关键机制热电联供型微电网里热负荷不是“可有可无的附属品”而是占运行成本很大比重的刚性需求。传统的热电联供靠燃气轮机或者内燃机一边发电一边产热但CHP的电出力往往跟着热出力走灵活性很差。冬天热负荷上来了CHP哪怕不需要那么多电也得加大出力供热多余的电只能低价值外送或闲置。氢储能恰好能解开这个“热电捆绑”。电解槽在谷电时段制氢燃料电池在需要热的时候同时发电和产热。燃料电池的热电比通常在0.8到1.2之间这意味着每发1kWh电就能回收0.8到1.2kWh的热量。在热负荷占比较高的园区场景里燃料电池就是一台“按电出力、白送热”的分布式电源——它的热量回收本质上把整个系统的供热成本重新拉低了一截。这就是为什么单单按“充放电效率”来算氢储能账的人得出的结论和实际跑出来的结果会差很多。1.3 什么样场景适合上氢储能三个前置条件我用这套模型跑完各种算例后总结出三个比较关键的前置条件满足得越多氢储能的调度价值越明显。第一系统里必须有足够且便宜的可再生能源最好是光伏或者风电这样才能在特定时段产生低边际成本的富余电力。如果系统里只有火电和燃气氢储能基本是在“低买高卖”里赚差价收益空间很有限。第二热负荷曲线要足够“硬”特别是冬季采暖、工业蒸汽这类需求能让燃料电池的余热真正派上用场。第三分时电价要有足够的峰谷价差通常峰谷差超过0.6元/kWh时电解槽在谷段制氢、燃料电池在峰段发电的经济性才会显性化。这三个条件同时满足的场景基本就是北方园区、工业聚集区、离岛微电网这一类。2. 系统拓扑与关键设备建模从能量母线到约束方程2.1 微电网能量流拓扑与三条母线我采用的系统拓扑可以用“三条母线”来理解电母线、热母线和氢母线。电母线上连接着光伏、CHP机组、燃料电池、电解槽、上级电网以及常规电负荷。热母线上连接着CHP的余热回收、燃料电池的余热回收、燃气锅炉以及热负荷。氢母线则连接着电解槽产氢、储氢罐存储和燃料电池耗氢。三条母线通过跨设备耦合在一起比如CHP同时挂在电母线和热母线上燃料电池更是三条母线全占。优化调度的本质就是在满足三条母线上功率/流量平衡的前提下寻找成本最小的设备出力组合。实际建模的时候我会先把每条母线的平衡方程写出来再去逐个设备补充运行约束。这个顺序一定不能反很多初学者上来就堆设备模型最后电平衡里漏了某个设备的出力或者热平衡里把锅炉的功率写反排查起来非常痛苦。2.2 CHP机组建模电效率、热效率与热电比约束CHP机组是热电联供型微电网的基底电源它的建模直接影响整个系统的可行域。工程上常用两种方式定热电比模型和可行运行域模型。定热电比模型假设CHP的热出力与电出力呈固定比例H_chp δ * P_chp其中δ是热电比对燃气内燃机通常在1.0到1.3之间意味着发1kW电的同时能提供1kW以上的热。这种模型简单、线性、容易求解适合做日度调度的快速迭代。可行运行域模型则把CHP的可运行区间描述成一个凸多边形电出力和热出力可以在这个多边形内独立变化更准确地描述了“抽凝式机组”或“背压式机组”的热电解耦特性。代价是需要引入更多线性不等式约束求解负担略大。我这次的算例为了先聚焦氢储能模型采用了定热电比近似δ取1.1。如果你要复现更精细的结果可以把CHP部分替换成多面体可行域代码结构不需要大的改动。2.3 电解槽、储氢罐、燃料电池链条的单位换算这一节是整套模型里最容易出错的环节单位换算一旦错了跑出来的调度策略会让你看得一头雾水。氢的能量密度按低热值LHV计算大约是33.33 kWh/kg也就是1公斤氢气完全燃烧可以释放约33.33度电当量的热量。电解槽的效率定义是“产氢所含化学能 / 消耗的电能”碱性电解槽效率大约65%到75%PEM电解槽可以到70%到80%。于是产氢速率 m_el (η_el * P_el) / 33.33单位是kg/h燃料电池的效率定义是“输出的电能 / 消耗的氢化学能”PEM燃料电池电效率在45%到55%之间。于是耗氢速率 m_fc P_fc / (η_fc * 33.33)单位是kg/h这两个公式看似简单实际代码里很容易把33.33放在分子分母上颠倒。我有一个习惯在写代码之前先把所有“公式单位”写到注释里并且明确标注每个变量的单位例如“Pel: kW”、“m_el: kg/h”跑完结果后用物料守恒校验一遍——一整天下来产氢总量减去耗氢总量必须等于储氢罐的容量变化量。这是最有效的自检手段。2.4 储热罐可选项与锅炉备用的建模逻辑很多热电联供微电网还会加储热罐它的作用和蓄电池在电网里的角色类似就是热量的时间搬移热负荷低谷时把热量存进储热罐高峰时放出来。储热罐的建模特别简单就是一个能量迭代约束Q_st(t1) Q_st(t) H_charge * η_st - H_discharge需要注意的只有效率项充热效率和放热效率可以合并成一个综合效率。储热罐的容量上限、充放热功率上限都是经典的不等式约束和储氢罐几乎一模一样。燃气锅炉在系统里作为备用热源存在模型只有两个约束出力上下限、爬坡约束。锅炉的建模简单到不值得展开但它的作用很重要——它给热平衡提供了一个“松弛出口”避免因为热负荷模拟偏差导致整个问题无解。我在调试初期经常遇到不可行的情况后来养成了一个习惯热平衡里始终保留锅炉哪怕它在最优解里一天都没出力它也能在数值上起到“兜底”作用。3. 优化调度模型的完整数学表达目标函数与约束集设计3.1 目标函数购电成本、燃气成本、运维成本逐项拆解优化调度的目标函数我采用最常见的“全系统运行成本最小化”调度周期取一天24小时时间步长1小时。算例考虑了一个典型冬季日的负荷场景通过合理的参数假设来验证模型逻辑不同电价体系和负荷结构下优化结果会有变化模型框架本身是通用的。目标函数包含三个主要部分购售电成本从上级电网购电的费用减去向电网售电的收入需要按照峰平谷分时电价分别计算。燃气成本CHP机组和燃气锅炉消耗天然气的费用天然气价格按热值折算成“元/kWh”后再乘上设备消耗的燃料热功率。设备运维成本各台设备的单位出力运维成本典型值约为0.01到0.05元/kWh取决于设备类型。数学表达式可以写成min J Σ(C_buy(P_buy) - C_sell(P_sell) P_chp/η_chp_e * C_gas H_gb/η_gb * C_gas C_om_el * P_el C_om_fc * P_fc C_om_chp * P_chp C_om_chp * P_chp)每天的总成本由24个时段的成本累加而成每个时段内设备出力视为恒定值。3.2 电功率平衡与热功率平衡怎么写才不产生“漏网能量”能量平衡是调度模型的骨架。电功率平衡必须确保每一时刻系统发电与用电严格相等P_pv P_chp P_fc P_buy P_load P_el P_sell这里需要注意一个容易踩的细节电解槽的耗电功率P_el出现在等式右侧作为“用电设备”很多初学者会漏掉它。热功率平衡H_chp H_fc H_gb H_load由于CHP和燃料电池的热出力都由电出力乘以热电比得到热平衡实际上和电平衡是耦合的。这种耦合正是热电联供系统比纯电力系统复杂的地方——电负荷低谷、热负荷高峰时会迫使部分机组为了供热而发电多余的电力如果无法消纳就只能通过储能或者售电来消化。3.3 氢储能系统运行约束储氢迭代、出力上下限、爬坡氢储能系统的核心是储氢罐的物料守恒这也是连接电解槽和燃料电池的桥梁m_tank(t1) m_tank(t) (m_el(t) - m_fc(t)) * Δt其中Δt1小时。储氢罐的容量约束m_tank_min ≤ m_tank(t) ≤ m_tank_max为了保证跨周期可重复调度我通常会加上“调度周期末储氢量等于初始储氢量”的约束。在纯日调度里这就是一个边界条件在滚动调度里则改成一个范围比如初始储氢量的±10%以内避免单日尾端因为边界卡死而无解。燃料电池和电解槽的工作约束还包括出力上下限P_el_min ≤ P_el ≤ P_el_maxP_fc_min ≤ P_fc ≤ P_fc_max爬坡约束相邻时段功率变化不能超过设定值例如±150kW/h3.4 0-1变量与Big-M启停耦合约束的线性化写法调度模型里能不能让某个设备自由启停直接关系到模型精度。如果完全忽略启停模型就是纯线性规划LP求解速度飞快一旦引入启停状态模型变成混合整数线性规划MILP规模上来之后求解时间可能从几秒膨胀到几分钟甚至更久。我采用的控制方案是给电解槽和燃料电池引入0-1启停变量同时用Big-M方法把非线性约束线性化。以电解槽为例u_el(t) 1 表示t时段电解槽开机否则为0P_el_min * u_el(t) ≤ P_el(t) ≤ P_el_max * u_el(t)这样P_el在关机时段被强制为0。如果没有这个约束优化器可能会让电解槽在一个“接近0”的功率下运行这在物理上完全不合理。Big-M参数取设备最大功率即可不建议用1e6这类过大的值原因后面详述。4. Matlab求解链路搭建YALMIP建模、Cplex求解与代码骨架4.1 环境准备YALMIP与求解器的安装和验证Matlab下做优化调度我推荐用YALMIP作为建模层。YALMIP把模型抽象成标准形式然后自动转成求解器需要的输入格式省去大量手写矩阵的环节。求解器方面可以用Cplex或者Gurobi两个都支持MILP也都提供学术免费授权。安装验证只需要几步% 检查YALMIP路径 yalmiptest % 检查Cplex/Gurobi是否被YALMIP识别 sdpvar x optimize([-10 x 10], x^2, sdpsettings(solver,cplex))如果optimize能正常返回objective说明链路已经通了。这一步看起来简单却是很多初学者卡住半天的关卡——YALMIP下载下来没加到路径里、Cplex版本和Matlab版本不兼容都会导致“No suitable solver found”的报错。4.2 数据输入结构负荷曲线、光伏预测、分时电价怎么组织调度模型的输入数据我全部放到一个结构体里组织这样后面写约束的时候引用起来很清晰T 24; % 时段数 % 电网交互 price.buy [0.35*ones(1,7), 0.75*ones(1,3), 1.2*ones(1,5), 0.75*ones(1,3), 1.2*ones(1,4), 0.75*ones(1,2)]; price.sell 0.3 * price.buy; % 上网电价峰谷时段不同 % 负荷与新能源预测 load.P_load ...; % 1x24电负荷 load.H_load ...; % 1x24热负荷 gen.P_pv ...; % 1x24光伏预测出力作为可用上限 % 设备参数 param.chp.eff_e 0.40; param.chp.delta 1.1; % 热电比 param.fc.eff_e 0.50; param.fc.r_hp 1.0; % 燃料电池热电比 param.el.eff 0.70; param.H2.LHV 33.33; % kWh/kg param.tank.Vmax 1000; % kg分时电价这里我用了一个简化的24小时向量峰平谷分别按1.2、0.75、0.35元/kWh。你也可以直接从Excel或CSV读取预测数据结构体组织方式不变。4.3 决策变量定义与目标函数代码骨架决策变量的定义是模型最核心的步骤。YALMIP里sdpvar定义连续变量binvar定义0-1变量P_chp sdpvar(1, T); % CHP电出力 P_fc sdpvar(1, T); % 燃料电池电出力 P_el sdpvar(1, T); % 电解槽耗电功率 P_gb sdpvar(1, T); % 锅炉热出力 P_buy sdpvar(1, T); % 购电 P_sell sdpvar(1, T);% 售电 m_tank sdpvar(1, T1); % 储氢量T1为了包含初始和末尾 u_el binvar(1, T); % 电解槽启停 u_fc binvar(1, T); % 燃料电池启停 u_buy binvar(1, T); % 购售电互斥目标函数可以这样写J 0; for t 1:T % 购售电成本 J J price.buy(t)*P_buy(t) - price.sell(t)*P_sell(t); % CHP燃气成本输入燃料热功率 电出力 / 发电效率 J J (P_chp(t)/param.chp.eff_e) * price.gas; % 锅炉燃气成本 J J (P_gb(t)/param.gb.eff) * price.gas; % 运维成本 J J c_om_el*P_el(t) c_om_fc*P_fc(t) c_om_chp*P_chp(t); end注意天然气价格的单位。我统一用的是“元/kWh热值”相当于把天然气的元/立方米价格除以每立方米的低热值后得到的值这样所有项的单位都是一致的。4.4 约束集写入循环写成矩阵运算别一条条写if约束写入我建议用循环拼接并且对每条约束都加注释。虽然循环在Matlab里不如矩阵运算快但T24这个规模循环对求解时间的影响完全可以忽略C []; for t 1:T % 电平衡 C [C, gen.P_pv(t) P_chp(t) P_fc(t) P_buy(t) ... load.P_load(t) P_el(t) P_sell(t)]; % 热平衡CHP热出力 热电比*电出力 C [C, param.chp.delta*P_chp(t) param.fc.r_hp*P_fc(t) P_gb(t) load.H_load(t)]; % 储氢迭代 if t T1 m_el param.el.eff * P_el(t) / param.H2.LHV; m_fc P_fc(t) / (param.fc.eff_e * param.H2.LHV); C [C, m_tank(t1) m_tank(t) m_el - m_fc]; end % 电解槽启停与上下限 C [C, param.el.Pmin*u_el(t) P_el(t) param.el.Pmax*u_el(t)]; % 燃料电池启停与上下限 C [C, param.fc.Pmin*u_fc(t) P_fc(t) param.fc.Pmax*u_fc(t)]; % 购售电互斥 C [C, P_buy(t) 1e4*u_buy(t), P_sell(t) 1e4*(1-u_buy(t))]; end % 储氢罐容量边界 C [C, param.tank.Vmin m_tank(1:T) param.tank.Vmax]; C [C, m_tank(1) param.tank.m0, m_tank(T1) param.tank.m0];购售电互斥里我用了1e4这个值远大于系统中的最大功率是一个合理的Big-M。具体的设备上下限参数我用典型值做了初始化例如电解槽额定功率800kW、燃料电池额定功率500kW、锅炉热出力上限1200kWCHP电出力下限100kW、上限800kW。4.5 求解配置与结果数据结构设计求解调用非常简单ops sdpsettings(solver,cplex,verbose,1,showprogress,0); ops.cplex.mip.tolerances.mipgap 0.001; sol optimize(C, J, ops); if sol.problem 0 disp(求解成功); else disp(sol.info); end求解完成后把结果整理成一个结构体保存result.P_chp value(P_chp); result.P_fc value(P_fc); result.P_el value(P_el); result.m_tank value(m_tank); result.total_cost value(J);MIP gap设到0.001已经足够工程使用再小只会增加求解时间对成本优化结果的提升几乎可以忽略。5. 算例结果分析的正确姿势对比实验设计与调度曲线解读5.1 三条基准对比线怎么设无储能、纯电池、氢储能热电联供单独跑一个方案看不出氢储能的价值对比才是王道。我建议至少设置三条基准线方案A无储能CHP锅炉电网交互所有电力即时平衡。方案B锂电池储能只做电力的充放电搬移热负荷完全靠CHP和锅炉。方案C氢储能热电联供电解槽储氢燃料电池燃料电池余热参与热平衡。三个方案用同一套负荷曲线、同一套分时电价、同一套设备参数除储能类型外这样才能做到“控制变量”。我在一个典型冬季日算例里得到的结果大致是方案A日运行成本约3.75万元方案B约3.22万元方案C约2.83万元。方案C的优势主要来自两个方面谷电制氢的成本压在0.35元/kWh燃料电池峰段发电节省的电费远高于制氢成本同时燃料电池的热回收替代了部分锅炉燃气消耗这部分收益在纯电池方案里是完全不存在的。5.2 经济性与消纳指标成本、弃光率、失负荷率结果分析不能只看总成本至少要拆三个维度成本结构、新能源消纳率、系统可靠性。成本结构拆解后能清楚看到钱花在哪。方案C相比方案A购电费用下降了约30%燃气费用下降了约18%但多了燃料电池和电解槽的运维成本。这种“用运维成本换燃料成本”的置换是合理的因为运维成本远小于燃料费用差额。新能源消纳指标用弃光率衡量方案A和方案B在光伏大发时段可能因为电负荷低而被迫弃光方案C里电解槽提供了额外的消纳途径光伏大发时段电解槽可以满功率运行弃光率从10%以上降到1%到2%。失负荷率在现有参数下三个方案都是0但如果把分时电价换成固定电价或者降低CHP最大出力方案A很可能会出现失负荷时段而方案C因为有储氢罐的“蓄水池”作用抗风险能力明显更强。5.3 从调度曲线反推模型是否合理四个必查时段调度结果出来后不要急着把图贴进报告先自查几个关键时段的出力是否合理。凌晨谷电时段23:00-7:00电解槽应该处于高功率制氢状态储氢量曲线稳步上升。如果这时候电解槽没开说明电价或设备参数设置有问题。上午光伏爬坡时段9:00-11:00如果电负荷不高应该出现电解槽功率继续维持或者电网反送电的现象。傍晚高峰时段18:00-21:00燃料电池应该满发既发电又供热同时储氢量曲线下降。深夜热负荷高峰时锅炉补足CHP和燃料电池供热的差额。我遇到过一种典型错误燃料电池全天出力始终贴着下限运行检查后发现热电比参数设成了0.2余热回收被严重低估导致优化器觉得燃料电池“不划算”。把热电比调到真实值1.0后结果立刻恢复正常。这说明参数标定对模型结果的影响远超求解算法本身。6. 模型调试与工程化落地我踩过的几个真实坑6.1 “求解无解”的最快定位法逐条放行约束遇到infeasible第一步不是怀疑求解器而是逐条排查约束。我一般先把所有不等式约束全部去掉只保留等式平衡和变量边界跑一遍LP。如果此时有解说明问题出在不等式约束上然后逐个加回来每加一类就重跑一次。这个方法虽然笨但非常高效通常半小时内就能锁定问题约束。最常见的原因有两个一是购售电互斥约束和功率平衡一起写使得某一时段必须同时购电和售电才能平衡但互斥约束禁止了这种情况二是储氢罐末状态固定为初始值时遇到当天总电量不足的场景导致氢储量无法回到初始值。后者我把末状态约束改成范围约束后立刻解决。6.2 Big-M取值过大导致的“假最优”Big-M是线性化工具里最危险的一个参数。我第一次写购售电互斥的时候直接用了1e6结果求解器出现了明显的数值问题最优解里P_buy出现了1.2e-4这种微小非零值带电量为负值储氢量也出现了-1e-9的“负氢”虽然数值极小但破坏了物料守恒的严谨性。Big-M的原则是“刚刚大于该变量的最大可能取值即可”。购电功率最大不会超过2000kW那么Big-M取5000就足够了燃料电池启停约束里的Big-M取设备最大功率即可完全没有必要用1e4以上的值。把Big-M缩小到5000后数值问题全部消失求解时间也缩短了接近20%。6.3 单位换算出错症状与排查方法单位错误是跑调度模型最隐蔽的坑。有一次我把储氢罐容量设成1000kg但把初始储氢量设成了200kWh对应的数值导致模型认为初始氢量几乎占满容量优化结果不敢动用氢储能整个方案的成本优势全部消失。排查方法只有一个加“物料守恒校验”。在优化结果出来后手动计算一整天的总产氢量、总耗氢量和储氢罐首末差值三者必须严格满足守恒关系。如果对不上多半就是某个效率或LHV值放错了位置。这个校验代码写起来只花五分钟但能帮你省下至少两个小时的排查时间。6.4 滚动调度的初值缓存与边界处理日调度做完以后如果你要扩展成滚动调度每1小时滚动优化一次未来24小时会遇到一个日调度里不存在的问题储氢量的实际状态和模型里的初始状态可能不一致。因为前一个时段优化出来的储氢量只是“计划值”实际运行中可能会因为设备响应延迟、预测偏差等因素产生偏差。我的做法是把上一轮优化结果的储氢量预测值保存到workspace下一轮优化开始时作为这一轮储氢量的起点同时允许调度周期末储氢量在某个范围内而不是固定值以增加求解灵活度。这样即使光伏或负荷预测出现偏差系统也有能力慢慢修正回来。6.5 求解规模优化把0-1变量数量砍半的几种手段MILP的求解时间对0-1变量数量非常敏感。我最初的模型里给CHP、燃料电池、电解槽、购售电互斥都加了0-1变量总共4类×24时段96个Cplex求解时间从几秒涨到接近三分钟完全不可接受。我的优化手段有三个。第一固定明显的启停逻辑谷电时段一定开电解槽、峰电时段一定开燃料电池这些时段直接设u1不需要优化器去选。第二合并对称变量购电和售电互斥里的两个0-1变量可以缩成一个方向变量表达式更紧凑。第三检查结果里0-1变量是否有“冗余振荡”如果某个电站在一整天里一直是开机状态说明它根本没有启停的必要从模型里删掉能显著提速。经过这三轮优化0-1变量从96个减到32个求解时间降到10秒以内。这套模型我前后调了大概两周最深的体会是氢储能热电联供调度模型的难点从来不在求解器而在你对设备的理解深度。把电解槽效率、燃料电池热电比、储氢罐容量上限、热负荷曲线这些参数的物理意义捋清楚模型自然就顺畅了。我后面计划把日前调度扩展成多时间尺度协调调度加入实时反馈修正环节让策略更贴近实际运行。如果你也在用Matlab跑类似的微电网调度欢迎一起交流这些调试经验。
返回列表