ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Matlab实现电力系统潮流计算与不对称短路分析实战解析

Matlab实现电力系统潮流计算与不对称短路分析实战解析 做电力系统仿真的人应该都有体会潮流计算和不对称短路分析这两块几乎是一切电网分析的基础。潮流算不对后面的暂态稳定、继电保护整定、短路电流校验全都无从谈起而短路分析尤其是不对称短路又是保护配置和设备选型绕不开的环节。我在读研和工作初期断断续续用Matlab写过好几版这样的程序从最开始的照着书上公式抄到后来慢慢理解每一步迭代和矩阵变换在干什么中间踩了不少坑也积累了一些能直接用的经验。这篇博文就把我手头这套“电力系统潮流计算及不对称短路分析”的Matlab实现思路、核心代码逻辑、参数设置方法以及最常见的报错和坑位整理出来主要面向正在做课程设计、毕业设计或者刚入门电力系统仿真、想把理论算法落地的同学。我会把牛顿-拉夫逊法潮流计算和基于对称分量法的各类不对称短路计算拆开讲附上可以直接参考的代码骨架和测试数据。1. 为什么要把潮流计算和不对称短路分析放在一套程序里1.1 两个模块的天然依赖关系很多人觉得潮流计算是一回事短路计算是另一回事分开做不就行了。但实际搭建过整套仿真流程就会明白短路计算必须建立在潮流结果之上。道理很简单发生短路故障前系统里各节点是有初始电压和功率分布的这些初值直接影响故障后的电气量计算。举个例子在对称短路三相短路计算中故障点短路电流的周期分量其实可以用戴维南等值电路求但这个等值电势的取值就来自故障前的空载电压。而在不对称短路分析里正序、负序、零序网络的序电压分量都必须以故障前正常运行状态下的节点电压为基准。所以一套完整的程序必然是先跑潮流、再算短路前者给后者提供初值。把两个模块放在同一套代码里不仅能省掉中间环节的数据交互更重要的是保证数据的一致性。比如潮流计算中得到的各节点电压幅值和相角会直接影响短路后各序网的电压分布。如果分开用两套软件、两套数据文件很容易出现节点编号不一致、基准容量不统一这类低级错误排查起来非常头疼。1.2 为什么用Matlab而不是专用电力系统仿真软件现在做电力系统仿真很多人第一反应是PSASP、BPA、PSS/E这些专业软件。它们在工程界确实够用但在教学、科研算法验证和个人学习场景下Matlab有明显优势。首先是灵活性。专业软件的核心算法是封死的你能做的是填参数、选模式但很难看到迭代过程更别说去修改算法本身。Matlab里矩阵就是一等公民牛顿-拉夫逊法本质上就是反复求解J*Δx-f(x)这个线性方程组这几乎是Matlab的“主场作战”一个反斜杠运算符就能解。调试时可以随时打印中间变量观察每次迭代的误差变化这对理解算法本身非常有帮助。其次课程设计和毕业设计往往要求你“实现算法”而不是“使用软件”。老师要看到你理解节点导纳矩阵如何形成、雅可比矩阵如何计算、对称分量变换如何作用在三相网络上。这些如果用专用软件根本展示不出来用Matlab每一段代码都是可读、可改、可解释的。第三数据和图形处理方便。算完潮流直接一个plot就能画电压分布曲线算完短路能直接绘制各序电压、电流的向量关系图。这对接报告、写论文非常友好不需要像传统软件那样到处导数据。1.3 这套代码的整体框架设计我做这套程序时把整个流程拆成了四个相对独立的模块数据读取与参数初始化定义节点数据、支路数据、基准容量、迭代收敛精度。潮流计算内核形成节点导纳矩阵用牛顿-拉夫逊法迭代求解节点电压。不对称短路分析基于潮流结果用对称分量法构造正、负、零序网络按不同故障类型求解边界条件。结果输出各种短路类型下的故障电流、各节点电压幅值和相角以及必要的图形化展示。模块化不是花架子而是为了排查问题方便。比如潮流不收敛问题一定在第二模块不用怀疑是短路模块的问题反过来序网参数对不上基本就是第三模块的数据传递出错了。2. 核心原理要点在代码里必须“落地”的那些公式2.1 潮流计算节点导纳矩阵和牛顿-拉夫逊迭代潮流计算的本质是求解一组非线性方程说的是每个节点的注入功率等于该节点电压与所有相连节点电压关系的乘积和公式表达为Pi Ui * Σ(Uj * (Gijcos(θi-θj) Bijsin(θi-θj))) Qi Ui * Σ(Uj * (Gijsin(θi-θj) - Bijcos(θi-θj)))这里面需要理解的核心概念有三个。第一是节点导纳矩阵Y。它的对角元素是自导纳等于与该节点相连的所有支路导纳之和含对地导纳非对角元素是互导纳等于两节点之间支路导纳的负值。在Matlab里我习惯先初始化一个全零矩阵然后遍历每条支路把支路导纳加到对应位置上去。这个过程中最容易出错的是变压器支路因为有非标准变比导纳会乘以变比的平方很多人第一次写都会漏掉这个系数。还有考虑对地导纳的时候要记得把它加到自导纳上而不是互导纳上。第二是节点分类。潮流计算把节点分为PQ节点已知有功和无功求电压幅值和相角、PV节点已知有功和电压幅值求无功和相角、平衡节点基准节点已知电压幅值和相角求有功和无功。程序里我会用一个数组来标记每个节点的类型然后根据类型决定状态变量取哪些、方程约束取哪些。第三是雅可比矩阵Jacobian矩阵。牛顿-拉夫逊法的核心就是线性化给定一个初值把非线性方程在这个初值处泰勒展开取一阶项得到一个线性方程组解出修正量反复迭代直到修正量足够小。雅可比矩阵就是误差函数对状态变量的一阶偏导数矩阵。具体到潮流计算状态变量是各PQ节点的电压幅值U和相角θPV节点只有θ方程是有功偏差ΔP和无功偏差ΔQ。雅可比矩阵可以分成四个子块HΔP对θ求导、NΔP对U求导、MΔQ对θ求导、LΔQ对U求导每个子块的元素都有解析式可以写出来。我对初学者最想强调的一点是不要直接从书上抄雅可比矩阵的公式最好自己在Matlab里从偏导数定义出发推一遍或者先用符号计算工具验证一下。因为这四个子块的维数不一样H是(nPQnPV)×(nPQnPV)N是(nPQnPV)×nPQM是nPQ×(nPQnPV)L是nPQ×nPQ组合的时候得特别小心下标对应关系错了程序运行起来不会报错但迭代就是收敛不了或者收敛到一个完全错误的解上。2.2 不对称短路分析对称分量法和三序网络不对称短路包括单相接地、两相短路、两相接地短路处理的核心工具就是对称分量法。这个方法的思路是把一组不对称的三相电气量电压或电流分解成三组对称的分量——正序分量按A-B-C相序、负序分量按A-C-B相序、零序分量三相同相且幅值相等。每组分量的三相互差120度或相等就可以把不对称问题拆成三个对称问题来处理分别求解后再叠加。在Matlab里对称分量变换的核心就是一个转换矩阵A [1, 1, 1; 1, a^2, a; 1, a, a^2];其中a e^(j*2π/3)也就是旋转120度的算子。反变换矩阵是A的逆需要除以3A_inv (1/3) * [1, 1, 1; 1, a, a^2; 1, a^2, a];这个变换矩阵的书写和控制领域里的Park变换、派克变换很像但注意序分量变换用的是120度旋转算子不是90度。我在实际项目中见过同学把a写成了e^(jπ/2)结果算出来三相短路电流不平衡排查半天才发现是这个符号的问题。三序网络的概念也很关键。正序网络就是你平时做对称短路计算用的那个网络负序网络里所有发电机的电动势都为零阻抗是次暂态阻抗或负序阻抗零序网络更特殊只存在于中性点接地的路径上和变压器的接线方式密切相关。代码里要为这三种序网分别建立序导纳矩阵短路发生前只有正序网络有电压源激励负序和零序网络都是无源网络。2.3 潮流结果向短路分析的数据传递要点把潮流计算的结果接到短路分析模块时有一个坑很容易踩潮流计算得出的节点电压是相量包含幅值和相角但在传统短路计算公式里故障前各节点电压一般只关注幅值而忽略相角差异。这在忽略负荷电流且认为各节点电压近似相等的经典假设下是可以的但如果你的程序要做到更精确就应该保留各节点的电压相量并在构造正序网故障点电压时把潮流算出的该节点电压直接作为戴维南等值电势。我在自己的程序里采取的做法是从潮流模块输出一个正序节点电压相量数组U_node然后在短路模块里直接取故障节点的电压幅值和相角作为正序网戴维南电势的初值。这样算出来的短路电流比直接用标称电压比如1.0∠0°要准确。3. Matlab代码实现从导纳矩阵到短路电流3.1 数据准备和节点导纳矩阵构建我习惯用结构体数组或者单元格来存储节点和支路数据这样比一堆分散的向量更清晰。下面是一个简单的数据定义示例% 节点数据格式 % [节点编号 电压幅值初值 电压相角初值 有功出力 无功出力 有功负荷 无功负荷 节点类型] % 节点类型: 1平衡节点, 2PV节点, 3PQ节点 bus [ 1 1.06 0 0 0 0 0 1; 2 1.00 0 0.4 0.2 0.2 0.1 2; 3 1.00 0 0 0 0.6 0.3 3; 4 1.00 0 0 0 0.4 0.2 3; ]; % 支路数据格式 % [首端节点 末端节点 电阻R(pu) 电抗X(pu) 对地电纳B/2(pu) 变比k] branch [ 1 2 0.010 0.050 0.02 1.0; 2 3 0.015 0.060 0.02 1.0; 3 4 0.012 0.045 0.015 1.0; 1 4 0.020 0.080 0.03 1.0; ];这段数据格式是电力系统课程和教材里最经典的IEEEX型节点数据格式的简化版。有了这个基础数据就可以构建节点导纳矩阵了。核心逻辑是遍历每条支路先计算支路导纳y 1/(RjX)然后将y加到首端和末端节点的自导纳上将-y加到互导纳上如果有变压器变比k则在靠近首端一侧乘上1/k^2。function Y build_Y(bus, branch) n size(bus, 1); Y zeros(n, n); for k 1:size(branch, 1) i branch(k, 1); j branch(k, 2); R branch(k, 3); X branch(k, 4); B branch(k, 5); % 对地电纳这里存的是整个B/2 tap branch(k, 6); y 1 / (R 1i*X); % 支路导纳 yij y / tap; % 考虑非标准变比的折算 Y(i,i) Y(i,i) yij 1i*B; Y(j,j) Y(j,j) yij 1i*B; Y(i,j) Y(i,j) - yij; Y(j,i) Y(j,i) - yij; end end这里有一个细节我在支路数据里存的是对地电纳B/2因为输电线路的等效π型电路里对地电容分成两半分别挂在两端。上面这段代码每端都加一次B也就是B/2B/2刚好等于整个对地电容。如果忘了这个处理LU分解解潮流时经常会遇到导纳矩阵在某些运行条件下病态虽然不一定直接报错但迭代过程会变得异常缓慢。3.2 牛顿-拉夫逊潮流迭代的实现细节潮流迭代的核心是不断求解修正方程[ΔP; ΔQ] J * [Δθ; ΔU/U]。这里有个技巧很多人第一次看推导会奇怪为什么右边要写成ΔU/U而不是ΔU其实是为了让雅可比矩阵的表达式更简洁、数值性质更好。在代码实现时解出ΔU/U之后再乘上U就得到ΔU。我把牛顿-拉夫逊迭代的核心循环骨架写在这里% 初始化 Y build_Y(bus, branch); V bus(:,2) .* exp(1i * bus(:,3) * pi/180); % 节点电压相量初值 iter 0; max_iter 50; tol 1e-8; while iter max_iter % 计算注入功率 I Y * V; S V .* conj(I); Pcal real(S); Qcal imag(S); % 计算有功和无功偏差 nPQ sum(bus(:,8)3); nPV sum(bus(:,8)2); % 取需要迭代的节点去掉平衡节点 ... dP Pspec - Pcal; % 有功偏差 dQ Qspec - Qcal; % 无功偏差 % 求雅可比矩阵各子块 [H, N, M, L] jacobian(Y, V, nPQ, nPV, bus); J [H N; M L]; % 解修正方程 dThetaU J \ [dP; dQ]; dTheta dThetaU(1:nnPQ-1); % 注意维数 dU_over_U dThetaU(nnPQ:end); % 更新电压 ... if max(abs([dTheta; dU])) tol break; end iter iter 1; end雅可比矩阵子块的元素以H子块为例偏移节点间的表达式是H_ij Ui * Uj * (Gijsin(θi-θj) - Bijcos(θi-θj))对角元素是H_ii -Qi - Bij*Ui^2类似地N、M、L子块也有各自的表达式。我强烈建议在正式编码之前先用Matlab的符号数学工具箱Symbolic Math Toolbox把四组子块公式全部验证一遍看符号推导和手写的是否一致。当时我在写代码时就是因为在N和M子块的符号上面搞错了迭代老是震荡后来用符号计算验证才发现是公式最前面的正负号抄反了。还有一个容易被忽略的小细节PV节点的无功不需要迭代但它的无功功率作为状态量要参与后续计算。所以在每轮迭代结束后要单独重新计算PV节点的无功并检查是否超出发电机无功上限。如果超限需要把该节点从PV改成PQ节点重新计算这个逻辑在工程中非常常见但课堂练习里很少被提到。3.3 对称分量变换与序网构造潮流计算收敛之后就进入了短路分析阶段。第一步是把相域里的数据变换到序域里。对于三相对称系统序网是解耦的但实际上线路参数有互感严格来说要完全解耦需要用到相分量到序分量的变换矩阵。不过对大多数课程设计和工程近似计算采用经典假设是合理的认为各序网络独立正序参数等于建筑在潮流导纳矩阵里的参数负序一般取和正序相等对于静止元件零序则要看变压器接法和中性点接地情况。在代码中我构造序网的方式是直接复制一份正序导纳矩阵Y_pos Y_build出来的矩阵然后根据变压器接法修改零序网络。比如Y-Y接地变压器零序网络能形成通路Y接线三角形接线零序通不过去。零序导纳矩阵的修改逻辑是对星形中性点不接地的节点自导纳中与变压器相关的支路要置零对三角形连接的节点该节点在整个零序网络中表现为孤立点。代码层面我会在数据输入里增加一个列来标记变压器的接线方式和中性点接地情况然后根据这些标记来生成零序导纳矩阵function Y0 build_Y0(bus, branch, trans_data) % 先复制正序导纳矩阵 Y0 build_Y(bus, branch); % 对零序网络做特殊处理 for k 1:size(trans_data, 1) % trans_data每行: [支路编号 接线方式 中性点是否接地] % 如果三角接法或者中性点不接地则将对应支路从零序网络中移除 if trans_data(k, 3) 0 i branch(trans_data(k,1), 1); j branch(trans_data(k,1), 2); y_old Y0(i,i) - (-1/(branch(k,3)1i*branch(k,4))); % 简化处理实际代码里要仔细扣除原支路导纳 end end end这个模块特别容易出现“串联阻抗算错了”的问题因为零序和正序的变压器等值电路完全不同Y-Y接地和Y-Δ两种接线方式下零序阻抗差异很大。3.4 各种短路类型的统一计算框架教科书里会把单相接地、两相短路、两相接地短路、三相短路分开推公式但在代码实现中其实可以统一成一个框架。以故障点F作为端口用序网络戴维南等值的方式来处理。故障口序电压和序电流之间的关系可以写成Uf_pos Uf_0 - Zff_pos * If_pos Uf_neg -Zff_neg * If_neg Uf_zero -Zff_zero * If_zero其中Zff_pos、Zff_neg、Zff_zero分别是从故障点看进去的正、负、零序戴维南阻抗Uf_0是故障前故障点的正序电压由潮流结果提供。不同故障类型的区别只是边界约束条件不同。单相接地短路的边界条件是If_pos If_neg If_zero Uf_pos Uf_neg Uf_zero 0联立求解可以得到If_pos Uf_0 / (Zff_pos Zff_neg Zff_zero)然后回代得到各序电压再通过对称分量反变换得到相域的故障电流和电压。两相短路的边界条件是If_pos -If_neg If_zero 0 Uf_pos Uf_neg求解后得到If_pos Uf_0 / (Zff_pos Zff_neg)两相接地短路的边界条件要复杂一些If_zero -If_pos - If_neg Uf_pos Uf_neg Uf_zero解出来If_pos Uf_0 / (Zff_pos Zff_neg * Zff_zero / (Zff_neg Zff_zero))在Matlab里我可以把这些统一为以下代码段% 故障类型: 1三相短路, 2两相短路, 3单相接地, 4两相接地 switch fault_type case 1 % 三相短路 If_pos Uf_0 / Zff_pos; If_neg 0; If_zero 0; case 2 % 两相短路 If_pos Uf_0 / (Zff_pos Zff_neg); If_neg -If_pos; If_zero 0; case 3 % 单相接地 If_pos Uf_0 / (Zff_pos Zff_neg Zff_zero); If_neg If_pos; If_zero If_pos; case 4 % 两相接地 Z_parallel (Zff_neg * Zff_zero) / (Zff_neg Zff_zero); If_pos Uf_0 / (Zff_pos Z_parallel); If_neg -If_pos * Zff_zero / (Zff_neg Zff_zero); If_zero -If_pos * Zff_neg / (Zff_neg Zff_zero); end解出故障点各序电流之后先通过对称分量反变换得到故障点的三相电流然后再看需要计算网络中其他节点的电压和各支路的电流分布。这里面最关键的一步是把各序电流注入到序网络中去然后求解线性方程组得到各节点的序电压分布。这一步在Matlab里的实现特别省力% 将故障点各序电流注入序网络求解序电压分布 % 在正序网络中故障点注入电流是 -If_pos I_inj_pos zeros(n, 1); I_inj_pos(fault_bus) -If_pos; U_pos_node Y_pos \ I_inj_pos; I_inj_neg zeros(n, 1); I_inj_neg(fault_bus) -If_neg; U_neg_node Y_neg \ I_inj_neg; I_inj_zero zeros(n, 1); I_inj_zero(fault_bus) -If_zero; U_zero_node Y_zero \ I_inj_zero;这种“注入电流法”比我最早用的“修改导纳矩阵法”要方便很多因为不需要在故障类型变化时反复重组导纳矩阵只需调整注入电流向量。最后把三个序电压叠加到相域% 节点k的三相电压故障前用潮流结果故障后需要叠加序分量 A [1 1 1; 1 a^2 a; 1 a a^2]; % 对称分量变换矩阵 Va_node U_pos_node U_neg_node U_zero_node; Vb_node a^2 * U_pos_node a * U_neg_node U_zero_node; Vc_node a * U_pos_node a^2 * U_neg_node U_zero_node;4. 实操过程从IEEE标准节点到代码验证4.1 测试系统的选择与参数基准做课程设计或者毕设我建议从IEEE 3机9节点通常叫WSCC 9节点系统开始跑。这个系统有3台发电机、9条母线、足够体现各种节点类型平衡节点、PV节点、PQ节点都有又不会大到让你在调试时晕头转向。等这套系统跑通了再扩展到IEEE 14节点、IEEE 30节点。获取标准参数时需要注意统一基准值。IEEE官方数据里给出的参数都是标幺值pu但基准容量通常没写明确。IEEE 9节点系统的基准容量一般取100 MVA但网上某些流传的数据文件用的是其他基准混用的时候容易出错。我的经验是一开始就在代码注释里写清楚“本文档所有参数基于SB100MVAUB230kV母线1-2”并且每次导入新数据都重新核验一下节点电压初值是否符合1.0pu左右。另一点要注意的是发电机参数。不对称短路分析需要用到发电机的负序和零序阻抗算法上要看成是在故障视角下发电机的等值阻抗。但从系统角度看发电机提供的短路电流由戴维南等值电路决定这和潮流计算时的功率注入模型是不同的。所以我们在搭序网时发电机节点要接上一个阻抗支路值等于次暂态电抗或负序电抗而潮流计算时发电机节点是PV节点或平衡节点视不同的计算目的而定。4.2 关键参数设置收敛阈值、迭代限制与基准值潮流迭代中最重要的几个参数是收敛阈值、最大迭代次数、电压初值。收敛阈值我一般设成1e-8这是牛顿-拉夫逊法的标准值。设1e-6也能收敛但有时候结果差那么一点影响短路计算的精度。最大迭代次数设50足够因为牛顿法在初值合理的情况下一般5-10次就能达到收敛精度。如果你发现迭代次数超过了15次还没收敛大概率不是算法问题而是数据或公式写错了。电压初值的设置有个技巧PQ节点的电压初值设成1.0∠0°PV节点设成给定电压的幅值和0度相角平衡节点始终保持1.0∠0°。这个初值策略基本是所有教科书的一致选择实际跑下来也最稳。如果你非要标新立异把初值设成0或者一个特别离谱的值牛顿法很可能在第一步就因矩阵奇异而崩溃。在短路计算模块要设置的参数还有故障点位置、故障类型、故障时间如果你还要做暂态分析的话。静态不对称短路分析主要关注故障发生后的稳态值所以时间参数不是必需的。这个部分我给出一个参数速查表参数项推荐值说明潮流收敛阈值1e-8电压修正量最大偏差小于该值即收敛最大迭代次数50超过后强制退出并报错电压初值PQ节点1.0∠0°标幺值基准容量100 MVAIEEE节点系统通用短路故障类型4种三相、两相、单相接地、两相接地故障点位置任意节点或支路指定位置代码里用节点编号指定4.3 典型测试结果与验证方法跑完一个系统怎么验证结果对不对我的习惯是用“双轨验证法”先用自己写的代码算一遍再用Matlab自带的电力系统仿真工具或者手算一个小系统来交叉验证。以IEEE 9节点系统为例在母线7处设置单相接地短路程序输出的短路电流总会以潮流计算出的母线7电压为基准。一般结果会是故障相电流很大可能达到几千安培非故障相电流很小因为负荷电流存在。这个数量级关系本身就是一种验证——如果非故障相电流和故障相电流一个数量级说明序网参数错了。另一个验证点是两相短路时故障相之间的线电压为零。当我用Matlab绘制短路后各节点电压时能看到故障点特定相之间电压确实为零而非故障相电压会有一定程度的抬升这就说明边界条件用对了。要对“节点阻抗矩阵法”和“注入电流法”的结果进行比较可以这样做算完潮流后先通过矩阵求逆得到节点阻抗矩阵Z inv(Y_pos)然后取出故障节点的自阻抗Zff用公式If Uf_0 / (Zff_pos Zff_neg Zff_zero)直接算短路电流再用注入电流法走一遍两个结果应该完全一致。如果对不上说明代码实现有问题这是一个非常好的自查方法。5. 常见问题与排查技巧实录5.1 潮流不收敛第一时间查什么潮流不收敛是初学者遇到最多的报错情况我大概归纳为几类原因。第一类是导纳矩阵构建错误。判断方法很简单把导纳矩阵打印出来看对角元素是不是正的自导纳的正负号取决于你的约定但数值上应该等于所有连接支路导纳之和非对角元素是不是负的互导纳是负的。如果自导纳小于互导纳的绝对值之和说明有支路没加进去或者符号错了。第二类是雅可比矩阵维数不匹配。这个问题在Matlab里反而不容易报错因为你用\运算符时如果左边是n×n矩阵右边是n×1向量Matlab会自动解方程但结果就是错的而且不会给你任何报错提示。我建议在解修正方程之前用size(J)和size([dP; dQ])来确认维数一致或者用assert写断言检查。第三类是节点类型定义错误。比如把平衡节点漏了或者一个节点既是PQ又是PV这会导致方程数不足或者冗余。检查办法是统计一下状态变量数 2 * PQ节点数 PV节点数这个数必须等于方程数。我当时就犯过这种错因为把BUS_TYPE那一列的数据写错了导致迭代算出来的电压全部跑飞到天上。如果你遇到的情况是“前几次迭代误差在下降但到后面开始震荡或者发散”可以先试着把初值改得更贴近实际运行点比如把PQ节点电压幅值设成1.0pu、相角设成0。还有一些情况下减小负荷功率或者增加无功补偿可以帮助收敛。这可能是因为系统本身就没有可行解。5.2 短路计算结果异常问题多半出在序网参数上如果潮流计算正常但短路电流算出来离谱我的排查顺序是这样的。首先检查负序和零序阻抗参数。很多教材的例题里负序阻抗直接等于正序阻抗这是近似但在电力系统里电机的负序阻抗和正序阻抗通常不一样。如果程序里把所有序阻抗都设成相同值那不对称短路电流会偏大或偏小。正确的做法是对发电机负序电抗用X2次暂态的负序值零序电抗用X0对变压器和线路零序阻抗参数要查表或者根据类型设置。然后是检查零序网络是否闭合。零序电流要有通路必须经过接地中性点。如果系统中性点都没有接地那零序网络是断开的单相接地和两相接地短路的零序电流应该为零或者由其他接地路径决定。我调试过一套系统算出来单相接地短路电流和三相短路电流几乎一样大排查了半天发现是某个变压器节点零序处理错了导致零序网络把原本应该断开的路径连上了。第三个高频问题是故障后节点电压越界或者出现NaN。这通常是因为线性方程组奇异也就是导纳矩阵不可逆。零序导纳矩阵尤其容易奇异因为如果系统完全不接地零序导纳矩阵会是奇异的。遇到这种情况可以在形成零序网络后先看一眼cond(Y_zero)条件数特别大就要小心了。5.3 调试工具和排查命令推荐在Matlab里调试这套程序我常用的几个工具和命令可以分享一下。第一是spy(Y)这个命令它能把稀疏矩阵的非零元素分布画出来。导纳矩阵本身是稀疏的用spy可以一眼看出哪些节点间有连接关系。如果某条支路该出现在矩阵里但没出现spy图上一眼就能看出来。第二是disp中间结果打印。我在迭代循环里会打印每一次迭代的max(abs(dP))和max(abs(dQ))观察误差是单调下降还是来回震荡。如果误差单调下降说明算法本身没问题只是收敛速度慢如果是震荡几乎可以断定是公式或数据错误。第三是profile性能分析工具。当系统规模变大到几百个节点时如果循环写法不好雅可比矩阵计算会非常慢。用profile能看到是哪个函数耗时最多通常是雅可比矩阵子块计算的循环嵌套。优化办法就是向量化把内层循环改成矩阵运算。比如N子块的表达式可以一次性写成矩阵形式而不是逐个元素去算。5.4 常见问题速查表为了便于查阅我整理了一张速查表基本把新手阶段可能遇到的问题都覆盖了症状可能原因解决办法潮流收敛但电压结果明显异常导纳矩阵符号错误、负荷功率正负号约定不统一检查导纳矩阵对角元素是否为正以及Pspec和Qspec的正负号定义迭代开始后误差增大并震荡雅可比矩阵公式有误尤其是符号用符号数学工具箱验证每个子块的解析表达式PV节点无功越限发电机无功出力超出上限将节点改判为PQ节点重新指定无功继续迭代短路电流包含实部虚部但模值偏小基准值不统一检查所有参数是否基于统一SB和UB零序电流恒为零零序网络未形成通路检查变压器接线方式和中性点接地信息故障后电压出现NaN导纳矩阵奇异检查节点编号是否有孤立点或零序网络是否正确断开程序运行慢循环嵌套过多用向量化替代循环尤其雅可比矩阵计算写在最后一点个人经验我从最开始照着课本公式硬抄到后来能把雅可比矩阵的每个子块默写出来再到后面自己往程序里加线路故障、变压器分接头调节这些功能大概花了几个月时间。现在回头看最大的转折点就是不再把代码当成“翻译公式”而是真正理解每一步矩阵运算在物理上对应什么。比如看到Y矩阵的非对角元素你能想象出它对应的那条输电线路看到H子块的元素你能知道它是节点注入功率对相角的敏感度。如果你正在做类似的课题我建议不要只停留在把程序跑通这一步。把故障类型做成一个循环让程序自动计算四种短路类型下的短路电流并绘制对比曲线再把短路点从单一节点扩展到所有节点输出一条“短路电流随故障点位置变化”的曲线。这些扩展功能写进报告里很加分更重要的是每加一个功能你对系统各个量之间耦合关系的理解就会深一层。最后分享一个小技巧在Matlab里写这种偏计算类的程序养成“一边写、一边用assert做校验”的习惯能帮你省掉大量排查时间。比如潮流的功率平衡校验所有节点注入功率之和加上网损等于零完全可以在迭代收敛后加一条断言。如果断言不通过说明你中间某个环节有问题立刻就能定位不用等整段代码跑完才发现结果不对。
返回列表