ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

配电网台风故障建模与场景生成:从风速场到韧性评估

配电网台风故障建模与场景生成:从风速场到韧性评估

台风天里,配电网最让人头疼的不是“一条线路故障”,而是几十条线路在几个小时内接连跳闸、倒杆、断线,故障之间还互相牵连。传统的随机故障假设,到了台风场景下基本失效,因为故障不是独立的,而是被同一个台风风场“牵着走”。这也是我搭建这套基于33节点配电网的台风故障建模与场景生成流程的初衷:把台风路径、风速场、元件故障概率串起来,用蒙特卡洛方法生成有时空相关性的故障场景,再把故障特征直接映射到抢修排序、网络重构和孤岛划分这些应急响应策略上。

这套流程用Matlab实现,规模不大但逻辑闭环完整。如果你是做配电网韧性评估、应急调度优化或者新能源背景下的灾害仿真,这篇文章可以帮你省下不少弯路。下面我把整个建模思路、核心代码逻辑和踩过的坑完整过一遍。

1. 项目要解决的问题与设计思路

1.1 台风故障为什么不能按“独立元件故障”来生成

我在初版方案里踩过这样一个坑:直接用固定的故障概率p,对每条支路做独立伯努利抽样,生成故障场景。比如33节点系统32条支路,设p=0.1,抽样出来的场景平均只有3条左右的故障支路。问题是,这些故障在空间上是均匀随机撒开的,而实际台风造成的故障画面完全不是这样——台风中心附近风速大,那里的支路故障概率会同时变高,形成明显的“故障聚集区”。独立抽样永远模拟不出“一个区域成片停电”的形态。

另一个问题是时间维度。台风不是静止的,它是移动的。路径扫过哪里,哪里的风速先起来,故障就先出现;等台风眼移到下一点,前一个区域的风速回落,故障概率也降下来,但该坏的已经坏了。也就是说,故障场景的生成必须是一个时序演化过程,不能只在某个时刻抽一次。这个理解直接影响后面的算法框架。

更深一层,群发故障带来的应急响应复杂度是单故障场景没法覆盖的。单故障时只需要隔离一个元件再恢复;但台风场景下多个故障并存,负荷失电可能是多条路径同时断开的结果,抢修还需要考虑“先修哪条路最划算”、联络开关能不能转供、局部区域能不能靠分布式电源形成孤岛。不做故障场景生成,后面这些优化决策都没有可靠的输入。

1.2 总体技术路线与方案选型

我最终采用的技术路线可以概括成六步:

  1. 构造台风路径(每小时的中心位置);
  2. 用风场模型计算33节点配电网每条支路位置处的风速;
  3. 通过元件脆弱性曲线把风速换算成支路故障概率;
  4. 按时间步进做蒙特卡洛抽样,生成故障-修复事件序列;
  5. 从场景中提取故障特征(位置、时序、失电负荷、恢复时间等);
  6. 将故障特征接入应急响应策略,并统计韧性指标。

算例选择上,我用了经典的33节点辐射状配电网。这个系统的母线数、支路数、联络开关位置都是公开的标准算例数据,总负荷大约3715kW加2300kvar,电压等级12.66kV,适合做教学和论文级别的演示。更关键的是它自带5条联络开关支路(可以合上形成转供路径),刚好满足重构和孤岛策略的演示需求。规模再大的系统,可视化不够直观,调试也繁琐;规模再小的,故障特征和响应策略跑不出区分度。

工具选用方面,Matlab的优势是矩阵计算和统计分布函数齐全。33节点系统计算一次辐射状潮流只需要毫秒级,批量生成1000个场景也不会超过几秒,完全够用。而且Matlab的绘图能力可以直接画出风场分布、故障时序图和恢复率曲线,对结果解读很有帮助。

2. 台风风场与元件故障概率建模

2.1 由台风路径算风场,落到每条支路上

