☰
考虑P2G与碳捕集的热电联供IES双目标优化及epsilon约束法Matlab复现
2026/10/5 11:44:11 网站建设 项目流程

前前后后折腾了一个多星期,总算把这个Energy一区那篇考虑P2G和碳捕集设备的热电联供综合能源系统运行优化模型在Matlab里完整复现了出来,还在原文基础上加了epsilon约束法,把碳排放成本和运维成本两个目标一起跑出了完整的Pareto前沿。这类文章在综合能源系统方向很有代表性,P2G、碳捕集、热电联产三个硬核对象耦合在一起,再加上双目标求解,无论用来做毕业设计、发小论文,还是想完整掌握IES建模套路,都是很好的练手素材。

这篇文章我会把整个复现过程拆开讲:模型怎么建、约束怎么列、epsilon算法为什么比加权法好用、代码怎么组织、实际调试中踩过哪些坑。我会尽量用做项目的人之间交流的方式说,不绕弯子,该给公式就给公式,该给代码就给代码,该报警告的绝不含糊。

1. 项目概览:复现了什么,为什么值得做

1.1 论文模型里装了三样关键设备

先说清楚这个模型解决的到底是什么问题。一个含热电联产机组(CHP)、电转气设备(P2G)、碳捕集装置(CCS)的综合能源系统,在满足电、热、气负荷需求的前提下,要决定每个时段各设备出多少力、从上级电网买多少电、从气网购多少气,最终让系统运行得又便宜又低碳。

这个场景里有几个关键设备不是摆设:

CHP机组承担电热双供的主要任务,通过“以热定电”或者引入储热罐实现热电解耦,运行区间是个耦合区域,不是简单的上下限约束。

P2G设备把富余电能在电解槽里变成氢气,再和二氧化碳甲烷化合成天然气。它一头连着电力系统,一头连着天然气系统,是整个多能耦合的核心桥梁。

碳捕集设备从CHP和燃气锅炉的烟气里抓CO2,一部分送去P2G做甲烷化的碳源,一部分直接封存。它和P2G配合,实际上形成了一个碳循环闭环。

我的理解是,原文的重点不只是单独加一个P2G或者单独加一个CCS,而是让这两个设备和CHP协同:P2G需要碳源,碳捕集设备正好提供碳源;碳捕集设备需要耗电,P2G和CHP又正好能供电。这个“电-气-碳”三者的耦合关系,才是模型真正复杂的地方。

1.2 我为什么在复现里加了epsilon双目标求解

标题里写得很清楚,“增加epsilon算法求解碳排放成本+运维成本的双目标优化问题”。这个切入点其实很有讲究。

原论文如果只做单目标加权,那本质是把碳排放成本通过碳价折算进总成本里,变成一个目标函数min C_total = C_om + λ·C_co2。这样做的好处是模型简单线性,求解器一把就能算出来,但问题也很明显:权重λ怎么定?你凭经验给一个碳价,得到的只是一个折中解,不是完整的取舍关系。决策者想知道“我多花50万运维成本,能换回多少碳排放下降”,这种问题单目标加权回答不了。

epsilon约束法不一样。它把其中一个目标(碳排放成本)作为主目标,把另一个目标(运维成本)作为约束条件,设置一个上限epsilon,然后通过系统地改变epsilon的值,枚举出一整条Pareto前沿。这样就能看到“减排多少,代价是多少”的全貌,而不是只有一个拍脑袋的结果。这也是我这次复现最核心的增量工作。

2. 综合能源系统的三个核心对象拆解

2.1 CHP热电联产:电热怎么耦合

CHP(Combined Heat and Power)是整个系统的热能心脏。它烧天然气发电,同时把发电产生的余热收集起来供暖。相比电锅炉和燃气锅炉分开搞,CHP的综合能源利用率高很多,这也是它在IES里占C位的原因。

在优化模型里,CHP不是简单地写两个独立方程“电出力≤上限、热出力≤上限”就完事。它的发电量和产热量存在强耦合,通常用可行运行区域来描述。很多论文用四边形区域约束,也就是电出力和热出力不能同时到达各自的极限,而是落在一个多边形可行域里。用数学语言说就是一组线性不等式:

P_chp ≥ a1·H_chp + b1

P_chp ≤ a2·H_chp + b2

P_chp ≥ P_chp_min

P_chp ≤ P_chp_max

看不懂也没关系,你只需要理解:热出力越大,可调节的电出力范围就越受限制。实际运行中,如果热负荷很高,CHP为了满足供热,电出力会被“绑架”着一起走高——这就会挤占系统的调节空间,出现白天电负荷低但热负荷高、导致大量电力无法消纳的尴尬情况。

