跳到主内容

潮流计算实战

教程

潮流计算实战

本教程演示如何使用 EnerOS 执行 IEEE 14-bus 标准测试系统的潮流计算,涵盖网络建模、求解、结果分析、越限校验、持久化与可视化全过程。

潮流计算是电力系统分析的基础,用于求解给定网络结构与边界条件下的稳态运行点(各母线电压幅值与相角、各支路功率分布)。EnerOS 将潮流求解器下沉到内核态(eneros-powerflow crate),所有 Agent 与上层应用可通过系统调用直接调用,无需重复建模。

准备工作

确保已按 安装与构建 完成 EnerOS 构建,并能正常运行 eneros-api。本教程涉及以下 crate:

Crate作用
eneros-topology网络拓扑建模(母线、支路、开关)
eneros-powerflow潮流求解器(牛顿-拉夫逊、快速解耦、直流)
eneros-core基础类型(BusTypeBranchTypeYBusMatrix
eneros-timeseries时序数据持久化
eneros-apiREST/WebSocket 接口与可视化前端

新建一个二进制 crate 并添加依赖:

[package]
name = "ieee14-tutorial"
version = "0.1.0"
edition = "2021"

[dependencies]
eneros-topology = { path = "../eneros/crates/eneros-topology" }
eneros-powerflow = { path = "../eneros/crates/eneros-powerflow" }
eneros-core = { path = "../eneros/crates/eneros-core" }
eneros-timeseries = { path = "../eneros/crates/eneros-timeseries" }
tokio = { version = "1", features = ["full"] }

IEEE 14-bus 系统概览

IEEE 14-bus 是美国电气电子工程师协会发布的标准测试系统,广泛用于潮流算法验证。其拓扑如下:

  • 14 个母线:1 个 Slack(平衡节点)、4 个 PV(电压控制节点)、9 个 PQ(负荷节点)
  • 20 条支路:16 条线路 + 4 台变压器(含 3 台非标准变比变压器)
  • 基准容量:100 MVA
  • 9 号母线:装有 19 MVar 并联电容器
母线编号类型电压 (p.u.)P 注入 (MW)Q 注入 (MVar)
1Slack1.060平衡计算平衡计算
2PV1.04518.3-12.7
3PV1.010-94.2-19.0
4PQ1.019-47.83.9
5PQ1.020-7.6-1.6
6PV1.070-11.2-7.5
7PQ1.0620.00.0
8PV1.0900.00.0
9PQ1.056-29.5-16.6
10PQ1.051-9.0-5.8
11PQ1.057-3.5-1.8
12PQ1.055-6.1-1.6
13PQ1.050-13.5-5.8
14PQ1.036-14.9-5.0
支路 (From-To)类型R (p.u.)X (p.u.)B/2 (p.u.)变比
1-2线路0.019380.059170.05281.0
1-5线路0.054030.223040.04921.0
2-3线路0.046990.197970.04381.0
2-4线路0.058110.176320.03401.0
2-5线路0.056950.173880.03461.0
3-4线路0.067010.171030.01281.0
4-5线路0.013350.042110.01.0
4-7变压器0.00.209120.00.978
4-9变压器0.00.556180.00.969
5-6变压器0.00.252020.00.932
6-11线路0.094980.198900.01.0
6-12线路0.122910.255810.01.0
6-13线路0.066150.130270.01.0
7-8变压器0.00.176150.00.969
7-9线路0.00.110010.01.0
9-10线路0.031810.084500.01.0
9-14线路0.127110.270380.01.0
10-11线路0.082050.192070.01.0
12-13线路0.220920.199880.01.0
13-14线路0.170930.348020.01.0

步骤 1:构建网络拓扑

使用 eneros_topology::NetworkGraph 构建 IEEE 14-bus 网络。Slack 母线指定电压幅值与相角,PV 母线指定电压幅值与有功注入,PQ 母线指定有功/无功负荷。下面给出完整的母线与支路定义(无任何省略):

use eneros_topology::{NetworkGraph, Bus, Branch, BusType, BranchType};
use eneros_core::ElementId;

/// 构建 IEEE 14-bus 标准测试系统的网络拓扑
fn build_ieee14_network() -> NetworkGraph {
    let mut graph = NetworkGraph::new();

    // ===================== 母线定义 =====================
    // 1 号:Slack(平衡节点),V=1.06 p.u.,θ=0°
    graph.bus_add(Bus {
        id: 1,
        name: "Bus1_Slack".into(),
        bus_type: BusType::Slack,
        voltage_kv: 138.0,
        zone_id: 1,
        bus_type_pf: BusType::Slack,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 0.0,
        q_load: 0.0,
        v_pu: 1.060,
    });

    // 2 号:PV,P_inj=18.3 MW(发电 40 - 负荷 21.7),V=1.045 p.u.
    graph.bus_add(Bus {
        id: 2,
        name: "Bus2_PV".into(),
        bus_type: BusType::PV,
        voltage_kv: 138.0,
        zone_id: 1,
        bus_type_pf: BusType::PV,
        p_gen: 40.0,
        q_gen: 0.0,
        p_load: 21.7,
        q_load: 12.7,
        v_pu: 1.045,
    });

    // 3 号:PV(同步调相机),P_inj=-94.2 MW,V=1.010 p.u.
    graph.bus_add(Bus {
        id: 3,
        name: "Bus3_PV".into(),
        bus_type: BusType::PV,
        voltage_kv: 138.0,
        zone_id: 1,
        bus_type_pf: BusType::PV,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 94.2,
        q_load: 19.0,
        v_pu: 1.010,
    });

    // 4 号:PQ,P_inj=-47.8 MW,Q_inj=3.9 MVar(容性负荷)
    graph.bus_add(Bus {
        id: 4,
        name: "Bus4_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 138.0,
        zone_id: 1,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 47.8,
        q_load: -3.9,
        v_pu: 1.019,
    });

    // 5 号:PQ,P_inj=-7.6 MW,Q_inj=-1.6 MVar
    graph.bus_add(Bus {
        id: 5,
        name: "Bus5_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 138.0,
        zone_id: 1,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 7.6,
        q_load: 1.6,
        v_pu: 1.020,
    });

    // 6 号:PV,P_inj=-11.2 MW,V=1.070 p.u.
    graph.bus_add(Bus {
        id: 6,
        name: "Bus6_PV".into(),
        bus_type: BusType::PV,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PV,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 11.2,
        q_load: 7.5,
        v_pu: 1.070,
    });

    // 7 号:PQ,无负荷
    graph.bus_add(Bus {
        id: 7,
        name: "Bus7_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 0.0,
        q_load: 0.0,
        v_pu: 1.062,
    });

    // 8 号:PV(同步调相机),V=1.090 p.u.
    graph.bus_add(Bus {
        id: 8,
        name: "Bus8_PV".into(),
        bus_type: BusType::PV,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PV,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 0.0,
        q_load: 0.0,
        v_pu: 1.090,
    });

    // 9 号:PQ,P_inj=-29.5 MW,装有 19 MVar 并联电容器
    graph.bus_add(Bus {
        id: 9,
        name: "Bus9_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 29.5,
        q_load: 16.6,
        v_pu: 1.056,
    });

    // 10 号:PQ,P_inj=-9.0 MW
    graph.bus_add(Bus {
        id: 10,
        name: "Bus10_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 9.0,
        q_load: 5.8,
        v_pu: 1.051,
    });

    // 11 号:PQ,P_inj=-3.5 MW
    graph.bus_add(Bus {
        id: 11,
        name: "Bus11_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 3.5,
        q_load: 1.8,
        v_pu: 1.057,
    });

    // 12 号:PQ,P_inj=-6.1 MW
    graph.bus_add(Bus {
        id: 12,
        name: "Bus12_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 6.1,
        q_load: 1.6,
        v_pu: 1.055,
    });

    // 13 号:PQ,P_inj=-13.5 MW
    graph.bus_add(Bus {
        id: 13,
        name: "Bus13_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 13.5,
        q_load: 5.8,
        v_pu: 1.050,
    });

    // 14 号:PQ,P_inj=-14.9 MW
    graph.bus_add(Bus {
        id: 14,
        name: "Bus14_PQ".into(),
        bus_type: BusType::PQ,
        voltage_kv: 13.8,
        zone_id: 2,
        bus_type_pf: BusType::PQ,
        p_gen: 0.0,
        q_gen: 0.0,
        p_load: 14.9,
        q_load: 5.0,
        v_pu: 1.036,
    });

    // ===================== 支路定义 =====================
    // 辅助函数:添加线路
    let add_line = |g: &mut NetworkGraph, id: ElementId, from: ElementId, to: ElementId,
                    r: f64, x: f64, b: f64| {
        g.branch_add(Branch {
            id,
            name: format!("Line_{}_{}", from, to),
            from_bus: from,
            to_bus: to,
            branch_type: BranchType::Line,
            status: true,
            r, x, b,
            tap_ratio: 1.0,
        });
    };

    // 辅助函数:添加变压器
    let add_tx = |g: &mut NetworkGraph, id: ElementId, from: ElementId, to: ElementId,
                  x: f64, tap: f64| {
        g.branch_add(Branch {
            id,
            name: format!("Tx_{}_{}", from, to),
            from_bus: from,
            to_bus: to,
            branch_type: BranchType::Transformer,
            status: true,
            r: 0.0, x, b: 0.0,
            tap_ratio: tap,
        });
    };

    // 7 条线路(主网架)
    add_line(&mut graph, 101, 1, 2, 0.01938, 0.05917, 0.0528);
    add_line(&mut graph, 102, 1, 5, 0.05403, 0.22304, 0.0492);
    add_line(&mut graph, 103, 2, 3, 0.04699, 0.19797, 0.0438);
    add_line(&mut graph, 104, 2, 4, 0.05811, 0.17632, 0.0340);
    add_line(&mut graph, 105, 2, 5, 0.05695, 0.17388, 0.0346);
    add_line(&mut graph, 106, 3, 4, 0.06701, 0.17103, 0.0128);
    add_line(&mut graph, 107, 4, 5, 0.01335, 0.04211, 0.0);

    // 3 台变压器(4-7、4-9、5-6),含非标准变比
    add_tx(&mut graph, 201, 4, 7, 0.20912, 0.978);
    add_tx(&mut graph, 202, 4, 9, 0.55618, 0.969);
    add_tx(&mut graph, 203, 5, 6, 0.25202, 0.932);

    // 6-11、6-12、6-13 线路
    add_line(&mut graph, 108, 6, 11, 0.09498, 0.19890, 0.0);
    add_line(&mut graph, 109, 6, 12, 0.12291, 0.25581, 0.0);
    add_line(&mut graph, 110, 6, 13, 0.06615, 0.13027, 0.0);

    // 7-8 变压器(含非标准变比)
    add_tx(&mut graph, 204, 7, 8, 0.17615, 0.969);

    // 7-9、9-10、9-14、10-11、12-13、13-14 线路
    add_line(&mut graph, 111, 7, 9, 0.0, 0.11001, 0.0);
    add_line(&mut graph, 112, 9, 10, 0.03181, 0.08450, 0.0);
    add_line(&mut graph, 113, 9, 14, 0.12711, 0.27038, 0.0);
    add_line(&mut graph, 114, 10, 11, 0.08205, 0.19207, 0.0);
    add_line(&mut graph, 115, 12, 13, 0.22092, 0.19988, 0.0);
    add_line(&mut graph, 116, 13, 14, 0.17093, 0.34802, 0.0);

    graph
}

fn main() {
    let network = build_ieee14_network();
    println!("母线数: {}", network.bus_count());
    println!("支路数: {}", network.branch_count());
    println!("连通区域数: {}", network.zone_count());
}

执行后应输出:

母线数: 14
支路数: 20
连通区域数: 1

:::tip 使用内置 IEEE 14 数据 eneros-powerflow 已内置完整的 IEEE 14-bus 标准数据,可直接通过 ieee14() 函数获取,无需手动构建。本节展示手动构建过程是为了让读者理解网络建模的完整流程。 :::

步骤 2:转换为求解器输入

NetworkGraph::to_solver_input(base_mva) 将拓扑导出为潮流求解器所需的四元组:

use eneros_core::BusTypeNR;

let base_mva = 100.0;
let (ybus, p_spec, q_spec, bus_types, v_initial) = network.to_solver_input(base_mva);

println!("Y-Bus 维度: {}x{}", ybus.size(), ybus.size());
println!("非零元数: {}", ybus.nnz());
println!("P_spec (p.u.): {:?}", p_spec);
println!("bus_types: {:?}", bus_types);

输出示例:

Y-Bus 维度: 14x14
非零元数: 56
P_spec (p.u.): [0.0, 0.183, -0.942, -0.478, ...]
bus_types: [Slack, PV, PV, PQ, PQ, PV, PQ, PV, PQ, PQ, PQ, PQ, PQ, PQ]

导出过程做了以下处理:

字段说明
ybus节点导纳矩阵,包含支路 R/X/B 与变压器变比
p_spec每个节点的有功注入 (p_gen - p_load) / base_mva(标幺值)
q_spec每个节点的无功注入 (q_gen - q_load) / base_mva(标幺值)
bus_types节点类型枚举(Slack / PV / PQ),决定求解变量
v_initial初始电压幅值(来自 Bus::v_pu),用于热启动

步骤 3:配置并执行潮流求解

EnerOS 提供三种潮流算法:

算法适用场景收敛性速度
NewtonRaphson输电网、环网二阶收敛
BackwardForwardSweep配电网、辐射状一阶收敛
DC实时筛查、规划线性最快

对 IEEE 14-bus 推荐牛顿-拉夫逊法:

use eneros_powerflow::{PowerFlowSolver, PowerFlowAlgorithm};

let solver = PowerFlowSolver::new(50, 1e-8)
    .with_algorithm(PowerFlowAlgorithm::NewtonRaphson);

let result = solver.solve_with_initial(
    &ybus,
    &p_spec,
    &q_spec,
    &bus_types,
    Some(&v_initial),
)?;

println!("收敛: {}", result.converged);
println!("迭代次数: {}", result.iterations);
println!("最大失配: {:.2e}", result.max_mismatch);
println!("总网损: {:.4} MW", result.total_losses * base_mva);

输出示例:

收敛: true
迭代次数: 4
最大失配: 3.21e-09
总网损: 13.8392 MW

启用 Q 限制

PV 母线的无功出力可能超出发电机容量。启用 Q 限制后,越限的 PV 母线会自动转换为 PQ 母线:

use eneros_powerflow::QLimits;

let mut q_limits = QLimits::new();
// 2 号机:Q ∈ [-50, 50] MVar
q_limits.add(1, -0.50, 0.50); // bus_idx=1(即 2 号母线),单位 p.u.
// 6 号机:Q ∈ [-25, 25] MVar
q_limits.add(5, -0.25, 0.25);

let result_q = solver.solve_with_options(
    &ybus, &p_spec, &q_spec, &bus_types,
    Some(&v_initial), Some(&q_limits), None,
)?;
println!("Q 限制后总网损: {:.4} MW", result_q.total_losses * base_mva);

使用 Recycle Cache 加速

对于拓扑不变的连续求解(如时序潮流),可复用上次电压结果作为初始值,减少迭代次数:

use eneros_powerflow::RecycleCache;

let mut cache = RecycleCache::new();
// 第一次求解
let r1 = solver.solve_with_options(
    &ybus, &p_spec, &q_spec, &bus_types,
    None, None, None,
)?;
cache.update(
    &r1.bus_results.iter().map(|b| b.voltage_magnitude).collect::<Vec<_>>(),
    &r1.bus_results.iter().map(|b| b.voltage_angle).collect::<Vec<_>>(),
);

// 第二次求解(负荷微调后),复用缓存
let p_spec_2: Vec<f64> = p_spec.iter().map(|p| p * 1.05).collect();
let r2 = solver.solve_with_options(
    &ybus, &p_spec_2, &q_spec, &bus_types,
    None, None, Some(&cache),
)?;
println!("复用缓存后迭代次数: {}", r2.iterations);

步骤 4:查看与导出结果

逐母线打印电压幅值与相角,并与 IEEE 标准参考值对比:

println!("{:>6} {:>10} {:>10} {:>12} {:>10}",
    "Bus", "V(pu)", "θ(°)", "P_inj(MW)", "Q(MVar)");
println!("{}", "-".repeat(54));

for br in &result.bus_results {
    let angle_deg = br.voltage_angle.to_degrees();
    println!("{:>6} {:>10.4} {:>10.4} {:>12.4} {:>10.4}",
        br.bus_id + 1,  // 转回 1-based
        br.voltage_magnitude,
        angle_deg,
        br.p_injection * base_mva,
        br.q_injection * base_mva,
    );
}

输出示例:

  Bus     V(pu)      θ(°)   P_inj(MW)     Q(MVar)
------------------------------------------------------
     1     1.0600     0.0000     232.3863    -16.5467
     2     1.0450    -4.9826      18.3000     33.5234
     3     1.0100   -12.7242     -94.2000     25.1468
     4     1.0187   -10.3129     -47.8000      3.9000
     5     1.0202    -8.7813      -7.6000     -1.6000
     6     1.0700   -14.2210     -11.2000     12.7312
     7     1.0620   -13.3620       0.0000      0.0000
     8     1.0900   -13.3620       0.0000     17.5654
     9     1.0564   -14.9385     -29.5000    -16.6000
    10     1.0514   -15.0982      -9.0000     -5.8000
    11     1.0569   -14.7953      -3.5000     -1.8000
    12     1.0552   -15.0736      -6.1000     -1.6000
    13     1.0505   -15.1548     -13.5000     -5.8000
    14     1.0356   -16.0336     -14.9000     -5.0000

支路潮流与网损

println!("{:>10} {:>10} {:>10} {:>10} {:>10}",
    "支路", "P_from(MW)", "Q_from", "P_to(MW)", "网损(MW)");
println!("{}", "-".repeat(56));

for br in &result.branch_results {
    println!("{:>4}-{::<5} {:>10.4} {:>10.4} {:>10.4} {:>10.4}",
        br.from_bus + 1, br.to_bus + 1,
        br.p_from * base_mva,
        br.q_from * base_mva,
        br.p_to * base_mva,
        br.loss_mw * base_mva,
    );
}

println!("\n系统总网损: {:.4} MW", result.total_losses * base_mva);

步骤 5:越限校验

约束校验是 EnerOS 内核强制的”法律”。即便在教程场景中,也应主动检查电压与支路负载率是否越限:

fn check_violations(result: &eneros_powerflow::PowerFlowResult, base_mva: f64) {
    // 电压越限检查(正常运行范围 0.95 ~ 1.05 p.u.,紧急范围 0.90 ~ 1.10)
    let v_min_normal = 0.95;
    let v_max_normal = 1.05;
    let mut v_violations = 0;

    for bus in &result.bus_results {
        if bus.voltage_magnitude < v_min_normal || bus.voltage_magnitude > v_max_normal {
            eprintln!("[电压越限] Bus {}: V={:.4} pu (允许范围 {}-{})",
                bus.bus_id + 1, bus.voltage_magnitude, v_min_normal, v_max_normal);
            v_violations += 1;
        }
    }

    // 支路过载检查
    let loading_limit = 100.0; // %
    let mut b_violations = 0;

    for branch in &result.branch_results {
        if branch.loading_percent > loading_limit {
            eprintln!("[支路过载] Branch {}-{}: {:.1}% (> {}%)",
                branch.from_bus + 1, branch.to_bus + 1,
                branch.loading_percent, loading_limit);
            b_violations += 1;
        }
    }

    println!("\n越限统计: 电压={}, 支路={}", v_violations, b_violations);
    if v_violations == 0 && b_violations == 0 {
        println("✓ 所有约束满足");
    }
}

check_violations(&result, base_mva);

输出示例:

[电压越限] Bus 1: V=1.0600 pu (允许范围 0.95-1.05)
[电压越限] Bus 6: V=1.0700 pu (允许范围 0.95-1.05)
[电压越限] Bus 8: V=1.0900 pu (允许范围 0.95-1.05)

越限统计: 电压=3, 支路=0

:::warning 1 号、6 号、8 号为 PV 母线,其电压由发电机/调相机控制为 1.06 / 1.07 / 1.09,超出常规负荷母线的 0.95-1.05 范围是正常的。实际工程中应按母线类型分别设置约束。 :::

步骤 6:持久化与可视化

将结果写入时序引擎,便于历史回放与趋势分析:

use eneros_timeseries::{TimeseriesEngine, WriteOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut ts = TimeseriesEngine::open("/var/lib/eneros/ts")?;

    let opts = WriteOptions::default().tags([
        ("system", "ieee14"),
        ("scenario", "base_case"),
    ]);

    // 逐母线写入电压时序
    for bus in &result.bus_results {
        let point_name = format!("ieee14.bus{}.voltage", bus.bus_id + 1);
        ts.write_point(&point_name, bus.voltage_magnitude, &opts).await?;
    }

    // 写入系统级指标
    ts.write_point("ieee14.total_losses_mw",
        result.total_losses * base_mva, &opts).await?;
    ts.write_point("ieee14.iterations",
        result.iterations as f64, &opts).await?;

    println!("✓ 已写入 {} 个测点", result.bus_results.len() + 1);
    Ok(())
}

通过 REST API 触发可视化前端刷新:

let client = eneros_api::Client::new("https://api.eneros.internal");

// 发布潮流结果到事件总线
client.publish("/topics/powerflow/ieee14", &result).await?;

// 触发可视化前端刷新单线图
client.post("/api/visualization/refresh")
    .json(&serde_json::json!({
        "network_id": "ieee14",
        "result_id": result.id(),
        "layers": ["voltage", "loading", "loss"],
    }))
    .await?;

步骤 7:完整端到端示例

将上述步骤整合为一个完整的可运行程序:

use eneros_powerflow::{ieee14, PowerFlowSolver, PowerFlowAlgorithm};

fn main() -> eneros_core::Result<()> {
    // 1. 加载 IEEE 14-bus 标准数据
    let data = ieee14();
    println!("加载网络: {} 母线, {} 支路", data.buses.len(), data.branches.len());

    // 2. 转换为求解器输入
    let (ybus, p_spec, q_spec, bus_types) = data.to_solver_input();
    let v_initial: Vec<f64> = data.buses.iter().map(|b| b.v_pu).collect();

    // 3. 求解
    let solver = PowerFlowSolver::new(100, 1e-8)
        .with_algorithm(PowerFlowAlgorithm::NewtonRaphson);
    let result = solver.solve_with_initial(
        &ybus, &p_spec, &q_spec, &bus_types, Some(&v_initial))?;

    // 4. 输出关键指标
    println!("收敛: {}, 迭代: {}, 失配: {:.2e}",
        result.converged, result.iterations, result.max_mismatch);
    println!("总网损: {:.4} MW", result.total_losses * data.base_mva);

    // 5. Slack 母线有功(应接近 232.4 MW)
    let slack_p = result.bus_results[0].p_injection * data.base_mva;
    println!("Slack 有功: {:.2} MW (期望 ≈232.4 MW)", slack_p);

    // 6. 越限校验
    let overloaded = result.branch_results.iter()
        .filter(|b| b.loading_percent > 100.0)
        .count();
    println!("过载支路数: {}", overloaded);

    Ok(())
}

验证

按以下指标验证求解正确性:

指标期望值容差
收敛性true
迭代次数3-5 次< 20
最大失配< 1e-8 p.u.
Slack 有功≈ 232.4 MW±1%
总网损≈ 13.8 MW±1 MW
所有母线电压0.9-1.1 p.u.
支路负载率< 100%

调试技巧

  • 不收敛:检查 PV 母线是否有足够的无功容量,启用 Q 限制
  • 网损偏大:检查变压器变比是否正确(0.978/0.969/0.932/0.969)
  • 电压异常:检查 9 号母线的并联电容器(19 MVar = 0.19 p.u.)
  • 迭代过多:使用 v_initial 热启动,或启用 RecycleCache
  • Y-Bus 错误:确认支路 B 值是总充电电纳(非 B/2)

命令行验证

# 运行单元测试
cargo test -p eneros-powerflow test_ieee14 -- --nocapture

# 查看详细输出
RUST_LOG=eneros_powerflow=debug cargo run --release

下一步