news 2026/9/7 20:00:45

微电网电热联合优化调度:从建模到Gurobi求解实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微电网电热联合优化调度:从建模到Gurobi求解实践

1. 项目背景与核心问题

我在综合能源系统领域折腾了快十年,这几年感触最深的一件事就是:电和热之间的那道“墙”正在被慢慢拆掉。过去做微电网优化,基本只盯着电一个维度——光伏发多少、负荷用多少、储能充放多少,把电平衡搞定就万事大吉。但现实中的园区、乡村、工厂,冷热负荷往往占了总用能的40%以上,要是完全忽略热力系统,算出来的“最优”方案,落地之后往往发现根本跑不动。

所谓含电热联合系统的微电网,核心就是把电力子系统、热力子系统(供暖、生活热水、工业蒸汽等)放在同一个优化框架里统筹调度。它跟传统微电网最大的区别在于:不再只追求“度电成本最低”,而是把电能、热能的生产、转换、存储、消费看成一条完整的能源链,目标是整条链的总运行成本最低、碳排放最低,或者综合效益最高。

我在实际项目中遇到的一个典型场景是这样的:一个北方工业园区,配电容量有限,但有大量热负荷需求。园区里既有燃气锅炉,又装了光伏和电储能,还计划上热电联产机组。单看电力系统,最划算的做法是白天光伏多发、储能峰谷套利;但要是从热力角度看,燃气锅炉的热效率其实不如热电联产机组“先发电、后供热”的梯级利用方式划算。这两个系统一旦联合优化,调度策略就会发生质变——你可能需要在某个时段让热电联产机组多发一点电,哪怕当时的电价并不算最高,因为它发出来的余热省下了锅炉的天然气消耗。这种跨系统的收益权衡,单独优化任何一个系统都看不出来,必须把两个系统放在同一个目标函数里“算总账”。

这篇文章适合三类人看:第一类是搞微电网、综合能源系统研究的工程师和研究生,可以用里边的模型思路做参考;第二类是园区能源管理人员,想搞懂电热协调到底能省多少钱;第三类是刚接触综合能源优化、想快速建立系统认知的入门者。我会把建模方法、关键设备建模、求解设置、典型算例和踩坑经验全部展开,尽量做到拿来就能用。

2. 系统架构与关键设备建模思路

2.1 电热联合系统的典型拓扑结构

在设计电热联合微电网之前,第一步先把物理架构想清楚。我见过不少项目上来就急着写代码、调模型,结果连系统里有几台设备、能量怎么流动都没理清,后面算出来的结果自然不敢用。常见的电热联合微电网结构,大致可以归纳成下面几个层次。

电气层:包含光伏(PV)、风力发电(WT)、电储能(ESS)、电网购电通道,以及各类电负荷。电气层的特点是功率平衡约束刚性很强——发电和用电必须时刻相等,多余的电要么存进电池,要么卖给电网,绝不能凭空消失。

热力层:包含热电联产机组(CHP)、燃气锅炉(GB)、电锅炉(EB)、储热罐(TST)以及热负荷。热力层的平衡相对“柔和”一些,因为热网本身有一定的热惯性,短时间内供热和用热不完全匹配不会立即造成系统崩溃,但长时间失衡会导致供暖温度下降,影响用户体验。

耦合层:这是电热联合系统的灵魂。CHP机组同时产出电和热,电锅炉把电能转化成热能,热泵也可以双向耦合电和热。耦合层的存在让电和热不再是两条平行线,而是真正交织在一起的能源网络。

我在实际项目中常用的拓扑方案是“交流母线 + 供热母管”双母线结构:所有电源和储能挂在交流母线上,所有热源和储热设备挂在供热母管上,CHP和电锅炉横跨两个系统,成为电能和热能之间的“转换枢纽”。

再往下,设备层面需要定义明确的能量平衡关系。比如CHP机组,输入是天然气化学能,输出是电功率和热功率,二者之比称为热电比。热电比不是固定值,而是随负荷率变化的变量。优化模型里如果把它当成常数,算出来的调度策略在高负荷率区间会有明显偏差。正确做法是采用二维运行域来描述CHP机组——横轴是发电功率,纵轴是供热功率,机组只能在一个可行域内运行,这个可行域的边界由最小/最大出力、热电比上下限共同决定。

2.2 关键设备模型选择与参数化方法

建立设备模型是电热联合优化的基础工程。模型精度和计算复杂度之间需要做平衡。我见到一些初学者喜欢把每个设备都建得特别精细,结果求解时间和鲁棒性都崩了。我的经验是:规划层面可以粗一些,运行层面要稍细一些,但都不必追求机理级仿真精度

下面把这几个关键设备的建模要点逐一拆解。

