考虑特性分布的多时间尺度源储荷协调调度建模与实现
2026/9/9 21:05:58 网站建设 项目流程

储能电站接入电网这件事,这两年做调度的人应该都感受很深——单机优化、静态断面分析的老套路已经不太够用了。源侧有风电光伏的间歇性,荷侧有越来越复杂的用电行为,再把储能电站这种双向可调的单元加进来,整个系统的时间特性一下子丰富起来:火电爬坡慢、储能响应快、负荷波动随机,如果还在单一时间尺度上做调度,要么计划冒进执行不了,要么反应太慢白白浪费储能能力。所以多时间尺度源储荷协调调度,不是学术圈造概念,而是实际运行里被逼出来的需求。这篇文章我从工程落地的角度,把这套策略的建模思路、三层时间尺度框架、约束表达,以及Matlab代码实现的关键环节完整梳理一遍。

标题里有一句"考虑特性分布",很多人第一次看容易忽略,但恰恰是这句话决定了模型能不能贴合实际。储能电站不是一台理想电池,它是由大量电池簇、电池单体聚合起来的,不同簇之间SOC、SOH、内阻、可用容量都存在差异。所谓考虑特性分布,就是在调度模型里把这种差异显式表达出来,而不是简单用一个等效电池代替整个电站。这套思路加上多时间尺度协调,基本就是当前储能参与电网调度的主流技术路线。

1. 储能电站接入后,调度模型的核心矛盾在哪

1.1 源、储、荷三者在时间尺度上的天然错配

电网调度之所以难,本质上是因为源、储、荷的响应速度根本不在一个量级上。风力发电的波动是秒级到分钟级的,光伏受云层影响可能在几分钟内剧烈升降,负荷侧既有平稳的基荷,也有冲击性的短时大功率变化。而传统火电机组的爬坡速率通常在每分钟1%到3%额定功率左右,从调度指令下达到实际出力变化,中间隔着汽轮机、锅炉的热惯性,快不起来。

储能电站的加入提供了一个非常特殊的调节资源:它的功率响应可以达到毫秒级到秒级,双向可调,既能充电也能放电。但这个"快"是有限制的,它的能量是有限的,SOC不能越界,充放电功率受PCS容量限制,长期运行还要考虑循环寿命损耗。这就构成了一个矛盾:系统需要储能承担快速调节任务,但储能自身的能量约束和特性差异又限制了它不能想怎么用就怎么用。

如果把所有决策都放在同一个时间尺度上做,比如只做日前24小时优化,那么日内出现的预测偏差就没人管;如果只做实时控制,那又失去了前瞻性,容易把储能电量在某个时段耗尽,后面出现高电价或高负荷时段反而无电可用。所以多时间尺度协调调度,本质上是把决策分层:时间尺度长的负责前瞻和计划,时间尺度短的负责修正和执行。

1.2 储能的"特性分布"为什么不能忽略

储能电站内部的一致性问题是工程里躲不掉的。一组新投运的电池簇,出厂时各项参数基本一致,但运行一段时间后,因为温度分布不均、充放电深度不同、电池单体自放电率差异,不同簇之间的SOC和SOH会逐渐拉开差距。如果调度模型假设整个电站是一个理想等效电池,按平均SOC去安排充放电计划,实际执行时就会出现部分电池簇已经达到充电截止电压、部分还远没充满的情况,电站实际可用的功率区间跟模型算出来的完全对不上。

特性分布要表达的东西,简单说就是:电站的可用功率不是一个固定值,而是与当前各电池簇的状态分布有关。比如某簇SOC偏高,那它还能充电的容量就小;某簇SOH偏低,内阻大,同样功率下发热严重,调度上就应该限制它的出力。把这些分布信息吃进模型,调度策略给出的指令才是物理上可执行的。

1.3 多时间尺度调度不是简单地把模型跑三遍

