电热综合能源市场双层出清模型与能源集线器建模实践

发布时间:2026/10/2 3:28:07
电热综合能源市场双层出清模型与能源集线器建模实践 1. 为什么要把电和热放进同一个市场出清1.1 传统“电热分账”模式的尴尬前一阵子我在做一个园区级综合能源项目的仿真任务是把电热综合能源市场的出清逻辑跑通。这个方向看似小众实际上在综合能源系统、区域能源规划、电力市场机制设计里都是绕不开的核心问题。所谓“电热综合能源市场”简单说就是把电力市场和热力市场的交易放在一个统一的框架里联合出清而不是各算各的账。而“双层出清模型”是这个统一框架里最常见也最难缠的一种建模方式它要描述的是市场运营者和能源枢纽参与者之间的博弈关系。至于“能源集线器”Energy Hub则是耦合电、气、热多种能源流的经典抽象工具是整个模型里连接物理系统与市场行为的关键节点。传统模式下电和热由电网公司和热力公司分别调度、分别结算二者只在物理上通过热电联产机组发生联系。电网侧看到的是CHP机组的最大电出力热力侧看到的是供热量的调度自由度可实际上这两件事被同一台机组的运行可行域牢牢绑在一起。以热定电是供热期的常态电网调度想要电出力时热网却可能没有对应的热需求反过来热网需要加大供热时电网又可能因为调峰压力不接受额外的电出力。这种“电热分账”模式在能源系统规模小、耦合设备少的年代问题不大但是当园区里出现电锅炉、储热罐、热泵还有大量可调节电热负荷时缺失统一出清机制的后果就是价格信号互相打架设备利用率低下甚至出现一边弃风弃光、一边烧气供热的荒诞场景。我做这个项目最大的动机就是想把这套逻辑用模型说清楚而不是继续停留在“应该耦合”的口头共识上。1.2 能源集线器为什么是建模抓手做电热联合市场建模时最让人头疼的不是写目标函数而是怎么描述“一个节点同时输入电和气、输出电和热”这类多能流耦合关系。能源集线器之所以被大量文献采用是因为它把复杂的设备矩阵收敛为一个清晰的输入-输出耦合关系输入侧是电网购电、天然气、光伏输出侧是电负荷、热负荷中间用耦合矩阵把所有换能设备的转换效率、运行约束打包进去。所以建模上手的第一步不是翻设备手册而是先把输入输出端口定死再往里填设备的效率系数这样整个模型的结构就不会乱。实际建模中我不建议一上来就搞复杂设备模型。尽量先用线性的能源集线器结构把市场机制跑通再去扩展非线性部分。因为双层出清模型的求解难度已经足够高如果设备模型再引入非线性、非凸约束求解器和调试时间都会呈指数上升。很多论文里用复杂的CHP可行域多边形但工程实现时先用几段线性近似就能把主要特征保留住后面如果确实需要描述机组运行域细节可以在模型跑通之后逐层加入多边形约束再观察求解时间是否还能接受。1.3 谁适合读这个方向这篇文章适合的对象比较明确一是做综合能源系统规划与运行的研究生二是能源交易平台、园区微网项目的技术工程师三是想快速了解电热市场出清机制的产品经理或投资分析师。阅读门槛其实不高最好有最基础的优化理论概念比如目标函数、约束、KKT条件是什么但如果你只是想知道双层出清大概怎么搭、能源集线器如何建模也可以直接跳过我讲求解细节的部分。我尽量把工程上踩到的坑和实际运行中验证过的思路写清楚而不是停留在文献综述层面。说句实话把电热市场做联合出清本质上不是数学题而是机制设计题。数学只是工具真正决定模型好坏的是你让谁先动、谁后动上层和下层各自追求什么目标价格信号怎么传递以及哪些约束在物理上不可以放松。想清楚了这些MATLAB只是顺手的事。2. 双层出清模型结构、博弈逻辑与求解思路2.1 上层和下层各扮演什么角色电热综合能源市场的双层出清模型对应的是经济学里的Stackelberg博弈。我的经验是建模前先花半天时间想清楚谁是“领导者”、谁是“跟随者”比急着写代码重要得多。多数文献里上层通常是独立系统运营商或园区能源管理中心负责制定统一的电、热出清价格同时以系统总运行成本最小或者社会福利最大为目标安排各设备的调度出力下层则是若干个能源集线器运营商或者大用户、聚合商他们拿到价格信号后以自身利润最大化为目标确定购电、购气、产热、储热等具体计划。上下层之间不是一个包含关系而是通过市场结算变量耦合起来。上层想压低系统成本下层想多赚利润二者目标并不一致这种不一致恰好就是博弈发生的地方。设计时要特别注意信息流的方向上层先发布价格或调度指令下层据此做出最优反应上层再把下层的反应作为参数重新优化。如果反过来让下层先行动模型性质就变了不能套用同一套KKT转化逻辑。2.2 为什么不直接建一个单层优化很多初学者问既然目标是系统成本最小把各个EH的约束都收进一个单层优化里直接用求解器算最小成本不就行了吗答案是可以但那个模型解决的是“一体化调度”问题不是“市场出清”问题。二者区别在于单层模型假设所有参与者都服从全局最优调度而双层模型假设每个下层参与者只对自己的利益负责。这么说吧一体化调度就像家长给全家人统一安排三餐追求的是全家人总热量最合理市场出清则更像每个人自己点菜商家只负责定一个价格。个人点菜的结果必然不是全局最优但这才符合真实市场行为能源枢纽并不会为了系统利益而牺牲自己的收益。所以如果你拿到一个“电热综合能源市场”项目核心诉求通常是评价机制设计好不好、价格信号是否引导了合理行为而不是单纯求解最小运行成本。切记目标函数选错了“最优解”再漂亮也没有意义。2.3 双层模型求解的三条路线这里把三种主流求解路线做个对比方便你根据实际场景选型求解路线核心思想优点缺点适用场景KKT条件单层化把下层问题用KKT条件替换嵌入上层数学严谨能得到局部或全局最优互补约束难处理需要大M法或专用求解器下层是凸优化、规模较小的场景迭代/交替求解上下层交替计算直到价格和出力收敛实现简单代码直观可能不收敛或收敛到伪均衡模型规模大、追求工程可用的场景元启发式仿真用粒子群等算法搜索均衡改动灵活结果无法保证最优性复现性差论文初探或机制对比我实际项目里最常用的是KKT条件单层化配合YALMIP建模后用Gurobi解。原因很简单工程上需要一个可复现、可对比的出清结果。哪怕是次优解只要稳定、可解释就比一次一个结果的黑箱搜索强得多。如果你的下层问题是线性的KKT转化几乎是标准操作如果下层有整数变量比如设备启停那就要小心了KKT条件不再适定只能走迭代或者启发式。2.4 互补约束的工程化处理双层模型单层化后最难啃的骨头是互补松弛条件。它长这样0 ≤ λ ⊥ g(x) ≥ 0意思是拉格朗日乘子λ和约束g(x)中至少一个是零。YALMIP和Gurobi都不能直接处理这种“二者必有一零”的关系工程上的标准做法是引入一组0-1变量和足够大的常数M把互补条件拆成两个不等式% 大M法处理互补约束的示意 lambda sdpvar(1, n); % 拉格朗日乘子 z_comp binvar(1, n); % 0-1辅助变量 constraints constraints [lambda 0, g_lower 0]; constraints constraints [lambda M * (1 - z_comp)]; constraints constraints [g_lower M * z_comp];关于M的取值我踩过不小的坑M太小会人为排除掉可行区域M太大会导致数值病态Gurobi给出一堆警告甚至错误结果。后来我改成一种稳妥做法——先求解模型得到一个大致的解用解的约束松弛量去估算M的量级再把M设成估算值的3-5倍。这种做法虽然要多算两遍但数值稳定性好了很多尤其是约束规模大、阶数差异明显的场景里特别管用。3. 能源集线器建模耦合矩阵与设备约束3.1 从“黑箱”到“灰箱”的耦合矩阵我在文章开头说能源集线器是建模抓手这里展开讲。标准电热能源集线器模型可以写成输出向量等于耦合矩阵乘输入向量的形式P_out C × P_in其中P_in表示从外部输入的能源向量电网购电、天然气、光伏P_out表示对外供应的能源向量电、热耦合矩阵C里的每个元素是相关转换设备的分配系数和效率项。这个数学形式对理解能源集线器特别友好它把“多种能源进去、多种能源出来”的逻辑压缩成了一个矩阵乘法。实际建模中我不会只用一个大矩阵因为纯“黑箱”矩阵无法表达设备爬坡、储热时序这些动态约束。更实用的做法是“灰箱”耦合矩阵只用来表达稳态能量平衡设备本身的约束单独写成一组不等式。这样既保留了能源集线器的直观性又不至于把模型简化到失去物理意义。整个EH的状态变量也就控制在十来个左右对优化求解器的负担比较友好。3.2 一个典型EH配置的完整建模以我项目里用的典型配置为例一个能源集线器内包含热电联产机组CHP、燃气锅炉GB、电锅炉EB和储热罐TES外部输入是电网购电P_E_in和天然气G_in输出是电负荷L_E和热负荷L_H。关键约束如下我用线性化后的表达CHP热电耦合关系P_CHP k1 × H_CHP q_min其中H_CHP是该时段CHP供热出力k1是电热比的斜率q_min是最小电出力燃料消耗F_CHP a × P_CHP b × H_CHP。燃气锅炉H_GB η_GB × F_GB效率η_GB一般为0.85-0.92。电锅炉H_EB η_EB × P_EB效率η_EB一般为0.95以上注意电锅炉本质是把高品位电能降为低品位热能经济性取决于电价和热价差。电力平衡L_E P_E_in P_CHP P_PV - P_EB。热力平衡L_H H_CHP H_GB H_EB H_TES_dis - H_TES_chg。储热罐SOC(t1) SOC(t) H_TES_chg × η_chg - H_TES_dis / η_dis同时充放热功率和SOC都有上下限充放热不能同时进行。这几个约束看起来普通但联合在一起就能解释很多市场行为。比如夜间风电大发、电价很低时电锅炉会被激励增加用热产出或者储热罐启动蓄热把过剩电力转化为热能存储白天热负荷高峰时CHP和储热罐协同放热既能满足热量需求又能少烧燃气。模型能把这些行为模拟出来就意味着你抓住了电热耦合的核心而不是只在纸面上做文章。3.3 设备参数怎么取值才合理设备参数是模型容易失真、也容易引起审稿人或者领导质疑的地方。我建议用如下典型参数作为初值后面案例里还会用设备参数典型取值备注CHP电效率0.35-0.42容量不同差异较大CHP热效率0.40-0.50取决于余热回收设计CHP最小电出力系数0.3-0.5以额定容量为基准燃气锅炉热效率0.85-0.92启停快、效率基本恒定电锅炉电热效率0.95-0.98可用于消纳低谷电储热罐充/放热效率0.90/0.90储热技术相对成熟储热罐SOC范围0.1-0.9留出安全裕量特别注意CHP的热电比。定容式CHP的“以热定电”特性我用了斜率k1来近似但如果机组是抽汽式CHP可行域会复杂得多需要在P-H平面上用一组多边形不等式表达。这种多边形在文献里很常见但实现时要小心顶点顺序不然建立的约束可能把机组的真实可行域扩大或缩小。4. MATLAB实现从数学模型到可运行代码4.1 为什么选MATLAB配YALMIP做这个项目我直接选了MATLAB原因很现实团队里大家最熟的是MATLAB而且YALMIP这个建模工具箱对上层/下层变量、约束的书写支持非常好几乎所有优化问题都能用可读性很高的代码表述出来。YALMIP不是求解器它是中间层——把数学问题翻译成求解器能懂的格式再调用Gurobi、CPLEX或者fmincon求解。有用Python的朋友问我为什么不直接用Pyomo或CVXPY其实都可以核心模型和求解思路完全通用。但MATLABYALMIP有一个明显的优势调试时可以直接在工作区看每个变量的名字和数值不像Python环境里那样“变量存进去之后很难直观观察中间过程”。加上矩阵化写法非常自然向量化约束语句的可读性比循环写法高很多。当然前提是你有可用的license如果还要引Gurobi则需额外申请并配置好MATLAB的路径。4.2 代码框架决策变量、目标函数、约束下面给出一个精简但可运行的代码骨架展示怎么把上文提到的上、下层模型落到YALMIP里T 24; % 调度时段数 % —— 上层变量 —— price_e sdpvar(1, T); % 出清电价 price_h sdpvar(1, T); % 出清热价 P_CHP sdpvar(1, T); % 上层给CHP的电出力指令 H_CHP sdpvar(1, T); % 上层给CHP的热出力指令 % —— 下层决策变量以第一个EH为例—— P_buy_e sdpvar(1, T); % 从电网购电 F_GB sdpvar(1, T); % 燃气锅炉燃料输入 H_TES_chg sdpvar(1, T); % 储热罐充热 H_TES_dis sdpvar(1, T); % 储热罐放热 SOC sdpvar(1, T); % 储热罐状态 % 上层目标系统总成本最小 objective_up sum(price_e .* P_buy_e c_gas * (F_GB F_CHP)); % 下层目标EH利润最大化等价于成本减收益最小化 objective_lo sum(price_e .* P_buy_e c_gas * F_GB ... - price_e .* P_CHP - price_h .* H_CHP);啰嗦一句YALMIP里用sdpvar定义连续变量、binvar定义0-1变量。求解器选择通过sdpsettings指定ops sdpsettings(solver, gurobi, verbose, 2, ... mip_tolerances_integrality, 0, ... mip_tolerances_mipgap, 0.01);如果你不需要特别高的精度mipgap设成0.01-0.001就够了没必要追求0否则求解时间会明显变长。4.3 下层KKT条件的自动生成YALMIP最方便的一点是不用手写一大堆拉格朗日和偏导表达式。它提供kkt函数可以提取约束对应的对偶条件constraints_lo [P_buy_e 0, F_GB 0, ...]; % 下层约束集合 KKT_system kkt(constraints_lo, objective_lo);注意上层问题的约束中需要加入下层KKT系统然后一起交给求解器。如果下层存在双线性项比如价格乘以电量或者非凸约束kkt函数会报错或者生成系统不对这时只能手动推导KKT别偷懒。手动推导时我最常犯的错误是漏掉非负变量的KKT条件导致求出来的“均衡解”实际上并不满足下层的利润最大化条件。检查方法很笨但有效拿求出的解反代到下层优化里看单独求解下层问题时是否还有更优方案。4.4 迭代求解的备选方案如果你觉得KKT单层化写起来太繁琐还有一个工程上更省事的尝试机会上下层迭代。具体流程是先给电价和热价一个初始值求解每个EH的下层优化得到购电、产热等计划再把所有EH的计划汇总到上层更新系统成本和出清价格把新价格返回下层反复循环直到价格和出力变化小于阈值。这个方案最大的问题是可能无限振荡尤其当价格信号直接耦合到电锅炉、储热罐这类快速响应设备时会出现“今天电价高明天就低”来回翻转的情况。解决办法是加阻尼每次迭代只取新价格的20%-50%作为输入相当于给博弈加惯性。虽然理论上没法保证收敛到真解但工程上往往足够用而且代码简单得多。5. 案例一个小型电热市场出清的完整流程5.1 场景设置与基础数据为了演示双层出清怎么跑通我设置了一个典型园区系统一个上层运营商管辖两个能源集线器EH1、EH2每个EH内配置一台CHP、一台燃气锅炉、一台电锅炉和一个储热罐。外部电网提供分时购电天然气价格固定。热负荷曲线是明显“双峰”早晚各一个高峰电负荷曲线则有一个晚高峰。光伏出力集中在10点到15点。下面是我用的简化参数CHP额定容量1.5 MW电电热比斜率k11.2最小电出力系数0.3热效率0.45燃气锅炉容量0.5 MWth效率0.88电锅炉容量0.6 MWth效率0.97储热罐容量0.8 MWh最大充放功率0.2 MW。电网分时电价谷时0.32元/kWh平时0.55元/kWh峰时0.82元/kWh天然气价格按热值折算为0.35元/kWh。这些数据不是从某份标准测试系统里抄的属于工程上的常见量级你复现时可以根据自己的项目替换。5.2 出清结果怎么看跑了24小时仿真最重要的三个输出是出清电价曲线、出清热价曲线、各EH的CHP和储热罐出力计划。我发现一个很有意思的现象热价在夜间低谷时段明显低于白天因为这时电锅炉和储热罐在大量产热、蓄热热源供给充足热价被压下来了。这正好形成一种“低热价用电制热、高热价用热”的良性互动机制——前提是上层与下层之间的价格传递没有被扭曲。再看CHP出力因为热负荷和电负荷的双峰不是同时出现CHP并不会全天满发而是跟着综合价格信号走。上午低谷期CHP维持在最小技术出力附近下午电负荷和热负荷同时走高时CHP升到高负荷夜间利用储热罐放热来顶替CHP和燃气锅炉整体来看燃料成本明显降低。这些结果都在模型预期之内说明程序逻辑没有问题。我会把三类曲线叠在一张图里反复看这个习惯帮我抓出过不少隐含bug。5.3 敏感性分析做了两件事案例跑通后学着论文惯常做法做了敏感性分析。第一件事是把天然气价格从0.30元/kWh梯度升到0.45元/kWh观察EH在不同气价下如何重新分配“CHP锅炉储热”的比例。结果很清楚气价上升后CHP经济性变差电锅炉和储热罐的利用率上升而热价整体上移。第二件事是改变储热罐容量从0.4 MWh到1.2 MWh看上限。储热容量越大夜间电价的“低谷红利”用得越充分但容量超过一定值后边际收益几乎归零——因为夜间低谷电时段和热负荷可转移空间已经用完了。做敏感性分析的用处不只是发文章凑图表更重要的是找出项目实施方案里最值得投资的变量。如果你要给园区提改造建议储热罐容量、电锅炉容量是相对容易落地的增量而气价是外生变量模型能告诉你的是当气价涨到多少时原先经济上可行的CHP方案会失去优势。这种结论对园区投资决策有直接参考价值。6. 常见问题与实操经验速查6.1 求解无解或求解时间爆炸怎么办这是双层出清项目里最常遇到、也最容易劝退新人的问题。我的排查顺序如下第一步检查下层模型是否可行把下层KKT条件单列出来先单独求解下层问题看是否有解。如果单层就无解问题多半出在物理约束上比如某时段热负荷抬得过高而产热设备容量不足。第二步检查M取值如果模型运行时间正常但Gurobi一直卡在整数变量上十有八九是大M选得太大导致每个整数节点都能找到松弛解剪枝效率暴跌。我建议对每个互补约束单独估一个M不要全局共用一个M。第三步把mipgap调松。模型不是为了拿到小数点后六位的全局最优工程上0.1%-1%的gap完全够用。你会发现mipgap0.001时求解器可能要多跑十倍时间收益却微乎其微。6.2 下层KKT推导时最容易翻车的细节实际推导下层KKT条件时出问题最多的地方是拉格朗日函数的符号和非负变量的互补条件。我见过不少人把对偶变量符号写反导致求出的解是“最大化问题的最小值”而不是真正的“利润最大值”。判断对错有个土办法求出解以后把该解代入下层目标函数再用同样的模型单独跑一遍下层的原问题如果利润不是最大就是不对。这个反代验证我建议每个新项目都做一次成本极低但能挡住大量低级错误。6.3 价格信号不收敛、出清价格振荡这个问题多半出在迭代求解方案。我最初直接用完整价格回代结果价格在峰谷之间反复跳跃两轮就发散。加阻尼系数0.3之后价格曲线稳定了很多但收敛速度变慢了需要七八轮才稳定。后来我改成自适应阻尼振荡期用0.2平稳期用0.5速度和稳定性都有改善。这个方法没有写进论文但对工程落地很实用尤其是需要频繁调节场景参数的试算阶段能省下大量等待时间。6.4 一个容易被忽略的坑时段耦合约束储热罐的SOC时序约束是最容易被忽略的薄弱环节。如果你忘记加SOC上下限或者充放热功率的上下限只写了一个求解器会在满足24小时总热平衡的前提下把某个时段SOC推到物理不可能的值。模型结果看着“最优”实际上设备根本执行不了。我处理这类问题有个原则凡是涉及时序状态的量宁可多写约束也不要少写因为多写一条冗余约束最多影响一点点求解速度少写一条会直接导致结果不可信。尤其是类似SOC(t1) SOC(t) ...这种递推式必须把首末时段SOC也关联上否则模型还会出现“首尾不接”的储能滥用问题。结尾这个模型做到后面的一些体会项目收官时回头复盘最大的体会是电热综合能源市场的双层出清模型难不在数学而在于你如何定义“谁在跟谁博弈”。能源集线器把物理耦合讲清楚双层模型把市场博弈讲清楚MATLAB让这两件事可以快速试错但真正有价值的产出是模型背后对机制设计和设备配置的判断。如果你测出来某一种出清方式会让储热罐白白闲置那不是求解器的错而是机制设计本身没有给储能留出盈利空间。我建议复现这个项目时先把一个最小的“1个上层1个能源枢纽”跑通再扩展到多枢纽、多场景。如果一开始就上24时段、多设备、多博弈者的完整模型你大概率会在求解器报错和调试中消耗掉所有热情。做研究的路径从来都是从简单到复杂而不是从复杂到更复杂。另外一个小技巧把运行结果导出成CSV之后不要只看总成本或者总利润按设备、按时段多画几张图。我在实际调试中最有用的一张图是“电价、热价、储热罐SOC”三者叠在一起它一眼就能看出价格信号是否合理、储热罐有没有利用低谷红利。模型说得对不对图纸比你想象的更能给出答案。