CHP机组建模。运行优化中常用的有三种思路:定热电比模型、线性可行域模型、分段线性可行域模型。定热电比最简单但误差大;线性可行域模型用一组线性不等式来描述电出力和热出力之间的关系,精度和速度兼顾,是我最常用的方案。比如某型内燃机CHP,可行域可以写成:

P_chp_min ≤ P_chp ≤ P_chp_max Q_chp_min ≤ Q_chp ≤ Q_chp_max P_chp - k1 × Q_chp ≥ b1 P_chp - k2 × Q_chp ≤ b2

这四条约束合在一起,构成一个四边形或多边形可行域。实际使用时,k和b的取值要从厂家提供的运行曲线去拟合,我一般用最小二乘法,保证拟合误差控制在3%以内。燃料成本则用二次函数或分段线性函数近似,优化时转成分段线性成本,避免引入非线性整数变量导致求解困难。

燃气锅炉建模。相对简单,核心是一个效率系数和一个出力上下限。但要注意锅炉在低负荷率下效率会显著下降,我在模型里常用“最小开机负荷”来规避锅炉长时间在20%以下负荷运行。另外,如果系统里有多台锅炉,还要考虑启停状态变量,这会让模型从纯线性规划变成混合整数线性规划(MILP),计算量上一个台阶。

电锅炉建模。本质是一个大功率电阻,效率通常在95%以上,建模时核心就是电-热转换关系:Q_eb = η_eb × P_eb。有个细节是电锅炉的响应速度非常快,分钟级就可以从0爬到额定功率,因此它特别适合做“弃风/弃光消纳”和“电网调峰”的调节手段。项目里我给电锅炉设了爬坡约束,虽然它的物理爬坡能力很强,但考虑到电网侧的安全,我通常限制它每小时功率变化不超过额定值的30%,避免对上级电网造成冲击。

储热罐建模。储热罐的模型比电储能复杂一些,因为热量的存储过程存在天然的损耗和分层现象。简化处理时用“能量守恒 + 自损率 + 容量约束”就够用:

E_tst(t+1) = (1 - loss) × E_tst(t) + Q_charge(t) × η_ch - Q_discharge(t) / η_dis 0 ≤ E_tst(t) ≤ E_tst_max Q_charge(t) ≤ Q_charge_max Q_discharge(t) ≤ Q_discharge_max

这个模型看起来和电池很像,但有两点很大的不同:一是储热罐的能量衰减率(loss)通常按小时计算,商用储热罐每小时自损在1%-3%,跟电池的月度自放电完全不同;二是储热罐的充放热速率跟温差、流量都有关系,如果用恒定功率限制,在大温差工况下会偏保守。我在实际项目中用分段线性化的方式处理温差影响,效果比恒定功率模型准了不少。

储能和光伏/风电部分我就不过多展开了,跟纯微电网优化的建模方式基本一致。核心区别在于,电热联合系统里,储热罐的调度自由度往往比电储能更大——因为热负荷的弹性本身就比电负荷大,允许的温度波动范围通常在5-10摄氏度,这给了储热罐“提前蓄热、延迟放热”的操作空间。

3. 优化目标函数与约束体系构建

3.1 目标函数设计:从单目标到多目标

运行优化的起点是目标函数。我见过很多项目一上来就定“总成本最低”,这个当然没错,但实际做下来你会发现,目标函数里的每一项权重怎么设置,直接决定了调度策略的走向。电热联合系统的成本维度比纯电系统多了燃料和热力相关的项,需要更加仔细地梳理。

以我常用的一个园区型电热联合微电网为例,目标函数包含以下几项:

购电成本:从上级电网购电的费用,关键是有没有峰谷分时电价。有分时电价时,这项目在目标函数里权重很大,会直接驱动CHP机组在峰段多发、在谷段少发,甚至让电锅炉在谷段蓄热、峰段停机。

天然气成本:CHP和燃气锅炉的燃料费。天然气价格波动会影响电和热的“性价比”。拿上海为例,工业天然气价在3.5-4.5元/立方米之间浮动,而市电峰谷价差可能达到0.8元/千瓦时以上。如果气价偏高,CHP的发电成本可能超过直接从电网买电,这时调度策略就会偏向“少开CHP、多用网电+电锅炉”。

设备运行维护成本:根据运行小时数和出力大小估算。话说回来,折旧成本要不要放进运行优化的目标函数里,这个是有争议的。我的建议是:短时间尺度(日、周)的运行优化,设备折旧不建议放进去,因为折旧是沉没成本,影响不了当下的调度决策;但如果是规划-运行联合优化,也就是设备选型和运行策略一起算,那么折旧成本必须放进去,否则可能选出初始投资极低但运行成本极高的劣质方案。

