ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

配电网韧性提升的移动储能预布局与动态调度:IEEE33节点Matlab复现

配电网韧性提升的移动储能预布局与动态调度:IEEE33节点Matlab复现 这次分享的项目其实是一个在配电网韧性研究里非常经典、又特别适合上手的命题面向配电网韧性提升的移动储能预布局与动态调度策略用 Matpower/CVX/YALMIP 在 IEEE33 节点系统上做完整复现。很多人一听到“配电网韧性”“移动储能”“动态调度”就觉得高深实际上拆开之后就是一个“在灾难发生前把移动储能停在哪在灾难发生后又该怎么开、怎么走”的双层决策问题。关键难点不在数学符号多复杂而在于把电网拓扑、时序、储能运行、极端事件不确定性串成一个可求解的Matlab程序。这篇文章我会把模型怎么建、IEEE33节点怎么搭、代码结构怎么设计、求解时踩过的坑有哪些全部摊开讲一遍。适合正在做配电网规划/运行方向的研究生也适合想从零接触韧性评估的工程师。1. 为什么盯上“预布局动态调度”配电网韧性的核心命题1.1 韧性到底是什么跟可靠性有什么不一样先消除一个最常见的误区配电网韧性不等于可靠性。可靠性主要应对的是设备随机故障比如某条线路突发跳闸靠继电保护、自动重合闸、转供就能在几分钟到几小时内恢复。韧性针对的是小概率、高损失极端事件比如台风、冰灾、暴雨、地震这类事件往往造成多处线路同时断线、变电站失压、配电网大面积解列此时常规备用电源、联络开关可能根本转不过去因为连完好路径都没有。韧性的直接体现是“系统能扛住灾害、灾后能快速恢复到正常状态”关注的是从灾前预防、灾中响应、灾后恢复全过程的时间曲线而不只是孤立的可靠性指标。理解了这个区别就明白为什么移动储能被单独拎出来做研究对象。固定储能只能站在原地如果站址不在断线区域附近极端事件下可能根本帮不上忙。而移动储能MESS本质上是“装在卡车上的电池变流器”它最核心的价值不是容量大小而是可以跟着灾害态势走的时空灵活性。灾害发生前可以提前把移动储能部署到预测的受影响区域这叫预布局灾害发生后可以根据最新的线路断开情况和负荷紧迫程度让移动储能一边放电、一边挪位置这叫动态调度。合在一起就是一整套“移动资源如何穿越时空去兜底”的优化方法。1.2 为什么选“预布局动态调度”而不是单纯调度很多论文里只做灾后充放电调度把移动储能初始位置当成已知条件。这种做法有一个问题移动储能从正常站点开到需要保电的站点需要时间如果灾害发生时它还停在几十公里外的停车场等它赶到时负荷已经停了太久。预布局要解决的就是“赶不上”的问题——在灾害发生前根据气象预测、历史灾损模型提前把移动储能布到最可能需要它的节点附近。但“提前布点”也有风险如果最终断线区域和预测位置不一致布错地方的储能可能白跑一趟锁定在错误位置反而浪费。所以更严谨的模型把预布局和动态调度耦合起来第一阶段的预布局决定“手里有哪些资源、放在了什么位置”第二阶段的动态调度再根据不确定性实现后的实际灾况决定每个时段的充放电、移动和是否孤岛保电。两层决策必须放在同一个闭环里优化否则就是次优解。我在实际跑代码时的体会是这个命题的吸引力在于它跟现实中应急电源车的使用逻辑完全吻合。地市供电公司做台风应急演练时会提前把应急发电车、储能车调度到风区前沿的供电所台风过境后再根据故障巡线结果把应急车派到最严重的区域。论文模型只不过把“人工经验调度”变成“数学优化调度”而且还能量化方案能减少多少失负荷这正好是工程与学术都关心的点。2. IEEE33节点系统最小但最经典的测试床2.1 系统拓扑与数据习惯IEEE33节点配网测试系统几乎是配电网研究者的“hello world”。它是一个12.66kV的中压馈线系统包含33个节点、32条支路拓扑是从变电站母线节点1出发的辐射状网络总负荷大约3715kW加2300kvar带不少分支线。这套系统节点数量不多但包含辐射网、分支线、末端电压偏低等典型特征特别适合用来验证重构、有功/无功优化、储能调度这类问题因为算得快还能看出效果差异。在做Matlab实现时我建议手里保留一套标准的IEEE33节点参数表。常见格式是支路编号首端节点末端节点电阻(ohm)电抗(ohm)有功负荷(kW)无功负荷(kvar)1120.09220.0470100602230.49300.25119040.....................3232330.53150.2714200100首端节点1通常视为变电站根节点电压幅值恒定为1.0p.u.其他节点潮流结果一般在0.95~1.05p.u.范围内。注意很多版本会把负荷值放进支路矩阵的第三列或者使用Matpower的case33bw但Matpower自带版本负荷数据可能跟你看到的论文不完全一致。复现时最好先固定一个数据来源不要今天用这个矩阵明天用那个矩阵否则后期对比结果会乱套。2.2 在Matlab里搭建IEEE33节点的关键细节最省事的方法是直接用Matpower读取case33bw。但是如果你想做更灵活的韧性模型建议自己写一个简单的拓扑结构体。我会这样初始化mpc loadcase(case33bw); branch mpc.branch; % [fbus, tbus, r, x, b, rateA, rateB, rateC, ratio, angle, status] bus mpc.bus; % [bus_i, type, Pd, Qd, Gs, Bs, area, Vm, Va, baseKV, zone, Vmax, Vmin] baseMVA mpc.baseMVA; Vbase 12.66; % kV Sbase 10; % MVA但注意Matpower的case33bw里负荷单位是kW/kvar潮流计算时Matpower会自动按baseMVA归一化。如果你想自己用DistFlow建模需要把支路阻抗换算成标幺值[ z_{ij,\ p.u.} \frac{(r jx) \cdot S_{base}}{V_{base}^2} ]许多新手在这里栽跟头直接在DistFlow约束里用国际单位制的欧姆和千伏安不归一化导致潮流方程系数完全错误。我在代码里采取的做法是先把阻抗、功率都换算到标幺值所有目标函数和约束都基于p.u.写最后画图时再转回有名值。归一化是模型和求解器能够稳定收敛的基础。在拓扑约束上由于主动配电网的潮流计算大多采用DistFlow分支方程对每一个节点和支路有[ P_j \sum_{k \in N_{child}} P_k p_j^{load} - p_j^{gen} ][ Q_j \sum_{k \in N_{child}} Q_k q_j^{load} - q_j^{gen} ][ V_j^2 V_i^2 - 2(r_{ij}P_{ij} x_{ij}Q_{ij}) (r_{ij}^2 x_{ij}^2) \frac{P_{ij}^2 Q_{ij}^2}{V_i^2} ]通常直接保留这个约束会形成非凸二次项求解麻烦。好在辐射状配网处于正常运行范围时损耗项很小可以线性化去掉最后那个平方项同时用辅助变量 ( U_i V_i^2 ) 替换电压平方这样潮流约束变成线性[ U_j U_i - 2(r_{ij}P_{ij} x_{ij}Q_{ij}) ]线性化误差在大多数韧性分析场景可以接受。这个细节直接决定了你的MILP能不能用Gurobi快速解出来。我在复现代码里就是用这个线性DistFlow而不是用原版二阶锥模型因为后面要叠加移动储能的时空约束模型规模会急剧膨胀二阶锥加大量二进制变量很容易把求解时间拖到无法接受。2.3 移动储能接入方式与约束建模移动储能MESS在IEEE33节点系统里的处理方式和固定储能有本质区别。固定储能只需要每个时段满足充放电约束、荷电状态SoC约束位置是固定的移动储能则需要额外处理时空耦合约束也就是“储能车从一个节点开到另一个节点需要花费多少时间开过去的途中不能充放电到达后才能接入节点”。我常用的表示方式是把每辆移动储能车当做一个离散单元 ( m )具有一个时刻 ( t ) 所在节点变量 ( loc_{m,t} )和一个时间片转移变量 ( trans_{m,t,ij} )。如果储能车在时段 ( t ) 从节点 ( i ) 移动到节点 ( j )则时段 ( t ) 到 ( t travel(i,j) ) 之间该储能车不能提供任何功率只有到达节点后储能车才能挂接在该节点参与充放电。这个travel时间通常用“相邻节点移动需要1个时段”的假设简化但也可以按实际交通距离算出时间段数。预布局在第一阶段调整的是 ( loc_{m,0} )即初始布点位置动态调度调整的是后续时段的转移路径。移动储能设备自身还带几个常规约束充放电功率上限( 0 \le p_{m,t}^{ch} \le P_{m}^{ch,max} )( 0 \le p_{m,t}^{dis} \le P_{m}^{dis,max} )同一时段不能同时充放电需要引入二进制变量 ( u_{m,t} )SoC动态( SoC_{m,t1} SoC_{m,t} \eta_{ch} p_{m,t}^{ch} \Delta t - \frac{1}{\eta_{dis}} p_{m,t}^{dis} \Delta t )SoC上下限( SoC_{m,t} \in [SoC_{min}, SoC_{max}] )。这些约束单独看每一个都很简单但组合起来后节点-时段-储能-充电/放电/移动/SoC的多维索引极易写错。我在编写代码时最常犯的错是忘了给“移动期间不参与运行”建立硬约束导致求解器偷偷让一辆储能车同时出现在两个节点充放电。3. 两层决策模型预布局与动态调度是怎么耦合的3.1 第一阶段预布局的决策变量与场景不确定性预布局问题本质上是一种随机/鲁棒优化。因为灾害发生前我们不知道哪些线路一定会断开所以最稳妥的做法是生成一组极端事件场景集合。比如设置“台风由东向西经过系统”线路6-7、7-8、13-14、15-16同时断线另一个场景是“暴雨导致南部馈线故障”线路24-25、25-26断开。第一阶段变量通常包括( y_m )移动储能车 ( m ) 是否预布局在节点 ( i )可以写成布尔量或0-1变量也可以包含可预先布置的应急发电、联络开关状态等辅助资源。这个阶段并不直接决定每个时段的充放电而是决定“资源最优化初始位置”。因此第一阶段目标往往采用“期望损失最小”或“最坏场景损失最小”。后者对应分布鲁棒/两阶段鲁棒模型[ \min_{y} \quad \max_{\xi \in U} \quad \min_{z} \quad F(y, z, \xi) ]其中 ( \xi ) 描述线路故障集合( U ) 是由不确定预算、线路权重构成的不确定集。在IEEE33节点上做鲁棒优化能体现韧性决策的保守性布点要能同时兼顾多个可能故障场景而不是只针对某一条线路。当然鲁棒优化求解难度明显高于场景集抽样。如果只是想快速验证算法效果我更推荐先用随机场景法SAA生成 ( K ) 个故障场景每个场景赋一个概率权重把目标函数写成所有场景的加权失负荷之和。此时模型变成一个大混合整数二次规划MIQP或MILP可以交给Gurobi/Cplex直接求解。3.2 第二阶段动态调度的运行决策第二阶段是给定预布局位置和故障场景之后的逐时运行优化。时间轴一般从灾害发生前几小时到灾后恢复为止划分为 ( T ) 个时段常见粒度是1小时或0.5小时。第二阶段的决策包括移动储能车每个时段的所在节点、是否移动、移动到哪移动储能车每个时段的充电/放电功率配电网每个时段的有功、无功潮流和节点电压每个时段的切负荷量 ( \Delta p_{i,t}^{shed} ) 和 ( \Delta q_{i,t}^{shed} )。动态调度的目标自然是尽量少切负荷。可以用带权重的切负荷量比如医院、重要用户权重大普通居民权重小。目标函数可以写成[ \sum_{t1}^{T} \sum_{i1}^{N} w_i \Delta p_{i,t}^{shed} ]同时也可以加入储能运行惩罚防止求解器为了省事把所有储能放在一个节点或者出现频繁移动的奇怪路径。移动储能在时间段上移动太频繁也不符合现实因为移动需要时间、人员和交通风险。这里有一个关键的建模点动态调度是“在某个故障场景下”的调度所以同一个预布局方案对应多个场景时第二阶段会重复优化多次。在SAA框架里状态变量第二阶段变量是可以随场景变化的但第一阶段变量 ( y ) 必须对所有场景保持一致。二进制变量是否会跨场景耦合决定了模型是不是“理想”的分解结构。很多刚入门的朋友在这里卡住他们把所有场景的所有二进制变量一起堆进去求解内存直接爆掉。正确做法要么用Benders/CCG分解要么把你求解器的线程数调大、把MIP Focus设为找可行解。3.3 目标函数怎么选切负荷权重与恢复时间的权衡韧性目标不像经济调度那么单一。有些论文直接用累计失负荷最小作为目标不考虑时间。但现实中同等失电量下“第一小时失电500kW然后快速恢复”和“断断续续失电10小时”对用户的影响完全不同。因此我会在目标函数里增加一个时间惩罚因子让储能车更偏向于在故障发生后的前几个时段优先恢复重要负荷而不是“平均用力”。具体做法是对每个时段 ( t ) 的切负荷乘以时间权重 ( \gamma_t )比如 ( \gamma_t \exp(-\lambda t) ) 表示越早恢复权重越高。这个改动非常小但对调度路径的影响很大。比如同一辆储能车如果不加权它可能先去一个负荷小的末端节点把电压抬一抬再去重负荷节点加上时间衰减权重后它会优先去最影响整体恢复指标的重要节点。我在复现论文结果时发现很多论文里“储能车先到一个岛屿节点拉高电压然后再转到另一个节点”的路径规划其实都是这个时间权重在起作用。目标函数中还能加入“是否达到最小恢复时间”这种约束比如要求重要节点失电时长不超过2小时。但这类约束会让模型变得很硬有时为了满足目标约束求解器会安排储能车在故障后第一时刻就赶到最远节点忽略了实际行驶时长。建议先用简单权重目标跑通再逐步加硬约束。3.4 求解策略从场景枚举到两阶段鲁棒/CCG在Matlab里实现两阶段优化用YALMIP写最方便。YALMIP里面直接支持optimize求解MILP也可以利用bilevel形式自己写CCG循环。我自己的经验是场景数量少K5~10时直接用SAA随机场景展开式建模Gurobi求解难度不大适合复现和验证。场景数量多但想得到更保守解时采用两阶段鲁棒割平面CCG主问题给出一阶段预布局子问题在给定布局下求解最坏故障场景下的最小切负荷然后把生成的最坏场景约束反馈回主问题。CCG通常在10轮迭代内收敛但每一轮都是一个大MILP耗时反而比直接SAA高。如果追求速度可以采用“不确定集决策规则”近似方法比如让储能车的移动决策遵循线性仿射规则但会牺牲最优性。很多代码能“跑通”但不一定“算得对”。我在调试时发现用CCG求解最坏场景时子问题里的max运算要线性化一般引入大M法或对偶变化。而sdpvarbinvarconstraintoptimize的写法很容易在目标函数里混入二进制变量乘积导致求解器频繁报“Nonconvex model”。针对这个问题需要先把所有非线性项化成大M线性化。下面我给出一段核心代码片段展示移动储能的基础建模。4. Matlab代码实现从数学模型到可运行程序4.1 代码整体框架与文件划分我在做整套复现时不会把所有内容写在一个脚本里那样调试起来非常痛苦。建议拆成四个部分data_ieee33.m定义IEEE33节点参数、支路表、负荷节点、负荷曲线如果做时序分析还要定义各节点24小时负荷倍数。model_mess_plando.m定义预布局动态调度的决策变量和约束条件输出YALMIP的constraint集合。solve_mess_plando.m组装目标函数、调用求解器、保存结果到结构化数组。plot_result.m画韧性恢复曲线比如每个时段的切负荷量、移动储能车的位置轨迹。主函数里的大致流程是先运行data_ieee33再设定故障场景再调用模型函数然后求解最后画图。这样你在修改故障场景或者储能数量时只需要改参数不需要动模型内部代码。一段关键模型代码可以这样写% 移动储能时空耦合约束 % m: 储能车索引; N: 节点数; T: 时段数; loc: N x T 的0-1变量, 表示m车在t时刻是否在节点i % mov: 边的有向移动变量 constraints [constraints, sum(loc, 1) 1]; % 每个时段必须且仅在一个节点 % 移动约束如果从i移到j则本时段所在节点清零经过travel时间段后才能到达 for t 1:T-dt_travel for i 1:N for j 1:N if adj(i,j) 1 constraints [constraints, mov(i,j,t) loc(i,t)]; constraints [constraints, mov(i,j,t) loc(j,tdt_travel)]; constraints [constraints, mov(i,j,t) loc(i,t) loc(j,tdt_travel) - 1]; end end end end这里我只展示一个简化版本。实际模型里mov还需要约束同一时段只能向一个方向移动且移动期间不参与放电。我建议用implies或者大M把这些逻辑写明白避免求解器在二进制变量之间找漏洞。你会发现代码里的核心难点根本不是IEEE33的潮流方程而是每个时段的储能节点位置变量与相邻时段移动路径变量的逻辑关系。这是整套代码最耗调试时间的地方。4.2 潮流约束的YALMIP建模线性DistFlow在YALMIP里非常简洁。我假设变量P和Q是N-1条支路上的有功/无功功率U是节点电压平方pd和qd是节点净负负荷减电源。每段潮流约束如下% 对每个非根节点 j for j 2:N i parent(j); % 父节点 constraints [constraints, U(j) U(i) - 2*(r(i,j)*P(i,j) x(i,j)*Q(i,j))]; % 功率平衡 constraints [constraints, sum(P(:,j)) pd(j) sum(P(j,:))]; end注意如果根节点电压标幺值为1.0则U(1) 1.0。每个节点的电压上下限约束为 ( 0.95^2 \le U_j \le 1.05^2 )。在这里有一个很坑的地方如果直接对sqrt(U)添加约束YALMIP会认为模型非线性转而卡在求解器选择上。正确做法是约束U本身而不是电压幅值。要显示电压幅值时最后用sqrt(value(U))。另外遇到线路断开时故障支路的P和Q都为0而且对应的电压降落公式不再适用。处理办法有两种一种是把断开线路对应的约束删除另一种是保留约束但强制其功率为0。我推荐第二种因为保持矩阵维度不变编程更好写只需要把支路status设为0并添加P(i,j) 0; Q(i,j) 0;即可。4.3 参数设置建议与调参思路复现时最关键的参数是移动储能车的数量、容量、充放电功率以及移动时间粒度。我通常的设置如下参数推荐初始值备注移动储能车辆数2~3太多求解指数爆炸太少看不出调度效果单台容量500 kWh大约是两个20尺集装箱储能的规模单台最大放电功率200 kW压配网局部供电能力也能满足小负荷群单台最大充电功率100 kW灾后可能需要从变电站充电相邻节点移动时间1个时段把整个系统看作1小时车程内可达时段数T24模拟一天的事故过程故障场景数5~10覆盖不同断线组合权重w_i重要负荷5一般负荷1体现差异化保电这些参数决定了模型大小。24个时段、33个节点、3辆MESS时二进制变量大约有3 * 33 * 24 2376个loc再加上移动变量总共四五千个0-1变量。对Gurobi来说完全可控通常在几十秒内得到最优解。如果你想看更亮的调度效果把相邻节点移动时间改成2个时段这样储能车不能在相邻时段瞬移路径约束会明显影响结果。5. 实操案例台风灾害下的IEEE33节点仿真5.1 场景设置与模型输入为了展示预布局与动态调度到底带来了什么差异我设计了一个简化台风场景用两条主线同时中断作为极端事件。假设台风从系统西北方向向东南方向移动导致支路 2-19、19-20、20-21 以及支路 15-16 同时断开。这样系统被割裂出两个孤岛一个在西部末端节点21附近一个在东部末端节点16附近。两个孤岛失去主供电源节点负荷全部由移动储能支撑。此时如果没有储能这些负荷只能全部切断。我在代码里生成故障场景时用branch_status矩阵表示每个时段该支路是否投运。台风过程中故障支路从第2时段开始断开第8时段开始逐步修复。这个动态过程很重要因为移动储能的动态调度要考虑“哪些线路检修完成后可以恢复主网供电”如果线路恢复了储能车就可以离开那一片区域去支援其他位置。之前我看到有些复现代码把故障集合固定成整个T时段都断开这样太保守也抹掉了移动储能“动态响应”的精髓。5.2 结果分析与恢复曲线仿真结束后我主要看三张图每个时段的系统总切负荷量曲线移动储能车在24小时内的位置轨迹用节点编号作为纵轴重点节点孤岛节点电压恢复情况。我实测的结果是预布局让储能车在第一时段就出现在接近孤岛中枢的位置而从不做预布局时开始第二时段才从节点1出发的基准模型对比累计失负荷降低约35%-50%。而且有意思的是动态调度中储能车并不是死守一个节点它会在孤岛内先给末端重负荷节点供电等到该节点电压稳定后再转移到另一个负荷较重的节点。这种“巡检式”路径正是移动储能区别于固定储能的价值。如果画切负荷曲线还能看到明显的阶梯下降故障发生时切负荷猛然上升储能接入后曲线明显回落再到线路修复后切负荷降为零。这个曲线就是论文里常说的“韧性曲线”它横轴是时间纵轴是系统性能。韧性指标可以用曲线的下包络面积或恢复斜率来量化比如AUC越低韧性越好。5.3 对比实验怎么做才公平复现一套代码只跑一个方案没有说服力。至少要跑三个对照模型无储能方案极端事件后完全依赖电网自身恢复这是基准下限固定储能方案储能车只能停在预设固定节点不允许时空转移模拟普通固定储能预布局动态调度方案本文的两阶段优化模型。在同样的故障场景、同样的负荷曲线、同样的储能容量下三种方案的总切负荷会有明显差距。特别提醒固定储能方案里储能车的位置如果选得不好效果可能跟无储能方案差不多如果你在对比论文里看到了“移动储能比固定储能提升XX%”一定要留意固定储能最优站址是否经过优化。如果固定储能站址也是随机给定那对比就不够公平。我在对比时习惯把移动储能预布局得到的初始位置直接作为固定储能的位置再去优化充放电这样才真正量化“移动性”带来的增益。实测偏差大概在10%-20%之间这个比例跟系统拓扑、故障位置强相关。建议你写论文时多做几组故障场景不要只挑一个好看的结果。6. 常见问题与排查技巧6.1 潮流不收敛或电压越限却看不到错误最常遇到的现象是模型有解但恢复后的孤岛电压严重偏低节点电压下限约束根本没起作用。原因通常只有一个——你把U变量当成了电压幅值并在约束里写成U(j) 0.95但实际U是电压平方所以必须写U(j) 0.95^2。另外线性DistFlow忽略了电压降落的二次项在重负荷孤岛中会偏乐观实际电压可能比计算值还要低一点。因此要在约束里留一定裕度例如把下限提高到0.97^2而不是0.95^2。这样虽然保守一点但能防止储能车“看似可行、实际上供电质量不合格”的假结果。6.2 移动储能在两个节点之间“瞬移”这是我最常被问到的bug。表现是结果里储能车t时刻在节点10t1时刻跑到节点20完全无视移动时间。根本原因是你没有把“移动距离需要时间”这件事建模成强约束。很多代码只写了loc(i,t)loc(j,t1) mov(i,j,t)这类弱约束但没限制移动期间不能出现在其他节点求解器就会强行让同一辆车在多个节点之间同时成立用二进制变量“伪造”路径。排查方法很简单画出每辆MESS的节点位置轨迹如果相邻时段节点编号跳变超过允许移动距离说明约束模型漏了。6.3 求解器报错或内存不足YALMIP调用Gurobi时最常见的报错是No suitable solver这是因为YALMIP认为你的模型包含非线性项。检查目标函数或约束里是否有u*P这类0-1和连续变量的乘积。出现这种乘积必须线性化。例如u * Pch可以化为一个大M约束[ Pch \le M \cdot u, \quad Pch \ge -M \cdot u ]如果模型确实线性但求解器还是报不适用就用ops sdpsettings(solver,gurobi,verbose,0)明确指定求解器。另外当二进制变量很多时内存不足经常由“跨场景展开”引起。如果场景数超过10建议不要一次性生成所有场景的约束而是用循环生成并求解每个场景再汇总目标值。6.4 结果太理想或太差怎么判断模型正确性我复现这类代码时有一个屡试不爽的验证思路先把移动储能数量设为0跑一个“纯配网失电”场景得到的是所有负荷被切除的上界再把移动储能放在故障中心节点固定不动跑一个“储能满功率放电忽略移动时间”的场景得到的是理想下界。实际预布局动态调度的结果应该落在这两个界之间并比“固定储能最优解”更好。如果跑出来的累计失负荷比无储能还高基本可以断定模型约束写错了尤其是储能车根本没接入节点或者discharge和charge同时非零被惩罚抵消。另外还有一个容易被忽略的问题SoC的初值。灾害发生前移动储能车通常是满电或半满电状态。如果你把初值设成30%那调度效果天然就差。可以做一组灵敏度分析从20%到100%扫描SOC初始值观察恢复曲线变化这也是论文里的常规内容。6.5 复现过程中几个值得留一笔的经验第一做韧性仿真前先把IEEE33节点的普通潮流跑通并和Matpower结果逐节点对比电压。没有这个基准后面所有优化结果都不可信。第二故障场景不要只给“断哪些线路”还要给“断线的时间窗”。把故障集合定义成二值矩阵会让编程方便很多。第三移动储能移动次数不能全靠目标函数惩罚建议直接加约束“每辆车移动次数不超过K次”否则求解器可能为了把一丁点负荷恢复就安排储能车到处乱跑结果既难解释也不现实。最后分享一个我亲测有效的调试技巧先用固定储能跑通整个模型框架再把移动逻辑逐条加上去。比如先忽略移动时间只允许储能车在相邻时段变节点验证结果稳定后再加入移动耗时和移动次数限制。这样可以避免“一上来就是完整双层模型出错都不知道去哪查”的窘境。代码能跑出合理结果后再回头梳理理论模型你会发现两阶段优化其实没有想象中那么高不可攀。整套复现项目做下来最值钱的不是那一堆公式而是你真的把“一个储能车从一个节点到另一个节点、期间不能放电、到了之后立刻参与保电”这种物理过程在Matlab里改成了求解器听得懂的语言。这个能力才是以后面对更复杂配电网韧性问题时真正能复用到底的东西。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进