
做新能源调度绕不开一个尴尬的现象独立看风电、光伏的预测曲线都还行但把它们放进同一个系统里要么白天光伏功率顶着天、晚上风机疯转负荷侧却跟不上要么连续几天阴雨无风电池耗尽整个微网只能靠外购电硬顶。这几年我一直在做风光储互补调度的工程仿真项目的核心是“储能”而且不是单一的电池储能是电池和废弃矿井小型抽水蓄能搭在一起的多元储能。这套东西真正难的不是单独建模某个电源而是如何在Matlab里把风、光、电池、抽蓄、负荷、并网功率全都耦合到一起跑出一个让各个单元都不越限、还能把弃电率和失负荷率压到最低的调度方案。今天这篇就围绕“风电、光伏与储能含电池和废弃矿井小型抽水蓄能互补调度运行研究”展开完整讲一遍我个人的建模思路、调度目标设计、Matlab代码实现框架以及实际跑仿真时踩过的坑。内容对电力系统方向的研究生、做微电网调度算法的工程师、新能源消纳方向的从业者都有参考价值。我会把关键的数学约束和代码结构都拆开讲尽量让有Matlab基础但没做过调度优化的人也能照着落地。1. 整体设计思路为什么要做多元储能互补1.1 电池和抽水蓄能压根不是同一类“储能”很多人一提储能就习惯性只想到锂电池但这个项目的核心恰恰是把两种完全不同的储能形态放在一个调度框架里。电池的本质是能量型功率型兼顾响应速度快毫秒级就能完成功率调节但它的短板是容量受制于电芯数量和成本连续几小时大功率放电就会触及SOC上下限而且循环次数是宝贵的频繁深充深放会让寿命衰减非常快。废弃矿井小型抽水蓄能则是典型的能量型储能。利用矿井巷道、采空区或竖井改造出的上、下水库通过水泵把水打到高处蓄能需要时放水发电。它的能量容量取决于水库容积和水头落差规模可以做得比电池大循环寿命几乎不受充放电次数限制但是响应速度天然就慢水泵启动、水轮机导叶调节都需要时间而且整个机组的运行效率受水头波动影响很大。这两种储能在调度里的角色完全不同。电池负责快速响应、平抑短时波动承担负荷突变和风光短时预测误差抽水蓄能负责能量搬移把午间光伏大发时段的电量挪到晚高峰或者在连续无风无光时段作为后备容量。调度模型如果不区分这两者的动态响应差异把它们都当成一个简单的“能量罐子”来建模那结果只能勉强用于理论演示没法落到工程实践。1.2 互补调度的本质是“缺口管理”风光互补调度这个词看起来高大上本质其实就是一句话在每一个调度时段里让系统内的所有电源和储能共同去满足负荷同时把成本或弃电损失压到最低。风光的“互补”体现在时间尺度和气象尺度上——白天光伏强、夜间风电可能更强晴天风电弱、阴雨风电反而可能飙起来。这些天然特性让风光联合出力比单一电源更平滑但还远远不够可靠。加入储能之后调度就成了一个带约束的多时段优化问题。你要决定每个时段电池是充电还是放电、充放多少功率抽蓄是抽水还是发电、要不要停机从电网买电还是卖电光照不足时是切负荷还是调用储能。这一系列决策互相牵制比如抽蓄在用电高峰放水发电就意味着它必须在此前的某个低谷时段把水抽上去而抽水的电量可能来自光伏也可能来自电网。这种跨时段的耦合关系决定了调度模型不能只做单时段的功率平衡。就我个人的工程经验来说做这种多元储能互补调度第一步永远是画能量流图而不是急着写代码。把风电场、光伏阵列、电池、抽蓄上水库、下水库、负荷、并网点全都画出来标清楚每个单元之间的功率流向和效率关系然后再把这张物理图翻译成数学约束。物理关系理不顺后面写多少代码都是在原地打转。1.3 为什么选择Matlab作为实现平台这个项目选择Matlab原因很直接Matlab自带的Optimization Toolbox对线性规划、整数规划、非线性规划都有成熟求解器而基于问题problem-based的建模方式让我可以把优化目标、约束条件按数学思路直接写出来不用自己手写拉格朗日对偶或内点法。另一个好处是风电光伏的时序数据我用Matlab做预处理非常顺手比如风速到功率的转换、光伏组件的倾角修正、异常数据清洗一套流程下来数据、模型、求解、绘图全在同一个环境里闭环。对于想进一步做强化学习调度比如用DQN或PPO做数据驱动策略的同学Matlab环境同样能衔接。但前提是你得先把物理模型和状态转移方程写清楚否则训练出来的智能体连基本的功率平衡都学不会。2. 系统建模与核心参数设置2.1 风电出力模型风电的建模可以深也可以浅做调度研究没必要把叶素动量理论搬进优化里那属于气动设计层面的事。调度模型中更常用的是风速-功率转换曲线法。用实测风速序列加上风机的功率曲线就能得到风电场并网点功率。单台风机功率输出的经典分段函数可以写成当风速低于切入风速时出力为0当风速在切入风速和额定风速之间时出力近似随风速的三次方增大当风速在额定风速和切出风速之间时出力保持在额定功率当风速超过切出风速风机停机避风出力为0。Matlab里可以用interp1对厂家提供的功率曲线做插值也可以用式(1)的三次方拟合。实际操作时我建议不要直接用单一风速值乘风机台数算整个风电场功率因为尾流效应会让下游风机风速偏低。更稳的做法是给不同机组的风速引入一个0.9~1.1的扰动系数模拟速度损失这样风电出力曲线不会过于“平滑”调度模型面对的输出波动更接近真实。2.2 光伏出力模型光伏建模的核心物理量有三个水平面辐照度、组件倾斜面辐照度、组件温度。调度研究通常拿不到专用的辐照度预报多数情况下用的是历史气象站的水平辐照度然后通过Hay模型或Liu-Jordan模型转成倾斜面辐照度。不过这一步对于微网调度来说属于锦上添花如果你手上没有倾斜面辐照度数据直接用水平辐照度乘一个经验系数一般取1.05~1.15也可以接受关键是把“辐照度→直流功率→交流功率”这条链的效率和损耗算清楚。光伏阵列的直流输出可以简化为P_pv 额定容量 × 辐照度/标准辐照度 × [1 温度系数 × (组件温度 - 25)]组件温度可以用环境温度和辐照度的经验公式估算。模型里要再乘逆变器效率和无功控制系数才能得到交流并网功率。我见过不少同学在调度模型里直接把光伏功率当常量输入这样做其实也没错因为调度是“基于预测”的光伏预测出力本来就是一个时序数列。但要注意预测数据和实际数据之间必然有误差完整的研究应该在调度方案生成后做误差敏感性分析看看方案在光伏低估或高估30%的情况下是否依然可行。2.3 电池储能模型电池储能建模的核心是SOC的时序递推关系。离散化后每个时段k的SOC等于上一时段SOC加上充放电导致的SOC变化。需要注意两点一是充放电效率不一样充电时交流侧到直流侧的变换损耗更大放电时直流到交流的逆变效率也不到1所以模型里充电和放电要用不同的效率系数二是SOC不能简单用功率积分除以容量了事还要考虑电池的自放电率虽然锂离子电池自放电率很低但如果你把调度周期拉到几天甚至几个月自放电项就得加进去。为了延长电池寿命优化模型里还必须加两个约束SOC运行上下限以及充放电功率上下限。工程上锂离子电池SOC通常控制在0.2~0.9之间充放电倍率限制在0.5C~1C。单位调度时段内的功率变化率也要限制否则求解器会给出一个功率从-0.5MW瞬间跳到0.5MW的疯狂方案物理上根本无法执行。这里有一个我觉得很关键的小技巧电池的充放电状态不要直接用连续变量P_b的正负来表达最好引入一个0/1状态的整数变量u_b并配合大M约束来分离充电功率和放电功率。这样虽然把模型变成了混合整数问题但好处是国内绝大多数毕业设计或项目评审都会要求看到“电池禁止同时充电和放电”这个约束连续变量模型表达不了这种互斥逻辑而整数变量可以。2.4 废弃矿井小型抽水蓄能模型这部分是整个项目的特色也是很多论文里写得最含糊的地方。我先说一个最核心的物理概念抽水蓄能的可调度能量取决于当前上下水库的水位差和可用水量这个状态量叫做水量SOC它和电池SOC最大的不同在于——它同时受能量守恒和水力学约束的控制。小型抽水蓄能建模时上水库库存量的递推关系包含三个部分天然来水量废弃矿井往往有矿井水涌出这可以作为一个恒定的小流量输入、抽水注入量、发电放水量。如果矿井水涌出量不稳定可以简化为一个随机扰动项或用历史均值代替。下水库同样重要。下水库容量决定了一次抽水循环能储存多少水量而废弃矿井的下水库往往就是采空区积水空间容积有限且不可随意扩容。建模时要给上水库和下水库分别加水量上下限约束而且上下水库的水量变化量必须严格相等忽略蒸发渗漏时。功率与流量的关系取决于水头和水轮机、水泵的效率P_phs_gen ρ g Q_t H η_t / 1e6其中Q_t是发电流量H是当前净水头η_t是水轮机发电效率。抽水时消耗的功率是P_phs_pump ρ g Q_p H / η_p / 1e6注意这里的H取的是抽水工况下的扬程而扬程和水头并不完全相同抽水时还要考虑管道损失不过调度模型里可以用固定管道损失系数近似。要特别提醒的是废弃矿井型抽蓄的水头不是恒定值。上水库水位下降时净水头减小发电功率会降低水泵抽水时扬程升高抽水功率会增加。严谨的模型应该把水头做成水量的函数在水位上下限之间线性化。如果偷懒用固定水头算下来的可发电量可能差出10%~20%如果矿井巷道长度大、摩擦损失明显误差会更大。举个例子方便大家理解数量级假设矿井可利用高差是80m有效库容是10000立方米水轮机发电效率0.85那么满库存对应的可发电能量大约是E 1000 × 9.81 × 10000 × 80 × 0.85 / 3.6e6 ≈ 1852 kWh你没看错这个能量只有1.8MWh左右和一块大型工商业储能电池差不多。所以对“小型”这两个字要有清醒认识它解决的是微网里的能量搬移问题而不是大电网的调峰问题。也正因为能量有限调度模型中才需要精打细算每一滴水都得放在刀刃上。2.5 负荷与并网交互微网负荷曲线通常用典型日负荷数据可以叠加随机扰动来模拟负荷预测误差。并网交互的建模决定了系统是孤网运行还是并网运行。本项目的调度框架里我采用的是“允许从电网购电和向电网售电”的并网模式这样调度模型有外购电这个兜底手段不至于在风光出力不足时直接无解。并网交互需要设置联络线功率上限、购售电价可以是分时电价以及是否允许倒送。这里注意倒送功率往往有政策限制模型里一般会加一个并网点功率上下限约束比如不允许反向送电或者限制倒送不超过某个百分比。3. 调度策略与Matlab代码实现3.1 目标函数设计调度模型的目标函数取决于研究侧重。我自己的版本用的是多目标加权包含四项弃风弃光惩罚、失负荷惩罚、从电网购电成本、储能深度充放损耗惩罚。目标函数写成min F Σ[k_wash * (P_w_available - P_w_dispatch) k_load_shed * P_load_shed k_grid * P_grid_buy k_battery * (P_b_charge P_b_discharge)]举一个具体的权重设置例子弃风弃光每MWh罚10元失负荷每MWh罚500元购电按分时电价电池损耗按充放功率的0.1%折算。这样求解器在权衡“弃掉光伏”和“电池深充”时会倾向于少弃光但当电池逼近SOC上限时又不会硬性让它过充。不同权重设置会得出风格完全不同的调度方案。失负荷惩罚权重越大系统越保守储能会在用电低谷提前充满电以备不时之需弃电惩罚权重越大系统越激进储能充电会更频繁也更容易出现尾时段储能SOC偏低的情况。做对比分析时把这两组权重各跑一遍你就理解什么叫“调度倾向”了。3.2 约束条件清单我在Matlab里实现的约束分成六组功率平衡约束每个时段光伏风电电池放电抽蓄发电购电负荷电池充电抽蓄抽水售电电池SOC递推约束SOC(k1) SOC(k) η_c * P_c * Δt / E_b - P_d * Δt / (E_b * η_d)抽蓄水量递推约束V_up(k1) V_up(k) Q_pump * Δt - Q_turbine * Δt Q_natural * Δt电池充放电互斥约束u_c u_d 1抽蓄抽水/发电互斥约束u_p u_g 1并网联络线功率约束-P_line_max P_grid P_line_max第三组约束里的天然来水项是废弃矿井抽蓄的特色普通抽蓄不需要这个但矿井型如果水文条件好涌水本身就是一种额外能源这部分应该被充分利用。3.3 采用求解器的选择与建模思路对这类混合整数优化问题我个人在Matlab里的首选是optimproblem构建问题再用intlinprog或ga求解。optimproblem的好处是表达方式和数学公式高度一致变量、约束、目标函数一目了然。不过要小心intlinprog要求目标和约束都是线性的。如果你在目标里加入了电池寿命的非线性惩罚函数那就需要做分段线性化或者换用fmincon配SQP算法把整数变量松弛成连续变量做近似求解。一个不太有人提但非常实用的经验不要一上来就上MILP。先跑一个把所有储能都当成连续变量的线性规划版本看能量平衡是否能满足再把整数约束加进去。这样既能验证物理逻辑对不对也能明显缩短调试时间。如果直接上MILP第一次跑出来不可行你根本分不清是模型写错还是整数约束太紧导致的。下面是核心调度模型在Matlab中的定义思路非完整可运行代码重点看建模结构T 96; % 15分钟一个点共24小时 P_w wind_power_forecast; % 风电预测序列 P_pv pv_power_forecast; % 光伏预测序列 P_load load_forecast; % 负荷预测序列 % 决策变量 P_b_d optimvar(P_b_d, T, LowerBound, 0, UpperBound, 0.5); % 电池放电 P_b_c optimvar(P_b_c, T, LowerBound, 0, UpperBound, 0.5); % 电池充电 u_b optimvar(u_b, T, Type, integer, LowerBound, 0, UpperBound, 1); SOC_b optimvar(SOC_b, T1, LowerBound, 0.2, UpperBound, 0.9); P_phs_g optimvar(P_phs_g, T, LowerBound, 0, UpperBound, 0.4); % 发电流量折算功率 P_phs_p optimvar(P_phs_p, T, LowerBound, 0, UpperBound, 0.4); % 抽水功率 V_up optimvar(V_up, T1, LowerBound, 0, UpperBound, 12000); % 上水库水量 P_grid_buy optimvar(P_grid_buy, T, LowerBound, 0); % 购电 P_grid_sell optimvar(P_grid_sell, T, LowerBound, 0); % 售电 P_curtail optimvar(P_curtail, T, LowerBound, 0); % 弃风弃光 P_shed optimvar(P_shed, T, LowerBound, 0); % 失负荷这里我把所有功率都设成了非负变量购电和售电分开、充放电分开为的就是把模型中的互斥状态用整数变量直接表达清楚。如果你想精简变量数量可以用一个带正负号的P_grid变量代替购售电两个变量但那样分时电价下的购售电收益就不容易分别约束了。对我来说多几个变量的求解代价远低于逻辑模糊的代价。3.4 约束条件的Matlab表达对应的约束在Matlab里写起来非常直接。功率平衡约束power_balance P_w P_pv P_b_d P_phs_g P_grid_buy ... P_load P_b_c P_phs_p P_grid_sell P_curtail P_shed;电池SOC递推约束SOC_constraints SOC_b(2:T1) SOC_b(1:T) ... 0.85 * P_b_c * delta_t / E_b ... - P_b_d * delta_t / (E_b * 0.95);抽蓄水量递推约束V_constraints V_up(2:T1) V_up(1:T) ... P_phs_p * 3600 / (rho * g * H * 1e6) ... - P_phs_g * 3600 / (rho * g * H * eta_t * 1e6) ... Q_natural * delta_t;这个递推式其实是把2.4节的功率-流量关系反解成了流量-功率关系。抽水时从电网吸收的电能一部分转化为水的势能发电时水的势能一部分转化为电能输出两者都通过效率系数计入。3.5 求解与结果输出定义完变量、目标、约束后用prob optimproblem(Objective, F, Constraints, cons)组装问题再调用solve(prob)。求解完成后把结果可视化。我建议至少输出四张图电源出力堆叠图和负荷曲线对比图电池SOC、抽蓄水量在两个周期内的变化曲线购电售电功率时序图弃风弃光和失负荷功率时序图。这四张图基本就能说明调度方案的“好”与“坏”也是论文或项目报告里最核心的结果展示。如果条件允许再画一张“各类储能出力占比”的饼图这个在项目汇报时非常直观。4. 仿真实验与结果对比分析4.1 典型场景设置我用一个模拟的矿区微网做测试风电场装机3MW光伏装机2MW电池储能1MW/2MWh废弃矿井抽蓄额定功率0.4MW。上水库有效库容取10000立方米平均水头80m。负荷峰值为2MW日用能约30MWh。调度步长15分钟周期24小时。分时电价峰平谷三段峰时1.0元/kWh平时0.7元/kWh谷时0.3元/kWh。这个配置看起来光伏风电装机远大于负荷但实际上矿区负荷峰值2MW而风光装机合计5MW就是想刻意制造“午间大发、夜间缺电”的典型矛盾让储能的调节价值放大了。如果不制造这种极端场景储能的存在感会很弱调度策略看不出区别。4.2 三种策略的对比结果我分别跑了三种方案无储能、仅电池储能、电池抽蓄多元储能。无储能方案里午间光伏大发时有接近40%的光伏电量被弃掉晚间负荷高峰则需要从电网购电接近8MWh购电成本非常刺眼。仅电池储能方案把弃光率压到了11%但代价是电池SOC频繁触底如果连续两天阴天电池根本顶不住。电池抽蓄方案的结果更有意思抽蓄在中午承担了主要的抽水任务把富余光伏能量存为水的势能电池则更多在傍晚光伏功率骤降、负荷爬坡的阶段放电到了深夜负荷低谷抽蓄又启动抽水为第二天早高峰做准备。最终弃电率从无储能时的40%降到4%左右购电成本比仅电池方案再降约21%。抽蓄的“跨时段能量搬移”价值体现得非常清楚。4.3 对废弃矿井抽蓄出力上限的敏感性分析废弃矿井抽蓄的功率受到巷道过流能力和水泵选型的双重限制不是想建多大就多大。我把抽蓄额定功率从0.2MW逐步加到0.8MW看系统购电成本和弃电率怎么变。结果是0.2~0.4MW区间增益极明显每提升0.1MW就能让弃电率下降2~3个百分点但到了0.6MW之后继续加大抽蓄功率的边际收益几乎归零。原因在于上水库容量是有限的中午的光伏富余功率再大蓄水池就那么大抽完水就没地方装了。这个现象说明多元储能互补系统的瓶颈未必是功率而是能量容量。做方案设计时如果发现某类储能的利用率长期饱和第一反应不应该是扩建同类储能而应该反思另一类储能的容量和功率是否匹配。4.4 调度结果异常情况分析还有一次仿真出现了一个特别典型的异常抽蓄水量序列在一天结束时比开始时高了将近30%。起初我以为是模型bug后来排查发现天然来水量参数Q_natural设成了一个不小的恒定值而矿井涌水在真实环境里每天持续不断流入上水库。这不只是模型正确性的问题它直接影响了调度策略因为来水是“免费的”调度器会倾向于晚一点放水发电尽量让水留在高处。但这个“免费资源”恰恰反映了废弃矿井抽蓄和普通抽蓄的一个本质区别——它不是纯封闭循环系统有天然径流注入相当于多了一个随机的可再生能源输入。后续我建议在电网调度之外单独研究涌水量的随机性对调度经济性的影响这也是这个方向可以深入挖掘的学术点。5. 常见问题与调试实战记录5.1 模型不可行是约束过紧还是数据错误新手最容易卡死的就是solve返回“problem is infeasible”。一个非常隐蔽的坑是SOC递推约束里的容量单位不一致。如果你把电池容量用MWh但功率用的是kW时间步长用分钟那递推方程里就差了一个3600倍的系数模型几乎必然不可行。我的习惯是把所有单位统一成“MW、MWh、小时”时间步长也折算成小时所有输入数据进来第一件事就是做单位归一的预处理。另一个常见原因是初始SOC设置过低但第一个时段就遇到高峰负荷需要电池放电。可以把SOC初始值设为0.5以上或者放开电池放电功率的约束让模型迭代几次后再收紧。跑调度优化模型不能所有约束一步到位要像开车一样先松油门再踩刹车。5.2 电池SOC曲线在边界上反复震荡怎么办有几次仿真的SOC曲线一直在0.2的下边界附近来回撞看着非常不舒服。原因是我把SOC下限定在0.2但放电功率在最后一个时段的松弛变量P_shed没有被完全限制求解器选择用失负荷来避免电池过放这样SOC勉强维持在下限附近代价是失负荷率偏高。解决思路有两个一是把SOC下限抬高到0.25这样电池有安全裕量二是打开电池最后一段时间的低SOC区间惩罚也就是在目标函数里加一个SOC_terminal惩罚项让调度器主动把末端SOC拉回0.3以上。工程上这叫“末端SOC恢复约束”对连续多日运行的调度系统非常必要。5.3 抽蓄水量越限检查水量约束和SOC约束不一样SOC越限是违反数值边界直接导致无解但水量可能因为天然来水项的存在而悄悄越限。如果上水库初始水量为0.9中午抽水1小时再加上0.1的涌水水量就顶到1.0以上了。这类越限用constraint violation报告很难发现我后来写了一个独立的校验脚本把水量、SOC、功率平衡每个约束单独提取出来检查只要有一个绝对值超过1e-3立刻标红。还有一个和实际相关的坑是抽蓄发电功率和抽水功率的互斥约束用大M法表达时M取值不能太大。过度松弛会导致MILP求解效率严重下降取值太小又可能错误地排除可行解。我一般把M取成该设备额定功率的1.5倍既能保证约束有效又不影响求解速度。5.4 求解时间太长如何加速如果你的调度周期拉长到30天、步长15分钟那决策变量数量会到几万个整数变量也会上千纯MILP求解会非常吃力。三个实测有效的办法减少整数变量把充放电互斥约束的粒度放宽比如允许一日内最多切换N次运行状态用顺序约束代替逐时段的0/1变量缩减法先跑一个粗粒度版本每小时一个时段把结果作为细粒度模型的初始解热启动可以大幅缩短求解时间分解法把抽蓄和电池的调度解耦成两个子问题通过迭代协调这在学术论文里叫拉格朗日松弛法。工程实践中先用热启动就够用了。5.5 数据驱动方法扩展的接口做完这个模型之后如果还想往深度强化学习方向走我的建议是保留现在的数学模型不动把每一步的决策变量、状态转移函数、奖励函数单独抽成一个函数文件。Matlab里做DQN或PPO都要定义环境交互函数而你的环境交互本质上就是功率平衡方程加SOC递推方程这些都已经写好了。把最优解作为专家轨迹存下来后面既可以直接做模仿学习也可以作为RL算法的初始策略。写在最后的个人经验这个项目做下来我最深的感受是多元储能互补调度最考验人的不是算法有多高级而是对物理过程的抽象能力。电池和抽蓄的数学模型如果你只会套公式那代码跑通很容易但结果是否可信完全取决于你对参数的理解。废弃矿井小型抽水蓄能尤其如此水头波动、巷道沿程损失、涌水量随机性每一个看似可以忽略的“工程细节”最后都可能成为让理论方案失效的元凶。拿我跑完仿真后复盘的数据来说如果不考虑矿井天然来水调度方案的购电成本比考虑来水时高出约4%弃电率高出近2%。这些数字不大却在项目汇报时被评审专家一眼看穿——说明模型离实际还有差距。所以我建议每一个做这类研究的同行建模前一定要先去现场看看实际设施的物理边界哪怕只是站在废弃矿井口感受一下巷道空间尺寸也比在电脑前空想几万字约束要强得多。另一个我觉得有价值的扩展方向是精细化成本建模。电池的寿命损耗、抽蓄机组的启停磨损、购售电价的不确定性这些都可以逐步从固定参数升级为动态模型。模型越接近真实调度决策越有工程指导价值。后续如果有机会我会继续分享多时间尺度调度和电池寿命衰减建模的具体实现那些内容比今天这篇更细也更值得反复推敲。