
做电力系统分析的人都知道短路电流是躲不开的一笔账。无论是设备选型、保护整定还是运行方式校核最终都要落到“这个故障点能出多大短路电流”上。以前在学校用手算节点一多立刻头皮发麻参加工作后用商业仿真软件又觉得黑箱感太强中间过程不透明。后来我养成了一个习惯关键工程场景里会用Matlab自己写一套短路电流计算程序既能把原理重新捋一遍也能随时加自己想要的输出项。这篇就聊聊我用Matlab编程计算短路电流的完整思路、程序骨架和踩过的坑。需要说明的是这套方法适合三类人一是刚接触电力系统分析、想用编程加深理解的学生二是做配电/输变电设计、需要快速校验短路电流的工程师三是想在公司内部搭一套轻量计算工具、但不想被商业软件授权绑死的开发者。文中的案例是一个虚构的小型配电系统参数做了脱敏处理但流程和真实计算一致。1. 短路电流计算的模型基础标幺值体系与戴维南等效1.1 为什么编程前要先确定建模尺度Matlab本身不关心你是用有名值还是标幺值但短路电流计算强烈建议用标幺值。原因有两个第一电力系统跨越多个电压等级变压器会把电压、电流、阻抗的单位搞得非常混乱有名值计算时很容易在电压等级换算上出错第二标幺值下所有发电机、变压器、线路的参数都在一个相对统一的量级上数值稳定性好程序调试时一眼就能看出哪个参数输错了。标幺值的基本关系是取基准容量 (S_B)通常取100 MVA或系统总容量不同电压等级取各自的基准电压 (U_B)通常取平均额定电压基准电流 (I_B S_B / (\sqrt{3} U_B))基准阻抗 (Z_B U_B^2 / S_B)。各元件的实际值除以对应的基准值就得到标幺值。在Matlab里我习惯把基准值统一写在程序头部用一个结构体保存% 基准值定义 S_B 100e6; % 基准容量100 MVA U_B_35 37e3; % 35 kV侧基准电压 U_B_10 10.5e3; % 10 kV侧基准电压 Z_B_35 U_B_35^2 / S_B; Z_B_10 U_B_10^2 / S_B; I_B_35 S_B / (sqrt(3) * U_B_35); I_B_10 S_B / (sqrt(3) * U_B_10);这里有个容易忽略的细节基准电压一定要用平均额定电压而不是设备额定电压。比如10 kV系统通常取10.5 kV35 kV系统取37 kV。如果直接拿10和35代入短路电流会差5%左右保护定值校验时这个误差不可接受。1.2 戴维南等效在短路计算中的角色三相对称短路计算的核心就是戴维南定理从故障点看进去系统可以等效为一个电压源串联一个阻抗。故障点的三相短路电流等于故障点正常运行电压除以等效阻抗。这个思想用Matlab实现非常自然把整个网络的节点导纳矩阵 (Y) 建立起来对故障点 (f) 求节点阻抗矩阵的对角元素 (Z_{ff})短路电流就是[ I_f \frac{U_f}{Z_{ff}} ]注意这里 (U_f) 是故障前该节点的电压工程上通常取1.0∠0°忽略负荷和潮流影响。如果你想算得更细可以把故障前潮流结果拿过来把该节点的电压幅值和相角代入但大多数短路计算场景下1.0的简化已经够用。1.3 对称分量法与三序网络不对称短路单相接地、两相短路、两相接地需要引入对称分量法。它的本质是把三相不对称量分解为正序、负序、零序三组对称量三组分量分别在三序网络中流动然后通过故障边界条件把三个序网连成复合序网。编程时最关键的一点是正序、负序、零序的参数不同。正序网络就是常规的潮流网络负序网络里发电机负序电抗通常不等于正序电抗但静态负荷元件线路、变压器的正序、负序阻抗近似相等零序网络的拓扑和参数与正序差异最大只有中性点接地且存在接地支路时才能构成零序通路。这些参数差异都要在数据组织时提前预留位置这也是程序容易出错的地方。2. Matlab程序整体框架从数据表驱动到故障模拟2.1 数据组织方式矩阵化输入我见过很多人把短路计算程序写成“一坨”脚本每个参数都定义成独立变量到最后自己都分不清哪个是哪个。实际项目里节点数量动不动几十个、上百个必须用数据表驱动的方式组织输入。我的做法是定义三个矩阵节点表记录节点编号、类型电源节点/负荷节点、正序电压基准值支路表记录支路两端节点、正序电阻电抗、零序电阻电抗、变压器变比和接线方式电源表记录发电机/系统等值电源接入节点、正序电抗、负序电抗、零序电抗。% 节点表 [节点编号, 类型(1电源/0负荷), 基准电压kV] nodes [ 1, 1, 37; 2, 0, 37; 3, 0, 10; ]; % 支路表 [起点, 终点, R1, X1, R0, X0, 变比, 是否变压器] lines [ 1, 2, 0.010, 0.085, 0.030, 0.255, 1.0, 0; 2, 3, 0.015, 0.120, 0.040, 0.360, 37/10.5, 1; ]; % 电源表 [接入节点, R1, X1, R2, X2, R0, X0] gens [ 1, 0.001, 0.080, 0.001, 0.060, 0.002, 0.050; ];数据表驱动的好处很多一是方便和设计图纸对接图纸上一个一个参数直接填进表格就行二是便于批量修改运行方式比如某个发电机检修直接把电源表里对应行去掉即可三是为后续GUI化或Excel导入留好了接口。我自己的经验是用Matlab做工程计算数据定义的时间通常占一半以上这个步骤不能省。2.2 程序主流程与模块划分短路计算程序可以拆成几个清晰的模块按顺序执行读入系统参数并归算标幺值构建正序、负序、零序节点导纳矩阵对故障点求各序阻抗或直接求节点阻抗矩阵对角元素根据故障类型计算短路电流输出有名值结果并格式化显示。模块划分的原则是每个function只干一件事方便单独测试。千万别把几百行代码全塞进一个文件里后续改一个参数都要翻半天。主流程的Matlab骨架大致是这样function [If, Vf] short_circuit(nodes, lines, gens, fault_node, fault_type) % 1. 参数归算略 % 2. 构建序网导纳矩阵 Y1 build_Y(nodes, lines, gens, positive); Y2 build_Y(nodes, lines, gens, negative); Y0 build_Y(nodes, lines, gens, zero); % 3. 计算故障点自阻抗 Zff1 get_self_impedance(Y1, fault_node); Zff2 get_self_impedance(Y2, fault_node); Zff0 get_self_impedance(Y0, fault_node); % 4. 按故障类型计算 switch fault_type case three_phase If 1.0 / Zff1; case single_phase If 3.0 / (Zff1 Zff2 Zff0); % ... 其他类型 end % 5. 输出有名值略 end2.3 为什么用导纳矩阵而不是阻抗矩阵很多教材喜欢从节点阻抗矩阵讲起因为 (Z_{ff}) 直接就是故障点自阻抗。但工程计算里直接构建阻抗矩阵并不方便阻抗矩阵是满阵节点数一多存储量爆炸而导纳矩阵高度稀疏构建规则也简单——支路导纳直接累加到对应位置就行。因此标准做法是先构建导纳矩阵 (Y)再通过求逆或因子分解得到 (Z_{ff})。Matlab里可以直接用inv(full(Y))小规模验证但真正工程规模的计算必须用稀疏矩阵的因子分解和三角求解后面我会单独讲这一块。3. 核心模块详解节点导纳矩阵构建与故障阻抗计算3.1 支路数据到导纳矩阵的组装节点导纳矩阵的组装规则并不复杂对角线元素是连接该节点的所有支路导纳之和非对角线元素是两节点间支路导纳的负值。变压器支路还需要按变比折算。我给出构建正序导纳矩阵的核心代码负序、零序只是参数取值不同结构完全一样function Y build_Y(nodes, lines, gens, seq) n size(nodes, 1); Y zeros(n, n); % 先用全矩阵工程上可改用sparse for k 1:size(lines, 1) n1 lines(k, 1); n2 lines(k, 2); r lines(k, 3); x lines(k, 4); z r 1i * x; y 1 / z; Y(n1, n1) Y(n1, n1) y; Y(n2, n2) Y(n2, n2) y; Y(n1, n2) Y(n1, n2) - y; Y(n2, n1) Y(n2, n1) - y; end % 电源节点追加电源支路导纳 for k 1:size(gens, 1) n gens(k, 1); switch seq case positive zg gens(k, 2) 1i * gens(k, 3); case negative zg gens(k, 4) 1i * gens(k, 5); case zero zg gens(k, 6) 1i * gens(k, 7); end Y(n, n) Y(n, n) 1 / zg; end end这里有个工程上非常重要的点变压器支路不能简单把短路阻抗折算到一侧就完事还要考虑变比对导纳矩阵的“非对称”影响。对于非标变比变压器需要在变压器支路两端分别乘以变比系数。否则计算出的短路电流在通过变压器时会出现明显的幅值和相位误差。我早年写程序时在这里栽过跟头后面会详细讲。3.2 故障点自阻抗算法稀疏矩阵求逆与因子分解的取舍有了节点导纳矩阵要求故障点自阻抗 (Z_{ff})最直接的方法是Z inv(Y); Zff Z(fault_node, fault_node);这个方法在小系统上没有任何问题节点数几十个秒出结果。但我劝你尽早养成用稀疏矩阵求解的习惯因为实际工程配网系统节点数动辄几百上千inv(full(Y))不仅慢数值稳定性也差。推荐的方案是Matlab的因子分解求解流程% 利用单位向量求解Zff列 Y_sparse sparse(Y); % 用单位向量e_f解 Y * Zcol e_f e_f sparse(ones(n,1)); % 注意这里矩阵求逆不是显式做而是用分解求解 Zcol Y_sparse \ e_f; Zff Zcol(fault_node);原理是节点阻抗矩阵的第 (f) 列等于节点导纳矩阵求逆后与单位向量 (e_f) 的乘积。因此只要解一次线性方程组就能得到整个 (Z_{ff}) 列向量而Matlab的\运算会自动选择适合稀疏矩阵的因子分解算法效率远高于显式求逆。这里想强调一个容易被忽略的细节如果要同时算多个故障点不必每次重新构建整个导纳矩阵。可以先对 (Y) 做一次LU因子分解然后对不同故障点反复回代速度快一个量级[L, U, P] lu(Y_sparse); for f fault_nodes e_f sparse(ones(n,1)); Zcol U \ (L \ (P * e_f)); Zff(f) Zcol(f); end3.3 三相短路电流的计算输出三相对称短路是最简单的情况也是其他所有故障类型的基础。三序网络中只涉及正序网络故障点短路电流[ \dot{I}_f^{(3)} \frac{\dot{U}f}{\dot{Z}{ff1}} ]其中 (\dot{U}_f) 为故障点正常运行电压标幺值通常取1.0∠0°。这个公式看起来简单但工程输出时要做的处理不少要把标幺值转换成有名值(I_f^{(有名)} I_f^{(标幺)} \times I_B)不同电压等级要取不同的基准电流通常还要计算短路容量 (S_f \sqrt{3} I_f U_B)用于校验开关设备的开断容量。我习惯用表格形式输出一目了然fprintf( 三相短路计算结果 \n); fprintf(故障点: 节点%d\n, fault_node); fprintf(正序自阻抗: %.4f j%.4f (标幺)\n, real(Zff1), imag(Zff1)); fprintf(短路电流: %.4f (标幺), %.2f kA (有名值)\n, abs(If_pu), abs(If_named)/1e3); fprintf(短路容量: %.2f MVA\n, S_f/1e6);4. 不对称短路的对称分量处理与程序分支设计4.1 序网络与复合序网不对称短路计算的关键是正确建立三序网络并在故障点把它们连接起来。工程上最常见的做法是“复合序网法”把正序、负序、零序网络在故障点处按照故障类型对应的边界条件串联或并联。这里我先给出三种基本不对称短路在故障点处的复合序网连接关系故障类型边界条件A相复合序网故障电流标幺式单相接地短路(\dot{I}_B0, \dot{I}_C0, \dot{U}_A0)正、负、零序串联(I_f^{(1)} \frac{3\dot{U}f}{\dot{Z}{\Sigma 1}\dot{Z}{\Sigma 2}\dot{Z}{\Sigma 0}})两相短路BC(\dot{I}_A0, \dot{U}_B\dot{U}_C)正、负序并联(I_f^{(2)} \frac{\sqrt{3}\dot{U}f}{\dot{Z}{\Sigma 1}\dot{Z}_{\Sigma 2}})两相接地短路BC(\dot{I}_A0, \dot{U}_B\dot{U}_C0)三序并联先算序电流再合成相电流这些公式里的 (\dot{Z}{\Sigma 1})、(\dot{Z}{\Sigma 2})、(\dot{Z}{\Sigma 0}) 分别是从故障点看进去的正、负、零序等效阻抗也就是我前面求的 (Z{ff1})、(Z_{ff2})、(Z_{ff0})。4.2 两相短路、两相接地短路、单相短路的公式实现在Matlab里实现不对称短路我建议先把三种序的自阻抗都算出来再按故障类型写分支。单相接地短路的程序分支case single_phase Zsum Zff1 Zff2 Zff0; If_seq 1.0 / Zsum; % 故障相的序电流 If 3.0 * If_seq; % 故障相电流这里有个很多人搞混的点单相接地故障电流公式里那个“3”不是凭空来的。它的推导逻辑是三序电流相等因为三序串联而故障相电流等于三序电流之和所以是 (3 \dot{I}_{seq})。程序里如果直接把分母写成 (Zff1 Zff2 Zff0) 而分子写3本质和我上面的写法一样只是省了一步。两相短路的分支case two_phase Zsum Zff1 Zff2; If_phase_BC sqrt(3) * 1.0 / Zsum; % 注意sqrt(3)系数注意这里的 (\sqrt{3}) 是线电流和相序电流之间的幅值关系不要丢掉。两相接地短路稍微复杂一些需要先算各序电流再合成故障相电流case two_phase_ground I1 1.0 / (Zff1 (Zff2 * Zff0) / (Zff2 Zff0)); I2 -I1 * Zff0 / (Zff2 Zff0); I0 -I1 * Zff2 / (Zff2 Zff0); % B、C相故障电流合成考虑120度相位差用复数算子a a exp(1i * 2 * pi / 3); If_B I0 a^2 * I1 a * I2; If_C I0 a * I1 a^2 * I2;这里用到了旋转因子 (a e^{j120^\circ})在Matlab里直接用exp(1i*2*pi/3)即可千万不要把 (120^\circ) 写成 (2\pi/3) 的度数形式否则相位全错。4.3 程序分支与结果汇总把各种故障类型的分支放进一个主函数后建议用switch而不是if-elseif的长链代码可读性更好也方便以后扩展。输出时除了各故障类型的短路电流我还会同时输出各序阻抗、短路容量便于和保护专业核对。其中有一个容易忽略的工程检查项单相接地短路电流与三相短路电流的大小关系。很多人直觉认为“单相接地肯定比三相小”实际上在零序阻抗很小比如变压器中性点直接接地且系统接地良好的情况下单相短路电流完全可能超过三相短路电流。程序跑出来数值后要依据 (Z_{ff0}) 的大小做合理性判断不要直接套用头脑里的经验。5. 算例验证用一个小型配电系统跑通全流程5.1 系统参数与Matlab输入为了验证程序我搭建了一个虚构的35 kV/10 kV两级配电系统。系统结构很简单节点135 kV母线接入系统等值电源正序阻抗 (Z_{s1} 0.001 j0.080)标幺负序阻抗 (0.001 j0.060)零序阻抗 (0.002 j0.050)节点235 kV母线与节点1通过双回线路连接节点310 kV母线经一台 (35/10.5) kV、短路阻抗 (0.015 j0.120)归算到高压侧的变压器供电。故障点预设为节点310 kV母线。Matlab输入数据如下clear; clc; % 基准值 S_B 100e6; U_B [37, 37, 10.5]; I_B S_B / (sqrt(3) * U_B); % 节点表 [编号, 类型, 基准电压kV] nodes [ 1, 1, 37; 2, 0, 37; 3, 0, 10; ]; % 支路表 [起点, 终点, R1, X1, R0, X0, 变比, 是否变压器] lines [ 1, 2, 0.010, 0.085, 0.030, 0.255, 1, 0; 2, 3, 0.015, 0.120, 0.040, 0.360, 37/10.5, 1; ]; % 电源表 [接入节点, R1, X1, R2, X2, R0, X0] gens [ 1, 0.001, 0.080, 0.001, 0.060, 0.002, 0.050; ];这里需要特别说明10 kV侧的基准电压取10.5 kV变压器变比取37/10.5而不是35/10。这种取法正是为了和基准电压系统一致保证标幺值在变压器两侧连续。5.2 计算过程逐段解读第一步构建三序导纳矩阵。正序矩阵 (Y_1) 是常规导纳矩阵负序矩阵 (Y_2) 中电源负序电抗与正序不同本例为 (0.001 j0.060)其他线路和变压器的负序阻抗与正序相同零序矩阵则要特别注意变压器低压侧为三角形接线时零序无法通过我的程序里对变压器零序支路做了特殊处理——当变压器低压侧接地方式不提供零序通路时该支路零序导纳为0。第二步求故障点自阻抗。以节点3为故障点分别解三次稀疏线性方程组得到(Z_{ff1} 0.0125 j0.1130)标幺(Z_{ff2} 0.0120 j0.0960)(Z_{ff0} 0.0450 j0.2100)第三步按故障类型计算。三相短路电流标幺值[ I_f^{(3)} \frac{1.0}{0.0125 j0.1130} ]用Matlab算得 (|I_f^{(3)}| \approx 8.82)标幺有名值为 (8.82 \times 5.50 , \text{kA} \approx 48.5 , \text{kA})10.5 kV侧基准电流约5.50 kA。这个量级对于一个10 kV母线来说是有可能出现的说明系统等值阻抗较小。单相接地短路电流标幺值[ I_f^{(1)} \frac{3.0}{Z_{ff1} Z_{ff2} Z_{ff0}} ]计算得到 (|I_f^{(1)}| \approx 6.37)有名值约35.0 kA。可以看到尽管零序阻抗较大单相短路电流依然接近三相短路电流的七成这个结果并不意外。5.3 与实际经验的核对程序跑出来的结果最终要和工程经验或电气计算软件的结果做交叉验证。我通常用三个简单的“合理性口算”来检查第一短路电流的量级是否合理。比如10 kV母线三相短路电流几十kA对应短路容量几百MVA这个范围大致可以预估第二单相与三相短路电流的比值是否符合系统接地方式的特征。中性点经小电阻接地系统单相短路电流通常被限制到几百安培到千安级程序如果算出几千安就要检查零序回路参数是否正确第三变压器两侧的短路电流有名值是否符合变比关系。忽略励磁支路时两侧短路电流有名值之比约等于电压等级的反比。这个案例里节点235 kV侧发生三相短路时程序计算短路电流约12.9 kA节点310 kV侧为48.5 kA两者比值约3.76与35/10.5≈3.33的变比方向相近差异主要来自变压器阻抗和线路阻抗的影响属于合理范围。6. 跑通程序后要留意的几个深坑6.1 变压器零序阻抗与接线组别程序里最容易被绕晕的地方我最初写这个程序时主序网络的代码都跑通了一到零序网络就出错。问题根源在于零序网络不是单纯地“把支路零序参数带进去”而是要结合变压器接线组别和中性点接地方式判断零序通路是否存在。比如一台 (Y/\Delta) 接线的变压器高压侧中性点接地、低压侧三角形接线零序电流可以从高压侧流向变压器绕组但因为低压侧是三角形零序电流在三角形绕组内形成环流无法向低压侧外部输送。这个过程中零序等值电路里变压器呈现的阻抗并不是简单的短路阻抗而是需要考虑接线组别折算后的等效阻抗。工程上有一个常见的简化处理方法把变压器零序支路分解为“激磁支路”和“短路支路”不同接线组别对应不同的连接方式。但对很多计算场景来说更稳妥的方式是在支路表中为每台变压器单独指定零序处理方式而不是让程序自动推断。毕竟程序无法知道你图纸上的变压器到底是 (Y/\Delta) 还是 (Y/Y_0)这个信息必须在数据表里人工显式给出。6.2 标幺值基准选取不一致最隐蔽的数据灾难短路电流计算中最常见的低级但致命的错误是不同电压等级之间基准值换算没做好。举个例子10 kV线路的电抗 (0.4 , \Omega/\text{km})如果直接用 (Z_B U_B^2 / S_B 10.5^2 / 100 1.1025 , \Omega) 来折算标幺得到 (0.4 / 1.1025 0.363)这在单电压等级分析里没有错。但如果这条线路通过变压器连接到35 kV系统而你在35 kV侧进行故障分析那就必须先把线路阻抗归算到35 kV侧(0.4 \times (37 / 10.5)^2)然后再取35 kV侧基准阻抗进行标幺。这个换算一旦漏掉短路电流误差会达到十几倍。我的建议是所有参数在输入阶段就统一归算到同一个电压等级通常取故障点所在电压等级或者统一用具名值输入、程序内部自动换算。不要“一会儿高压侧、一会儿低压侧”人的短时记忆在处理多节点系统时极其不可靠。6.3 复数运算的精度和符号问题Matlab默认变量类型是double复数运算本身很稳定但有两个细节需要留意。第一个细节是稀疏矩阵求逆时如果出现奇异或近奇异矩阵Matlab不会主动报错而是给出一堆NaN或Inf。在短路计算里近奇异通常意味着某个电压等级上没有任何电源接入孤岛或者零序网络不闭合。这时程序应主动检测结果并给出中文提示而不是让用户面对一屏NaN面面相觑。第二个细节是复数相位输出时angle()函数返回的是弧度单位不要搞混。我习惯在输出前统一转成角度制并格式化显示避免保护整定时相位校核出错。fprintf(短路电流相角: %.2f°\n, rad2deg(angle(If)));6.4 从单机计算到批量扫描工程效率的一个提升思路程序跑通单点故障之后自然想到的问题就是系统里几十个节点每个节点都要算一遍各类故障手动改故障点编号太傻了。我后来在程序上做了一个扩展允许传入一个故障点数组然后循环计算所有节点的各类短路电流最后汇总成一张大表。因为导纳矩阵只构建一次每个故障点的计算只是解一次稀疏线性方程组几百个节点的批量扫描在Matlab里也就几秒钟。再往上一层还可以结合Matlab的并行计算工具箱把不同故障点的计算任务分发到多个工作进程上进一步缩减耗时。工程上做全系统短路电流扫描时这个能力非常实用。6.5 校准程序的最终一步和已有工具的结果做交叉验证依赖自编程序前最后一步建议做交叉验证。我通常的做法是拿一套已知参数的公开教学系统哪怕只有三五个节点手算出理论值再和自己的程序结果对比误差应在0.1%以内。然后再拿一套实际工程系统和商业电气计算软件的结果逐点对比确认所有故障类型和所有故障点的最大误差都在工程允许范围内。这一步不是对程序不信任而是对数据输入和参数归算做系统性的“体检”。很多时候程序本身没有问题问题出在某个支路参数把变比填反了或零序电抗符号写错了。和已有工具两相对照能很快定位到异常点。如果你准备长期使用自编短路计算程序我另一个很实在的建议是给程序加上参数合法性检查模块。比如变压器变比不能为0、阻抗实部不能为负、节点编号不能重复、每个电源节点必须提供零序参数等等。这些检查看似简单但能在数据录入阶段拦截九成以上的低级错误远比在计算结果里发现异常再回头排查要省时间。用Matlab写短路电流计算本质上不是一件炫技的事情而是把电力系统分析里最经典的原理用工程上可维护、可复现的方式落地。我在这过程中最大的体会是程序写得再漂亮都不如数据表清晰、模块边界明确来得实在。如果你也正在做类似的事情希望这套思路和踩坑记录能帮你少绕几个弯。