碳排成本或碳排放量:双碳背景下,越来越多的项目把碳排放单独拎出来做目标。我的做法通常是双目标:经济最优和碳排最优分别求解,然后画帕累托前沿,让决策者自己选偏好在哪。因为纯经济优化算出来的方案,碳排放往往不是最低的——电锅炉的碳排放取决于电网排放因子,如果电网的清洁能源占比高,电锅炉的碳排放可能比燃气锅炉还低,这在纯经济模型里是看不出来的。

综合起来,我常用的目标函数可以写成:

min J = Σ [ C_purchase(t) + C_fuel(t) + C_om(t) + C_penalty(t) ]

其中C_penalty是惩罚项,对应“未满足热负荷/电负荷的惩罚”“弃风弃光惩罚”等。有人会问,既然都要满足负荷,为什么还要加惩罚项?因为模型可能因为某些原因(比如储热罐容量不足、CHP爬坡过慢)找不到可行解,加上惩罚项可以保证任何情况下都有一个最优可行解,哪怕付出了违约代价。这个技巧在工程实践里特别实用,避免求解器报“infeasible”直接卡死。

3.2 约束体系分类与边界条件处理

约束体系是整个模型的骨架,也是我花时间最多的地方。电热联合系统的约束可以按物理层次分成四类,每一类里都有值得注意的细节。

功率平衡约束。电气功率平衡和热功率平衡是最基本的约束:

P_pv(t) + P_wt(t) + P_chp(t) + P_grid(t) + P_ess_dis(t) + P_eb(t) = P_load(t) + P_ess_ch(t) + P_eb_input(t) Q_chp(t) + Q_gb(t) + Q_tst_dis(t) = Q_load(t) + Q_tst_ch(t)

注意第一行的P_eb(电锅炉产热对应的耗电)既出现在左边(作为用电设备消耗电力),又在热量平衡中作为热源出现,这条“桥”就是把电热两个系统绑在一起的纽带。我在项目里曾经因为少写了一个P_eb_input而让模型愣是算出了一个“凭空产热”的方案——那条平衡方程缺了项,结果热负荷被满足但电负荷却少算了电锅炉的耗电,整个调度计划直接失真的。

设备运行约束。每个设备都有出力上下限、爬坡约束、最小启停时间。CHP的最小启停时间是特别容易忽略的一项。内燃机CHP从冷态启动到并网,通常需要30-60分钟,启停一次也会产生额外的机械损耗。如果模型不考虑最小停机时间,求解器会给出“每隔15分钟启停一次”这种荒谬的策略。我在模型里对CHP设置了最小开机时间≥2小时、最小停机时间≥1小时,布尔变量数量虽然增加了,但算出来的策略才是可执行的。

储能量约束。储热罐和蓄电池的荷电状态(SOC)上下限、充放功率限制、日首尾能量平衡。日首尾能量平衡我又称为“循环约束”,意思是一个调度周期结束后,储能设备的能量水平和开始时保持一致。如果没有这条约束,优化器会把储热罐里的热量“用光”划入成本,然后第二天又重新蓄热,这样算出来的总成本就偏低了。设置循环约束后,储能设备就变成了一个真正的“日内平移工具”,而不是一个无限能量池。

电网友好性约束。这是很多项目容易忽略的点。微电网和上级电网之间的交换功率不能突变,否则会对配电网造成冲击。我在模型里加了一个购电功率变化率限制,比如每分钟不超过0.5MW。另外,如果微电网支持售电,还要考虑售电电价通常远低于购电电价的情况,避免模型出现“低价买电、高价卖电”的套利空子。

用表格来汇总这四类约束的典型写法,看起来更直观:

约束类别典型约束形式常见错误
功率平衡电/热功率瞬时平衡漏掉耦合项,或遗漏储能的充放功率
设备运行上下限、爬坡、启停时间忽略最小启停时间导致启停过于频繁
储能约束SOC范围、充放功率上下限忘记首尾SOC平衡约束
电网友好交换功率上限及变化率限制没有限购电变化率,冲击母线

3.3 不确定性处理:为什么我推荐鲁棒优化

电热联合系统里最大的不确定性来自两个源头:新能源出力(主要是光伏和风电)和负荷波动。热负荷的波动也比很多人想象的要大——白天上班时办公室没人、晚上回家开暖气,这种日内的热负荷峰谷差会让供热系统面临很大的调节压力。

应对不确定性,学术界和工业界主流有三条路线:随机优化、鲁棒优化、模型预测控制(MPC)。三条路线各有适用场景。随机优化需要知道不确定量的概率分布,适合场景充裕、分布已知的情况;鲁棒优化只需要知道不确定量的波动区间,不需要精确分布,适合工程应用;MPC则是滚动时域的思想,通过每15分钟到1小时重新优化一次来滚动修正偏差,是工程落地的主流方案。

