跳到主内容

eneros-powerflow

Crate 索引

eneros-powerflow

eneros-powerflow 提供电力系统潮流计算求解器,采用 Newton-Raphson 主方法,并支持 PQ 解耦与直流潮流作为快速近似。基于 eneros-linalg 的稀疏 LU 分解,1000 节点网络典型求解时间 < 10ms。潮流结果是约束校验、OPF、孪生体等上层分析的输入。

职责描述

eneros-powerflow 承担以下核心职责:

  • YBus 构建:根据 eneros-topology 提供的网络拓扑,构建稀疏 CSR 格式的节点导纳矩阵
  • Newton-Raphson 求解:使用全雅可比矩阵迭代求解,自动处理 PQ / PV / Slack 三类节点
  • 快速近似:提供 P-Q 解耦(FastDecoupled)与直流潮流(DC)两种轻量求解器
  • 收敛诊断:功率残差 < 1e-8 收敛判定,发散时返回残差曲线供分析
  • 结果缓存:拓扑未变更时复用上次结果,避免重复计算
  • 支路潮流:求解后计算每条支路的有功、无功、损耗与负载率

关键类型与接口

PowerFlowSolver

use std::time::Duration;
use eneros_core::{BusId, BranchId, Result};
use eneros_topology::NetworkGraph;

pub struct PowerFlowSolver {
    method: PowerFlowMethod,
    tolerance: f64,
    max_iterations: usize,
    enable_cache: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PowerFlowMethod {
    NewtonRaphson,
    FastDecoupled,
    DcPowerFlow,
}

impl Default for PowerFlowSolver {
    fn default() -> Self {
        Self {
            method: PowerFlowMethod::NewtonRaphson,
            tolerance: 1e-8,
            max_iterations: 50,
            enable_cache: true,
        }
    }
}

impl PowerFlowSolver {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn method(mut self, m: PowerFlowMethod) -> Self {
        self.method = m;
        self
    }

    pub fn tolerance(mut self, t: f64) -> Self {
        self.tolerance = t;
        self
    }

    pub fn max_iterations(mut self, n: usize) -> Self {
        self.max_iterations = n;
        self
    }

    pub fn enable_cache(mut self, on: bool) -> Self {
        self.enable_cache = on;
        self
    }

    pub fn solve(&self, network: &NetworkGraph) -> Result<PowerFlowResult> {
        let ybus = YBusMatrix::build(network);
        let start = std::time::Instant::now();
        let inner = match self.method {
            PowerFlowMethod::NewtonRaphson => Self::solve_nr(network, &ybus, self.tolerance, self.max_iterations)?,
            PowerFlowMethod::FastDecoupled => Self::solve_fd(network, &ybus, self.tolerance, self.max_iterations)?,
            PowerFlowMethod::DcPowerFlow => Self::solve_dc(network, &ybus)?,
        };
        let duration = start.elapsed();
        let branch_flows = Self::compute_branch_flows(network, &inner.buses);
        Ok(PowerFlowResult {
            converged: inner.converged,
            iterations: inner.iterations,
            residual: inner.residual,
            duration,
            buses: inner.buses,
            branch_flows,
        })
    }
}

YBusMatrix

use eneros_linalg::SparseMatrix;

pub struct YBusMatrix {
    pub data: SparseMatrix<Complex64>,
    pub bus_order: Vec<BusId>,
}

impl YBusMatrix {
    pub fn build(network: &NetworkGraph) -> Self {
        let buses: Vec<BusId> = collect_bus_ids(network);
        let n = buses.len();
        let mut matrix = SparseMatrix::new(n, n);
        let index: HashMap<BusId, usize> = buses
            .iter()
            .enumerate()
            .map(|(i, id)| (id.clone(), i))
            .collect();

        for branch in network.iter_branches() {
            if branch.status != BranchStatus::Closed {
                continue;
            }
            let i = index[&branch.from];
            let j = index[&branch.to];
            let z = Complex64::new(branch.params.r_pu, branch.params.x_pu);
            let y = Complex64::new(0.0, 0.0) - z.inv();
            matrix.add(i, j, -y);
            matrix.add(j, i, -y);
            matrix.add(i, i, y + Complex64::new(0.0, branch.params.b_pu / 2.0));
            matrix.add(j, j, y + Complex64::new(0.0, branch.params.b_pu / 2.0));
        }

        Self { data: matrix, bus_order: buses }
    }
}

PowerFlowResult

use eneros_core::{Voltage, BusId, BranchId};

pub struct PowerFlowResult {
    pub converged: bool,
    pub iterations: usize,
    pub residual: f64,
    pub duration: Duration,
    pub buses: Vec<BusSolution>,
    pub branch_flows: Vec<BranchFlow>,
}

#[derive(Debug, Clone)]
pub struct BusSolution {
    pub id: BusId,
    pub voltage: Voltage,
    pub p_pu: f64,
    pub q_pu: f64,
}

#[derive(Debug, Clone)]
pub struct BranchFlow {
    pub from: BusId,
    pub to: BusId,
    pub p_from_pu: f64,
    pub q_from_pu: f64,
    pub p_to_pu: f64,
    pub q_to_pu: f64,
    pub loading_percent: f64,
    pub loss_pu: f64,
}

impl PowerFlowResult {
    pub fn bus_by_id(&self, id: &BusId) -> Option<&BusSolution> {
        self.buses.iter().find(|b| &b.id == id)
    }

