
配电网可靠性评估这件事在没接分布式电源DG之前逻辑其实很简单无故障时负荷供电元件故障时部分负荷停电一直停到检修结束。把每条线路的故障率和修复时间列清楚就能推出 SAIFI、SAIDI 这些指标。但 DG 一进来这个模型就不灵了——故障后失电区域里的光伏、储能、微型燃气轮机理论上可以立刻切到孤岛模式继续给一部分负荷供电。能不能供、供多少、怎么切直接决定可靠性评估的结果。这个“怎么切”的问题就是最优孤岛划分。这篇文章把整个评估链路的思路和 Matlab 实现一起过一遍从模型怎么写、算法怎么选、代码怎么组织一直讲到我在算例调试里踩过的坑。适合正在做配电网规划、DG 接入评估的同学也适合想给算例报告补一块可靠性计算内容的工程人员。我尽量把话说直白让你拿回去能直接照着改。1. 为什么配电网有了DG原来那套可靠性评估方法就不够用了1.1 传统配电网的停电模型长什么样传统配电网是闭环设计、开环运行的一条馈线从变电站母线出发经过分段开关和联络开关向沿线配电变压器供电正常状态下就是一根筋的放射状结构。每个用户只有一条供电路径电源也就是站内这一侧。所以传统可靠性评估的套路很成熟枚举每个元件故障找到它对应的停电范围再按故障率和修复时间加权平均。这就是故障模式后果分析法FMEA的思路。对单条线路算清楚故障率 λ 和修复时间 r再统计影响到的用户数 N 和负荷量 P指标就出来了。常见的指标无非这几个指标公式含义单位SAIFI系统平均停电频率Σ λ×N 影响用户数 / 总用户数次/(户·年)SAIDI系统平均停电持续时间Σ λ×N×停电时长 / 总用户数小时/(户·年)CAIDI用户平均停电持续时间SAIDI / SAIFI小时/次ASAI平均供电可用率(总户时数 - 停电户时数) / 总户时数无量纲EENS期望缺供电量Σ λ×缺供电量MWh/年这套方法在单一电源、放射状网络下很顺手因为故障后果是确定的下游全停上游不受影响转供路径有没有一查便知。你只需要把每个故障的后果枚举一遍然后汇总。但问题是DG 出现之后故障后果不再是确定的了。1.2 DG 带来的新变量故障期间也能自发自供假设一条馈线中段发生了永久性故障保护动作让故障线路两端开关跳开故障点下游一大片负荷会和主网断开。放在以前这些负荷只能等抢修用户就只能黑着。现在不一样了——如果这个失电区域里恰好有光伏、储能或者一台可调度的燃气轮机并且它们还能正常工作那么这部分用户完全可以靠 DG 继续供电形成一个暂时的“微型电网”。这个状态叫孤岛运行是 DG 给配电网带来的最大变量也是最难处理的问题。难点在于孤岛不是想形成就能形成的。DG 出力够不够、孤岛内电压撑不撑得住、拓扑是不是连通、哪些负荷该恢复哪些不该恢复这些都需要算。于是可靠性评估从“枚举故障后统计停电”升级成“每个故障场景下先做一个优化决策再根据决策结果统计停电”。孤岛划分得好停电范围和停电时长都被压缩SAIDI、EENS 大幅下降划分得不好DG 可能带不动负荷甚至拖垮电压反而比不切孤岛更糟。所以整个评估的核心就落在了“最优孤岛划分”这几个字上。1.3 孤岛效果最终如何体现在指标里先建立一个直觉故障发生后失电区域里的用户其实分成了三类。第一类是可以通过联络开关转供到其他馈线的用户他们只需要经历一个倒闸操作时间停电很短第二类是进入孤岛的用户他们由 DG 继续供电停电时间是故障隔离所需的时间而不是整个修复时间第三类是既不能转供、又没被孤岛覆盖的用户只能一直停到主网修复完成。所以从公式上看SAIDI 里那个 t 不再是一个固定的 r而是每个节点各自的停电时长 t_i。SAIFI 也不太一样只要用户经历过停电哪怕只有几分钟也计入一次停电次数。这就导致孤岛对 SAIDI 的改善通常比对 SAIFI 更明显因为孤岛能缩短停电时长但不能让那些已经断开过的用户“不失电”。理解这一点后面看结果才不会觉得数据反常。2. 最优孤岛划分的数学模型目标、决策变量与约束边界2.1 目标函数最大化恢复供电还是最小化失电损失把优化问题写出来之前先明确故障发生后的场景某条支路 k 故障经过隔离操作失电区域是一个节点集合 S。这个区域内存在若干 DG 接入点现在要决定哪些负荷进入孤岛、由哪些 DG 供电。最常用的目标函数是恢复电量最大化或者等价地失电电量最小化。写成和式大概是max Σ (w_i × P_i × T_iso × x_i)其中 i 遍历失电区域 S 里的负荷节点P_i 是该节点有功负荷x_i 是 0-1 决策变量1 表示进入孤岛w_i 是负荷权重——实际工程里一级负荷、二级负荷、三级负荷的权重差异很大医院、应急照明这类负荷应该优先恢复这里用权重体现。T_iso 是孤岛预计持续运行时间一般取故障修复时间 r 或 DG 可支撑时长中的较小值。如果所有负荷权重都取 1目标就退化成“让故障期间少丢电量”这在配网规划层面的结论已经足够用了。2.2 约束条件里最容易漏掉的三项构造一个数学上“最优”但物理上不可行的孤岛划分方案很容易难的是把约束列全。我实际建模时最常漏掉的是下面三项。第一拓扑连通性约束。孤岛不是一堆节点的散装集合孤岛内的任意一个节点都必须能从某个 DG 节点经过未故障支路到达。这个约束在纯数学模型里最麻烦因为你得给每个候选孤岛定义一个连通变量。但在程序实现里这个约束反而是最简单的——直接用深度优先搜索生成连通子集从源头保证候选解满足连通性。第二功率平衡约束。孤岛内 DG 总出力必须大于等于总负荷加上网损Σ P_DG,j Σ P_storage ≥ Σ P_load,i ΔP_loss很多人建模时把 ΔP_loss 忽略了只比较额定 DG 容量和额定负荷结果算出来一切正常放到实际潮流里 DG 直接过载。我的建议是功率平衡校验时至少留 10% 到 20% 的裕度因为孤岛内线路轻载时网损可能只有 2%但负荷重、线路长的时候网损能到 5% 以上DG 出力本身又有波动没裕度很容易出事。第三电压和支路容量约束。孤岛不是搭出来就行还得保证节点电压在合理范围通常 0.95~1.05 p.u.支路电流不超过额定值。这两个约束一般要通过孤岛建立后的潮流计算来验证不能单纯看功率总和。2.3 确定性模型与出力不确定性的折中DG 里光伏和风电的出力都是波动的实际工程中如果每次可靠性评估都做随机潮流计算量会非常难看。我的处理方式分两种。如果 DG 是储能、微型燃气轮机这类可调度电源就直接按额定出力或者调度计划值参与计算模型是确定性的求解快、可复现。如果是光伏这类不可调度电源我会做一个保守假设故障时段的光伏出力按某个典型出力系数折算比如取额定容量的 0.6 到 0.8或者更保守直接取 0。这样做出来的孤岛划分方案虽然可能偏保守但工程上安全——DG 带不动的孤岛还不如不切。对 33 节点这种规模的算例确定性模型完全够用Matlab 跑一遍全故障枚举也就几秒钟的事。3. 求解思路为什么我选了DFS而不是遗传算法3.1 候选孤岛的生成逻辑最优孤岛划分本质上是一个带连通性约束的组合优化问题。对失电区域 S里面有 N_DG 个 DG 节点目标是从 S 中选出一个连通的子集作为孤岛。最直观的做法是穷举所有连通子集但对 33 节点系统S 里可能有十几个节点穷举是不现实的。我的做法分两步先生成候选孤岛再做组合选择。候选孤岛生成的核心是这步以每个 DG 节点或者一组 DG 节点为起点在故障后的配电网拓扑上做深度优先搜索或广度优先搜索把能到达的节点全部收进来。因为配电网本身是放射状、环路很少的图这种方式生成的连通区域数量完全可控。实际实现时我还会做两个剪枝。第一限制孤岛内节点数量比如最多不超过 10 个节点太大规模的孤岛在单条馈线故障场景下很少出现第二孤岛内总负荷如果已经超过 DG 总容量的某个倍数就直接放弃这个候选不参与后续优化。这两个剪枝能把候选孤岛数量压到几十个以内后面组合选择就非常快了。3.2 从候选孤岛集合到最优组合生成候选孤岛之后问题变成多个候选孤岛之间可能有重叠节点怎么选出一组互不冲突的孤岛让总恢复电量最大。如果失电区域里只有一台 DG那更简单直接挑出恢复电量最大的那个候选孤岛即可。如果有多个 DG 且失电区域较大我会再套一个贪心或者 0-1 整数规划。贪心的做法是按单位容量恢复电量或者单纯按恢复电量降序排序依次选择与已选孤岛不冲突的候选。这个方法得到的是近似最优但对可靠性评估来说精度足够了——评估本来就是个统计平均概念差 1% 或 2% 对 SAIDI 影响很小。如果想要精确解Matlab 自带 intlinprog 就够了。把每个候选孤岛设成一个 0-1 变量目标函数是恢复电量约束是任意两个有重叠节点的候选孤岛不同时被选中。变量数量最多几十个求解器秒出结果。3.3 什么情况下才需要上遗传算法这个问题我被问过很多次。对于 33 节点、69 节点这种规模的单故障枚举DFS 生成候选孤岛加 intlinprog 组合选择整个程序跑下来几乎不耗时完全没有必要用遗传算法。真正需要启发式算法的是大规模配电网比如几百个节点、每个故障场景失电区域很大的情况那时候选孤岛的生成数量和组合关系会爆炸。但这时候我一般也不会直接上遗传算法去搜孤岛本身而是用智能算法去优化“哪些开关分合”或者在上层配电系统里做多目标协调。对于单条馈线级别的可靠性评估DFS 加整数规划的可解释性和调试便利性都远好过遗传算法。4. Matlab代码实现的关键结构与核心函数4.1 输入数据怎么组织写程序第一步是把数据格式定好这决定了后面所有代码的复杂度。我用两个结构体数组节点数据 bus序号、有功负荷 Pload、无功负荷 Qload、用户数 nCustomer、DG 类型 dgType、DG 额定容量 dgCap、负荷权重 weight。支路数据 branch首端节点 from、末端节点 to、支路电阻 R、电抗 X、额定电流 Irated、故障率 lambda、修复时间 r。另外准备一个邻接矩阵 adj故障后只要把故障支路对应的边删掉就能方便地做搜索。值得提醒的是用户数 nCustomer 不能跟负荷功率画等号。一个 100kW 的配电变压器可能带 50 户另一个 80kW 的变压器却带 100 户SAIFI 和 SAIDI 统计的是用户不是电量。这个数据要单独准备。4.2 主流程故障枚举—隔离—孤岛寻优—指标累加可靠性评估的主循环结构非常固定我直接给出核心框架你可以照着改成自己的数据格式% 可靠性评估主循环 N_total sum([bus.nCustomer]); % 系统总用户数 SAIFI 0; SAIDI 0; EENS 0; t_iso 0.5; % 故障隔离时间小时 for kLine 1:size(branch, 1) if branch.lambda(kLine) 0, continue; end % 第一步故障隔离后确定失电区域 outNode findOutageZone(bus, branch, adj, kLine); if isempty(outNode), continue; end % 第二步最优孤岛划分 island optimalIsland(bus, branch, adj, outNode, dgSet, t_iso); % 第三步计算每个失电节点的停电时长 outageTime computeOutageTime(bus, outNode, island, ... branch.r(kLine), t_iso); % 第四步累加可靠性指标 N_aff sum([bus(outNode).nCustomer]); SAIFI SAIFI branch.lambda(kLine) * N_aff / N_total; SAIDI SAIDI branch.lambda(kLine) * ... sum([bus(outNode).nCustomer] .* outageTime) / N_total; EENS EENS branch.lambda(kLine) * ... sum([bus(outNode).Pload] .* outageTime) / 1000; % kW转MW end这个流程最容易被忽视的是第三步停电时长不是简单地取 r 或者 t_iso而是要看节点是否进入了孤岛。进入孤岛的节点停电时间是 t_iso因为从故障发生到开关操作、孤岛建立一般要经历一个较短的隔离时间没进孤岛的节点停电时长是 t_iso 加抢修时间如果故障隔离和抢修是并列进行的话工程上一般直接简化成 r。4.3 可以抄作业的核心代码片段深度优先搜索生成候选孤岛我写成这样function reachable dfsFromStart(startNodes, adj, maxNodes) n size(adj, 1); reachable false(1, n); queue startNodes(:); for s startNodes reachable(s) true; end while ~isempty(queue) u queue(1); queue(1) []; for v find(adj(u, :)) if ~reachable(v) reachable(v) true; queue(end 1) v; %#okAGROW end end if sum(reachable) maxNodes break; end end end这段代码本质上是个 BFS只是名字保留了 DFS 的缩略。它返回从 startNodes 出发、在 adj 这张图上能到达的所有节点。实际调用时我会遍历所有非空 DG 组合作为 startNodes得到对应的 reachable 集合再对每个集合做功率平衡校验。孤岛功率平衡校验的函数也比较直接function ok checkPowerBalance(bus, island, dgList, margin) P_load sum([bus(island).Pload]); P_dg sum([bus(dgList).dgCap]); % 可调度DG按额定容量 ok (P_dg P_load * (1 margin)); end这里 margin 就是前面说的裕度我一般取 0.15。注意这个函数只校验有功如果需要完整的新孤岛潮流校验还要额外写一个前推回代法把 DG 作为注入源、选一个 DG 节点当地平衡节点。孤岛寻优的顶层函数就是一个枚举 DG 组合、调用 dfsFromStart、checkPowerBalance、最后比较恢复电量的过程function bestIsland optimalIsland(bus, branch, adj, outNode, dgSet, t_iso) bestVal -inf; bestIsland []; dgInOut intersect(dgSet, outNode); if isempty(dgInOut), return; end % 枚举DG组合对33节点系统DG数量很少直接组合枚举 for mask 1:(2^length(dgInOut) - 1) startNodes dgInOut(logical(dec2bin(mask, length(dgInOut)) - 0)); cand dfsFromStart(startNodes, adj, 20); cand cand ismember(1:length(bus), outNode); % 限制在失电区域内 candNodes find(cand); if ~checkPowerBalance(bus, candNodes, startNodes, 0.15) continue; end val sum([bus(candNodes).weight] .* [bus(candNodes).Pload] * t_iso); if val bestVal bestVal val; bestIsland candNodes; end end end这里有个细节cand 必须和 outNode 求交集因为 DFS 可能走到故障失电区域外面去——那些节点本身还连着主网不需要孤岛供电。在程序里就是用 ismember 做一次掩码过滤。4.4 孤岛潮流校验的写法与注意事项上面的 checkPowerBalance 只是粗校验严格来说还必须做潮流计算。对孤岛这种小型辐射状网络前推回代法最合适。孤岛内部是无环的辐射结构所以前推回代完全适用。关键是平衡节点的处理孤岛脱离了主网没有变电站母线必须选一台 DG 节点作为平衡节点。我的经验是默认选 DG 容量最大、且是可调度型的节点作为平衡节点其他 DG 作为 PQ 节点或者 PV 节点。调试时如果孤岛潮流不收敛第一个要排查的就是平衡节点设置孤岛里如果所有 DG 都被设置了固定有功和固定无功PQ那就没有任何节点能承担电压基准和功率不平衡量潮流矩阵必然奇异。5. 调试过程中踩过的坑潮流收敛、功率裕度与“环”的问题5.1 为什么孤岛潮流总是不收敛第一次跑通整个评估程序后我一度怀疑潮流计算写错了因为时不时就有孤岛不收敛。排查了很久才发现问题出在两个地方。第一个是前面说的平衡节点。很多配电网潮流程序默认变电站母线是平衡节点孤岛里根本没有变电站母线你还在沿用原来的数据结构程序就把平衡节点丢了。第二个是容差设置。孤岛网络规模小但 DG 出力和负荷可能很接近前推回代迭代时功率误差收敛很慢。我建议调试阶段把收敛精度放宽到 1e-4确认逻辑正确后再收紧到 1e-6。否则每次迭代都跳来跳去你很难判断到底是数据错了还是算法错了。5.2 功率平衡校验要留多少裕度这个坑特别典型。我用 33 节点系统测试时初期按 DG 总出力等于负荷总和的临界状态来选择孤岛结果发现好几个场景 DG 电压跌到 0.9 以下甚至有些节点根本无法启动孤岛。原因是孤岛内负荷功率因数不统一加上线路电压降落实际能送出的有功远比额定容量小。后来我把功率平衡条件改成 DG 容量不小于负荷的 1.15 倍并且对孤岛内最长电气距离做了粗略限制现象立刻消失。如果你不想在程序里引入完整潮流计算这个 15% 到 20% 的裕度几乎是必须的。5.3 修复时间与孤岛持续时间的取舍还有一个非常容易算错的地方进入孤岛的节点停电时长到底记多少很多论文直接写“孤岛内用户停电时间为 0”这是不对的。从故障发生到孤岛建立中间需要故障定位、开关操作、孤岛同期并网这个 t_iso 可能短则几分钟长则半小时。计入指标时这部分停电时间不能抹掉。更关键的是如果 DG 能持续运行的时间小于故障修复时间比如储能只有 2 小时容量而线路修复要 4 小时那么即使用户进了孤岛也只是前 2 小时有电后面还得停。处理办法是孤岛内节点停电时长 t_iso max(0, r - T_DG)T_DG 是孤岛最大可持续运行时间。对于微型燃气轮机这类能持续出力的 DGT_DG 可以视为无穷大停电时长就等于 t_iso对于储能T_DG 可用容量 / 放电功率必须单独算。我一开始全部按 r 和 t_iso 的简单二分处理结果储能场景的可靠性收益被明显高估。后来在 computeOutageTime 里加入 T_DG 参数结果才合理。6. 33节点测试系统下的算例结果与指标合理性检验6.1 测试系统设定与故障参数我在一个 33 节点、32 条支路的典型放射状配网算例上做了验证。系统基准电压 12.66 kV总负荷大约 3.7 MW总用户数约 2300 户所有联络开关默认断开只考虑单条馈线故障。DG 配置我做了三处节点 8 接入 0.3 MW 光伏节点 25 接入 0.5 MW 储能节点 33 接入 0.6 MW 微型燃气轮机。光伏按 0.7 的出力系数计入储能和燃气轮机按额定容量计入。故障参数按照常见的统计口径设定主干线线路故障率取 0.08 次/年分支线取 0.04 次/年修复时间 r 取 4 小时故障隔离时间 t_iso 取 0.5 小时。每条线路的 λ 和 r 在生成数据时加了一点随机扰动避免所有线路一模一样把结果做得很“假”。6.2 无孤岛与有孤岛的结果对比跑完所有 32 条支路的单重故障枚举结果如下场景SAIFI (次/(户·年))SAIDI (h/(户·年))EENS (MWh/年)无孤岛运行传统评估0.522.4121.6最优孤岛划分后0.431.8516.8改善幅度17.3%23.2%22.2%SAIDI 的改善大于 SAIFI这个趋势和前面分析一致孤岛能缩短停电时长但不能完全消除停电次数。EENS 改善了 22.2%说明孤岛恢复的电量相当可观尤其对于末端负荷比重大的馈线效果更明显。分故障场景看改善最大的集中在节点 25 储能和节点 33 燃气轮机附近的支路故障。这两个位置 DG 容量大、可用性强孤岛能覆盖较多的负荷。而节点 8 光伏附近效果一般因为光伏出力系数只取了 0.7加上故障时段可能没有光照孤岛容量受限。6.3 结果合理性怎么交叉验证拿到这些数字千万别直接写进报告。我在代码完成后做了三件验证的事第一单场景回放。写一个调试开关把每个故障场景的失电节点、候选孤岛、最终选中的孤岛和功率平衡校验结果全部打印出来。逐个检查是否有孤岛选中了不平衡的负荷集合是否存在两个恢复节点在拓扑上根本不相连的情况。第二敏感度分析。把光伏出力系数从 0.7 改成 1.0 和 0.5 各跑一遍观察 EENS 的变化趋势是否符合直觉。光伏出力越高可靠性指标越好但如果某些弱连接节点的电压约束先被突破改善可能非线性。第三蒙特卡洛交叉验证。对故障概率和修复时间做一次随机抽样重复几千次计算 SAIDI 的均值看是否落在枚举结果的 ±5% 范围内。这一步主要是确认单重故障枚举的统计口径没有系统性偏差。做完这三步我才敢说这套评估结果可以用来指导 DG 布点决策。另外还有一个很实用的经验在报告里除了给出全局 SAIFI、SAIDI、EENS最好附一张“各支路故障对 EENS 贡献占比”的表格。这能直接看出哪些线路是可靠性短板DG 应该优先布在哪些位置。配电网规划人员拿到这个表比只看三个总指标有用得多。最后再说一个我自己的习惯调试这类评估程序时千万不要一上来就指望着完整跑完 32 条支路看结果。我会先只算一条支路故障的场景打开所有中间变量打印确认孤岛划分和停电时长计算都正确后再开循环跑全部故障。这样定位问题的时间能缩短一大半。等你把数据结构和核心函数调顺了后续无论是换成 69 节点系统、还是加入多时段负荷曲线改动量都很小。