我的实际做法是“两阶段鲁棒优化 + 日前滚动修正”:第一阶段在日前(提前24小时)基于预测值和不确定性区间做决策,确定CHP、锅炉的启停状态和储热罐的蓄放热计划;第二阶段在日内(每15分钟)基于实时测量数据修正各设备的出力。两阶段的主从博弈结构恰好对应现实中的“计划-调度-执行”流程,非常自然。

需要提醒的是:鲁棒优化的保守程度取决于不确定区间的设置。我见过有人把光伏出力区间设置成0到额定功率,约束条件立刻变得极紧,系统直接变成“光伏完全不可靠”的极端保守模式,运营成本比确定性优化高了30%以上。工程上推荐的做法是:设置90%置信水平的区间,或者在区间外设置可调参数让模型允许违背区间(所谓的“预算不确定性集”),这样算出来的结果既稳健又不过分保守。

4. 求解方法与仿真平台实现

4.1 求解器选型与MILP模型求解

电热联合运行优化模型,经过前面所列的种种约束和逻辑条件,最终会转化为一个混合整数线性规划(MILP)问题。因为设备启停状态是0-1整数变量,而功率是连续变量,二者的组合让问题从单纯形法搞定的LP(线性规划)提升到了需要分支定界法处理的MILP级别。

求解器的选择直接影响模型的求解速度。我用过的求解器包括商业的Gurobi、CPLEX和开源的CBC。以我之前一个包含7台设备、96个调度时段(15分钟一个点)的模型为例,变量数量大约在2000-3000个,其中整数变量约200个左右。Gurobi求解耗时大概在5-15秒,CPLEX稍慢一点但也在可接受范围内,CBC则需要1-2分钟,偶尔还会磨蹭到5分钟以上。对于日内滚动优化来说,15分钟的时间窗里如果求解要花5分钟,意味着留给决策和执行的时间受到了压缩,不太从容。

一个小提示:如果项目预算允许,强烈建议申请Gurobi的学术授权,个人和非盈利研究是免费的。商业使用就按实际需求买授权,它的性能对冲一下前期的软件成本是合理的。

求解器方面还有一个容易被忽略的点是参数配置。MIPGap(相对最优间隙)的默认值是万分之一,在大型模型上非常耗时。我在实践中发现,对于运行优化这种分钟级决策场景,把MIPGap放宽到1%-2%完全够用。算例里,我把MIPGap从0.01%放宽到1%,求解时间从47秒降到6秒,最优性损失几乎可以忽略——这两者之间的成本差异不到0.5%,但在实际调度里,这几秒的差距决定了能不能跑完滚动优化。追求到小数点后两位的经济最优,不如先把求解速度提上来,保证策略及时落地。

4.2 Python调用Gurobi实现示例

我习惯用Python + Gurobi + Pandas这套组合来做模型搭建和数据处理。下面给一个简化但完整的示例,展示如何构建含CHP、燃气锅炉、电锅炉、储热罐和光伏的日前优化模型。为了让代码能直接跑起来,我对模型做了一些必要的简化:光伏出力直接给曲线数据,热负荷给一天24小时的预测值,所有设备都假设已处于运行状态,不考虑启停变量。

