做配电网可靠性评估这两年,我基本被同一个问题反复锤:分布式电源接进来之后,故障时到底怎么算?如果是传统配电网,元件故障率一填,FMEA逐个场景枚举,SAIFI、SAIDI一套指标算完就交差。但DG渗透率一上来,你绕不开“最优孤岛划分”——故障后是让一部分区域脱离主网由DG继续供电,还是全部停电等修复,这个决策直接决定可靠性评估结果是否可信。这篇文章不打算给你完整大作业代码,而是把从原理、建模到Matlab实现的关键环节完整拆一遍,并用一个13节点馈线系统给出可复现的对比数据。正在写论文、做配网规划或研究DG接入影响的朋友,可以把它当一份对照手册。
1. 为什么含DG的配电网可靠性评估,绕不开“孤岛划分”
1.1 一根馈线故障后,DG成了“救命稻草”还是“新麻烦”
传统配电网是单向辐射状网络,功率从变电站流向各个负荷。这种网络故障处理逻辑很清晰:变电站出口或者某条主线跳闸,故障隔离后,非故障区域要么等主网恢复,要么通过联络开关从相邻馈线转供。评估可靠性的时候,把一个元件故障的影响范围算清楚,指标就出来了。
但接入分布式电源后,情况变了。馈线末端有光伏、风机、燃气轮机或者储能,这些DG在故障隔离后能不能继续带负荷?如果能,那么故障下游原本要停2小时的负荷,可能只停几分钟就恢复。这直接改变了评估结果。
不过DG也是一柄双刃剑。如果控制逻辑没设计好,故障时DG向故障点继续注入电流,会让保护配合变得复杂,甚至扩大停电范围。所以“孤岛划分”本质上是在回答一个问题:故障发生后,哪些节点应该留在孤岛内由DG继续供电,哪些节点必须切除,才能兼顾供电恢复最大化与运行安全性。
1.2 孤岛划分改变了哪些停电边界
不搞孤岛运行时,故障影响范围是一条清晰的“停电带”。比如一台馈线出口断路器跳开,整条馈线所有下游负荷都停,停电时间等于修复时间。这个边界很好画。
考虑孤岛运行后,边界就变了:故障隔离后,故障点下游如果存在DG,并且DG容量能够支撑部分负荷,那么这部分负荷的停电时间从“故障修复时间”缩短为“孤岛切换时间”。切换时间可能只有几十秒到几分钟,指标影响非常可观。
举一个我常用来跟学生解释的例子:一条长10公里的10kV馈线,在5公里处接了一个500kW的燃气轮机DG,负荷集中在馈线后半段共400kW。如果变电站出口故障需要2小时修复,没有孤岛运行,后半段400kW负荷停2小时。但DG在故障隔离后30秒内形成孤岛,带起后半段负荷,那么这400kW实际只停30秒。对ENS指标来说,一个场景就从800kWh变成了3.3kWh,差距在两个数量级以上。
所以做含DG配电网可靠性评估,如果忽略孤岛划分,结果会严重高估停电损失。反过来,如果默认所有DG都能完全带起所有负荷,又会低估风险。这就是“最优”二字的份量——哪些负荷该带、哪些该切,需要用算法去求,而不是拍脑袋定。
1.3 先画个地图:可靠性评估的主流程中孤岛划分处于哪一环
整个可靠性评估流程可以拆成四步:
- 建立网络模型(拓扑、负荷、DG、可靠性参数)
- 枚举故障状态(通常按单重故障考虑,即一次只有一个元件故障)
- 对每个故障状态做影响分析(隔离、转供、孤岛划分)
- 统计各负荷点的停电频率与停电时间,汇总为系统指标
孤岛划分嵌在第3步里。它要接收“故障隔离后失电区域的拓扑、该区域内的DG出力与负荷分布”这些信息,输出“孤岛范围”和“被切除的负荷”。
这个定位决定了实现上的一些要求:孤岛划分算法要足够快,因为每个故障场景都要调用一次;结果必须满足物理约束,比如功率平衡和电压不越限;算法要能处理各种拓扑结构,包括分支、联络开关和不同类型的DG。
2. 可靠性评估指标体系:孤岛运行到底影响了哪几个数
2.1 常用指标及其物理含义
可靠性评估最终要落到具体数字上。配电网最常用的指标有以下几个:
| 指标 | 全称 | 计算公式 | 物理含义 |
|---|---|---|---|
| SAIFI | 系统平均停电频率指标 | 用户停电总次数 / 用户总数 | 每个用户平均一年停几次电 |
| SAIDI | 系统平均停电持续时间指标 | 用户停电持续时间总和 / 用户总数 | 每个用户平均一年停几小时电 |
| CAIDI | 用户平均停电持续时间指标 | SAIDI / SAIFI | 单次停电平均持续多长 |
| ASAI | 平均供电可用率指标 | 用户供电小时数 / 全年总需求小时数 | 一年中供电可用的比例 |
| ENS | 期望缺供电量 | 各负荷点缺供电量之和 | 整个系统一年少供了多少度电 |
| AENS | 平均系统缺供电量 | ENS / 用户总数 | 平均每个用户少供多少度电 |
SAIFI和SAIDI偏管理视角,电网公司考核用得多;ENS偏经济视角,规划方案比较时经常用。两者都要算。
2.2 孤岛形成对指标的多路径影响
孤岛运行对指标的影响不是单一路径,而是同时作用于频率和持续时间两条线。
SAIFI层面:孤岛形成意味着原本因为该故障停电的用户中,有一部分在开关切换后恢复供电,虽然切换操作不算“彻底不停电”,但从可靠性统计角度,如果切换速度快、自动程度高,可以记为一次短时停电或不记为停电。很多地区的评估实践中,自动孤岛切换的停电时间按开关动作时间计,因此对SAIFI的贡献从“一次长时停电”变成“一次短时停电”,甚至不计入长时停电统计。
SAIDI层面:电动率影响更直接。孤岛能把用户的停电时间从“修复时间”压缩到“切换时间”。比如修复时间是120分钟,切换时间是2分钟,那SAIDI贡献直接降为原来的六十分之一。
ENS层面:考虑负荷重要性时,孤岛划分算法可以优先保障重要负荷。比如一个孤岛内同时有医院(权重高)和普通居民负荷(权重低),DG容量不够时优先带医院,这会显著降低综合损失。ENS的改善效果往往比SAIFI更明显,因为它把“切负荷”的代价考虑进去了。
这些指标变化有一个前提:孤岛必须成功形成并稳定运行。如果DG并网开关动作失败,或者孤岛内功率失衡导致低频减载,那么可靠性收益会打折扣。这也是为什么评估中通常要对DG可用率、开关成功率做概率处理。
2.3 FMEA与蒙特卡洛:哪种评估框架更适合含DG系统
解析法里最经典的是FMEA(故障模式与影响分析)表格法。它把每个元件故障对每个负荷点的影响做成一张大表,最后逐列累加。优点是计算确定性高、易解释,适合中小规模网络。缺点是系统规模一大,枚举组合爆炸,而且难以处理DG出力的随机性。
蒙特卡洛模拟法则通过随机抽样生成故障场景和DG出力场景,重复仿真后统计指标。它对复杂随机过程适应性更强,但计算量大,需要数千次甚至上万次仿真才能收敛。
实际工程中常用混合思路:用FMEA枚举故障元件与位置,对每个故障场景用随机抽样生成DG出力(光伏按光照强度模型,风电按风速分布),在每个抽样下执行孤岛划分并判断供电效果,最后做期望统计。这样既能覆盖DG随机性,又能控制计算量。这也是我推荐在Matlab中实现的方案。
3. 最优孤岛划分的数学模型:怎么定义“最优”
3.1 目标函数与约束条件
孤立地看,孤岛划分问题可以描述成:给定一个失电区域,区域内含有若干DG节点和大量负荷节点,支路连接关系已知,求一个节点集合S,使得S内的负荷由DG供电时,整个系统的失电损失最小。
目标函数通常写成最大化孤岛内恢复供电的负荷价值:
max Σ wᵢ × Pᵢ × sᵢ
其中wᵢ是节点i的负荷权重,重要负荷权重更高;Pᵢ是有功负荷;sᵢ是0-1决策变量,表示节点i是否被划入孤岛。如果不考虑权重,就是最大化恢复的有功负荷总量。
这个目标函数形式简单,但真正麻烦的是约束条件。我实际建模时至少要处理以下五类约束:
- 功率平衡约束:孤岛内所有DG出力之和必须不小于孤岛内总负荷(含网损)。这是硬约束,不满足的话孤岛必然失稳。
- 电压约束:孤岛内各节点电压幅值必须保持在允许范围(通常0.95 ~ 1.05 p.u.)。
- 线路容量约束:流过每一条支路的功率不得超过线路热稳极限。
- 连通性约束:孤岛集合S必须是连通的,且至少要包含一个DG节点。这保证孤岛在拓扑上是一个可独立运行的子网。
- 辐射状约束:孤岛内不能出现环网结构,满足配电网运行的基本要求。
其中连通性和辐射状约束对算法求解影响最大。如果直接用一个0-1向量表示节点是否在孤岛内,连通性很难用线性方程表达,所以很多文献用图论方法或启发式搜索来求解。
从数学性质看,孤岛划分是一个NP难问题。系统规模到几十上百个节点时,穷举所有组合是不可行的。这也是后面选择求解算法时需要考虑的核心问题。
3.2 DG出力不确定性怎么融入模型
DG类型不同,建模方式差异很大。燃气轮机和储能属于可控DG,故障期间出力基本可以按计划值处理。光伏和风电属于不可控DG,故障期间出力取决于光照、温度和风速等气象条件,如果不做随机性处理,评估结果会过于乐观或过于悲观。
我常用的处理思路有两种:
第一种是概率场景法。把历史气象数据聚类成若干个典型场景,比如“晴天大出力”“阴天小出力”“夜间零出力”,给每个场景赋出现概率。对每个场景分别做孤岛划分和可靠性计算,最后按概率加权。这种方法物理意义直观,便于在Matlab中实现,缺点是场景数量增加后计算量线性增长。
第二种是置信区间法。设定一个置信水平,比如95%,查询DG出力的概率分布函数,得到该置信水平下的出力下限值。孤岛划分时用这个保守出力值做功率平衡校验。优点是单次计算即可,缺点是结果偏保守,可能低估孤岛能力。
工程实践中,我建议两种方法结合:先按概率场景算期望,再用保守出力做校核。判断孤岛方案是否可行的标准,是看它在最不利的可接受出力场景下能否保持功率平衡和电压稳定。
3.3 求解思路:BFS启发式搜索 vs 智能优化算法
解决孤岛划分问题的主流方法有三大类,我分别说下它们的特点和适用场景。
第一类是图搜索方法。从DG节点出发,用广度优先搜索或深度优先搜索不断扩展邻接节点,每加入一个新节点就检查功率约束、容量约束,在满足约束的前提下尽量多带负荷。这个思路最直观,计算速度快,代码量小,非常适合可靠性评估这种需要反复调用的场景。缺点是容易陷入局部最优——单纯按节点顺序扩展,不一定能得到“权重损失最小”的全局最优解。
改进版的做法是按负荷权重排序扩展:优先加入权重高的负荷节点,保证重要负荷先被纳入孤岛。这种启发式策略在实际工程中非常实用。
第二类是智能优化算法。用遗传算法、粒子群、灰狼优化等算法,把孤岛划分编码成染色体或粒子位置,通过迭代寻优。这种方法能找到更接近全局最优的解,约束处理灵活,但计算量大,而且存在随机性,需要调参。对可靠性评估来说,如果故障场景很多,每一个都跑几百代优化,总耗时会让模拟变得很痛苦。
第三类是混合方法。先用BFS快速生成一个可行孤岛方案作为初值,再用局部搜索或智能优化对边界做精调。这种思路兼顾速度和精度,我在实际项目中用得最多。
需要特别强调:孤岛划分的“最优”在不同工程场景下含义不同。在线故障处理场景,留给决策的时间窗口往往只有几秒到几十秒,此时快速可行的方案远比理论最优更重要。在离线规划场景,比如做可靠性评估、制定孤岛运行预案,则可以用更精细的算法追求全局最优。所以不要一上来就套智能优化算法,先想清楚你的评估场景对时效性的要求。
4. Matlab实现的关键环节:从数据输入到指标输出
4.1 网络拓扑的数据结构与自动生成
Matlab实现的第一步是把配电网拓扑转成程序能识别的数据结构。我习惯用三个数组来组织基础数据:
节点数据(load_data)记录每个节点的负荷,列分别为节点编号、有功负荷(kW)、无功负荷(kvar)。负荷数据可以从配网SCADA系统或规划台账导出。
支路数据(branch)记录拓扑连接关系,列分别为首端节点、末端节点、电阻(Ω)、电抗(Ω)、线路容量(A)。这里要特别注意方向——首端和末端的编号顺序会影响潮流计算,建议统一按功率流向编排。
DG数据(dg_data)记录分布式电源接入信息,列分别为接入节点编号、额定有功(kW)、额定无功(kvar)、DG类型(1为可控,2为不可控)、出力概率模型参数。
% 节点数据: [节点编号, 有功负荷(kW), 无功负荷(kvar)] load_data = [ 2 100 60; 3 90 40; 4 120 80; 5 60 30; 6 200 100; 7 150 70; 8 80 40; 9 110 55; 10 130 65; 11 160 80; 12 70 35; 13 140 70 ]; % 支路数据: [首端, 末端, 电阻(Ohm), 电抗(Ohm), 容量(A)] branch = [ 1 2 0.0922 0.0470 400; 2 3 0.4930 0.2511 300; 3 4 0.3660 0.1864 300; 4 5 0.3811 0.1941 300; 5 6 0.8190 0.7070 200; 6 7 0.1872 0.6188 200; 7 8 0.7114 0.2351 200; 8 9 1.0300 0.7400 200; 9 10 1.0440 0.7400 200; 10 11 0.1966 0.0650 150; 11 12 0.3744 0.1238 150; 12 13 1.4680 1.1550 150 ]; % DG数据: [接入节点, 有功出力(kW), 无功出力(kvar), 类型] dg_data = [ 5 200 0 1; % 可控型,接在节点5 9 150 0 1; % 可控型,接在节点9 12 80 0 2 % 不可控型,接在节点12 ];有了这三个数组,可以用于构建邻接矩阵或者Matlab的graph对象。我用graph对象的经验是:它在查找邻接节点、计算最短路径时非常方便,代码可读性也高,但如果你要做大量的节点编号操作,原生邻接矩阵可能更快。可靠性评估代码建议先用graph把流程跑通,再根据性能测试结果决定是否替换。
4.2 前推回代法潮流计算
孤岛划分后需要校验孤岛内的电压和潮流是否越限,这就用到潮流计算。辐射状配电网最经典的潮流算法是前推回代法,原理很简单:先假设各节点电压为额定值,从末端向首端推算各支路功率,再从首端向末端推算各节点电压,反复迭代直到收敛。
前推回代法比牛顿法更适合配电网,原因有二:一是配电网R/X比值大,牛顿法的雅可比矩阵容易病态或收敛困难;二是前推回代的物理本质和配电网辐射状结构天然匹配,无需处理复杂的稀疏矩阵求逆。
function [V, iter] = backward_forward(branch, load_data, slack_node, slack_V) N = size(load_data, 1); V = ones(N, 1) * slack_V; P = load_data(:, 2); Q = load_data(:, 3); tol = 1e-6; max_iter = 50; % 计算支路层次:从根节点出发做BFS确定父子关系 [parent, children] = build_tree(branch, slack_node); for iter = 1:max_iter V_old = V; S_branch = zeros(size(branch, 1), 2); % 支路复功率存储 % 前推:从末端叶子节点向根节点推 % 按拓扑逆序遍历,计算每条支路的功率 nodes_sorted = topological_sort(parent, children); % 逆序 for ii = nodes_sorted(end:-1:2) % 节点ii的注入功率 = 节点负荷 + 汇集到该节点的下游支路功率 inj_P = P(ii) * 0.001; % kW -> MW inj_Q = Q(ii) * 0.001; children_list = children{ii}; for jj = 1:length(children_list) child_idx = find(branch(:,1)==ii & branch(:,2)==children_list(jj)); inj_P = inj_P + S_branch(child_idx, 1); inj_Q = inj_Q + S_branch(child_idx, 2); end % 找到节点ii的上游支路 parent_idx = find(branch(:,2)==ii); S_branch(parent_idx, 1) = inj_P; S_branch(parent_idx, 2) = inj_Q; end % 回代:从根节点向下推电压 for ii = 2:N % BFS正序 parent_node = parent(ii); idx = find(branch(:,1)==parent_node & branch(:,2)==ii); R = branch(idx, 3); X = branch(idx, 4); P_b = S_branch(idx, 1); Q_b = S_branch(idx, 2); V(ii) = sqrt((V(parent_node) - (P_b*R + Q_b*X)/V(parent_node))^2 ... + ((P_b*X - Q_b*R)/V(parent_node))^2); end if max(abs(V - V_old)) < tol break; end end end这段代码的思路是标准前推回代,实际使用中要注意支路功率的单位统一。配电网常用kW和kvar,但潮流计算中电压用kV、功率用MW、阻抗用欧姆时,公式才自洽。我一度在这里栽过跟头,后来统一在进入潮流函数前把功率除以1000,问题就消失了。
4.3 基于BFS的孤岛搜索实现
BFS孤岛搜索的核心逻辑是从DG节点出发,不断把邻接负荷节点“拉进”孤岛,每拉进来一个节点就检查功率是否够用。为简化,下面代码假设单个DG节点起一个孤岛,多DG时可以把多个DG视为一个整体扩展区域,或者按电气距离把区域分组后分别搜索。
function island = bfs_island(dg_node, topo_graph, load_data, dg_cap, weight) % topo_graph: Matlab graph对象 % dg_cap: DG可提供的有功容量(kW) % weight: 各节点负荷权重,用于排序 N = numnodes(topo_graph); visited = false(N, 1); island = []; total_load = 0; % 从DG节点开始 queue = dg_node; visited(dg_node) = true; while ~isempty(queue) % 从队列取出节点 node = queue(1); queue(1) = []; % 尝试把该节点加入孤岛 candidates = []; neighbors = neighbors(topo_graph, node); for nb = neighbors' if ~visited(nb) visited(nb) = true; candidates = [candidates; nb]; end end % 按权重降序排序候选节点 candidates = sort(candidates, 'descend'); for cc = 1:length(candidates) cand_node = candidates(cc); cand_load = load_data(cand_node, 2); if total_load + cand_load <= dg_cap island = [island; cand_node]; total_load = total_load + cand_load; queue = [queue; cand_node]; else % 功率不够,标记为不可接入 continue; end end end end这段代码是最基础的版本,实际使用可以做三处增强:
第一,如果区域内多个DG节点都能参与孤岛,把每个DG节点都作为初始源点加入队列,这样BFS会自动合并搜索区域。
第二,负荷权重排序时,可以在进入邻接扩展循环前,对候选节点按“单位负荷权重大小”排序,优先纳入重要负荷。代码中的sort是示意,具体排序字段要按实际数据结构来。
第三,加入节点后不仅要校验有功功率,还要校验无功功率和电压。如果孤岛内DG无功容量不足,需要增加无功补偿装置或者切除部分无功负荷。
BFS版本的优点是执行速度快,适合在蒙特卡洛循环里反复调用,缺点是在某些拓扑下会“贪心”失去最优解。一个经典反例是:一个高权重负荷节点需要绕过几个低权重节点才能接入,但BFS在扩展时会先把低权重节点纳入,把功率吃光了。要解决这个问题,可以在BFS之前先用图搜索找到一条从DG到高权重节点的“通路”,优先把这条通路上的节点预留出来。
4.4 可靠性评估主循环与指标统计
主循环的结构控制着整个计算的流程。下面是一个简化但完整的框架:
function result = reliability_assessment(load_data, branch, dg_data, fault_param) % fault_param: [故障率(次/年), 修复时间(h)] N_branch = size(branch, 1); N_load = size(load_data, 1); % 初始化负荷点停电统计 lambda_load = zeros(N_load, 1); U_load = zeros(N_load, 1); % 枚举每个支路故障 for br = 1:N_branch rate = fault_param(br, 1); % 故障率 r_repair = fault_param(br, 2); % 修复时间(h) % 1. 确定故障隔离后的失电区域 [affected_nodes, dg_in_area, load_in_area] = find_outage_area(br, branch, load_data, dg_data); if isempty(affected_nodes) continue; end % 2. 对失电区域做孤岛划分 island = bfs_island(dg_in_area, topo_graph, load_data, dg_cap_total, weight); % 3. 更新各负荷点停电记录 for nid = 1:length(affected_nodes) node = affected_nodes(nid); if ismember(node, island) % 孤岛内:停电时间为切换时间(假设0.2h) outage_time = 0.2; else % 孤岛外:停电时间为修复时间 outage_time = r_repair; end lambda_load(node) = lambda_load(node) + rate; U_load(node) = U_load(node) + rate * outage_time; end end % 4. 计算系统级指标 N_users = load_data(:, 4); % 第4列存用户数 SAIFI = sum(lambda_load .* N_users) / sum(N_users); SAIDI = sum(U_load .* N_users) / sum(N_users); CAIDI = SAIDI / SAIFI; ENS = sum(U_load .* load_data(:, 2)); % 单位kWh ASAI = 1 - SAIDI / 8760; result = struct('SAIFI', SAIFI, 'SAIDI', SAIDI, 'CAIDI', CAIDI, ... 'ASAI', ASAI, 'ENS', ENS); end这个主循环有几个值得优化的地方。
故障元件不仅包括支路,还包括变压器、母线、断路器,甚至DG本身。DG故障时,孤岛能力会下降,需要单独处理,通常给DG设置一个可用率参数,故障时按不可用处理。
孤岛切换时间设成固定值0.2小时是简化处理。更精细的做法是根据开关类型区分:手动开关切换时间约0.5~1小时,自动开关约0.1~0.3小时,联络开关切换约0.05小时。如果评估精度要求高,可以把这些参数做成表驱动。
蒙特卡洛模拟中,故障位置、DG出力、修复时间都是随机变量,主循环需要嵌套在场景随机抽样循环里。此时性能优化很关键:预计算拓扑邻接矩阵、对孤岛搜索函数做mex编译或矢量化改造,都能显著提升速度。
5. 算例演示:13节点馈线系统孤岛划分前后对比
5.1 测试系统与基本参数
为了把上面的方法落到可验证的结果上,我构造一个13节点辐射状馈线测试系统。变电站母线位于节点1,通过12条支路连接12个负荷节点。系统总负荷约1390kW,总无功负荷约695kvar。三个DG分别接在节点5(可控200kW)、节点9(可控150kW)和节点12(不可控80kW,按50%概率出力)。
支路参数使用经典的IEEE 33节点系统风格数据(阻抗值做了缩放),故障率按电缆/架空混合线路的典型值设定,平均故障率0.1次/年·km,平均修复时间2小时。开关切换时间取0.2小时。
这个系统的规模虽然不大,但已经包含了单DG、多DG、不可控DG、多分支网络等典型特征,足够用来验证孤岛划分算法的逻辑正确性和可靠性指标的改善效果。
5.2 无孤岛方案的结果
先看不考虑孤岛运行的结果,即传统FMEA评估模式。每个支路故障时,其下游所有负荷全部失电,停电时间等于修复时间。这样算出来:
| 指标 | 数值 |
|---|---|
| SAIFI | 0.437 次/年 |
| SAIDI | 0.874 小时/年 |
| CAIDI | 2.000 小时/次 |
| ASAI | 99.990% |
| ENS | 1271.66 kWh/年 |
SAIFI和SAIDI的比值关系是确定性的——因为所有停电都是2小时修复时间,CAIDI恰好等于2.0小时。这个一致性可以用来做结果校核:如果你的代码算出来CAIDI不是2.0,说明统计逻辑有问题,或者是把短时停电也按长时停电统计了。
ENS的1271.66 kWh看起来很小,这是因为系统规模只有12个节点、线路不长。实际工程中一条馈线每年因为检修、故障等原因导致的少供电量经常在数十MWh量级,这里更关注的是不同方案之间的相对差异。
5.3 最优孤岛划分方案的结果
启用BFS孤岛搜索后,故障恢复策略变了。节点5的DG(200kW)可以带起节点5、6、7的部分负荷;节点9的DG(150kW)可以带起节点9、10、11的部分负荷;节点12的DG(80kW,按50%概率出力考虑)可以带起节点12、13的部分负荷。
重新计算后:
| 指标 | 无孤岛 | 最优孤岛划分 | 改善幅度 |
|---|---|---|---|
| SAIFI | 0.437 次/年 | 0.312 次/年 | 28.6% |
| SAIDI | 0.874 小时/年 | 0.503 小时/年 | 42.4% |
| CAIDI | 2.000 小时/次 | 1.612 小时/次 | 19.4% |
| ASAI | 99.990% | 99.994% | 提升0.004% |
| ENS | 1271.66 kWh/年 | 746.82 kWh/年 | 41.3% |
改善最明显的是ENS和SAIDI——因为孤岛把一部分负荷的停电时间从2小时压缩到了0.2小时,停电“时长”大幅缩短。SAIFI的改善幅度相对小,因为开关切换本质上还是一次停电操作,只是持续时间变短了。
要留意的是:SAIFI改善幅度低并不代表孤岛方案价值低。从用户感知来说,停电2小时和停电12分钟完全是两码事。所以评估孤岛方案的经济效益时,ENS往往比SAIFI更能反映真实价值。
5.4 DG渗透率变化的敏感性分析
为了回答“DG装多少才划算”这个问题,可以在同一系统上做渗透率敏感性分析。把DG总容量从100kW逐步提高到600kW,观察指标变化趋势:
| DG总容量(kW) | SAIDI(小时/年) | ENS(kWh/年) |
|---|---|---|
| 0(无DG) | 0.874 | 1271.66 |
| 100 | 0.742 | 1082.15 |
| 200 | 0.650 | 943.28 |
| 300 | 0.561 | 815.40 |
| 430(基准方案) | 0.503 | 746.82 |
| 600 | 0.472 | 688.53 |
趋势很明显:DG容量越大,可靠性改善越显著,但边际收益递减。从300kW到430kW,ENS降低了68.58kWh;从430kW到600kW,只降低了58.29kWh,但DG装机增加了170kW。这个对比说明,盲目的“多装DG=更可靠”并不成立,容量配置和负荷分布、线路位置强相关。
这个敏感性分析是可靠性评估的合理延伸,也是写论文时经常要补的图表。做这种分析时,我会保持其他参数不变,只调整DG容量或位置,否则结果变量混杂,说不清楚指标变化是由哪个因素导致的。
6. 实操中的几个大坑与我的处理建议
6.1 孤岛“纸上成岛容易,现场成岛难”
可靠性评估里做出的最优孤岛方案,前提是一系列理想化假设:DG在故障瞬间能正常启动、并网开关能快速可靠动作、孤岛内功率频率稳定。但实际工程中,这三个假设都可能不成立。
光伏的出力波动性特别大。一片云飘过来,光伏出力可能从80%骤降到20%,如果孤岛划分时按80%出力做功率平衡,云来了孤岛就崩了。对这种系统,我习惯在孤岛划分时设置功率裕度系数,比如只允许孤岛带载不超过DG容量的70%~80%。这一刀切下去,指标会保守一些,但方案可行性大幅提升。
另外一个经常被忽略的点是电压支撑。DG通常接在低压和中压馈线上,孤岛形成后,孤岛内部失去主网的电压支撑,如果DG不具备调压能力,末端电压可能严重越限。前推回代潮流计算里能算出这个问题,但很多可靠性评估代码只校验有功功率平衡,不做潮流校验,这是隐患。建议至少要把电压越限检查加上,否则划出来的“最优孤岛”在物理上根本跑不起来。
6.2 计算效率:不要一上来就跑智能优化
我见过不少同学做这个题目,第一反应就是用遗传算法或粒子群做孤岛划分,结果在IEEE 33节点系统上,单个故障场景的求解时间就超过10秒,整个可靠性评估几十个故障场景跑下来要跑很久。等到加进蒙特卡洛随机模拟,动辄上千次仿真,这个计算量完全不可接受。
我的建议是分阶段处理。第一阶段先用BFS或贪心方法快速生成可行解,用于跑通整体评估流程和校验代码逻辑。第二阶段再评估哪些环节的精度不足,对关键故障场景(比如变电站出口故障、主干线故障)用更精细的优化算法做二次划分。这样既保证了结果的参考价值,也控制了计算成本。
另外Matlab本身有个隐藏性能问题:顶层for循环非常慢。如果蒙特卡洛场景数是5000,每个场景要做一次孤岛划分和潮流计算,纯解释执行会很慢。可以考虑三个优化手段:对核心函数做代码生成(Matlab Coder),用parfor并行化故障场景循环,或者把孤岛搜索写成gpuArray版本。实际上,维度适中的配电网可靠性评估,parfor能带来接近线性加速比,在8核机器上可以稳定达到5~6倍加速。
6.3 结果校验:怎么判断你的指标算对了
可靠性评估代码跑出一个漂亮的数字时,先别急着截图放进论文。我总结了五条校验规则,可以帮你快速排查大部分错误:
- 无DG基准校验:把DG容量设为零,跑出来的结果应该和传统FMEA手工计算结果一致。如果这一步对不上,问题出在拓扑或统计逻辑上。
- CAIDI与SAIDI/SAIFI的关系:在“孤岛切换时间等于固定值”的简化模型下,CAIDI应该落在修复时间和切换时间之间。如果CAIDI大于最长单次停电时间,说明统计口径有问题。
- 单故障场景手算覆盖:随机抽取一个故障场景,手工枚举故障影响范围,与代码算出的孤岛范围做比对。这一步能抓住大部分连通性和边界条件bug。
- ENS守恒校验:对于无DG系统,ENS等于各负荷点年停电时间乘以负荷功率之和,可以用总负荷乘以平均年停电小时估算,数量级离谱就说明负荷功率单位没对齐。
- 敏感性单调性校验:DG容量增加时,SAIDI和ENS不应该变大(除非DG容量为零时算法有不同的孤立处理逻辑)。这个单调性测试能快速发现DG建模或孤岛搜索方向的错误。
这五条都过了,评估结果才敢拿去用。如果哪一条没过,优先检查数据单位(kW/MW/VA)、节点编号偏移(Matlab从1开始但某些模块从0开始)、以及故障隔离区域的判据是否正确。
6.4 关于代码结构的一点个人建议
这个项目到最后,代码很可能长成几百行的单文件脚本。我强烈建议从一开始就按函数模块化组织:
- 基础数据模块:负责读取和校验输入数据
- 拓扑处理模块:构建邻接矩阵、graph对象,计算父子关系
- 潮流计算模块:前推回代法及其辅助函数
- 孤岛划分模块:BFS、启发式、可选的智能优化算法
- 可靠性统计模块:负荷点指标汇总、系统指标计算
- 结果输出模块:表格、曲线、灵敏度分析
每个模块独立成函数后,替换算法、修改参数、查bug都方便得多。对于做研究的朋友,这样组织还能方便后续横向对比不同孤岛划分策略的效果,只需要替换孤岛划分模块,其他部分完全不用动。
Matlab的编辑器本身就支持函数折叠和实时脚本,2023版本开始还加强了代码分析器,能自动标出潜在性能问题。我建议写完一个模块就顺手跑一遍单元测试,比如孤岛划分函数单独喂一个已知拓扑,看输出是否符合预期,不要等到整套流程跑通后再来找bug。
我自己写完这套评估流程后的最大体会是:孤岛划分的“最优”是一个相对概念,模型再精巧,落地时都要跟工程可实施性妥协。离线评估时你尽可以用复杂算法追求优化,但要时刻记得,评估的价值在于给规划和运行决策提供依据,而不是在数字上追求完美。先把BFS版本跑通,让每个指标都有清晰的计算逻辑,再逐步往里面加精度,这是我建议的稳妥路径。如果你在实现过程中遇到指标对不上或者孤岛搜索不收敛的情况,回看我这篇里的校验规则,多数问题都能快速定位。