ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

电转气协同碳捕集与垃圾焚烧的虚拟电厂优化调度MATLAB实现

电转气协同碳捕集与垃圾焚烧的虚拟电厂优化调度MATLAB实现 这两年我自己在虚拟电厂优化调度上写了不少模型之前主要集中在传统火电、储能和新能源的组合直到最近把碳捕集、垃圾焚烧和电转气三个模块揉进同一个框架里才真正体会到“协同”两个字不是随便说说的。这套MATLAB代码做的是计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度说白了就是把垃圾焚烧机组、碳捕集装置、电转气设备、风电光伏和储气储碳设施放在一个优化问题里统一决定每个时段该发多少电、捕多少碳、制多少气、存多少能。刚立项时我也觉得这是不是有点强行拼凑垃圾焚烧和碳捕集各有一堆复杂的物理约束再塞进电转气模型规模和求解难度都会明显上升。但算例结果出来后我发现这三者之间确实存在一条很自然的协同链垃圾焚烧提供连续稳定的电力和蒸汽碳捕集消耗这些能量去抓二氧化碳电转气再在弃风弃光时段把电能和二氧化碳转成天然气储存起来峰时放出来使用。整个过程把“碳”当成了能量载体在时间轴上倒腾最终系统总成本、碳排放和弃电率都有明显改善。这篇文章就把我的建模思路、MATLAB实现和踩坑过程完整梳理一遍给想复现或者做类似项目的人一个能直接参考的框架。1. 单独算账不赚钱放进虚拟电厂里反而能盈利这套组合的逻辑起点很多人一看到“碳捕集”三个字第一反应就是高能耗、高成本。这个印象没错常规胺法碳捕集每捕集一吨二氧化碳电耗加热耗加起来折算能量损失非常可观单独给电厂加一套CCS几乎就是纯花钱的设备。电转气也一样电解水制氢再甲烷化能量转换效率一路打折从电力视角看怎么算都不太经济。但垃圾焚烧电厂的情况不一样。城市生活垃圾每天必须处理焚烧厂通常是连续运行、负荷相对平稳的机组等于一个天然基荷电源。焚烧产生的高温烟气和余热蒸汽恰好分别是碳捕集装置需要的“碳源”和“热源”。一吨生活垃圾焚烧产生的烟气里含有大量CO2浓度比普通燃煤锅炉还更集中这就让碳捕集的单位成本下降不少。电转气设备的角色则更像“能量搬用工”。虚拟电厂里通常还有风电和光伏深夜风电大发、负荷很低的时候如果不消纳就只能弃掉。把弃电送进电解槽制氢再用碳捕集抓下来的CO2完成甲烷化反应就能把原本放弃掉的电能变成天然气存进储罐。天然气可以等到傍晚用电高峰再用燃气轮机发出来或者直接对外出售。这一进一出等于把“时间”纳入了调度决策。这里还有一个容易忽略的点碳捕集系统本身是可调负荷。捕集率调高耗电耗热上升多抓CO2捕集率降下来耗电下降相当于给系统腾出电力空间。电转气用的CO2正好来自捕集系统所以当系统电力富余时P2G可以开大功率多产气同时需要更多CO2原料CCS就跟着提高捕集率电力紧张时P2G降低运行CCS也可以减少捕集把电让给更重要的负荷。这三个设备的运行节奏、碳排放和能量流互相咬合只有放在同一个优化问题中用同一个时间尺度、同一套平衡约束去求解才能把这种互补关系真正用起来。我下面先详细讲每个子系统的数学建模然后给出MATLAB搭配YALMIP的代码框架再用三组算例对比来解释协同效应的来源最后分享几个实际调试模型时非常容易踩的坑。2. 建模第一步把垃圾焚烧、CCS和P2G三个子系统的状态方程写清楚2.1 垃圾焚烧机组它不仅是电源还是整条碳链的起点在虚拟电厂框架里垃圾焚烧机组我习惯用进料量而不是发电功率作为主要决策变量。设第t个时段的垃圾进料量为M(t)单位是吨/小时那么焚烧发电功率可以写成P_w(t) η_w * LHV_w * M(t) / 3.6这里的η_w是焚烧-余热锅炉-汽轮机发电的综合电效率LHV_w是生活垃圾低位热值单位取MJ/kg除以3.6是为了把单位折算成MWh/t。城市生活垃圾的热值通常在6到11 MJ/kg之间电效率大概0.2到0.24所以一台日处理1500吨的焚烧厂额定发电功率也只有30兆瓦左右单看体量很小但胜在稳定。垃圾焚烧的约束里有几个容易遗漏的地方。首先是日处理总量约束城市的垃圾收运量是刚性的每天必须处理掉约定的吨位写成数学约束就是sum(M(t), 1, T) M_daily其次是焚烧炉的燃烧稳定性约束。为了保护炉膛和烟气净化系统进料量不能频繁大范围波动所以有爬坡约束和负荷上下限M_min、M_max。工程上垃圾焚烧机组极少深度调峰模型里我会把出力限制在60%到100%额定负荷之间这样很符合实际。最后是蒸汽耦合。余热锅炉的抽汽量S_ext(t)近似与进料量线性相关S_ext(t) k_w * M(t)这部分蒸汽正好用于碳捕集再生塔的再沸器。在模型中我把蒸汽成本折算进CCS的运行成本不单独建一套热力管网模型因为虚拟电厂层面的调度重点并不在热力学细节而在整个系统的能量流和碳流分配。2.2 碳捕集系统捕集率是核心但千万注意双线性项的坑碳捕集系统的最简模型是焚烧烟气中CO2总流量G_co2(t)正比于垃圾进料量实际捕集量C_cap(t)等于烟气CO2流量乘捕集率δ(t)C_cap(t) δ(t) * G_co2(t)捕集率δ的工程范围一般在0.1到0.9之间。下限不能为零是因为胺法捕集系统有一个运行负荷下限如果液气比失衡吸收塔会出各种问题。捕集系统的耗电E_ccs(t)包括引风机、循环泵和压缩机电耗再加上再沸器蒸汽耗量。为了线性化我写成E_ccs(t) a_ccs * C_cap(t) b_ccs * u_ccs(t)其中u_ccs(t)是0-1变量表示捕集系统是否在线b_ccs是固定功耗。这里要特别提醒一句如果直接把C_cap(t)δ(t)*G_co2(t)写进代码就产生了一个连续变量与连续变量相乘的双线性项模型会从MILP变成MINLP求解难度直线上升还容易陷入局部最优。我在实际代码里不显式引入δ(t)这个变量而是把C_cap(t)直接作为连续决策变量用以下约束来限定C_cap(t) ≤ δ_max * G_co2(t) C_cap(t) ≥ δ_min * G_co2(t) - bigM * (1 - u_ccs(t)) C_cap(t) ≤ bigM * u_ccs(t)这样当u_ccs(t)1时捕集量被限制在最小和最大烟气流量之间当u_ccs(t)0时第二和第三个约束共同把C_cap(t)压到0。整个模型依然是线性约束捕集率δ变成了事后计算出来的结果。捕集下来的CO2不一定马上被电转气用掉所以我加了储碳罐。储碳罐的状态方程是V_co2(t1) V_co2(t) C_cap(t) - U_p2g_co2(t)U_p2g_co2(t)是电转气在t时段消耗的CO2量。加入储碳罐之后CCS和P2G的节奏可以错开夜间捕捉的CO2白天再用也行模型的灵活度显著提高。2.3 电转气系统电解制氢、甲烷化与储气罐的时间平移作用电转气设备从电到天然气的完整链条包括两个环节电解水制氢和甲烷化。电解槽消耗电功率P_p2g(t)产出氢气的能量为H2_energy(t) η_el * P_p2g(t)η_el是电解效率通常在0.65到0.75之间。接下来甲烷化反应把氢气和二氧化碳合成甲烷反应关系简化为4H2 CO2 → CH4 2H2O工程上我不去细算摩尔质量直接用一个总效率η_p2g_total来对应“电力到天然气热功率”的转换H_gas(t) η_p2g_total * P_p2g(t)同时产出的天然气需要消耗一定比例的CO2U_p2g_co2(t) μ_co2 * H_gas(t)μ_co2大约在0.20到0.23 kg/kWh这表示每生产一千瓦时热值的天然气大约需要消耗0.2千克左右的CO2。这样建模的好处是碳循环链条可以在物料平衡里直接体现出来垃圾焚烧烟气里的CO2 → CCS捕集 → 储碳罐 → P2G甲烷化 → 储气罐 → 高峰时段燃机发电。电解槽自身也有运行限制。频繁启停对电解槽寿命有很大影响所以模型加入了最小运行功率P_p2g_min和0-1变量u_p2g(t)避免在低功率下“似开非开”。储气罐的容量和状态方程是V_gas(t1) V_gas(t) H_gas(t) - D_gas(t)D_gas(t)代表对外放气可以是供给燃气轮机发电也可以是外售天然气。我用燃气轮机发电为主算例这相当于把弃电通过碳和氢载体存储在电力负荷高峰再释放这是整套协同机制里最关键的时间平移约束。补充一个重要细节就是初始储能约束。储气罐和储碳罐都必须加上V(1)V(T1)否则优化器会“白嫖”初始储存的能量把账算得过于乐观。这个约束在后面的踩坑章节里我会再次强调。2.4 虚拟电厂全局层功率平衡、备用约束、碳配额与目标函数有了三个子系统的模型最后把它们组装到虚拟电厂层。最基本的约束是每个时段的电功率平衡P_w(t) P_GT(t) P_wind(t) P_pv(t) P_buy(t) P_load(t) P_p2g(t) E_ccs(t) P_sell(t)P_buy(t)是向外部电网购电功率P_sell(t)是向外部电网售电功率。购售电不应该同时大于零模型里我会加入互斥约束避免优化器在同一时段低价买入高价卖出这种投机套利因为它不仅不符合虚拟电厂实际交易规则也会扭曲机组调度结果。碳配额是整个模型的目标驱动力之一。假设虚拟电厂每天获得一定免费碳排放配额E_quota实际净排放量是E_net(t) E_total(t) - C_cap(t)当E_net低于配额时多余的配额可以在碳市场卖出反之需要花钱购买。碳价越高模型越倾向提高捕集率碳价低的时候捕集装置就会降低出力甚至停机。目标函数是日运行总成本最小化总成本 垃圾进料成本 燃机燃料成本 购电成本 - 售电收入 碳交易净支出 CCS运维成本 P2G运维成本 - 垃圾处理补贴这里垃圾处理补贴必须放进目标函数而且权重通常还不小。城市焚烧厂的基本商业模式是“处理费上网电费”如果漏掉处理补贴这一项模型会觉得少烧垃圾更省钱这完全脱离实际。我还加入了系统备用约束让垃圾焚烧机组和燃气轮机在正常出力之外保留一定上调空间防止新能源突降时无法满足负荷。当这些约束全部装配好整个模型就成为一个混合整数线性规划MILP问题。三个子系统之间的耦合关系本质上只是三条线电功率平衡、CO2物料平衡、天然气/氢气储运平衡。只要这三条线没写错最优调度中就会自然出现“弃风时段P2G多产气、高负荷时段储气放气发电、碳价高时CCS提高捕集率”的行为。3. MATLABYALMIP落地参数、变量、约束的代码逐段拆解3.1 数据准备虚构一个园区级虚拟电厂的典型日场景为了验证模型我自己构造了一个园区级虚拟电厂的典型日数据时间粒度为1小时一个调度周期24小时。系统包含一个垃圾焚烧机组、一个额定功率30兆瓦的风电场、20兆瓦光伏、10兆瓦电解槽、配套储气罐和储碳罐负荷曲线模拟一个中型工业园区的用电特征。代码里的基础参数设置大致如下T 24; dt 1; % 负荷、风电、光伏预测曲线虚构典型日单位MW P_load [22 21 20 20 21 24 29 33 35 34 32 30 29 31 34 36 38 40 39 37 34 30 26 23]; P_wind [10 11 9 8 10 6 5 4 3 4 5 6 7 8 10 9 8 8 9 8 7 9 8 7]; P_pv [0 0 0 0 0 0 1 3 5 8 10 11 10 8 6 3 1 0 0 0 0 0 0 0]; % 垃圾焚烧机组参数 M_min 60; M_max 105; M_daily 2000; % 进料上下限及日处理总量, t eta_w 0.22; LHV_w 9.8; % 发电效率与低位热值, MJ/kg ramp_w 30; % 进料爬坡上限, t/h % CCS参数 delta_min 0.1; delta_max 0.9; a_ccs 0.15; b_ccs 0.8; % 电耗系数 MWh/tCO2, MWh k_co2 0.18; % 单位进料烟气CO2量, tCO2/t垃圾 V_co2_max 300; % 储碳罐容量, t % P2G参数 P_p2g_min 1; P_p2g_max 10; % 电解槽功率范围, MW eta_p2g_total 0.55; % 电力到天然气的总效率 mu_co2 0.21; % 单位天然气输出的CO2消耗量, t/MWh V_gas_max 200; % 储气罐折算热功率容量, MWh eta_GT 0.45; % 燃机发电效率 % 电价与碳价 C_buy [0.8*ones(1,8) 1.0*ones(1,8) 1.2*ones(1,4) 1.0*ones(1,4)]; % 分时电价, 元/kWh C_sell 0.85*C_buy; % 上网电价 carbon_price 300; % 碳价元/吨注意所有功率单位统一用MW电量和能量单位统一用MWhCO2质量单位统一用吨碳价单位用元/吨。这种单位的一致性如果没做好很容易出现求解结果莫名其妙的“十倍误差”这也是我后面专门要讲的坑。3.2 决策变量定义哪些是连续量哪些必须用0-1变量在YALMIP中定义决策变量我习惯把连续量和二进制量分开写清楚% 垃圾焚烧与CCS M_feed sdpvar(1,T); % 垃圾进料量, t/h C_cap sdpvar(1,T); % 实际CO2捕集量, t E_ccs sdpvar(1,T); % CCS耗电, MW u_ccs binvar(1,T); % CCS在线状态 % 储碳罐 V_co2 sdpvar(1,T1); % 储碳罐CO2储量, t % P2G与储气 P_p2g sdpvar(1,T); % P2G用电功率, MW H_gas sdpvar(1,T); % 产天然气热功率, MWh/h U_co2 sdpvar(1,T); % P2G消耗CO2量, t V_gas sdpvar(1,T1); % 储气罐储量, MWh热值 u_p2g binvar(1,T); % P2G运行状态 % 燃气轮机与电网交互 P_GT sdpvar(1,T); % 燃气轮机发电功率, MW P_buy sdpvar(1,T); % 购电功率, MW P_sell sdpvar(1,T); % 售电功率, MW z_trade binvar(1,T); % 购售互斥状态可能你会问为什么垃圾焚烧机组不用0-1启停变量因为城市垃圾焚烧电厂在调度周期内通常全程运行不允许随意启停所以只需要设置爬坡和上下限。CCS和P2G则存在明显的小时级启停可能性所以加了在线状态变量。3.3 约束构建功率平衡、碳流耦合与储能状态逐条写入主要约束的代码框架如下我在每条约束后面都加了注释方便对照前文的公式Constraints []; for t 1:T % 垃圾焚烧约束 Constraints [Constraints, M_min M_feed(t) M_max]; P_w(t) eta_w * LHV_w * M_feed(t) / 3.6; % 发电功率折算 % CCS约束 G_co2(t) k_co2 * M_feed(t); % 烟气CO2总流量 Constraints [Constraints, E_ccs(t) a_ccs*C_cap(t) b_ccs*u_ccs(t)]; Constraints [Constraints, C_cap(t) delta_max * G_co2(t)]; Constraints [Constraints, C_cap(t) delta_min*G_co2(t) - 1e3*(1-u_ccs(t))]; Constraints [Constraints, C_cap(t) 1e3*u_ccs(t)]; % 储碳罐状态 Constraints [Constraints, 0 V_co2(t1) V_co2_max]; Constraints [Constraints, V_co2(t1) V_co2(t) C_cap(t) - U_co2(t)]; % P2G约束 Constraints [Constraints, P_p2g_min*u_p2g(t) P_p2g(t) P_p2g_max*u_p2g(t)]; Constraints [Constraints, H_gas(t) eta_p2g_total * P_p2g(t)]; Constraints [Constraints, U_co2(t) mu_co2 * H_gas(t)]; % 储气罐状态 Constraints [Constraints, 0 V_gas(t1) V_gas_max]; Constraints [Constraints, V_gas(t1) V_gas(t) H_gas(t) - D_gas(t)]; % 燃气轮机 Constraints [Constraints, P_GT(t) eta_GT * D_gas(t) * 0.9]; % 留10%裕度 % 功率平衡 Constraints [Constraints, P_w(t)P_wind(t)P_pv(t)P_GT(t)P_buy(t) ... P_load(t)P_p2g(t)E_ccs(t)P_sell(t)]; % 购售互斥 Constraints [Constraints, P_buy(t) 50*z_trade(t)]; Constraints [Constraints, P_sell(t) 50*(1-z_trade(t))]; end % 周期约束 Constraints [Constraints, sum(M_feed) M_daily]; Constraints [Constraints, V_co2(1) V_co2(T1)]; Constraints [Constraints, V_gas(1) V_gas(T1)];有一点要说明代码块里的P_w(t)、G_co2(t)、D_gas(t)这些中间变量需要在循环外先定义为sdpvar我为了精简直接用了赋值语句实际运行时把P_w、G_co2、D_gas先声明成一维sdpvar变量再逐个赋值即可。这条约束写法的本质是把各个子模块的物料平衡和能量平衡在时间轴上拉通只要代码逻辑清晰后面再加扩展模块也方便。3.4 目标函数与求解器配置如何把成本项和收入项放对位置目标函数是最小化系统日运行总成本我的写法如下Objective sum(C_w * M_feed) ... % 垃圾处理运行成本 sum(C_GT * P_GT) ... % 燃气轮机燃料及运维成本 sum(C_buy .* P_buy) ... % 购电成本 - sum(C_sell .* P_sell) ... % 售电收入 carbon_price * sum(E_total - C_cap) ... % 碳交易净支出 sum(C_ccs_om * E_ccs) ... % CCS运维 sum(C_p2g_om * P_p2g) ... % P2G运维 - sum(C_waste_subsidy * M_feed); % 垃圾处理补贴 ops sdpsettings(solver,gurobi,verbose,0); sol optimize(Constraints, Objective, ops); if sol.problem 0 value(Objective) else sol.info check(Constraints) end碳交易项需要注意符号。E_total系统总碳排放减去C_cap捕集量之后如果净排放大于配额该项为正代表买配额支出如果小于配额该项为负相当于卖配额收入。算例里我设配额基准与垃圾处理量挂钩这样垃圾焚烧的免费配额能够降低系统的真实碳压力。求解建议如果机器上没有商业求解器也可以用MATLAB自带的intlinprog代替。YALMIP里只要把solver改成‘intlinprog’就行不过求解速度会明显变慢。我这套24时段模型用Gurobi求解大约用时0.8秒换成intlinprog大概要十几秒在可接受范围内。4. 算例对比无CCS、单独CCS、CCSP2G三组场景的结果差异4.1 三组场景的设定说明为了说明协同效应的来源我在同一套系统参数下做了三组对照算例。场景S1完全不安装碳捕集和电转气设备垃圾焚烧机组与风电光伏直接参与调度弃电只能放弃碳排放按配额缴纳碳费。场景S2只安装碳捕集系统但不装电转气捕集下来的CO2没有下游用户只能算作减碳配额收益。场景S3就是本文的核心场景同时安装碳捕集和电转气设备允许捕集的CO2进入碳储罐再由P2G转化为天然气并储存到气罐。4.2 结果表格协同同时降低了成本和碳排放三组场景的计算结果如下表所示指标S1 无CCS无P2GS2 仅CCSS3 CCSP2G系统总运行成本万元/日86.481.774.6净碳排放量吨/日1093817756弃风弃光率%12.69.52.8碳交易净支出万元/日4.62.11.5CCS平均捕集率%058.371.5P2G运行时段h009S3比S1总成本下降了约13.7%净碳排放下降了30.8%弃风弃光率从12.6%降到2.8%。S3比S2也有明显优势说明P2G的加入不是简单增加了一套耗电设备而是直接提升了碳捕集系统的利用率和经济性。4.3 典型日的调度曲线拆解协同发生在哪些时段打开最优调度结果看一天24小时的时序曲线会更直观。凌晨0点到5点是负荷低谷风电出力反而很大系统电力严重富余。此时P2G开启电解槽满负荷产氢并甲烷化储气罐的储量快速上升CCS的捕集率也跟着提高因为P2G需要大量CO2原料。储碳罐里的CO2被抽走碳循环链条高速运转。这就是“弃风时段制造天然气”。上午6点到9点负荷开始爬升风电出力下降P2G慢慢退出燃气轮机不发电储气罐只进不出。CCS维持在一个中等捕集率因为碳价尚不能支撑满负荷捕集的成本。中午时段光伏大出力P2G会有第二次短时启动但产气量不如凌晨。傍晚16点到21点是负荷高峰电价高企储气罐开始放气燃气轮机发电顶上。与此同时CCS捕集率适当下调释放一部分电功率给负荷。到了夜间垃圾焚烧机组保持稳定出力并为第二天新一轮P2G运行提前把储碳罐补满。这段调度曲线最直观地说明了一个结论P2G本质上是在碳捕集的配合下把成本极低的夜间弃电转换成了高峰时段的高价值电力而CCS在这个过程里既是碳源、又是灵活负荷三个设备加起来形成了一套完整的“时间搬移”系统。5. 敏感性分析碳价、效率、储气容量一变结论就可能翻转5.1 碳价对捕集率与P2G运行时段的非线性影响碳价是影响整套模型走向的最敏感参数。我分别取100、300、600元/吨做了敏感性测试碳价元/吨CCS平均捕集率%P2G运行小时数h净碳排放吨/日系统总成本万元/日10041.2591289.330071.5975674.660085.61263469.8碳价从100涨到300元/吨的过程中CCS平均捕集率大幅提升P2G运行小时数也从5小时增加到9小时。原因是碳价提高后捕集CO2的配额收益增加储碳罐里有了更充足且更便宜的CO2原料P2G的边际成本随之下降于是模型安排更多时段运行P2G。但如果碳价继续涨到600元/吨P2G运行小时数增速放缓因为储气罐容量已经接近上限再增加产气也没地方放。这说明协同效益有一个受限于储能容量的平台期单纯提高碳价不一定会带来等比例的收益增加。5.2 P2G总效率与储气罐容量的边际效益递减P2G总效率η_p2g_total从0.5、0.55、0.6三档变化时P2G运行小时数明显增加系统成本则逐步下降。但效率超过0.6之后成本下降幅度开始变小因为限制运行的主要瓶颈变成了储气罐容量和CO2供给量而不是电解槽效率。储气罐容量对结果的影响类似。把V_gas_max从100 MWh提升到200 MWh系统成本下降非常明显继续提升到400 MWh成本只再降一点点。这说明协同系统的边际收益递减规律主要来自“时间搬移”能力达到饱和后的软约束。这类敏感性分析在项目方案阶段很有用。比如P2G设备采购时大容量电解槽与高效率电解槽价格差异很大通过先跑一遍灵敏度就能知道效率提升带来的运行收益能不能覆盖设备溢价免得拍脑袋选型。5.3 垃圾处理补贴的影响不同城市政策下结论差异很大垃圾处理补贴目前在各地差别很大每吨从几十元到上百元不等。我调整补贴价格后发现补贴越高垃圾焚烧机组越倾向于满负荷运行烟气CO2总量也越大CCS和P2G的碳源越充足系统的“碳链”潜力也越大。反过来如果补贴低到一定程度模型会偏好降低垃圾处理量P2G可用CO2减少协同效应被大幅削弱。这提醒了一件事做这类项目评估时不要只盯着碳价和技术效率垃圾处理补贴政策才是决定项目收益稳定性的关键变量。5.4 当前模型的主要简化边界最后说清楚这个模型刻意忽略的部分。首先是电网潮流我假设虚拟电厂与外部电网之间是一个理想节点没有线路容量和阻塞约束实际接入时可能需要增加网架约束。其次是碳捕集的详细热力学过程胺液再生能耗我用了常数系数没有考虑环境温度、胺液浓度衰减等细节。第三垃圾焚烧炉的烟气CO2浓度会随垃圾组分波动我只用了固定系数k_co2。第四模型中还没有考虑P2G设备的投资折旧只算了运行层面的收益所以结论偏乐观一些。这些简化在规划层面是够用的若要用于具体工程可研建议在本文框架基础上再补充设备投资年限、贴现率和台架实验数据。6. MATLAB实战排错双线性项、不可行解与储能量被“白嫖”的五个坑6.1 双线性项处理不当MILP变成MINLP前文提过捕集量C_cap(t)δ(t)*G_co2(t)这个式子看起来简单直接写进代码就是大坑。一开始我自己也犯过这个错用了连续变量δ和G_co2相乘YALMIP报出“bilinear equality”警告后模型求解时间从几秒变成几分钟最后解还经常不收敛。解决办法就是第2.2节讲的大M转换法把捕集率变成约束边界而不是显式变量。类似的双线性结构还可能出现在储能设备出力与状态变量相乘的判断里都要注意用0-1变量配合bigM拆开。6.2 求解器报Infeasible时应该按什么顺序排查如果Gurobi直接返回infeasible我的排查顺序很有规律。先把所有二进制变量固定成1把模型退化成LP看LP是否可行。如果LP还不可行问题几乎出在功率平衡或物料平衡等式上重点检查等式两侧的变量是否写反了符号。如果LP可行而MILP不可行问题多半出在0-1变量与互斥约束上比如购售互斥约束与P2G最小功率约束互相矛盾。第二步检查储能状态方程。特别是V(1)V(T1)这类周期约束一旦某个储罐的初始容量设置超过上限整个调度周期都可能卡死。第三步是用YALMIP的check函数挨条查看约束残差把残差超过1e-3的约束单独拿出来过一遍。6.3 储能初始值的重要性不要“白嫖”储罐能量这个坑我印象很深。有一版模型没加V_co2(1)V_co2(T1)和V_gas(1)V_gas(T1)求出来的成本比预期低了不少我当时还以为模型改进成功了。后来检查储气罐曲线才发现优化结果一上来就把储气罐里的天然气全放掉了等到周期结束时储罐却是空的等于凭空多出一大笔可用能量。加了周期约束后成本立刻回升到合理水平。这里建议把储罐的初始状态设置为计划期开始时的实际储量并在模型里保留周期相等约束这是一个保证调度结果可持续性的基本要求。6.4 单位不统一和数值尺度问题导致的“隐形误最优”有一次我在参数表里把LHV_w的单位填成kJ/kg实际约束里用的是MJ/kg结果所有焚烧发电功率都放大了1000倍功率平衡等式还神奇地满足了——因为负荷和风电也都被各种系数带偏了。后来查了一天问题就出在单位换算。建议所有人把单位清单打印出来放在参数表旁边功率MW、能量MWh、质量t、热值MJ/kg、单价元/MWh。YALMIP本身不检查单位这类错误不会报错只会给你一个数值上合理但物理上荒谬的解。数值尺度方面也值得注意如果某个约束里同时出现1000和0.001量级的系数求解器数值稳定性会下降。我会把目标函数中的成本先化成“万元”来计算把CO2质量统一用“吨”而不是“千克”这样约束系数基本都在同一数量级。6.5 目标函数漏掉垃圾处理补贴调度结果直接失真的教训前文说过垃圾处理补贴是垃圾焚烧电厂收益的基本盘。我第一次建模时只放了售电收入和碳交易成本结果优化器给出的最优策略是大幅度减少垃圾进料因为焚烧发电卖不了几个钱不如少处理垃圾少耗燃料。后来加入处理补贴收入后模型才真正呈现出“稳定处理垃圾、维持基本出力”的合理行为。这提醒所有做该类项目仿真的同行垃圾焚烧机组在虚拟电厂里的角色是带着环保服务属性的建模时一定把“处理服务收入”放进目标函数而不是只把它当成一台普通发电机组。这个项目做完之后我自己最大的体会是最优解往往不是某一台设备效率最高的结果而是让碳捕集、电转气和垃圾焚烧共享同一套能量流和碳流边界的结果。只要物料平衡、功率平衡和储能周期约束写对了模型会自动给出非常漂亮的时间互补方案。后续如果要工程化落地我会再把逐时碳排放因子、检修计划和设备寿命成本加进去那样应该会更接近实际项目的决策需求。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表