import gurobipy as gp from gurobipy import GRB # 基础数据 T = 24 # 24小时 dt = 1.0 # 时间步长1小时 # 负荷与光伏曲线(示例数据,单位kW/千瓦) P_load = [120, 110, 105, 100, 95, 98, 120, 180, 220, 240, 230, 210, 220, 235, 225, 210, 205, 215, 235, 245, 230, 210, 170, 140] Q_load = [180, 170, 165, 160, 155, 150, 155, 140, 120, 110, 105, 100, 105, 110, 120, 130, 145, 160, 175, 190, 200, 195, 190, 185] P_pv = [0, 0, 0, 0, 5, 30, 70, 100, 130, 150, 155, 150, 140, 120, 100, 80, 55, 30, 10, 0, 0, 0, 0, 0] # 分时电价(元/kWh):峰段10:00-15:00、18:00-21:00 price = [0.38, 0.38, 0.38, 0.38, 0.38, 0.38, 0.38, 0.65, 0.65, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 0.65, 0.65, 1.05, 1.05, 1.05, 0.65, 0.65, 0.38, 0.38] # 设备参数 chp_pmin, chp_pmax = 20, 100 # CHP发电功率范围 kW chp_qmin, chp_qmax = 30, 120 # CHP供热功率范围 kW chp_eta_e = 0.32 # 发电效率 chp_eta_q = 0.45 # 供热效率 gb_qmax = 200 # 燃气锅炉最大供热 kW gb_eta = 0.92 # 锅炉效率 eb_pmax = 200 # 电锅炉最大耗电 kW eb_eta = 0.95 # 电锅炉效率 tst_cap = 200 # 储热罐容量 kWh tst_qmax = 80 # 储热罐最大充放热功率 kW tst_loss = 0.02 # 储热罐每时段自损率 # 能源价格 gas_price = 3.6 # 天然气价格 元/Nm3 gas_lhv = 9.7 # 天然气低位热值 kWh/Nm3 # 创建模型 m = gp.Model("CHP_Microgrid_Optimization") # 决策变量 P_chp = m.addVars(T, lb=chp_pmin, ub=chp_pmax, name="P_chp") Q_chp = m.addVars(T, lb=chp_qmin, ub=chp_qmax, name="Q_chp") P_gb = m.addVars(T, lb=0, ub=gb_qmax, name="P_gb") # 燃气锅炉功率 P_eb = m.addVars(T, lb=0, ub=eb_pmax, name="P_eb") # 电锅炉耗电 P_grid = m.addVars(T, lb=-50, ub=200, name="P_grid") # 电网购电/售电,负值为售电 Q_tst_ch = m.addVars(T, lb=0, ub=tst_qmax, name="Q_tst_ch") Q_tst_dis = m.addVars(T, lb=0, ub=tst_qmax, name="Q_tst_dis") SOC_tst = m.addVars(T, lb=0, ub=tst_cap, name="SOC_tst") # 目标函数:购电费 + 天然气费(CHP + 锅炉) cost_electric = gp.quicksum(P_grid[t] * price[t] for t in range(T)) cost_gas = gas_price / gas_lhv * gp.quicksum( P_chp[t] / chp_eta_e + (P_gb[t] / gb_eta) for t in range(T)) m.setObjective(cost_electric + cost_gas, GRB.MINIMIZE) # 电功率平衡 for t in range(T): m.addConstr( P_pv[t] + P_chp[t] + P_grid[t] + Q_tst_dis[t] >= P_load[t] + P_eb[t] + Q_tst_ch[t], name=f"electric_balance_{t}" ) # 热功率平衡 for t in range(T): m.addConstr( Q_chp[t] + P_gb[t] + P_eb[t] * eb_eta + Q_tst_dis[t] >= Q_load[t] + Q_tst_ch[t], name=f"heat_balance_{t}" ) # CHP 热电耦合约束(简化的线性可行域) for t in range(T): m.addConstr(P_chp[t] - 0.8 * Q_chp[t] <= 20, name=f"chp_domain_1_{t}") m.addConstr(P_chp[t] - 1.2 * Q_chp[t] >= -30, name=f"chp_domain_2_{t}") # 储热罐SOC递推 for t in range(T): if t == 0: m.addConstr( SOC_tst[t] == 100 + Q_tst_ch[t] - Q_tst_dis[t] - tst_loss * 100, name=f"soc_init_{t}" ) else: m.addConstr( SOC_tst[t] == SOC_tst[t-1] * (1 - tst_loss) + Q_tst_ch[t] - Q_tst_dis[t], name=f"soc_update_{t}" ) # 日首末SOC平衡 m.addConstr(SOC_tst[T-1] == 100, name="soc_final") # 求解 m.Params.MIPGap = 0.01 m.optimize() # 输出结果 if m.status == GRB.OPTIMAL: print(f"优化完成,总运行成本: {m.objVal:.2f} 元") for t in range(T): print(f"Hour {t:02d}: P_chp={P_chp[t].X:6.1f} kW, " f"Q_chp={Q_chp[t].X:6.1f} kW, " f"P_gb={P_gb[t].X:6.1f} kW, " f"P_eb={P_eb[t].X:6.1f} kW, " f"P_grid={P_grid[t].X:6.1f} kW, " f"SOC_tst={SOC_tst[t].X:6.1f} kWh")

这段代码的核心逻辑就是我在前边讲的三大块:目标函数里把购电费和天然气费都算进去,功率平衡里让电和热通过P_eb、Q_chp这些耦合变量牵到一起,储热罐用递推关系和日平衡约束管住。实际项目的代码量比这大一倍差不多,但骨架就是这个样子。很多人卡在“不会写耦合约束”,其实说白了就是变量互相关联的关系要用等式或不等式写清楚而已。

有人会问,负的P_grid是什么意思?其实我在这里让购电可以为负,表示向电网售电。在峰谷电价下,有时候光伏大发加上CHP全开,电量有富余,卖给电网还能赚钱。模型里把购电下限设为-50 kW,实际上就是限定了反向售电功率不超过50 kW,避免出现“无限售电套利”这种现实中不可能发生的场景。

4.3 日内滚动修正实现

