做电力系统仿真的同行应该都有这种体会:拿到一个配电网模型,第一反应往往是“能不能直接用单相潮流程序算一遍,再乘个系数凑合一下?”遇到三相负荷平衡的系统,这么干确实能省不少事;但一旦面对低压台区、单相光伏、电动汽车充电桩这类场景,单相潮流的结果根本解释不了实际问题。我这些年反复踩同一个坑之后,最终老老实实写了一套三相潮流计算程序,核心算法用的是牛顿-拉夫逊法。这篇文章就围绕这套程序的功能说明展开,把三相建模思路、牛顿-拉夫逊法的迭代过程、程序实现细节和调试经验一次讲透,适合正在做配电网规划、分布式电源接入评估、电压质量分析的工程师参考。
1. 为什么必须做三相潮流:单相潮流解决不了的问题
1.1 单相潮流的隐含假设,配电网里根本不成立
单相潮流本质上把系统看成“三相对称、单相等效”的模型:发电机输出电压三相对称,线路参数三相对称,负荷也按三相对称分布。在这种假设下,三相电气量只有正序分量,负序和零序为零,随便取一相计算,另外两相只需旋转±120度就能推出来。这个前提在输电网层面还勉强说得过去,因为输电网有换位、有大量平衡度较好的负荷。
但配电网完全不同。低压馈线的单相用户随处可见,两条线供电的场合也不少,三相负荷不平衡才是常态。再加上近年分布式光伏大量接入,不少还是单相逆变器,直接挂在某两相之间或某一相上。这时候再用“对称”假设去简算,算出来的母线电压既不是A相真实值,也不是B相真实值,而是三个相取平均后再虚构出来的一个值。
更麻烦的是,配电网导线间距小、电压等级低,相与相之间的电磁耦合明显,单相潮流根本无法体现“某一相负荷增大时,另外两相电压受到多大影响”这种耦合关系。三相潮流计算程序就是在这一背景下出现的:真正把A、B、C三相分开建模,逐相求解,把不平衡带来的影响显式算出来。
1.2 三相潮流能计算哪些核心功能
从功能上看,这套三相潮流程序至少应该支撑以下几项计算:
- 逐相电压计算:输出每个节点的A、B、C相电压幅值和相角,这是后续分析的基础。
- 三相不平衡度分析:根据负序分量与正序分量的比值计算不平衡度,判断电压是否越限。
- 支路功率与损耗分相统计:每条线路的A、B、C相功率、电流、损耗可以单独查看,也能汇总成三相总量。
- 中性线电流估算:低压系统是三相四线制,三相不平衡时中性线电流可能非常大,三相潮流能直接通过相电流相量和估算出来。
这些功能对实际工作很有用。比如判断台区末端电压是否偏低,单相潮流只能给一个“平均电压”的概念,三相潮流能直接指出“C相跌到190V,A相还有218V”,问题定位就精准得多。
2. 三相系统怎么建模:节点导纳矩阵的关键细节
2.1 相坐标法和对称分量法,选哪个更合适
做三相潮流,行业里主要有两条路线:对称分量法和相坐标法。
对称分量法先把A、B、C相电压和电流变换成正序、负序、零序三个序分量,然后分别建立序网络方程。理论上序分量之间解耦,计算有优势。但前提是网络元件必须对称。配电网里负荷不对称、导线未换位、变压器接线组别多样,序网之间会相互耦合,还要额外引入耦合项,反而把模型搞复杂了。
相坐标法就没有这个问题:直接对A、B、C相建立方程,所有不对称因素都能自然体现。分布式电源接在哪一相,就直接把功率放在哪一相;负荷是三角形接法,直接用线电压计算。模型直观,概念简单,编程时也不用频繁做坐标变换。
所以,面向配电网的三相潮流计算程序,我最终选择相坐标法。这套程序里,每个母线不再是一个节点,而是对应三个节点:A相节点、B相节点、C相节点。如果是三相四线制,还需要考虑中性点节点,不过大多数配电网计算可以先把中性点电压消去,只保留ABC三相。
2.2 三相节点导纳矩阵Ybus的组装方法
单相潮流的Ybus是N乘N方阵,每个元素是一个复数。三相潮流程序里的Ybus规模则是3N乘3N,因为每相展开后都成了独立节点。
线路模型不能再用单一序阻抗,而要采用3乘3的相阻抗矩阵:
Zabc = [ Zaa Zab Zac ] [ Zba Zbb Zbc ] [ Zca Zcb Zcc ]其中Zaa是A相导线自阻抗,Zab是A相与B相之间的互阻抗。架空线路的相间互阻抗来自导线间磁场耦合;电缆线路由于护套和铠装的存在,相间耦合更复杂。建立线路相阻抗矩阵后,求逆得到相导纳矩阵Yabc,再按支路两端节点位置加入Ybus。
组装时的基本规则和单相潮流类似:
- 支路首端的3乘3子块加Yabc;
- 末端的3乘3子块也加Yabc;
- 首末端之间的互导纳子块减Yabc;
- 线路对地导纳Ysh按3乘3对角阵加入两端自导纳子块。
节点排列方式我习惯按“母线号优先、相序次之”来编号:母线0的A、B、C相分别对应第0、1、2个全局节点,母线1对应第3、4、5个全局节点。这种编号方式代码好写,索引直观,调试时也方便打印某条母线的三相数据。
2.3 变压器接线组别对Ybus的影响
变压器是三相互感,各种接线组合对相角、取向的影响是新手最容易出错的地方。不同接线方式分为两类问题:变比折算和相位移相。
- Yg-Yg(星形接地对星形接地):原副边电压同相位,只做变比折算,Ybus里就是一个导纳矩阵乘以变比平方。
- Y-D(星形对三角形):副边是线电压,绕组有30度移相。程序里副边必须先用绕组变换矩阵把相电压换算成线电压,再将变压器漏抗形成的导纳矩阵装配进去,否则算出来的幅值可能正确,相角却整体错位。
- D-D:没有相位移相,直接按变比折算。
- D-Yg:类似Y-D,只是移相方向相反。
这些处理最终都体现在Ybus对应的3乘3子块上,不是简单乘一个常数,而是乘一个3乘3的变换矩阵。程序功能说明里,我特别列出各接线组别的支持范围,用户在使用时必须指定变压器联结方式,否则程序默认按Yg-Yg处理,遇到三角形接线就会算错。
2.4 负荷模型:星形与三角形接法的换算
负荷建模也很关键。配电网负荷大致分三种模型:恒功率(PQ恒定)、恒电流(I恒定)、恒阻抗(Z恒定)。实际工程中大多数台区负荷按恒功率建模,但它也是牛顿-拉夫逊法收敛性最差的模型,因为电压跌了,功率却不跌,迭代就容易振荡。
负荷接法分为星形和三角形两类。星形负荷直接接到母线相端子和地(中性点)之间,某相吸收的复功率为:
Sa = Va * conj(Ia)计算注入电流时用:
Ia = conj(Sa / Va)三角形负荷则接在相与相之间,相电流由线电流合成。例如AB相之间接一个负荷,则:
Iab = conj(Sab / Vab)然后A相注入电流要综合Iab和Ica两路,B相综合Iab和Ibc,C相综合Ibc和Ica。程序里要先算线电压,再折算每相注入电流,最后带入潮流迭代方程。
很多三厢潮流程序在初始化时会允许用户选择负荷模型:恒功率模型最通用,计算速度慢一点;恒阻抗模型可以直接折算成导纳并入Ybus,让雅可比矩阵初始状态更健康,收敛速度明显更快。这套程序的逻辑是默认按恒功率迭代,但对重载台区建议先按恒阻抗迭代到初步收敛,再切换回恒功率,能大幅减少发散概率。
3. 牛顿-拉夫逊法在三相潮流中的应用拆解
3.1 程序到底在解哪些方程
三相牛顿-拉夫逊的推导思路和单相版本一脉相承,只是把所有量带上了相别下标。对第i条母线的m相(m=a,b,c),功率方程是:
Pim = Vim * Σ( Y * V ) 的实部 Qim = Vim * Σ( Y * V ) 的虚部程序从给定的负荷和发电功率出发,计算各母线各相的注入功率,然后与期望值比较,得到功率失配量:
ΔPim = Pim_给定 - Pim_计算 ΔQim = Qim_给定 - Qim_计算牛顿-拉夫逊法的目标就是通过迭代调整电压幅值和相角,把每个节点的ΔP和ΔQ压到接近零。
如果把某个系统看成N条母线,三相展开后有3N个相节点。每个三相PQ节点有6个未知量:Va、Vb、Vc的幅值和相角,对应6个方程:三相各有1个有功和1个无功方程。发电机节点则要把其中某相或三相的无功方程替换成电压幅值约束。
3.2 节点类型在三相模型下的延伸
这套程序延续了单相潮流的节点分类习惯,但有细微差别:
- 平衡节点(Slack):指定三相电压幅值和相角,通常取1.0、1.0、1.0和0度、-120度、120度。平衡节点用来承担系统功率差额。
- PQ节点:每相给定有功和无功,这是配电网中绝大多数负荷节点。单相光伏接在A相时,就只给A相一个PQ,B相和C相负荷为0。
- PV节点:每相给定有功和电压幅值,无功保持自由。适用于三相并网逆变器这类可以维持机端电压的设备。需要注意,三相PV节点比单相复杂:如果只有单相电源接在其中一相上,通常仍按PQ节点或恒阻抗节点处理,不强行设PV。
程序里对节点类型的设置不同,直接影响迭代时修正方程需要去掉哪些行和列。代码实现时,只需要维护一个自由度列表,把已知量从状态量集合里剔除,剩下的量交给雅可比矩阵求解。
3.3 雅可比矩阵的组成与迭代流程
牛顿-拉夫逊法的核心是雅可比矩阵J。在三相模型里,J仍然分成四个子块:
J = [ ∂P/∂θ ∂P/∂V ] [ ∂Q/∂θ ∂Q/∂V ]只是每个元素都要对应到具体的相别和母线。如果程序用解析公式,那么非对角线元素和单相潮流长得很像,例如第i条母线m相与第j条母线n相之间:
∂Pim/∂θjn = Vim * Vjn * (Gimjn * sin(θim-θjn) - Bimjn * cos(θim-θjn)) ∂Pim/∂Vjn = Vim * (Gimjn * cos(θim-θjn) + Bimjn * sin(θim-θjn))对角线元素可以直接套用教科书上的单相公式,把母线相别带上就行。不过这套程序第一个版本我建议先用数值差分构造雅可比矩阵,扰动电压幅值和相角,计算失配量变化梯度。这样能避免解析公式写错符号导致隐蔽错误。等到程序调试稳定、模型规模变大之后,再切换回解析雅可比来提速。
迭代流程可以概括为:
- 读入母线、线路、变压器、负荷数据,组装三相Ybus。
- 初始化所有节点电压为平启动:幅值取1.0,相角按正序排列。
- 计算各母线各相的注入功率和失配量,判断是否满足收敛条件。
- 构造雅可比矩阵。
- 求解修正方程,得到电压幅值和相角的修正量。
- 更新电压向量,回到第3步。
收敛判据我通常用两个:
- 功率失配绝对值最大值小于1e-6标幺值;
- 电压修正量最大值小于1e-8标幺值。
两个条件同时满足才认为收敛,缺任何一个都说明计算还在波动。
3.4 为什么配电网也敢用牛顿-拉夫逊
很多教材说配电网R/X比值很大,快速解耦法(Fast Decoupled)容易失效,但牛顿-拉夫逊法不会。因为牛顿-拉夫逊法完整保留了有功和无功对电压幅值、相角的全部耦合关系,不忽略任何交叉项。R/X大只影响系统矩阵的条件数,在阻尼因子调好的前提下,牛顿法依然能收敛。
所以配电网三相潮流程序,核心算法用牛顿-拉夫逊而不是快速解耦,是合理的。即使遇到电缆线路R/X比接近1甚至更高,程序只要加一个阻尼调整策略,照样能算下来。
4. 实操:三相潮流计算程序的功能实现
4.1 程序架构与模块划分
在实际实现里,程序通常分成五个模块:
- 数据输入模块:解析母线表、支路表、变压器表、负荷表。
- Ybus组装模块:根据线路和变压器参数建立三相导纳矩阵。
- 失配量计算模块:根据当前电压计算注入功率,求出ΔP和ΔQ。
- 雅可比矩阵模块:生成求解所需矩阵,支持解析式和数值差分两种模式。
- 后处理模块:输出每相电压、线路功率、损耗、不平衡度。
母线表至少要包含:母线编号、电压基准、负荷有功、负荷无功、发电机有功、发电机无功、节点类型、电压设定值。支路表至少包含:首端母线、末端母线、三相阻抗矩阵、对地导纳。变压器表则需要额外指定接线组别和分接头位置。
4.2 三相Ybus组装的Python示例
用Python实现时,scipy的稀疏矩阵是首选。下面是一段简化的Ybus组装代码:
import numpy as np from scipy.sparse import lil_matrix, csc_matrix def assemble_ybus(buses, branches): n_bus = len(buses) n3 = 3 * n_bus Y = lil_matrix((n3, n3), dtype=complex) for br in branches: f = 3 * br['from_bus'] t = 3 * br['to_bus'] zabc = br['zabc'] # 3x3 相阻抗矩阵 yabc = np.linalg.inv(zabc) Y[f:f+3, f:f+3] += yabc Y[t:t+3, t:t+3] += yabc Y[f:f+3, t:t+3] -= yabc Y[t:t+3, f:f+3] -= yabc # 对地导纳 Y[f:f+3, f:f+3] += br['ysh_f'] * np.eye(3) Y[t:t+3, t:t+3] += br['ysh_t'] * np.eye(3) return csc_matrix(Y)变压器支路不能直接套用这段代码,因为涉及移相和变比,要在组装前把变压器的3乘3等效导纳算出来,再合并进支路数据结构里。这个细节我在前面已经说明,实际工程中千万不能省。
节点编号约定会影响计算结果的可读性。我推荐“母线号乘3加相序”的索引方式:A相是3i,B相是3i+1,C相是3i+2。这样调试打印节点电压时,可以一行代码就还原出母线i的三相电压数组,排查起来非常方便。
4.3 核心牛顿-拉夫逊迭代循环
下面是迭代循环的示意代码,重点展示牛顿法主流程:
import numpy as np from scipy.sparse.linalg import spsolve def run_powerflow(Y, bus_spec, free_idx, tol=1e-6, max_iter=50): n_free = len(free_idx) V = np.ones(3 * len(bus_spec), dtype=complex) th = np.zeros(3 * len(bus_spec)) vm = np.ones(3 * len(bus_spec)) for it in range(max_iter): F = mismatch(Y, V, bus_spec, free_idx) if np.max(np.abs(F)) < tol: break J = numeric_jacobian(Y, V, bus_spec, free_idx, mismatch, eps=1e-6) dx = spsolve(J, -F) th[free_idx] += dx[:n_free] vm[free_idx] += dx[n_free:] V = vm * np.exp(1j * th) return V这里的mismatch函数返回所有自由节点的ΔP和ΔQ拼接向量;numeric_jacobian函数通过对每个自由状态量施加微小扰动,重新计算失配量,得到雅可比矩阵。第一次实现时用扰动法最不容易出错,等程序验证通过后再改解析雅可比。
需要特别提醒:代码中dx = spsolve(J, -F)是因为F的定义是“给定值减计算值”,失配量需要沿负梯度方向修正。很多人在第一次写牛顿法时最容易在这个符号上栽跟头。如果你在论文或教科书里看到的是J·Δx = ΔS,那只是正负号约定不同,只要保证失配定义和修正方向一致即可。
4.4 后处理功能输出
收敛后,程序要输出几个关键指标:
- 节点三相电压表:母线号、A相幅值、A相相角、B相幅值、B相相角、C相幅值、C相相角。
- 三相电压不平衡度:按负序与正序比值计算,常用公式是负序分量幅值除以正序分量幅值。
- 支路分相功率:每条支路首端和末端的A、B、C相有功、无功、电流。
- 线损分相统计:把每条线路首末两端功率差的实部按相累加,得到A、B、C相损耗。
- 中性线电流估算:用三相电流向量求和,公式为 In = Ia + Ib + Ic。
这些输出能直接对接电压质量评估报告,对“改造台区时先处理哪一相”这类问题很有参考价值。
5. 常见问题与排查技巧实录
5.1 不收敛:先怀疑初值和重载
程序上线以来,我们遇到最多的就是不收敛。排查顺序一般是:
先看是不是负荷模型的问题。恒功率负荷在低压重载场景下最容易导致迭代振荡,尤其是电压值已经偏低时,功率方程会出现无解或病态解。解决办法有三个:把恒功率负荷先改成恒阻抗试算一次;给迭代加阻尼系数(0.8左右);或者按负载率分阶段加载,比如先带30%负荷迭代收敛,再把负荷逐步加到100%,每步以上一步结果作初值。
再看是不是模型存在孤立节点或悬空节点。三相程序中,如果某条母线的C相没有接任何线路和负荷,C相节点会在雅可比矩阵里形成零行零列,直接导致矩阵奇异。排查时打印Ybus每行非零元个数,很容易发现这类问题。
5.2 变压器接线组别导致的结果错误
变压器是三相潮流里最隐蔽的错误源。曾经有个模拟项目,程序反正能收敛,但结果每相电压都偏得离谱。最后检查发现,用户输入变压器数据时没有指定接线组别,程序默认按Yg-Yg处理,而实际台区变压器是D-Yg接法,副边相角整体差了30度。
这种错误有一个快速识别特征:三相电压幅值还算正常,但相角关系不再是近似0度、-120度、120度的对称分布,而是整体偏移或两两之间角度畸变。发现问题后,在变压器支路数据里显式指定接线组别,让Ybus组装的绕组变换矩阵生效,结果立刻恢复正常。
5.3 三相程序与单相程序互相校验的小技巧
这个技巧是我个人强烈推荐的。程序编完之后,不急着做复杂算例,先构造一个完全对称的三相系统:三相负荷相等,线路参数对称。此时三相潮流的结果应该退化为单相潮流的结果,A相、B相、C相电压幅值完全相同,相角互差120度。
再用第二个算例:三条完全独立的单相线路,线路之间没有耦合,负荷分别接在每条相上。三相程序算出来的每条相结果,应该和三组独立单相潮流的结果一致。这两个测试通过后,程序的核心求解逻辑才算真正可靠。
5.4 分布式光伏接入后的收敛性处理
某个低压台区模拟项目里,馈线上接了上百台单相光伏逆变器。光伏功率大、接入点多,程序从全负荷平启动开始直接算,经常在第七八次迭代后发散。排查之后发现,光伏节点按恒功率PQ建模,在电压偏低时恒功率特性会加剧迭代振荡。
处理方式是引入连续化求解思想:先让所有光伏出力设置为0,跑一个收敛结果作为初值;然后把光伏出力按20%、50%、80%、100%四档逐级增加,每一档都以下一档初值继续迭代。这个思路本质上类似于连续潮流法,代码改动量很小,但收敛稳定性提升非常明显。之后这套程序在类似场景下基本没有再遇到发散问题。
结尾不想多写总结,最后分享一个调试习惯
程序调试阶段,我最后一步总会做“反向测试”:把系统里所有单相负荷换到另一相,再比较两次结果。比如负荷原本都在A相,程序算出A相电压偏低;把负荷转移到B相后,B相电压应该同步偏低。这个简单测试能快速发现相序映射错误,因为很多三相程序的bug都出在节点编号和相别对应关系上。
还有个小建议,迭代过程里每轮都打印最大失配量和最大电压修正量,不要只等最终结果。看到失配量从1e-2降到1e-4再降到1e-6,你会对整个求解过程心里有数;看到它来回震荡,就能提前判断是不是阻尼太小或负荷过重。三相潮流的复杂性不在于算法本身,而在于建模细节和调试功夫,多留点心眼,程序才真正在工程上靠得住。