资讯详情 P2G厂站综合能源系统规划模型Matlab复现与求解实践
📅 2026/10/5 8:40:04
1. 项目概述与论文复现的核心价值先说说这个题目本身。P2GPower to Gas电转气是电气综合能源系统里这两年绕不开的一个关键环节它把富余风电、光伏的电能转化成氢气甚至合成天然气让电力系统和气网系统产生双向耦合。我当初选择复现这篇论文核心目的是想把这套计及P2G厂站的规划模型彻底吃透并且在Matlab环境里跑通完整的优化求解流程——从天然气网络建模、电力系统约束、P2G厂站运行特性到规划方案的迭代寻优每一步都要落地成可执行的代码。为什么值得复现这类论文最大的价值不在于最终的规划结果而在于建模思路它把电-气耦合从单一的电转气购能问题升级成了考虑厂站内部运行约束电解槽效率、储氢罐容量、甲烷化反应热量平衡的一体化规划问题。对于准备做综合能源系统方向的学生或者刚接触能源互联网优化的工程师把这篇论文的代码复现出来等于一次性打通了电力系统优化调度、天然气网络稳态分析、混合整数线性规划MILP求解三条技术线。我在复现过程中的体会是这类论文的难点不在数学推导而在工程落地。学校给的论文材料往往只给最终模型和算例参数中间过程——比如天然气管道怎么线性化、网损怎么处理、NLP和MILP怎么切换——需要自己大量补课。下面我把整个复现过程拆开讲从建模到代码实现再到踩坑记录给你一条相对平整的路。2. 系统建模电网、气网和P2G厂站的协同表达2.1 电力系统部分怎么建电力系统在规划模型里一般保留节点功率平衡、机组出力上下限、爬坡约束这几个核心模块。复现时我确认了原论文的假设规划层不考虑暂态过程用直流潮流模型近似交流潮流这么做既保留了网络拓扑约束对规划结果的影响又让模型整体保持线性。需要特别留心的是P2G厂站作为负荷接入时怎么建模。P2G的本质是一个大功率电负荷所以任何含P2G的节点负荷不再是固定值而是决策变量的一部分。这在实现上要改动现有的节点功率平衡方程% 节点功率平衡P_P2G是决策变量 % 原方程: sum(Pg) - sum(Pload) sum(Pij) % 修改后: sum(Pg) - sum(Pload) - P_P2G sum(Pij) balance_eq sum(Pg_idx) - sum(Pload_idx) - sum(P2G_idx) sum(flow_idx);很多同学复现时容易在功率平衡里忘掉P2G这一项直接导致规划结果里P2G容量越大系统不平衡量越大仿真结果完全失真。再就是网损。直流潮流模型一般忽略网损但在规划问题里全网总有功平衡往往对计算结果影响很大。我看的这篇论文采用的是迭代修正法先求解不计网损的模型再根据潮流结果计算网损作为已知量回调到下一个迭代中。这种做法实现起来简单但要注意迭代的收敛条件设置。我在实测中用的是网损前后两次变化小于0.1%作为停止条件通常在3到5轮就能收敛。2.2 天然气网络稳态模型气网部分是这个领域公认的难点。天然气管网的核心变量是节点气压和管道流量两者之间的非线性关系让问题变得很棘手。常见的处理手段有两种一是分段线性化piecewise linearization把Weimouth方程按流量区间分段逼近二是直接在大规模MILP里用增量线性化方法嵌入。原论文采用的是增量线性化方法这是我复现时印象最深的一块。Weimouth方程本身是% 管道流量与两端压力满足非线性关系 % F_ij C_ij * sqrt(pi^2 - pj^2) % 令 H_ij pi^2 - pj^2则流量关于H_ij是根号关系 % 线性化: 将H_ij取值范围分成N段每段内流量线性逼近分段数量是精度和计算量的折中。我试过5段、8段、10段发现对规划问题来说8段已经足够分段数超过10段之后计算时间几乎翻倍而结果差异不到0.5%。如果论文没给具体分段数我建议直接采用8段作为默认参数这也是该领域文献里最常见的选择。气源、储气罐、负荷这三类节点的约束相对直接主要注意气源出力的上限和节点气压的上下限。节点气压范围在规划问题里经常被误设为固定值实际上气网节点气压允许在合理区间内浮动比如0.9到1.2倍的基准值。如果气压约束过紧会过度限制气网消纳P2G产气的能力。2.3 P2G厂站内部的黑箱变白箱这篇论文区别于普通电-气耦合研究的最大亮点是把P2G厂站内部过程展开了。P2G不是一个简单的输入电、输出气的黑箱而是一条由电解槽、储氢罐、甲烷化反应器、气体压缩机四部分组成的工艺链条。电解槽环节的关键约束是额定容量和运行范围。电解槽的输入功率不能低于某个比例否则电解效率急剧下降所以一般设一个最小运行功率约束比如额定功率的20%。储氢罐的作用是缓冲电解产氢和甲烷化耗氢之间的时间不匹配它的状态方程是一个离散时间递推式容量约束和初始/终态储量约束都必须加进去。甲烷化反应环节存在热量平衡问题——甲烷化是强放热反应建模时要在P2G功率输出和运行温度之间做一个温度约束的简化处理。不过大多数规划类论文并不真正求解热平衡而是直接用氢转甲烷的转换效率乘以输入氢量得到产气量。如果复现时想更严谨可以加一个温度惩罚项但我个人认为对于年度规划问题来说意义不大徒增非线性。气体压缩机在P2G厂站模型里往往是最容易被忽略的一块。P2G产气压力通常低于天然气输气管网的压力等级必须经过压缩机升压才能注入气网。压缩机本身消耗的功率虽然占比不大约占P2G总耗电的2%到5%但在规划模型里如果不计这部分自耗电P2G的净效率会被高估。我建议至少按压缩比和流量做一个线性化的功耗估算别完全省略。3. 规划模型构建与求解器选型3.1 目标函数的三层结构原论文的目标函数是典型的多层规划架构投资成本运行成本环境成本。我复现时把目标函数拆成了三层方便后续做敏感性分析投资成本层P2G厂站各设备的单位投资成本乘容量再乘年值系数注意设备寿命不同折算系数也不同。电解槽寿命一般按10到15年算甲烷化设备按20年算别统一套一个系数。运行成本层包括购电成本、购气成本、机组启停成本。这里购电成本要区分分时电价论文算例里通常给的是峰平谷三段电价。环境成本层按碳排放量折算成惩罚费用。需注意碳价参数设置原论文一般会说明基准碳价是多少复现时务必核对单位——是元/吨还是元/千克弄错一个量级整个结果全乱。这里有个心得论文的原始算例数据不同成本项权重差异很大。复现前先把目标函数各成本项的数量级算一遍如果发现某一项比另一个项小几个数量级大概率是单位问题而非真实差异。3.2 约束条件的层级拆分规划模型本质上是双层问题投资决策长期与运行决策短期。复现时如果直接用一个大规模MILP求解器硬解整个模型计算规模会非常恐怖——因为运行层要模拟365天×24小时的调度过程变量总量轻松上万。原论文这里的处理思路值得学习把规划问题拆成主问题和子问题的迭代式。主问题是投资决策输出P2G厂站建设方案子问题是给定投资方案后的年度运行优化输出运行成本和可行域反馈。主-子问题之间通过Benders分解的思路交互。我在复现中没有写完整的Benders分解而是采用了更工程化的启发式迭代方案先给一个初始P2G容量猜测值求运行子问题得到该方案下的最优运行成本把第一轮结果里被触发的容量瓶颈约束提取出来用于修正下一轮的投资方案如此迭代三到四轮便可收敛。必须说明的是这个简化方案牺牲了严格的全局最优性。如果审稿要求严格的最优解正版的Benders或直接MILP求解器是必需的但如果只是做工程方案分析这个迭代法的结果已经足够可靠而且速度快一个数量级。3.3 求解器选型与性能表现Matlab环境下求解MILP问题我比较过几套方案自带的intlinprog、 YALMIPGurobi、 YALMIPCPLEX。实际测试结果让我有点意外intlinprog在中小规模算例节点数少于30表现尚可但一旦进入IEEE 39节点或118节点级别的气电耦合系统intlinprog的求解时间和数值稳定性都肉眼可见地变差。Gurobi在MILP求解上的性能优势非常明显尤其是大量二元变量的场景。以我复现的30节点电网加20节点气网算例为例Gurobi求解时间约120秒intlinprog则耗了近800秒而且Gurobi的解质量目标值更优更好。给一个小建议复现这类论文如果资金宽裕优先用Gurobi。如果只有Matlab基础工具箱也完全可以跑通只是要把算例规模控制在合理范围内并设置合适的求解精度和最大迭代次数。4. Matlab代码实现从框架到核心函数4.1 代码整体架构设计我见过不少同学复现代码时喜欢把所有逻辑写在一个几百行的主脚本里面向过程的写法虽然直白但一旦需要调节参数或换算例就变得寸步难行。我这次复现采用了模块化设计简单说就是数据、模型、求解、结果四层分开项目根目录/ ├── data/ % 算例数据按系统分类存放 ├── models/ % 模型构建函数 ├── solver/ % 求解器调用封装 ├── results/ % 结果输出与图表生成 └── main.m % 主入口整个流程编排这个架构的收益是在换算例时显现的——只需新增一个data子目录中的数据文件代码零改动即可运行新的系统。如果你手头没有现成的电-气耦合标准算例用MATPOWER提供的电力系统数据搭配一个自建的气网数据文件也能拼凑出可用算例不必非要获得原论文的配套数据。4.2 关键数据结构设计Matlab编程里最容易被忽视的是数据结构设计。我发现用结构体数组按对象组织数据比散落的命名变量清晰得多。比如电网数据可以这样组织grid.bus struct(id, [], type, [], Pg, [], Pd, [], Vmin, [], Vmax, []); grid.line struct(from, [], to, [], R, [], X, [], capacity, []); grid.gen struct(id, [], bus, [], Pmin, [], Pmax, [], ramp, [], cost, []);P2G厂站的数据结构更复杂一些需要包含四个子模块的参数p2g.electrolyzer struct(capacity, [], eta_elec, [], Pmin_ratio, [], inv_cost, []); p2g.h2storage struct(capacity, [], init_level, [], final_level, [], inv_cost, []); p2g.methanation struct(capacity, [], eta_meth, [], Q_consume, [], inv_cost, []); p2g.compressor struct(elevation_ratio, [], power_coef, [], inv_cost, []);我踩过的一个坑是初期把所有数据分散在不同变量里结果跑大规模算例时内存管理混乱经常出现变量名写错但程序不报错的情况因为Matlab对变量名检查不严只是逻辑错了。用结构体之后至少能在视觉层面对数据关系一目了然。4.3 模型构建核心流程建模型的过程我分为五步走每一步都通过测试函数验证正确性后再进入下一步第一步读取算例数据并预处理。这一步的关键是节点编号的对齐——电网和气网的节点编号体系不同必须在数据层建立映射关系论文里通常给的算例图数据已经标好直接用即可。第二步构建电网模型。直流潮流中关键是导纳矩阵B的形成和节点分类平衡节点、PV节点、PQ节点。给定P2G厂站接入的新节点编号后在B矩阵中插入对应行列注意新增节点的基准电压和基准功率要与全系统一致。第三步构建气网模型。这部分是代码里最容易写错的。管道流量线性化需要预先计算分段点和斜率我写成了一个独立函数function [seg_points, slopes, intercepts] linearize_weimouth(pipe_C, p_max, p_min, n_seg) % 输入: 管道常数C, 压力上下限, 分段数 % 输出: 每个分段的端点、斜率、截距 H_max pipe_C^2 * (p_max^2 - p_min^2); H_seg linspace(0, H_max^0.5, n_seg1).^2; F_seg sqrt(H_seg); % 计算各段斜率 slopes diff(F_seg) ./ diff(H_seg); intercepts F_seg(1:end-1) - slopes .* H_seg(1:end-1); seg_points H_seg; end第四步把P2G厂站四个模块全部纳入模型。这一块我建议画一个简易的能流框图在纸上画即可不必画进代码明确每一级转换的能量流方向再逐一写约束。第五步组装目标函数和全部约束交给求解器。第五步是整个过程中最耗时的环节。我第一次组装模型时光约束数量就遇到上百条Matlab命令行窗口里报错信息满天飞后来学会了一个技巧每加一组约束后立即求解一个简化版模型只有该约束相关变量的固定值验证可行性。这样做问题定位很快基本不用从头调试。4.4 求解封装与结果后处理求解器封装我写成了通用接口这样可以在intlinprog和Gurobi之间无缝切换function [x, fval, exitflag] solve_milp(model, use_gurobi) if use_gurobi % 转换为Gurobi的输入格式 result gurobi_optimize(model); x result.x; fval result.objval; exitflag result.status; else options optimoptions(intlinprog, Display, final, ... MaxTime, 1800, RelativeGapTolerance, 0.01); [x, fval, exitflag] intlinprog(model.f, model.intcon, ... model.Aineq, model.bineq, model.Aeq, model.beq, ... model.lb, model.ub, options); end end结果后处理这块我建议一定做三张核心图第一张是不同P2G容量方案下的总成本柱状图第二张是典型日的电功率和气功率平衡曲线第三张是P2G厂站内部能量流桑基图用Matlab绘图函数手动实现。这三张图是论文复现成果最直观的呈现方式。特别是不同P2G容量下的成本曲线这张图几乎可以一眼看出规划方案的最优点——总成本最低处对应的P2G容量就是最优容量。5. 常见问题与排查技巧实录5.1 求解不收敛或收敛极慢这是复现此类论文最普遍的问题。我在调试时遇到过不少次模型不收敛的情况原因是多方面的但绝大多数指向同一个核心——约束条件过于激进。比如P2G年最大利用小时数设得过高导致投资容量在运行层面无法收回成本模型就会反复尝试调整投资方案始终找不到可行解。如果遇到收敛慢的问题我强烈建议先检查以下几处排查点典型症状处理方式P2G最小运行负荷约束模型某时刻P2G出力低于下限改为逻辑约束P2G要么关闭要么至少运行在20%额定功率储氢罐初末状态约束储氢罐储量出现不现实的锐减或激增放宽末端状态限制如终值在初值±10%之间气压节点上下限个别节点气压越界导致整体不可行适当放宽至1.2倍基准值或检查是否有气压等级设置错误分段线性化精度单段斜率过陡导致最优解落在分段点附近震荡增加分段数或改用均匀残差误差分布的分段方式5.2 线性化误差过大增量线性化方法的误差主要源于分段点的选取。我最初用等间距分段发现管道流量较大的情况下误差可以达到5%以上在系统层面产生可感知的偏差。改进方式是让分段间距不再均匀而是让单位区间内的流量残差保持一致即误差等分法。具体实现思路是先初步分段求出各段最大残差再调整分段点使各段最大残差相等。这种方法实现较为复杂但在求解效率和精度之间能取得更好平衡。如果只是复现论文结果用均匀分段并取8到10段一般就够用了。5.3 算例结果与论文不一致的排查这也是复现代码时非常常见的情况代码能跑通结果却和论文对不上。通常问题不在代码逻辑而在数据。建议按以下顺序排查第一步检查单位是否一致。论文中天然气流量可能是立方米/小时、千克/小时、Mbtu/小时三种不同单位混用换算关系搞错会直接导致几十倍的偏差。第二步检查基准功率和基准电压设置。ylq9综合能源系统研究中电力和天然气的基准值通常设为100MVA和1.0MPa如果基准值取错整个标幺值体系都会偏移。第三步检查典型日的选取。原论文的规划周期是8760小时但算例里的典型日可能是按季节或按峰谷时段浓缩出来的。复现时要明确原论文是用了完整的8760小时建模还是用了若干个典型日乘以权重系数。这两者的结果会有不小差异。第四步检查P2G效率的计算方式。是低热值效率还是高热值效率两者数值相差约10%左右论文如果没有明确说明复现时很容易出现几不可见的差异。5.4 求解器数值稳定性问题Matlab的intlinprog在处理具有不同量级数值的混合整数问题时容易陷入数值病态问题——比如投资成本是千万量级而运行成本是百万量级二元变量的目标系数很小导致MIP启发式搜索表现不佳。解决办法是对模型中的系数进行归一化把投资成本除以一个基准值比如总投资上限让所有目标项的量级集中在1到100之间。这个操作的原理是避免求解器内部处理跨量级数值时产生舍入误差。别小看这一步我遇到过一组算例归一化前后目标值相差4%的情况而这个差异完全来自数值误差而非模型变化。6. 复现过程的经验总结与后续扩展方向整个项目复现下来我最大的体会是论文复现不是简单的翻译代码而是对建模思路的再发现。原论文里一笔带过的许多假设——比如管道流量线性化的具体分段数、P2G厂站内部压缩机自耗电的处理方式——恰恰是工程实现中最需要斟酌的细节。真正跑通一轮完整流程之后你对综合能源系统规划的理解深度会远远超过只看理论推导时的水平。如果后续想在这个基础上扩展我个人建议几个方向一是把P2G厂站模型换成更精细的电制氢全链条模型加入电解槽的启停成本和动态效率曲线二是在规划模型中加入不确定性因素比如风电出力和电价的随机场景三是把天然气网由稳态模型扩展为动态模型考虑管道储气效应。这三个方向在当前的研究中都很热门而且都是能在复现代码基础上做增量式修改完成的。最后再分享一个经验复现过程中请务必保存好每一个能运行的版本并做好注释。你可能现在觉得某个中间版本没用但三周后当你发现新模型的求解器行为变得诡异时那个旧版本就是你回溯排查的最佳参照物。每次改动前先跑一遍当前版本记录目标值和关键约束的满足情况再做修改。这套好习惯可以帮你省掉大量调试时间。