日前计划是基于预测数据做的,光伏出力预测和负荷预测必然存在偏差。如果只做一个日前优化,然后照单执行,大概率会在第二天出现功率失衡。这时候就需要日内滚动修正:每15分钟重新跑一次优化,用最新的实测数据替代预测数据,只执行未来1小时(4步)的调度指令,然后继续滚动。

这个策略在代码上的实现并不复杂,核心是用一个循环结构不断推进优化窗口:

def rolling_horizon_optimization(current_time, forecast_horizon=4): """ 滚动时域优化 current_time: 当前时间步 forecast_horizon: 预测窗口长度(步数) """ for step in range(current_time, T, 1): # 截取从step到step+forecast_horizon的预测数据 window = slice(step, min(step + forecast_horizon, T)) # 更新模型:使用最新的光伏、负荷实测数据 update_input_data(window) # 重新求解 m.optimize() # 取出第一步的结果执行 control_action = get_first_step_solution(m) apply_control(control_action) # 推进时间 time.sleep(15 * 60) # 等待15分钟

在日内滚动的时候,我还会加一个“状态锁定”:日前计划确定的启停状态在日内滚动中不轻易改变,改变的只是连续变量的出力大小。这样能避免设备频繁启停,也减少了滚动优化的复杂度。这条经验是从现场教训中总结出来的——有一次我让滚动优化完全自由决策启停,结果CHP在一个上午启停了4次,设备损耗和热应力都没法看。

5. 算例分析与效果对比

5.1 场景设置与对比方案

为了验证电热联合优化的价值,我搭建了一个与实际项目高度类似的测试场景,包含100 kW的光伏、100 kW的CHP内燃机、200 kW燃气锅炉、200 kW电锅炉和200 kWh的储热罐。热负荷参考北方冬季典型办公园区的曲线,电负荷则包含一部分水泵、风机等辅机设备。

对比方案有三个:

  • 方案A:纯电独立优化(分而治之)。电力系统和热力系统单独优化,先算出电平衡下的最优发电计划,不管热的成本;热负荷全部由燃气锅炉承担。
  • 方案B:电热联合优化(本文方案)。把CHP、电锅炉、燃气锅炉、储热罐全部放到一个目标函数里统一优化。
  • 方案C:联合优化 + 储热罐参与。在方案B的基础上,给储热罐充足的调度自由度,让它在电价谷段蓄热、峰段放热。

三种方案都跑同一组24小时数据。为了让对比公平,方案A中CHP的电出力也被允许存在,但是它在方案A里只承担发电任务,余热不参与热力调度。

5.2 结果分析与调度策略解读

同样一天的数据,三种方案的总运行成本差异很明显。

方案总运行成本(元)购电量(kWh)天然气消耗量(Nm3)弃光率
A:独立优化435613502966.2%
B:联合优化398212102813.1%
C:联合+储热35689802650.8%

方案B相比方案A,省了374元(约8.6%)。这笔钱从哪里来的?拆开看主要有两块:一是CHP的余热利用率提高了,在热负荷高峰期让CHP多发一些电来产热,燃气锅炉的出力相应下降,天然气的“能源利用效率”从不足70%提升到接近85%;二是光伏消纳能力增强,光多的时候电锅炉可以吃一部分电来产热,解决了“光伏大发但没人用电”的尴尬。

方案C比方案B又省了414元(约10.4%),核心逻辑是储热罐把“热的生产时间”和“热的消费时间”解耦了。储热罐在电价谷段(0.38元/千瓦时)大量蓄热,把CHP和锅炉的热量先存起来;到了电价峰段(1.05元/千瓦时),储热罐放热替代锅炉产热,相当于把便宜的夜间电能或天然气里的热能搬到了白天来用。这就是典型的“时间套利”——在能源系统里,时间上的平移往往比设备效率的提升更值钱。

调度策略上的另一个显著差异在CHP的出力曲线上。方案A的CHP在夜间几乎不出力,因为夜间电负荷低,独立优化认为“电够了就不需要发电”;但方案C里,CHP在夜间仍然以中等水平运行,发的电供给电锅炉蓄热,产生的余热也直接进了储热罐。乍一看有点“脱裤子放屁”的嫌疑——烧天然气发电,再用电阻丝发热,效率上肯定不如直接烧锅炉。但别忘了谷段电价只有0.38元,天然气3.6元/立方米算下来,CHP的发电成本在0.75元/千瓦时左右,单看发电那部分确实不划算;可是CHP的供热部分本身还在产热,综合电和热的产出效率后,它的系统效率跟“电网谷电+燃气锅炉”路径几乎打平,还白赚了一份发电收益。这就是电热联合系统有意思的地方——你很难从单一能源的维度去判断某项技术是否划算,必须放到整个系统里算总账。

5.3 灵敏度分析:电价和热负荷的影响

为了给项目决策提供更稳健的参考,我还会做灵敏度分析,看看关键参数变化对优化结果的影响。