我见过不少初学者有个误解,觉得多时间尺度调度就是把日前模型在日内再跑一次、在实时再跑一次,顶多改改预测数据。实际上三层时间尺度之间有严格的逻辑关系:日前计划确定机组启停和储能日前充放电的基准曲线,日内滚动优化在基准曲线上做修正,实时层则只处理短时偏差。每一层模型的决策变量、约束条件、时间分辨率都不一样,而且层与层之间有信息传递——上一层的优化结果会作为下一层的边界条件或者基准值。

这里有一个关键设计思想:各层不是各算各的,而是通过"计划-修正-反馈"的闭环串起来。日前给日内提供基准,日内给实时提供参考,实时执行的结果再反馈回去,影响下一轮日内的滚动优化。这个闭环就是协调二字的精髓。

2. 特性分布建模:给储能电站做一张"状态画像"

2.1 用聚类分群描述储能特性差异

特性分布建模的第一步是确定用哪些特征参数来描述电池簇的状态。工程上最常用的是三个:SOC(荷电状态)、SOH(健康状态)、最大允许充放电功率。SOC决定了当前的剩余能量,SOH决定了可用容量,最大允许功率则由PCS容量和电池自身特性共同决定。

一个储能电站可能有几十甚至上百个电池簇,如果每簇都作为一个独立单元进入调度模型,变量数量会爆炸,求解速度完全不可接受。所以工程上通常的做法是先做聚类分群:把特性相近的电池簇聚成一类,每一类用一个代表性参数描述。聚类的依据可以是当前SOC、SOH、温度等特征,常用的方法包括K-means聚类或按SOC区间分段。

聚类之后,电站在某个时刻的可用充放电能力就不是一个点,而是一个由各分群状态共同决定的聚合可行域。比如某几个分群SOC偏低,那充电能力就强、放电能力弱;另外几个分群SOC偏高,情况就反过来。把这些分群的参数代入模型,调度的结果自然而然地会优先调用状态更合适的电池簇。

2.2 从特性分布到调度约束的转化

有了分群参数,下一步是把它们转化成优化模型里能用的约束。假设电站内部有N个电池分群,每个分群i在t时刻的SOC记为SOC_i(t),那么聚合电站的总充电功率上限、总放电功率上限分别由各分群状态决定。

充电时,分群i可接受的充电功率受两个因素限制:一是该分群PCS允许的最大充电功率,二是该分群剩余可充电容量。如果SOC_i(t)已经接近SOC_max,即使PCS能扛得住,电池也不能继续大功率充电,否则电压会迅速逼近截止值。放电同理,SOC偏低时分群可放电功率会受限。

这个转化过程写进代码时,最常见的是用分段线性函数近似SOC与可用功率的关系。SOC在中间区间时可以保持额定功率,贴近上下限时功率线性下降。这种近似虽然简单,但工程上非常实用,既保留了特性分布的本质信息,又不需要引入非线性约束,对求解器非常友好。

2.3 特性分布的时变更新

特性分布不是静态的,随着充放电进行,各分群的SOC会动态变化,SOH则是一个慢变量,按天或按月变化。调度模型里必须有一套状态更新机制:每个调度时段结束后,根据该时段各分群的实际充放电量,更新下一时段的SOC,然后重新计算可用功率区间。

在MATLAB代码实现时,我是把特性分布做成一个结构体数组来管理,每个元素对应一个电池分群,包含SOC、SOH、额定容量、最大功率等字段。每个调度周期结束时调用一个更新函数,传入该周期的充放电功率,返回更新后的状态。这个设计的好处是代码结构清晰,后续如果要改成动态聚簇也很方便。

3. 三层时间尺度框架:日前、日内、实时各管一段

3.1 日前调度:在24小时尺度上定基准

日前调度是整个策略的顶层,它在负荷预测和新能源出力预测的基础上,安排未来24小时的机组启停计划、储能充放电计划,以及联络线交换功率。时间分辨率一般取1小时,预测误差相对较大,所以日前计划不追求精细,重点是算出一个经济性较好、可行的大框架。

