ARTICLE DETAIL

资讯详情

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

并/离网风光互补制氢合成氨容量-调度优化及Cplex求解

并/离网风光互补制氢合成氨容量-调度优化及Cplex求解 1. 项目整体设计与核心思路1.1 这个优化问题到底在解决什么把风光互补制氢合成氨系统拆开看它本质上是一条由“发电侧—制氢侧—合成氨侧”三级构成的能量-物质耦合链路。风电、光伏出力是波动的电解槽和合成氨装置却希望平稳连续运行这中间的缓冲要靠储氢罐和电网并网模式下来承担。这个系统的复杂性在于设备规格选型容量决策和每一小时怎么分配功率调度决策互相咬合谁也不能脱离对方单独定。我们常说的“容量-调度优化”实际包含两类决策变量一类是长期投资决策比如风电场装多少兆瓦、光伏阵列多少兆瓦、电解槽额定功率多大、储氢罐有效容量多少方、合成氨装置设计负荷多大另一类是短期运行决策比如某个小时电解槽输入功率是多少、储氢罐是不是该充放、向电网买电还是卖电。传统做法是先估一个容量再去跑调度发现不行再回头调整容量来回迭代很痛苦。而把两层问题塞进同一个数学规划模型里同时求解就是在数学上一次性找到“最优的容量配置及其对应的最优运行方式”这个题目走的就是这条路而且明确用Cplex做混合整数规划求解Matlab负责建模、调用求解器、处理数据。这类问题适合谁来参考我的看法是做绿氢项目前期规划、园区能源系统设计、风光制氢一体化方案的人都能从中找到可迁移的框架。哪怕是没接触过Cplex的读者只要熟悉Matlab基本操作跟着这个思路也能把模型跑起来因为建模语言方面Matlab的YALMIP工具箱已经帮我们屏蔽了大量求解器底层的复杂度。1.2 并网与离网是两种完全不同的设计哲学标题里的“并/离网”不是我打错字指的是并网模式和离网模式两种工况它们的差异远不止“能不能从电网买电”这么简单而是直接决定了最优容量结构长什么样。并网模式下电网像一个无限大的缓冲池风电光伏出力大时可以把多余的电卖给电网出力不足时可以用电网的电补充电解槽和合成氨的用电缺口。这种模式下储氢罐不需要做得很大因为电网兜住了电侧的波动氢侧只需要应对合成氨装置的负荷波动即可但代价是电价的峰谷平差值决策了运行策略的走向。离网模式则完全不同。系统必须时刻自己保证电力平衡风光出力不足时要么降负荷、要么靠储氢缓冲维持合成氨不停产出力过多时要么制氢、要么弃风弃光。所以离网系统的最优容量往往会出现两个特征电解槽额定功率明显放大用来多消耗富余电力储氢罐容量也大幅增加因为氢的存储比电储能便宜且更适合长时间尺度调节。如果不做联合优化单凭经验拍脑袋很可能会把储氢罐配小了结果就是夜晚无光无风时合成氨装置被迫频繁降负荷设备利用率惨不忍睹。维度并网模式离网模式电力平衡电网参与调剂买电卖电自由完全自平衡必须设弃电/降载变量储氢罐角色缓冲合成氨负荷波动长周期能量转移核心容量显著增大电解槽容量可略小于风光极限出力通常要大于平均出力匹配峰值富余购售电价峰谷价差影响调度策略无电价信号只以成本最省为目标求解难度有购售电0-1变量规模中等需加弃电约束可行性验证更关键两种模式在同一套模型框架里切换时只需要增删电网交互约束、修改电力平衡等式就能完成这也是为什么这类项目普遍把并网和离网放在一起研究——对比出来的结论对业主选型最有参考价值。1.3 为什么选Cplex而不是别的求解器混合整数线性规划MILP领域可选的求解器不少但Cplex在Matlab环境下仍然是最常用的选择之一。核心原因有三点一是Cplex对大规模MIP的branch-and-cut框架成熟几万变量、几万约束的规模通常能稳定求解二是它在处理数值病态问题时相对宽容配合Matlab的稀疏矩阵接口不容易因为矩阵里出现极端系数而崩掉三是YALMIP工具箱对Cplex的支持很完整一条solvercplex的配置就能把建模和求解分开代码可读性也好。需要提一句的是像Gurobi现在也很流行性能上两家各有千秋。但如果项目环境里只有Matlab、又没有额外预算Cplex的学术版或企业版授权相对好获取社区案例也多资料好查。我的经验是如果你的模型已经写成YALMIP的sdpvar/binvar格式换求解器只是改一行配置的事所以学习阶段用Cplex踩过的坑后续换求解器也不用重写模型。2. 数学模型构建与约束细节2.1 目标函数投资成本和运行成本怎么放在一个式子里这个模型的目标函数标准写法是年化总成本最小化。设备投资费用不是一次性全算进第一年而是用资本回收因子CRF等额分摊到每一年这样投资和运行才具备可比性。CRF的计算式是CRF i*(1i)^n / ((1i)^n - 1)其中i是折现率n是设备寿命。例如折现率取6%风电寿命取20年CRF算出来大概是0.0872意味着每1万元的风电投资等效年成本是872元。光伏寿命可以取25年电解槽寿命取10~15年储氢罐取20年。不同寿命的设备要用各自的CRF不能图省事全用同一个数否则寿命短的电解槽投资会被严重低估。目标函数的具体形式可以写成min Σ_j CRF_j * C_j * X_j (投资年化) Σ_t (OM电 OM制氢 OM合成氨) (年运行维护) Σ_t (p_buy(t)*P_buy(t) - p_sell(t)*P_sell(t)) (购售电净支出)其中C_j是单位容量投资成本X_j是待优化的容量变量。这里要注意并网模式下P_sell会给目标函数贡献负成本模型自然倾向于在电价高峰时段卖电但如果电价政策不允许上网卖电就把P_sell上限定为0模型也能正确响应。离网模式下购售电变量不出现即可。2.2 设备建模的三组关键约束第一组是风电和光伏的出力上限约束。风电出力P_w(t)不能超过装机容量X_w对应的理论出力cap_w(t)*X_w光伏同理。这里的cap_w(t)、cap_pv(t)是单位装机的归一化出力曲线通常来自历史气象数据或仿真软件如PVsyst、WAsP的输出。模型可以决定切机弃电但不能超过物理上限。第二组是电解槽约束这是整个模型里最容易出问题的部分。电解槽不是简单地把电变成氢的“电阻丝”它有最小运行负载率。碱性电解槽一般要求负载不低于20%~40%否则产气纯度下降、甚至可能引发氢氧混合安全问题PEM电解槽负载下限低一些但设备贵得多。所以约束要写成两段P_elec_min * z_elec(t) ≤ P_elec(t) ≤ P_elec_max * z_elec(t)这里的z_elec(t)是0-1变量1表示开机。同时产氢量与输入功率的关系可以近似写成线性Q_h2(t) η_elec * P_elec(t) * k_h2其中k_h2是单位电耗对应的氢气产量系数。如果电解槽的电流效率随负荷变化明显可以分段线性化处理但一般容量规划阶段用常数效率就够了误差在可接受范围。第三组是储氢罐的动态约束。储氢罐的储氢量S(t)满足S(t) S(t-1) η_in * Q_in(t) - Q_out(t)/η_out 0 ≤ S(t) ≤ C_h2 0 ≤ Q_in(t) ≤ Q_in_max 0 ≤ Q_out(t) ≤ Q_out_max注意充放氢速率上限和储氢罐容量是两个不同维度的约束。很多人只写容量约束忘了速率约束结果模型规划出来的储氢罐在1小时内就充满或放空这在现实中是不可能的。速率约束的标定取决于压缩机功率和储罐进出气阀的流量一般按“容量/最短充放时长”来设置比如4小时充满对应Q_max C_h2/4。2.3 电力平衡和合成氨连续生产的“硬约束”电力平衡约束是整个模型的骨架。并网模式写为P_w(t) P_pv(t) P_buy(t) P_elec(t) P_sell(t) P_aux(t)其中P_aux(t)是合成氨装置、压缩机、冷却系统等辅助用电。离网模式则去掉P_buy和P_sell同时必须在左边加一个弃电量变量P_curtail(t)否则当风光出力大于电解槽上限时模型会直接不可行。这个小小的弃电变量正是离网系统模型能跑起来的保证。合成氨装置对氢气供应有连续性要求。哈伯-博施工艺一旦停车再重启需要很长的恢复时间和大量能耗所以工程上希望装置尽量连续运行。模型里常见的处理方式是限制单位时段进入合成氨反应器的氢气流量的波动幅度比如|Q_reactor(t) - Q_reactor(t-1)| ≤ ΔQ_reactor_max或者更简单地设一个最小产氨负荷率Q_reactor_min合成氨装置要么按最小负荷运行要么停机。因为氨合成是连续过程调度优化结果里基本都会让装置在全年大部分时间保持运行这本身就验证了储氢缓冲的必要性。3. Matlab调用Cplex的实现流程3.1 环境配置Cplex与Matlab的连接新手卡在第一步的情况很普遍。Cplex安装完后Matlab不会自动认识它需要手动把Cplex的Matlab接口路径加入环境中。以Cplex 12.10版本为例安装目录下通常有cplex/matlab文件夹在Matlab里执行addpath(C:\Program Files\IBM\ILOG\CPLEX_Studio1210\cplex\matlab) savepath如果用的是YALMIP还需要下载YALMIP工具箱并同样addpath然后在命令行里跑一次yalmiptest确认Cplex能被识别为可用求解器。配置许可证时如果系统提示找不到license常见做法是设置环境变量LM_LICENSE_FILE指向许可证文件路径或者用cplexlicsetup工具导入。这块没有太多技术含量但确实能卡掉一批初学者。3.2 用YALMIP建模的核心代码结构下面这段代码是我实践中的核心骨架完整度足够跑通一个简化版并网模型% 读取归一化出力曲线和电价序列T为时段数 % 决策变量 X_wind sdpvar(1,1); % 风电装机容量(MW) X_pv sdpvar(1,1); % 光伏装机容量(MW) X_elec sdpvar(1,1); % 电解槽额定功率(MW) X_h2 sdpvar(1,1); % 储氢罐容量(kg) P_elec sdpvar(T,1); % 电解槽输入功率 z_on binvar(T,1); % 电解槽开关 S_h2 sdpvar(T,1); % 储氢量 P_buy sdpvar(T,1); % 购电 P_sell sdpvar(T,1); % 售电 P_cur sdpvar(T,1); % 弃电(离网模式用) Constraints []; % 电力平衡(并网版) P_wind_avail cap_wind .* X_wind; P_pv_avail cap_pv .* X_pv; Constraints [Constraints, P_wind_avail P_pv_avail P_buy ... P_elec P_aux P_sell P_cur]; % 电解槽约束 Constraints [Constraints, P_elec_min*z_on P_elec X_elec*z_on]; Constraints [Constraints, 0 X_elec X_elec_ub]; % 储氢罐动态 Q_prod eta_elec * P_elec * k_h2; % 产氢速率 Constraints [Constraints, S_h2(2:T) S_h2(1:T-1) Q_prod(2:T) - Q_reactor(2:T)]; Constraints [Constraints, 0 S_h2 X_h2, S_h2(T) S_h2(1)]; % 目标函数年化投资 运维 购售电净成本 CRF [crf_wind, crf_pv, crf_elec, crf_h2]; Cost_inv CRF * [c_wind*X_wind c_pv*X_pv c_elec*X_elec c_h2*X_h2]; Cost_op om_fixed * (X_wind X_pv X_elec) ... om_var * sum(P_elec); Cost_grid sum(p_buy.*P_buy - p_sell.*P_sell); Objective Cost_inv Cost_op Cost_grid; options sdpsettings(solver,cplex,verbose,2,... cplex.mip.tolerances.mipgap,0.01); optimize(Constraints, Objective, options);代码里有几个容易忽略的细节。一是S_h2(T) S_h2(1)这个约束它强制一个调度周期的末储氢量不低于初值否则模型会把储氢罐里的氢“白嫖”掉结果不满足全年循环的物理事实。二是P_cur虽然在并网模型里设成0也能跑但保留它在数学上更稳健可以吸收掉由于数据不一致导致的微小不平衡。三是X_elec_ub要给个合理上界比如风光总容量的1.5倍避免求解器给出脱离实际的极端容量。3.3 求解参数调优和结果提取Cplex默认目标是证明最优性但大模型里死磕全局最优会等得让人怀疑人生。工程实践里我一般把mipgap设为0.01或0.005也就是容忍1%的次优偏差求解时间通常能缩短一个数量级。timelimit也要设置比如3600秒到点就输出当前最优解至少能作为方案对比的基准。结果提取同样有讲究value()函数拿到的变量是数值但要检查optimize返回的info.problem是否为0并且info.gap不要太大否则这个“最优解”可能还差得远。更稳妥的做法是把目标函数值、投资成本、运行成本分开打印和手工验算的结果对照确认单位的换算没有出错——我踩过最大的坑就是功率单位MW和kW混用导致投资成本怪异到离谱。4. 典型算例与结果分析4.1 算例参数和场景数据设定为了讲清楚模型输出长什么样我构造一个可供复现的小算例假设目标合成氨产量为每年1万吨合成氨装置连续运行平均每小时需要约0.65吨氨对应氢气消耗量约为0.115吨/小时。风光资源数据用某地春季典型工况的归一化出力曲线时间分辨率取1小时模拟周期先取168小时一周便于调试再扩展到8760小时做全年校核。电价采用分时电价峰时1.2元/kWh、平时0.75元/kWh、谷时0.4元/kWh。投资成本参数取风电6500元/kW、光伏4000元/kW、碱性电解槽1500元/kW、储氢罐按容量折算约8000元/吨氢、合成氨装置按年产万吨规模折算总投资约6500万元。折现率6%。4.2 并网模式下的最优容量和运行特征把上述参数喂给模型并网模式下得到的容量配置大概会是风电装机容量偏小、光伏容量适中电解槽额定功率刚好覆盖平均负荷需求并有一定余量储氢罐容量只够缓冲8~12小时的氢气用量。原因并不难理解——并网模式下电网提供了电力缓冲电解槽可以在电价低谷时段多制氢把氢气储存起来供高峰时段合成氨使用所以储氢罐承担的是“移谷填峰”的作用不需要覆盖连续多天的风光不足。调度结果曲线的特征也很典型白天光伏出力大、电价高系统倾向于把光伏电力自用制氢夜间尤其是谷电时段电解槽反而加大功率从电网买电制氢储氢罐白天放氢、夜间充氢形成日内的氢量循环。这套行为完全由目标函数里“购电成本最小化”驱动理性得毫无感情但工程上恰恰就是合理的。4.3 离网模式下的容量变化储氢罐变得巨大切到离网模式后系统行为会发生戏剧性变化。容量优化结果中储氢罐容量可能比并网模式大三到五倍电解槽额定功率也显著增大而光伏装机容量成为决定性变量——因为它决定了晴天的制氢量上限。风电的作用则是弥补夜间和阴天的出力缺口所以风光的配比往往和当地资源特性高度相关风速好的地区风电占比大辐照好的地区光伏占比大。离网模型在气象恶劣期连续阴雨天加静风的可行性完全依赖储氢罐的缓冲。模型如果在选定的时间范围内都没有迫使合成氨降负荷则说明储氢罐容量足够反之如果约束里放行了降负荷模型会权衡“更大储氢罐的投资增加”和“降负荷导致的减产损失”哪个更划算。从工程经验看离网系统如果把储氢罐容量配到并网方案的3倍以上、电解槽配到1.5倍左右往往就能在多数天气条件下维持合成氨装置连续运行且综合成本仍然低于加装大规模电化学储能的方案。4.4 敏感性分析参数一变最优解就变做优化项目如果只给一组结果那只能算完成了一半。我更推荐接着跑几组单因素敏感性分析。比如电解槽单位投资从1500元/kW降到800元/kW模型会自动增加电解槽容量因为便宜的大槽子可以多利用弃电产氢。电价谷段从0.4元/kWh降到0.2元/kWh并网模式下的储氢罐容量会明显增大电解槽夜间运行时间变长。这种敏感性分析在Matlab里实现非常简单写一个循环每次改动一个参数、重复调用optimize把目标值和容量变量存下来画图即可。它最大的价值是给业主谈判投资决策时提供依据——可以看出哪个参数对最终成本影响最大从而技术谈判时重点攻坚。5. 常见问题与排查经验实录5.1 求解时间过长到无法忍受这是最常被问的问题。8760小时全年仿真、并网模式、电解槽0-1变量加上可能的购售电0-1变量模型规模轻松超过十万变量直接求解确实很慢。我的常规手段是三板斧。第一板斧是缩短调度周期用聚类算法比如k-means把全年风光出力曲线聚成典型日每个典型日代表若干天数周期从8760小时降到几百小时甚至更低模型规模立刻缩水一个数量级。代价是牺牲日内时序细节但容量配置的准确度通常能保住90%以上。第二板斧是去掉不必要的整数变量。电解槽的启停0-1变量如果影响不大可以先松弛成连续变量试跑或者固定合成氨装置全年连续运行不减负荷这能大幅降低MIP求解难度。第三板斧是调cplex参数mipgap0.02、timelimit600再不行就用cplex.benders.strategy参数把问题按Benders分解的框架跑部分大规模问题会加速明显。顺序是先用“快而糙”跑通框架再逐步收紧精度而不是一上来就死磕全局最优。5.2 模型报“不可行”时的定位方法模型不可行原因排查是最耗精力的。我的经验是先做“松弛测试”给所有平衡约束加一个松弛变量目标函数里惩罚这个变量的平方或绝对值然后看哪些松弛量被激活了激活处就是冲突的源头。常见元凶是储氢罐约束初始储氢量、末储氢量和中间充放加起来不自洽。比如给一个很小的储氢罐容量、又强制末储氢量不低于初值模型找不到可行的运行轨迹。另一个常见元凶是电解槽最小负载率设得过高、又没有给它足够的电力供应离网模式下尤其容易发生。再一个就是S_h2(T) S_h2(1)这种循环约束在数据有微小不匹配时也会卡死模型可以先放开再局部调整。5.3 数值警告精度和尺度问题Cplex报出数值警告时不要无视。最常见的是约束系数跨度极大比如投资成本的单位是万元、储氢量的单位是kg两者相差好几个数量级导致矩阵条件数变差求解器精度下降甚至得出荒谬结果。解决办法是统一量纲功率全部用MW能量用MWh氢量用吨成本用万元。每一类约束的系数都控制在一个相对接近的范围求解器的数值稳定性就会好很多。还有一种技巧是把一些超大上界从模型里去掉改用-inf的大区间加一个合理上界减少数值负担。6. 常见报错速查与工程扩展建议6.1 报错速查表现象可能原因处理建议Cplex求解器找不到安装路径未addpath、license缺失执行yalmiptest重新配置LM_LICENSE_FILE模型不可行电力平衡没有弃电变量、储氢循环不自洽加P_cur松弛变量检查S_h2(T)S_h2(1)求解极慢整数变量过多、周期太长典型日缩减法、松弛整数变量、调大mipgap结果出现负容量或离群值上界约束缺失、量纲混用给所有容量变量设上下界统一kW/MW单位目标值异常低末储氢量被“白嫖”强制循环约束S_h2(T)S_h2(1)目标值异常高忽略了辅助用电或运维成本检查目标函数各项是否重复统计、单位是否一致6.2 从复现到项目落地的几点想法容量-调度的联合优化做完不代表项目方案可以直接施工。我个人的体会是模型给出的最优解更像是一个“靶心”工程落地时还需要用全年的逐时仿真去校核设备是否频繁启停、电解槽负载波动是否过大、极端天气下系统是否还能撑住。这部分建议把模型输出连接到一个离散事件仿真平台比如在Matlab里再写一个固定容量下的纯调度优化对比联合优化的运行成本差异。扩展方向上可以在模型里加入储能电池的选项做“电-氢-氨”多能耦合比选。也可以引入鲁棒优化用天气不确定性集替代单年时序数据这样决策出来的容量对极端情况更有韧性。还可以把合成氨的市场价格波动纳入目标函数从“成本最小”变成“利润最大”。每一步扩展都是在这个基础框架上加变量、加约束的活骨架没变。6.3 最后再分享我踩过的一个小坑做这类项目最容易栽跟头的地方是数据对齐。归一化出力曲线的下标、电价序列的下标、辅助用电序列的下标任何一个时间轴错位都会导致结果“看上去合理实际上完全错误”。我自己的习惯是建模前先画一遍所有输入数据肉眼检查时间维度的对应关系再开始写约束。这种检查很笨但每回都能救回一两个小时的调试时间。
返回列表