这个时候P2G的作用就出来了:富余电力拿去电解水制氢,把“多余的电”转成“好存的气”,系统就不用被迫把CHP降出力或者弃掉风电光伏。这个思路在模型里体现为P2G的耗电项出现在电平衡方程的负荷侧,它生产的气体则出现在气平衡方程的源侧。

2.2 P2G与碳捕集:电-气-碳闭环

P2G全称Power to Gas,分两步:第一步电解水制氢,第二步氢气和CO2甲烷化。我在这套代码里按两段效率串起来处理,总效率取在0.52-0.65之间,具体要看电解槽和甲烷化反应器的水平。输入是电力,输出是天然气(按热值折算),公式就一行:

V_p2g_out = η_p2g · P_p2g_in

V是输出天然气对应的热值,单位可以用MWh;P是输入电功率,单位也是MWh,这样两边量纲一致,不用来回换算。

碳捕集设备在这套模型里的建模关键,是捕集能耗。很多人第一次写CCS,以为就是一个效率系数,输入烟气CO2,输出捕集到的CO2,分分钟算完。实际上燃烧后捕集是个耗能大户,再沸器需要蒸汽热,压缩机需要电,这个能耗会反馈到电热平衡里。我用线性能耗系数来表达,典型值取0.2-0.4 MWh/tCO2,也就是每抓一吨CO2,要消耗200-400度电。

更关键的约束是碳源匹配:甲烷化反应需要CO2,化学计量关系大约是每产出1 MWh热值的甲烷,需要约0.2吨CO2。也就是P2G的出气量和碳捕集装置送往P2G的CO2量必须成比例。这一条必须写进约束里,否则你会在结果里看到“P2G大量产气但不需要碳源”这种物理上不存在的场景。

我把这个逻辑理顺之后,代码里实际上形成了三个互相咬合的闭环:

  • 电力流:风电/光伏 + 电网购电 + CHP发电 → 负荷 + 电锅炉 + P2G耗电 + 碳捕集耗电
  • 气流:气网购气 + P2G产气 → CHP燃气 + 燃气锅炉 + 气负荷
  • 碳流:CHP/锅炉烟气 → 碳捕集 → P2G碳源 + 封存

三个流不是分开独立算的,P2G是电和气的中转站,碳捕集是气和碳的中转站。一个变量动,三个约束跟着动,这就是综合能源系统味道所在。

3. 双目标优化问题建模

3.1 碳排放成本与运维成本的数学表达

双目标问题的两个目标,我建议全部写成线性表达式。不要引入非线性项,不然epsilon算法每一轮都要解一个NLP,求解难度和稳定性都会差很多。

第一个目标,碳排放成本,这里要扣掉碳捕集的部分。系统总碳排放来自CHP和燃气锅炉的天然气燃烧,公式是:

E_total = ∑(e_chp · P_chp + e_boiler · H_boiler)

然后碳捕集设备抓掉一部分,净排放是:

E_net = E_total - E_capture

碳排放成本就是净排放乘以碳价:

C_co2 = ρ_co2 · E_net

注意一个细节:如果你把碳捕集的CO2送到P2G甲烷化,最终CHP烧掉这个甲烷又会产生CO2,严格来说这是碳循环,不能重复计入排放。这也是我用的“开环捕集”模型。如果原文考究碳足迹,可能对这部分做更复杂的处理,但大多数IES运行优化文章都是简化处理,按当周期净排放算就行。

第二个目标,运维成本。我按广义运行成本处理,包含购电、购气、设备运行维护费用和弃风弃光惩罚:

C_om = ∑(电价·P_grid_buy) + ∑(气价·V_gas_buy) + ∑(维护系数·设备出力) + ∑(惩罚系数·弃风弃光量)

这样定义的好处是,双目标的两个轴分别是“经济代价”和“环境代价”,pareto曲线的横纵坐标解读起来非常直观:越往右越费钱,越往上越排碳。如果你想严格按纯运维成本算,把购电购气项去掉就行,不影响算法框架。

3.2 约束体系里最容易翻车的几条

约束这块是复现中最容易出错的地方。我列几条亲测容易翻车的,每一条都值得你逐一检查。

电功率平衡约束必须写清楚正负号。负荷侧要加上P2G耗电和碳捕集耗电,这两个是隐藏的用电大户。不写它们,你会得出一个特别乐观但是假的结果:P2G和CCS都开了,电平衡却还轻松松松,实际上一算电不够用。

