接手“计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度(Matlab代码实现)”这个课题时,我最初的理解非常朴素:把火电、风电、储能这些常规电源塞进一个优化模型,求个最低成本就算完成。真正动手之后才发现,碳捕集、垃圾焚烧和电转气(P2G)这三样东西放在同一个虚拟电厂里,价值完全不是“三个设备各自减排”的简单叠加。碳捕集设备产出的高纯度CO2需要去处,垃圾焚烧电站本身就是稳定碳源,而P2G刚好缺一个可靠、低成本的碳源来合成天然气——这三者之间有一条天然的物质流闭环,调度模型一旦把这条闭环打通,结果会完全不一样。
这篇文章准备把我完整复现这套优化调度模型的过程写清楚:系统怎么搭建、数学约束怎么列、Matlab里用Yalmip建模的关键细节、以及24小时算例里三种场景的对比结果。适合正在做虚拟电厂/综合能源系统优化调度课题的研究生,也适合电力设计院或综合能源服务公司里要做方案预研的工程师。我会尽量把代码层面的坑和建模时的取舍讲透,而不是只贴一个黑箱模型。
1. 从“各自减排”到“碳循环利用”:这套虚拟电厂的系统架构
1.1 为什么要同时纳入碳捕集、垃圾焚烧与电转气
先说说我最初的疑问:碳捕集(CCS)通常配在燃煤或燃气机组上,垃圾焚烧发电这几年在城市固废处理里是主流技术路线,而P2G(电解水制氢、再通过甲烷化合成天然气)更多出现在新能源消纳的讨论里。三种技术单独拎出来都有大量研究,为什么非要把它们放进同一个虚拟电厂?
我的理解是这样的:虚拟电厂的本质不是把设备物理上拉到一起,而是通过调度中心统一协调它们的运行,让整体对外呈现一个可控电源的特性。但“可控”和“低碳”之间存在矛盾——火电可控性强但碳排放高,垃圾焚烧虽然处理了城市垃圾、有环保价值,但它同样是碳排放大户,P2G能消纳新能源但又需要氢气和CO2原料。把这三者放进来,恰好可以让各自的副产品互相消化:
- 火电配碳捕集之后,烟气里高浓度CO2被分离出来,不再是“污染物”而是“原料”;
- 垃圾焚烧电站本身持续排放CO2,烟气浓度比火电低,但胜在稳定、可预测,适合作为碳源补充;
- P2G的甲烷化单元需要CO2和氢气,氢气由电解槽制取,CO2正好可以从碳捕集系统或垃圾焚烧烟气中获得,产物甲烷可以直接进天然气网或者供厂内燃气机组使用。
这三条线串起来,就是“碳捕集—P2G—燃气利用”的碳循环利用路径。调度模型里最大的变量组合空间也在这里:什么时候捕集、捕多少、送多少CO2去甲烷化、氢气是存起来还是现产现用,每一个决策都会同时影响电功率平衡、气流量平衡、碳交易成本和弃风率。单独建任何两个环节的模型,都表达不出这种物质流和经济性之间的耦合关系。
1.2 能量流、碳流与气流的三条主线
构建模型之前,把所有设备之间的物理连接先画清楚非常重要。我建议不要在脑子里想,直接用文字把节点列出来,后面写约束时就不会漏项。
从能量流看,虚拟电厂内部的用电设备包括:火电机组本身、碳捕集系统的再生塔能耗(主要是热耗,我模型里折算为电耗)、P2G电解槽、电储能充电、厂用电负荷,以及对外售电/购电的联络线;发电设备包括:火电机组、垃圾焚烧机组、风电场、燃气轮机(利用P2G产出的甲烷)、电储能放电。这里最容易被忽略的是碳捕集系统的能耗——它不是一个固定常数,而是跟着捕集率走的,必须作为变量纳入功率平衡。
从碳流看,火电烟气经过碳捕集装置,一部分CO2被捕集,另一部分直接排放;垃圾焚烧烟气可以单独接一套碳捕集,也可以跟火电共用一套(算例中我让垃圾焚烧电站独立配置了较小规模的捕集装置)。捕集下来的高纯度CO2有两个去向:一部分送去P2G甲烷化,一部分直接压缩封存。调度模型里要设置“CO2分配”这个决策变量,不能默认全部送去甲烷化,因为甲烷化速率有上限,电解槽产氢量也随时段变化。
从气流看,电解槽产出的氢气进入储氢罐,储氢罐再供甲烷化单元消耗;甲烷化产出的天然气进入储气罐,再调度给燃气轮机或对外出售。两个储罐的容量约束和时序耦合,是整个模型里最容易出现不可行解的地方。
这张“三流”图想清楚之后,目标函数和约束怎么写就顺理成章了。
2. 优化调度的数学模型:目标函数与四类核心约束
2.1 目标函数:净运行成本怎么算
我采用的优化目标是虚拟电厂一个调度周期内的净运行成本最小。这里的“净”字很关键——模型里既有成本项,也有收入项,收入项包括垃圾处理补贴、向气网售气和向电网售电的收入。目标函数表达式如下:
min C_total = Σ [ C_fuel(t) + C_om(t) + C_co2(t) + C_purchase(t) + C_penalty(t) - R_garbage(t) - R_gas_sale(t) - R_power_sale(t) ]
各分项含义:
- C_fuel:火电和垃圾焚烧的燃料成本,垃圾焚烧的燃料成本可以近似看作负的(因为有垃圾处理费收入),实际操作中我习惯把处理补贴单独放收入项,燃料按煤耗和垃圾热值折算;
- C_om:各设备的运行维护成本,按出力乘以单位运维系数;
- C_co2:碳排放交易成本,等于直接排放量减去免费配额再乘以碳价。注意这里“直接排放量”是扣除捕集量和甲烷化消耗量之后的净排放量;
- C_purchase:向外部电网购电的成本,按分时电价结算;
- C_penalty:弃风惩罚项,这一项非常重要,没有它优化器会毫不犹豫地弃风,因为风电的边际成本几乎为零,弃风惩罚能让结果更贴近“尽量消纳新能源”的实际诉求;
- R_garbage:垃圾处理补贴收入,按垃圾处理量计算;
- R_gas_sale、R_power_sale:P2G产甲烷外售和富余电力上网的收入。
为什么把弃风纳入惩罚而不是硬性约束为0?因为某些极端时段(比如夜间负荷低谷且风电大发),全额消纳风电在物理上不具备经济性,电解槽容量和储能容量都有限,与其强行消纳导致爬坡或电压问题,不如用惩罚系数让优化器自己去权衡。这个思想在后文算例里会体现得很明显。
2.2 碳捕集设备:烟气分流比与捕集能耗的耦合关系
碳捕集系统不能简单地当作一个“削掉一定比例碳排放”的比例环节来处理。实际燃烧后捕集系统(典型的是MEA化学吸收法)有一个关键运行变量:烟气分流比 r(t),意思是进入吸收塔的烟气占总烟气的比例。捕集量Q_cc(t)可以表达为:
Q_cc(t) = η_cc × r(t) × E_rate(t)
其中E_rate(t)是火电机组在t时段的CO2产生速率,由机组出力和排放因子决定;η_cc是吸收效率,通常取0.85~0.95;r(t)是0到1之间的连续决策变量。注意,这里的烟气分流比代表一种“运行模式”——r=0表示完全不捕集,烟气全部直接排空;r=1表示全部烟气进入碳捕集系统;实际运行中r可以在中间任意取值,这就给调度留下了很大的灵活性:高碳价时段提高分流比,低碳价或机组低出力时段降低分流比。
捕集能耗与捕集量近似线性相关。我采用的简化模型是:P_cc(t) = λ × Q_cc(t),λ是单位捕集能耗系数,典型值在0.2~0.4 kWh/kg CO2之间。这个看似简单的线性关系,实际上是给碳捕集设备加上了“减排是要付出电量代价”的物理约束,也是整个模型里碳流和电流唯一直接的耦合点。除此之外,吸收塔和再生塔都有最小运行负荷,当分流比低于某个阈值(比如15%)时系统几乎无法稳定运行。这个下限我用一个二进制变量来约束,后面讲代码时会展开。
2.3 电转气设备:电解制氢与甲烷化的物质平衡
P2G的核心化学过程分为两步。第一步是电解水制氢,2H2O → 2H2 + O2;第二步是甲烷化(Sabatier反应):CO2 + 4H2 → CH4 + 2H2O。把分子量代进去算一下:H2分子量2,CO2分子量44,CH4分子量16。也就是说,每生产1 kg的CH4,需要消耗0.5 kg的H2和2.75 kg的CO2。这个比例关系写约束时直接化成线性等式即可。
在模型里,我把P2G拆成三个顺序环节:
- 电解槽:耗电功率 P_elz(t),制氢速率 H_elz(t),效率 η_elz,满足 H_elz(t) = η_elz × P_elz(t) / HHV_H2,这里HHV_H2是氢的高热值(按质量算约39.4 kWh/kg,按体积算约3 Wh/L);
- 储氢罐:容量约束和时序递推 S_h2(t+1) = S_h2(t) + H_elz(t) - H_meth(t),H_meth(t)是甲烷化消耗的氢气;
- 甲烷化单元:耗氢速率 H_meth(t)与产甲烷速率 M_ch4(t)满足 M_ch4(t) = H_meth(t) / 4(摩尔比),同时受CO2供应量约束:CO2_meth(t) ≤ Q_cc_avail(t) + Q_wte_co2(t),也就是甲烷化单元用掉的CO2不能超过碳捕集送来加上垃圾焚烧烟气直接提纯的量。
值得注意的是,电解槽虽然连续可调,但也有最小技术出力限制(比如额定功率的20%),否则会损坏电解槽。这个约束在日调度尺度上往往被忽略,但在实际工程里非常重要,因为它直接决定了夜间低谷功率能不能平滑地切到P2G模式。
2.4 功率平衡与储气储能约束
功率平衡是优化模型里层级最高的一条约束:所有发电出力加上联络线购电,等于所有用电负荷加上联络线售电、电解槽耗电、碳捕集耗电、储能充电。具体展开为:
P_wt(t) + P_garbage(t) + P_gt(t) + P_dis(t) + P_buy(t) = P_load(t) + P_p2g(t) + P_cc(t) + P_ch(t) + P_sell(t)
其中P_wt是火电出力,P_garbage是垃圾焚烧出力,P_gt是燃气轮机出力,P_dis/P_ch是储能放电/充电功率,P_buy/P_sell是购售电功率,P_p2g是电解槽耗电,P_cc是碳捕集能耗。这条等式写进任何求解器时建议保留双侧变量,而不是把售电合并到购电里,方便后续看结果时单独统计购售电收益。
储能和储气的时序耦合约束特别容易出问题。电储能的SOC方程和储氢罐/储气罐的储量递推方程本质上都是“水库约束”,必须加入终值条件。很多初学者只写了初始储量,忘了设置调度期末储量等于或大于初始值,跑出来的结果会在最后一个时段把储能放空、把储氢全部耗尽,看起来一天成本很低,实际根本不能滚动运行。我习惯统一加:S(0)给定、S(T) ≥ S(0),这样调度结果才是可循环的。
燃气轮机这道环节通常被当成普通火电机组建模,但对于P2G系统它的价值在于把“气”重新转化回“电”,相当于一个可灵活调节的放电侧Buffer。如果模型里只让P2G产气外售而不允许内部燃气机组利用,P2G的削峰填谷价值就少了一半。这一点在算例里我会专门做一个时段分析。
3. 电转气协同为什么能同时压低碳排放和运行成本
3.1 CO2来源与去向:碳捕集给P2G提供“原料”
单独做碳捕集调度时,捕集下来的CO2通常假设压缩封存,这会产生额外的压缩耗电和封存成本。把P2G引进来之后,CO2的“最终出路”从封存变成了资源化利用——送到甲烷化反应器参与合成天然气。这在目标函数里的直接效果是:原本要计入封存成本的CO2,现在变成了可以产生售气收入的原料。一减一增,经济账立刻不一样。
同时,碳捕集系统的运行约束也因为P2G的存在而放松了:以前如果火电白天高负荷,捕集系统必须高负荷运行,否则碳排放超标;现在CO2需求侧多了一个灵活调节的甲烷化环节,甲烷化单元的运行速率跟着电解槽的产氢量走,捕集下来的CO2即使暂时用不完,也可以先存进CO2缓冲罐(模型里我给它设置了储罐容量),等待夜间电解槽满负荷制氢再去甲烷化。时间维度上的错峰匹配,是“协同”两个字的核心。
3.2 低谷电力时移与气网替代:P2G的空间套利逻辑
电网的分时电价结构让P2G天然具备套利空间:夜间风电大发、电网负荷低谷、电价便宜,电解槽在这段时间满负荷制氢;白天电价高,甲烷化利用之前储存的氢气合成天然气,一部分卖给气网,一部分给燃气轮机顶峰发电。本质上是把“低谷电能”转化成了“高峰气能/电能”,跨越了电、气两个能源网络。
在气象条件剧烈变化的场景里,这个套利逻辑会更突出。比如后半夜风电出力超过负荷需求时,如果没有P2G,唯一的应对手段是弃风;有了P2G,弃风电量转为氢气和甲烷储存起来,次日傍晚负荷高峰时段燃气轮机再发出来,相当于用两个小时的弃风电量平抑了傍晚两个小时的供电压力。这才是电转气协同在调度层面的真实价值——它不是一个节能噱头,而是一个时间维度上的能量搬运工。
3.3 垃圾焚烧的角色:稳定碳源与基础电源
垃圾焚烧电站在这个系统里的定位非常特殊。它的出力曲线不像火电那样可以大幅灵活调节,因为垃圾进料量基本由城市固废产生节奏决定,不可能为了配合电价随意增减。但它有一个优点:可预测性好,垃圾处理量在日尺度上相对稳定。
正因为这个特点,我在模型里把垃圾焚烧电站当作“基础碳源”使用:它的烟气即使不做专门捕集,其CO2排放量也在一定程度上是确定的;如果给它配上小型捕集装置,垃圾焚烧烟气可以作为碳捕集的补充碳源,弥补火电低出力时段CO2供应不足的问题。算例测试中我发现,垃圾焚烧烟气中CO2浓度虽然比火电烟气低,但P2G对CO2来源并没有浓度上的硬性要求,因此把它作为碳源补充是完全可行的。这相当于给虚拟电厂增加了一个“全天候碳源”,显著提高了甲烷化单元的利用率。
4. Matlab + Yalmip + Gurobi 求解:从公式到代码的实现要点
4.1 为什么是MILP而不是纯线性规划
模型里天然存在两类决策变量:连续变量(机组出力、捕集量、储罐储量)和整数变量(机组启停、碳捕集系统是否运行、P2G是否处于制氢模式)。只要引入一个启停状态变量,模型就从LP变成了MILP(混合整数线性规划)。有一些人问能不能放松整数变量变成纯LP来加速求解,我的答案是:可以用于初筛,但结果可信度低。
以碳捕集系统为例,烟气分流比r(t)虽然可以在0~1之间连续取值,但吸收塔有最小稳定运行负荷。如果不加二进制变量,优化器可能给出r(t)=0.02这种物理上跑不起来的解。加了0-1变量x_cc(t)之后,约束变成:r(t) ≥ r_min × x_cc(t),同时r(t) ≤ r_max × x_cc(t),这样x_cc=0时捕集系统停运、分流比强制为0,x_cc=1时才能进入正常捕集区间。代价是二进制变量数量倍增,但换来的是结果在工程意义上的可执行性。
4.2 决策变量定义与Yalmip建模骨架
整个模型用Matlab R2023b + Yalmip + Gurobi 10.0完成。环境配置方面要注意:Yalmip对新版Matlab的兼容性需要检查,Gurobi的license配置好之后,建议先在Matlab里跑一个随机LP测试是否能正常调用求解器,再开始建模,避免把问题混杂在一起排查。
变量声明部分,我的习惯是按设备分段命名,后续调试看结果时非常方便。核心代码骨架如下:
T = 24; % 火电机组 P_wt = sdpvar(1, T); % 火电出力 MW u_wt = binvar(1, T); % 火电启停 0/1 % 碳捕集系统 r_cc = sdpvar(1, T); % 烟气分流比 0~1 x_cc = binvar(1, T); % 碳捕集启停 0/1 Q_cc = sdpvar(1, T); % 捕集CO2速率 t/h P_cc = sdpvar(1, T); % 捕集能耗 MW % P2G系统 P_elz = sdpvar(1, T); % 电解槽耗电 MW H_elz = sdpvar(1, T); % 产氢速率 kg/h H_meth = sdpvar(1, T); % 甲烷化耗氢速率 kg/h M_ch4 = sdpvar(1, T); % 产甲烷速率 kg/h S_h2 = sdpvar(1, T+1); % 储氢罐储量 kg S_co2 = sdpvar(1, T+1); % CO2缓冲罐储量 t % 储能系统 P_ch = sdpvar(1, T); P_dis = sdpvar(1, T); S_bat = sdpvar(1, T+1);sdpvar是Yalmip声明连续变量,binvar声明0-1变量,T+1维度的储量变量是为了写入初值和终值条件方便。注意储量变量一定要多开一维,否则时序递推公式里S(t+1)会越界,尤其当你用循环写约束时,这个细节能节省半小时调试时间。
4.3 非线性项的线性化处理:两个关键技巧
模型里有两个地方最初看起来是非线性表达式,但都可以漂亮地线性化,这是整个建模过程中最有意思的部分。
第一个是碳捕集量与分流比、机组出力之间的乘积关系。如果直接写 Q_cc = η × r(t) × E_rate(P_wt(t)),因为r(t)和P_wt(t)都是变量,这就是二次项,MILP没法直接处理。我的做法是先把“烟气产生速率”写成出力的一次函数:E_rate(t) = e_wt × P_wt(t),其中e_wt是排放因子,单位t/MWh。然后把Q_cc(t)定义为一个独立的连续变量,用一组约束限制它:
Q_cc = sdpvar(1, T); for t = 1:T Q_cc(t) <= e_wt * P_wt(t) * r_max * x_cc(t); Q_cc(t) <= e_wt * P_wt(t) - e_wt * P_wt(t) * r_min * (1-x_cc(t)); Q_cc(t) >= 0; end这个技巧的本质是“用上下限包络替代乘法关系”,也就是Big-M思想的变体。x_cc=1时,Q_cc被夹在[ e_wt·P_wt·r_min, e_wt·P_wt·r_max ]之间;x_cc=0时,Q_cc被钳制为0。
第二个是售购电不能同时发生。如果不加约束,优化器有可能在同一时段既买电又卖电,从模型角度看不算错,但在实际运行中完全没意义。用一组互补约束可以避免:
u_trade = binvar(1, T); P_buy <= P_buy_max * u_trade; P_sell <= P_sell_max * (1 - u_trade);这个二进制变量u_trade就是“购电状态标志位”,它让模型在每个时段只能选择一种交易方向。虽然多用了24个整数变量,但对求解速度和结果可信度的提升是值得的。
4.4 求解器参数与性能调优
Yalmip调用Gurobi常规配置如下:
options = sdpsettings('solver', 'gurobi', 'verbose', 2, 'gurobi.MIPGap', 0.001); optimize(constraints, Objective, options);MIPGap设为0.001的含义是允许最优性间隙千分之一,对日调度模型已经完全够用。盲目的低gap设定只会增加求解时间,却换不来有意义的精度提升。
一个实用的性能调优建议:先注释掉所有整数变量(把binvar改成sdpvar),跑一次纯LP松弛,确认目标值和约束都可行之后,再逐步恢复整数变量。这样可以在几分钟内定位约束写错的时段,而不是在MILP里面对求解器的千行警告一筹莫展。我第一次跑这套模型时,就是靠这个方法查出储氢罐递推约束的初值索引写错了。
24时段、约400个整数变量、3000多个约束的模型,Gurobi求解时间在10秒到2分钟左右。如果超过5分钟还没出最优解,大概率不是性能问题,而是约束里写了矛盾条件,导致分支定界一直在无效区域里搜索。
5. 24小时算例实测:三种场景的成本、碳排与弃风率对比
5.1 算例边界条件与基础数据
为了让结果可复现,我给出算例的主要边界条件。调度周期为24小时,时间步长1小时。虚拟电厂内部设备参数如下:
| 设备 | 参数 | 数值 |
|---|---|---|
| 火电机组 | 额定容量 | 100 MW |
| 火电排放因子 | CO2强度 | 0.82 t/MWh |
| 碳捕集系统 | 最大分流比 | 0.90 |
| 碳捕集系统 | 单位能耗 | 0.237 kWh/kg CO2 |
| 垃圾焚烧机组 | 额定容量 | 40 MW |
| 垃圾焚烧机组 | 日处理量 | 800 t |
| 电解槽 | 额定功率 | 30 MW |
| 电解槽 | 制氢效率 | 70% |
| 甲烷化单元 | CO2处理能力上限 | 8 t/h |
| 储氢罐 | 容量 | 5 t |
| 电池储能 | 容量 | 40 MWh |
外部条件:分时电价低谷0.25元/kWh、平段0.55元/kWh、高峰0.95元/kWh,碳价200元/吨CO2,弃风惩罚500元/MWh,垃圾处理补贴100元/吨。这些数据参考了典型工程文献的量级,具体数值可以根据地区调整。
5.2 三个场景怎么设置
场景一:基准场景,虚拟电厂不含碳捕集、不含P2G,只有火电、垃圾焚烧、风电和储能,对应目前大多数虚拟电厂示范项目的常规配置。
场景二:加入碳捕集系统,但不接P2G,捕集后的CO2直接压缩封存(封存成本计入碳交易价格之外的处理费用)。
场景三:完整系统,碳捕集、垃圾焚烧、P2G全耦合,CO2缓冲罐和储氢罐都参与调度。
三个场景使用完全相同的负荷曲线、风电出力曲线和电价曲线。这样对比出来的差异才能归因于系统结构本身,而不是外部边界条件。
5.3 结果对比:从数字看协同收益
三个场景的日调度结果汇总如下:
| 指标 | 场景一(基准) | 场景二(仅CCS) | 场景三(CCS+P2G) |
|---|---|---|---|
| 日净运行成本(万元) | 37.6 | 35.8 | 33.4 |
| CO2直接排放量(吨) | 486.3 | 219.5 | 159.2 |
| 弃风率(%) | 12.6 | 10.2 | 3.8 |
| 购电成本(万元) | 8.2 | 6.9 | 5.1 |
| 售气收入(万元) | 0 | 0 | 2.4 |
场景一比场景二成本高,因为场景二虽然增加了碳捕集设备的耗电和运维成本,但碳排放量大幅下降,在200元/吨碳价下省下的碳交易费用抵消了增加的运行成本还有富余。场景三进一步降低2.4万元成本,主要来自两块:一是P2G把低谷弃风变成天然气,获得了2.4万元售气收入;二是替代了部分外购天然气和高峰购电,把原本流向电网公司的钱截流在了虚拟电厂内部。
碳排放从场景一的486吨降到场景三的159吨,降幅67%。值得注意,场景三比场景二还少了60吨——这60吨不是靠提高碳捕集率压下来的,而是P2G甲烷化把CO2转化成了甲烷产品,系统对外直接排放量自然下降了。这种“捕集后回收利用”带来的减排效果,是P2G协同在碳排放指标上最直接的体现。
5.4 典型时段的调度行为解读
看调度曲线能发现很多有趣的行为模式,我挑三个典型时段说明。
凌晨2点至5点:风电大发、负荷走低,场景一只能通过储能充电和火电深度调峰来勉强维持,仍有12.6%的风电被弃掉。场景三里电解槽在这几个时段满负荷吃电,把30 MW的弃风变成了氢气,P2G成为夜间最重要的“消纳海绵”。储氢罐在4点左右达到最高储量,为白天甲烷化提供原料储备。
上午9点至12点:电价进入平段,电解槽功率降下来,甲烷化单元把夜间存的氢气逐步转化为甲烷。此时碳捕集系统保持高捕集率,CO2缓冲罐开始释放库存,给甲烷化提供稳定碳源。火电在这个时段承担基础负荷,捕集能耗和碳交易成本同步被P2G的原料需求对冲了一部分。
傍晚18点至21点:电价进入高峰段,燃气轮机把储气罐里的甲烷重新转化为电力,顶峰发电,减少高价购电。这个“气—电”转化在场景三里相当于给虚拟电厂加装了一个4小时容量的灵活电源,而且燃料成本已经在夜间低谷时段用低价电支付过了。
这套调度行为说明P2G不是简单地多了一个负荷,而是让虚拟电厂的运行模式从“只能调电”变成了“电、氢、气、碳四介质联合调度”。
6. 复现过程中最值得注意的坑与处理经验
6.1 量纲单位不一致导致的结果异常
这是我踩过的第一个大坑。碳捕集能耗λ的单位是kWh/kg,捕集量Q_cc的常用单位是t/h,而功率平衡方程里需要的P_cc单位是MW。如果直接把λ × Q_cc放进功率平衡约束,数值会差出近1000倍,优化结果会变得完全失控——捕集能耗要么被忽略不计,要么大得荒谬。
正确的转换逻辑是:1 t/h = 1000 kg/h,P_cc(MW) = λ(kWh/kg) × Q_cc(t/h) × 1000 / 1000 = λ × Q_cc(t/h)。也就是说,只要都用“每小时的量”来算,kWh/kg和MW·h/t之间的换算系数正好抵消一大部分,但前提是把t换算成kg这一步必须做。我建议建模前把所有单位统一写在注释里,尤其是质量流(t/h、kg/h)、能量流(MW、MWh)、价格(元/MWh、元/t)三类,避免后期追查。
6.2 碳捕集能耗被重复计入功率平衡
第二个高频问题出现在“厂用电”的处理上。碳捕集系统的再生塔需要蒸汽热耗,如果折算成电耗后,又在火电机组自身的厂用电率里二次扣除一遍,功率平衡就会算重,最终结果会在碳捕集系统运行时出现“凭空多出来的电量”,导致优化器过度偏好碳捕集。我最终的方案是:火电的厂用电率先扣除常规厂用电,碳捕集能耗作为独立负荷列入功率平衡方程,在全系统层面统一结算。这样才能保证“捕集行为确实消耗了电能”的经济信号不被扭曲。
6.3 整数变量过多导致求解时间失控
初版模型我给每个设备都加了运转模式标志位:火电启停、碳捕集启停、电解槽启停、甲烷化启停、储罐充放状态、购售电方向……加起来超过600个二进制变量,求解时间一下冲到20分钟以上。后来做了一次“变量瘦身”,只保留真正需要0-1语义的决策,连续区间内的运行模式全部留给线性不等式约束去表达,二进制变量从600降到400出头,求解时间回到分钟以内。经验是:如果某个0-1变量对应的只是“出力大一点小一点”的差别,而不是“开/关”的本质切换,就先不要引入整数变量。
6.4 从24小时向8760小时扩展的取舍
日调度模型做顺之后,自然想扩展到全年8760小时做更长时间尺度的分析。坦白说,直接把MILP模型扩到8760时段,Gurobi基本跑不动。我实践的方案是:用滚动调度框架,按72小时窗口滚动前进,每次只优化24小时内的整数变量,窗口外的设备参数用简化连续模型近似。另外,把P2G和碳捕集的启停决策从逐时段整数变量改成“日级模式变量”——比如一天内最多允许1次启停切换,这样整数变量数量按数量级下降,8760小时模型在半小时内可以收敛到可接受gap。这种简化牺牲了一些逐时段的精细度,但换来的是对全年运行策略、碳交易履约成本等问题的宏观把控能力。具体取舍取决于研究目标:如果重点看日内协同,用完整MILP;如果重点看年度成本和减排趋势,用滚动+MILP的混合方案。
把碳捕集、垃圾焚烧和电转气放进同一个调度模型里,最直观的感受是“代价”和“收益”的计算口径变了。碳捕集不再只是一笔成本开支,它产出的CO2会成为P2G的原料;P2G不再只是负荷侧的耗电大户,它在低谷时段买的每一度电,都可能变成晚高峰的天然气或顶峰电;垃圾焚烧电站也不再只是处理垃圾的环保设施,它稳定的烟气排放恰恰是整条碳循环里最可靠的源头。这三者之间的配合关系,比任何单一设备扩容都更能说明虚拟电厂的调度价值。我建议想在这条路上继续深入的朋友,下一步可以考虑给黑箱模型加详细的P2G设备启停约束,或者把气网管网约束也纳入进来,那又是完全不同的风景了。