做微电网调度的朋友应该都有过类似经历:早上根据预测做了一份自我感觉良好的日前计划,下午一片云飘过来,光伏出力直接腰斩,计划当场作废,只能手忙脚乱地切手动模式。我在一个含电、热、气多种能源的微网项目里折腾了大半年,对这个问题体会尤其深——多能源耦合不是简单的“多个设备各管各的”,而是牵一发动全身。后来我把调度框架改成了“日前双层 + 日内多时间尺度滚动优化”,问题才算真正压下来。这篇文章就把这套模型的整体思路、上下层分工、滚动机制、数学模型、算例结果和我在工程里踩过的坑完整摊开来讲,适合正在做微电网能量管理、综合能源系统调度,或者刚接触滚动优化的同行参考。
1. 单一时间尺度调度为什么撑不住
1.1 我最早踩过的坑:日前计划频繁“打脸”
最开始我做的其实就是最常规的日前经济调度:按小时分辨率,对未来24小时做一次优化,给出每台机组的出力和储能的充放电计划,然后按这个计划执行一天。听起来没什么问题,但实际跑起来就会发现,计划在上午还靠谱,下午就开始离谱。
举一个我实际遇到过的场景:早上预测当天下午光伏出力约300千瓦,日前计划据此安排了燃气轮机和锅炉的低出力运行,还从电网买了比较少的电。结果下午一点左右云层变厚,光伏实际出力掉到120千瓦,瞬时缺口接近180千瓦。此时燃气轮机受爬坡速率限制,没法一下子顶上去,储能又因为上午按计划充得太满、放电功率接近上限,结果只能靠电网紧急买电。电网侧电价偏偏又是下午高峰时段,这一波临时购电直接让当天的运行成本比计划高了将近20%。
这不是预测算法不够准的问题——预测误差是客观存在的,只是被“按计划死执行”的模式放大成了运行失败。问题的根源在于:单一时间尺度的日前调度,把所有决策都押在了一组24小时前的预测上,完全没有给不确定性留出修正通道。
1.2 多能源耦合让问题更复杂
纯电力微网虽然也有预测误差问题,但至少电力系统响应快,储能调节还算直接。多能源微网就麻烦在电、热、气三条能量流是绑在一起的。
我当时项目里的核心供能设备是热电联产机组(CHP),它同时产电和产热,而且电出力一变,热出力也跟着变,这就是常说的“以热定电”或“以电定热”的耦合关系。如果某段时间电负荷预测偏差大,我强行调整CHP电出力,热出力就会偏离热负荷需求,导致锅炉需要额外补燃,或者多余的热量只能白白散掉。反过来也一样,热负荷判断失误,也会拖累电力侧的调节能力。
再加上蓄电池和储热罐的时间常数完全不同:电池的响应是秒级到分钟级,储热罐的热惯性可以到小时级。要让这两种“性格迥异”的储能配合好,单靠一个24小时尺度的日前计划根本做不到。我试过在日前计划里给储热罐排一个非常精细的充放热时序,结果当日运行偏差一大,这个时序立刻变成废纸。
1.3 多时间尺度的本质:拿时间换确定性
这个问题的解法思路其实不复杂,就一句话:预测时间越短,误差越小。日前预测的误差动辄20%以上,但未来4小时内的超短期预测可以把误差压到5%左右;未来15分钟内的预测误差还能更低。既然短时间尺度的信息更准,那就不应该把所有决策都放在日前做完,而是把调度决策拆到多个时间尺度上,逐层修正。
这就是多时间尺度调度的核心逻辑:在日前尺度做长周期的粗规划,解决“大方向”问题;在日内尺度做短周期的细修正,解决“偏不偏”的问题。两层叠加之后,系统就像开车时既看导航规划路线,又盯着眼前的路况随时微调方向盘,而不是靠出门前看的导航一路硬开到底。
2. 双层调度模型的分工与整体架构
2.1 上层日前调度:看全局,定骨架
我先说上层。上层模型对应的是传统日前经济调度,优化时域是未来24小时,时间分辨率取1小时。它的职责不是精确控制每台设备的每一分钟,而是确定一整天的运行骨架:哪台机组开、哪台停、储能的电量“大概怎么走”、和电网交互的总体用电计划。
目标函数是全天总运行成本最小,主要包括燃气成本、购电成本、设备启停成本和运维成本,减去可能的售电收益。约束方面则覆盖电力平衡、热力平衡、设备出力上下限、爬坡约束、储能SOC范围、联络线功率限制等常规项。这个层级的求解结果,会被当作日内层的参考基线。
需要提醒的是,上层调度不直接下发“精确指令”,它下发的是“参考计划”。这个定位如果不明确,后面日内层和它衔接的时候就会打架。我在第一次搭建模型时就踩过这个坑:上层把CHP出力定死成一个数值,下层滚动优化时发现必须偏离这个值,但惩罚项又设得太重,结果日内层几乎失去了修正能力。后来我把上层的结果定位成“软参考”,只在偏差超过一定范围时才触发惩罚,问题就顺了。
2.2 下层日内滚动:盯局部,做修正
下层模型对应日内滚动调度,优化时域缩短到未来4小时,时间分辨率细化到15分钟,并且每隔15分钟就重新优化一次。它干的事有两件:一是跟随上层给出的参考计划,二是用最新预测和实测数据修正偏差。
比如下午光伏实际出力比预测低了60千瓦,日内层会立刻在接下来几个15分钟时段内重新分配CHP、锅炉、储能和购电的比例,优先用成本最低的调节手段把缺口补上,同时尽量不偏离日前计划的总体安排。因为预测时域短、信息新鲜,日内层对突发波动的响应比日前层可靠得多。
下层的目标函数一般是“运行成本 + 对日前计划的偏差惩罚”。这里有个细节:为什么不直接全盘推翻日前计划重新优化一遍?因为日前计划虽然局部可能不准,但它在全局上经过了24小时的统筹,比如考虑了夜间低谷充电、白天高峰放电的总体策略。如果日内层完全不参考它,很可能为了眼前15分钟的便宜,破坏了全天的经济性。所以偏差惩罚项的设置,本质上是让日内层在“局部最优”和“全局承诺”之间做一个折中。
2.3 两层之间的“接口设计”
双层模型能不能跑通,关键在上下层接口怎么定义。我的做法是传递三类信息:
- 各设备在对应时段的参考出力计划;
- 储能设备的参考SOC轨迹;
- 联络线功率参考值。
下层在滚动优化时,把这些参考值作为软约束纳入目标函数,用带权重的偏差平方项(或绝对值项)来惩罚偏离。同时,下层每一轮优化结束后的实际状态(尤其是储能SOC实测值)会反馈到下一轮优化的初始条件里,形成状态衔接。
这个接口设计的核心原则是:上层给方向,下层给精度,两者通过“惩罚系数”沟通。惩罚系数设得太大,下层僵化;设得太小,等于放弃日前全局优化。具体怎么调,我在第6部分会详细讲。
3. 滚动优化到底是怎么滚起来的
3.1 预测-优化-执行-滚动:四步循环
很多刚接触滚动优化的朋友,会把“滚动优化”和“多次重新优化”混为一谈。其实它的标准流程是一个四步闭环:
- 读取当前时刻的系统状态(储能SOC、设备当前出力、重要负荷实测值等);
- 基于最新超短期预测,求解未来一段时域(预测时域)内的优化问题;
- 只执行当前时刻到下一个滚动步长之间的控制指令;
- 时间推进一个滚动步长后,回到第1步,重新读取状态、刷新预测、再次优化。
这里有一个关键点:虽然我们求解了未来4小时的最优决策,但真正下发执行的只有未来15分钟的那一部分。等15分钟过去,新的实测数据进来、预测刷新,再重新解一遍。这一步叫“滚动”,本质上就是让决策永远站在最新信息上。
我用一段伪代码描述这个流程,方便大家直接对照实现:
for t = 0, 15min, 30min, ..., 日内结束: 读取当前状态: SOC(t), P_device(t), load_meas(t) 获取预测: load_forecast(t : t+H), pv_forecast(t : t+H) 求解优化问题: 目标 = 运行成本 + 日前偏差惩罚 约束 = 设备出力/爬坡/SOC/能量平衡 下发指令: 执行 t 到 t+Δt 的控制量 等待 Δt, 进入下一轮循环3.2 预测时域、控制时域和滚动步长的取舍
这里有几个时间参数需要拍板:预测时域H(一般取2到6小时)、控制时域(一般取一个滚动步长)、滚动步长Δt(日内层我取15分钟)。
预测时域不是越长越好。太短,比如只有1小时,优化问题看不到储能低谷充电、高峰放电的完整机会窗口,日内层会变得短视;太长,比如12小时,超短期预测的优势就没了,而且求解规模变大,15分钟的滚动周期内可能算不完。我在项目里对比过4小时和6小时两种设置,收益差别不大,但4小时的求解时间明显更友好。所以最终选了“预测时域4小时 + 滚动步长15分钟”的组合。
控制时域方面,我采用的是“每步只执行第一个15分钟决策,然后重算”的标准做法,也就是控制时域等于滚动步长。这样做最稳,因为每一次执行都建立在最新状态和最新预测之上。如果你对求解速度非常自信,也可以尝试执行未来30分钟甚至1小时的指令再重算,但那样做等于主动放弃了反馈修正的机会,我不太推荐。
3.3 反馈校正环节为什么必要
滚动优化和普通的“定时重新优化”之间的本质区别,在于有没有用实测状态做反馈校正。每一次滚动开始前读取的“当前状态”不是预测出来的,而是传感器实测的储能SOC、设备出力和负荷数据。这就相当于给优化器装了一双眼睛:你看到的不是模型推测的世界,而是真实世界。
我做过一个对照实验:同样用4小时滚动时域,一组在每次优化开始时用实测SOC作为初始条件,另一组用模型推算的SOC作为初始条件。跑完一天,前者的联络线功率偏差比后者小了约40%。原因很直接:模型推算是理想化的,实际运行中SOC会因为各种损耗和测量误差逐渐偏离模型轨迹,如果不读实测值,误差会在滚动过程中不断累积,最后滚动优化就退化成了开环优化。
所以,滚动优化这个框架要想真正发挥威力,数据采集链路和状态估计的可靠性,比优化算法本身更值得你花时间。这一点很多人容易忽视,我建议做项目的朋友一定把状态反馈放在最高优先级。
4. 模型构建中最费心思的三类约束
4.1 设备的“脾气”:出力区间、爬坡与启停
任何优化调度模型,第一步都是把设备的运行特性写成数学约束。多能源微网的设备种类多,约束也杂,我挑几个最容易出问题的说。
CHP机组有三类约束最要命:出力上下限、爬坡速率、最小启停时间。出力上下限好理解,但要注意电出力和热出力之间是耦合的——CHP的可运行域是一个二维区域,不是简单的两个独立区间。我最初把电、热出力当成独立变量分别加约束,算出来的结果CHP经常处于物理上不可能的电热组合点,后来改成可行域多边形约束才正常。
蓄电池的约束包括充放电功率上限、SOC上下限、以及充放电效率模型。这里有个容易踩的坑:如果忽略充放电效率,SOC的日结算会出现“账面电量”和“实际电量”不一致的问题。我在代码里对充电、放电分别定义效率η_c和η_d,并且在SOC递推方程里严格区分,才能保证15分钟滚动不会越滚越虚。
储热罐相对宽容一些,约束主要是储热量上下限和充放热功率上限,不需要考虑爬坡。但它的时间常数大,日内容易被忽视,要记得在日前层给它留出足够的重新蓄热窗口。
4.2 多能源平衡:电、热、气三条线的平衡约束
多能源微网调度之所以复杂,核心在于能量平衡约束是跨介质耦合的。电力平衡约束写出来大概是这个形式:
P_pv + P_wind + P_chp_elec + P_battery_discharge + P_grid_buy = P_load_elec + P_boiler_elec + P_battery_charge + P_grid_sell + P_curtailment
每一项都不能漏。热力平衡约束类似:
Q_chp_heat + Q_gas_boiler + Q_thermal_storage_discharge = Q_load_heat + Q_thermal_storage_charge
两条平衡通过CHP的“电-热可行域”耦合在一起,再加上天然气消耗量G_chp、G_boiler带来的燃气成本项,天然气的“平衡”其实体现在成本目标和供气上限约束里。我的项目没有气网容量限制,所以气侧只做了成本核算;如果你的园区有燃气管道容量约束,记得再加一条购气上限约束。
电力平衡里容易被漏掉的是电锅炉的耗电项。我最初的模型把电锅炉当成纯热出力设备,结果它明明在耗电产热,电力平衡方程里却少了这一笔,导致系统“凭空”多出来一块电力,调度结果偏乐观。后来我给电锅炉单独建了“电转热”的转换效率模型,才把这个漏洞堵上。
4.3 不确定性:从确定性模型到带反馈的校正
多时间尺度滚动模型本质上仍然是一个确定性优化模型——每一轮都在给定的预测值下求解。不确定性不是通过随机规划或鲁棒优化显式建模的,而是靠“频繁刷新预测 + 反馈校正”隐式处理的。这是我个人比较推荐的工程化思路:显式不确定性建模(比如场景法)在多能源微网这种大型混合整数问题上求解负担太重,滚动框架凭借“短时域 + 高频更新”已经能吃掉大部分预测误差。
不过隐性处理有一个前提条件:必须在目标函数里加入针对“日前计划偏差”的惩罚项,否则日内层会在每个15分钟时段里只顾眼前便宜,造成设备出力在滚动过程中“漂移”。我采用的惩罚形式是偏差绝对值项乘以权重λ,权重按设备类型区分:联络线功率偏差惩罚最重,储能SOC偏差其次,机组出力的偏差惩罚最轻。这样既保证了跨设备的公平性,也让系统在紧急情况下允许临时偏离日前的全局安排。
5. 算例设计与结果分析
5.1 算例配置
为了验证模型,我搭了一个典型的园区级多能源微网算例,设备配置如下表。这套参数是参考我实际项目的量级设计的,不一定代表所有场景,但数量级有参考意义。
| 设备/环节 | 关键参数 |
|---|---|
| 光伏 | 装机400 kW |
| 风电 | 装机200 kW |
| CHP机组 | 额定电出力300 kW,电效率0.35,热效率0.45,爬坡30 kW/15min |
| 燃气锅炉 | 额定热出力500 kW |
| 电锅炉 | 额定热出力200 kW,电热转换效率0.95 |
| 蓄电池 | 容量500 kWh,最大充放电功率100 kW,效率0.92/0.95 |
| 储热罐 | 容量800 kWh,最大充放热功率100 kW |
| 联络线 | 最大购/售电功率300 kW |
| 负荷 | 电负荷峰值约600 kW,热负荷峰值约500 kW |
电价采用分时电价:低谷0.35元/kWh、平段0.7元/kWh、高峰1.1元/kWh;天然气价格按3.2元/m³、热值9.8 kWh/m³折算。光伏和负荷预测误差按典型比例人工叠加:日前误差20%,日内4小时预测误差5%,15分钟实测值为真值。
5.2 三种调度策略的对比结果
我跑了三组对比:纯日前调度按计划执行、日前+日内滚动优化但不用实测反馈、日前+日内滚动优化且带实测反馈。一天运行下来的关键指标如下:
| 策略 | 日运行成本(元) | 联络线功率平均偏差(kWh) | 光伏弃光率 |
|---|---|---|---|
| 纯日前调度 | 8510 | 118 | 12.3% |
| 双层滚动(无反馈) | 8280 | 62 | 7.1% |
| 双层滚动(带反馈) | 8165 | 28 | 4.6% |
三组结果很直观:双层滚动优化相比纯日前,日成本下降约4%,联络线偏差大幅收窄,弃光率从12%压到4.6%。带反馈和不带反馈的差距也说明了一个关键结论——滚动优化本身的价值,有一大半是建立在状态反馈之上的,没有反馈的滚动优化只能算“定时重优化”,效果大打折扣。
5.3 从数字里读出来的几条规律
仔细看优化结果里的设备出力曲线,我发现了几条挺有意思的规律。
蓄电池的充放电切换次数明显增加了。纯日前模式下电池一天也就充放两三次;而滚动模式下每个15分钟都在根据最新预测微调,电池的动作频率更高。这说明滚动优化让储能真正发挥出了“快速响应”的价值,代价是电池循环次数上升,做工程落地时要额外评估电池寿命损耗,不能只看电费节省。
CHP机组的爬坡压力反而变小了。虽然日内频繁重算,但因为有日前计划的偏差惩罚在“拽”着,CHP出力并不会剧烈震荡,而是一步步平滑逼近修正后的目标。热负荷侧产生的热惯性偏差,大多被燃气锅炉和储热罐吸收了。这说明双层结构天然有“慢设备走计划、快设备做调节”的分工效果。
另外,电锅炉在滚动模式下的利用率比纯日前模式高一截。原因在于光伏预测偏差导致午间出现短时弃光风险,滚动优化可以及时启动电锅炉把这些“临时多余的电”转化为热能储存或直接供热。这种跨介质消纳能力,单层日前模型很难捕捉到,算是多能源耦合带来的一个额外红利。
6. 实测中的调参与避坑心得
6.1 求解速度是双层模型的头号敌人
双层模型最大的工程痛点不是建模,而是求解。日内滚动要求15分钟内必须出结果,而模型里含有二进制变量(机组的启停状态),属于混合整数线性规划(MILP)。如果日前层不加任何处理,直接和日内层用同一套完整模型,14个设备、96个15分钟时段的规模,商用求解器也可能跑出几分钟甚至更久。
我的处理办法有三个。第一,日前层用1小时分辨率,96时段模型比较小;日内层用15分钟分辨率但只优化4小时,模型规模也被限制住了。第二,给求解器设置合理的MIP Gap,比如1%;工程上没必要追求全局最优解到小数点后两位,1%的次优解换来速度的大幅提升,划算。第三,利用上层计算结果做“热启动”,把日前优化出来的开机状态作为日内层二进制变量的初值,能显著减少求解器的分支定界搜索时间。实测下来,日内层单轮求解能稳定控制在3秒以内,完全满足15分钟周期下发的实时性要求。
6.2 惩罚系数和滚动窗口的调参经验
滚动优化的参数里,最影响实际效果的是对日前计划的偏差惩罚权重λ。我一开始把λ取得很大,结果日内层死死咬住日前计划,光伏预测误差出现时宁可高价购电也不调整设备出力,滚动优化形同虚设。后来把λ降了两个数量级,系统才灵活起来。反复试下来,我的经验是先做敏感性分析,以“日运行成本 + 联络线偏差”的双指标综合评价,选定一个折中值。
滚动窗口方面,我建议按项目的数据刷新周期来定。如果预测系统每5分钟更新一次,滚动步长可以用5分钟;如果每15分钟更新一次,就设15分钟。滚动步长和预测刷新频率错配会造成信息浪费:步长比刷新周期短,中间几轮用的都是旧预测;步长比刷新周期长,新的预测又没能及时参与决策。
还有个细节:日内层的初始SOC必须用实测值,而且要在每次滚动开始前检查SOC是否越界。如果实测SOC低于模型下限(比如因为电池自放电),直接当作初始条件会导致优化无解。我给这种边界情况加了SOC校正逻辑,把越界的偏差折算成一个惩罚项,保证模型在极端情况下依然有可行解。
6.3 部署时容易忽略的数据与执行问题
模型本身跑通了,不代表现场能稳定运行。我在项目验收阶段遇到过几个和数据链路相关的问题,这里提醒一句:滚动优化的上限,由你的数据质量决定。
最典型的是预测数据时间戳不对齐。日前预测、超短期预测、实测采集三个系统的时间基准如果不统一,滚动优化拿到的“最新预测”可能是十几分钟前的旧数据,反馈校正的优势会被吃掉大半。我在现场用了一个数据缓存管理器,统一把所有数据源的时间戳对齐到同一时钟基准,并且为每个预测值打上“有效时间窗口”标签,过期预测一律弃用。
另外,控制指令下发环节也要考虑通信延迟。从优化器算出结果到执行机构真正动作,如果存在秒级到分钟级的延迟,15分钟滚动周期的有效性就会打折。我的做法是把下发时间点提前计算好,保证执行指令落在每个滚动时段的起点附近,而不是优化完成就立即下发。
最后,建议给日内层加一个“计划执行失败”的兜底逻辑。比如某台设备接收指令后没有按预期动作(通讯中断或设备故障),下一轮滚动读取状态时会发现SOC或出力对不上,优化器能自动重新规划;但如果连状态也读不到,就需要一个简单的规则兜底(比如按上一时刻指令继续执行),防止系统失去控制。这个问题看着不起眼,但现场调试时最容易耗尽你的耐心。
把我自己跑这一整套框架的体会浓缩成一句话:多时间尺度滚动优化的精髓不在数学模型有多华丽,而在于“不断用最新信息修正决策”这件事本身。只要预测刷新和状态反馈这两条数据链路不出问题,哪怕目标函数和约束写得朴素一些,系统也能跑得很稳。反过来,模型再精巧,数据链路断了,一切都白搭。这也是我做这个项目最大的收获。