    pub fn total_loss_pu(&self) -> f64 {
        self.branch_flows.iter().map(|f| f.loss_pu).sum()
    }

    pub fn max_loading(&self) -> Option<&BranchFlow> {
        self.branch_flows.iter().max_by(|a, b| {
            a.loading_percent.partial_cmp(&b.loading_percent).unwrap()
        })
    }
}

核心 API

方法签名说明
PowerFlowSolver::newfn new() -> Self构造默认求解器(NR / 1e-8 / 50 iter)
PowerFlowSolver::methodfn method(self, m: PowerFlowMethod) -> Self设置求解方法
PowerFlowSolver::tolerancefn tolerance(self, t: f64) -> Self设置收敛容差
PowerFlowSolver::max_iterationsfn max_iterations(self, n: usize) -> Self设置最大迭代次数
PowerFlowSolver::enable_cachefn enable_cache(self, on: bool) -> Self启用/禁用结果缓存
PowerFlowSolver::solvefn solve(&self, network: &NetworkGraph) -> Result<PowerFlowResult>执行潮流计算
YBusMatrix::buildfn build(network: &NetworkGraph) -> Self构建节点导纳矩阵
PowerFlowResult::bus_by_idfn bus_by_id(&self, id: &BusId) -> Option<&BusSolution>按母线 ID 查询解
PowerFlowResult::total_loss_pufn total_loss_pu(&self) -> f64网络总有功损耗(标幺值)
PowerFlowResult::max_loadingfn max_loading(&self) -> Option<&BranchFlow>最大负载率支路

使用示例

基础潮流计算

use eneros_powerflow::{PowerFlowSolver, PowerFlowMethod};
use eneros_topology::{NetworkGraph, Bus, Branch, BranchParams, BusType};
use eneros_core::Voltage;

let mut net = NetworkGraph::new();
net.add_bus(Bus::new("1", BusType::Slack, Voltage::new(1.05, 0.0)));
net.add_bus(Bus::new("2", BusType::PQ,   Voltage::new(1.00, 0.0)));
net.add_bus(Bus::new("3", BusType::PV,   Voltage::new(1.02, 0.0)));
net.add_branch(Branch::new("1", "2", BranchParams::line(0.1, 0.2, 0.02)));
net.add_branch(Branch::new("2", "3", BranchParams::line(0.05, 0.1, 0.01)));
net.add_branch(Branch::new("1", "3", BranchParams::line(0.08, 0.15, 0.015)));

let solver = PowerFlowSolver::new()
    .method(PowerFlowMethod::NewtonRaphson)
    .tolerance(1e-8)
    .max_iterations(50);

let result = solver.solve(&net)?;

println!(
    "收敛: {} 迭代: {} 残差: {:.2e} 耗时: {:?}",
    result.converged, result.iterations, result.residual, result.duration
);

for bus in &result.buses {
    println!(
        "母线 {}: V={:.4} θ={:.4}rad P={:.4} Q={:.4}",
        bus.id, bus.voltage.magnitude.0, bus.voltage.angle.as_radians(),
        bus.p_pu, bus.q_pu
    );
}

支路潮流与负载率

let result = solver.solve(&net)?;

for flow in &result.branch_flows {
    println!(
        "支路 {}-{}: P={:.4} Q={:.4} 负载率={:.1}% 损耗={:.4}",
        flow.from, flow.to,
        flow.p_from_pu, flow.q_from_pu,
        flow.loading_percent, flow.loss_pu
    );
}

println!("网络总损耗: {:.6} pu", result.total_loss_pu());

if let Some(max) = result.max_loading() {
    println!("最大负载支路: {}-{} ({:.1}%)", max.from, max.to, max.loading_percent);
}

直流潮流快速估算

use eneros_powerflow::PowerFlowMethod;

let dc_solver = PowerFlowSolver::new()
    .method(PowerFlowMethod::DcPowerFlow);

let dc_result = dc_solver.solve(&net)?;
println!("直流潮流耗时: {:?}", dc_result.duration);

PQ 解耦快速求解

let fd_solver = PowerFlowSolver::new()
    .method(PowerFlowMethod::FastDecoupled)
    .tolerance(1e-6)
    .max_iterations(30);

let fd_result = fd_solver.solve(&net)?;
println!(
    "解耦潮流: 收敛={} 迭代={} 耗时={:?}",
    fd_result.converged, fd_result.iterations, fd_result.duration
);

结果缓存失效

let solver = PowerFlowSolver::new().enable_cache(true);

let r1 = solver.solve(&net)?;
let r2 = solver.solve(&net)?;
println!("第二次复用缓存: {:?}", r2.duration);

// 拓扑变更后缓存自动失效
// net.add_branch(...);
let r3 = solver.solve(&net)?;
println!("拓扑变更后重新计算: {:?}", r3.duration);

收敛与诊断

Newton-Raphson 方法在每次迭代中求解线性方程组 J · Δx = -ΔS,其中:

