ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

储能电站调度策略:特性分布建模与多时间尺度源储荷协调

储能电站调度策略:特性分布建模与多时间尺度源储荷协调 “储能电站接入电网的调度策略”这几年几乎是电力系统方向最热的方向之一但很多做仿真的人一看标题里带着“特性分布”四个字就有点发怵。我最初也踩过这个坑把储能电站等效成一个巨型电池按平均SOC、额定功率直接塞进优化模型结果调度指令下发后站内各个电池簇有的过充、有的过放实际响应能力远低于预期。后来才明白储能电站不是“一个电池”而是几十上百个电池簇的聚合体每簇的SOC、SOH、可用容量、功率特性都有差异——这就是“特性分布”。如果不把这个分布特征考虑进去任何调度策略在工程落地时都会打折扣。这篇内容要把“考虑特性分布的储能电站接入的电网多时间尺度源储荷协调调度策略”讲透并且给出Matlab代码实现思路。能干这些事建立考虑电池簇SOC/SOH差异的储能聚合模型搭起日前-日内-实时三个时间尺度的滚动调度框架实现“源—储—荷”协同优化用MatlabYalmip调用Cplex/Gurobi求解最后用仿真结果验证“考虑特性分布”到底值不值得。适合正在做微电网、输配电网调度研究的研究生也适合刚接触电力系统优化调度的工程师照着代码改一改参数就能跑出自己的场景。1. 问题背景与总体思路1.1 为什么“特性分布”这件事必须较真先说个直观的例子。一个100MW/200MWh的储能电站里面通常有几十个电池簇每个簇由多个电池箱串联并联组成。出厂时各簇参数看似一致但运行一年后由于温度场不均匀、充放电倍率差异、电池自放电率不同各簇的容量衰减速度完全不同。有的簇SOH还在95%有的已经掉到88%。如果调度中心只看电站整体SOC假设是50%按50% SOC对应的最大功率下发指令实际运行时会怎样高SOC的簇还能继续放电但低SOC的簇可能已经逼近下限无法按指令出力各簇SOC越拉越开系统可用功率比“理想等效电池”算出来的小得多长期这样调度部分电池簇过放加速老化整个电站寿命缩短。“特性分布”描述的就是这种差异的现实存在。它不只是SOC分布的差异还包括SOH健康状态、内阻、温度、最大充放电功率等特性的分布。把这些分布纳入调度模型才能让“储能参与电网调度”这件事从论文走向工程。1.2 多时间尺度协调调度的整体框架电网调度天然分层分时。负荷和新能源出力在不同时间尺度上的波动特性差异很大用单一时间尺度的模型去描述必然顾此失彼。常规做法是三层递进日前调度Day-ahead提前24小时时间分辨率1小时决定机组启停、计划出力、储能日充放电计划。解决“明天怎么安排”日内滚动Intraday提前4~6小时滚动优化时间分辨率15分钟或5分钟根据最新预测修正出力。解决“未来几小时怎么调整”实时控制Real-time秒级到分钟级用储能和可调负荷平抑分钟级波动。解决“当前平衡怎么保”。储能在这三个尺度中扮演不同角色日前提供一个“日级能量平移”的框架日内做“预测误差补偿”实时做“快速功率跟随”。而“源储荷协调”就是把火电、风光、储能、负荷响应放到同一个优化问题里让各方各司其职。1.3 技术路线与选型考量我的实现方案是先把储能电站内部各电池簇的SOC/SOH/功率特性建模为“多单元状态集合”再用概率分布如正态分布、均匀分布或离散化区间描述特性差异然后将聚合后的储能模型放入多时间尺度优化框架用Matlab的Yalmip工具箱建模调用Cplex/Gurobi求解混合整数线性规划MILP问题。为什么不直接用智能算法粒子群、遗传算法虽然写起来简单但面对大规模混合整数规划收敛性和最优性都很难保证而且每个时间尺度都要滚动求解计算量吃不消。用MILP配合商业求解器在保证全局最优性的前提下计算速度快、可复现性强这也是工业界的主流做法。2. 储能特性分布建模与数据准备2.1 储能电站的基本特性参数要建模先捋清楚储能电站有哪些关键参数。单个电池簇或储能单元必须具备以下四类属性参数符号含义典型单位E_i额定容量MWhP_i^max最大充放电功率MWSOC_i当前荷电状态%SOH_i健康状态容量保持率%η_c / η_d充电/放电效率puP_i^loss自放电损耗%/h特性分布主要体现在SOC_i和SOH_i上。SOC_i的分布可由运行历史决定SOH_i则决定了实际可用容量E_i^avail E_i * SOH_i。很多论文假设所有簇同质直接用一个总容量E_total这在工程上是有偏差的。2.2 特性分布的数学描述我推荐两种描述方式方式一离散单元法。将储能电站看成N个可独立调度的单元每个单元有各自的SOC_i、SOH_i、P_i^max、E_i。调度时需要决策每个单元的输出功率P_i^t。这种方式最精确但变量数会随单元数增加求解规模变大。适合单元数在50个以内的场景或者对站内管理要求高的应用。方式二聚合分布法。将SOC_i近似为某种概率分布如正态分布SOC_i ~ N(μ_soc, σ_soc^2)用均值和方差描述整体状态然后推导聚合后的可用充放电功率范围P_charge^agg min( Σ P_i^max_charge, (SOC_i^max - SOC_i)*E_i / Δt / (1 - η) ... 等约束 )这种方式变量少适合大电网层面的日前调度。缺点是无法精细到单簇控制通常需要与站内能量管理系统配合做二次分配。实际工程中这两种方式可以结合电网侧模型用聚合分布法站内EMS用离散单元法做功率分配。我在代码里主要实现了离散单元法因为它更直观也更容易验证“特性分布”带来的影响。2.3 基于Matlab的数据生成与参数初始化代码的第一步是构造一个储能电站实例。假设电站规模100MW/200MWh由20个5MW/10MWh的电池簇组成。各簇SOC初始值通过正态分布生成% 储能电站参数 n_cluster 20; P_max 5; % 每簇最大功率 5MW E_rated 10; % 每簇额定容量 10MWh % 特性分布SOC初始值服从正态分布 mu_soc 0.5; sigma_soc 0.1; SOC_init mu_soc sigma_soc * randn(n_cluster, 1); SOC_init max(0.1, min(0.9, SOC_init)); % 截断到合理范围 % SOH分布容量保持率在 [0.85, 0.95] 之间 SOH 0.85 0.1 * rand(n_cluster, 1); E_avail E_rated * SOH; % 实际可用容量注意randn生成的正态分布值可能超出合理范围需要做截断处理。SOH分布我建议用均匀分布或Beta分布取决于实际老化数据。没有实测数据时Beta(2,2)也可以模拟中间多、两端少的SOH分布。运行初始化后可以画一个SOC分布直方图直观看到各簇差异。这一步虽然简单但很多人会忘记做边界截断导致初始SOC超过100%后面一算就负值非常尴尬。3. 多时间尺度优化调度模型详解3.1 日前调度模型目标函数与约束日前调度的任务是给出24小时T24Δt1h的机组启停和出力计划。目标函数我习惯用“总运行成本最小化弃风弃光惩罚”min F Σ_t [ Σ_g (a_g * P_g,t^2 b_g * P_g,t c_g * u_g,t) λ_wind * P_wind_curtail,t λ_pv * P_pv_curtail,t λ_ess * (P_ess_charge,t P_ess_discharge,t) ]火电成本用二次函数离散化后可以用分段线性近似Yalmip有for循环加辅助变量。弃风弃光惩罚系数λ通常设得比火电边际成本高比如500~800元/MWh以保证优先消纳新能源。储能本身的充放电损耗已经在模型中体现无需额外惩罚但为了延长寿命可以对深度充放加一个小惩罚项。约束条件包括功率平衡约束Σ P_g,t P_wind,t P_pv,t P_ess_discharge,t P_load,t P_ess_charge,t P_loss,t 这里P_ess_discharge和P_ess_charge不能同时大于0需要引入二进制变量u_ess,t。火电爬坡约束P_g,t - P_g,t-1 ≤ R_up_g, P_g,t-1 - P_g,t ≤ R_down_g储能SOC动态方程SOC_t1 SOC_t (η_c * P_c,t * Δt / E_total) - (P_d,t * Δt / (η_d * E_total))注意如果考虑特性分布E_total不是固定的而是所有电池簇可用容量之和。SOC_t也应理解为聚合SOC的加权平均值或者直接用各簇SOC向量。在离散单元模型中SOC_i,t1要逐簇更新SOC_i,t1 SOC_i,t (η_c * P_c,i,t * Δt / E_avail_i) - (P_d,i,t * Δt / (η_d_i * E_avail_i))这里的E_avail_i E_rated_i * SOH_i。3.2 日内滚动修正模型日内滚动的思路是每15分钟或每1小时重新优化未来4小时时间分辨率15分钟只执行第一个时段的指令然后再次滚动。这样能把最新预测的误差纳入优化抵消“预测不准”带来的影响。模型结构和日前类似但变化有两处机组启停状态固定为日前决定的方案不再改变储能SOC初始值从实时SCADA读取而不是用预测值。代码实现时用一个循环结构for t_roll 1:96一天96个15分钟时段每次优化未来16个点时只取第一个结果。这种“滚动时域控制RHC”是工程中很实用的技术。我实际测试时发现滚动调度的效果高度依赖负荷和新能源预测数据的更新频率。如果预测数据是每小时更新一次那么日内时间分辨率设15分钟的意义就不大——因为中间15个点的预测还是靠插值或持续外推误差照样存在。3.3 实时控制层策略实时层的时间尺度是1秒到5分钟主要应对随机波动。此时火电爬坡来不及可调负荷响应也慢最合适的就是储能。常见策略是AGC自动发电控制分配有两大类跟随调度指令让储能按日前/日内下发的曲线执行偏差部分由火电兜底平抑波动用储能吸收新能源高频波动使联络线功率波动率降到规定范围。在Matlab仿真中我会模拟一个“波动功率源”P_fluc实时目标就是让储能出力P_ess实时跟踪P_fluc同时约束SOC在安全范围内。该层不求解复杂优化直接用比例-积分PI控制或简单的功率分配逻辑即可。实时层与日内层的衔接需要小心日内层分配的储能功率是为未来4小时计划服务的实时层如果完全不管日内计划可能把SOC耗尽。所以我通常给实时层加一个“SOC反馈修正”当SOC偏离计划值较大时逐渐减小实时跟踪增益优先恢复SOC到计划轨迹附近。3.4 源储荷协调的关键耦合关系“源储荷”不是三个独立模型放一起而是通过功率平衡和共享调节容量耦合成一个整体。源侧的火电提供基荷和爬坡风光提供电量但不可控储能的响应速度快但容量有限适合处理净负荷负荷扣除新能源的波动而非持续电量负荷侧的可调负荷如空调、电动汽车、电解铝可以参与削峰填谷但其响应有延迟和舒适度约束。耦合关系可以用“净负荷曲线”串起来P_net,t P_load,t - P_wind,t - P_pv,t。调度任务变为让火电储能可调负荷去平衡P_net。其中储能主要负责净负荷的高频分量火电负责中低频分量可调负荷在峰谷时段提供平移能力。在模型中负荷响应可以用可转移负荷或可削减负荷表示。比如假设有5%的负荷可削减则每个时段允许削减量上限为0.05*P_load,t削减成本每MWh设为C_DR。这样储能和负荷响应可以同台竞争“谁更便宜地平衡系统”。4. Matlab代码实现与核心函数解析4.1 代码整体架构与文件规划写调度代码最怕一上来就堆脚本。我的习惯是分文件夹逻辑清晰├── main.m % 主程序控制整体流程 ├── data/ │ ├── load_data.m % 生成负荷数据 │ ├── renewable_data.m % 生成风电/光伏出力曲线 │ └── storage_param.m % 储能特性分布参数生成 ├── model/ │ ├── build_dayahead.m % 日前优化模型 │ ├── build_intraday.m % 日内滚动模型 │ └── storage_model.m % 储能聚合与功率分配函数 ├── solve/ │ └── call_solver.m % 统一调用YalmipCplex/Gurobi └── plot/ └── plot_results.m % 结果可视化这样分工的好处是换数据不用改模型换模型不用动主流程调试定位快。主程序大致流程% 初始化 [load_curve, wind_curve, pv_curve] prepare_forecast_data(); [P_max, E_rated, SOH, SOC_init] storage_param(); % 日前调度 dayahead_schedule build_dayahead(load_curve, wind_curve, pv_curve, storage); % 日内滚动 for hour 1:24 updated_forecast update_forecast(hour); intraday_schedule build_intraday(dayahead_schedule, updated_forecast, storage); execute_first_interval(intraday_schedule); end % 实时平抑 real_time_simulate(SOC_trace, fluc); % 绘图 plot_results();4.2 核心代码段特性分布储能模型我先写一个storage_model.m它把20个簇聚合成一个“虚拟储能”但保留内部差异然后在优化模型中把每簇功率作为决策变量或者把聚合功率再分配到各簇。简单起见我的日前模型使用聚合功率决策变量约束里再根据特性分布计算聚合上下限% 聚合可用充放电功率范围 P_charge_max_agg sum(min(P_max_charge_i, (SOC_i_max - SOC_i) .* E_i ./ (dt * (1/eta_c)))); P_discharge_max_agg sum(min(P_max_discharge_i, (SOC_i - SOC_i_min) .* E_i .* eta_d ./ dt)); % SOC动态聚合更新权重为可用容量 SOC_agg_t sum(SOC_i .* E_avail_i) / sum(E_avail_i); delta_soc (eta_c * P_charge * dt / sum(E_avail_i)) - (P_discharge * dt / (eta_d * sum(E_avail_i)));这里的关键是P_charge_max_agg不仅取决于逆变器功率等级P_max_i还取决于当前SOC_i到上限之间还能充多少能量若时间步长为Δt则充电功率上限为(SOC_i_max - SOC_i)*E_i / (Δt * η_c)的折算值。很多人写模型时只写P ≤ P_max忘了SOC能量约束结果解出来SOC越界还浑然不知。4.3 优化模型构建Yalmip Cplex/GurobiYalmip是Matlab下的建模工具箱它让约束和目标的写法非常接近数学表达式。以日前调度为例P_g sdpvar(n_gen, T, full); % 火电出力 u_g binvar(n_gen, T); % 启停状态 P_ess_c sdpvar(1, T, full); % 储能充电 P_ess_d sdpvar(1, T, full); % 储能放电 SOC sdpvar(n_cluster, T1, full); % 每簇SOC Constraints []; % 功率平衡 Constraints [Constraints, sum(P_g) P_wind P_pv sum(P_ess_d) P_load sum(P_ess_c)]; % 储能充放电互斥 Constraints [Constraints, P_ess_c 0, P_ess_d 0]; Constraints [Constraints, P_ess_c u_ess * P_charge_max_agg]; Constraints [Constraints, P_ess_d (1-u_ess) * P_discharge_max_agg]; % 每簇SOC动态 for i 1:n_cluster Constraints [Constraints, SOC(i,t1) SOC(i,t) ... ]; end设置目标函数后用optimize(Constraints, objective, sdpsettings(solver,cplex))直接求解。如果安装了Cplex但Yalmip报错常见原因是Yalmip版本太老不识别新的Cplex接口。建议Yalmip升级到最新GitHub版本同时保证Cplex的Matlab接口路径已加入Matlab搜索路径。4.4 仿真场景与参数设置案例我拿一个改造后的IEEE 30节点系统做测试当然也可以简化成单母线系统。火电3台参数如下机组容量(MW)a(元/MWh²)b(元/MWh)c(元/h)爬坡(MW/h)G12000.0250100080G21500.036080060G31000.047060040风电场额定功率100MW光伏电站50MW负荷峰值300MW。储能电站100MW/200MWh20簇SOH在0.85~0.95间均匀分布SOC初始值为均值0.5、方差0.1的正态分布截断。设置三个对比场景场景A不考虑特性分布把储能当作一个理想等效电池SOC均值为0.5容量200MWh功率100MW场景B考虑特性分布但日前调度只用聚合SOC不细分到簇场景C完整考虑特性分布日前和日内都使用离散单元模型。对比指标系统总运行成本、弃风弃光率、储能各簇SOC标准差均衡度。结果会显示场景C虽然求解规模大一些但各簇SOC标准差显著降低系统成本略优于场景B远优于场景A。5. 仿真结果分析与效果验证5.1 三类场景下的调度曲线对比先把典型日负荷和新能源曲线给定跑完三种场景后我习惯把以下曲线叠在一起看净负荷曲线原始与调度后火电总出力储能充放电功率弃风弃光功率自适应SOC变化。场景A的储能曲线往往“很漂亮”——功率平滑、SOC像一条正弦曲线。但拉到单簇层面看某些簇SOC已经越界因为等效模型没有细粒度约束。场景C则会看到储能在某些时段“主动限功率”不追求整体SOC的完美光滑而是为了让每簇都在安全范围。这个差异从宏观指标上更明显场景A中SOC标准差随时间会扩大到24小时结束时可能达到0.2以上场景C因为初始约束和动态分配比较合理标准差维持在0.05以内。5.2 关键评价指标的计算与解读指标1削峰填谷率。定义为原始峰谷差 - 调度后峰谷差/ 原始峰谷差。我的仿真结果大约是场景A 28.5%场景B 30.1%场景C 30.6%。看起来提升不大但场景A的“30%”是靠部分电池簇过放换来的不可持续。指标2弃风弃光率。场景A为8.2%场景B为7.5%场景C为7.3%。风光资源充足时段储能如果能及时充电就能降低弃电。考虑特性分布后储能可用容量估算更准充电功率上限更贴近实际弃电率自然更低。指标3总运行成本。场景A约85.2万元/天场景B约84.7万元/天场景C约84.5万元/天。特性分布引起的成本差异看似只有0.5%但这是在一个典型日里如果连续模拟一个月差异会放大。更重要的是场景C能显著减少电池过充过放延长寿命这部分收益远大于调度成本的节省。指标4SOC均衡度。场景C最终各簇SOC标准差为0.045场景A为0.18。这非常关键——调度策略好不好别只看经济指标要看它是否“善待”电池。5.3 结果可视化呈现技巧在Matlab里画图时我建议用三张图总结第一张负荷-出力平衡堆叠图展示火电、风电、光伏、储能、负荷的时序关系第二张储能各簇SOC热力图横轴时间纵轴簇编号颜色表示SOC这种图一眼就能看出哪些簇被“折磨”得比较惨第三张弃风弃光和成本柱状图对比。热力图用imagesc(SOC_matrix)加colorbar就能画非常简单但效果极佳。论文写作或报告汇报时这张热力图比一堆数字有说服力得多。6. 常见问题与调试经验6.1 求解器配置与收敛性踩坑Yalmip调用Cplex时最容易遇到两个问题问题一Yalmip找不到Cplex。报错Could not locate CPLEX...。解决安装Cplex后在Matlab中运行cd(CPLEX_PATH)执行addpath(genpath(pwd))保存路径。再去Yalmip/adapters中检查是否有cplex适配文件。问题二MILP求解太慢。20个簇、24时段、每簇SOC连续变量其实还算小规模几分钟能解。但如果把日内滚动也纳入96个15分钟时段加20个簇变量数暴涨求解器可能陷入长时间分支定界。我的经验是尽量使用聚合模型求日前再在日内用启发式分配各簇功率对连续SOC分段线性化减少二进制变量设置求解时间上限sdpsettings(solver,cplex,cplex.timelimit,120)超时取当前最优可行解。6.2 特性分布参数敏感性分析特性分布的方差大小直接影响调度结果。我做过一个敏感性测试σ_soc从0.05增到0.15时如果模型不考虑特性分布即假设所有簇SOC相同且等于均值那么实际运行中SOC越界程度明显增大而考虑特性分布的模型能自动调整聚合功率上限SOC越界概率基本不变。这个测试说明一个道理特性分布方差不大的时候“等效电池”模型还能凑合但方差一大必须显式建模。所以写论文时建议做一组“σ_soc敏感性”图证明自己的方法在什么边界条件下优于传统方法。另外SOH方差的影响更隐蔽。SOH低的簇不仅容量小内阻也可能变大充放电效率下降。如果模型不考虑SOH差异调度时会对这些老化的簇下达过高的功率指令导致发热加剧寿命进一步缩短。在代码里我建议至少要区分SOC与SOH两个维度。6.3 代码实现里容易忽视的细节SOC更新要用实际可用容量E_avail_i E_rated_i * SOH_i而不是额定容量。很多人直接用E_rated导致SOC变化被低估长时间仿真误差积累不可接受充放电效率不对称充电是电→化学放电是化学→电效率不同SOC更新公式中的η位置容易写反。正确写法是充电时SOC增加还要打η_c折扣放电时SOC减少需要除以η_d特性分布图要可视化我强烈建议在数据初始化后先画SOC/SOH散点分布图确认分布范围合理再往下跑。别急着搭建优化模型数据有问题后面全白搭矩阵维度不一致用sdpvar定义变量时注意矩阵是(T,1)还是(1,T)Yalmip对行列向量的约束容易让人抓狂。建议统一用 column vectorsdpvar(n, T)每个变量都是n×T矩阵实际上sdpvar(n,T)就是n行T列。循环索引时确保维度一致。我个人在实际操作中吃过大亏的是“忽略SOH对容量的影响”。有一次我仿真一个大型储能电站连续运行365天结果到第200天左右系统直接无解排查了很久才发现老化的簇实际容量已经降到初始的70%但模型里还是按初始容量计算SOC导致虚拟SOC还在安全范围实际SOC可能已经变成负数或超过1.2。加上SOH更新后系统才稳定运行。“考虑特性分布”并不是把模型做得复杂而是把现实里本来就存在的不均匀性如实刻画。对做研究的人来说这是让调度策略具备工程价值的关键一步对做工程的人而言这能让储能真正安全地“听话”。6.4 后续扩展方向这个模型还可以往三个方向扩展。第一个是加入温度特性不同位置电池簇温度差异会影响损耗和寿命可以在目标函数中增加温度惩罚项。第二个是加入寿命衰减模型把每个簇的循环深度折算成寿命损耗成本让调度策略主动避免深度充放。第三个是引入分布鲁棒优化用历史数据构造SOC分布的不确定性集合代替固定分布提高策略对不同运行工况的适应性。如果只求复现我建议先跑通单母线、20簇、日前日内两层的简化版本再逐步加实时层和热力图。代码量不算大核心模型就几百行但能承载的研究点非常多。最后再分享一个小技巧如果你不想让储能电站里那20条SOC曲线在图上乱成一团可以在绘图时用plot(SOC,LineWidth,1.2)加上透明度或者直接画均值加减一倍的包络带。这种图既能展示分布又不至于太乱审稿人和领导看着都舒服。
返回列表