简介:面向电力系统潮流计算与Matlab算法学习的Matlab工程包,覆盖IEEE 9~300节点的多个标准算例,集中实现直流法、牛顿拉夫逊法、快速PQ分解法、Gauss-Seidel法四类典型算法,适用于本硕博教学研究及编程实践。压缩包共44个文件,以41个Matlab脚本作为主体,包含核心算法、数据读入与结果输出等多个功能模块,另附1个操作录像、1个位图和1个文本说明,整体体积约472KB,轻量但结构完整。算例范围涵盖9、14、30、39、57、118、300等常用测试系统,并针对各算法提供独立核心函数与统一主控入口,可从数据读取、潮流求解到结果输出完整复现;配套操作录像演示了Matlab环境配置与正确启动方式,能帮助规避因当前文件夹路径设置不当或误运行子函数导致的报错。该资源已有1026人学习下载,适合需要横向对比四类迭代方法收敛性能的本科生与研究生,用于课程设计、毕业设计或科研入门。
1. 别急着按F5:这套IEEE9~300潮流资源到底帮你省了什么事
做电力系统潮流计算的人,手机里多少都存过几个“万能工具箱”,可真正打开第一步就卡住的比比皆是。这套IEEE9到IEEE300的潮流计算资源包,我的判断是:它把学术论文里最常被一笔带过的四件事一次性补齐了——直流法、牛顿拉夫逊法、快速PQ分解法、Gauss-Seidel法,每套算法都配好了从9节点到300节点的标准算例和一份能跟着点的操作录像。适合正在写课程设计、准备组会汇报或者被导师临时抓去复现某个算例的本硕博学生,也适合需要快速拿到一个可信基线的仿真工程师。你不用自己从IEEE官网一份份扒数据文件,也不用对着MATPOWER的手册猜参数。资源里从case9.m、case14.m一路到case300.m全齐,Runme_.m一键起算。但它有个前提条件,不满足就跑不出正确结果:MATLAB版本建议2021a或更高,当前文件夹必须切到工程路径,且只能运行入口脚本而不是子函数——这个坑后面专门展开。
2. 先把工程结构盘明白:几十个m文件谁是核心、谁是辅助
2.1 文件归属:数据文件、算法文件、工具函数各司其职
压缩包解压后看到一大片m文件时,别慌。先按“数据 / 算法 / 工具 / 辅助”四类归类,运行逻辑立刻清楚。
数据文件是case9.m、case14.m、case30.m、case39.m、case57.m、case118.m、case300.m这一组,命名规律非常直白:case后面跟的数字就是节点数。每个文件内部定义了三张表——bus(母线数据)、gen(发电机数据)、branch(支路数据),这是IEEE标准算例的通用组织方式。以case9.m为例,bus矩阵每行是“母线编号、母线类型、有功负荷、无功负荷、电压幅值初值、电压相角初值”等字段;branch矩阵记录线路两端节点号、电阻、电抗、对地导纳和变压器变比。
算法文件分四套:直流法对应dcpf.m和hhu_dcpf.m,牛顿拉夫逊法对应newtonpf.m和hhu_newtonpf.m,快速PQ分解法对应fdpf.m和hhu_pqpf.m,Gauss-Seidel法对应gausspf.m和hhu_gspf.m。你我需要注意一个重要细节:文件名里带hhu_前缀的版本相当于一个封装壳,负责把数据从外部格式转换成算法内部需要的格式,再调底层函数迭代。纯英文名的dcpf.m、newtonpf.m那些是底层求解核心,正常使用阶段不建议直接单独执行。
工具函数是容易被忽略却决定成败的一层:ext2int.m和int2ext.m负责外部母线编号和内部连续编号的互转,makeSbus.m构造节点注入功率向量,makeYbus.m通过支路数据组装节点导纳矩阵,makeB.m和makeBdc.m是为快速PQ分解法生成B'、B''矩阵。剩下idx_bus.m、idx_brch.m、idx_gen.m、idx_area.m这类文件是索引定义,它们不是算法,而是告诉程序“第几列代表什么”,修改算例数据时千万不能动这些列的排布。
2.2 程序主链路:从hhu_enter.m到hhu_runpf.m再到各算法
这套资源里我推荐的上手方式不是打开Runme_.m就跑,而是先顺着三行关键调用把主链路串一遍。Runme_.m大概率只做一件事:依次调用hhu_enter.m和hhu_runpf.m,再加一个清理环境的hhu_break.m。hhu_enter.m是数据总入口,它读取你选择的case文件,做数据完备性检查,比如检查bus矩阵里是否有重复编号、负荷列是否有NaN,同时检测是否装了MATLAB并行工具箱来决定是否走并行分支。hhu_runpf.m是算法分派器,根据你在参数里指定的method决定这次是调用hhu_newtonpf、hhu_pqpf、hhu_gspf还是hhu_dcpf。我建议你打开hhu_runpf.m看一个判断分支就明白了,它不复杂,像一个路由表。
核心调用关系可以写成这样:
% 手动复现主链路的调用顺序(与Runme_.m等价) [mpc, mpopt] = hhu_enter('case30'); % 读入IEEE30节点数据与默认参数 results = hhu_runpf(mpc, mpopt); % 按mpopt中的算法字段调度求解 if results.success hhu_again(mpc, results); % 结果回读与输出 end这里hhu_enter.m的第一个参数是case文件名,第二个参数mpopt是MATLAB风格的控制选项结构体,里面可以放算法选择、最大迭代次数、收敛精度等内容。hhu_runpf.m返回的results结构体里至少包含success字段(布尔值)、iterations(实际迭代次数)、et(计算耗时)、bus/branch/gen三张结果表。hhu_again.m的作用是把结果重新映射回原始的IEEE编号顺序——这是全套流程里最该理解的一步,因为内部计算用的是连续编号,而case数据文件里节点号往往是跳着定义或者从1到n但不连续的。
提示:初次跑通建议不要跳过hhu_again.m这一环。直接看newtonpf.m的返回值只能看到内部编号下的电压幅值和相角,如果和原始case数据的节点号对不上,那才是真正让人困惑的地方。
2.3 内部编号与外部编号:为什么hhu_break.m是你的后悔药
IEEE标准算例里的很多case文件节点编号带有工程习惯,比如平衡节点不一定放在第1位。ext2int.m会把外部编号(原始数据)映射成内部从1开始的连续编号,完成计算后再用int2ext.m把结果映射回去。这听起来简单,但实际操作中容易翻车的地方在于:你可能在hhu_runpf.m用错了编号版本,导致后面画图时母线名对不上。
我一般会在修改case数据之前,先执行一次ext2int.m拿到映射关系,并把映射关系保存下来:
% 查看外部编号到内部编号的映射关系(关键步骤) mpc = loadcase('case118'); % 读取IEEE118标准算例 [mpc_int, mapping] = ext2int(mpc); % mapping结构体保存双向映射 disp(mapping.order); % 查看重新排序后的内部节点顺序loadcase.m是从case文件或结构体载入数据的外部入口,它负责解析m文件里的矩阵并补全缺失字段。ext2int.m返回的mapping.order就是内部编号的有序列表,索引位置对应用新的连续编号,数值对应原始文件里的母线编号。如果算完发现某条母线结果异常,先查mapping而不是怀疑算法——90%的错位问题都能在这一步定位。
hhu_break.m这个文件很有设计感,它在计算结束后负责把临时变量、全局变量和持久变量清理干净,避免下一次切换算例时把上一个case的缓存带进来。尤其是你现在如果在同一进程里连续跑case9和case300,不做清理的话很可能出现“上一次的平衡节点编号还在工作区里”这类隐性问题。这个文件同时也是后悔药,当你想回到一段干净状态重新来过时,双击它比关掉MATLAB重新打开靠谱得多。
3. 直流法和Gauss-Seidel法:两种极端方法论
3.1 直流法为什么快:线性化背后有哪些假设条件
直流法从名字就能看出端倪,它是一种极度简化的潮流模型——把本来非线性的潮流方程线性化,当成直流电路来解。核心假设包括三条:线路电阻远小于电抗,可以忽略;节点电压幅值都接近1.0(标幺值);相角差足够小,sinθ≈θ。在这些假设下,有功功率和相角的关系近似为线性方程组P = B'θ,其中B'是由支路电抗倒数构成的节点导纳矩阵虚部。解这个线性方程组,不需要迭代,一步到位。
资源里的dcpf.m做了这样几件事:从case文件中提取支路数据,取每条支路电抗的倒数作为线路电纳(忽略电阻),组装出B矩阵,再对平衡节点所在行做置零处理并把平衡节点的角度固定为0。然后用左除直接求解θ,最后把角度结果放进result结构体。用代码定位它的核心逻辑是这么个意思:
% dcpf.m核心思路:对直流潮流实现步骤的简明回溯 function [theta, bus, branch] = dcpf(bus, branch, mpopt) [Ybus, Yf, Yt] = makeYbus(bus, branch); % 先组装完整导纳矩阵 B = imag(Ybus); % 取虚部作为B'矩阵 n = size(bus, 1); ref = find(bus(:, 2) == 3); % type=3的节点是平衡节点 B(ref, :) = 0; B(:, ref) = 0; % 平衡节点行与列需要置零处理 B(ref, ref) = 1; Pbus = bus(:, 3) / 100; % 有功注入量(标幺化) theta = zeros(n, 1); theta(ref) = 0; % 平衡节点角度固定为0 theta = B \ Pbus; % 左除解线性方程组,直流法一次性求解makeYbus.m是这一切的基础,它把case数据里的阻抗和导纳转换成节点导纳矩阵Ybus。这里你注意dcpf唯一需要的外部输入就是Ybus的虚部,所以其计算速度远快过任何迭代类方法。B矩阵奇异的原因多半出在置零逻辑上,如果某个节点与平衡节点之间没有任何连通路径,B对应行全零,左除就会直接NaN。IEEE9到300的算例都是标准连通图,理论上不会出现这个问题,但如果自己改branch数据时删了某条关键线路,就可能把图弄成不连通的,要小心的是这个操作。
直流法的适用场景定位在需要快速估计相角的场合,比如电力市场出清计算、安全校核预筛选、电网规划多场景扫算。误差范围一般在3%到5%,对工程决策是可接受边界。你要是用它去做精确无功分析,方向就错了。
3.2 Gauss-Seidel法的迭代公式:为什么它对初值那么敏感
Gauss-Seidel法是最古老的潮流迭代方法,它的思路是把每个节点的电压方程单独拆出来,不断用最新值替换旧值。对PQ节点,第k+1次迭代的电压值按如下公式更新:
$$ V_i^{(k+1)} = \frac{1}{Y_{ii}} \left(\frac{P_i - jQ_i}{V_i^{(k)*}} - \sum_{j \neq i} Y_{ij} V_j^{(k)}\right) $$
其中Yii是节点i的自导纳,V_i^{(k)}是上次迭代电压的共轭。PV节点的处理方式稍微不同:每次迭代后要计算无功注入量Q_i = -Im(V_i^{(k)} \sum_j Y_{ij} V_j^{(k)}),并修正电压幅值到指定值。Gauss-Seidel法的收敛速度近似线性,远慢于牛顿法的二阶收敛速度。
gausspf.m的实现顺序也很典型,它首先通过makeSbus.m计算每个节点的注入功率,然后逐点扫描更新电压。松弛因子常见做法是取1.0附近的值,理论上0.6到1.6之间都有收敛性保证,但具体取多少需要依据系统规模做数值实验。我对这个方法的判断是:它最大的学习价值在于把迭代思想讲透了,其次才是用于小规模系统的校核,但对IEEE300这种规模,它的迭代次数会显著增加,收敛速度会慢得让人失去耐心。
% gausspf.m的迭代核心(在hhu_gspf.m中被调用) % 用Gauss-Seidel更新PQ节点电压 for iter = 1 : max_it v_old = V; for i = 1 : n if bus_type(i) == 1 % PQ节点:只给定P和Q sumYV = Ybus(i, :) * V; V(i) = (conj(Sbus(i)) / conj(V(i)) - sumYV + Ybus(i, i) * V(i)) / Ybus(i, i); elseif bus_type(i) == 2 % PV节点:给定P和|V| sumYV = Ybus(i, :) * V; Qcalc = -imag(conj(V(i)) * sumYV); V(i) = (conj(Sbus(i) + 1j * Qcalc) / conj(V(i)) - sumYV + Ybus(i, i) * V(i)) / Ybus(i, i); V(i) = V(i) / abs(V(i)) * V_set(i); % 强制使幅值等于设定值 end end % 检查最大失配量是否小于收敛判据 if max(abs(V - v_old)) < tol break; end endSbus是节点注入复功率向量,由makeSbus.m根据bus和gen数据生成;Ybus(i,:) * V是节点i与全网的耦合,这个矩阵乘法是Gauss-Seidel法的主要耗时点。PV节点那行代码在V(i)更新后强制把幅值拉回设定值,数学上等价于用无功注入来抬升电压,这是Gauss-Seidel法实现PV节点最经典的方式。如果初值取得太离谱,比如把某个PQ节点的电压初值设成0.5,迭代器很容易发散。
我自己的习惯是:Gauss-Seidel法只用来算IEEE30以下的系统,或者作为牛顿法的预热器——先用它粗迭代几步得到一个不太离谱的初值,再切换到newtonpf完成精算。这种做法对大型系统有奇效,能减少牛顿迭代在初值不良时nearly singular matrix的报错概率。
4. 牛顿拉夫逊法和快速PQ分解法:电力系统里最硬的两种主力算法
4.1 牛顿法的核心:雅可比矩阵与两个关键导数文件dSbus_dV.m、dSbr_dV.m
牛顿拉夫逊法是当前商业软件和学术代码里的绝对主力,原理上是用泰勒展开取一阶项,把非线性潮流方程化成线性修正方程,反复迭代直到有功、无功失配量落入收敛门槛。方程形式是:
$$ \begin{bmatrix} \Delta P \ \Delta Q \end{bmatrix} = J \begin{bmatrix} \Delta \theta \ \Delta V \end{bmatrix} $$
其中J是雅可比矩阵,由四个分块组成:∂P/∂θ、∂P/∂V、∂Q/∂θ、∂Q/∂V。newtonpf.m的计算流程分三步:第一,用makeSbus.m算出节点注入功率Sbus;第二,调用dSbus_dV.m计算节点注入功率对电压幅值和相角的稀疏偏导矩阵;第三,调用dSbr_dV.m得到支路潮流的偏导,组装成完整的雅可比矩阵,解修正方程。
% newtonpf.m的简化主循环,展示雅可比矩阵的更新与求解 function [V, converged, iter] = newtonpf(Ybus, Sbus, V0, ref, pv, pq, mpopt) V = V0; [dSbus_dVm, dSbus_dVa] = dSbus_dV(Ybus, V); % 节点注入功率雅可比分块 [dSbr_dVm, dSbr_dVa] = dSbr_dV(Ybus, V); % 支路功率雅可比分块 n = length(V); J = assemble_jacobian(dSbus_dVm, dSbus_dVa, ... dSbr_dVm, dSbr_dVa, ref, pv, pq); % 按节点类型拼接 for iter = 1 : max_it S_calc = V .* conj(Ybus * V); mismatch = Sbus - S_calc; % 复功率失配量 [dSbus_dVm, dSbus_dVa] = dSbus_dV(Ybus, V); % 每次迭代更新雅可比 J = assemble_jacobian(dSbus_dVm, dSbus_dVa, ... dSbr_dVm, dSbr_dVa, ref, pv, pq); dx = J \ mismatch([pq; pv]); % 解线性方程组求修正量 V(pq) = V(pq) + dx(1:length(pq)); % 修正电压幅值 Va(pv) = Va(pv) + dx(length(pq)+1:end); % 修正相角 V = V .* exp(1j * Va); if max(abs(mismatch)) < mpopt.tol converged = true; break; end end enddSbus_dV.m返回的两个稀疏矩阵分别是dS/dVm(电压幅值偏导)和dS/dVa(相角偏导),它们的组装方式严格按照bus编号顺序,这也是为什么内部连续编号机制在整个流程中如此重要。你可以打开文件看一下矩阵赋值模式,每一行只与和该节点相连的支路相关,所以矩阵高度稀疏,MATLAB里直接用sparse命令操作,省内存也省时间。牛顿法最犀利的特性是二阶收敛,通常5到8次迭代就能在IEEE118系统上达到1e-8的收敛精度,前提是初值不能离谱。
4.2 快速PQ分解法的改进点:B'、B''矩阵与两个硬性前提
快速PQ分解法(也叫快速解耦法、B-X法)是在牛顿法基础上做的省力改造。它利用输电网中P主要受θ影响、Q主要受V影响这个物理特性,把完整的雅可比矩阵拆成两个解耦的低阶方程组:
$$ \Delta P / V = B' \Delta \theta,\quad \Delta Q / V = B'' \Delta V $$
B'矩阵由支路电抗倒数组装,B''矩阵由支路导纳虚部组装,两者在迭代开始前就固定下来,整个迭代过程不需要重新组装,所以单次迭代的计算量远小于牛顿法。fdpf.m和hhu_pqpf.m的关键区别在于:hhu_pqpf.m会先调用makeBdc.m生成B'和B'',而fdpf.m是在内部直接通过makeB.m一次生成。运行资源时注意makeBdc.m输出是两个矩阵:
% 用makeBdc.m构建P-Q分解法的常数矩阵 mpc = loadcase('case39'); [Bp, Bpp] = makeBdc(mpc); % Bp用于P-θ方程,Bpp用于Q-V方程 % 检查两矩阵是否奇异 if condest(Bp) > 1e12 || condest(Bpp) > 1e12 warning('B矩阵接近奇异,检查是否存在孤岛或电抗过大支路'); endcondest是MATLAB内置的条件数估计函数,这里用来预判数值稳定性。快速PQ分解法的适用硬性前提是:输电网R/X比值要足够小,通常要求小于0.3,如果改造的算例里有大量电缆线路或高电阻线路,PQ分解法的收敛性会显著恶化。它最显著的价值在于内存占用低、单次迭代快,适合在线潮流和安全分析,在IEEE300也算得上非常高效。
| 对比维度 | 牛顿拉夫逊法 | 快速PQ分解法 | Gauss-Seidel法 | 直流法 |
|---|---|---|---|---|
| 计算精度 | 高(可到1e-8) | 较高(通常1e-6量级) | 一般(1e-4量级) | 低(线性近似) |
| 迭代速度 | 快(二阶收敛) | 快(常数矩阵) | 慢(线性收敛) | 无迭代 |
| 内存占用 | 高(完整雅可比) | 低(两个常数矩阵) | 低 | 极低 |
| 收敛可靠性 | 强依赖初值 | 依赖R/X比值 | 强依赖初值与松弛因子 | 无收敛问题 |
4.3 四种算法在IEEE9和IEEE300间的调度建议
资源里hhu_runpf.m内部有一个算法选择字段,常见做法是用mpoption函数设置,之后runpf就会按这个选项去调对应算法文件。我常用的切换方式是:
% 在不同算法之间切换的标准写法 mpc = loadcase('case57'); mpopt = mpoption('PF_DC', 0, 'PF_ALG', 1); % 1=牛顿法 results = runpf(mpc, mpopt); mpopt = mpoption('PF_DC', 0, 'PF_ALG', 2); % 2=快速PQ分解法 results2 = runpf(mpc, mpopt); mpopt = mpoption('PF_DC', 0, 'PF_ALG', 3); % 3=Gauss-Seidel法 results3 = runpf(mpc, mpopt); mpopt = mpoption('PF_DC', 1); % 置1则走直流法 results4 = runpf(mpc, mpopt);runpf.m是分派总入口,它内部会根据PF_ALG字段来确定是调用newtonpf.fdpf还是gausspf。PF_DC置1时直接走hhu_dcpf或dcpf,完全绕过非线性迭代。我的经验是:IEEE9到30规模可以直接牛顿法;IEEE39到118节点用牛顿法初值如果来自平启动,偶尔会遇到半收敛状态,可以先跑两步Gauss-Seidel再切牛顿;IEEE300这种规模,快速PQ分解法是质量和速度的平衡点,直流法跑出来的相角结果也能给出一个不错的初值参考。
5. 运行避坑:五个频率最高的翻车现场与解决办法
5.1 现象:双击newtonpf.m直接运行,MATLAB报错“未定义函数或变量mpopt”
原因:算法文件是底层求解器,它默认所有输入参数已由上层函数组装好。直接执行时MATLAB工作区里根本没有mpc、mpopt这些变量。解决:永远只用Runme_.m这个入口执行。如果你只是想调某个算法,也得先手动建mpc和mpopt,再调用runpf:
% 正确的最小调用方式(改算例名只需替换case文件) mpc = loadcase('case30'); mpopt = mpoption('PF_DC', 0, 'PF_ALG', 1, 'OUT_ALL', 0); results = runpf(mpc, mpopt);5.2 现象:在当前文件夹窗口为空的情况下运行,报错“找不到case9.m”
原因:MATLAB的当前文件夹机制决定了脚本和数据的搜索路径。如果当前文件夹窗口指向了别的目录,loadcase或case9.m这类文件名只能靠系统搜索到,极易出现找不到文件或加载了重名文件。解决:运行前养成习惯,先cd到工程解压目录,再看左下角路径确认。命令行直接执行:
% 切换到工程目录并验证工作区 cd('D:\your_path\IEEE_trend_calc'); % 改成你自己的解压路径 pwd % 确认当前路径 ls % 查看文件是否就位5.3 现象:算完显示success,但bus结果表全是NaN,尤其IEEE300
原因:大部分NaN来自数值发散,根源多半是初值不良或雅可比矩阵奇异。IEEE300是大系统,平衡节点编号不一定在最前面,ext2int映射一旦没走对,雅可比矩阵的行列排序就出问题。解决:回查hhu_again.m是否参与运行,同时检查case300节点编号是否有跳号。再用max(abs(results.bus(:,8)))看最大电压幅值是否远大于1.1,超过1.5基本可以断定发散。
5.4 现象:直流法跑出来的相角数值大得离谱(超过30度)
原因:直流法本身忽略网损和无功,相角绝对值本来就偏大,这是模型误差而不是程序bug。IEEE300的某些线路电抗很大,P = B'θ中B'的元素偏小,导致θ变大。解决:不要迷信直流法的绝对值,用它做相对比较和初值定型。与牛顿法结果对比时,关注相角差而不是绝对相角。
5.5 现象:Gauss-Seidel法在IEEE118上迭代过千次依然不收敛
原因:Gauss-Seidel法的收敛速度本质是线性的,对系统规模敏感,IEEE118对纯Gauss-Seidel来说已经偏大。加上松弛因子若取1.4以上,系统一旦出现无功电压强耦合,就可能振荡。解决:把松弛因子调回1.0附近,并把收敛判据放宽到1e-4,这样至少能得到工程上可用的结果。如果还是不行,改用PQ分解法或牛顿法,不必为难自己:
% 调节Gauss-Seidel松弛因子与收敛判据的方式 mpopt = mpoption('PF_ALG', 3, 'PF_TOL', 1e-4); % PF_ALG=3为高斯赛德尔 % 如果需要修改松弛因子,在gausspf.m中搜索alpha变量,改为1.0或1.1提示:修改任何m文件前,先复制一份原文件存为.bak,所有调参实验在副本上做,避免把原始工程改废了。
6. 四算法验证与进阶:同一份数据上的对比脚本怎么搭
把资源吃透之后,最有价值的一件事是写一套自己的对比实验,用同一份case数据把四种算法全部跑一遍,输出迭代次数、计算耗时、最大失配量和相角最大偏差。这能让你直观看到直流法的近似误差有多大、PQ分解法和牛顿法在结果上有多少差别、Gauss-Seidel在小系统和大系统上的表现跨度。
% 基于本资源做的四算法对比脚本(可扩展到任意case文件) function compare_all_methods(casename) mpc = loadcase(casename); fprintf('Running %s\n', casename); % 直流法 mpopt = mpoption('PF_DC', 1, 'OUT_ALL', 0); r_dc = runpf(mpc, mpopt); fprintf('DC: time=%.4fs, maxVa=%.4f\n', r_dc.et, max(abs(r_dc.bus(:,9)))); % 牛顿法 mpopt = mpoption('PF_DC', 0, 'PF_ALG', 1, 'OUT_ALL', 0); r_nr = runpf(mpc, mpopt); fprintf('NR: iter=%d, time=%.4fs, mismatch=%.2e\n', ... r_nr.iterations, r_nr.et, max(abs(r_nr.bus(:,8)-1))); % 快速PQ分解法 mpopt = mpoption('PF_DC', 0, 'PF_ALG', 2, 'OUT_ALL', 0); r_fd = runpf(mpc, mpopt); fprintf('FD: iter=%d, time=%.4fs, mismatch=%.2e\n', ... r_fd.iterations, r_fd.et, max(abs(r_fd.bus(:,8)-1))); % Gauss-Seidel法 mpopt = mpoption('PF_DC', 0, 'PF_ALG', 3, 'PF_TOL', 1e-4, 'OUT_ALL', 0); r_gs = runpf(mpc, mpopt); fprintf('GS: iter=%d, time=%.4fs, mismatch=%.2e\n', ... r_gs.iterations, r_gs.et, max(abs(r_gs.bus(:,8)-1))); end这段脚本里r_dc.bus(:,9)是电压相角,r_dc.bus(:,8)是电压幅值,iterations字段仅对迭代类算法有效,直流法没有这个字段。对比结果通常你会发现三个趋势:第一,直流法的相角比牛顿法整体偏大,这是忽略了支路电阻和无功影响后的系统性偏差;第二,PQ分解法在IEEE39及以上系统的迭代次数比牛顿法多40%到60%,但单次迭代耗时长时更短,总耗时仍有优势;第三,Gauss-Seidel在IEEE57以后迭代次数明显爬坡。这个脚本建议每个case文件都跑一遍,做完之后你对四种算法边界的理解会非常具体。
更进阶的用法是改算例规模。很多人拿到case300就想自己造一个case400,工程做法是复制case300.m另存为case400.m,在bus矩阵尾部追加新节点,在branch矩阵追加相应线路,然后同步修改mpc.version字段和矩阵维度。改完以后不要急着跑,先执行一个快速完整性检查:
% 修改算例后的自检步骤 mpc = loadcase('case400'); % 新算例 assert(size(mpc.bus, 1) == 400, 'bus矩阵行数必须等于节点数'); assert(size(mpc.branch, 1) >= 399, '支路数至少要保证节点连通'); assert(all(mpc.bus(:, 1) == (1:400)'), '内部编号必须从1开始连续');这三条断言分别检查节点数、连通性和编号规则。第3条尤为重要,如果节点编号有跳号,ext2int还能救你一次,但编号严重混乱时hhu_runpf.m有可能直接报错。每次改完算例,都运行一遍这段自检脚本再进入主链路,能省掉大量排查时间。从那以后我每次拿到新算例都会先核一遍编号连续性和bus类型分布,再跑四种算法对比,这个顺序已经成了固定习惯,希望帮到你。
本文还有配套的精品资源,点击获取