恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
碳交易与需求响应下的园区综合能源系统优化运行MILP建模
首页
资讯中心
/
碳交易与需求响应下的园区综合能源系统优化运行MILP建模
碳交易与需求响应下的园区综合能源系统优化运行MILP建模
发布时间:2026/10/7 5:19:17
过去大半年时间我一直在折腾一个很“上头”的课题碳交易机制下需求响应的综合能源系统优化运行模型。听起来像论文标题但本质上是个非常落地的工程问题——一个园区里同时有燃气轮机、光伏、储能、电锅炉还有五花八门的电负荷和热负荷我要在碳配额约束下让整个系统的日运行成本最低同时还要把用户侧那部分可调动的负荷资源用起来。说白了就是给园区算出一个“既要省钱、又要减排、还得让用户配合”的24小时运行方案。这篇文章会把我完整的建模思路、参数设计、求解细节、踩过的坑全部展开。我不是来做科普的是想给正在做综合能源系统调度、微电网优化、碳资产管理或者需求响应方案的朋友一份能直接抄作业的参考。无论你是搞研究的、做设计的还是自己手上有园区项目要落地这篇文章应该都帮得上忙。先说清楚这是一个典型的**混合整数线性规划MILP**问题我以一天24小时、1小时间隔为调度尺度目标函数覆盖购电成本、燃料成本、碳配额交易成本、需求响应补偿成本约束覆盖电/热功率平衡、设备出力上下限、储能SOC连续性、爬坡约束和碳配额约束。下面逐个环节拆开讲。1. 模型要解决的核心问题1.1 综合能源系统优化到底在优化什么综合能源系统这个词这几年已经快被说烂了但真正做优化的人会知道它的核心难点在于“耦合”。电和热不是两条独立的管道燃气轮机在发电的同时必然产热余热锅炉把高温烟气变成采暖蒸汽电锅炉又把电变成热储能装置同时能存电蓄热罐能存热整个系统在每一个时刻都必须同时满足电功率平衡和热功率平衡。我做这个项目的时候反复提醒自己优化不是简单把各个设备的成本叠加起来让总量最小而是要让每个设备在哪个时间点出力、出多少力与外部电价信号、碳价格信号、用户负荷曲线形成共振。举个非常直观的例子中午光伏大发的时候如果电价也低、碳配额压力也小那燃气轮机就应该压低出力甚至停机晚上电价飙升如果燃气轮机有余热可以满足采暖它就应该顶上去发电余热顺便供热替代高成本的电锅炉。这种“设备之间的角色切换”靠人工经验根本算不全面必须用优化模型在约束空间里找全局最优解。1.2 碳交易机制切进来的逻辑碳交易机制进入优化模型等于在原本“看钱办事”的目标函数里额外塞了一个碳价格。原来你算成本只算电费、气费现在还要算你系统这个调度周期排了多少碳、手头有多少免费配额、多排的部分要从碳市场买、少排的部分可以卖出去赚钱。最关键的转变是——碳排放权从“约束”变成了“可交易资源”。免费配额像一个初始资产排放量小于配额意味着你有资产结余能变现排放量大于配额意味着你要额外支出购买配额。这样一来优化模型就会主动让系统去调整电源结构比如优先用光伏替代市电、用燃气轮机的高效区间发电、减少从高碳电力的电网购电。在这个模型里碳配额交易成本不是简单加一个固定罚款而是以一种线性形式嵌入目标函数。它一方面要求我引入一个“排放-配额”差值与碳价的乘积项另一方面还要求我动态判断多少个配额适合卖出、多少个时段需要预留排放空间。碳价越高模型越倾向于低碳设备这就是机制设计的核心价值。1.3 需求响应在这里是真金白银的成本项需求响应常常被讲得特别“高大上”什么用户侧灵活性、虚拟电厂、柔性负荷但在优化模型里它就是非常朴素的三个选择可削减负荷、可中断负荷、可转移负荷。园区里总有那么一部分负荷是无伤大雅的。空调温度调高两度、照明减个10%、某些工艺可以错峰运行几小时这些都在用户侧承受范围内。但让用户牺牲这些必须给补偿。所以需求响应进入优化模型是成本项不是奖励项。每一项可削减负荷都会产生单位补偿费用如果它低于节省下来的购电成本模型就会削如果不如直接买电划算模型就不碰。这么一带入需求响应就不再是“削峰填谷”的漂亮口号而变成了有明确边际成本的资源选项。配合碳交易之后它的意义更上一层楼——在碳配额紧张的时段削减负荷等于直接减少碳排放配额需求一石二鸟。2. 园区场景设定与数据准备2.1 我搭建的园区系统拓扑为了让模型具体化我设计了这样一个园区综合能源系统。设备清单如下燃气轮机额定功率200kW最低稳定出力50kW发电效率33%热电比1.2。光伏阵列装机容量50kW出力按预测曲线。电化学储能额定充放电功率100kW容量200kWh充放电效率95%SOC范围10%-90%。电锅炉额定功率60kW效率95%承担补充供热任务。余热回收锅炉回收燃气轮机烟气余热热效率80%。与外部电网连接可购电、可售电购售电价分时区别。热负荷由余热回收优先承担不足部分由电锅炉补足蓄热罐在这个模型里暂时不启用避免变量数量过多导致求解时间失控。电负荷则由光伏、燃气轮机、储能和外部购电共同满足。2.2 分时电价、燃料价格和碳价参数电价采用典型工商业峰谷三段式。峰时段设定为10:00-15:00和18:00-21:00购电价0.9元/kWh平时段7:00-10:00、15:00-18:00、21:00-23:00购电价0.6元/kWh谷时段23:00-次日7:00购电价0.3元/kWh。售电价按购电价的80%计算防止无意义套利。天然气价格按2.5元/m³天然气热值9.7kWh/m³。这么算下来燃气轮机每发1kWh电的燃料成本大约是2.5 / (9.7 × 0.33) ≈ 0.78元/kWh。对比峰时购电价0.9元/kWh其实燃气轮机在峰时段是有经济优势的这就是模型会主动优化出来的结果。碳排放参数方面市电排放因子取0.6kg CO2/kWh天然气排放因子按燃烧热值折算约0.2kg CO2/kWh。碳交易价格设定为0.1元/kg也就是100元/吨这基本接近目前国内碳市场的成交区间。2.3 四个对比场景的设计模型做出来不能光看一个结果必须得对比。我设定四种运行场景场景A传统经济调度。不引入碳交易也不做需求响应只优化购电、燃料和设备出力目标就是总运行成本最低。场景B只引入碳交易。目标函数加碳配额交易成本但不做需求响应。场景C只做需求响应。目标函数加需求响应补偿成本但不考虑碳配额。场景D碳交易 需求响应联合优化。完整模型也就是课题真正要研究的对象。四个场景跑在同一套负荷数据、同一套价格参数下最后对比总成本、碳排放量、购电结构能非常清楚地看到碳交易和需求响应各自贡献了多少。这个对比逻辑是项目成败的关键所在。3. 数学模型的搭建细节3.1 目标函数每一分钱花在哪优化目标设置为单目标最小化即系统日运行总成本。数学上可以写作目标F 购电成本 购气成本 - 售电收入 碳配额交易净支出 需求响应补偿成本逐项拆开购电成本是分时电价乘以各时段购电量购气成本是气价乘以燃气轮机各时段耗气量售电收入是售电价乘以售电量碳配额交易净支出是碳价乘以当日总排放量与免费配额的差值需求响应补偿成本是削减负荷量与单位补偿单价的乘积。这里的决策变量包括各时段燃气轮机出力、市电购入/售出功率、储能充放电功率、电锅炉供热量、各时段可削减负荷量、各时段实际电/热负荷值。整条目标函数线性可加没有非线性项这也是后续用商业求解器能快速收敛的前提。3.2 碳配额约束与排放计算碳排放量的计算不是把用电量乘以排放因子那么简单必须分来源:外购电力产生的间接碳排放按购电量×市电排放因子计算。天然气燃烧产生的直接碳排放按耗气量×天然气排放因子计算。光伏和储能在运行过程中不产生碳排放。免费碳配额按基准线法设定。针对这个园区规模我给出日免费配额400kg CO2。如果系统当日排放量低于400kg配额富余部分按碳价出售获利如果高于400kg超出部分必须从碳市场购买购买成本计入目标函数。这里有一个设计上的心得碳配额不应该按单个时段独立分配而应该按调度周期整体结算。如果按小时分配会出现某个时段配额用不完、另一个时段配额不够的情况加剧模型刚性导致结果偏离园区实际的碳资产管理模式。所以我在模型里用的是“全局配额约束”即整个24小时周期排放总量与配额总量比较而不是每个时段各算一笔。3.3 需求响应的约束建模需求响应在模型里我采用“可削减负荷”的方式建模即一部分电负荷可以在高峰时段被削减但每个时段削减量不能超过该时段原始电负荷的15%并且用户会按0.35元/kWh的标准获得补偿。这里最关键的是要把“原始负荷”和“实际负荷”区分开。设原始电负荷是一个外部参数实际电负荷等于原始电负荷减去削减量。削减量本身是决策变量上限为原始电负荷的15%再乘以一个0-1变量的开关也允许模型决定某个时段完全不削。补偿价格我特意设置为0.35元/kWh介于谷段电价和平时段电价之间这样模型不会一刀切把所有可削减负荷全部削掉而是在峰时段选择性削减。这个参数是项目里最敏感的参数之一我后面在问题排查部分会专门再讲。3.4 电功率平衡和热功率平衡约束电功率平衡是每一类微电网模型都无法回避的等式约束实际电负荷 储能充电功率 光伏出力 燃气轮机发电 市电购入 储能放电功率这个等式是每个时段强制成立的。如果光伏大发、负荷低谷储能该充电就充电甚至可以向电网售电来消纳冗余。如果光伏出力不足、电网电价又高燃气轮机就要顶上去。热功率平衡相对简单一些热负荷 燃气轮机余热回收供热量 电锅炉供热量余热回收供热量等于燃气轮机发电量乘以热电比再乘以热回收效率。电锅炉供热量等于耗电量乘以电热转换效率。注意电锅炉在电功率平衡里体现的是消耗电在热功率平衡里体现的是产出热这是一个典型的耦合点也是最容易造成约束冲突的地方。4. 求解实现与结果复盘4.1 用Python构建MILP模型求解器我用的Gurobi建模语言是Python。核心代码结构大致是这样import gurobipy as gp from gurobipy import GRB T range(24) # 决策变量 p_gt m.addVars(T, lb50, ub200, nameGT出力) # 燃气轮机 p_buy m.addVars(T, lb0, ub300, name购电) p_sell m.addVars(T, lb0, ub200, name售电) e_ch m.addVars(T, lb0, ub100, name储能充电) e_dis m.addVars(T, lb0, ub100, name储能放电) soc m.addVars(T, lb20, ub180, nameSOC) # 单位kWh p_cut m.addVars(T, lb0, ub40, name削减负荷) p_eb m.addVars(T, lb0, ub60, name电锅炉耗电) # 目标函数 m.setObjective( sum(price_buy[t] * p_buy[t] for t in T) gas_price * sum(gas_consume[t] for t in T) - sum(price_sell[t] * p_sell[t] for t in T) carbon_price * (emission_total - quota_total) dr_price * sum(p_cut[t] for t in T), GRB.MINIMIZE )当然实际代码里要把排放总量、燃气消耗量、设备爬坡约束、储能SOC递推方程全都写成具体的线性表达式。这里我建议所有变量约束统一用循环式添加不要一条条手写不然24时段下来光是排查笔误就够喝一壶。4.2 储能SOC递推与运行边界储能SOC的递推是蓄电池约束里最容易出错的地方。公式是SOC(t1) SOC(t) 充电功率×充电效率 - 放电功率/放电效率这个公式本身简单但要注意两个坑。第一SOC必须落在20kWh到180kWh之间不能等到24时段累计结束才看是否越界要每个时段都设置约束第二SOC的初值设定会影响全天运行结果我统一把SOC初值设为100kWh并且要求调度周期末SOC回到100kWh这样储能就不是一个“白拿的能量源”它只是能量的搬运工模型必须为挪用的每一度电在谷时段补充回去。这个约束加上去之后模型会明显变得更“理性”不会为了某一小时的尖峰电价把电池彻底放空因为末端SOC还要回正。4.3 四场景运行结果对比我把四组结果整理成了一张对照表这是整个项目最有说服力的一张表场景总运行成本(元)碳排放量(kg)购电总量(kWh)燃气轮机发电(kWh)削减负荷量(kWh)场景A 传统经济调度98626125804200场景B 只引入碳交易96355084305200场景C 只做需求响应947458848046058场景D 碳交易需求响应924646237056083只看数字四个场景的差异非常直观。场景A是纯成本驱动燃气轮机和购电的比例完全是“怎么便宜怎么来”场景B引入碳交易后模型主动压低了购电把更多出力转移给燃气轮机并减少了总排放场景C用需求响应削减了58kWh的峰时负荷成本明显下降但碳排放改善有限因为削减负荷削掉的更多是边际电量的碳总量贡献不大场景D两个机制叠加购电降到了370kWh碳排放降到462kg总成本比场景A节省了6.2%。这样对比下来就特别清楚碳交易主要在“供给侧”改变电源结构需求响应主要在“需求侧”改变用电曲线二者不是简单的加减法而是互相咬合的。需求响应削掉了峰时的高碳高价电碳交易则保证了夜间谷时储能充电、燃气轮机避开低效低负荷区间最终效果11大于2。5. 实操过程踩过的坑5.1 一上来就无解先别怀疑数据查初值我第一版模型跑出来的结果永远是“Model is infeasible”Gurobi只报一个Infeasible不告诉你哪里冲突。我花了一个下午把约束逐一注释掉才定位到是储能SOC递推方程惹的祸我把SOC初值设成100kWh却把SOC最小限制设成了180kWh这等于要求电池一开始就超过上限当然是死局。这类问题建议用两种手段定位。一是直接把模型写出来之后先跑一个“可行性模式”Gurobi里用computeIIS可以找出最小不可行约束集二是逐个放开约束观察哪个方向能通过。我做项目的习惯是先跑一个没有碳配额约束和需求响应约束的纯净版调度确认设备出力和储能充放电本身没问题再逐层加约束。这样出了问题一定出在新加的约束里。5.2 爬坡约束与启停约束是线性化的难点燃气轮机不是发电机不能随便从50kW跳到200kW每分钟爬坡率是有限制的。给燃气轮机加爬坡约束之后又发现一个问题如果机组要关停再启动爬坡约束会把启动过程卡得非常死。工程上常用办法是把“启停”作为一个0-1变量引入然后对启动状态做特殊约束启动时出力直接跳到最小技术出力以上正常运行时用爬坡约束限制相邻时段变化量。这个逻辑本身不算难但代码里最容易犯的错是启停变量和出力变量的关联约束写反了。我的建议是把启动成本放在目标函数里用启停变量乘以一个启动成本系数让模型综合判断“频繁启停省下来的燃料够不够覆盖启动成本”。这个取舍不做进去模型会给出一个特别僵硬的运行曲线看似可行实际没法执行。5.3 需求响应补偿单价别拍脑袋需求响应补偿单价我一开始拍脑袋定了个0.5元/kWh算出来的结果特别保守整个调度周期才削减了不到20kWh负荷。后来我意识到问题峰时购电价才0.9元/kWh储能低谷充电峰时放电的综合成本大约0.35元/kWh天然气发电成本0.78元/kWh如果削减负荷要给0.5元/kWh补偿显然不如储能放电和燃气轮机顶上去划算。后来我把补偿单价降到0.35元/kWh之后削减量才开始变得合理。这给了一个特别重要的启发需求响应补偿单价的上限必须低于最贵边际电源的等效成本。在这个系统里最贵边际电源是峰时购电0.9元/kWh第二贵是燃气轮机0.78元/kWh储能供电成本约0.35元/kWh所以合理的削减补偿区间应该在0.35到0.5元/kWh之间。太大了模型不削太小了用户不可能接受。这是需求响应建模里最需要反复试的参数。5.4 碳配额总量不同运行策略会从“买配额”切换成“卖配额”免费碳配额从每日100kg扫到800kg最优解的形态会发生一次质变。配额紧张的时候模型想尽办法减排包括增加燃气轮机出力、减少购电、允许更多需求响应削减此时碳价约束的“影子价格”很高配额充足的时候模型就敢多用市电因为碳配额富余可以拿去卖卖碳收入甚至能弥补一部分购电成本。这个特性意味着园区碳资产管理不能机械追求“少排放”而是要算清楚“每减少一公斤排放机会成本是多少”。如果碳价0.1元/kg而谷时市电比燃气轮机便宜很多那用市电多排一点、把配额卖出去反而是最优策略。所以模型里我没有设定“排放最小化”目标而是把碳交易差价放进经济目标里让经济账自己去平衡。6. 这个模型还能往哪些方向扩展6.1 从确定性优化到随机优化目前所有光伏出力曲线、负荷曲线都是预测数据模型完全是开环的。在实际运行里光伏预测误差、负荷波动、碳价波动都会影响当天最优运行策略。我已经在准备第二版模型把光伏和负荷场景集引入用两阶段随机优化替代确定性优化。简单说就是第一阶段决定燃气轮机启停、储能初始SOC这些“慢变量”第二阶段根据不同的光伏、负荷场景做再调度让总期望成本最小。6.2 引入碳流追踪和能耗双控指标现在的模型只追踪了系统整体的碳排放总量但没有精确回答“每个时段末端用户实际消耗了多少碳”。这属于碳流追踪的范畴核心思想是碳排放是跟着能量流走的光伏出力对应零碳燃气轮机对应高碳储能呢储能在谷时充的电是低碳电峰时放出来就带走了这份低碳属性这部分碳产权判断会直接影响用户侧碳排放核算。尤其在碳市场未来可能面向用户侧展开的情况下这个方向非常值得探索。6.3 考虑加入P2G电转气设备园区如果未来有氢气需求可以把电转气设备加进来利用谷时电力制氢氢气既可以作为燃气轮机的燃料替代天然气也可以外售。P2G本质上是把电、气、碳三者耦合得更深目标函数里会再多一个氢气销售收入项和电解槽启停约束。不过目前P2G设备成本还偏高现实中是否划算取决于具体的氢气价格和谷电价格需要仔细算一笔账再说。坦白讲这类综合能源优化模型做一次不难难的是每次改参数、改边界条件都要保证模型逻辑上没有遗漏。我做这个项目最深的体会是指望模型自动给出一个可靠结果远不如自己先把物理过程想透彻更重要。设备耦合关系、碳排放责任归属、需求响应补偿边界、碳配额结算周期每一个环节的建模误差都会传导到最终运行方案里。如果你也要做类似的系统我建议先把电/热平衡、设备出力限制、储能SOC这三类基础约束写扎实再逐步叠加碳交易和需求响应。千万不要一上来就搞一个大而全的模型那样你根本分不清哪些结果来自碳价、哪些来自负荷曲线、哪些来自设备耦合。从小到大逐级加约束出了问题能精准定位这才是做优化运行模型最省时间的一条路。