
最近我在调一个融合电力、热力、天然气和碳流四种元素的综合能源系统优化调度模型里面同时塞进了碳捕集电厂和需求响应两种灵活性资源。说句实话刚开始我也觉得只是把两类成熟技术塞进一个模型里真跑起来才发现耦合关系、时间尺度、碳流平衡这些东西远比想象中复杂。这篇文章就盘一盘这个模型怎么做、为什么这么做、哪些地方最容易翻车。文中所说的“综合能源系统”不是论文里那种理想化的抽象系统而是我实际在算的一个园区级多能互补项目里面有天然气、光伏、电锅炉、燃气锅炉、热电联产机组、碳捕集装置还有一堆可以转移或中断的电负荷和热负荷。目标很简单就是在满足电、热、气需求的前提下把一天的运行成本压到最低同时把碳排放总量控制住。需求响应和碳捕集电厂之所以能“玩出花样”核心原因是它们都能在时间维度上制造灵活性只是前者管负荷侧后者管发电侧。这个模型真正难的地方不在建模本身而在“电热气碳”四个系统之间的耦合关系。电负荷由燃气机组、光伏和电网共同承担热负荷由热电联产和燃气锅炉供应天然气则作为燃料输入参与调度碳捕集装置又会反过来消耗电能和热能。一整套约束互相咬合任何一个环节没处理好求解器就直接给你一个不可行解。下面我把整个模型的思路、约束搭建、求解实现和实际踩坑过程完整复盘一遍。1. 为什么把碳捕集电厂和需求响应放在一个模型里1.1 综合能源系统的“电热气碳”四维耦合先理清这个模型里的物理网络。典型园区级综合能源系统会有三个主要母线电力母线、热力母线、天然气母线。电力母线上连着光伏、燃气轮机、外网购电、电储能和各类电负荷热力母线上连着余热锅炉、燃气锅炉、电锅炉、蓄热罐和热负荷天然气母线则连接气源、燃气轮机和燃气锅炉。这三条母线本身已经够复杂碳捕集装置一进来等于在电力母线和热力母线上又挂了一个“能耗大户”同时还在系统里多引入了一条看不见的“碳流母线”。很多人容易忽略的一点是碳捕集电厂并不只是“发电的同时捕碳”这么简单。胺法碳捕集装置需要消耗大量蒸汽用于溶剂再生这部分蒸汽如果从汽轮机中段抽取就会导致发电出力下降同时捕集过程还需要电耗来驱动压缩机、泵和风机。所以碳捕集电厂的净上网功率实际上是“毛发电功率减去捕集能耗”的结果。这就像你一个月工资两万但房贷、车贷、日常开销加起来扣掉一万五真正能自由支配的只有五千。建模时如果把毛功率当成净功率来优化结果会乐观得一塌糊涂实际运行根本达不到。需求响应在这个模型里的角色则完全不同。它提供的不是能量而是“时间上的可调度性”。比如工业用户可以把一部分可中断负荷调整到电价低谷时段办公楼宇可以利用建筑热惯性提前蓄热。当碳捕集电厂因为捕集能耗增加而降低净出力时需求响应可以在负荷侧做反向配合把高峰负荷削减或转移出去相当于给系统装了一个双向缓冲阀。1.2 需求响应在模型里的真正定位单纯的碳捕集电厂调度本质上是一个发电侧优化问题什么时候多捕碳、什么时候少捕碳、溶剂存储量怎么变。但实际运行中你会发现碳捕集装置有一个很尴尬的特点它需要连续运行才经济频繁启停会造成溶剂损耗和能耗上升。因此它并不是想开就开、想关就关的最优策略往往是维持一个相对稳定的捕集率然后通过调整电、热负荷来配合它。这时候需求响应就体现出价值了。模型里我用了两类需求响应资源第一类是价格型需求响应通过分时电价引导用户改变用电行为第二类是激励型需求响应通过签订合同约定可中断负荷和可转移负荷。在优化调度模型里前者的体现方式是负荷弹性系数后者的体现方式是转移量约束和中断量约束。两类资源叠加之后系统可以在碳捕集电厂的捕集能耗高时主动削峰在光伏大发或电价低谷时主动填谷。这样发电侧和负荷侧就形成了真正的双向协同。我把这种组合方式看成“双杠杆”碳捕集电厂是发电侧的灵活性杠杆需求响应是负荷侧的灵活性杠杆两者联动才能在电热气碳四个维度上实现整体最优。只用其中一个模型的优化空间都会窄很多。2. 调度模型整体框架与关键变量设计2.1 多能流拓扑怎么搭模型采用了典型的多时间尺度日调框架时间分辨率取1小时优化周期24小时。这样做的好处是既能捕捉到峰谷差异又不会让变量规模失控。对于园区级系统96个时段虽然更精细但对数据要求太高尤其是热负荷和建筑热惯性的参数往往达不到这种精度强行用时只会增加模型病态风险。拓扑结构上我按能量母线把系统拆成了四个模块电源模块、热源模块、气源模块、碳流模块。每个模块内部设备独立建模模块之间通过功率平衡方程连接。电力平衡方程上所有发电机出力加外购电加上光伏出力减去电储能充电和碳捕集电耗等于电负荷减去需求响应转移量。热力平衡类似把所有热源的热出力相加减去蓄热罐蓄热速率等于热负荷。天然气平衡则要求气源供气量等于燃气轮机和燃气锅炉的耗气量加气负荷。碳流平衡则是这个模型里最特殊也最容易被忽略的一条约束总碳排放量减去碳捕集量最终要小于碳配额或碳排上限。这种模块化设计的最大好处是方便调试。跑出不可行解时可以逐个模块单独测试先让电力系统单独平衡再让热力系统单独平衡最后再加耦合约束定位问题速度能快好几倍。2.2 设备模型与决策变量清单模型中的决策变量可以分为三类连续变量、0-1整数变量和状态变量。连续变量包括各机组出力、各设备能耗、碳捕集量、需求响应转移量、储能充放电功率等0-1变量包括机组启停状态、碳捕集装置运行状态、需求响应调用状态状态变量包括储电、蓄热、溶剂存储等随时间演化的存量。设备建模时有一个关键取舍到底按静态效率建模还是按变工况建模。例如热电联产机组如果按定热电比建模模型会非常干净但实际运行中热电比是随工况变化的。我这次采用了线性化的可行域约束把机组的电出力和热出力限制在一个多边形可行域内相比定热电比它更真实相比非线性曲线它又能保持MILP求解的友好性。对于燃气锅炉直接按热效率折算燃气消耗量对于电锅炉按电热转换效率将耗电量映射为热出力这两个设备都很简单真正的复杂度都在碳捕集和需求响应上。碳捕集电厂的内部变量尤其值得注意。捕集装置有一个“烟气分流比”的概念你可以把一部分烟气直接排放另一部分送入吸收塔。这个分流比可以连续调节意味着捕集率不是固定的而是由调度决策内生决定的。再加上溶剂存储环节相当于给碳捕集系统增加了一个“能量仓”高峰时段可以降低捕集率释放电能低谷时段提高捕集率多捕碳这就是碳捕集电厂能参与调峰的根本原因。2.3 目标函数怎么设计才不跑偏目标函数我最终采用了系统总运行成本最小化。具体包含四项燃料成本、从外部电网购电成本、需求响应补偿成本和碳排放成本外加机组启停成本。燃料成本按天然气消耗量乘以气价计算购电成本按分时电价计算需求响应补偿成本按可中断负荷容量费加电量费用计算碳排放成本直接影响决策比如碳配额内免费超额部分需要购买碳配额。设计目标函数时最需要想清楚的一点是碳价到底放进去还是当成约束我两种方案都试过。如果只作为约束系统会优先用成本最低的方式把所有碳排放压到配额线以下不会产生“多减排换收益”的激励如果把碳价放进目标函数那么系统会根据碳价和捕集能耗成本自动权衡减排力度。我最终选择了后者碳价给到一个合理区间这样碳捕集装置的投运与否、捕集率高低都由经济性驱动而不是人工强行指定。还有一个小陷阱目标函数不能只看总成本还必须给储能或蓄热设备保留合理的运行空间。如果分时电价变化不大储能设备很可能在优化结果中完全不动作这倒不是模型错误而是经济上确实不划算。这个结果本身是有价值的但如果你希望看到储能参与调峰就得检查分时电价差是否足够覆盖储能损耗成本。3. 约束条件构建最容易翻车的地方3.1 碳捕集电厂的运行约束与能耗惩罚碳捕集电厂的建模是整个模型里最容易出错的地方。先说净出力约束。假设机组毛出力为 P_gross捕集能耗为 P_cc那么并网净出力是P_net P_gross - P_cc这个公式看起来简单但P_cc本身不是常数它取决于烟气流量和捕集量。工程上常用简化方式是按捕集量折算电耗和热耗也就是每捕集一吨CO2需要消耗固定数量的电能和蒸汽。例如设定每吨CO2捕集电耗为100千瓦时热耗为2吉焦那么捕集量越大净出力压降越明显。烟气分流比也是一个需要考虑的变量。设总烟气含碳量为 E_total分流进入吸收塔的比例为 split则捕集量为C_capture split * E_total * capture_efficiency未捕集的烟气和吸收塔尾气共同构成系统净排放。这条约束天然带有非线性因为 split 乘 E_total但E_total又取决于机组出力处理方式是引入一个大M变量或直接在0-1状态变量下分段线性化。我的实际做法是0-1变量表示“捕集装置是否投入运行”投入时烟气分流比只能在上下限之间变化不投入时捕集量和能耗全部为0。同时给碳捕集装置加一个最小技术出力约束防止模型为了省钱把捕集率设成一个极低但又不切实际的数值。这个看似很小的约束在实际求解中对可行域影响非常大。3.2 需求响应负荷的柔性边界需求响应建模要特别注意不要“过度柔性化”。真实用户可以调整的负荷永远是有限的不可能一天之内把所有负荷凭空消失或凭空增加。我在模型里用到三个核心约束可转移负荷的平衡约束所有时段转入的总负荷量必须等于转出的总负荷量。例如一天内从高峰时段转移出去100兆瓦时就必须在低谷时段补回来100兆瓦时否则相当于凭空省了电结果一定失真。转移时段限制单个负荷的转移时长必须小于合同约定的最大转移时间。比如约定一次最多转移3小时那就不能用5小时的长时转移来实现削峰。可中断负荷容量约束每个时段最多中断的负荷量不能超过签约容量而且中断后必须支付对应的补偿费用。中断负荷不像转移负荷那样需要“还回来”它本质上是用钱买服务所以约束较为简单但成本项要算清楚。需求响应还有个容易忽略的副作用转移负荷会改变系统原始负荷曲线进而影响碳捕集电厂的最优运行策略。这两者之间是强耦合关系所以不能先定负荷曲线再优化碳捕集策略必须在同一个模型里同时决策。3.3 热网/气网耦合约束处理电、气、热三个系统的耦合主要体现在热电联产机组上。它同时吃天然气发电力产热力所以它的运行点必须在“电出力-热出力-耗气量”三维空间中可行。如果用定热电比约束很简单但会牺牲灵活性我更推荐用可行域法把机组启停、爬坡、最小出力、最大出力都写成线性约束。热力系统还有一个建筑热惯性的问题。园区供冷供暖负荷不是刚性不变的建筑物本身可以蓄热提前一小时供暖也不会让室内温度立刻超标。模型里我用了一个简化的一阶等效热容模型把热负荷变成可延迟的柔性负荷并设置室内温度上下限约束。这个模型的引入让热负荷时序直接受到电负荷和碳捕集装置运行状态的影响协同效应一下子就出来了。天然气网络在园区级别通常可以简化处理不考虑管网的动态特性只按小时气量平衡约束限制购气上限。但如果要考虑管网压力约束或者气源供气波动就必须引入Weymouth方程它是典型的非线性约束。如果求解器处理不了可以做成分段线性化或者干脆用迭代法先算压力场再更新气量可行域避免直接非线性求解带来的不收敛问题。3.4 碳流平衡与碳排放约束碳流平衡约束是这个模型和其他普通经济调度模型最大的区别。系统总碳排放包含两部分燃气轮机的燃烧排放和燃气锅炉的燃烧排放如果外购电也会产生间接排放还需要按电网排放因子折算。总排放量减去碳捕集量等于最终净碳排放量这个净排放量要小于系统碳配额或碳排放上限。还有一个容易被忽略的约束是溶剂存储平衡。捕集下来的CO2如果马上送去封存或利用受限于下游消纳能力如果你在模型里考虑了溶剂罐库存就相当于给碳捕集系统增加了一个存储通道可以在低电价时段多捕碳储存在溶剂中在高电价时段减少捕集输出更多电力。这其实是全模型里最出彩的一个灵活调节手段它的价值相当于给发电侧也装了一块“碳储能电池”。溶剂罐约束形式为当前时段库存等于上一时段库存加上本时段捕集量减去本时段解吸或外运量。库存有上下限末端库存一般约束为不小于初始库存以保证日调度的可持续性。不加这条约束模型极有可能在最后一个时段疯狂捕碳把一整天没捕的碳全部“补作业”结果完全失真。4. 求解思路与代码实现要点4.1 模型线性化与求解器选择模型规模大致是这样的24个时段4台主要设备3个储能装置约2000个变量其中整数变量不到100个。这个规模对标准MILP求解器来说非常轻松用开源求解器也能算但我实际用的是商业求解器差别主要在求解速度和对数值稳定性的容忍度上。如果你的模型再往上扩展到几百个节点或8760小时建议直接上商业求解器并开启求解器的MIP gap容忍度设置别死磕最优性。为了让求解器吃得消所有非线性都做了线性化处理。煤耗曲线采用分段线性逼近机组可行域用多面体约束表示烟气分流比乘机组出力这种双线性项通过McCormick包络或大M法线性化天然气管网压力约束直接忽略或分段线性化。整个过程看起来繁琐但本质就是一句话能用线性表达式写出来的绝对不用非线性函数。4.2 核心建模骨架参考我用的是Python加MILP建模语言搭的模型下面给出几个核心代码片段仅供参考。目标函数部分的逻辑是先定义设备运行成本、购电成本、需求响应补偿和碳排放成本最后汇总取最小化。约束方面最核心的是电力平衡约束和碳捕集能耗约束这两个写对了模型基本就立住了一半。目标函数代码段示例model.obj pyo.Objective( exprsum( fuel_cost[t] buy_power_cost[t] dr_cost[t] carbon_cost[t] for t in model.T ), sensepyo.minimize )电力平衡约束示例def power_balance_rule(model, t): return ( model.P_chp[t] model.P_pv[t] model.P_buy[t] model.P_discharge[t] - model.P_charge[t] - model.P_cc[t] - model.P_eb[t] model.P_load_base[t] - model.P_dr_shift_out[t] model.P_dr_shift_in[t] )碳捕集能耗约束示例def cc_energy_rule(model, t): # 捕集电耗正比于捕碳量 return model.P_cc[t] model.cc_electricity_intensity * model.C_capture[t]多时段多设备耦合比较大的项目建议每个约束函数只做一件事命名尽量直白。因为后面调试不可行解时你要能在控制台里快速定位是哪条约束在哪个时段卡住了函数名写得太抽象会非常折磨人。4.3 参数设置与典型结果解读参数设置这一块我直接给一个可以照抄的基准值天然气热值取35.6兆焦耳每立方米气价按2.8元每立方米光伏装机10兆瓦预测曲线采用典型的晴天曲线分时电价峰平谷分别为1.2、0.8、0.4元每千瓦时碳配额设为一周平均排放量的90%左右碳价按80元每吨。碳捕集装置的单吨电耗设为110千瓦时每吨热耗设为2.5吉焦每吨。在这个基准参数下我跑了四组对照第一组什么都不加第二组只加碳捕集第三组只加需求响应第四组两个都加。结果很有意思只加碳捕集时系统总成本上升了约12%因为捕集能耗本身是净负荷会推高购电和燃料成本只加需求响应时系统成本下降了5%主要来自峰时购电量的削减两个都加时总成本只上升了4%比单独加碳捕集的12%明显低。原因是碳捕集装置在低谷时段多捕碳、在高峰时段降低捕集率让路给电负荷需求响应又把高峰负荷往低谷转移等于给碳捕集制造了更多低压运行空间。两者叠加产生的系统协同效应就是这类模型最有价值的产出。5. 实操中的坑与排查技巧5.1 碳捕集能耗参数设错导致无解我第一次跑这个模型时直接给碳捕集装置设了固定电耗常数没把它和捕集量挂钩。结果在光伏出力最高的中午时段模型让碳捕集装置满负荷捕碳净出力骤降电力平衡却要求它对外输出大量电力最后无解。排查了很久才发现问题出在能耗方程上。后来把捕集电耗改成与捕集量线性相关并在捕集装置投入运行的状态下加上最小捕集率约束模型才稳定下来。这类问题的典型特征是无解的时段集中在某个极端工况附近比如光伏大发、负荷低谷或负荷尖峰。排查时不要一个时段一个时段瞎试先把平衡方程拿出来手动核算一下该时段“总供给减总需求”是否真的闭合多数情况下马上就能看到是哪一方被约束卡死。5.2 需求响应削峰填谷不明显的常见原因调参时曾遇到一个问题需求响应成本调得很低模型却几乎不调用需求响应资源。后来检查发现需求响应的补偿成本虽然低但转移负荷增加的时段恰好也是电价较高且机组已接近最大出力的时段模型为了让转移过来的负荷落地必须加开机组或增加购电这部分额外成本抵消了需求响应的收益。换句话说需求响应不是“负荷软了就行”还要看负荷转移目标时段的发电侧是否存在接纳空间。解决办法是给需求响应加一个最小调用时长约束并检查低谷时段是否有足够的备用容量。如果低价时段机组已经压到最低出力那需求响应转移过去的负荷反而会推高成本模型自然不愿意调用。这是很反直觉的一点需求响应削峰填谷的前提是谷时段真的“有谷可填”。5.3 热负荷时序与电负荷耦合导致模型病态还有一次模型出现了“抖动解”相邻时段的蓄热罐充放速率来回剧烈变化成本却没有明显改善。原因是热负荷等效热容模型时间常数设得太小导致模型认为建筑热惯性几乎不存在蓄热罐成为唯一的热缓冲手段。把热容时间常数从0.5小时调整为2小时后抖动现象马上消失。这提醒我一个原则模型柔性越大越要关注解的合理性。柔性负荷也好储能也好加多了以后模型会出现大量“不花钱”的调节空间求解器会在这些空间里来回切换最优解导致对结果分析失去意义。所以每个柔性资源都要配上现实中的响应时间常数、爬坡限制、最小运行时间不能为了“好看”而无限制地增加自由度。5.4 快速校验模型的一些土办法调试模型时我有几个土办法虽然不高级但非常管用。第一把所有柔性资源参数设成极端值比如需求响应补偿设为0、碳价设为0看模型结果是否退化成一个普通的经济调度问题如果结果和预期逻辑不一致说明某些约束写错了。第二把全天负荷和可再生能源出力乘一个系数比如整体缩小10倍看模型结果是否也等比例变化如果出现非线性放大多半是某条约束漏了单位换算。第三随时用“检查每个时段的电力供给减需求是否为0”的脚本做后处理即使求解器报告最优也不要完全相信因为数值容差偶尔会让个别时段的平衡偏差超限虽然大问题不至于但会严重影响碳排核算精度。这套模型我前后迭代了将近三周从最初的根本跑不动到后来能稳定输出可解释的调度方案中间踩的坑基本都集中在耦合约束的线性化、柔性资源的参数标定和数值稳定性上。综合能源系统优化调度理论上很美落地时全是细节。如果你也在折腾类似模型建议别急着把模型搞复杂先把电、热、气、碳四条主线的平衡方程写对再逐步叠加需求响应和碳捕集的灵活性一步一步来模型才能真正跑出让你信服的结果。