台风路径我采用锚点插值的方式构造。设路径锚点坐标数组是(cx_anchor, cy_anchor),用interp1按时间插值到每个仿真小时,就能得到台风中心每小时的位置。这个方法简单、可复现,方便手动设计不同的台风走向,比如“从西南往东北扫过配电网中心”或“擦边而过”。

得到中心位置后,计算每条支路所在位置的风速。我这里用最经典的Rankine涡旋模型:

当 d <= Rmax 时:V = Vmax * d / Rmax 当 d > Rmax 时:V = Vmax * (Rmax / d)^0.5

其中d是支路位置到台风中心的距离,Rmax是最大风速半径,Vmax是台风最大风速。这个模型的物理含义很直观:从台风眼向外,风速先是线性增大到峰值,再向外指数衰减。用Matlab实现时,我会把每条支路的中点坐标作为计算点,避免整条线路长度带来的风速差异被忽略。

function V = windSpeedAtBranch(branch, cx, cy, Vmax, Rmax) dx = branch.x - cx; dy = branch.y - cy; d = sqrt(dx.^2 + dy.^2); V = zeros(size(d)); maskInner = d <= Rmax; V(maskInner) = Vmax .* d(maskInner) ./ Rmax; V(~maskInner) = Vmax .* (Rmax ./ d(~maskInner)).^0.5; end

这个风场模型是轴对称的,实际台风会有明显的不对称性和地形影响,更精细的研究可以用Holland模型或加入行星边界层的参数化方案。但我的建议是先把简化模型跑通全流程,再逐步替换风场内核,不要一上来就在气象模型里陷得太深。

这里有一个容易被忽略的细节:空间相关性不是靠复杂的Copula函数硬造出来的,而是由风场模型天然携带的。相邻的两条支路距离台风中心差不多远,风速就接近,故障概率也接近,于是故障场景中自然会出现空间聚集现象。这也是我把风场模型放在建模链路最前面的原因——先有物理相关性,才有统计相关性。

2.2 元件脆弱性曲线:杆塔、导线要分开建模

配电网在台风下的故障,主要来自两类元件:导线断线和杆塔倒伏。两者对风速的耐受能力不同,脆弱性曲线也应该分别设置。

我用的脆弱性曲线是分段线性形式:

V <= V0: pf = 0 V0 < V <= V1: pf = (V - V0) / (V1 - V0) V > V1: pf = 1

V0是故障起始风速,V1是完全失效风速。实际工程中,导线的设计风速通常低于杆塔,因为导线跨度大、风振效应明显,更容易断线。我常用的参数是:

元件类型V0 (m/s)V1 (m/s)说明
导线2238风速超过设计值后开始断线
杆塔2848杆塔结构更抗风,失效阈值更高

这样的两段线性模型虽然粗糙,但足以体现“低风速不坏、高风速必坏”的基本物理规律。想做更严格的分析,可以用正态积分或IEC标准推荐的脆弱性函数形式,但参数估计需要历史灾损数据支撑,对大多数研究场景来说线性形式已经够用了。

function pf = fragileCurve(V, V0, V1) pf = zeros(size(V)); pf(V <= V0) = 0; mask = V > V0 & V < V1; pf(mask) = (V(mask) - V0) / (V1 - V0); pf(V >= V1) = 1; end

元件脆弱性建模时有三个必须注意的点。第一,不要把故障概率的阈值参数设得太低,否则抽样时基本所有支路都会故障,生成的场景失去区分度,后面的应急响应策略也看不出差异。第二,V0和V1要与台风设计强度匹配,比如Vmax只有30m/s的台风,就不该让V1=38m/s的导线大量故障,否则场景失真。第三,如果研究目标中包含“风雨耦合”或“树木倒伏”,需要在脆弱性曲线上叠加修正因子,比如降雨量提高导线故障概率的偏移量。

3. 故障场景生成算法与Matlab实现细节

3.1 时序递推:风场在动,故障在累积,修复也在进行