  • J:雅可比矩阵(2N-2 阶,稀疏)
  • Δx:电压修正量 [Δθ, ΔV]
  • ΔS:功率残差 [ΔP, ΔQ]

收敛条件:max(|ΔP|, |ΔQ|) < tolerance

发散诊断返回每次迭代残差,便于排查:

match solver.solve(&net) {
    Ok(result) if !result.converged => {
        println!(
            "未收敛: 已迭代 {} 次, 最终残差 {:.2e}",
            result.iterations, result.residual
        );
    }
    Ok(result) => println!("收敛于第 {} 次迭代", result.iterations),
    Err(e) => println!("求解错误: {}", e),
}

性能指标

测试环境:4 核 / 8GB / Ubuntu 22.04 / Rust 1.78 release build。

网络规模Newton-RaphsonFast DecoupledDC Power Flow
IEEE-14< 1ms< 0.5ms< 0.1ms
IEEE-30< 2ms< 1ms< 0.2ms
IEEE-118< 5ms< 3ms< 0.5ms
1000 节点< 10ms< 6ms< 1ms
10000 节点< 120ms< 80ms< 10ms

YBus 构建性能

网络规模构建耗时内存占用
IEEE-14< 50μs< 4KB
IEEE-118< 500μs< 32KB
1000 节点< 5ms< 256KB
10000 节点< 60ms< 2.5MB

配置参数表

参数类型默认值说明
methodPowerFlowMethodNewtonRaphson求解方法
tolerancef641e-8收敛容差
max_iterationsusize50最大迭代次数
enable_cachebooltrue是否启用结果缓存

依赖关系

自身依赖

[dependencies]
eneros-core = { path = "../core", version = "0.47.0" }
eneros-linalg = { path = "../linalg", version = "0.47.0" }
eneros-topology = { path = "../topology", version = "0.47.0" }
num-complex = "0.4"
tracing = "0.1"

被依赖

  • eneros-analysis — OPF 与状态估计以潮流结果为初值
  • eneros-constraint — 校验潮流结果是否越限
  • eneros-twin — 孪生体在 What-If 中触发潮流
  • eneros-simulator — 场景模拟器调用潮流
  • eneros-network — 拓扑-潮流统一管线

版本与兼容性

eneros-powerflow 版本EnerOS 版本关键变更
0.47.x0.47.x雅可比矩阵 CSR 化,性能提升 2x
0.46.x0.46.x新增 PQ 解耦与直流潮流方法
0.45.x (LTS)0.45.xLTS 版本,至 2028 年安全更新

相关文档