日前模型的目标函数通常包括火电燃料成本、启停成本、储能充放电的寿命损耗成本,以及弃风弃光惩罚。约束包括功率平衡、火电出力上下限和爬坡约束、储能SOC轨迹约束、网络安全约束等。储能在这个层面是一个聚合模型,特性分布信息以聚合可行域的形式进入约束。

这里有个容易被忽略的点:日前计划给储能安排的SOC轨迹,要为日内和实时留出足够的调节裕度。比如预测午间光伏大发,日前计划安排储能中午充电,那就不能把SOC从早上就充满,必须预留一部分充电空间。在目标函数里加一个SOC目标带约束,让储能尽量运行在一个偏中间的区域。

3.2 日内滚动优化:用最新预测修正计划

日内滚动优化是应对预测误差的核心环节。它的思路是每过一定时间间隔(通常15分钟到1小时),用最新的超短期预测数据重新求解一次未来数小时(比如4小时)的优化问题,但只执行第一个时段的指令,到下一个周期再滚动求解。

日内模型与日前模型相比,变化有三点:一是预测精度更高,风电光伏出力基本能看准未来几小时的变化趋势;二是决策变量里增加了储能更精细的充放电功率调整量;三是日前确定的机组启停状态一般不再改变,只调整出力水平,这样避免了频繁启停机组带来的成本和安全问题。

滚动优化的代码实现上,我建议用一个while循环来模拟时间推进,每个循环迭代内调用一次优化求解,然后取出第一个时段的决策结果下发,更新时间状态。这样可以完整复现实际运行中滚动计算的过程。

3.3 实时调整:盯住秒级到分钟级的偏差

实时层处理的是分钟级甚至秒级的功率偏差。经过日前和日内两层优化,大部分预测误差已经被消化,实时层的任务就是跟踪运行点,把实际功率与计划值之间的偏差控制在允许范围内。

储能在实时层的角色是快速响应。当实际风电出力低于预测值,系统出现功率缺额,储能快速放电补上;当实际负荷低于预测值,系统功率过剩,储能吸收多余电量。这里的控制逻辑可以用简单的比例调节,也可以做一个基于模型预测控制的短时优化。工程实现上,MPC在实时层的应用效果很好,但要注意计算时间必须小于控制周期。

3.4 三个时间尺度的接口设计

三层时间尺度不是各自独立的,接口设计决定了协调效果。我总结下来有三个关键接口:

  • 日前到日内:日前计划的机组启停状态、储能SOC基准轨迹传给日内,日内在这基础上做调整,不能推翻重来。
  • 日内到实时:日内优化出的第一个时段计划值作为实时层的参考值,实时控制围绕这个参考值做偏差修正。
  • 实时到日内:实时层的执行结果(实际充放电量、最终SOC)反馈给下一轮日内滚动,作为初始状态。

用表格表示各层参数比较直观:

时间尺度预测精度分辨率优化周期主要任务
日前较低1小时24小时机组启停、储能基准计划
日内中等15分钟-1小时4小时滚动出力修正、储能精细调整
实时较高分钟级单周期偏差跟踪、快速响应

这个设计里,层次越往下时间分辨率越高、模型范围越小、计算量越可控,这是多时间尺度框架能够实际部署的关键。

4. 优化模型的数学表达与求解配置

4.1 目标函数设计:单一成本型怎么写清楚

以一个典型的风-火-储系统为例。调度模型的目标函数可以写为:

min F = Σ_t ( C_g(P_g(t)) + C_ess(P_ch(t), P_dis(t)) + λ_pv · P_curtail(t) )