整个场景生成采用时间步进的方式。我一般把总时长设为24小时,步长1小时,这样既能覆盖台风从登录到过境的主要过程,又能和应急调度的时间颗粒度对接。每个时间步内做三件事:

  1. 更新台风中心位置,重新计算全系统支路风速;
  2. 对每条未故障支路,用当前风速算故障概率,然后做伯努利抽样,判断是否新发生故障;
  3. 对已故障支路,刷新修复剩余时间,达到修复时长后恢复。

修复时间的采样我这里用对数正态分布,均值为6小时,标准差2小时。之所以用对数正态,是因为修复时间有长尾特征——大部分故障能在几个小时内处理完,但总有少数复杂故障会拖到十几小时以上,这在台风抢修里非常常见。

场景生成时,算法会给每条支路维护四个字段:是否故障、故障发生时刻、修复开始时刻、修复剩余时间。同时用一个事件列表记录每条支路的故障和恢复事件,方便后续绘制恢复率曲线。

function events = generateScenario(branch, typhoon, params) nBr = length(branch); nT = params.horizon; failState = zeros(nBr, 1); failTime = zeros(nBr, 1); repairLeft = zeros(nBr, 1); events = []; rng(params.seed + params.scenIdx); % 每个场景不同种子 for t = 1:nT V = windSpeedAtBranch(branch, typhoon.cx(t), typhoon.cy(t), typhoon.Vmax(t), typhoon.Rmax(t)); pf = fragileCurve(V, params.V0_branch, params.V1_branch); u = rand(nBr, 1); newFaults = find(u < pf & failState == 0); for k = newFaults' failState(k) = 1; failTime(k) = t; repairLeft(k) = lognrnd(params.mu_r, params.sigma_r); events = [events; k, t, 1]; end repairLeft = max(0, repairLeft - params.dt); recovered = find(repairLeft == 0 & failState == 1); if ~isempty(recovered) failState(recovered) = 0; events = [events; recovered, t * ones(length(recovered), 1), zeros(length(recovered), 1)]; end end end

性能方面有个很关键的处理:在进入场景循环之前,先对33节点系统的每个负荷节点做一次上游路径搜索,把“节点到根节点的支路编号序列”预存下来。之后判断某个节点是否失电,只需要查它上游路径里是否有任一支路处于故障状态即可。不要在每个场景里反复做连通性搜索,那样1000个场景的耗时会被放大很多倍。

3.2 失电负荷与可转供负荷的定量计算

判断失电负荷不能只看故障支路本身,还要看拓扑结构。例如支路1-2故障,那么节点2及其下游的所有负荷全部停电;但如果15号支路故障,它下游的节点可能因为联络开关的转供路径恢复供电,情况就不一样。

我的简化处理分两级:

第一级,直接失电判断。节点k的上游路径中,只要有一条支路故障,就认为该节点直接失电。

第二级,可转供判断。对直接失电的节点,检查是否存在一条由联络开关构成的备用路径,使它能通过另一条馈线恢复供电。33节点系统常用的5条联络支路是:8-21、9-15、12-22、18-33、25-29。判断可转供时,需要同时满足:备用路径与主网连通、备用路径上无故障、变压器容量和线路容量不越限。

function lostLoad = evalLoadLoss(branch, failState, nodeUpstream, loadData, linkBranches) nNode = length(loadData); lostLoad = 0; for i = 1:nNode upstream = nodeUpstream{i}; if any(failState(upstream)) % 直接失电,先按不可转供处理 lostLoad = lostLoad + loadData(i); % 可进一步判断联络转供 if hasBackupPath(i, failState, linkBranches) lostLoad = lostLoad - loadData(i); end end end end

严格的可转供判断需要通过潮流计算校验约束,我这里给的是一个工程近似,用来快速评估场景严重度。如果想要更精确,可以在判断候选转供路径后,用前推回代法跑一次潮流,检查节点电压和支路电流是否越限。

3.3 场景统计指标怎么输出

一次蒙特卡洛仿真会生成成百上千个场景,每个场景都是一个故障-恢复事件序列。我通常会从三个角度做统计:

第一个是故障规模分布。统计每个场景的故障支路数、同时故障峰值、总故障持续时间,画成直方图后能直观看出“台风过境时系统最坏情况有多严重”。

第二个是失电负荷时序曲线。把所有场景在同一时刻的失电负荷取平均,得到期望失电负荷曲线;取95%分位数,得到“较坏情形”曲线。这条曲线是后面应急响应策略比较的核心参照。

第三个是综合韧性指标。最常用的是用户平均停电时间SAIDI和用户平均停电频率SAIFI,但我更推荐加一个“韧性损失面积”指标,定义为1减去恢复率函数在时间轴上的积分。这个指标直观反映了台风过程中系统性能损失的总量,不同应急策略的差异一眼就能看出来。

4. 故障特征如何引入配电网应急响应

4.1 从故障场景里提取哪些故障特征

应急响应策略要能“看见”故障场景的具体性质,不能只拿一个总数。我通常从每个场景中提取以下特征:

特征维度具体内容在应急响应中的用途
空间位置故障支路编号及上下游关系确定隔离范围和可转供区域
时间信息故障发生时刻、预计修复时长决定抢修派单顺序和资源分配
失电负荷量直接失电负荷、可转供负荷、不可转供负荷评估严重度,决定响应等级
负荷重要性一、二级重要负荷比例孤岛划分时优先保障的对象
拓扑关联度故障支路是否处于关键割集位置判断是否触发重构和孤岛策略

故障特征的价值在于让应急响应不再是“一刀切”地启动预案,而是根据实际故障画面选择策略组合。比如某个场景中故障支路都在馈线末端,失电负荷小,那就不需要大规模重构;如果有一条支路处在主干线中间位置,导致下游一大片负荷失电,就必须快速投入抢修和转供。

4.2 故障特征到三种应急策略的映射

我针对33节点系统设计了三种响应策略的组合,按优先级从高到低安排:

第一层,网络重构。故障发生后先判断哪些直接失电负荷可以通过联络开关转供。转供的本质是改变配电网的拓扑结构,用健康馈线去带原本失电的负荷。此时需要枚举或启发式搜索联络开关的开合组合,同时强制保证系统保持辐射状结构,不允许合环运行。33节点系统只有5条联络开关,组合数有限,用穷举法也能压住计算量。

第二层,孤岛划分。对于联络开关也无法转供的失电区域,如果配电网内配置了分布式电源或储能,可以在故障隔离点处主动解列,形成孤岛,优先恢复孤岛内的一部分重要负荷。这一步需要注意孤岛内的功率平衡和电压约束,分布式电源容量不足时不能强行带全部负荷。

第三层,抢修排序。在所有可恢复措施都用完后,剩下的失电负荷只能等故障支路修复。抢修资源的分配需要按故障特征排序。我使用的排序权重是:

优先级权重 W_k = 边际可恢复负荷量 / 预计修复时长

这里“边际可恢复负荷量”是指第k条故障支路修复后能新增恢复的负荷总量。直观理解就是:一条修复时间短但能恢复大量负荷的故障支路,应该排在修复时间长且影响小的支路前面。这个权重把故障的空间位置(影响范围)和时间信息(修复时长)同时考虑进来了,比单纯按故障时间先后排单要合理得多。

4.3 应急响应效果的量化对比

接入应急响应策略后,场景生成的结果就不再只是“讲故事”,而是变成了策略评估的输入。我是这样做的:对同一个故障场景集合,分别跑“只抢修不重构”、“抢修+重构”、“抢修+重构+孤岛”三组策略,统计每组下的失电负荷时序曲线和韧性损失面积指标。

实际操作中我明显看到:加了重构后,失电负荷峰值和总损失面积都能下降一到两成;再加孤岛策略,重要负荷的恢复率会显著提升,虽然总失电负荷的改善不一定很明显,但“保重点”的效果非常好。这个对比结果正好印证了当初做故障特征提取的必要性——不同策略发挥作用的场景特征不同,有的策略在故障集中时效果最好,有的策略在面对长修复时长的故障时更有优势。

