这两年配电网韧性和移动储能成了不少项目组反复讨论的关键词。台风、冰灾这类极端事件一旦发生配电网最容易出现长时间停电传统抢修手段很难在几小时内恢复大面积供电。这时候固定储能站只能照顾到本站附近的负荷移动储能车则可以灵活换位把宝贵的电能送到最需要的负荷节点。我最近完整复现了一套面向配电网韧性提升的移动储能预布局与动态调度策略算例采用 IEEE33 节点系统优化模型和求解流程全部用 Matlab 代码实现。这篇文章就把这套策略从问题建模、求解框架到代码落地、算例分析的全过程拆开讲方便正在做配电网韧性、微网应急供电、移动储能优化配置方向的同学快速上手。如果你是想在工程预演中快速搭一个可复用的计算框架或者正在为“储能车停在哪儿、灾后往哪儿跑”这类问题发愁这篇文章应该能帮你少走不少弯路。我不会只贴代码更多会讲清楚几个关键判断为什么用移动储能而不是固定储能预布局和动态调度怎么统一建模CCG 求解框架在 Matlab 里怎么落地以及我在复现过程中踩过的几个有代表性的坑。1. 项目背景移动储能如何服务配电网韧性提升1.1 韧性提升到底提升什么先说清楚“韧性”和常规“可靠性”的区别。可靠性通常关注故障发生的频率和平均停电时间比如一年用户平均停电多少小时指标是 SAIDI、SAIFI 这一类。而韧性更关注极端事件发生后的“损失规模”和“恢复速度”也就是说当系统遭遇比设计准则更严酷的故障时能不能让关键负荷坚持住能不能快速恢复这几个维度才是韧性研究的重心。极端灾害和普通故障不一样有可能同时造成多条线路停运形成多个孤岛。常规的开关重构只能解决部分联络问题在分布式电源容量不足时负荷依然切掉。这时候移动储能就派上用场了。它可以像一个“可移动的备用电源”在灾前预置到风险较高的区域灾后根据实时网络故障情况再“跑”到最缺电的位置为关键负荷提供短时支撑。韧性提升的落脚点最终要落到量化指标上。最朴素也最常用的一种做法是用“系统在故障期间实际获得的电量”和“所有负荷正常用电需求电量”的比值来衡量。比值越接近 1说明极端事件下的供电保障做得越好。后面建立优化模型时我们就会围绕这个思路设计目标函数和约束条件。1.2 移动储能相对固定储能的核心优势固定储能和移动储能看起来都是在合适的位置放电但本质上差别很大。固定储能选址一旦确定就不可更改如果故障点距离储能接入点太远或者线路被切断储能再好也送不出去。移动储能可以在预布局阶段选择一个相对合理的落点故障动态阶段再通过道路系统把储能车调度到真正需要的位置相当于把“选址灵活性”和“运行灵活性”结合了起来。从投资利用率角度看固定储能很难兼顾多个位置的应急需求相当于每个站点都要配置一份备用容量成本很高移动储能车可以按风险变化在多个节点之间轮换一辆车就能覆盖更大范围的应急需求。当然移动储能的劣势也很明显车辆在移动期间无法供电到达新位置也需要时间因此“预布局”和“动态调度”必须放在同一个优化框架里考虑否则很容易出现储能车赶到了但负荷已经停了太久的情况。下表是我在复现时用来对比两者特征的简化表可以直观看到差异。对比项固定储能移动储能接入位置一次性选址灾前预置灾后可迁移故障适应性依赖固定线路连通性可根据故障动态调整利用率低峰时段容易闲置多场景复用利用率更高移动过程供电不存在移动期间不可供电需建模投资与运维单点重复配置单台覆盖范围更大选择移动储能并不意味着固定储能没有价值两者可以互补。只是当我们特别关注极端事件后的韧性恢复时移动储能的机动性往往比增加固定容量更划算这也是我选择复现这类策略的原因。1.3 为什么选 IEEE33 节点系统作为复现对象IEEE33 节点系统是一个很经典的配电网算例基准电压 12.66kV包含 1 个根节点、32 条支路和若干联络开关节点数不多不少非常适合研究馈线故障、负荷转供、分布式电源接入等问题。相比动辄上百节点的实际配电网IEEE33 节点既能体现潮流的空间特性又不会让优化模型在规模上失控用来验证移动储能预布局与调度策略再合适不过。另外IEEE33 系统的网络结构公开、数据统一不同文献、不同团队做出来的结果有可比性这给“复现”提供了很大的便利。我在实现时并不需要从零构建复杂的拓扑数据只需要把标准支路参数、节点负荷数据翻译成 Matlab 可读的结构体再统一处理成优化模型需要的矩阵形式。对于初学者来说从这个算例入手最容易建立“模型-代码-结果”的完整闭环。2. 问题建模预布局与动态调度的数学本质2.1 极端事件与场景集合怎么构造移动储能的预布局动作发生在灾害来临之前但故障到底发生在哪几条线路上、断开几条支路事前并不知道。为了在数学上刻画这种不确定性我采用多场景鲁棒优化的思路预先构造一组极端故障场景每个场景对应一组线路同时断开的组合。场景集合的构造既要覆盖可能出现的最坏情况又不能规模爆炸。最直接的方法是先识别系统中的脆弱线路通常是对负荷影响大、处于关键供电通道上的支路然后在脆弱线路里按“同时故障线路数上限”做抽样形成候选故障线路集合。比如设置最多同时断开 3 条支路就从候选支路中随机组合出 20 个场景。这个方式简单有效也方便后续调节鲁棒保守程度。还有一个细节值得注意故障场景并不是对称的。不同场景下同一储能车的初始位置相同但后续移动路径、接入节点可能完全不同所以预布局变量必须独立于场景而动态调度变量要随场景变化。这也是两阶段优化的基本结构第一阶段做不依赖于具体故障场景的部署决策第二阶段针对每个具体场景再优化。2.2 目标函数与韧性评估指标优化目标的核心是“让极端场景下的负荷削减量尽量小”。可以直接把多个场景的失负荷量加权求和作为目标权重可以取场景概率也可以取为 1代表等概率最恶劣情况。为了更贴近韧性评价我会额外加入一个所有场景统一计算损失函数的形式min Σ_s w_s · Σ_t Σ_i P_cut(s,i,t)其中 s 是场景t 是时间段i 是节点P_cut 是切负荷量w_s 是场景权重。如果要考虑移动储能车在不同位置的调度成本也可以加入“移动启用费用”和“充放电损耗”但要注意别让权重失衡。否则优化结果会为了省一点移动成本而牺牲大量负荷恢复这不是我们想要的。为了最后直观评估韧性我在代码里另外算一个指标 RIRI 1 - ( Σ_s Σ_t Σ_i P_cut(s,i,t) ) / ( Σ_s Σ_t Σ_i P_load(s,i,t) )RI 越接近 1代表极端事件下恢复水平越高。这个指标不参与优化只用于后处理和不同方案对比。实践上如果 RI 从 0.45 提升到 0.78对关键负荷的保障效果差异是非常明显的。2.3 核心约束潮流、储能、移动与网络辐射状约束部分是这个模型的真正难点我把它拆成四类写。第一类是潮流与电压约束。在配电网里我采用支路潮流模型把支路功率、节点电压、电流都写成变量。由于原始的非线性潮流方程求解困难通常采用二阶锥松弛把电压平方和电流平方设为新变量原问题就变成可以被商业求解器直接处理的凸优化子问题。用公式简写就是每条支路要满足首末端功率平衡、电压降落方程和容量限制再加节点注入功率平衡约束。松弛是否严格需要在求解后检查松弛间隙这一点我在后面避坑章节还会专门说。第二类是储能运行约束。每台移动储能车都有荷电状态SOC动态方程SOC(v,t) SOC(v,t-1) η_ch·P_ch(v,t) - (1/η_dis)·P_dis(v,t)同时放电功率不能超过额定上限SOC 也要保持在上下限之间比如 0.2 到 0.9。此外同一时刻不能同时充电和放电这个约束看起来简单但写成线性表达式时需要引入一个二进制变量比如用 z 表示充电状态用 1-z 表示放电状态。第三类约束是移动储能的“位置-时间”耦合约束。这是移动储能和普通储能的本质区别。每台储能车在每个时间段必须恰好位于一个节点位置变量是 0-1 变量如果从节点 i 移动到节点 j 需要耗费 delta 个时段那么在移动到达 j 之前该车辆不能在其他任何节点放电。这部分约束是最容易写错的地方我会在后面的代码和避坑章节重点讲。第四类约束是网络辐射状约束。配电网在正常运行和故障隔离后线路需要保证连通且无环。在多场景模型中每个场景的拓扑是确定的但可以操作联络开关进行网络重构。为了保持可行性需要加入保证辐射状结构的约束常见做法是用单商品流或独立节点生成树约束。在 IEEE33 节点这个小系统上用生成树约束可以接受但大规模算例就要留意计算量。3. 求解框架与 Matlab 代码实现3.1 两阶段鲁棒优化的整体结构我们面对的是一个“先部署、后响应”的决策过程自然对应两阶段优化模型。第一阶段变量是移动储能车的预布局位置和初始 SOC第二阶段变量包括每个场景下的储能车实时位置、充放电功率、网络开关状态以及切负荷量。从数学形式上看这是一个 min-max-min 结构min_y { C_pre(y) max_{s∈S} min_{z∈F(s)} C_ope(z, y) }也就是在第一阶段决策 y 时第二阶段要考虑最不利的场景 s 下最优运行决策 z 带来的运行损失。如果只用期望场景优化得到的结果往往低估不确定性如果针对每个单场景都强制满足又可能过于保守。鲁棒优化就是希望在两者之间寻找一个平衡点。在 Matlab 中我用 YALMIP 做建模平台外部调用 Gurobi 或 CPLEX 求解混合整数规划。YALMIP 的最大好处是可以用符号逻辑构建约束比如 binvar、sdpvar代码可读性很好适合复现和二次修改。如果你更习惯直接用求解器的 API 建模也可以只是变量矩阵比较复杂时维护成本会高不少。3.2 CCG 求解流程及伪代码两阶段鲁棒优化最常用的精确算法是列与约束生成CCG。它的思路是交替求解主问题和子问题主问题先假设只有一个或几个已知场景得到预布局方案子问题根据当前预布局方案找出让运行损失最大的最恶劣场景如果存在更恶劣的场景就把这个场景相关的变量和约束补充到主问题里继续迭代直到上下界收敛。我给一个简化的 CCG 伪代码方便理解整体流程初始化给定初始场景 s0设置 LB -infUB infk 0。 while (UB - LB) ε: 1. 求解主问题得到预布局 y_k 和目标值 obj_master。 更新 LB max(LB, obj_master)。 2. 固定 y_k对所有可能场景 s 求解子问题得到运行成本 obj_sub。 找到使 obj_sub 最大的场景 s*更新 UB min(UB, C_pre obj_sub)。 3. 将场景 s* 对应的第二阶段变量和约束加入主问题。 4. k k 1。 end while在实际复现时子问题不一定非得遍历所有场景。我们可以先用一个场景池做快速搜索再在一些极端故障组合中找更恶劣场景能显著降低迭代次数。对于 IEEE33 节点这种规模遍历几十个场景其实还好但如果把系统放大到几百个节点就要考虑用启发式方法加速场景识别。3.3 Matlab 代码结构与关键代码片段我的代码仓库目录大致是这样的|-- main.m # 主程序设置参数并启动求解 |-- init_IEEE33.m # 初始化IEEE33节点网络数据 |-- generate_scenarios.m # 生成极端故障场景 |-- build_storage_model.m # 构建移动储能数学模型 |-- solve_master.m # CCG主问题求解 |-- solve_sub.m # CCG子问题求解 |-- plot_results.m # 结果可视化其中build_storage_model.m是最核心的部分我贴一段位置变量的关键代码%% 移动储能车位置变量与约束 % x(v, i, t) 1 表示第v辆车在t时段位于节点i x binvar(nVehicle, nNode, nTime, full); cons_x []; % 每辆车每个时段只能在一个位置 for v 1:nVehicle for t 1:nTime cons_x [cons_x, sum(x(v, :, t)) 1]; end end % 移动过程约束从i到j至少需要delta个时段 % y_move(v,i,j,t)1 表示第v辆车在t时段开始从i移动到j y_move binvar(nVehicle, nNode, nNode, nTime, full); for v 1:nVehicle for i 1:nNode for j 1:nNode if i ~ j for t 1:nTime-delta(i,j)1 % 如果开始移动则起点在t时刻占位终点在tdelta到达 cons_x [cons_x, ... x(v,i,t) y_move(v,i,j,t) 1, ... x(v,j,tdelta(i,j)) y_move(v,i,j,t)]; end end end end end这段代码里用了两个变量来表示位置和移动事件配合起来就能保证“移动期间不能供电”和“到达后下一时刻可接入”的逻辑。实际建模时还要加一些冗余约束比如一个车辆不能同时开启两个方向的移动否则模型虽然可行但求解速度会变慢。4. 算例分析预布局节点怎么选、储能车怎么跑4.1 参数设置与场景数据为了能让结果可复现我在init_IEEE33.m里使用了标准的 IEEE33 节点拓扑基准功率 1MVA基准电压 12.66kV。移动储能参数假设如下表所示。参数名称数值移动储能车数量2 辆单台储能容量1 MWh最大充/放电功率0.5 MW初始 SOC 范围0.2 - 0.9充/放电效率0.95 / 0.95时间分辨率1 小时调度总时段8 小时场景数量6 个极端场景最大同时断线数3 条场景选取上我以支路 3-4、5-6、8-9、13-14、26-27 这些负荷较重或位于馈线末端的关键支路为主要候选随机组合出 6 个典型极端场景。在这个设置下预布局阶段解出来的运行成本、切负荷量以及韧性指标都符合物理直觉。4.2 预布局结果解读在本算例的参数下优化得到的预布局方案是第一辆车停在节点 18第二辆车停在节点 25。单看拓扑节点 18 和节点 25 都位于网络末端区域但周围负荷密度并不低。为什么不是停在根节点附近因为如果所有储能车都停在靠近变电站的位置故障一旦断开上游路线末端负荷依然孤立无援如果停在太偏远的末端又可能因为道路距离和移动时间太长无法在窗口期内支援其他区域。优化模型自动折中了这两点。另外预布局结果还与负荷时序有关。如果某个时段末端负荷特别高储能车会倾向于靠近该区域。我试过把模拟时间设为 24 小时并加入峰谷负荷曲线预布局位置会在馈线中段和末端之间来回选择说明这种策略对负荷时间特性的敏感度很高。做工程应用时至少要基于当地的典型日负荷曲线来定预布局方案不能只看平均值。4.3 动态调度过程与恢复效果以其中一个故障场景为例假设在 t1 时支路 8-9 和 25-29 同时断开导致节点 18 所在的支路末端以及节点 25 周边进入孤岛状态。优化后的动态调度结果大概是t1储能车1在节点18放电储能车2在节点25放电 t2储能车2感知到节点25下游负荷较低开始向节点29移动 t3储能车2到达节点29接入并恢复该区域关键负荷 t4储能车1继续在节点18放电同时等待网络重构结果 t5联络开关闭合部分负荷转供储能车1陆续降低出力可以看到储能车并不是从一开始就满功率放电而是结合网络重构的时序动态调整。早期孤岛内负荷需求量很大储能车高功率输出随着上游开关恢复供电储能车会降低出力次数保留一部分 SOC 给可能出现的二次故障。这就是“动态调度”和“静态应急电源”最大的区别。4.4 与无储能、固定储能的对比结果为了更清楚地体现移动储能的优势我设置了三个对比方案无储能、固定储能两套固定储能分别在节点 18 和 25、移动储能预布局加动态调度。在相同故障场景和负荷时序下结果如下表。方案总切负荷量 (MWh)韧性指标 RI无储能10.850.42固定储能6.720.64移动储能3.960.78固定储能能解决一部分末端孤岛供电但因为位置固定遇到故障点刚好阻断储能接入线路时就无能为力了。移动储能通过灾后移动到孤岛内部能够显著减少切负荷量。从算例看RI 从 0.64 提升到 0.78对应总切负荷量下降了接近一半。这个结果也说明仅靠增配储能容量不一定是最优解把储能车部署到“对的时间”和“对的位置”效果往往比单纯多买电池更明显。5. 避坑指南与扩展建议5.1 求解速度慢怎么办IEEE33 节点加上两个储能车、六个场景规模不大但如果把所有时段和所有节点的变量一次性铺开混合整数规划还是会变得很臃肿。第一次跑的时候我遇到主问题求解时间超过十分钟的情况后来通过三个手段解决。第一给初始解。先用启发式方法生成一个可行的预布局方案作为主问题的 MIP start。比如可以按“离脆弱线路近”的规则预先指定储能车停靠节点再让优化器在这个基准上调整能省去大量分支定界时间。第二加对称破除约束。两辆车参数相同时预布局结果会存在大量对称解变量置换后目标一样。加入“第一辆车位置编号小于第二辆车位置编号”之类的约束可以砍掉近一半搜索空间。第三在子问题里先求解线性松弛版本用目标值来判断该场景是否是潜在最恶劣场景。如果某个松弛场景的目标值排名靠后大概率不会成为真正的恶劣场景可以先不加入主问题减少主问题负担。5.2 DistFlow 二阶锥松弛细节在 YALMIP 里写 DistFlow 二阶锥约束时要注意变量替换后的松弛形式。简单来说对每条支路都需要满足V_j V_i - 2(R·P X·Q) (R^2 X^2)·I_ij其中 R、X 是支路电阻和电抗V 和 I 是平方形式的变量。这个约束直接写在 YALMIP 里就是锥约束。常用写法是cons [cons, V(j) - V(i) 2*(R*P_ij X*Q_ij) - (R^2X^2)*I_ij 0];松弛之后还需要检查误差。我一般会在结果更新后计算每条支路的松弛间隙gap_ij |P_ij^2 Q_ij^2 - V_i * I_ij|如果某个支路的间隙远远大于 1e-4说明这个支路很可能发生了电压越限或潮流不符合物理规律需要检查负荷参数和网络数据。多数情况下IEEE33 节点算例只要电压约束、容量约束不过于紧张松弛误差都很小。5.3 移动时间建模的常见错误移动时间是整个模型里最容易出错的地方。常见一个错误是只把“移动终点节点”的接入时间约束了却没有限制“移动起点节点”在移动期间不能供电。结果就是储能车一边移动一边还在给原来的节点放电模型看起来可行实际上却是物理悖论。正确的做法是同时约束起点和终点的位置状态。我建议把移动过程拆分为两个时间点开始移动的时刻 t 和到达目标的时刻 tdelta。在 t 到 tdelta-1 之间该车辆不能出现在任何节点可以通过“每辆车每时段必须位于一个节点”的约束结合移动状态实现。如果时间步长比较粗(比如1小时)可以假设车辆在整小时段内处于“不可用”状态到达后的下一个小时才能接入。这种近似对结果影响不大但模型复杂性会小很多。还有一个容易忽略的问题移动时间和道路距离不能直接用欧氏距离计算。IEEE33 节点只是电网拓扑不代表车辆行驶路径。我在代码里用了一个距离矩阵将节点之间道路距离折算成小时数值要设置合理否则预布局决策会过度乐观。5.4 鲁棒保守程度如何调节鲁棒优化的保守度由场景集合和故障组合上限共同决定。如果你把所有可能故障组合都纳入最恶劣场景求解结果会非常保守储能车几乎要覆盖所有末端节点这在工程上并不现实。反之如果只选个别场景决策又会过于激进。我在复现时增加了一个参数 Gamma表示“同时断线数量上限”。Gamma 越大考虑的最恶劣情况越严重系统韧性指标通常会提升但需要的储能容量和调度成本也会增加。实际使用时可以基于历史极端事件统计来设定 Gamma比如过去五年最大同时断线数是 4就设为 4不要凭感觉加大。另外还可以把多个场景赋予不同概率权重然后用条件风险价值指标替代期望值这样能兼顾极端小概率事件和平均表现。这个扩展用 CCG 框架也能实现只是子问题的目标函数要调整一下代码改动并不大。最后再分享一点个人的实际操作体会复现这套策略最难的不是储能本身的充放电方程而是“位置”和“时间”这两个维度交叉产生的约束。建议你先把移动约束单独抽出来做一个最小算例比如 5 节点 2 时段验证位置变量和移动变量的逻辑能跑通再把它放回 IEEE33 节点系统里做完整算例。另外预布局结果对场景集和负荷时序非常敏感不要指望一套参数在所有系统上都成立真正做项目时一定要用当地线路数据和负荷曲线重新校准。这样复现出来的代码才不是一纸空文而是可以支撑工程判断的“活”工具。