其中C_g是火电发电成本,通常用二次函数或分段线性函数表示;C_ess是储能充放电带来的寿命损耗和运行成本;λ_pv是弃光惩罚系数;P_curtail是弃光功率。目标函数的核心矛盾在于:多发电意味着多收入但要承担燃料成本和碳排放,储能调节可以减少弃光但自身有损耗成本,两者的平衡点就是最优解。

实际建模时,火电成本函数如果不是线性,求解会慢很多。我的建议是把它线性化成分段函数,比如把出力区间切成4到5段,每段对应一个边际成本,既有精度又不增加变量类型。储能寿命损耗成本可以用一个与充放电深度有关的惩罚项近似,简化处理时直接乘以一个很小的成本系数,目的只是防止储能频繁动作。

4.2 约束条件逐条分解

约束条件是调度模型的骨架,我按类别拆开说。

第一类:功率平衡约束。任意时刻t,系统总发电(火电+新能源+储能放电-储能充电)必须等于负荷。这是最核心的约束,每个时间尺度都要满足。

第二类:火电出力约束。包括出力上下限P_g_min ≤ P_g(t) ≤ P_g_max和爬坡约束,爬坡约束是日前模型和日内模型的连接纽带,日内不能要求机组在15分钟内完成爬坡,这必须依据日前确定的爬坡速率来约束。

第三类:储能SOC动态约束。这是储能模型的核心,SOC(t+1) = SOC(t) + η_ch·P_ch(t)·Δt/E_rate − P_dis(t)·Δt/(η_dis·E_rate),其中η_ch和η_dis分别是充放电效率,E_rate是额定容量。注意充放电效率如果分开建模,模型会出现双线性项,工程上常用一个简化做法:定义净充电功率P_ess(t)(正为充电、负为放电),用统一的充放电效率近似,SOC更新变成线性约束,求解速度快很多。

第四类:储能功率与SOC耦合约束。这是特性分布进入模型的地方。分群i的充电功率不能超过该分群当前可用充电功率上限,这个上限与SOC_i(t)相关。上面提到的分段线性近似就在这个环节起作用。

第五类:网络安全约束,主要是线路潮流不越限。在Matlab仿真里如果用的是直流潮流模型,这条约束是线性的,可以直接加入。如果做交流潮流,一般只在日前尺度用,日内和实时用直流潮流或者灵敏度近似。

4.3 求解器的选择与配置

这类多时间尺度调度模型的变量规模差别很大。日前模型如果是30台机组、24个时段、储能若干分群,变量数在几千到上万之间,有整数变量(机组启停)的话就是MILP问题。日内模型如果机组启停固定,就退化成LP问题。实时MPC的变量更少,几百个以内。

我常用的配置是:Milp用YALMIP建模,求解器用Gurobi或CPLEX;LP问题也可以用MATLAB自带的linprog,但大规模场景下Gurobi快得多。如果你没有商业求解器,可以用开源的CBC或者SCIP,但要注意安装的兼容性。YALMIP的好处是建模层与求解层分离,换求解器只需要改一行代码。

5. Matlab代码实现:从数据准备到结果输出

5.1 数据结构的组织方式

动手写代码前,第一件事是规划好数据怎么存。我建议用结构体分三层:

  • Data.load:负荷数据,24小时或96点
  • Data.renewable:风电、光伏预测出力和实际出力
  • Data.thermal:火电机组参数,包括容量、爬坡率、成本系数、初始状态
  • Data.ess:储能分群参数,包括各分群容量、SOC初值、最大功率、充放电效率、SOH

尤其要注意储能分群的数据组织,可以用一个数组,每一行代表一个分群,列是SOC、SOH、容量、最大功率。这样后面写约束时可以直接用矩阵运算,不需要写一堆for循环。

5.2 YALMIP建模的核心代码框架

下面是日前调度的核心建模框架,我用YALMIP来写:

% 决策变量 P_g = sdpvar(n_gen, T); % 火电出力 u_g = binvar(n_gen, T); % 机组启停状态 P_ess = sdpvar(n_ess, T); % 储能分群净充电功率(正充负放) SOC = sdpvar(n_ess, T+1); % 储能SOC % 目标函数 obj = 0; for t = 1:T for g = 1:n_gen obj = obj + c_gen(g,1)*P_g(g,t) ... + c_gen(g,2)*P_g(g,t)^2; % 发电成本 end obj = obj + c_ess * sum(abs(P_ess(:,t))); % 储能损耗成本 end % 功率平衡约束 Constraints = []; for t = 1:T Constraints = [Constraints, ... sum(P_g(:,t)) + P_re(t) + sum(P_ess(:,t)) == P_load(t)]; end % 储能SOC动态 for t = 1:T for i = 1:n_ess Constraints = [Constraints, ... SOC(i,t+1) == SOC(i,t) - P_ess(i,t)*dt / E_rate(i)]; end end % 求解 optimize(Constraints, obj, sdpsettings('solver','gurobi'));

注意上面这个框架里我特意用净充电功率P_ess来建模,正值为充电,负值为放电。这样做的好处是SOC更新约束是线性的,避免了充放电双线性项。下面再补上SOC边界、功率边界和特性分布约束。

5.3 特性分布约束的代码写法

特性分布约束的关键,是把各个分群的可用功率跟SOC关联起来。我用一个分段线性函数来实现:

% 分群i在SOC状态下允许的最大充电功率 % soc_low, soc_high: 线性过渡区间 % P_max: 额定最大充电功率 function P_ch_max = soc_limited_ch_power(SOC_i, soc_low, soc_high, P_max) if SOC_i <= soc_high P_ch_max = P_max; elseif SOC_i >= 1 P_ch_max = 0; else P_ch_max = P_max * (1 - SOC_i) / (1 - soc_high); end end

这个函数的意思是:SOC低于某个阈值(比如0.9)时,分群可以按额定功率充电;SOC超过0.9后,充电能力线性下降;SOC越接近1,能充的功率越小。放电侧逻辑对称,SOC高于0.1时能按额定功率放电,低于0.1后放电能力线性下降。

这个近似模型虽然不是最精细的,但稳定性非常好,在工程里大量使用。因为它本质上是对电池极化特性的一种简化表达——电池SOC接近充满或放空时,极化阻抗急剧增大,大功率充放电会导致电压快速越过截止限。

5.4 三层时间尺度如何串起来

完整的多时间尺度仿真脚本,我推荐按下面的流程组织:

  1. 初始化所有数据,生成预测序列。
  2. 执行日前优化,得到P_g_day、SOC_day轨迹。
  3. 进入日内循环:用最新预测数据,以日前SOC轨迹为参考,滚动求解4小时优化问题,取出第一个时段的储能指令。
  4. 执行实时MPC:在日内指令基础上,根据实际出力偏差计算储能修正量。
  5. 更新储能各分群SOC状态。
  6. 收集所有结果,画图分析。

这里面需要注意一个细节:从日前到日内再到实时,每一层的决策变量名称和含义要区分清楚。我习惯命名成P_ess_day、P_ess_intra、P_ess_real,避免不同时间尺度的结果互相覆盖,后面调试的时候也少掉头发。

6. 仿真算例设计与结果对比

6.1 典型算例参数设置

为了让结果有说服力,我建议设置一个包含对比组的算例。假设一个系统包含4台火电机组、一个200MW风电场、一个50MW/100MWh储能电站,储能分为3个特性分群,初始SOC分布分别为0.9、0.6、0.3,正好拉开差距来体现特性分布的影响。负荷曲线用典型的双峰曲线,风电出力设置一个晚上大白天小的反调峰场景。

对比组可以这样设计:方案A是无储能,方案B是不考虑特性分布的单层调度,方案C是本文的多时间尺度协调调度。三个方案跑同一个场景,对比指标包括弃风率、负荷峰谷差、系统运行成本。