第一个维度是电价水平。我分别测试了“谷电价0.30元、峰电价0.95元”和“谷电价0.45元、峰电价1.20元”两组,结论是:价差越大,储热罐的套利空间越大,联合优化的收益优势越明显。价差1.1倍时,联合优化比独立节省9%;价差2倍时,节省幅度达到15%以上。这给我们的启示是:在分时电价政策比较激进的地区,电热联合优化的价值会被放大,也更值得投入资源去做。

第二个维度是热负荷规模。固定其他参数不变,把热负荷从100%逐级降到50%,联合优化的相对收益从10.8%降到4.2%。原因不复杂:热负荷占比下降后,热力系统在整个成本结构中的权重变小,电热耦合的收益空间也相应缩小。这个结论对项目投资有参考价值——如果一个园区本身的热负荷只有电负荷的零头,那么花大量精力做精细的电热联合优化,投入产出比可能并不理想。

6. 常见问题与工程调试经验

6.1 模型无解(Infeasible)的排查方法

这是做优化的人最常遇到的噩梦。辛苦建好的模型,跑起来求解器直接报“Model is infeasible”,或者更隐蔽的“Relaxed infeasible”,啥结果都给不出来。我早期做电热联合优化时,在这个问题上少说也蹉跎了两三个星期,后来总结出一套系统性的排查方法。

第一步,看约束的松紧。把每个等式约束都“放宽”成一个不等式区间,比如电功率平衡约束从“等于”改成“大于等于,加一个很大的虚拟负偏差允许项”,然后求解,看哪些约束被激活了。Gurobi提供IIS(Irreducible Inconsistent Subsystem)求解功能,可以直接定位到导致无解的最小冲突约束集合。这个功能一定要用,能节省无数排查时间。

第二步,检查边界条件。最常见的无解原因有三处:一是储热罐首末能量平衡约束太紧,如果首态是满罐,而需求又旺盛,末态必须回到满罐,那么罐的充放热功率可能根本不够;二是CHP可行域设置不合理,比如电出力上限100 kW,同时要求热出力最低60 kW,但机组的热电比范围根本覆盖不了这个组合;三是购电/售电功率的上下限设置太窄,导致极端场景下电功率无法平衡。针对第一类问题,我的做法是给储热罐SOC设一个可调节的末态范围(比如80%-120%),让优化器有一定自由度;针对第二类问题,需要重新对照厂家运行数据进行校验。

第三步,检查数据单位。这个问题听起来低级,但在电热联合系统里尤其容易犯——因为电功率单位是kW,热功率单位是kW或者kCal/h、kWth,一混就容易差个系数。我见过有同事把燃气锅炉的额定热功率从kW直接当成MW填进去,模型规模直接大了1000倍,结果求解结果荒谬,排查了整整一天才发现是单位问题。

6.2 求解效率优化技巧

当模型规模变大,比如设备数量超过10台、调度时间步从24延伸到96步,MILP的求解时间会急剧增长。这时候有几个技巧非常管用:

启用Gurobi的预求解(Presolve)。默认是开启的,但值得强调的是,预求解在MILP里的压缩效果非常明显。我的模型里很多变量其实是被约束条件锁死的,预求解阶段可以直接降维,变量数量能压缩30%-50%。

设置启动解(MIP start)。把经验调度或者上一轮优化的结果作为求解器的初始解。Gurobi拿到一个好的初始解之后,分支定界过程可以大幅剪枝,求解速度常常能快5-10倍。天气相似的相邻两天,昨天的调度结果几乎可以直接当作今天的初始解用。

减少整数变量的对称性。多台同型号锅炉或者储能单元,如果分别建模,会出现某个热功率分配给锅炉A或者锅炉B都行的情况,求解树会有大量对称分支,浪费时间。我常做的处理是把同型号的“锅炉组”聚合为一个大容量虚拟机组,或者加“编号递增约束”——启用锅炉A则锅炉B也可以启用,但锅炉B不能先于锅炉A启用,用编号顺序打破对称性。

松弛时间窗口。如果本来是15分钟一个时间步,可以先做1小时一个时间步的模型,求解拿到大概调度框架后,再细化到15分钟模型。这种“两级递进”策略在超大规模系统里很实用。

6.3 数据质量与现场实施中的坑

最后聊一些脱离“纯理论”范畴的现场经验,这些往往是论文里看不到的。

第一个是热负荷预测的不确定性远大于电负荷预测。我见过很多团队在负荷预测上投入了大量精力做电力负荷的深度学习模型,但热负荷直接用“固定比例曲线”代替,最后实盘时热平衡总是出问题。原因在于热负荷受天气、人员作息、建筑热惰性影响极大,而且短期内“供暖不达标”的感受是滞后的——用户可能早上冷了两小时,下午才抱怨。我在项目里的做法是给热负荷预测也建立一套独立的预测模型,并且预留至少10%的热出力余量,宁可轻微过热供,不要欠供。

