恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
虚拟电厂多时间尺度调度:储能成本衰减建模与Matlab实现
首页
资讯中心
/
虚拟电厂多时间尺度调度:储能成本衰减建模与Matlab实现
虚拟电厂多时间尺度调度:储能成本衰减建模与Matlab实现
发布时间:2026/10/11 9:07:30
一个高比例可再生能源的并网方案如果只报一个“总成本最低”往往经不起细问这个最低是不是把储能当成了永远不会衰老的玻璃罐灵活性到底从哪条通道兑现储能的折旧是否被认真折进了账里不同时间尺度之间的调度计划又是怎么衔接上的。这篇我准备用虚拟电厂多时间尺度调度做主线把高比例可再生能源并网下的灵活性需求、储能成本、衰减建模和Matlab实现串起来讲清楚。内容相当于一次对某顶级SCI论文框架的复现笔记——不会只停留在公式表面而是会写出我在代码层面踩过的坑、怎么设计目标函数、怎么把储能寿命损耗折算进去最后给出一个可以直接改用的Matlab模型骨架。适合正在做电力系统调度、储能优化配置、虚拟电厂聚合控制这类课题的同行也适合想搞懂“多时间尺度调度到底比单层多算了什么”的入门研究者。1. 用一张净负荷曲线看清“灵活性”从哪来、钱从哪花1.1 净负荷的“峰谷差”和“爬坡率”才是真正的压力源做高比例可再生能源并网研究的人第一件事就是把常规负荷和新能源出力叠加得到净负荷曲线。净负荷才是电网里所有常规电源、储能和柔性负荷需要共同平衡的对象。光伏占比上来以后净负荷曲线会变得非常不讲道理中午光伏大发净负荷被压得很低傍晚光伏退坡负荷却进入晚高峰两个作用叠加导致净负荷在短短两三个小时内急速拉升。这个急速拉升就是系统对向上爬坡能力的需求。我见过一些实际算例光伏渗透率达到40%以上时净负荷的最大爬坡率可以达到每分钟几十兆瓦甚至上百兆瓦远远超过传统火电机组的爬坡能力上限。很多研究只盯着“电量平衡”把一天的总发电量和总负荷对上就以为万事大吉。但调度问题本质上是一个“功率是否随时平衡”的问题电量的守恒是积分层面的功率的平衡是每个瞬时都要满足的缺了爬坡速率、最小技术出力、启停时间这些时间耦合约束算出来的方案在物理上根本执行不了。1.2 灵活性需求要“货币化”不然无法和储能成本放在一个天平上为什么标题把“灵活性”和“储能成本”并列因为当净负荷波动变大时系统可以选多条路去应对让火电频繁爬坡、让部分负荷平移、让储能充放电。但每条路都有代价。灵活性来源响应速度主要成本结构规模化潜力火电调峰分钟级到小时级煤耗增加、磨损、启停成本受最小出力限制需求响应分钟级用户补偿费用、舒适度损失依赖负荷类型储能充放电秒级到分钟级设备投资、充放电损耗、循环老化受容量和功率限制问题在于传统火电由于爬坡慢往往在净负荷陡升时段“顶不上”需求响应如果被过度调用用户侧会开始反弹储能虽然响应快却有一笔常被忽略的隐形成本——每一次充放电循环都在折损电池寿命。如果优化目标里没有这笔寿命损耗调度器会倾向于把储能当作“免费橡皮泥”让它在一天内反复深度充放最后算出来的最优方案在设备寿命维度上完全失真。所以“灵活性成本化”的真正含义是把每条灵活性通道的代价都写成可以进目标函数的数值。储能不再是白送的容量它每贡献一度电的调节能力就对应一个衰减成本系数。这个系数怎么定后文第4章会展开。2. 虚拟电厂的聚合逻辑什么资源能进“池子”怎么变成统一变量2.1 我理解的VPP三层结构虚拟电厂不是一个物理实体而是一个控制与市场代理。它把分散在配电网里的分布式光伏、风电、储能、可调负荷聚合起来对外形成一个“可以调度的大电厂”。我在建模时习惯把它分成三层物理资源层各类DER设备包括屋顶光伏、小型风机、电化学储能站、充电桩、温控负荷等。聚合调节层把分散设备的可调能力汇总成一条虚拟功率曲线对外表现为“VPP可以按指令增减出力”。优化决策层在满足内部资源约束的前提下决定每时刻各资源的出力、充电、放电、削减或者平移使整体运行成本最小。2.2 把每个资源写成统一的数据结构Matlab建模的第一步不是写优化代码而是先把资源抽象成统一的数据结构。我会用一个结构体数组保存所有资源参数例如res(1).type storage; res(1).eNom 10; % 额定容量 MWh res(1).pMaxCh 2; % 充电功率上限 MW res(1).pMaxDis 2; % 放电功率上限 MW res(1).socMin 0.2; res(1).socMax 0.9; res(1).etaCh 0.95; res(1).etaDis 0.95; res(1).socInit 0.5; res(2).type flexLoad; res(2).pBase 1.2; % 基准负荷 MW res(2).deltaMax 0.3; % 可平移比例 p.u. res(2).maxShiftHour 2; % 最多平移时长另一个容易被忽略的点是负荷侧和电源侧都要“行为化”。可调负荷不能只给一个功率上下限还必须给能量约束。比如用户允许空调负荷提前或延后半小时但累计被削减的电量不能超过多少否则温度会飘出舒适区间。这些约束如果漏掉调度结果会“聪明地”把负荷削到离谱水平现实中根本没法落地。2.3 聚合的数学表达聚合后的功率平衡方程可以写成P_grid(t) P_dg(t) P_dis_bat(t) P_load_base(t) P_ch_bat(t) P_flex_cut(t) P_pv_curtail(t)其中P_grid是VPP和外部电网的交换功率P_dg是可控分布式电源出力P_dis_bat和P_ch_bat是储能放电和充电功率P_flex_cut是负荷削减量P_pv_curtail是光伏弃光量。弃光变量看似多余但恰恰是高比例可再生能源场景里最关键的松弛变量。优化模型里如果没有弃光项无解的概率会很高加了弃光项并且给它一个合理的成本系数调度器才会在“弃一点光”和“花大价钱储下来”之间做出真实取舍。3. 三层时间尺度调度日前、日内、实时各算一遍凭什么不重复3.1 为什么不能只做一次长时间尺度的优化如果能完美预知未来24小时的光伏出力、风电出力和负荷曲线那确实只需要求解一个大优化问题。但现实是预测精度随时间尺度变化很大提前24小时的光伏预测误差可能超过20%提前4小时能到5%10%到了实时的分钟级才能压得比较低。多时间尺度调度的本质是用“滚动刷新”去对冲预测误差。粗时间尺度算出长期的资源安排细时间尺度根据最新预测去校准短期的功率分配。每一层不是重复劳动而是分工不同日前层决定“大致怎么安排”以小时级为间隔。日内层修正“偏差怎么补”以15分钟或5分钟为间隔。实时层处理“分钟级波动”依靠储能的快速调节兜底。3.2 日前调度的目标函数和约束日前调度是一个线性或混合整数线性规划。我常用的目标函数是min Σ [ c_grid(t) * P_grid(t) c_fuel * P_dg(t) c_deg * (P_ch P_dis)*Δt λ_forecast * |P_forecast偏差| ]约束至少包含功率平衡方程储能SoC动态方程 SoC(t) SoC(t-1) η_ch * P_ch(t) * Δt / E_nom - P_dis(t) * Δt / (η_dis * E_nom)充放电功率上限约束SoC上下限约束火电爬坡约束备用容量约束联络线交换功率约束。这里有一个容易出错的细节目标函数中必须给“不平衡电量”一个惩罚价格。日前预测有误差是必然的如果模型不允许任何偏差往往只能得到无解的结论。惩罚价格的量级也需要动脑子它要比正常电价高一些但不要高到离谱否则日内层完全不敢调整丧失了滚动调度的意义。3.3 日内滚动调度把日前计划当成软约束日内层用的是模型预测控制MPC的思路在当前时刻k基于最新预测的从k到kH的净负荷曲线重新优化未来H个时段但只执行第一时段的结果执行后到下一个时刻再滚动一次。日内层最关键的技巧是怎么把日前计划“嫁接”进来。我说的不是硬性锁定日前值而是把日内出力和日前计划的偏差写成惩罚项min Σ [ c_punish * | P_rt(t) - P_da(t) | ... ]这样日内层既能跟随日前计划避免给外部电网带来意外冲击又能根据最新预测适度调整储能出力和弃光量。3.4 实时层不需要再优化一遍大模型实时层如果还去解一个有大整数变量的混合整数规划时间上来不及。实践中我会把实时问题简化为二次规划或单纯形在日前和日内已经给出的基准功率上只优化储能和联络线的微小修正量。此时风电和光伏出力已经基本确定修正量范围很小求解速度快得多。三层之间的信息传递链条是这样日前层把储能SoC计划轨迹和机组启停计划传给日内层日内层把下一时段的储能基点功率传给实时层实时层只负责偏移量修正。我在实际程序里用一个结构体变量trackPlan依次存放各层结果方便后续检查各层之间到底有没有跑偏。4. 储能衰减建模把“寿命损耗”折成真金白银调度结果才敢信4.1 不建模衰减的典型翻车现场我最早做储能调度时目标函数里只有购电成本、卖电收益和火电煤耗成本。结果是储能被调度器物尽其用地“往死里用”中午光伏大发时满功率充电傍晚高电价时满功率放电一天下来SoC像锯齿一样来回满幅震荡。表面看这个方案让系统购电成本最低但它是建立在电池寿命无限、容量永不衰减的假设上的。现实里锂电池在这么激进的充放策略下容量会快速衰减。用五年维度去看这个“最优”方案需要提前更换电池总成本反而比温和调度更高。4.2 衰减成本的折算方式严谨的电池寿命模型要考虑循环次数、放电深度、SoC工作区间、温度、倍率等但调度模型里不可能完整嵌入电化学模型。工程上常用的是等效循环折算和能量吞吐折算。能量吞吐折算的思路最简单假设电池在其整个生命周期内可以累计吞吐某个总能量E_total单位吞吐能量的衰减成本就是c_deg C_replace / E_total如果知道一个2 MW / 4 MWh的电池系统投资替换成本约为400万元生命周期内可吞吐约3000 MWh那c_deg大约是1333元/MWh也就是每充放1 MWh电量折损0.13万元左右。把它乘以充放电功率和时长就得到了调度目标函数里的衰减惩罚项。还有一种更精细的做法是按放电深度非线性折算放电深度越深等效循环寿命衰减得越快。调度模型里为了线性化可以分段逼近放电深度和循环寿命的关系但这会让模型规模明显变大。我的建议是先用线性吞吐模型跑通框架如果后期需要论证“更换电池周期”对结果的影响再在仿真后处理阶段做详细寿命评估而不是一上来就把模型搞成非线性。4.3 衰减成本写进优化模型后会改变什么行为在目标函数里加上c_deg之后经验结果是储能一天内的等效循环次数明显下降SoC曲线不再是满幅震荡而是保持在比较温和的区间内小幅波动。系统会倾向于用火电爬坡、负荷调节来承担一部分波动储能只扛那些最尖锐的峰谷。这才是真实世界里最经济的运行方式。除此之外衰减模型还有效改变了“是否弃光”的决策。如果光伏大发时段电价极低储能的充电收益可能弥补不了电池衰减损失那么最优决策就是弃掉一部分光。这个结论在没有衰减成本时永远得不出来因为不加衰减成本的话储能充电仿佛是免费的。5. Matlab落地细节目标函数、约束写法与求解器选择5.1 整体程序框架Matlab代码的搭建我会分成四个部分loadInput.m载入负荷数据、风光预测数据、储能参数、分时电价。buildDayAhead.m构造日前优化问题包括目标函数系数和约束矩阵。buildIntraday.m构造日内滚动优化问题按预测更新频率反复调用。plotResult.m汇总各层结果绘制出力曲线和SoC曲线。值得多花一点时间构思的是输入数据结构。多时间尺度模型涉及的数据量不小如果输入数据格式不统一调试时会非常痛苦。我会把负荷和新能源预测都组织成表格列名分别为time、load、pv、wind日内预测则存成多行滚动样本每一行代表一个预测更新时间。5.2 核心Matlab代码片段以日前调度为例使用Optimization Toolbox的优化变量类写起来很直观n 24; dt 1; % 每小时一个时段 P_ch optimvar(P_ch, n, LowerBound, 0, UpperBound, 2); P_dis optimvar(P_dis, n, LowerBound, 0, UpperBound, 2); P_grid optimvar(P_grid, n, LowerBound, -5, UpperBound, 5); SOC optimvar(SOC, n1, LowerBound, 0.2, UpperBound, 0.9); u_ch optimvar(u_ch, n, Type, integer, LowerBound, 0, UpperBound, 1); u_dis optimvar(u_dis, n, Type, integer, LowerBound, 0, UpperBound, 1); prob optimproblem; prob.Objective sum(price .* P_grid * dt) sum(c_fuel * P_dg) ... sum(c_deg * (P_ch P_dis) * dt); prob.Constraints.balance P_grid P_dis P_dg Load - pv - wind P_ch; prob.Constraints.SOC_init SOC(1) 0.5; prob.Constraints.SOC_end SOC(end) 0.5; prob.Constraints.SOC_update SOC(2:end) SOC(1:end-1) ... (eta_ch * P_ch - P_dis / eta_dis) * dt / E_nom; prob.Constraints.ch_disch u_ch u_dis 1; prob.Constraints.ch_link P_ch 2 * u_ch; prob.Constraints.dis_link P_dis 2 * u_dis; options optimoptions(intlinprog, Display, off); [sol, fval] solve(prob, Options, options);这段代码有几个值得注意的点引入u_ch和u_dis两个0-1变量是为了避免储能同时充电和放电。这在纯线性规划里是必要的大M法处理如果不加互斥约束优化器可能同时置P_ch和P_dis为正白白产生损耗还解释不通物理含义。SoC末值约束要视场景决定。如果日内还要滚动优化通常不强约束末值等于初值而是给一个末端惩罚项让SoC在合理范围内自然游走。强约束每天回到0.5会削弱储能在跨日电量调节中的作用。功率和容量的单位一致性问题。常有人把MWh和MW搞混导致SoC更新公式算出来的数值离谱。我习惯统一用MW和MWh时间步长是小时这样能量公式最简洁。5.3 求解器选择与效率经验如果模型只有连续变量用linprog就够了。加上机组启停、充放互斥这些0-1变量后就是混合整数线性规划Matlab自带的intlinprog可以处理中小规模问题。一个24时段、50个储能节点、20条联络线的模型intlinprog通常几秒到几十秒能解完。但到了日内滚动层每一轮都要重新解一个优化问题实时性要求高我会做两个简化一是把日前层已经确定的机组组合固定下来不再让日内层重复决定启停二是把储能充放的互斥约束通过目标函数系数设计来变相规避。比如充电成本本来就高于放电收益时优化器天然不会同时充放此时可以不引入0-1变量把问题退化成纯线性规划单次求解速度可以控制在毫秒级。如果追求更高的求解性能建议用YALMIP或CVX接线性的Gurobi求解器。Matlab内置的intlinprog在大型问题上偶尔会有数值稳定性问题尤其是在约束矩阵条件数较大时。遇到“求解器报无界或者不可行”时先查约束矩阵的稀疏表示再查SoC更新公式的数据单位和系数这两个是最常见的原因。6. 跑完以后怎么看结果以及我调出的三个典型坑6.1 复现阶段的结果判读模型跑通以后不能只看总费用一个数我习惯设置三个检查指标第一是爬坡满足率即在每个时段系统的可调容量是否都能应对净负荷最大爬坡第二是储能SoC轨迹的合理度是否频繁到达上下限是否长时间保持在0.5附近一动不动第三是各时间尺度计划的一致性日内层实际执行结果和日前计划的偏差是否控制在一个合理带宽内。我复现这篇SCI论文时把三组不同渗透率下的仿真做对比得到最直观的现象是当光伏渗透率从20%升到50%时如果没有衰减成本储能的等效循环次数从每天2.5次暴涨到5.8次弃光率却只下降很少计入衰减成本后循环次数回落到2.1次弃光率反而上升了几个百分点但系统十年总成本显著下降。这个结果说明衰减成本在高级别渗透率下是改变“储能充多少”“什么时候充”的关键因素而不是修修补补的小参数。6.2 坑一SoC在层间跳变原因是跨层约束没接好我在第一次写多时间尺度程序时日前层和日内层是分开优化、分开求解的然后直接把日前层最后一个SoC值作为日内层的初始值。结果发现某些时段日内层优化的SoC轨迹和日前层规划的SoC轨迹出现明显脱节原因是我没有给P_ch和P_dis在日前/日内之间加偏差惩罚日内层为了应对最新的光伏波动把储能调度方向整体反转了。修正方法是在日内目标函数里加入相对日前计划的功率偏差惩罚项并且把日前算出的SoC轨迹作为参考轨迹写入日内层的SoC软约束。软约束用二次罚函数表达既允许日内层根据新信息微调又避免它彻底推翻日前安排。6.3 坑二末端SoC强制约束导致日前无解另一个常踩的坑是强约束SoC每天必须回到初值。如果哪天晚峰负荷特别高储能不得不在傍晚深度放电但第二天中午光伏预测又偏低那么为了让SoC回到0.5模型必须安排其他电源在早晨多发电甚至可能出现联络线功率超过上限的问题。这时整个日前模型直接判为不可行。后来我把“SoC末端等于初值”改成了“SoC末端不小于某个下限再加末端价值函数”相当于给储能留了跨日调节的余地。虽然模型允许SoC在一天结束时不在0.5但通过给末端SoC加一个影子价格调度器会自行权衡是当天多留一点电量还是次日多充一点更划算。6.4 坑三衰减成本系数不合理储能角色突然消失调试时如果把衰减成本系数定得过高储能会被优化器“一刀切”闲置。这时候储能虽然不花钱了但灵活性也归零净负荷爬坡只能靠火电硬扛火电的煤耗和爬坡压力反而上升总成本不降反升。这说明衰减成本的取值不能拍脑袋最好从电池厂商的循环寿命曲线反推。比如厂商说某款电池在80%放电深度下有6000次循环寿命容量为4MWh那总吞吐量基本是4MWh6000次2充加放*0.8再代入替换成本就得到一个在数据上有依据的c_deg。取值后最好在仿真里做敏感性分析看体量级变化对储能利用率的影响而不是只定一个固定值。如果不想把衰减写得太细可以在模型外做一个两层迭代先用粗略的c_deg跑一遍调度统计某个月的实际等效循环次数再根据循环次数更新c_deg重新优化直到前后两层结果收敛。这样既保持了调度模型的可解性又照顾到了储能寿命和运行策略之间的耦合关系。这套模型我已经复现过几次每一次都会在产品入网条件、储能初始配置、预测误差分布上再做局部调整。就我个人实操的体会来说多时间尺度调度的价值不在于把优化模型写得多么花哨而在于让每一层调度都知道自己该忽略什么、该盯紧什么——日前层盯长期经济性日内层盯预测偏差实时层盯瞬时平衡。把储能衰减成本放进去以后里层的决策会变得克制很多而恰恰是那份克制才是高比例可再生能源系统真正需要的工程判断。