6.2 关键结果怎么解读

仿真出的结果一般有以下几个规律,可以对照检查自己的模型是否正常:

第一,多时间尺度策略的弃风率明显低于单层调度。原因是日内滚动优化能够根据最新的风功率预测及时修正储能计划,不会出现日前安排充电、实际风没了还硬充的情况。

第二,储能SOC轨迹更平滑。日内和实时层的修正让储能不会在某个时段被逼到SOC边界,寿命损耗会更小。

第三,火电的爬坡压力下降。多时间尺度协调让储能承接了大部分短时波动,火电出力变化率显著降低。

如果算出来的结果不符合这些规律,先检查约束是否写错,再看预测误差是否合理。我遇到过不少次,结果不对不是模型问题,而是预测数据的波动范围设得太离谱,导致日内层根本没有调整空间。

6.3 参数敏感性分析

实际操作中,有四个参数对结果影响非常大,值得专门做敏感性分析:储能额定容量、最大充放电功率、预测误差水平、分群SOC差异程度。特别是最后一项,如果三组SOC差异很大但模型不考虑,算出来的调度计划执行时的偏差会非常大。通过敏感性分析,可以直观看到"考虑特性分布"带来的增益到底有多大。

7. 代码落地过程中常踩的坑

7.1 变量单位不统一,结果全乱

储能建模中功率用MW、容量用MWh,时间间隔用小时,这三个单位必须一致。如果SOC更新公式里Δt用的不是小时单位,比如用了15分钟却按1小时算,结果会差4倍。我建议在代码开头做一个单位换算的公共函数,所有数据进入模型前统一成MW和MWh,不要在模型里临时换算。

7.2 整数变量太多,求解卡死

日前模型如果机组数多、时段长,启停整型变量会非常多。一个只有20台机组24时段的模型就有480个二值变量,如果再引入储能分群的启动状态,变量更多。求解MILP很费时间,我的经验是:能线性化的都线性化;储能的状态变量用连续变量,不要人为加整数约束;如果机组启停决策在日前已经定了,日内和实时模型就不要再出现整数变量。

7.3 SOC边界的数值问题

SOC更新是递推关系,如果SOC初值设置不合理,比如所有分群都从1.0开始,那么第一时段充电功率必然被限制到很低,模型可能无解。建议初值都设置在0.2到0.8之间,并且给SOC约束留1%-2%的裕度,避免求解器因为数值误差误判越界。

7.4 预测数据的生成方式

仿真里用的预测数据一般是由真实数据叠加误差生成的。误差的分布要合理,比如风功率预测误差用正态分布近似,但注意截断——不能让预测值超出装机容量或者变成负值。另外,实时层用到的"实际出力"跟日内层用到的"预测出力"要有明显的差异,不然三层时间尺度就没有存在意义了。

回头看这套多时间尺度源储荷协调调度,本质上没什么神秘的技术,更多是把储能的状态特性、源侧的波动特性和负荷的变化规律,按照各自的时间尺度分层建模,让每一层干每一层最擅长的事。MATLAB只是工具,真正花心思的地方在数据怎么组织、约束怎么表达、三层模型怎么衔接。上面这些内容,从特性分布的聚类建模到三层时间尺度的模型衔接,再到代码实现和调参细节,都是我实际调试过、踩过坑后沉淀下来的东西。

如果你自己也搭过类似的调度模型,应该能感觉到,模型能不能跑通、结果合不合理,往往不取决于优化算法本身,而取决于你对物理过程的理解落到代码上的方式。比如SOC与可用功率的分段线性近似、净充电功率的建模、滚动时域里基准轨迹的传递,这些看着不起眼的处理,恰恰决定了仿真能不能真实反映系统运行情况。先把这些基础环节做扎实,再慢慢往模型里加通信约束、需求响应、辅助服务这些更复杂的场景,路径就顺畅多了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询