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

资讯详情

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

多时间尺度源储荷协调调度策略及Matlab实现

多时间尺度源储荷协调调度策略及Matlab实现 调度室的大屏幕上日前安排的机组组合曲线还安安静静地躺在那里可到了中午光伏出力一路往上冲午后一场云又让出力瞬间掉了三四成。火电还在慢悠悠地爬坡储能电站的充电功率却被卡在计划值上——不是指令下不去而是站内好几簇电池的SOC已经顶到上限再充就会越限告警。这就是我最近在调的多时间尺度源储荷协调调度策略里最典型的一个场景。这个题目看起来很长拆开其实就是三件事储能电站不是一台电池而是成百上千簇电池组成的一个对象每簇之间SOC、容量、效率都有差异这就是标题里说的“特性分布”要让发电侧、储能、负荷侧配合起来拧成一股绳这就是“源储荷协调”而这种协调不能只在日前做一个静态计划得放到日前、日内、实时多个时间尺度上去滚动修正这才能应对预测误差和负荷波动。我这次用Matlab把整条策略从建模到代码实现完整走了一遍这篇就把整个思路、模型、代码结构和踩过的坑一起分享出来。适合正在做储能调度、微网优化、电力系统经济调度的同学参考尤其是想用Matlab把论文里的策略落地的朋友。1. 为什么储能接入后单时间尺度调度不再够用1.1 传统调度最大的麻烦是“断层”传统的电力调度习惯上是分段做的日前做机组组合和发电计划实时做AGC自动发电控制二者之间缺了中间环节。小时级的日前计划面对分钟级甚至秒级的波动非常被动比如上午10点前机组启停已经固定火电爬坡能力就摆在那风电和光伏出力又说不准负荷每天也都不一样。真正的调度员面对的是一个连续变化的动态过程而不是一张静态的计划单。这三个断层在工程上特别致命时间尺度断层日前计划是小时级或15分钟级的实时AGC是秒级的二者之间没有滚动修正的机制。对象断层传统调度只管机组发电不管储能电站怎么分配内部功率也不管可调负荷到底能调多少。信息断层预测误差出现之后没有一套回流到计划层的机制只能靠AGC在末端硬扛。单时间尺度模型要么“只看当下”要么“只按日前来”没有中间修正空间。储能一旦接入这个断层问题会被进一步放大。1.2 储能引入之后问题变成了“时间上的搬运”储能和发电机有个本质区别发电机是即时设备燃料往里倒、电往外发能量是连续的电池则是能量在时间轴上的搬运工——中午光伏多发就把电存起来晚上再放出去。这个搬运属性带来两个传统模型里没有的新麻烦。第一个麻烦是SOC是一个跨时段的记忆状态。今天凌晨做调度决策的时候必须知道晚上预期要放多少电否则可能白天把电充过头晚上该放的时候已经没电可放了。第二个麻烦是充放电效率、自放电率、寿命损耗并不是固定常数而是随使用状态变化的。储能电站的等效运行成本不像煤耗曲线那么好估计深度充放一次和浅充浅放一次对寿命的影响完全不同。如果只在单一时间尺度里建模短期层看不见明天的净负荷曲线长期层又追踪不到当前的实测SOC和预测偏差调度结果自然会出现“计划出力很大、实际根本执行不下去”的尴尬局面。1.3 为什么必须把源、储、荷放在一起协调源、储、荷三个对象的时间常数差别非常大。火电机组爬坡以分钟计储能响应是毫秒到秒级可调负荷和需求响应通常又按小时安排。如果三者各自为政会出现一个典型的错配新能源波动来了火电跟不上储能却因为日前计划没预留足够SOC区间而无法补上可调负荷又没有被激活——整个系统只能靠弃风弃光来维持平衡。多时间尺度协调的实质就是让快变量和慢变量各司其职。日前尺度里火电和储能协同安排基础运行点日内尺度里储能根据超短期预测快速修正偏差实时尺度里储能再做最后的兜底调节。源、储、荷各自的灵活性在不同时间尺度上被分层利用这样才能把整个系统的调节能力榨干用尽。2. “特性分布”到底在说什么储能不是一个电池组而是一群电池组2.1 站内电池簇的天然不一致工程上一个几十兆瓦时的储能电站并不是一台大电池而是由几十甚至上百个电池簇并联组成的。因为出厂批次差异、运行温度场不同、老化速度不同、内阻增长不同同一时刻站内各簇的SOC可能相差5%到15%SOH健康状态的差异会导致实际可用容量明显低于铭牌容量。如果不考虑这些差异调度模型把整个电站当成一台理想电池来处理优化结果下发到现场之后BMS和PCS会以“该簇SOC越限”“该簇功率超限”等理由拒绝执行指令。我在调模型时遇到过一模一样的情况日前优化给储能电站下发了80MW充电指令结果站内有一半的电池簇SOC已经到90%BMS直接限制了充电功率实际充电功率只有40MW出头。这就是“特性分布”这四个字的分量所在。2.2 三类核心特性分布要建模先要厘清到底哪些特性需要纳入考虑。我按工程常用分类整理了下面这张表特性类型具体内容对调度的影响建模处理建议SOC分布各簇当前荷电状态参差不齐决定哪些簇可充、哪些簇可放、可用调节方向聚类分群或加入SOC均衡约束SOH/容量分布各簇容量衰减程度不同可用容量小于铭牌值功率能力受限用SOH折算后的有效容量建模效率/响应分布充放电效率、响应速度不同影响成本计算和实时分配比例分群后按等效效率聚合2.3 把“分布”变成模型聚合分群加站内二次分配考虑特性分布不一定要把每一簇电池都塞进优化模型否则决策变量会爆炸仿真也跑不动。工程上我推荐两阶段方案。阶段一把电池簇按SOC、SOH等特征做聚类得到若干个代表性储能群。常见做法是K-means聚类目标可以写为min Σ_i Σ_k |SOC_i - C_k|² λ·|SOH_i - H_k|²其中C_k和H_k是第k类簇的SOC与SOH聚类中心λ是权重系数。聚类之后优化模型里只保留K个“等效储能单元”每个单元维护自己的SOC递推和功率约束。阶段二优化结果给出各储能群的总功率P_b,k站内再按各簇的可用功率和SOC均衡目标做二次分配。例如P_i P_b,k · (SOC_i - SOC_min_i) / Σ(SOC_j - SOC_min_j)这样既避免了变量爆炸又保证了站内各簇不至于出现“一个簇充到顶、另一个簇还空着”的极端情况。2.4 不考虑特性分布后果是什么用一组常见现象做个类比整站聚合模型相当于把所有电池假设成同一水位的水池但实际情况是这个水池被隔成了几十个格子格子之间的水位差很大抽水机能真正用到的有效容量远小于总容积。在类似规模的算例里SOC分布方差较大的储能电站如果按照整站聚合模型做调度实际可用的调节能力往往只有计划值的70%到80%。具体数值和电池簇数量、温度差异、老化程度都有关但趋势是确定的忽略分布特性调度计划的可执行性会显著下降。3. 三层时间尺度框架日前优化、日内滚动、实时调整如何分工3.1 日前层把“明天怎么安排”算清楚日前层是整个策略的骨架以净负荷预测曲线为基础将24小时划分为96个时段每15分钟一个时段优化目标是系统综合运行成本最小。决策内容包括火电机组的启停状态和出力曲线、储能电站各群在96个时段的充放电计划、可调负荷的用电计划调整量。这里最容易犯的一个错误是把日前计划当成唯一的依据认为提前算好了就能照着执行。实际运行中预测误差不可避免尤其是新能源出力预测误差达到20%以上是常态。所以日前层作用不是“定死未来”而是给后两层提供一个合理的运行基准和约束边界尤其是储能SOC的走廊。3.2 日内层用最新预测滚动修正日内层采用滚动时域控制每5到15分钟调用一次。每次滚动优化都读取最新的超短期预测数据把日前计划的热点转移过来作为软约束重新求解未来4到6小时内的调度方案。日内层输出的核心是两部分一是火电出力的修正量二是储能各群的SOC修正轨迹。比如日前计划里18:00储能SOC应该到90%但下午实际光伏多发了15:00储能已经充到了95%日内层就会及时调整后续几个时段的出力安排防止SOC越限。3.3 实时层秒级调节储能兜底实时层对应传统AGC的概念工作周期在秒级到分钟级。当系统频率偏差或联络线功率偏差出现时实时层需要快速决定谁来顶住这个差额。储能因为响应速度快通常在实时层扮演兜底角色。但实时层的分配不是简单均摊而是要把特性分布考虑进去SOC高的簇多放、SOC低的簇少放SOH好的簇承担更多调节任务SOH差的簇少动。这样既满足调节需求又能减少对老化严重电池的损耗。3.4 层与层之间的数据流三层之间不是孤立的数据流才是整个策略的灵魂。我常用下面这张表来梳理信息传递关系尺度层决策周期主要输入主要输出传递到下一层的信息日前层24小时96时段日前负荷预测、新能源预测、机组参数机组启停、出力计划、储能SOC计划机组运行状态、SOC走廊日内层每5~15分钟滚动4~6小时超短期预测、实测SOC、日前计划出力修正量、储能SOC修正轨迹修正后的出力基点、SOC目标实时层秒级频率偏差、实测充放电状态储能功率分配指令实际执行的SOC变化反馈给日内层一句话概括日前定骨架日内修偏差实时兜底线。4. 目标函数与约束的数学模型拆解4.1 目标函数设计不只有经济成本多时间尺度协调调度的目标函数通常不是单一的成本最小化而是多个目标的权衡。我采用的是典型加权形式min F Σ_t ( C_fuel(t) C_bat(t) C_curtail(t) C_loadshift(t) )其中C_fuel(t)火电燃料成本常按二次函数拟合C_fuel Σ_i (a_i·P_i² b_i·P_i c_i)C_bat(t)储能使用成本包含充放电循环带来的寿命损耗折算可以用等效折旧系数乘以功率绝对值来表示C_curtail(t)弃风弃光惩罚项通常设一个比较高的单位惩罚系数避免优化结果为省燃料而故意弃新能源C_loadshift(t)可调负荷调整带来的用户补偿成本权重系数的设置是一门实践学问。我的经验是先把弃风弃光惩罚设为燃料成本的5到10倍再根据仿真结果微调否则优化器会倾向于牺牲新能源来换取燃料成本最小。4.2 功率平衡与网络约束每个时段t都必须满足系统功率平衡Σ_i P_gen,i(t) P_wind(t) P_pv(t) Σ_k P_bat,k_dis(t) P_load(t) Σ_k P_bat,k_ch(t) P_shift(t)如果考虑网络安全可以加入直流潮流约束线路潮流限制为-P_l,max ≤ Σ_m GSF_l,m · P_inj,m(t) ≤ P_l,max其中GSF是发电转移系数P_inj是节点注入功率。算例规模不大时忽略网络约束只做功率平衡也能看出策略框架的行为特征但要发论文或者做实际规划建议把网络约束加上。4.3 储能运行约束与SOC递推方程储能群k的约束包括功率上下限和SOC递推充放电功率上下限0 ≤ P_ch,k(t) ≤ P_ch,k,max0 ≤ P_dis,k(t) ≤ P_dis,k,maxSOC递推SOC_k(t1) SOC_k(t) η_c·P_ch,k(t)·Δt/E_k - P_dis,k(t)·Δt/(η_d·E_k)SOC边界SOC_k,min ≤ SOC_k(t) ≤ SOC_k,max一般取0.1到0.9充放电互斥充放电不同时进行的约束代表性差异通过不同的SOC初值、E_kSOH折算后的有效容量和效率η来体现。如果采用了K-means分群每个群都有一套上述约束整站约束就是K组约束的联合。4.4 机组爬坡约束、负荷约束与多时间尺度耦合火电机组的爬坡约束在相邻时段之间耦合-R_down,i·Δt ≤ P_i(t1) - P_i(t) ≤ R_up,i·Δt可调负荷的总调整量通常有一个比例限制比如全系统可调负荷占比不超过总负荷的5%到10%。时间尺度的耦合重点在SOC。日前层算出的SOC轨迹要作为日内层的参考走廊日内层算出的SOC目标还要回传给实时层做功率分配这种跨层传递是“多时间尺度”的模型本质。实现上我会在日前层结束后把每个时段SOC的最优值存成一个向量在日内层里以软约束形式加入目标函数允许偏离但偏离要付出代价。5. Matlab实现路线从参数初始化到滚动时域控制5.1 程序结构与文件划分我习惯把代码拆成下面几个部分方便调试和复用main.m % 主循环负责调用各层模块 data_load.m % 读入负荷、新能源、价格、储能参数 init_storage.m % 初始化电池簇SOC/SOH并做聚类分群 day_ahead_scheduling.m % 日前优化求解 intraday_rolling.m % 日内滚动优化求解 real_time_dispatch.m % 实时层功率分配 compute_indicators.m % 计算弃风弃光率、SOC越限次数等指标 plot_results.m % 画曲线模块化最大的好处是可以单独改某个层面的约束而不影响其他层。比如想换一套实时分配策略只需要改real_time_dispatch.m其他层都不用动。5.2 参数初始化与预测数据准备参数初始化的质量直接决定优化结果的合理性。以我常用的测试系统为例参数取值调度周期24小时15分钟间隔T96火电机组数量3台容量分别为200/300/100MW新能源装机风电150MW、光伏100MW储能电站总容量100MWh30个电池簇聚类分4群储能功率限制每群最大充/放功率对应额定功率的0.25负荷可调比例总负荷的5%预测数据我会生成两组一组是“完美预测”用于验证策略上限另一组是加入随机误差的“实际预测”用于检验滚动修正的效果。这一步容易被忽略但没有误差场景多时间尺度的价值根本体现不出来。5.3 日前优化核心代码逻辑日前层用YALMIP建模的话核心代码如下所示。这里我把风电光伏出力和负荷都作为已知参数传入%% 日前优化YALMIP建模 T 96; P_gen sdpvar(3, T); % 三台火电机组出力 P_ch sdpvar(4, T); % 4个储能群充电功率 P_dis sdpvar(4, T); % 4个储能群放电功率 SOC sdpvar(4, T); % 4个储能群SOC Constraints []; % 功率平衡约束 for t 1:T Constraints [Constraints, ... sum(P_gen(:,t)) P_wind(t) P_pv(t) sum(P_dis(:,t)) ... P_load(t) sum(P_ch(:,t))]; end % 储能SOC递推约束 for k 1:4 for t 1:T-1 Constraints [Constraints, ... SOC(k,t1) SOC(k,t) eta_c(k)*P_ch(k,t)*dt/E_k(k) ... - P_dis(k,t)*dt/(eta_d(k)*E_k(k))]; end end % SOC边界和功率边界 Constraints [Constraints, 0.1 SOC(:) 0.9]; Constraints [Constraints, 0 P_ch(:) P_ch_max(:)]; Constraints [Constraints, 0 P_dis(:) P_dis_max(:)]; % 目标函数燃料成本 储能使用成本 弃风弃光惩罚 Objective 0; for t 1:T for i 1:3 Objective Objective a(i)*P_gen(i,t)^2 b(i)*P_gen(i,t) c(i); end Objective Objective sum(bat_cost(:).*(P_ch(:,t)P_dis(:,t))); Objective Objective curtail_penalty*(P_wind(t)P_pv(t) - ... min(P_wind(t)P_pv(t), P_load(t)sum(P_ch(:,t)))); end ops sdpsettings(solver, gurobi, verbose, 1); optimize(Constraints, Objective, ops);注意这里每簇电池的容量E_k是用SOH折算后的有效容量SOC的初始值是从init_storage.m聚类结果里取出来的各群加权平均SOC。5.4 日内滚动与实时控制的循环结构日内滚动层的主循环结构如下%% 日内滚动每15分钟重调度一次 T_roll 24; % 滚动窗口4小时15分钟一个点共16个点 for step 1:96 % 更新预测读取该时刻之后的预测序列 pred_wind forecast_wind(step:stepT_roll); pred_pv forecast_pv(step:stepT_roll); pred_load forecast_load(step:stepT_roll); % 读取实时SOC反馈 soc_now get_measured_soc(storage_plant); % 求解滚动优化日内层目标加入SOC偏离惩罚 [P_gen_ref, P_ch_ref, P_dis_ref] ... intraday_rolling(soc_now, pred_wind, pred_pv, pred_load, day_ahead_soc); % 把第一个时段的指令下发到实时层 real_time_dispatch(P_ch_ref(:,1), P_dis_ref(:,1), cluster_info); end实时层拿到总功率指令后按第2章提到的比例分配方法下发给各个电池簇同时检查每一簇的SOC边界。如果某一簇越限就将其功率置零把差额重新分配给其他簇。5.5 求解器选型与YALMIP配置注意事项在Matlab环境里做这类优化求解器选择直接影响成败。我的经验是纯线性模型目标函数没有二次项可以直接用linprog速度快、不依赖第三方求解器。目标函数包含火电成本二次项时推荐用YALMIP加Gurobi或者直接用MATLAB自带的quadprog。充放电互斥需要引入二值变量时模型变成混合整数规划建议用Gurobi或COPT这类商用求解器如果机器上没有装也可以用intlinprog先跑小规模算例。这里特别提醒一点不少同学在Matlab新版本里装老版本YALMIP会遇到求解器路径识别不了、许可证报错等问题。用哪个版本的求解器就在YALMIP的addpath里配套哪个版本路径混乱是这类工具链最常见的问题来源。求解器装好后先用一个随机小矩阵测试一下yalmip是否正常调用再开始跑调度模型能省很多查错时间。6. 算例验证与结果差异分析策略到底比不做协调好在哪里6.1 算例与对比方案设置为验证“多时间尺度”和“特性分布”两个核心点我设计了三个对比方案方案A不装储能只靠机组和常规调度方式运行。方案B装储能采用日前单尺度优化储能按整站聚合建模不考虑特性分布。方案C装储能采用日前、日内、实时多时间尺度协调调度储能按分群建模考虑特性分布。输入数据保持一致同一组负荷曲线、同一组风光预测数据含误差储能电站参数也一样只有建模方式是变量。6.2 关键指标与效果对比评价策略好不好我一般看四个指标系统运行成本、弃风弃光率、储能SOC越限次数、负荷峰谷差变化。下面是类似规模算例中比较典型的一组结果趋势具体数值会随算例数据变化重点看相对关系指标方案A方案B方案C运行成本均值基准值下降约8%~12%下降约12%~18%弃风弃光率12%~15%6%~10%2%~5%SOC越限次数-日均5~10次日均0次峰值负荷削减03%~5%5%~8%方案B的主要问题是日前计划做得再漂亮实时执行时因为SOC分布不均导致部分指令无法执行实际效果打折扣。方案C因为日内滚动修正了SOC轨迹实时分配又按各簇状态动态微调几乎不会出现越限因而调节能力被完整释放。6.3 结果解读与灵敏度分析这一类策略研究里结果不只有一个“更优”的结论更重要的是搞清楚“为什么更优”。我建议做完主场景后加一组灵敏度分析把电池簇之间的SOC分布方差从5%调到15%观察方案B和方案C的差距变化。通常趋势是SOC分布差异越大方案C相对方案B的优势越明显。这个结论在逻辑上也讲得通——特性分布越是参差不齐越需要一个能感知并响应这种差异的调度策略。如果你的算例里分布差异很小两方案的结果差异也会缩小反而是正常的说明模型没有失真。7. 实操中容易踩的坑与处理经验7.1 SOC初值决定全局走向多时间尺度模型的SOC是一个有记忆的状态变量初值设错整条轨迹都会偏离。最稳妥的做法是先用一段“预运行”来逼近一个相对合理的初始SOC分布让系统运行几天之后站内SOC分布自然进入统计稳定状态再开始正式记录指标。7.2 充放电互斥约束的非线性陷阱不少人为了表达储能不能同时充放电直接写P_ch * P_dis 0。这个约束是非线性的还带等式形式求解器非常容易陷入数值困难。正确做法是引入二值变量P_ch(t) ≤ M·u(t), P_dis(t) ≤ M·(1-u(t))其中M是一个足够大的正数u(t)是0/1变量。虽然模型从LP变成了MILP但求解稳定性远好于非线性写法。我用Gurobi解这个规模的MILP几百个变量也就几秒到几十秒的事完全可接受。7.3 预测误差更新频率别走极端滚动更新的频率不是越高越好。我的经验是5到15分钟滚动一次既不影响实时性能又不会让优化求解占用太多算力。每1分钟滚动一次不仅算力消耗大而且超短期预测在该时间尺度上的信息增益已经很小边际收益很低。7.4 模型粒度与仿真速度的平衡刚接触这类问题的人容易一上来就把每个电池簇、每条线路都建进去结果模型大得跑不动调参周期拉得很长。我的建议是分三步走先用整站聚合模型把三层框架跑通确认各层逻辑正确再加入分群聚类验证特性分布的影响最后根据研究需要加入网络约束或其他细节。这个由简到繁的过程基本能避免“一上来就卡死在求解器里”的困境。最后说点我在实际项目里的体会。多时间尺度源储荷协调调度这套策略框架本身并不难理解难点在于每一个细节都真实地影响最终结果SOC初值、预测误差建模、储能簇间分配比例、求解器选择任何一个环节处理草率优化结果都会和现场执行“两张皮”。在Matlab里把这套东西落地本质上是一个不断逼近物理现实的过程——把储能电站当成一群状态各异的电池来对待把调度决策放进多个时间尺度里去滚动修正结果自然不会差。
返回列表