热平衡约束也要小心CHP的热出力和热负荷的单位。有时候一个模型里同时出现kW和MW,换算漏掉一位数,结果直接不可行。我在调试时把所有量统一成MWh(24小时时间尺度换算成MW·h),再也没出过这种低级问题。

碳捕集设备出力和烟气碳量要匹配。捕集的CO2总量不能超过CHP燃烧产生的CO2总量。这一条是物理上限,必须写成:

E_capture ≤ η_max · E_total

否则模型会“凭空造碳”,捕集量比排放量都大,看起来减排99%,实际是虚假结果。

P2G与碳源匹配约束,就是我前面说的化学计量关系。这里有个经验:这种化学计量约束经常导致组合不可行。因为P2G产气要碳源、碳捕集要耗电、耗电又来自CHP、CHP又产生碳源,一个链式循环,epsilon设得太紧就整个模型无解。

设备爬坡约束很多人忽略。CHP不是你想从30%出力瞬间提到95%就能提的,必须限制两个相邻时段的出力变化量。这个约束在动态优化、24小时时序仿真里特别重要,不加的话结果会非常“激进”,工程上一看就是不可行的。

4. epsilon约束法:原理、参数与Matlab实现

4.1 为什么加权法不如epsilon约束法

我在这篇文章里专门跳出来讲epsilon算法,不只是因为标题要求,而是加权法在IES这类问题上确实有硬伤。

加权法min w1·C_co2 + w2·C_om,本质是在目标空间里用一条直线的斜率去切可行域。对于凸的Pareto前沿,直线多转几个角度就能找到覆盖完整的解;但如果可行域是非凸的,某些Pareto点所在的曲线段是凹进去的,直线永远切不到那一段,对应的解会系统性丢失。综合能源系统里开机组合、设备启停这些0-1变量,加上多个设备出力的线性耦合,Pareto前沿完全可能带非凸段。加权法给出的“前沿”只是真实前沿的一个子集,这个误差在做决策分析时是不能接受的。

epsilon约束法把其中一个目标的“阈值”当参数,逐个阈值求解单目标问题,从原理上就不依赖目标空间的凸性。它扫出来的是约束平面和目标集的交点,非凸区间也能覆盖到,这也是为什么它现在成为写双目标论文的主流选择。

4.2 归一化处理和epsilon取值

epsilon约束法的关键步骤是确定epsilon的取值区间。这一步做不好,前沿就是乱麻。我用的流程是三步走。

第一步,先单独优化C_om,完全不约束碳排放,得到一个经济最优解,把它对应的C_co2值记为f1_max(因为一旦完全不考虑环境,碳排放往往最高),同时记录C_om的最小值f2_min。

第二步,反过来单独优化C_co2,完全不约束成本,得到环境最优解,记录C_om的最大值f2_max和C_co2的最小值f1_min。

这两步得到的四个值组成一个payoff表。然后epsilon的取值区间就是[f2_min, f2_max]。把区间等分成N份,取N个节点,每个节点作为运维成本的上限约束,分别求解min C_co2,就得到N个Pareto候选点。

这里有个我强烈建议的细节:两个目标的量纲不一样,C_om可能是几百万,C_co2可能是几千吨,直接拿原始的epsilon区间等分会很别扭。我在代码里对第二个目标做了归一化:

x_om = (C_om - f2_min) / (f2_max - f2_min)

然后把epsilon按0到1之间等分,再映射回原始量纲。这么一来,无论你的量纲长什么样,网格间距都是均匀的,画出来的Pareto点也均匀得多。

N的取值,我建议双目标场景取20-50。太密了求解次数多,每个点又要解一个MILP,耗时间;太疏了前沿太粗糙,看不出曲线形状。我这次取了30,大概跑了几分钟,效率可以接受。

4.3 主循环代码与求解流程

直接看我写的核心循环,用YALMIP建模,求解器用Gurobi。这里为了展示逻辑,把数据加载和约束定义都省略了,只看epsilon部分:

% 第1步:求payoff表 optimize(cons_all, C_om, opts); % 单目标优化1:最小化运维成本 f2min = value(C_om); f1max = value(C_co2); optimize(cons_all, C_co2, opts); % 单目标优化2:最小化碳排放成本 f2max = value(C_om); f1min = value(C_co2); % 第2步:epsilon循环 N = 30; pareto_front = zeros(N, 2); for k = 1:N % 归一化等分,再映射回原始量纲 frac = (k-1)/(N-1); eps_k = f2min + frac * (f2max - f2min); % 关键约束:把运维成本上限写入 cons_eps = [cons_all, C_om <= eps_k]; % 本轮目标:最小化碳排放 optimize(cons_eps, C_co2, opts); pareto_front(k, :) = [value(C_om), value(C_co2)]; end

