ARTICLE DETAIL

资讯详情

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

虚拟电厂优化调度:碳捕集、垃圾焚烧与P2G协同的MILP建模与Matlab实现

虚拟电厂优化调度:碳捕集、垃圾焚烧与P2G协同的MILP建模与Matlab实现 最近在做一个虚拟电厂优化调度项目模型里同时聚合了碳捕集火电机组、垃圾焚烧电厂和电转气P2G装置用Matlab搭模型、Yalmip建模、Gurobi求解。这类“计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度”的题目现在很常见但打开论文看公式是一回事真正把代码跑起来又是另一回事变量维度、碳平衡边界、分段线性化、求解器不可行……每一步都可能卡住。这篇文章不打算复述论文摘要而是按我自己从建模到调参的完整顺序把这个题目的模型怎么搭、目标函数怎么线性化、Matlab代码怎么组织写清楚以及哪些地方最容易把调度结果搞偏。如果你正在做类似方向的毕设或工程项目可以直接参考这套思路。1. 为什么要把碳捕集、P2G和垃圾焚烧放进同一个调度框架1.1 三个主体能形成“碳闭环新能源消纳”的双循环要理解这个模型先要搞清楚这三个主体放在一起的真实诉求是什么。虚拟电厂VPP本身是一个聚合层概念把分散在配电网里的分布式电源、储能、可控负荷整合成一个整体对外像一个电厂一样接受调度。但聚合进来的机组类型差异非常大尤其是碳捕集电厂和垃圾焚烧电厂。碳捕集电厂本质上还是同步机组但它的净出力受捕集能耗影响对外输送的功率是“发电功率减去捕集能耗”的结果。垃圾焚烧电厂则受环保约束城市垃圾每天必须处理不能像常规火电那样“停机备用”。P2G则是一种“电负荷气源”的混合体用电力制氢再甲烷化既能消纳弃风弃光又能产生天然气还能源源不断地消耗二氧化碳。这三者放在一起最大的价值在于形成一个双循环。传统火电加装碳捕集后烟气里的CO2被溶剂捕获下来但捕获下来的CO2如果只封存经济性并不好。P2G的甲烷化反应正好需要CO2电解水制氢后氢气和CO2在催化剂作用下反应生成甲烷和少量水捕集下来的CO2就从“负担”变成了“原料”。另一边当电网出现弃风时比如凌晨风电大发而负荷处于低谷多余电能可以驱动P2G转化为天然气储存如果P2G单独运行它还需要额外寻找CO2来源或向大气购买碳碳效益打了折扣。所以把碳捕集电厂、垃圾焚烧电厂与P2G联合调度能同时实现高碳机组低碳化改造、风电消纳加强、燃气增产从系统级而不是设备级优化成本与碳排放。1.2 为什么这类题通常要写成MILP而不是用启发式算法这类调度问题包含机组启停0-1变量、碳交易阶梯区间选择、分段线性成本本质是一个混合整数线性规划问题。在Matlab生态里最靠谱的路线是YalmipGurobi/Cplex而不是用一个遗传算法或粒子群去硬搜。原因是模型规模通常是24时段变量数量在几百个量级0-1变量几十个对成熟MILP求解器来说是很小的问题几秒钟就能稳定求解到全局最优。而启发式算法不仅每次结果有随机性而且面对分段线性、逻辑约束时很难给出可靠的可行性。更重要的一点是MILP能生成对偶信息和约束影子价格后续做碳价敏感性分析、市场交互研究时非常有用。2. 三类核心设备的建模变量多耦合关系是关键建模阶段我建议不要急着敲代码先用表格把“输入-输出-耦合关系”列清楚。机组、P2G、碳捕集模块之间有共享变量CO2流、电功率流、气流量。如果变量维度没对齐Yalmip会直接报维度错误或者更坑的是约束尺寸对但物理意义错结果解出来一团乱。模块主要输入主要输出关键耦合变量碳捕集机组燃料、捕集能耗净发电出力、逃逸CO2、捕获CO2净出力、C_capt、C_emitP2G设备电能、CO2、水天然气、氧气不计P_p2g、G_p2g、C_consume垃圾焚烧电厂垃圾量、辅助助燃燃料发电出力、烟气CO2P_msw、C_emit_msw下面逐个拆开讲。2.1 碳捕集机组的“净出力-捕集能耗-烟气碳量”三角关系碳捕集火电机组通常按两输入三输出来建模。输入是燃料热量和捕集能耗输出是上网电力、烟气CO2排放量、被捕集的CO2量。核心公式如下P_net(i,t) P_raw(i,t) - P_ccs(i,t) % 净出力 毛发电出力 - 捕集能耗 P_ccs(i,t) lambda_ccs * C_capt(i,t) % 捕集能耗与捕获CO2量成正比 C_flue(i,t) e_intensity * P_raw(i,t) % 烟气CO2总产生量 C_flue(i,t) C_capt(i,t) C_emit(i,t) % 总烟气碳 捕获碳 逃逸碳这里的lambda_ccs通常取0.25~0.35 MWh/tCO2取决于再生塔蒸汽消耗量。e_intensity是机组单位毛发电量的CO2排放强度燃煤机组一般在0.8~0.9 t/MWh。把捕集能耗写成与捕集量成正比的线性式是调度模型里的常见假设因为胺法吸收/再生的主要能耗与处理量近似线性。热力学上更精细的模型当然可以做但调度模型覆盖全天24小时、多个机组时线性化是精度和求解效率之间的平衡点。有几个易错点特别提醒捕集能耗的物理含义是“在厂用电中增加了一部分”优化模型里要体现在净出力上不要单纯把它当作外部电负荷再叠加一次否则功率平衡会重复计算。捕集量上限不是简单取决于烟气总量还和吸收塔处理能力相关需要定义C_capt C_capt_max。捕集装置有爬坡限制不能期望一个小时内捕集量从0跳到满值溶剂循环和控制系统都有滞后要加爬坡约束。2.2 P2G的输入侧和输出侧要分开建模P2G分两步电解水制氢然后和CO2在甲烷化反应器中合成甲烷。调度模型通常只关心三件事耗电量、产气量折算成热值功率、耗碳量。G_p2g(k,t) eta_p2g * P_p2g(k,t) % 产气功率 综合效率 * 耗电功率 C_consume(k,t) beta_c * G_p2g(k,t) % 消耗CO2量与产气功率成正比综合效率eta_p2g在0.55~0.65之间取决于电解效率和甲烷化效率。beta_c表示产出单位热值天然气所需CO2量工程上大约0.7~0.85 t/MWh。如果自己推导可以用化学计量比和热值换算但调度模型直接用经验系数更方便。P2G的运行边界常被忽略导致结果过于理想电解槽有最小负载一般不允许低于额定功率的10%~20%否则效率骤降但有些论文出于简化会设0这会让P2G在系统最需要时以极低功率运行实际中做不到。电解槽电功率爬坡很快但甲烷化反应器是化工设备负载变化率会限制整体爬坡。所以模型里要给P2G加爬坡约束。P2G消耗的CO2并不强制要求来自碳捕集。但在协同调度模型里我们会加一个“碳源选择”机制优先使用内部捕集CO2外购CO2设定较高价格这样模型会自动选择内部碳闭环体现协同价值。2.3 垃圾焚烧电厂的“必须处理量”是最容易被低估的约束垃圾焚烧电厂在虚拟电厂里通常当作可控电源处理但不能完全照搬火电模型。因为它承担城市固废无害化处理任务在调度周期内必须处理掉当日入厂的垃圾量这是硬约束。所以模型里一般要写出力上下限焚烧炉稳定燃烧需要出力下限通常是额定的50%~60%不是0全天垃圾处理量下限sum(G_msw(t)) G_msw_total。没有这个约束优化器一定会把所有时段出力压在下限省燃料成本但实际垃圾根本没烧完垃圾焚烧发电效率通常在18%~22%单位燃料成本较低有时还可以计入政府补贴体现在目标函数里可能是负成本项促使它多发如果给垃圾焚烧电厂也加碳捕集它的烟气碳量同样简化成与发电量线性适用2.1中的捕集关系。但要注意垃圾焚烧的烟气成分比煤电复杂这里只是工程简化。3. 目标函数与碳交易成本阶梯碳价必须线性化3.1 目标函数怎么搭目标函数的基本形式是min 总成本 常规机组燃料成本 启停成本 运行维护成本 碳捕集运行成本 P2G运行成本 垃圾焚烧处理成本/补贴 碳交易成本 弃风惩罚常规机组燃料成本可以用二次函数但求解时要做分段线性化。启停成本用0-1变量一次启停固定成本。碳捕集运行成本可以折进捕集能耗中惩罚也可以单独写成一个与捕集量正比的线性项。P2G运行成本主要是设备维护和辅助能耗按产气量线性。垃圾焚烧部分的成本要看考虑的是“单纯发电”还是“城市固废处理”。如果是后者入厂垃圾的处理费收入会抵消很大一部分发电成本因此目标函数里的单位成本可能是负值。这个设计会明显影响调度结果要结合实际补贴政策设定别乱填。弃风惩罚也必须有。没有弃风惩罚很多情况下最优方案就是直接弃掉额外的风电反正风电边际成本也是0。要给它一个单位惩罚系数比如200元/MWh才能体现可再生能源消纳的优先级。3.2 碳交易成本的线性化方案碳排放交易是这套模型的低碳导向核心。目前常见的是阶梯型碳交易机制根据净上网电量发放免费配额实际排放低于配额可出售超出需要购买且连续超出时碳价递增。先定义配额E_quota(t) quota_rate * P_vpp_net(t) % 配额与虚拟电厂净输出电量挂钩 E_trade(t) E_emit_total(t) - E_quota(t) % 需要交易的碳量负值代表出售然后构建分段线性成本。比如三段碳价分别为100、150、200元/tCO2分段上限为Delta1、Delta2。直接用min/max函数会让问题变成非光滑优化求解器不稳定。我建议用binvar加Big-M做区间选择虽然增加了整数变量但MILP求解器非常擅长这类约束。核心思路是定义分段量E_seg(k,t)和分段选择变量z(k,t)保证每个时段的超额碳量先填满低区间再流入高区间。在Yalmip里可以手工写z binvar(3, T, full); E_seg sdpvar(3, T, full); % 每个时段的总超额碳量 各分段之和 Constraints [Constraints, E_trade sum(E_seg, 1)]; % 每个分段量非负 for k 1:3 Constraints [Constraints, E_seg(k,:) 0]; end % 后一段只有在前面段满额时才能占用用大M控制 M_bound 5000; % 大于可能的碳排放量即可 Constraints [Constraints, E_seg(2,:) z(1,:) * Delta1 M_bound * (1 - z(1,:))];具体写法可以根据区间数调整但思想是一致的用0-1变量锁定额外区间用连续变量表达区间内碳量。实现时最怕的是M取值过大导致分支定界效率下降所以M要尽量贴近实际量级比如最大碳量是3000 tCO2M设5000就够。4. MatlabYalmip建模实操从0到可跑的代码框架4.1 变量定义与维度约定如果你用Matlab做这套题我建议用YalmipGurobi而不是自己写求解器。Yalmip可以让你像写数学公式一样组织符号变量极大减少矩阵堆叠工作。我习惯按“参数区-变量区-约束区-目标区-求解区-后处理区”组织代码。变量命名要统一第一维是设备编号第二维是时间。后处理时直接P_g(i,:)就是第i台机组一整天的时序。T 24; n_g 2; % 常规机组数 n_ccs 1; % 带碳捕集机组数 n_msw 1; % 垃圾焚烧电厂数 n_p2g 1; % P2G设备数 P_g sdpvar(n_g, T, full); % 常规机组出力 u_g binvar(n_g, T, full); % 启停状态 P_raw sdpvar(n_ccs, T, full); % 碳捕集机组毛出力 P_ccs sdpvar(n_ccs, T, full); % 捕集能耗 C_capt sdpvar(n_ccs, T, full); % 捕获碳量 C_emit sdpvar(n_ccs, T, full); % 逃逸碳量 P_msw sdpvar(n_msw, T, full); % 垃圾焚烧出力 P_p2g sdpvar(n_p2g, T, full); % P2G耗电 G_p2g sdpvar(n_p2g, T, full); % P2G产气sdpvar默认创建满矩阵最好显式加维数和full避免列向量矩阵乘法时维度混乱。垃圾焚烧的碳捕集变量可以单独定义也可以在同一个矩阵里加一行看你的规模。4.2 功率平衡和碳平衡是两类最核心约束功率平衡要写在“净出力”层面P_wind_used sdpvar(1, T, full); % 实际消纳风电 Constraints [Constraints, ... sum(P_g,1) sum(P_raw - P_ccs,1) sum(P_msw,1) P_wind_used ... P_load sum(P_p2g,1)];这里P2G耗电是负荷放在等式右边弃风量就是P_wind_pre - P_wind_used在目标函数里加惩罚。碳平衡约束是这套模型的灵魂也是很多人建模时最容易算重复的地方。我建议用“净排放”作为系统的唯一口径系统净排放 所有机组未捕集逃逸排放量 - 外部封存抵扣 P2G外部购碳?更稳妥的写法是把碳捕集和P2G分开算再统一汇总C_capt_total sum(C_capt,1) C_capt_msw; % 总捕获碳 C_emit_total sum(C_emit,1) C_emit_msw; % 总逃逸碳 C_consume_p2g beta_c * sum(G_p2g,1); % P2G耗碳量 % 系统总排放参与碳交易的口径C_consume_p2g作为碳利用抵扣项 E_emit_total C_emit_total - C_consume_p2g;注意这里有个逻辑陷阱如果碳捕集捕获的CO2已经被记入“逃逸排放”之外那么P2G再去扣一遍就会重复计算。所以要么把C_consume_p2g理解成“碳捕集后未封存而进入P2G的量”不重复在净排放里扣要么就按照上面代码这样把E_emit_total定义为“逃逸排放-被P2G利用的外部碳”但要给自己固定一套边界不要一会儿扣一会扣。我在调试中就因为口径不一致出过碳排放量为负数的不合理结果。4.3 求解器设置与不可行排查ops sdpsettings(solver, gurobi, verbose, 2, showprogress, 1); diagnosis optimize(Constraints, Objective, ops); if diagnosis.problem ~ 0 yalmiperror(diagnosis.problem) end遇到不可行时我一般这样排查先去掉碳交易分段约束只跑基础功率平衡和机组约束看是否可行再逐项加P2G、碳捕集、垃圾处理量约束每次加完都用check(Constraints)看哪些约束残差过大检查爬坡约束是否跨时段错位第2时段的爬坡应当用P(:,2)-P(:,1)不要写反检查Big-M是否过大过大M会拖垮求解性能。5. 算例设计怎么看出“协同”的价值5.1 四套对照算例怎么设计搭好代码之后最怕打印一堆结果却说不清优劣。我一般设计四个对照场景场景A普通虚拟电厂含常规燃煤机组、垃圾焚烧、风电没有碳捕集和P2G场景B在场景A基础上加碳捕集捕获的CO2直接封存场景C在场景A基础上加P2G但P2G所需CO2来自外部采购场景D在场景A基础上同时加碳捕集和P2G捕集的CO2优先供给P2G。通过四个场景的对比能拆出碳捕集和P2G各自的作用以及协同带来的增量。对比指标建议用四个总运行成本、净碳排放量、弃风率、P2G的时段利用率。下面是我以一个典型24小时系统跑出来的趋势方向具体数据取决于参数仅说明变化关系场景总成本净碳排放弃风率说明A基准最高最高明显弃风无CCS、无P2G碳交易成本高BCCS中等明显下降弃风可能反而增加捕集能耗挤占风电出力CP2G中等略下降弃风下降P2G消纳风但CO2靠外购DCCSP2G最低或接近最低最低很少弃风P2G利用捕集的CO2形成闭环这里特别值得注意场景B加碳捕集后捕集能耗很大在负荷低谷时段反而需要机组提升毛出力来维持净出力可能导致弃风加剧。如果没有P2G这些“为了捕集而额外发出的电”无处可去。加了P2G之后低谷时段P2G启动既消纳了风电和多余电量又消耗掉捕集下来的CO2相当于把“为减碳而付出的成本”部分转化为天然气资产。5.2 从结果曲线看协同价值画图时重点看三条曲线风电场出力曲线对比预测可用功率、实际消纳功率、P2G耗电功率能直观看出P2G在哪些时段“吃掉”了弃风CO2流向曲线画碳捕集捕获量、P2G耗碳量、封存量三条线看协同时段是否对齐。如果P2G耗碳量和捕集量在低谷时段重合说明碳闭环起了作用系统净排放柱状图叠加碳交易成本和P2G收益看看协同场景的经济性来源在哪里。我在调试时发现很多算例的场景D并不是所有时段P2G都满负荷而是集中在凌晨风电大发、负荷低谷时段启动。白天P2G会主动降出力因为风电消纳压力小直接用市电更划算。这说明时序耦合是对的。如果结果里P2G全天满负荷那大概率是参数设置或爬坡约束缺失要回去查。6. 代码扩展方向与个人实操体会6.1 可扩展的几个方向这套模型做完以后可以往很多方向继续扩展把风电预测误差显式建模改成多场景随机优化。Yalmip里可以按场景循环叠约束目标函数改成期望值求解时间会明显增加但结果更稳健加入电储能。电储能和P2G既竞争又互补储能效率高P2G能产气并利用CO2系统会依据成本自动决定用哪种缓冲资源把碳捕集的详细热力过程加进来比如再生塔能耗随负荷率非线性变化甚至让P2G的余热供应捕集再生能耗形成热-电-气耦合做碳价敏感性分析从50元/t拉到200元/t观察CCS和P2G何时真正进入经济运行。这个结论对政策解读和项目论证都很有用考虑配电网潮流约束用DistFlow或直流潮流替代单节点平衡但要注意求解规模上升。6.2 个人实操过程中的几条经验最后说几条实实在在的经验。第一建模之前先画能量流和碳流图把每个变量的耦合关系标出来后面写约束基本是“抄图”。第二不要一上来就上复杂的捕集热力学模型先用线性模型跑通再逐步扩展。第三变量命名一定要统一我习惯决策变量全大写参数小写或带前缀否则后处理时找bug会非常痛苦。第四做算例对比时固定同一份负荷曲线和风电预测数据只改设备参数结果才有可比性。这套“碳捕集P2G垃圾焚烧虚拟电厂优化调度”虽然看起来像是关键词拼接的题目但实际是一个多能互补、低碳环保和经济效益三方博弈的典型优化问题。把模型逻辑理清、Matlab代码跑通之后后续无论是继续深入做随机优化、多能流还是市场机制研究都有了扎实的基础。尤其是碳平衡和分段线性化这两道关突破一次后面再遇到类似题目基本就能顺手拈来。
返回列表