ARTICLE DETAIL

资讯详情

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

碳捕集与电转气协同的虚拟电厂优化调度复现及MATLAB实现

碳捕集与电转气协同的虚拟电厂优化调度复现及MATLAB实现 1. 项目概述与实际意义1.1 垃圾焚烧电厂为什么要引入电转气和碳捕集先说结论这个复现程序解决的是一个非常典型的双碳背景问题——垃圾焚烧发电厂虽然是城市固废处理的主力但它的碳排放强度并不低。烟气里的二氧化碳不能直接排掉而碳捕集装置恰恰能把这部分碳“抓回来”。抓回来的碳往哪放电转气Power to Gas, P2G工艺里的甲烷化反应正好要消耗二氧化碳。于是“垃圾焚烧发电 碳捕集 电转气”这三者就形成了一条天然的碳-电-气闭环链。我在复现这个程序之前一直觉得虚拟电厂VPP就是个聚合源荷储、参与电网互动的软件系统。但真正把碳捕集和电转气放进同一个优化框架里之后才意识到这套东西的难点根本不在调度策略本身而在于怎么把电、气、碳三种物理量统一到一个优化模型里。程序的本质是做24小时优化调度目标函数是运行成本最小化决策内容是每个时刻焚烧机组出力、捕集能耗、P2G输入功率、储气罐充放气量以及与外部电网的交换功率。输出则是各设备的功率曲线、二氧化碳捕集量与消耗量曲线、以及总成本和碳排放量的统计结果。适合谁看两类人。一类是正在做虚拟电厂、综合能源系统或碳捕集协同优化方向的硕士博士需要复现论文做对比实验另一类是做工程可行性分析的人想快速知道碳捕集P2G这套组合在一个实际垃圾焚烧项目里是否划算。两者的关注点完全不同但好在程序把机理和经济性放在同一个框架下都能回答。1.2 程序复现的整体架构与模块划分拿到这个题目时我第一反应是找原始论文里的数据。但网上常见版本多数只给了模型公式程序要么加密要么残缺所以复现最重要的不是“让程序跑起来”而是理解每一步为什么要这么建模。我的架构划分方式是四层基础数据层24小时分时电价、垃圾供应量曲线、光照或风电出力曲线如果VPP里含可再生能源、设备参数、碳价参数。机理模型层焚烧锅炉的出力模型、碳捕集装置的电耗模型、P2G两阶段转换模型、储气罐动态模型。优化模型层决策变量定义、目标函数、约束条件、线性化处理。结果展示层功率平衡图、捕集量消纳图、SOC曲线、成本与碳减排对比表。实际编码时我发现一个规律如果你把机理模型层的参数写对了后面的优化层根本不需要什么高级算法一个MILP求解器稳稳地出结果。但如果机理参数写错了比如P2G的二氧化碳消耗系数搞反了模型仍然能“成功求解”但结果就是物理上不可能出现的垃圾数据。这一点我在后面会详细讲。2. 核心数学模型电转气与碳捕集的耦合关系2.1 电转气两阶段过程的数学表达电转气并不是一个“电进去、天然气出来”的黑箱。从机理上它分两步第一步是电解水制氢消耗电能把水分解成氢气和氧气。这一步我用一个线性效率关系表达P_H2 η_el × P_P2G其中 P_P2G 是输入电功率η_el 是电解效率一般在 70-80% 之间。P_H2 是氢气化学功率不是氢气的质量流量。这里我习惯统一折算成功率或者统一折算成热量避免出现“kW”和“Nm³/h”混用后量纲混乱。第二步是甲烷化反应CO2 4H2 → CH4 2H2O。这一步最大的价值在于它把二氧化碳变成了原料。甲烷化效率 η_m 一般在 75-85% 之间于是P_CH4 η_m × P_H2两步串联综合效率就是二者相乘。举例电解效率 0.75甲烷化效率 0.8综合效率就是 0.6意味着 1 kW·h 电能最终只能转化为 0.6 kW·h 的天然气热能。更关键的是第二步的化学计量关系。根据反应方程式每生成 1 kmol 甲烷需要消耗 1 kmol 二氧化碳。换算成质量1 Nm³ 甲烷约 0.717 kg大约需要消耗 1.96 kg 二氧化碳。这是建模时最容易出错的地方很多人用效率算完了产气量却忘了同时算二氧化碳消耗量导致碳平衡约束永远不闭合。我在程序里用的是简化线性关系m_CO2_P2G β × P_CH4β 取约 1.96/9.5 ≈ 0.206 kg CO2/kWh因为 1 Nm³ 甲烷低位热值约 9.5 kWh。这样二氧化碳消耗量就直接与产气功率挂钩不需要额外引入气体质量流量变量模型保持线性。2.2 碳捕集装置的电耗与净出力耦合碳捕集不是白干活的它最大的代价是能耗。燃烧后捕集工艺中吸收剂再生需要消耗大量蒸汽和电力折算成统一的电功率后捕集系统相当于一个“电老虎”。我建模时用捕集单位二氧化碳的电耗系数 δ 来表示P_CCS δ × m_CO2_captureδ 的典型值范围在 80-150 kWh/tCO2 之间取决于你假设的是化学吸收法还是膜分离法。这里有个很关键的耦合约束垃圾焚烧电厂的“毛出力”与“净上网出力”不再是一回事。毛出力 P_g 送往母线的电量中必须先扣掉碳捕集装置的耗电P_net P_g - P_CCS而垃圾焚烧机组本身有个出力波动特性——它要跟随垃圾供应量不能像燃气轮机那样随意爬坡。焚烧炉温度稳定性和垃圾热值波动决定了机组的最小技术出力通常不能低于额定功率的 60%这个约束在纯燃气电厂里不常见但在垃圾焚烧场景里非常关键直接影响到低谷时段P2G的用能安排。需要注意的是碳捕集的能耗在数学上是一个线性项但它在物理上会让电厂的“最大可上网电量”下降。这也意味着如果谷电时段为了给P2G供电去买高价电捕集系统再去分一杯羹账就算不过来了。因此优化程序必须自动权衡这些相互冲突的用电路径。2.3 虚拟电厂整体调度模型的目标函数把上面的模块全部放进一个VPP调度模型后目标函数采用典型的日运行成本最小化形式min Σ C_buy × P_buy - C_sell × P_sell C_fuel C_OM C_co2 C_net逐项拆开C_buy × P_buy向电网购电成本分时电价下低谷时段很便宜这为P2G在夜间运行提供了经济空间。C_sell × P_sell向电网售电收益。C_fuel垃圾处理相关成本我按每吨垃圾的处理费计算这部分其实是电厂收入来源垃圾处理费补贴所以通常取负值。C_OM设备运维成本对焚烧机组、碳捕集、P2G分别乘以单位电量维护系数。C_co2碳排放成本与碳收益的组合。如果总排放超过配额需要购买碳配额形成成本如果捕集后封存的碳被认定负排放则按CCER价格计入收益。这个双向机制决定了碳捕集P2G是不是划算。C_net储气罐、储氢罐的启停损耗通常很小可以并入运维成本。追求目标函数“最小”本质上就是在不同时刻选择电能的最佳流向——是卖给电网、送给P2G、还是送给碳捕集系统。每一千瓦时电能的机会成本不同这正是优化调度发挥价值的地方。3. 优化调度求解流程与算例设计3.1 决策变量与约束清单具体到MATLAB程序实现我把决策变量按时间维度建成长度为24的向量方便用Yalmip的sdpvar直接定义。核心决策变量清单如下变量含义单位P_g(t)焚烧机组毛出力MWP_CCS(t)碳捕集系统耗电功率MWP_P2G(t)电转气系统输入功率MWP_buy(t) / P_sell(t)与外网交换功率MWV_sto(t)储气罐当前储量Nm³m_capture(t)CO2捕集质量流量t/hm_P2G(t)P2G消耗CO2质量流量t/hm_seq(t)封存CO2质量流量t/h约束条件分成四组缺一不可第一组是母线功率平衡约束。所有发电与耗电设备在每一时刻必须满足进等于出P_g P_buy P_CCS P_P2G P_load P_sell注意P_load代表厂用电与对外供电的净负荷。如果VPP里还有风电光伏P_wind也必须加在等式左侧。第二组是机组运行约束。焚烧机组出力上下限、爬坡约束、最低出力约束。垃圾焚烧机组因为炉膛热惯性大爬坡速率通常只允许每分钟1%-3%额定功率换算到小时尺度就是比较大的“软约束”但对日调度来说仍然可能限制夜间与午间的转换速度。第三组是碳捕集与P2G的耦合约束。捕集的CO2总量一部分去甲烷化一部分去封存m_capture m_P2G m_seq同时捕集量不能超过捕集系统容量P2G消耗量有个上限这保证了设备不会同时在满负荷和冷却状态之间疯狂切换。第四组是储气罐动态约束。储气量等于上一时刻储气量加上产气量减去用气量V_sto(t1) V_sto(t) V_prod(t) - V_use(t)并加上容量上下限约束。储气罐的存在让P2G具备了“时间平移”能力低谷产气高峰用气这是整个协同系统经济性的突围口。3.2 Yalmip Cplex求解MILP的完整流程模型里的设备效率都是用固定系数表达的不存在变量乘积所以这是一个标准的混合整数线性规划MILP问题。只有储气罐的充放状态和机组启停需要二进制变量其他全是连续变量。我在MATLAB里的求解流程是标准的Yalmip三段式。先定义变量再写目标函数和约束最后调用优化器求解。Cplex在这个问题规模下非常轻松24个时段的变量量级不过几百个求解时间通常在一秒以内。不过有一点要提醒如果未来你往模型里加入“储氢罐压力与压缩机流量”的关系就不再是线性关系了必须引入分段线性化或者额外整数变量。我这次复现刻意保持全线性因为VPP调度的核心价值在于说明“协同逻辑”而不是在非线性细节里打转。等你把线性版本跑通再逐步加复杂度也不迟。3.3 典型算例参数设置为了让仿真结果有参考价值我设置了一个典型的日调度场景。垃圾焚烧电厂额定功率30MW日处理垃圾1200吨分时电价采用北方某城市的峰谷三段式。P2G系统额定功率15MW综合效率60%。碳捕集系统额定捕集量约5 t/h捕集电耗100 kWh/tCO2。储气罐容量3000 Nm³。具体参数整理如下表参数取值备注焚烧机组额定功率30 MW最低出力60%日垃圾处理量1200 t/d折算产电约28.8 MWhP2G额定功率15 MW综合效率60%P2G耗CO2系数0.206 t/MWh按甲烷化计量关系碳捕集电耗100 kWh/tCO2燃烧后化学吸收法碳捕集率上限90%工业装置典型值碳价80 CNY/t含封存收益储气罐容量3000 Nm³初始储量50%分时电价我按峰平谷分别取1.0、0.55、0.3元/kWh峰段9:00-12:00与17:00-21:00谷段23:00-次日7:00。这个电价结构对P2G特别友好因为夜间的谷电价格只有高峰的三分之一足够在24小时内跑出“谷电产气、峰时售气或发电”的套利逻辑。4. MATLAB核心代码实现与关键踩坑记录4.1 变量定义与约束写入的代码骨架我在Yalmip里的变量定义方式如下。先定义24个时段的连续决策变量n 24; P_g sdpvar(1, n); % 焚烧机组毛出力 P_CCS sdpvar(1, n); % 碳捕集耗电 P_P2G sdpvar(1, n); % 电转气输入电功率 P_buy sdpvar(1, n); % 购电功率 P_sell sdpvar(1, n); % 售电功率 m_capture sdpvar(1, n); % CO2捕集量 t/h m_P2G sdpvar(1, n); % P2G消耗CO2量 t/h m_seq sdpvar(1, n); % 封存量 t/h V_sto sdpvar(1, n); % 储气罐储量变量定义之后约束写入的要点是按照“先物理耦合、再运行边界、最后功率平衡”的顺序分组加进约束集合。C []; % 碳捕集与P2G之间的碳流平衡 C [C, m_capture m_P2G m_seq]; % P2G耗CO2量与产物之间的计量关系 C [C, m_P2G 0.206 * P_P2G * 0.6]; % 母线功率平衡 C [C, P_g P_buy P_CCS P_P2G P_load P_sell];这里有一个关键点很多新手会把 m_P2G 与 P_P2G 的关系写成“m_P2G k * P_P2G”但忘记乘以P2G的综合效率。实际化学反应中二氧化碳消耗量取决于产物甲烷量而产物量是输入电功率乘以效率得到的。少乘这个效率P2G的耗碳量就会虚高20%以上整个碳平衡结果就是错的。目标函数写起来最要注意的是分时电价的向量化操作。电价向量的长度是24购电成本和售电收益直接用向量点乘objective sum(price_buy .* P_buy) - sum(price_sell .* P_sell) ... sum(0.02 .* P_g) ... % 机组运维成本 carbon_price * (sum(E_total) - E_quota) ... % 碳配额成本 - carbon_subsidy * sum(m_seq); % 封存碳收益optimize调用则是一行optimize(C, objective, sdpsettings(solver, cplex, verbose, 2));求解结果出来后我习惯先验证一下碳平衡是否闭合再去做结果图。这一条简单却极其重要。4.2 求解器选择与数值鲁棒性调优我在这类优化调度问题上首选Cplex其次Gurobi。Cplex在线性规划求解上稳定性非常好Yalmip调用也很成熟。不过Cplex也有个烦人的地方就是License。如果你没有装完整版可以考虑换成Gurobi或免费的SCIP、GLPK但GLPK处理MILP的能力偏弱算稍大问题时会明显变慢。数值鲁棒性是另一个值得说的坑。我的设备参数有些以小时为单位有些以秒为单位混合起来数值尺度差距很大Cplex迭代时经常出现数值警告。解决办法很简单——对变量做标幺化处理。把所有功率除以基准值我是100MW气体储量除以基准容积电价除以基准电价。标幺化之后所有约束矩阵的系数都落在0.001到1000之间求解速度和稳定性都有明显提升。一个更隐蔽的问题是储气罐储量的单位换算。如果我P2G产气量用Nm³计算储气罐储量也用Nm³那没问题。但如果P2G用热量MWh表达产气量而储气罐用体积Nm³表达中间必须有热值换算系数。我最初写代码时在这里漏了一步导致储气罐SOC曲线疯狂震荡但目标函数照样收敛了。这是个典型的“物理单位不一致但数学可求解”的隐性错误单看结果根本发现不了。我现在的做法是写模型之前先在纸上把所有变量的单位统一成一套体系代码里每个变量的注释都标明单位结算后再手动验证一次关键数据。4.3 仿真结果可视化的绘图要点结果可视化是程序复现里“性价比”最高的部分。一张好的功率分配图比一万字描述更有说服力。我推荐用双层绘图第一层画功率平衡图用面积图stackedplot展示每个时刻的购电、焚烧出力、风/光出力、P2G消耗、碳捕集消耗、负荷供应的叠加关系。这样一眼能看出电能从哪儿来到哪儿去。第二层画碳流图左右两个堆叠柱状图左边是CO2捕集量的去向分配P2G消耗 vs 封存右边是CO2的来源垃圾焚烧、外购、可再生能源抵消中间用连线连起来。MATLAB实现大致这样figure; subplot(2,1,1); area(t_hours, [P_buy; P_g; P_wind; -P_CCS; -P_P2G; -P_sell]); legend(购电, 焚烧, 风电, 捕集耗电, P2G耗电, 售电);关键在于负值耗电设备也用面积图展示方向不同不会影响可读性反而让“汇”和“源”的流动路径看得更清楚。如果只用折线图所有曲线叠加在一起基本没法分辨。5. 仿真结果三种场景的对比与逻辑解读5.1 场景设置无协同、半协同、完全协同为了单独展示电转气和碳捕集的贡献我做了A、B、C三组对比仿真。场景A常规垃圾焚烧电厂无碳捕集、无P2G排放全部计入碳成本。场景B加装碳捕集但未接入P2G捕集到的CO2全部封存。场景C碳捕集P2G协同运行捕集CO2一部分用于甲烷化剩余封存。这样做的目的是把两个设备的价值拆开算账。B和C的差别就是P2G带来的增量收益A和B的差别就是碳捕集单独运行的经济性。5.2 优化结果的功率平衡与碳流分析场景C下优化结果呈现出典型的“三个时段三种状态”模式夜间谷电时段23:00-7:00外部电网购电价格极低P2G系统满负荷运行输入功率约12-14MW。焚烧机组保持最低技术出力运行白天储存的垃圾热量在夜间持续释放碳捕集装置同步运行捕集来的CO2大量送入甲烷化反应器。白天峰电时段9:00-12:0017:00-21:00电价高P2G降载或停机储气罐里的天然气被用于燃烧发电或外售发电机组尽可能高负荷运行。碳捕集装置在峰段仍然运行但因为捕集电耗降低了净上网功率优化程序会自动权衡“少卖一度电”与“减排一吨碳”哪个更划算。平段时段其他时间系统处于中间状态P2G可能以较低功率运行储气罐进行动态调整碳捕集率跟随碳价和电价的相对关系小幅波动。碳流分析则显示场景C中大约55%-65%的捕集CO2被P2G甲烷化利用其余封存。P2G消耗的碳量完全由自身烟气提供不需要外购CO2碳自给率约100%这是协同路径最大的优势。5.3 经济性与碳排放量综合对比三组场景的经济与碳排结果汇总如下对比项场景A无协同场景B仅捕集场景C捕集P2G日运行净成本基准100%约112%约104%日CO2排放量100%约22%约14%碳捕集利用量0全部封存约40%封存60%利用可再生能源消纳无无谷电时段约30MWh用于P2GP2G产气量00约1800 Nm³场景C的碳排放只有场景A的14%左右成本却仅高出4%。也就是说用户花少量成本换来了超过80%的额外碳减排。这背后的经济动力主要来自两块一是分时电价套利谷电制气、峰时售气创造收入二是碳收益封存的CO2与甲烷化使用的CO2都按特定规则计入减排量直接冲抵了设备运行成本。单独看场景B碳捕集设备确实增加了运行成本如果没有碳价支撑很难单纯靠卖碳回收投资。但补上P2G之后捕集到的CO2不再只是“处理掉”的负担而是“用起来”的原料经济效益和环保效益就形成了一个正循环。这也是虚拟电厂协同调度最值得宣传的一个结论。6. 常见问题与排查技巧实录6.1 Yalmip报错和变量定义失误我用遇到过的典型Yalmip报错来总结第一个是“sdpvar objects cannot be used in logical comparisons”。这是把约束写成了 if 语句或者在约束里用了比较运算符。Yalmip要求约束必须是声明式的不能程序化判断。遇到这种问题要么把条件改成二进制变量加权要么用implies命令建模逻辑关系。我改过一次把储气罐满时不能充电的约束写成了if结果直接在optimize前报错改写成binary big-M之后才通过。第二个是约束赋值时用[]拼接导致约束维度不匹配。特别是写24小时循环约束的时候如果手滑写成了[约束1 约束2]而不是[约束1, 约束2]会出现一个1×48的标量数组而不是约束集合。Yalmip不会立刻报错但求解时会给出空解或警告排查起来非常痛苦。我的经验是统一先初始化C []然后每一行约束用逗号连接最后用optimize前打印length(C)检查约束数量是否与预期一致。6.2 模型不可行的排查顺序模型不可行是复现里最崩溃的错误。Yalmip会给你一个infeasible的通知但不会告诉你哪条约束出了问题。我的排查顺序是固定套路。先检查功率平衡约束确认等式两边维度单位一致。然后逐个约束松开每次从约束集合里剔除一条看问题是否仍然不可行。这个方法虽然笨但在24小时的模型里特别快因为你的约束数量有限。但更常见的是“初始条件没交代清楚导致不可行”。比如储气罐初始储量如果设为0而运行边界又要求终点储量不低于某个值那么模型必须靠全天产量来满足如果储气罐容量不够约束直接不可行。处理办法是给初始储量设一个合理的百分数比如50%并且加一条循环调度约束终点储量回到初始值这样既能保证调度方案的可持续性又避免了边界不可行。6.3 结果异常摆动与参数敏感性还有一种现象比不可行更隐蔽——结果完全可行但曲线剧烈摆动。焚烧机组出力在相邻两个时段从15MW直接跳到30MW再跳回来储气罐SOC在满和空之间疯狂切换。这通常是因为我还在约束条件里加了过于激进的目标比如把封存碳收益的单位价格设置得过高优化器就会为了多拿收益而让捕集装置在满负荷和停机之间摇摆。工程师眼中这是不合理的运行方式但优化器只认收益不认“启停磨损”。解决思路是加“最小运行时间约束”或“设备爬坡约束”。最小运行时间约束属于混合整数约束需要加额外的二进制状态变量和逻辑约束实现起来稍复杂。我在这个程序里采用了更简单的做法给碳捕集装置和P2G各加一个“单时段增减功率上限”默认是额定功率的30%/小时这样曲线的摆动幅度被物理限制住结果也更贴近真实设备的表现。另外有一个参数敏感性技巧分时电价和碳价是最敏感的两个参数。做结果分析时一定要多做几组碳价扫描。你会发现碳价很低时协同场景的经济性只比场景A略差一点点碳价一旦上升到某个阈值协同场景立刻反超。这个阈值就是项目的“减排盈亏平衡点”对投资决策有直接参考价值也是仿真结果展示里最值得单独画图的部分。我在实际运行中发现碳捕集率和碳价的敏感性是非线性的捕集率从70%提到90%成本增幅远大于减排增幅但这个拐点的位置因设备参数而异。你可以把碳捕集率设成一个扫描变量跑10次程序画出“成本-碳排放”的帕累托前沿这会比单纯展示一个优化结果有说服力得多。7. 复现过程的经验小结与后续扩展方向这个程序跑通之后给我最大的感触是这种多能互补协同优化调度的坑90%不在算法而在物理建模的细节。单位换算、效率连乘、碳平衡闭合这几个细节哪一个没检查到结果都会跑偏。可能是我研究周期里踩过最深的一个坑——P2G的CO2消耗系数直接取了论文里的随机数值结果捕集量永远满足不了甲烷化需求模型怎么调都不可行。后来自己从反应方程式一步步推了一遍计量关系才把系数定下来。如果你准备在自己的项目里扩展这个程序我建议从三个方向入手。第一个方向是加入氢能交通负荷P2G的中间产物氢气可以直接供给氢燃料车而不仅仅是全部甲烷化这会让模型增加一个气源分支经济性又会发生变化。第二个方向是在虚拟电厂里加入电动汽车集群的V2G调度这样P2G消耗谷电EV也在谷电充电两者会产生竞争关系很有研究价值。第三个方向是把确定性调度改成两阶段随机优化风电或垃圾热值的不确定性用场景法建模这会显著提升模型的学术价值。但无论怎么扩展前面说的建模纪律始终不变先定义清楚每个变量的物理单位和量纲再写方程所有效率系数要有文献出处或用反算验证约束一次性写完整不要测试“少了某条约束能不能解”这种侥幸心理。我的体会是仿真程序的最终价值不只是输出“系统运行成本降低X%”这样的结论而是让每个读过你代码的人都能理解电转气和碳捕集在垃圾焚烧场景下的协同不是政策催出来的概念它在分时电价和碳价的共同作用下确实存在一条经济可行的运行路径。能把这个逻辑讲清楚这套复现程序就成功了。
返回列表