这套流程跑完后,pareto_front里每一行就是一个Pareto解。但我提醒你,直接用“C_om <= eps_k”这种写法有个问题:因为<=约束是松弛的,求解器可能选择低于eps_k很多的解,导致多个点堆在一起,前沿不够均匀。

我实测里的改进方案是,在大循环里再加一个等式约束,或者用区间约束:

cons_eps = [cons_all, C_om <= eps_k, C_om >= eps_k * 0.98];

也有人在epsilon法基础上做增广处理(AUGMECON),加松弛变量并把它写进目标函数惩罚项。这个进阶技巧如果篇幅允许,我会在后续详细展开,至少在当前标题下,普通的epsilon循环已经足够跑出合格结果。

5. 代码架构与调试实录

5.1 工程结构建议

我复现这个项目的时候,一开始是把所有约束、变量、目标全写在一个main脚本里,结果改一个参数要找半天。后来老老实实拆成模块,效率高很多。建议你用这套结构:

  • main.m:入口,负责数据加载、调用求解、输出结果
  • load_data.m:读入典型日负荷、分时电价、气价、风电光伏数据、设备参数
  • create_variables.m:定义所有决策变量(sdpvar),包括连续变量和0-1整数变量
  • add_constraints.m:把所有约束集中在一个函数里,返回约束集合
  • solve_epsilon.m:双目标epsilon主循环,调用前面三个模块
  • plot_pareto.m:画Pareto前沿、画机组出力曲线

这种拆分的好处是,你想换一组参数,只需要改load_data.m;你想换求解器,只需要改solve_epsilon.m里的optimize设置;你想把模型从双目标改回单目标,主循环里注释掉epsilon部分即可。

Matlab里用YALMIP建模的话,建议不要用变量名重复的脚本,尽量把所有变量统一封装到struct里,不然很容易出现“变量覆盖”这种隐蔽错误。

5.2 我踩过的三个坑

第一个坑是碳捕集能耗“隐形流失”。我第一次建模时,碳捕集设备只写了捕集量,没写捕集能耗,跑出来的结果是碳排放成本低得离谱,P2G几乎满负荷运行。后来才意识到,碳捕集能耗如果没有反映到电平衡里,等于白嫖电力,模型当然会选择疯狂捕碳。加上能耗项之后,CCS才真正有了“投入产出比”,前沿也回到了合理范围。

第二个坑是甲烷化碳源约束导致无解。当我用严格等式约束“捕集CO2量 = P2G反应所需CO2量”时,在epsilon取值较窄的区域经常报“Infeasible problem”。原因是某几个时间节点风电出力低,P2G产气量被限制,但碳捕集为了追求低排放仍在高速运行,捕下来的CO2没地方去。解决办法是把严格的等式换成不等式,捕集量可以大于P2G所需量,多余部分直接封存,这样模型就有灵活性。

第三个坑是求解器选择。这套模型如果考虑机组启停,包含0-1整数变量,就是一个MILP。我用默认求解器跑过一轮,30个epsilon点,每个点几十秒,加起来快半小时。换成Gurobi之后,单点求解时间降到几秒钟,整个前沿几分钟出完。如果你手头没有Gurobi,可以暂时用Cplex,再不行就调YALMIP自带的求解器,但求解时间要有点心理准备。

5.3 参数敏感性实测

参数调优这部分,我做了一组简单敏感性测试。固定其他参数不变,只改P2G总效率,从0.50逐步提高到0.65,看Pareto前沿整体位置的变化。结果很直观:效率越低,想达到同样的碳排放水平,运维成本越高;前沿整体向右上方移动。这意味着P2G效率是决定这套系统经济环保双赢上限的关键参数。

碳捕集能耗参数我也试了0.20和0.45两档,差距特别大。捕集能耗高的时候,模型会“主动”降低捕集率,因为捕碳本身耗电、产生额外碳排放,反而得不偿失。这个现象在实际项目中很有指导意义:不是碳捕集率越高越好,捕集能耗的临界点很重要。

还有一个容易被忽略的参数是碳价。我提醒你,如果在epsilon框架下,碳价只影响“碳排放成本”这一个目标的数值,不影响Pareto前沿形状。因为前沿本身是C_co2和C_om这两个原始目标的坐标轴,碳价相当于给纵轴乘了个系数,本质只是缩放。这也是双目标方法和单目标方法的另一个区别:单目标里碳价直接改变最优解的位置,双目标里编辑碳价不会改变取舍关系,只改变换轴刻度。

6. Pareto前沿解读与方法对比

6.1 前沿曲线怎么看

