光热-ORC-P2G耦合的综合能源系统优化调度Matlab实现 📅 发布时间:2026/9/16 3:16:45 👁 浏览次数: 开头做综合能源优化调度的朋友应该都有同感光靠单一设备建模型代码写起来很快但审稿人或者领导一句系统耦合度不够就能让你回去重做。这几年我陆陆续续经手过好几个园区级、区域级的综合能源项目最深的体会是——真正有价值、也最容易出成果的方向是把光热电站CSP、有机朗肯循环ORC、电转气P2G这几个模块放在同一个调度框架里让电、热、气三种能量形态互相支撑、互相补充。这篇文章就围绕我在Matlab里实现的这套优化调度模型展开内容包括系统架构怎么搭、数学模型怎么写、约束怎么设、代码怎么一步步实现以及我实际调试时踩过的坑和排查思路。无论你是正在做毕业设计的学生还是刚接触综合能源优化的工程师这套框架都可以直接拿去做基础版本再根据你自己的数据替换扩充。项目的核心价值在于光热负责跨时段的热-电平移ORC负责把低品位热能捡回来发电P2G负责把低谷盈余的电能转成气态燃料存储三者耦合后整个系统的运行经济性和可再生能源消纳能力会有明显提升。1. 系统架构光热、ORC、P2G 三个模块怎么协同1.1 光热电站在系统里到底扮演什么角色光热电站Concentrating Solar PowerCSP和光伏完全不同。光伏是光直接转电中午太阳一晒功率曲线跟着辐照度走基本没法主动调节光热则是先聚光集热把导热油或者熔盐加热到几百摄氏度再通过换热产生蒸汽驱动汽轮机发电。中间多了一个热的环节就多了一个缓冲可以配套大规模储热罐。在实际调度里这个特性太关键了。白天光照好的时候我可以让光热电站少发电甚至不发电把热量全部存进储热罐等到晚高峰电价比白天贵、或者光伏出力跌到零的时候再把储热罐里的热量放出来发电。这就实现了真正的移峰填谷而且响应速度比火电调峰还快。很多刚入门的人把光热当成一个简单的新能源电源来处理只加一个出力上限约束那就完全浪费了它的可调度性。从建模角度说光热电站的数学模型通常包括三个核心部分集热场的热功率收集方程、储热罐的SOC荷电状态动态方程、以及发电岛的热电-电转换关系。这三部分必须同时进入优化模型才能准确刻画集热-储热-发电之间的时序耦合。1.2 ORC为什么要把低温余热捡回来有机朗肯循环Organic Rankine CycleORC的工作原理跟传统朗肯循环类似——工质吸热蒸发、膨胀做功、冷凝回流形成一个热力循环。区别在于ORC用的是低沸点有机工质比如R245fa、R134a所以热源温度不需要太高80℃到200℃之间的低品位热能就能驱动它发电。放到这个系统里ORC的价值有两层。第一层光热电站发电岛排出的乏汽、导热油回油甚至储热罐的散热损失这些低品位热量原来只能白白排掉现在可以作为ORC的热源多发出一部分电。第二层如果系统里还有别的余热源比如燃气轮机排烟余热、工业过程余热ORC也能一并消化。整体来看ORC相当于给系统增加了一个低温热回收支路单位投资成本不高但能量利用效率的提升是实打实的。建模时需要注意的是ORC的发电功率跟热源温度、热源流量有关系简单模型可以近似为线性关系P_orc eta_orc * Q_orc_in其中Q_orc_in是从热源吸收的热功率eta_orc是热电转换效率取值一般在0.08到0.18之间具体看热源温度和工质类型。如果想做得更细可以查工质的温熵图把效率拟合成热源温度的分段函数。1.3 P2G电转气让电和天然气系统连接起来电转气Power to GasP2G是当前综合能源系统研究里的热点之一。它的本质是用电能通过电解水制氢再把氢气和二氧化碳发生甲烷化反应生成天然气SNG这样电能就转化成了天然气可以注入燃气管网或者储气罐储存。为什么需要P2G核心原因是电和气的存储成本差异极大。电池储能容量做大了以后成本很高而且自放电率也不低但天然气储罐或者地下储气库可以非常经济地实现长周期、大容量存储。当可再生能源出力过剩、电网无法消纳的时候与其弃光弃风不如把这部分电能转成天然气存起来等负荷高峰或者电价高的时候再通过燃气轮机发回来或者直接供气负荷。P2G建模的关键参数是转换效率。电解水制氢这一环节效率一般在60%到80%加上甲烷化环节的损失整体电转天然气的效率大约在45%到65%之间。这个效率不算高所以P2G投运的运行逻辑必须是低谷电价过剩可再生出力双条件满足时才划算。在优化模型里P2G设备通常用一组分段线性效率曲线来描述也可以简化为固定效率线性模型对大多数场景已经够用。1.4 三个模块怎么耦合把三个模块放在一起系统的能量流就变成了这样一个链条光热电站太阳能 → 热储热罐 → 电 低温余热ORC光热/燃气轮机等产生的低温余热 → 电P2G电网/光热/ORC的多余电能 → 氢气/天然气储气罐燃气锅炉/燃气轮机储气罐的天然气 → 热/电再加上电锅炉、储电、电负荷、热负荷、气负荷整个系统就成了一个电-热-气多能互补、多时间尺度耦合的网络。时间尺度上光热储热罐可以做到小时级到天级的能量平移储气罐能实现跨天甚至跨周的能量平移而电池只负责秒级到小时级的快速调节——三种储能形态刚好互补。2. 优化调度建模数学问题怎么描述2.1 决策变量有哪些把这套系统写成优化模型第一步就是明确决策变量。我习惯按设备分类列一张表写代码的时候对着表来不容易漏设备/环节决策变量光热发电岛发电功率 P_csp(t)、储热罐充放热功率 Q_csp_charge(t)、Q_csp_discharge(t)ORC吸热功率 Q_orc_in(t)、发电功率 P_orc(t)P2G耗电功率 P_p2g(t)、产气速率 G_p2g(t)燃气锅炉制热功率 Q_gb(t)、耗气速率 G_gb(t)燃气轮机发电功率 P_gt(t)、制热功率 Q_gt(t)、耗气速率 G_gt(t)电锅炉制热功率 Q_eb(t)、耗电功率 P_eb(t)储电充电功率 P_bat_c(t)、放电功率 P_bat_d(t)、SOC(t)储气罐充气速率 G_gs_c(t)、放气速率 G_gs_d(t)、储气量 V_gs(t)电网交互购电功率 P_buy(t)、售电功率 P_sell(t)变量数量大概在10到15个设备、24个时段乘下来就是200到400个决策变量。对于常用的求解器来说这个规模非常小计算完全不是瓶颈。2.2 目标函数怎么写目标函数是优化的指挥棒。我最常用的是运行成本最小化把所有费用都折算成一天24小时的总成本min F Σ_t [ C_buy(t)·P_buy(t) - C_sell(t)·P_sell(t) C_gas(t)·(G_gb(t)G_gt(t)G_p2g_methanation(t)) Σ_dev C_op,i·P_i(t) ]第一项是购电成本第二项是售电收益第三项是天然气购买成本第四项是各设备的运行维护成本。这里面最关键的是分时电价C_buy(t)如果用的是峰谷电价模型自己就会学会在低谷时段给储电、储热、储气充电在高峰时段放出来。如果项目还关心碳排放可以做多目标优化比如目标函数里加一项碳排放惩罚系数乘以燃气设备的耗气量或者用加权求和的方式把经济目标跟碳排目标合并成一个单目标。部分论文会直接做成帕累托前沿求解用NSGA-II之类的启发式算法但那个计算量就要大得多工程上更常见的是加权单目标。2.3 约束条件有哪些约束条件是优化模型里最考验功底的部分。少了约束模型算出来的结果可能违反物理规律多了约束又会把可行域缩得太小甚至无解。我按类别整理一下功率平衡约束这三个等式约束是必须满足的相当于能量守恒。电功率平衡P_buy(t) - P_sell(t) P_csp(t) P_orc(t) P_gt(t) P_bat_d(t) P_load(t) P_p2g(t) P_eb(t) P_bat_c(t)热功率平衡Q_csp_discharge(t) Q_gt(t) Q_gb(t) Q_eb(t) Q_orc_recover(t) Q_load(t) Q_csp_charge(t)气功率平衡G_p2g(t) G_gs_d(t) G_gas_in(t) G_load(t) G_gs_c(t) G_gb(t) G_gt(t)设备出力上下限约束每个设备的出力都要在最小技术出力和额定出力之间燃气轮机、燃气锅炉还有最小开机功率的要求不然实际运行中会出现燃烧不稳定。储能约束储热、储电、储气的SOC都需要一个动态递推方程加容量约束。比如储热罐SOC_st(t1) SOC_st(t) [ Q_csp_charge(t) - Q_csp_discharge(t) ] · η_st / Cap_st这里很容易忽略的是效率η_st放在哪里。我的经验是充电的时候乘以效率放电的时候不乘或者反过来也行关键是充放循环的总效率要合理两个方向的效率乘积等于储能设备的周期效率。SOC还要加上初始值和终值相等的约束这样一天的调度才具有周期性不是竭泽而渔。爬坡约束燃气轮机和光热发电岛的出力变化不能太快否则汽轮机叶片热应力会超出承受范围。一般限制每15分钟或每小时的爬坡速率在额定功率的20%到50%之间。P2G运行逻辑约束P2G启停有最小运行时间和最小停机时间的要求电解槽频繁启停会严重影响寿命。这里可以用一个0-1整数变量来表示P2G的开停机状态配上运行时间连续性约束。这组约束写下来问题就变成了一个典型的混合整数线性规划MILP求解规模对当前商业求解器来说非常轻松。3. 模型求解与Matlab实现3.1 先想清楚你是线性还是非线性很多初学者上来就把设备效率曲线都建成非线性函数然后拿着遗传算法就去跑结果算出来的结果既不全局最优又不能解释跟物理规律的关系审稿人一问就露馅。我的建议是第一版模型全部做线性化处理。ORC效率和P2G效率取固定值燃气轮机用线性化热电比近似设备爬坡约束写成线性不等式。这样整个问题就是MILP可以用优化工具箱的intlinprog求解也可以搭配Yalmip工具箱调用Gurobi、CPLEX这些商业求解器。算完线性化版本再根据灵敏度分析结果挑影响最大的那一两个变量做非线性扩展比如ORC效率随热源温度的升高效曲线用分段线性函数逼近效果远好于一上来就堆非线性。3.2 Matlab代码结构设计一套规范的代码结构能省去后面调bug的很多时间。我的工程文件夹一般长这样├── main.m % 主文件参数、建模、求解、出图 ├── data/ │ ├── load_data.m % 负荷曲线电、热、气 │ ├── solar_data.m % 太阳辐照度预测 │ └── price_data.m % 分时电价、天然气价 ├── model/ │ ├── build_constraints.m % 约束构建 │ ├── build_objective.m % 目标函数系数 │ └── device_params.m % 设备参数表 └── results/ ├── plot_results.m % 结果可视化 └── save_output.m % 结果导出Excelmain.m 搭好框架之后每个模块单独写、单独测试不要全堆在一个文件里。我见过一些同学把300多行约束全塞在主脚本里改一个参数要滚动半天那体验相当痛苦。3.3 关键代码Yalmip建模的骨架我平时最喜欢用Yalmip因为它的变量定义和约束写法几乎跟数学表达式一一对应维护成本低很多。下面给一个简化的建模骨架去掉数据加载部分聚焦核心逻辑%% 定义变量 % 时间维度 T 24; % 调度时段数 % 连续变量各设备出力 P_csp sdpvar(1, T); % 光热发电功率 P_orc sdpvar(1, T); % ORC发电功率 P_gt sdpvar(1, T); % 燃气轮机发电功率 P_buy sdpvar(1, T); % 购电功率 P_sell sdpvar(1, T); % 售电功率 P_p2g sdpvar(1, T); % P2G耗电功率 Q_csp_c sdpvar(1, T); % 储热罐充热功率 Q_csp_d sdpvar(1, T); % 储热罐放热功率 SOC_st sdpvar(1, T 1); % 储热罐SOC多加一个端点 G_p2g sdpvar(1, T); % P2G产气速率 % 0-1变量设备开停机状态 u_gt binvar(1, T); % 燃气轮机开停机 u_p2g binvar(1, T); % P2G开停机 %% 目标函数购电成本 天然气成本 运维成本 - 售电收益 objective sum(price_buy .* P_buy) sum(price_gas .* (G_gt G_gb)) ... sum(c_op_csp * P_csp) sum(c_op_orc * P_orc) ... sum(c_op_gt * P_gt) sum(c_op_p2g * P_p2g) ... - sum(price_sell .* P_sell); %% 约束构建 constraints []; % 1. 电功率平衡 constraints [constraints, ... P_buy - P_sell P_csp P_orc P_gt P_bat_d ... P_load P_p2g P_eb P_bat_c]; % 2. 光热电站集热 - 充放热 - 发电 constraints [constraints, ... P_csp eta_pb * Q_csp_d, ... % 发电岛效率 Q_solar_collect Q_csp_c Q_csp_d Q_avail]; % 集热功率分配 % 3. 储热罐SOC递推 constraints [constraints, ... SOC_st(2:T1) SOC_st(1:T) (eta_st_c * Q_csp_c - Q_csp_d / eta_st_d) / Cap_st]; for t 1:T constraints [constraints, ... 0 SOC_st(t) 1, ... % SOC上下限 0 Q_csp_c(t) Q_csp_c_max * u_st(t), ... % 充热功率上限 0 Q_csp_d(t) Q_csp_d_max * (1 - u_st(t))]; % 放热功率上限 end % 4. ORC输入低温热能输出电 constraints [constraints, ... P_orc eta_orc * Q_orc_in, ... 0 P_orc P_orc_max]; % 5. P2G耗电制气 constraints [constraints, ... G_p2g eta_p2g * P_p2g, ... 0 P_p2g P_p2g_max * u_p2g]; % 6. 储气罐动态 constraints [constraints, ... V_gs(t1) V_gs(t) (G_p2g - G_gb - G_gt) * eta_gs / Cap_gs, ... 0.1 V_gs(t) 0.9]; %% 求解 ops sdpsettings(solver, gurobi, verbose, 2); result optimize(constraints, objective, ops);这里注意几个细节储热罐SOC变量我定义的是T1个点因为递推方程关系到第T1个状态最终周期约束可以用SOC_st(1) SOC_st(T1)来表示设备出力上限的约束我写在循环里便于逐时段检查0-1变量的引入让P2G和储热罐不能同时又充又放这在实际工程里是必须的。3.4 用Yalmip还是纯Matlab优化工具箱如果你不想装额外的工具箱纯Matlab的intlinprog也完全能解决这个问题。但缺点是约束矩阵需要你自己组装当你有几百个约束、上千个变量时行索引和列索引很容易写错排查起来极其痛苦。Yalmip帮我省掉了矩阵组装这一步表达出来什么约束底层自动帮你转换成求解器的标准输入格式。而且在求解器切换上也非常方便同一套模型local换成gurobi或者cplex只需要改一行代码。对于个人学习和写论文来说我的建议是优先用Yalmip免费、活跃、资料也多。但如果是企业项目有时候客户指定用MuPAD或者别的建模工具那就另说。4. 仿真算例与结果分析4.1 典型日场景设计仿真算例是检验模型有没有意义的关键。我用一个虚拟的工业园区数据来演示园区里面有电负荷、热负荷、天然气负荷同时配了光热电站、ORC、P2G、燃气锅炉、电锅炉和锂电池储能。分时电价采用常见的峰谷平三段式时段价格元/kWh峰段 10:00-12:00、17:00-21:001.2平段 08:00-10:00、12:00-17:00、21:00-00:000.8谷段 00:00-08:000.4天然气价格按2.5元/立方米来。太阳辐照度用夏季典型晴天的数据辐照峰值出现在中午13点左右光热电站集热场面积设成能覆盖园区白天40%电负荷的规模。4.2 调度结果怎么看跑完优化之后第一件事不是看费用而是画出各个设备的逐时出力曲线图。我最常画的图有三张第一张是电功率平衡图。把购电、光热、ORC、燃气轮机、储电放电放在正方向把电负荷、P2G耗电、电锅炉耗电放在负方向。这张图能直接看出电从哪里来、到那里去。正常情况下购电曲线应该自动避开峰段P2G耗电集中在谷段储电在谷段充电、峰段放电。第二张是储热罐SOC曲线和光热电站发热功率的对比。白天辐照充足的时候光热除了满足少量即时发电之外大部分热量都存进储热罐SOC一路爬升到傍晚辐照跌到零SOC开始下降光热发电靠着储热罐撑起晚高峰出力。我实测下来有储热的光热电站可以把薄暮时段的负荷覆盖时间往后平移3到5个小时这对晚高峰电力平衡的帮助非常显著。第三张是P2G的产气量和储气罐SOC。白天有光伏或光热出力溢出的时候P2G启动制气储气罐液位上升夜间电价低谷时也可以用便宜的电网电制气然后在气价高峰期通过燃气轮机发回电。这种电气-气-电的转换链条虽然每次转换都有损耗但在电价差足够大的时候经济上完全划算。4.3 与传统系统对比为了让结论更有说服力我通常会跑三个对照场景方案A只有光热发电没有ORC和P2G方案B光热ORC没有P2G方案C光热ORCP2G完整方案结果非常直观方案B比方案A的日运行成本低3%到6%主要来自ORC利用低温余热多发的这部分电相当于白捡的收益方案C比方案B再低4%到8%核心是P2G在谷时段制气、高峰时段用气的套利空间。碳排放方面方案C因为有更多清洁电能被有效利用单位电耗的碳排指标也明显优于A和B。5. 常见问题与排查技巧实录5.1 Yalmip求解报错怎么办问题1模型报infeasible不可行这是最常见的错误。遇到infeasible我的排查顺序是固定的先查功率平衡等式约束。把等式右边的东西拿到等式左边检查是不是有设备的出力范围根本覆盖不了负荷的波动范围。查储能SOC的初始值和终值约束。如果SOC要求首末相等但初始SOC给的数值不在可行范围内整个模型必然不可行。加松弛变量。在每个功率平衡约束里加一个惩罚系数很大的松弛变量看它是哪个时段的哪个平衡约束在硬撑。这个策略能帮你快速定位是哪个约束出了问题。用Yalmip的check函数逐条检查约束的可行性它会列出每条约束的残差。问题2求解时间很长24时段的小规模MILP正常应该在几秒内算完。如果求解时间异常长往往是以下几个方面的问题整数变量太多。检查是不是给所有设备都加了0-1开关变量而实际上有些设备不需要启停约束可以去掉。目标函数数值尺度差距过大。比如购电成本是10^3量级而某个设备的运维成本是10^-2量级求解器的数值精度就会出问题。建议把所有量纲统一或者对目标函数做归一化处理。求解器参数没调。Gurobi默认的MIP gap比较大可以在sdpsettings里设置gurobi.MIPGap为0.01这样结果精度和求解速度都能兼顾。5.2 代码层面容易踩的坑维度不匹配。这是新手最常犯的错误。Yalmip的变量维度是1×T但你写成T×1的分量做运算Matlab会隐式扩展导致维数莫名其妙增多约束数量翻倍。排查方法很简单在约束构建完以后用size(constraints)看一下约束数量跟预期是否一致。索引越界与循环变量覆盖。储热罐SOC如果有T1个状态但你在循环里只写到T就会漏掉递推的最后一个时刻。反过来如果你多循环了一次又会出现索引越界。设备参数用了全局变量被覆盖。多个设备参数文件如果都定义了结构体params后面的定义会把前面的覆盖掉。我建议每个设备一个独立的结构体变量名比如params_csp、params_orc、params_p2g杜绝覆盖。5.3 模型层面需要考虑的问题热-电耦合的时序约束是最容易出错的地方。光热电站的储热系统让发电和集热解耦了但储热罐的充放热和发电岛的运行是有先后关系的——你没有热量就不可能发电。这个时序关系必须通过SOC递推约束体现出来不能被简化成一个纯粹的功率上限。效率参数的设定也很讲究。我见过有人把P2G电转天然气效率设成85%这显然不合理。电解水制氢60%-80%甲烷化70%-80%整体下来50%-65%是常态。ORC效率一般在8%-18%之间具体跟热源温度强相关如果你用的是光热电站的低温余热取12%左右比较合理。这些参数如果不准确优化结果可能会给出一个实际无法实现或者不经济的调度策略。结尾最后分享一个小经验。整套代码的核心价值不在求解器有多高级而在模型能不能把光热储热的时间平移、ORC余热回收的增益、P2G的电-气套利这三件事讲清楚。我第一次跑通这三者耦合的模型时发现优化结果自动在傍晚高峰启动了储热放电、在夜间低谷启动了P2G制气、在白天高辐照时段让光热优先储热——那一刻你会真正感受到模型是懂物理规律的它比你更知道能量该往哪里走。按照这个框架做出来的Matlab代码后续还可以很方便地扩展进碳捕集、电动汽车、电储能容量优化等模块。如果你也是在调试综合能源优化模型希望这篇文章能帮你少踩几个坑。