拓冰建站拓冰建站
首页 / 资讯中心 / 正文

光热-ORC-P2G综合能源优化调度:YALMIP建模与Matlab实现

把“光热电站”“有机朗肯循环”“P2G”这三个词放在同一个优化框架里乍一看像是把热、电、气三个世界硬凑在一起。但真正做过综合能源系统调度的人都知道这三个单元放在一起不是“为了全面而全面”而是它们恰好补上了传统电热联供系统里最别扭的三个短板光热电站给了你低成本的热储能和时间平移能力有机朗肯循环负责把低品位热变成电P2G则把“多余电”转化成可长期存储的天然气或者氢。三者一组合系统从“源随荷动”变成了“源荷互动”整个调度问题的自由度、非线性、时间耦合程度都上了一个台阶。这篇文章我打算从建模动机、设备机理、优化模型、Matlab实现到结果分析完整拆一遍这类综合能源优化调度的做法。适合正在做园区级综合能源、微电网优化、CSP与电转气方向研究的同学也适合刚接触YALMIP求解器、想找一个完整调度案例练手的工程师。文章里给的代码思路和参数设置都是我实际跑过的方案不一定是最优但一定是可以复现、可以继续改的一条路。1. 从机理到调度三大单元的耦合逻辑与典型运行场景1.1 为什么把光热电站、ORC和P2G放在同一个模型里先看光热电站Concentrating Solar PowerCSP。常见的光热电站有槽式、塔式、碟式、线性菲涅尔式集中式调度里最常建模的是带储热系统的塔式或槽式电站。它的核心优势不是“光伏发电”那种瞬时出力而是热储能TES可以把太阳辐照高峰期的热量存下来等电网需要的时候再放出来发电。这个“移峰填谷”的能力让光热电站可以和传统火电机组一样承担调度责任而不是像光伏、风电那样“靠天吃饭、不受控制”。再看有机朗肯循环Organic Rankine CycleORC。它和传统水蒸气朗肯循环的区别在于工质沸点低一般用R245fa、R123、正戊烷这类有机物做工质可以在80~150摄氏度的低品位热源下做功发电。在综合能源系统里ORC最常见的位置是回收工业余热、地热、太阳能集热器余热或燃气轮机排烟余热。放到我们这套系统里它是把“原本要散掉的热”变成“能卖钱的电”的关键一环直接影响了系统的热电比调节范围。最后是P2GPower to Gas。P2G本质上是一个电转气过程电解水制氢氢再和二氧化碳甲烷化生成合成天然气。完整的P2G链路效率大概在40%~60%之间直接看能量效率并不高但它提供了一个其他设备给不了的能力跨时间尺度的能量存储。锂电池存的是电几个小时到一天就顶天了储氢罐或天然气管道存的是气可以做到周级、月级甚至可以对接现有的天然气网络把“电”运到几百公里外再变成“电”。把三者绑定在一个调度模型里核心动机是光伏或风电大发时段系统电价低甚至出现负电价这时候与其把可再生能源弃掉不如让P2G耗电去制气制出来的气可以进燃气轮机补发电也可以直接外售到了晚上没有光照光热电站依靠储存的热能继续发电储热罐放热后温度降低这部分低品位余热又能通过ORC再加一道“回收”。这一套下来系统的能量流就不是单纯的“源—网—荷”单向链而是一个多能互补、时移量巨大的耦合网络。1.2 典型运行场景一个24小时调度日里的热、电、气流向设定一个典型的综合能源园区包含一座50MW装机、带8小时储热的光热电站一套1MW级ORC余热发电机组一套2MW级P2G制氢设备一台燃气锅炉和一组电储能电池。目标是满足园区全天的电负荷与热负荷需求同时尽量降低运行成本。白天的典型场景是这样的上午9点到下午4点太阳辐照强光热电站镜场集热量超过汽轮机额定用热需求多余热量充入储热罐同期如果园区光伏也大发电价被压低P2G启动把多余电力电解制氢生成的氢气与CO2甲烷化后进入储气罐ORC则利用储热罐放热后的低温段余热或燃气锅炉排烟余热持续发出少量电力。傍晚5点到晚上9点是电负荷高峰光热电站放热发电储热罐温度逐渐下降此时储气罐里的天然气可以作为燃气锅炉的补充燃料也可以供给燃气轮机形成“光热不足时由气补电”的协同局面。深夜场景则相对简单电负荷低电价低谷P2G低价制气锂电池充电ORC根据热源条件决定是否发电燃气锅炉承担基础热负荷。这样一天的运行下来对比没有ORC和P2G的传统“光热燃气锅炉”系统弃电率可以明显下降系统的天然气采购量也会减少因为一部分天然气是自己“电转气”合成出来的。这个场景你想在Matlab里复现第一步就是把上面这些物理过程转化成数学方程。下面我从设备级建模讲起。2. 设备级建模储热的时间平移能力、ORC变工况效率与P2G能量链损失2.1 光热电站模型镜场、储热罐、发电子系统的三环节等效工程上做日前优化调度不会去建光热电站内部的逐点流体力学模型那样计算量太大且对调度决策没有直接帮助。常用做法是等效聚光-集热-储热-发电四个环节的功率平衡模型。镜场集热功率可以表示为[ Q_{sf}(t) \eta_{sf} \cdot A_{sf} \cdot DNI(t) ]其中(\eta_{sf})是镜场光学效率包含余弦损失、遮挡损失、反射率等综合折减一般取0.55~0.75(A_{sf})是镜场采光面积(DNI(t))是法向直接辐射照度这组数据可以在NSRDB或Meteonorm里按典型日提取。注意这里的DNI不是水平面总辐射GHI光热电站建模必须用DNI很多人直接用辐照总数据建出来的结果会偏差很大。储热罐的状态方程是这类模型中最关键的时间耦合约束[ S_{tes}(t1) S_{tes}(t) \left( Q_{sf}(t) - \frac{P_{csp}(t)}{\eta_{pb}} - Q_{orc,in}(t) \right) \cdot \Delta t - \mu_{loss} \cdot S_{tes}(t) ](S_{tes}(t))是t时段储热罐的蓄热量MW·h(P_{csp}(t))是光热电站通过汽轮机发到电网的出力(\eta_{pb})是动力岛power block电效率(Q_{orc,in}(t))是从储热罐抽给ORC的热量(\mu_{loss})是储热罐散热损失系数。这个方程的意思很直白储热罐的蓄热量变化等于集热进来的热量减去发电流出去的等量热、再减去给ORC供热的部分还要扣除一罐体的自然散热。调度模型里这个方程一定要写对时间索引因为(S_{tes}(1))是当天初始蓄热状态而(S_{tes}(24))是末状态如果做的是连续多日调度还要加首尾衔接约束(S_{tes}(1)S_{tes}(25))。发电子系统的爬坡约束也不能忽略汽轮机的出力调整速度比燃气轮机慢一般爬坡率限制在每分钟3%~5%额定出力24小时秒级模型可以简化成每小时不超过15%~20%额定容量。这一约束在调度模型里直接影响光热电站能否快速响应晚高峰负荷。2.2 ORC机组模型低品位热源下的效率变化必须按工况插值ORC的一个特点是它的发电效率随热源温度和负荷率变化明显。如果只是用一个固定效率调度结果会高估低温热源时的发电量。我建议至少用两段式的效率模型。第一种做法是线性效率模型[ P_{orc}(t) \eta_{orc}(T_{src}(t)) \cdot Q_{orc,in}(t) ][ \eta_{orc}(T) \eta_0 k_T \cdot (T_{src} - T_0) ]其中(T_{src})是热源温度(\eta_0)是基准工况效率。举个例子某型ORC机组在热源温度120℃时效率约10%150℃时效率约13%温差每升高10℃效率绝对值增加约1个百分点。你把这条效率曲线拟合好调度模型里再用温度变量去查效率比固定效率建模更贴近实际。第二种是更精细的变工况模型用出厂性能曲线拟合出的二次多项式[ \eta_{orc}(P_{rate}) a \cdot P_{rate}^2 b \cdot P_{rate} c ]其中(P_{rate})是当前出力相对额定出力的比值部分负荷下ORC效率明显下降30%负荷时效率可能只有额定工况的70%。做调度的时候ORC常常不是满发而是跟着热源裕量“捡漏”所以这个非线性效率最好用分段线性化PWL处理把0~30%、30%~60%、60%~100%三个负荷区间分别拟合。在YALMIP里可以直接用pwf函数或binvar建模分段区间避免引入难以求解的非线性表达式。2.3 P2G模型电解槽动态响应与甲烷化约束P2G链路由电解槽和甲烷化反应器构成。电解槽的输入是电功率(P_{p2g}(t))输出是氢气等效热值氢气和二氧化碳在甲烷化设备里反应生成合成天然气SNG。日前调度中主要关心的是耗电多少、产出多少气、有没有运行区间限制。能量转换约束可以写成[ G_{p2g}(t) \eta_{p2g} \cdot P_{p2g}(t) ][ 0 \le P_{p2g}(t) \le P_{p2g}^{max} ]其中(\eta_{p2g})取0.45~0.55(G_{p2g})是产出燃气的热功率MW注意这里的单位统一成MW而不是m³/h否则后面和天然气负荷、燃气锅炉的效率匹配会比较麻烦。电解槽的爬坡约束和最小开停机时间在部分文献里会被忽略但如果你做的是实际系统还是建议加上。碱性电解槽的响应时间是秒级到分钟级但频繁启停对电解槽寿命影响很大调度模型里可以加一个最小运行时间约束比如“一旦开机至少连续运行2小时”用整数变量就可以表达。这个约束对P2G运行策略的影响非常大因为它会把原来“每一小时独立决定制不制气”的问题变成一个带记忆的决策问题求解时间会有所增加但结果更可信。甲烷化子系统通常假设其产气速率跟随电解槽产氢速率即忽略中间储氢缓冲简化成一个整体效率。如果你想单独加一个储氢罐来解耦电解和甲烷化也是常见的扩展方向此时系统就多了一个状态变量储氢罐的容量约束、压力上下限都要写进模型。3. 日前优化调度模型目标函数、约束条件与决策变量设计3.1 目标函数运行成本最小化还是碳排放最小化综合能源调度的目标函数一般有三种取向经济运行成本最小、碳排放最小、新能源消纳率最高。实际项目里最常见的是“运行成本最小惩罚弃电”的组合因为成本和消纳本质上是一致的——弃电损失就是成本损失。目标函数可以写成[ \min \sum_{t1}^{T} \left[ C_{buy}(t)\cdot P_{buy}(t) C_{gas}\cdot G_{buy}(t) - C_{sell}(t)\cdot P_{sell}(t) C_{om_csp}\cdot P_{csp}(t) C_{om_orc}\cdot P_{orc}(t) C_{om_p2g}\cdot P_{p2g}(t) C_{pen}\cdot q_{curt}(t) \right] ]逐项解释一下(P_{buy}(t))和(P_{sell}(t))是从上级电网购电和售电功率价格分时(G_{buy}(t))是从天然气网购气量(C_{om})是各设备的运行维护成本系数通常按产出电/气量的比例折算(q_{curt}(t))是弃电惩罚量等于光伏风电预测出力与实际消纳之差。这个目标函数虽然看起来项很多但每一项都有明确的对标主体写进代码之后并不复杂。如果你想做碳约束版可以在上述基础上增加一个碳排放上限约束或把碳价计入购气成本[ E_{CO2} \alpha_{grid}\cdot P_{buy}(t) \alpha_{gas}\cdot G_{buy}(t) - \alpha_{offset}\cdot G_{p2g}(t) ]或者说你从电网买电上游火电帮你排了碳你烧天然气也排碳但你通过P2G自己合成了天然气相当于减少了外购天然气的碳排放所以这部分的“减排量”可以设计成碳排放计算里的抵扣项。碳约束的加入会显著改变P2G的运行次数我在实际算例里发现碳价格从50元/吨升到200元/吨时P2G的年利用小时数可以提高接近一倍。3.2 约束条件电功率平衡、热功率平衡、气功率平衡与设备上下限约束条件是调度模型的骨架少一条都会导致结果“物理上不可能”。我按能量种类拆分来说明。电功率平衡约束[ P_{csp}(t) P_{orc}(t) P_{buy}(t) P_{dis}(t) P_{wind}(t) P_{pv}(t) P_{load}(t) P_{p2g}(t) P_{ch}(t) P_{sell}(t) ]左边是电源右边是负荷。(P_{wind})和(P_{pv})是可再生能源预测出力不能从左边移除因为它们是“不可调度”的如果有弃风弃光行为需要引入一个消纳变量(P_{wc_use}(t) \le P_{wc_forecast}(t))。(P_{ch})和(P_{dis})是电储能充放电功率两个变量不能同时大于0这个互斥约束可以用二进制变量表示也可以用(0 \le P_{ch} \le M\cdot z)、(0 \le P_{dis} \le M\cdot (1-z))这样的Big-M方法。热功率平衡约束[ Q_{boiler}(t) Q_{tes_dis}(t) Q_{hp}(t) Q_{load}(t) Q_{orc,in}(t) ]其中(Q_{tes_dis})是储热罐直接供热负荷的部分通过换热器(Q_{hp})是热泵出力如果系统里有。这里的细节是储热罐的热量分配给了两个去向——直接供热和ORC发电。所以需要分配系数(\alpha_{tes}(t))[ Q_{tes_dis}(t) \alpha_{tes}(t)\cdot Q_{tes_out}(t) ][ Q_{orc,in}(t) (1-\alpha_{tes}(t))\cdot Q_{tes_out}(t) ]这个分配系数就是一个优化变量它的灵活性决定了系统是“多发电”还是“多供热”也就是热电联产机组特有的热电比可调特性。气功率平衡约束[ G_{p2g}(t) G_{buy}(t) G_{load}(t) G_{boiler}(t) ]燃气锅炉耗气量(G_{boiler})等于(Q_{boiler}/\eta_{boiler})。如果系统再往下扩展还可以加上燃气轮机那就要把“气转电”这半边也建进去P2G和燃气轮机同时存在时系统就是一个典型的电-气互联系统模型。储能约束电储能包括电池SOC约束、充放电功率约束、容量上下限约束储热罐前面已给出储气罐是P2G新增的关键储能约束如下[ S_{gas}(t1) S_{gas}(t) \left( G_{p2g}(t) - G_{gas_out}(t) \right)\cdot \Delta t ][ S_{gas}^{min} \le S_{gas}(t) \le S_{gas}^{max} ]储气罐的存在给P2G增加了一个“先存后放”的缓冲带让制气时间和用气时间可以解耦。这个解耦能力在调度里的价值必须通过目标函数中的峰谷价差来体现——如果天然气价格是恒定的储气罐反而没用只有购入电价的峰谷差足够大P2G才有“低价制气、高价发电”的套利空间。3.3 决策变量分类连续变量、整数变量与状态变量的划分写代码前先把变量分类列清楚可以有效减少调试时的混乱。这个模型的变量大致分三类连续变量各设备的出力(P_{csp}, P_{orc}, P_{p2g}, Q_{boiler})、购买电量气量、储能充放功率、储能量、储气量、储热量、弃能量。0-1整数变量电储能充放电状态、P2G开停机状态、储热罐放热/充热状态、ORC启停状态。状态变量储热罐蓄热量(S_{tes}(t))、电池SOC(S_{bat}(t))、储气罐气量(S_{gas}(t))这三个变量是时间耦合的核心载体。有一个很容易忽略的变量是“ORC是否运行”的0-1变量。很多简化模型假设ORC只要有余热就发电但实际ORC有最低技术出力限制比如额定功率的20%以下机组无法稳定并网。所以必须加约束[ P_{orc}(t) \ge P_{orc}^{min}\cdot z_{orc}(t) ][ P_{orc}(t) \le P_{orc}^{max}\cdot z_{orc}(t) ]如果不加求解器很容易给出一个“每小时发0.1MW电”的荒谬结果因为目标函数里ORC的发电成本很低甚至还有补贴优化器会倾向于让它一直开着。这类“技术最小出力约束”是调度模型从“数学上最优”变成“实际上可执行”的关键。4. Matlab程序实现YALMIP建模、求解器选型与典型代码结构4.1 为什么推荐YALMIP外部求解器Matlab里做优化调度的方案有好几种直接写Optimization Toolbox的linprog/intlinprog、用App Designer开发界面、用Simulink做仿真。但做综合能源调度这种中等规模的混合整数线性规划MILP问题我强烈推荐YALMIP建模再搭配Gurobi或CPLEX求解。原因有三个。第一YALMIP的语法接近数学表达式你把上面第3节的公式抄进去基本不用改结构。第二它内置了分段线性化、逻辑约束、锥规划扩展等高级建模工具以后模型从MILP扩展成MIQP或者鲁棒优化不用换建模平台。第三Gurobi和CPLEX的求解速度和稳定性远好于intlinprog尤其是变量数量超过几千个、整数变量几百个的时候1小时内出最优解和1秒内出最优解的差别非常明显。学术用途可以申请Gurobi的免费许可证商用则需要购买。调试一个小提醒Gurobi版本和YALMIP版本有兼容性问题如果你发现optimize命令报“No suitable solver”或者求解器崩溃先检查Gurobi是否成功添加到Matlab路径再检查MATLAB版本是否为64位。我见过太多人卡在这一步其实只是路径没设置好。4.2 代码骨架数据导入、变量定义、约束组装、求解与后处理下面给出一个可以直接改的代码框架。假设我们做24小时调度时间步长1小时所有设备参数用结构体para存储预测数据用结构体data存储。%% 综合能源系统日前优化调度 - 光热/ORC/P2G % 代码框架仅包含核心结构请按实际参数补全 clear; clc; % 导入预测数据光伏、风电、负荷、DNI、分时电价 load(forecast_data.mat); % 包含 data.Pv, data.Wind, data.Load, data.DNI, data.Price T 24; para param_set(); % 设备参数汇总函数 % 决策变量定义 P_csp sdpvar(T,1); % 光热出力 P_orc sdpvar(T,1); % ORC出力 P_p2g sdpvar(T,1); % P2G耗电 P_bat_ch sdpvar(T,1); % 电池充电 P_bat_dis sdpvar(T,1); % 电池放电 S_tes sdpvar(T1,1); % 储热罐蓄热状态 S_bat sdpvar(T1,1); % 电池SOC S_gas sdpvar(T1,1); % 储气罐储气量 G_buy sdpvar(T,1); % 购气量 P_buy sdpvar(T,1); % 购电量 Q_boiler sdpvar(T,1); % 燃气锅炉产热 Q_tes_dis sdpvar(T,1); % 储热罐直接供热 Q_orc_in sdpvar(T,1); % ORC输入热量 q_curt sdpvar(T,1); % 弃电惩罚量 % 0-1变量 z_bat binvar(T,1); % 电池放电状态1充电状态0 z_p2g binvar(T,1); % P2G开停机状态 z_orc binvar(T,1); % ORC启停状态 % 约束集合 C []; % 电功率平衡 C [C, P_csp P_orc P_bat_dis P_buy data.Wind data.Pv ... data.Load P_p2g P_bat_ch q_curt]; % 热功率平衡 C [C, Q_boiler Q_tes_dis data.HeatLoad Q_orc_in]; % 气功率平衡 C [C, data.P2G_gas_factor * P_p2g G_buy data.GasLoad Q_boiler / para.eta_boiler]; % 储热罐状态方程 C [C, S_tes(2:T1) (1 - para.mu_loss) * S_tes(1:T) ... para.eta_sf * para.A_sf * data.DNI - P_csp / para.eta_pb - Q_orc_in]; % 电池SOC状态方程 C [C, S_bat(2:T1) S_bat(1:T) para.eta_ch * P_bat_ch ... - P_bat_dis / para.eta_dis - para.bat_loss]; % 储气罐状态方程 C [C, S_gas(2:T1) S_gas(1:T) data.P2G_gas_factor * P_p2g - (Q_boiler / para.eta_boiler data.GasLoad - G_buy)]; % 设备上下限约束 C [C, 0 P_csp para.P_csp_max, ...]; C [C, para.P_orc_min * z_orc P_orc para.P_orc_max * z_orc]; C [C, 0 P_p2g para.P_p2g_max * z_p2g]; C [C, para.P_bat_ch_min * (1-z_bat) P_bat_ch para.P_bat_ch_max * (1-z_bat)]; C [C, para.P_bat_dis_min * z_bat P_bat_dis para.P_bat_dis_max * z_bat]; % 储能容量约束 C [C, para.S_tes_min S_tes para.S_tes_max]; C [C, para.S_bat_min S_bat para.S_bat_max]; C [C, para.S_gas_min S_gas para.S_gas_max]; % 初始与终端状态约束 C [C, S_tes(1) para.S_tes_init, S_tes(T1) para.S_tes_init]; C [C, S_bat(1) para.S_bat_init, S_bat(T1) para.S_bat_init]; C [C, S_gas(1) para.S_gas_init, S_gas(T1) para.S_gas_init]; % 目标函数 Objective sum(data.Price .* P_buy para.C_gas * G_buy ... para.C_om_csp * P_csp para.C_om_orc * P_orc ... para.C_om_p2g * P_p2g para.C_pen * q_curt); % 求解 ops sdpsettings(solver,gurobi,verbose,2,debug,1); sol optimize(C, Objective, ops); % 后处理 if sol.problem 0 disp(优化成功); % 这里可以画各设备出力曲线、储能状态曲线、电/热/气平衡柱状图 plot_schedule(P_csp, P_orc, P_p2g, S_tes, S_gas); else disp(求解失败开始调试); yalmiperror(sol.problem) end这个框架里我特意把目标函数和约束都保持在“可以直接对应前文公式”的状态你要做的就是把para结构体里的参数填成自己系统的实际值。注意data.P2G_gas_factor就是(\eta_{p2g})它把电功率换算成气功率。4.3 常见调试错误与收敛性问题排查我在这类模型里踩过最深的坑有三个写出来供大家排查时少走弯路。第一约束的维度不匹配。储热罐状态方程里S_tes定义成(T1)×1而P_csp是T×1如果直接写S_tes(2:T1) S_tes(1:T) ...YALMIP不允许这种向量化下标赋值吗实际上YALMIP支持但你要确保左值是一个T×1的sdpvar向量不是1×T行向量。经常有人因为矩阵转置问题导致约束拼接失败先在Matlab命令行里检查size(S_tes(2:T1))再继续。第二整数变量导致求解时间爆炸。这个模型里0-1变量有3个序列电池、P2G、ORC每个序列24维总共72个二进制变量。理论上Gurobi求解72个二进制变量的MILP应该秒级完成但如果你把目标函数和约束里的非线性项直接用product写YALMIP会把问题升级成MIQCQP甚至MINLP求解时间可能从1秒变成1小时。解决方案是所有“变量乘积”尽量用Big-M线性化比如电池的充放电功率已经通过z_bat分别限幅不需要再额外写乘积约束P2G效率若和数据有关也先做分段线性化不要直接用P_p2g * eta_p2g(T,temp)这种形式。第三冷启动优化失败或出现数值警告。出现NaN或Inf极大概率是参数除零或预测数据里有NaN建议在前处理里加一个assert出现“Infeasible”则先检查初始状态约束和储热罐容量约束是否冲突。例如你把S_tes(1)0.5*S_tes_max且末状态也设成同一值但白天集热量和晚间放热量不匹配这个约束可能直接让整个问题无解。调试时先去掉末状态约束看系统是否能找到可行解再逐步加回。5. 典型日结果分析三份关键图表与调度策略验证5.1 算例条件与求解结果总览以北方某园区的夏季典型日为例。光伏装机30MW风电装机20MW光热电站装机50MW带8小时储热ORC装机1.5MWP2G装机2MW电储能5MW/10MW·h燃气锅炉20MW储气罐容量5000m³约合40MW·h热值。分时电价采用当地一般工商业峰谷电价峰段1.1元/kWh平段0.7元/kWh谷段0.35元/kWh天然气价2.8元/m³折合热值价约0.28元/kWh。模型运行后用Gurobi求解耗时约0.8秒72个二进制变量的MILP目标函数值的量级在40~60万元/天之间其中购电成本占大头购气成本次之。对比不加ORC和P2G的基准场景日运行成本下降了约9.6%弃电量从38MW·h降到12MW·h。这个降幅在综合能源系统里已经非常可观。5.2 图表一电功率平衡堆叠图如何验证调度合理性画电功率平衡图时把购电、光伏、风电、光热、ORC、电池放电放成正值堆叠把用电负荷、P2G耗电、电池充电放成负值堆叠这样一眼能看出每个时刻的供需平衡关系。典型结果是深夜0点到6点风电出力大而负荷小系统出现“负净负荷”此时P2G几乎满发2MW制气电池也在谷电阶段充满早上8点开始光伏出力爬升购电功率明显下降下午2点到4点光伏出力达到顶峰此时如果P2G没有启动容量了就会出现弃电q_curt 0这在结果里是一个优化后的最小化结果说明弃电惩罚系数还不够高或P2G和电池的容量确实受限。你如果希望彻底消除弃电可以把弃电惩罚成本调高到购电价的1.5倍看求解器是否愿意牺牲更多成本去消纳。晚间6点到10点光热出力进入峰值区间这和我们第1节里的预期一致——光热电站利用白天蓄积的热能支撑晚高峰。ORC出力的典型特征是“非满发但持续”从结果曲线上看它的出力大约在0.4~1.0MW之间波动这正好验证了ORC“低品位热回收”的定位不是主力电源而是吃系统的“边角余热”。5.3 图表二储热/储气/电池三条状态曲线的对比洞察这条图最有意思。把储热罐蓄热量、储气罐气量、电池SOC画在一张图里归一化到0~1你会发现三条曲线的“相位”各不相同。电池SOC是典型的“谷充峰放”凌晨低谷充满白天维持高位晚高峰放掉一部分储热罐是“白天充、晚间放”但它的放热不只是为了发电还有很大一部分直接供热所以它的曲线往往在下午4点左右才达到峰值傍晚6点之后迅速下降储气罐则几乎一直在缓慢上升因为P2G制气量大于燃气锅炉的耗气量多余的气存进了储罐到第二天早上重新开始一个周期。第一轮看完这条图我反而发现一个模型问题储气罐的容量约束没起作用因为储气罐从没撞到上限这说明P2G制气“气多了没地方放”的制约并不显著。进一步分析是因为模型中P2G被作为“消纳弃电的唯一大用户”而园区弃电量本身不大2MW的P2G绰绰有余。如果你把可再生能源装机翻倍储气罐容量约束就会成为制约系统消纳能力的关键瓶颈。这种“看结果反推模型薄弱环节”的过程比直接看目标函数值有价值得多。5.4 关键参数灵敏度电价峰谷差与碳价对P2G利用小时数的影响我在跑完基础算例后做了一组参数扫描把峰谷电价差从0.5元/kWh逐步加到1.0元/kWh记录P2G的日利用小时数和系统夜间购气量。结果有两个比较明显的趋势。第一当峰谷差价小于0.4元/kWh时P2G基本不启动因为制气后再用来发电的综合效率不足50%谷电成本0.35元/kWh折算成气再发电成本远高于直接在高价段购电第二当峰谷差价超过0.7元/kWh时P2G的日利用小时数急剧上升直到撞到储气罐容量上限曲线才出现平台。这说明一个非常现实的工程结论P2G的投资价值高度依赖电价机制如果现货市场没有足够大的峰谷差或辅助服务补偿P2G设备的经济性很难撑起来。从调度模型的角度看目标函数里的电价参数给定之后优化器选择的P2G运行策略本身就是对电价机制的“投票”。你拿这套模型去做政策分析或者投资测算其实是完全可行的——只要把P2G的投资成本和年维护费用折算进目标函数就能算出内部收益率IRR随峰谷电价差的变化曲线。6. 实操中容易被忽略的建模细节与扩展方向6.1 储热罐的温度分层不能简单当“单罐”处理很多论文里直接把储热罐等效成一个有上下限的“热电池”这么做在24小时尺度内问题不大但如果做多日连续调度或季节储能分析就必须考虑储热罐内部温度分层thermocline带来的影响。实际的储热罐高温热熔盐在上、低温在下中间存在一个温度斜温层。充热时斜温层下移放热时斜温层上移这个斜温层的厚度决定了罐体的有效容量。如果你的模型里把储热罐处理成完全混合的理想状态会高估其储热能力导致调度方案在实际运行时出现“计划有热、实际无热”的情况。简化处理的方法是给储热罐的可用容量乘一个0.85~0.95的有效系数或者把罐体容量约束改成和当前蓄热量相关的非线性函数。这个细节在写论文时可以放进模型描述的假设部分说明你已经认识了简化边界审稿人对这类细节通常比较有好感。6.2 ORC冷凝温度与并网友好性ORC机组的并网友好性常常被忽略。ORC发电机的并网条件、无功调节能力在不同品牌之间差异很大但在调度模型里一般只看有功出力。有一类实际问题如果电网电压偏高ORC可能会被限制出力此时模型里的“ORC满发计划”就无法执行。解决做法是在调度模型里给ORC的出力上限加一个随节点电压变化的修正系数或者至少留一个出力备用率比如上限乘以0.95。这个系数虽然会损失一点经济性但换来的是调度计划的可执行性。6.3 P2G产物的去向建模全进储气罐还是直接进入天然气管网P2G制出的合成天然气可能有两种去向一种是在园区内部就地储存储备另一种是直接升压后注入市政天然气管网。后者在模型里其实可以简化成“气功率外售”但要注意压力和组分约束因为合成天然气的热值通常在8.5~10.5 kWh/Nm³之间和天然气不完全一致混入管网的比例通常不能超过5%~10%。综合能源系统文献里大多回避这个问题直接假设合成气可以任意比例混入天然气网络在实际项目中这会让燃气公司非常紧张。做工程落地时我建议把“P2G产气混入管网比例上限”写成一个参数哪怕初算时先设成10%也比你完全不考虑要好得多否则后面被燃气公司质询时拿不出依据。6.4 从日前调度走向滚动修正与实时控制这套模型本质上是日前调度day-ahead scheduling时间尺度是1小时但真正运行中光伏、风电的预测误差、负荷波动都需要更短时间的调整。一个常见的扩展路线是先用本文模型生成日前计划再在日内每15分钟或5分钟用MPC模型预测控制做一个滚动修正修正时把日前计划的设备出力作为参考值目标函数里加一个偏离惩罚项。这样既保留了日前优化对全局经济性的把握又能应对实时的预测误差。用YALMIP做滚动修正也非常方便只需要把时间区间从24改成9615分钟粒度在每次优化时更新最新的预测数据然后只执行第一个时间步的控制指令即可。需要注意的是时间粒度细化后爬坡约束的表达式要相应调整不能让求解器误以为15分钟就能执行原来1小时才允许完成的爬坡量。6.5 代码里建议写清楚的参数注释与模块划分最后还是想建议一句这类型号的调度模型变量和约束数量动辄几百上千代码写到最后自己都会忘。我现在的习惯是每个设备一个函数文件比如csp_model.m负责返回光热相关的所有约束和参数orc_model.m负责返回ORC的约束主文件只负责拼装和求解。这样以后换一组成数据只改参数文件不用动约束逻辑。另外所有单位在注释里统一标注电功率一律MW热功率一律MWt或者MWth气功率也统一成MW。单位不统一是这类模型最常见却最难排查的bug来源。比如你从某篇文献抄来效率0.45但它可能是“kWh电/kWh气”的效率而你模型里P2G耗电是MW、产气是m³/h换算系数少乘一个3.6整个结果就偏得离谱。我的做法是在参数文件顶部专门加一个unit_check()函数把所有参数的单位和量级打印出来肉眼过一遍看起来笨拙但真能省下大量调bug的时间。这套模型还有一个很大的扩展空间如果把多个园区连接起来让储气罐和储热罐共享问题就变成多主体博弈求解从单层优化变成双层优化或分布式优化如果你再引入不确定性把光伏、风电、电价都当成随机变量模型就升级成随机规划或分布鲁棒优化计算量再上一个台阶。但不管怎么扩展设备建模和基础约束框架都和本文这套一脉相承把这版跑通、看懂、能改后面做复杂模型就有了一个非常可靠的地基。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门