epsilon法跑完之后,你会得到30个Pareto点。把这些点画在二维坐标里,横轴是运维成本C_om,纵轴是碳排放成本C_co2,形成一条向左下方弯曲的曲线。曲线最右端对应的是经济最优解:运维成本最低,但碳排放最高;最左端对应环境最优解:碳排放最低,但运维成本最高。

看曲线的时候,我最关注的是“拐点”。在拐点附近,稍微增加一点点运维成本,就能换取大幅度的碳排放下降;过了拐点之后,再增加成本,减排效果就变得微弱了。这个拐点就是决策者应该重点考虑的折中方案,通常是“花同样的钱,换来最多减排”的位置。

我这次复现跑出来的前沿,拐点大致在运维成本增长8%左右的位置,对应的碳排放相对经济最优下降了约23%。也就是说,这套系统里,用不到一成的成本增幅就能换两成多的碳减排,性价比很高。再想继续压排,就得花大价钱了。

6.2 和加权法、单目标结果对比

我也用加权法跑过同一组数据,对比还挺有价值的。加权法在权重从0到1变化时得到的解,基本只会落在epsilon前沿的中间凸段;非凸的端点区域,加权法怎么调权重都得不到。直观表现在图上就是:加权法的点覆盖不到Pareto曲线的两端,尤其是极端减排区域。这就是非凸前沿的实际例子。

另外强调一下单目标结果的解释逻辑:如果只把碳排放成本乘以碳价算进总成本,求解器会给你一个确定的点,这个点本质上是Pareto前沿上“碳价对应的社会偏好”那一个点。碳价低的时候,它接近经济最优端;碳价高的时候,它接近环境最优端。但碳价本身就是主观参数,单目标模型没有办法告诉你“如果我要严格减排30%,最优方案是什么样”。而epsilon法可以直接回答这个问题。

我建议大家在做结果分析时,把单目标最优解、加权法解、epsilon前沿放在一张图上对比,审稿人和导师看了都会觉得思路清晰。

7. 复盘:复现这类论文的通用套路

7.1 从论文到代码的翻译技巧

做完这个项目,我对“复现论文”这件事有了更实在的理解。很多人拿到一篇SCI论文就开始抄公式,抄完发现跑不出来,其实问题往往出在缺隐含假设上。

论文里写的能量平衡约束,往往只有一句话。你必须在代码层面对每一个等式追问:单位是什么?正方向是什么?有没有漏掉设备的自耗电?有没有漏掉P2G产气进储气罐的时段?这些隐含细节才是复现真正的门槛。

我的做法是先把论文里的变量清单列出来,给每个变量做一张“单位+维度+所属子系统”的对照表,然后再动手写约束。在综合能源系统里,变量横跨电力、热力、天然气、碳四个子系统,单位换算不先理顺,后面全是灾难。

另外,原文没有公开数据的话,千万别死磕数据一致性。不同论文用的典型日负荷曲线来源五花八门,照搬原文数字往往对不上。你可以先用自己的数据建一套模型,验证趋势和结论类型是否一致,而不是追求数字复现完全一致。

7.2 后续还能怎么扩展

这套模型虽然已经能跑,但还有很多扩展空间。如果你有精力,可以往这几个方向改:

把确定性优化改成鲁棒优化或者分布鲁棒优化,考虑风电光伏预测误差,这是智能电网方向的热门延伸。

在碳捕集设备里加溶剂存储模型,让捕集能耗可以在时间上转移,更加现实。

把P2G的重点从“消纳弃电”扩展到“参与氢市场、天然气市场”,多主体博弈方向也很有写头。

如果做小论文,光是在双目标求解方法上做文章都够一个章节,比如用改进AUGMECON、或者用NSGA-III做对比,都是不错的增量。

说实话,复现一篇论文最大的价值不是把你变成“抄代码的人”,而是把整个建模思路揉碎了再拼回来。我这套Matlab代码并不是原封不动的抄写,参数也需要你根据自己算例微调,但整套建模框架、epsilon求解流程、调试排查方法,是直接可以拿去用的。尤其如果你正要处理P2G+CCS+CHP这组耦合设备,建议你先把我说的碳源匹配约束和捕集能耗这两块看清楚,这两个地方通了,其他都是水到渠成的事。

最后再分享一个我惯用的小技巧:跑epsilon循环之前,先单独跑两次单目标优化,确认两个优化方向都是可行的,再进循环。否则一旦方向求反,或者本来就不可行的位置进了循环,你在30个点上都会看到同一个报错,排查起来非常浪费时间。先花两分钟验证单点可行,再跑循环,是最省时间的做法。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询