尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

考虑特性分布的多时间尺度源储荷协调调度建模与实现

考虑特性分布的多时间尺度源储荷协调调度建模与实现 储能电站接入电网这件事这两年做调度的人应该都感受很深——单机优化、静态断面分析的老套路已经不太够用了。源侧有风电光伏的间歇性荷侧有越来越复杂的用电行为再把储能电站这种双向可调的单元加进来整个系统的时间特性一下子丰富起来火电爬坡慢、储能响应快、负荷波动随机如果还在单一时间尺度上做调度要么计划冒进执行不了要么反应太慢白白浪费储能能力。所以多时间尺度源储荷协调调度不是学术圈造概念而是实际运行里被逼出来的需求。这篇文章我从工程落地的角度把这套策略的建模思路、三层时间尺度框架、约束表达以及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(t1) 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或CPLEXLP问题也可以用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, T1); % 储能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,t1) 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 三层时间尺度如何串起来完整的多时间尺度仿真脚本我推荐按下面的流程组织初始化所有数据生成预测序列。执行日前优化得到P_g_day、SOC_day轨迹。进入日内循环用最新预测数据以日前SOC轨迹为参考滚动求解4小时优化问题取出第一个时段的储能指令。执行实时MPC在日内指令基础上根据实际出力偏差计算储能修正量。更新储能各分群SOC状态。收集所有结果画图分析。这里面需要注意一个细节从日前到日内再到实时每一层的决策变量名称和含义要区分清楚。我习惯命名成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与可用功率的分段线性近似、净充电功率的建模、滚动时域里基准轨迹的传递这些看着不起眼的处理恰恰决定了仿真能不能真实反映系统运行情况。先把这些基础环节做扎实再慢慢往模型里加通信约束、需求响应、辅助服务这些更复杂的场景路径就顺畅多了。
返回列表