5. 仿真配置、常见坑与调参建议

5.1 一组可复现的仿真参数

我用的一组默认参数如下,直接在Matlab里设置即可复现:

参数取值说明
仿真时长24小时步长1小时
台风最大风速Vmax35 m/s可随路径分段变化
最大风速半径Rmax15 km空间尺度要与配电网范围匹配
导线脆弱性阈值V0=22, V1=38 m/s分段线性曲线
杆塔脆弱性阈值V0=28, V1=48 m/s分段线性曲线
修复时间分布对数正态,均值6h,标准差2h长尾特性
场景数500需要更高精度可加到1000
随机种子固定seed=42保证可复现

在这个配置下,500个场景的运行时间在Matlab里大约十几秒到几十秒,主要耗时取决于是否做潮流校验。如果只做拓扑级失电评估,速度很快。

5.2 我已踩过的四个坑

第一个坑是脆弱性阈值设得太低,导致场景里几乎所有支路都故障。台风Vmax取35m/s,导线V0取20、V1取30,结果每条支路的故障概率都在0.3以上,500个场景全是全网瘫痪,研究完全失去意义。后来我按“V0接近设计风速、V1留足余量”的原则重新取值,才得到有区分度的故障场景分布。

第二个坑是修复时间对数正态参数没调好。均值6小时、方差太大会出现某些场景里一条支路修复时间超过48小时的长尾,这在实际台风抢修里极少见。后来我把标准差压到2小时,并且对采样值做了上限裁剪,比如最多不超过24小时,使恢复曲线看起来更接近真实。

第三个坑是重构策略没有校验辐射状约束。我最初把5条联络开关全部合上,以为储能恢复最多,结果某条支路潮流越限,很多负荷反而受影响。之后我把辐射状约束和线路容量约束都加到重构搜索里,才得到合理的结果。记住:配电网重构不是把所有联络线都合上就完了,合环运行是禁区。

第四个坑是随机种子不固定。我早期做策略对比时,每组策略都重新生成Fault场景,结果策略差异和随机噪声混在一起,指标波动很大,根本看不出规律。后来我固定基座场景集,所有策略在完全相同的场景集上比较,结论才稳定下来。这是做策略对比最容易忽略的细节,一定要先固化场景集再跑策略。

5.3 后续扩展与实用建议

这套流程的扩展空间很大。如果要做更实际的研究,可以往三个方向延伸。

第一,风场模型升级。把Rankine轴对称模型替换成Holland模型,加入台风移动速度和边界层摩擦的影响,使风速场更接近真实观测。升级时保持接口不变,只替换windSpeedAtBranch函数内部实现即可。

第二,场景约简。蒙特卡洛生成的500个场景里有很多相似画面,可以先用聚类方法选出代表性场景,再用于后续优化调度,能大幅压缩计算时间。我在做应急响应策略的枚举优化时就是这样处理的。

第三,融入抢修队伍的交通时间。严格来说,抢修资源调度需要考虑故障点之间的路程,而不是只看修复时间。可以把车辆路径问题加进来,让场景生成结果直接驱动调度优化算法,形成“场景-特征-调度”的完整闭环。

我个人在实际操作中的体会是:这套流程里最耗精力的往往不是算法本身,而是“气象模型和电网模型的粒度对齐”。气象数据通常是公里网格、小时级的,而配电网关心的是母线节点、分钟级的动态,两边数据粒度不一致时,过渡和插值方法的选择会直接影响结果。建议先把整条链路用简化模型跑通,再逐步精确化,不要一上来就追求风场和脆弱性模型的高精度,否则光是参数标定就能耗掉大半时间。

最后一个实用建议:台风故障场景生成这种随机性很强的代码,务必从一开始就养成固定随机种子的习惯。我自己的项目里专门建了一个随机数管理函数,每个场景都基于唯一的种子编号,确保场景集可以完全复现。否则后续做策略对比时,你会发现“算法改进”带来的提升可能只是随机波动,白折腾几周时间。

RELATED READING

延伸阅读

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