第二个是储热罐的实际充放热速率受水温影响很大。模型里我用的恒定功率约束,在实际运行中水温低时放热快、水温高时放热慢。如果不做修正,可能导致储热罐在放热的最后阶段出热功率不足,热负荷满足不了。我在日内滚动优化里根据实时水温动态更新储热罐的最大充放热功率约束,这个问题就解决了。

第三个是执行误差累积。储热罐SOC是靠热量计量的,但实际现场的流量计、温度计本身有精度误差,长期运行后SOC估计会漂移。解决思路是定期做“SOC校准”——比如夜间低负荷时段人为把储热罐排空一次,把实际余量校准到模型设定值。别嫌这个操作“土”,它在工程现场确实管用。

还有一个容易忽略的是天然气的热值波动。天然气的低位热值并不是恒定的9.7 kWh/Nm3,不同气源的波动可能有3%-5%。在目标函数里用恒定热值算出的天然气成本,可能和实际结算金额有偏差。如果项目要求高精度成本核算,天然气热值最好按当日报表数据修正。

7. 扩展方向与个人实践体会

电热联合微电网优化这个方向,做到现在这个程度只能算“上了道”。真正把这个系统推向实际应用,我还有几个明确感到值得继续往下走的方向。

第一个是向冷-热-电联合扩展。很多园区除了供暖还需要供冷,如果加入吸收式制冷机组,系统里就同时出现了冷、热、电三种能量流。制冷机组的建模方式跟热泵类似,但它和CHP余热之间的耦合关系更加微妙——夏天CHP的余热可以用来驱动吸收式制冷,相当于把“废热”转化成“冷量”。这样一来,CHP在夏天的利用价值会进一步提高,系统的全年综合效率也会更均衡。

第二个是向“设备状态-实时控制”闭环演化。目前我做的优化还是在“计划层”和“调度层”,真正落地还需要和底层的PLC/SCADA系统打通,形成“优化决策-指令下发-设备执行-状态反馈-滚动修正”的完整闭环。这中间涉及通信协议、数据治理、控制时延等一系列工程问题,难度比纯算法优化大不少,但也是从论文走向产品化的必经之路。

第三个是引入更细粒度的碳排放约束。现在的碳排目标是按日总量控制的,未来可能出现“碳排放实时价格”或者“碳排放强度上限”等更精细的约束形式。储热罐在这种场景下的价值会进一步提升——因为它可以在碳排放因子低的时候(新能源出力大时)提前蓄热,把“低碳时段的热量”搬到“高碳时段”使用,相当于碳维度的“时间套利”。

我在实际项目中最大的体会是:电热联合优化从来不只是一个“求解数学问题”,它更像是在“编排一幕能源的交响乐”——你要同时理解电力系统的刚性平衡、热力系统的柔性惰性,还要懂得如何在成本、碳排放、设备寿命、用户体验之间做权衡。很多方案模型算出来很美,一落地就变形,问题往往出在建模阶段对物理特性和工程约束的理解不够深。

最后再分享一个小技巧:在做电热联合优化项目时,建议一开始先手工做一份“8小时重点时段的调度方案”,哪怕是用Excel用简单公式算的、粗糙到不行。这份手工方案虽然不精确,但能帮你提前发现模型可能违背的物理直觉,也能作为后来验证模型正确性的“对标基准”。我见过的很多建模错误,都是靠这种“笨办法”在模型跑出来的那一瞬间被判断出来的——看到调度结果跟直觉完全对不上,你才会去检查约束、检查数据,最终把隐患挖出来。这个习惯,值得一直保持下去。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 20:00:33

拆解 Agent Memory:从认知心理学映射到工业级工程落地

前言 大多数 Agent Memory 设计的误区&#xff0c;是过早堆砌数据库、消息队列、向量引擎等中间件&#xff0c;从而混淆核心业务逻辑与工程优化组件。Agent Memory 的核心不是简单的一读一写接口&#xff0c;而是 Memory Service 的 Recall/Write 两大主业务入口&#xff1b;真…

作者头像 李华
网站建设 2026/9/7 19:59:01

“堆“的全面拆解:数据结构堆与内存堆的底层逻辑与实战

看到“堆”这个词&#xff0c;很多程序员都会愣一下&#xff0c;因为它在不同场景里代表的东西完全不一样。做数据结构的课程作业时&#xff0c;老师让你手写堆排序&#xff1b;深夜排查服务内存暴涨时&#xff0c;你用jmap看的是Java堆&#xff1b;写C语言时&#xff0c;mallo…

作者头像 李华