跳到主内容

电网拓扑一等公民

核心能力

电网拓扑一等公民

EnerOS 将电网拓扑作为操作系统内核的一等公民数据结构,而非应用层的数据文件。这意味着 NetworkGraph、Bus、Branch 等抽象在内核态即被原生支持,Agent、调度器、保护逻辑、数字孪生等所有上层组件都共享同一份电网拓扑视图,避免重复建模与一致性同步开销。

「拓扑一等公民」是 Power-Native First 设计哲学的直接落地:电网的物理结构本身就是操作系统世界观的一部分,就像 Linux 内核理解文件系统与进程树一样,EnerOS 内核理解母线、支路、电气岛与连通性。

设计动机

传统电力软件将电网拓扑建模为应用层的 JSON / XML / CIM 文件,每次潮流计算、状态估计、保护整定都需要重新加载并解析。这带来三个问题:

  • 重复建模:调度、运检、保护各维护一份拓扑,状态漂移严重
  • 事件失效:拓扑变更无法实时通知所有订阅者,决策基于过期视图
  • 性能浪费:每次解析与构建拓扑图占用 10-100ms,无法支撑实时应用

EnerOS 通过将拓扑下沉到内核态,所有组件通过系统调用访问同一份拓扑对象,变更事件由内核广播,单次拓扑分析延迟降至 1ms 以下。

架构总览

┌─────────────────────────────────────────────────┐
│  应用层:DispatchAgent / ProtectionAgent / Twin │
└───────────────────┬─────────────────────────────┘
                    │ 系统调用 get_network / subscribe
┌───────────────────┴─────────────────────────────┐
│  eneros-topology (内核原生拓扑引擎)             │
│  ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│  │ NetworkGraph│ │ TopologyOps │ │ EventBus  │ │
│  └─────────────┘ └─────────────┘ └───────────┘ │
│  ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│  │ Bus / Branch│ │ IslandIndex │ │ VersionLog│ │
│  └─────────────┘ └─────────────┘ └───────────┘ │
└─────────────────────────────────────────────────┘

核心抽象

NetworkGraph

NetworkGraph 是 EnerOS 中所有电网拓扑操作的入口,采用基于 petgraph 的有向图结构,并附加电力系统专用的索引与元数据。

use eneros_topology::{NetworkGraph, Bus, Branch, BusType, BranchParams, Voltage};

let mut network = NetworkGraph::new();

// 添加母线
network.add_bus(Bus::new(1, BusType::PQ, Voltage::new(1.0, 0.0)));
network.add_bus(Bus::new(2, BusType::PV, Voltage::new(1.02, 0.0)));
network.add_bus(Bus::new(3, BusType::Slack, Voltage::new(1.05, 0.0)));

// 添加支路
network.add_branch(Branch::new(1, 2, BranchParams::line(0.1, 0.2, 0.02)));
network.add_branch(Branch::new(2, 3, BranchParams::transformer(0.05, 0.1, 1.0)));

Bus 字段说明

字段类型含义默认值
idu32母线编号,全局唯一必填
bus_typeBusTypePQ / PV / Slack / IsolatedPQ
voltageVoltage电压幅值与相角(p.u.)(0.0, 0.0)
areau16所属区域编号0
zoneu16所属分区编号0
base_kvf64基准电压(kV)110.0
v_maxf64最高运行电压(p.u.)1.10
v_minf64最低运行电压(p.u.)0.90
nameString可读名称""

Branch 字段说明

字段类型含义默认值
fromu32起始母线 ID必填
tou32终止母线 ID必填
paramsBranchParams电阻、电抗、对地导纳、变比必填
statusBranchStatusClosed / Open / GroundedClosed
rating_mvaf64额定容量(MVA)100.0
emergency_mvaf6415 分钟紧急容量rating_mva * 1.2
length_kmf64线路长度(km)0.0

BranchParams 构造器

use eneros_topology::BranchParams;

// 传输线 Π 型参数:(r, x, b/2)
let line = BranchParams::line(0.1, 0.2, 0.02);

// 变压器参数:(r, x, 变比)
let xfmr = BranchParams::transformer(0.05, 0.1, 1.0);

// 三绕组变压器(折算到高压侧)
let three_winding = BranchParams::three_winding(
    (0.01, 0.15, 1.0),
    (0.01, 0.10, 1.0),
    (0.01, 0.05, 1.0),
);

// 分布参数线路(Bergeron 模型)
let distributed = BranchParams::distributed(
    0.025,   // r (Ω/km)
    0.3,     // x (Ω/km)
    0.015,   // b (μS/km)
    150.0,   // length (km)
);

拓扑分析

内核内置常见拓扑分析算法,全部基于一次遍历完成,无需应用层重复实现。

let topology = network.topology();

// 电气岛检测
let islands = topology.find_islands();

// 连通性检查
let connected = topology.is_connected(bus1, bus2);

// 最短路径(按跳数)
let path = topology.shortest_path(bus1, bus2)?;

// 最短路径(按阻抗)
let path_z = topology.shortest_path_by_impedance(bus1, bus2)?;

// 邻居节点
let neighbors = topology.get_neighbors(bus_id);

// 上游电源
let sources = topology.upstream_sources(bus_id);

// 下游负荷
let loads = topology.downstream_loads(bus_id);

// 供电范围
let scope = topology.supply_scope(bus_id);

TopologyOps API 一览

方法入参出参时间复杂度
find_islands-VecO(V+E)
is_connectedbus1, bus2boolO(V+E)
shortest_pathfrom, toVecO((V+E) log V)
get_neighborsbus_idVecO(deg)
upstream_sourcesbus_idVecO(V+E)
downstream_loadsbus_idVecO(V+E)
supply_scopebus_idScopeO(V+E)
find_loops-Vec<Vec>O(V+E)
cut_setbus_idVecO(V+E)
radial_check-RadialReportO(V+E)

拓扑变更与事件

任何拓扑变更都会触发内核事件总线广播,订阅者通过 subscribe 接收:

use eneros_topology::event::{TopologyChanged, BranchStatusChanged, BusAdded};

// 订阅拓扑变更
ctx.subscribe::<TopologyChanged>().await?;
ctx.subscribe::<BranchStatusChanged>().await?;

// 增量更新拓扑
network.update_branch(1, 2, |b| b.status = BranchStatus::Open);
// 内核自动完成:
//   1. 失效潮流缓存
//   2. 重新计算电气岛索引
//   3. 推送 BranchStatusChanged 事件
//   4. 推送 TopologyChanged 事件
//   5. 触发约束重算
//   6. 通知数字孪生同步镜像

事件类型

事件触发时机携带数据
BusAdded新增母线bus_id, voltage
BusRemoved删除母线bus_id
BranchStatusChanged支路开合branch_id, old, new
TopologyChanged任意拓扑变更变更摘要、affected_buses
IslandFormed形成新电气岛island_id, buses
IslandMerged电气岛合并island_a, island_b

事件订阅完整示例

use eneros_topology::event::TopologyChanged;

impl Agent for TopologyListenerAgent {
    async fn run(&mut self, ctx: &mut AgentContext) -> AgentResult<()> {
        let mut rx = ctx.subscribe::<TopologyChanged>().await?;
        while let Some(event) = rx.recv().await {
            println!("拓扑变更: 影响 {} 条母线", event.affected_buses.len());
            self.recompute_dispatch(ctx).await?;
        }
        Ok(())
    }
}

与 Agent 集成

Agent 通过内核 API 直接访问拓扑,无需额外建模。这是 Power-Native 内核区别于通用 AgentOS 的关键所在——Agent 从诞生起即运行在电网的物理世界模型之上。

use eneros_agent::{Agent, AgentContext, AgentResult};
use eneros_topology::BusType;

struct TopologyAwareAgent {
    interval: std::time::Duration,
}

impl Agent for TopologyAwareAgent {
    fn name(&self) -> &str { "topology_aware" }

    async fn run(&mut self, ctx: &mut AgentContext) -> AgentResult<()> {
        loop {
            // 获取完整拓扑
            let network = ctx.get_network().await?;

            // 分析拓扑
            let islands = network.topology().find_islands();

            // 基于拓扑决策
            for island in &islands {
                if island.buses.len() > 1 {
                    self.optimize_island(island, ctx).await?;
                } else {
                    self.handle_isolated(island, ctx).await?;
                }
            }

            ctx.sleep(self.interval).await;
        }
    }
}

impl TopologyAwareAgent {
    async fn optimize_island(
        &mut self,
        island: &eneros_topology::Island,
        ctx: &mut AgentContext,
    ) -> AgentResult<()> {
        let network = ctx.get_network().await?;
        let total_load: f64 = island.buses.iter()
            .filter_map(|&b| network.bus_load(b))
            .sum();
        let total_gen: f64 = island.buses.iter()
            .filter_map(|&b| network.bus_generation(b))
            .sum();
        let balance = total_gen - total_load;
        println!("岛 {} 平衡量: {:.2} MW", island.id, balance);
        Ok(())
    }

    async fn handle_isolated(
        &mut self,
        island: &eneros_topology::Island,
        ctx: &mut AgentContext,
    ) -> AgentResult<()> {
        println!("检测到孤岛: {:?}", island.buses);
        ctx.publish(eneros_topology::event::IslandFormed {
            island_id: island.id,
            buses: island.buses.clone(),
        }).await?;
        Ok(())
    }
}

与潮流计算联动

拓扑变更会自动触发潮流计算缓存失效,并通过事件总线向所有订阅者推送 TopologyChanged 事件,保证状态一致性。

use eneros_powerflow::{PowerFlow, NewtonRaphson};

// 监听拓扑变更,自动重算潮流
ctx.subscribe::<TopologyChanged>().await?;

let mut pf = NewtonRaphson::new()
    .tolerance(1e-8)
    .max_iter(50);

// 拓扑变更后潮流缓存自动失效,下次调用自动重算
let result = pf.solve(&network)?;
println!("收敛迭代次数: {}", result.iterations);
println!("最大失配量: {:.2e}", result.max_mismatch);

持久化与版本

拓扑对象支持持久化到内核管理的对象存储,并保留完整的变更历史:

// 保存当前拓扑
network.save("case_2026_summer").await?;

// 加载历史版本
let historical = NetworkGraph::load("case_2025_winter").await?;

// 查看变更历史
let history = network.version_log();
for entry in history.iter().rev().take(10) {
    println!("{}: {} by {}", entry.timestamp, entry.action, entry.author);
}

// 回滚到指定版本
network.rollback_to("v2025.12.01-1200").await?;

性能指标

操作延迟吞吐
添加母线/支路< 1μs-
删除母线/支路< 2μs-
拓扑分析(1000 节点)< 1ms-
电气岛检测(1000 节点)< 5ms-
电气岛检测(10万 节点)< 80ms-
最短路径(1000 节点)< 100μs-
连通性检查< 50μs-
拓扑变更事件广播< 10μs100k events/s
拓扑序列化(CIM XML)-10k buses/ms
拓扑快照写入< 5ms-

测试环境:4 核 / 8GB / Ubuntu 22.04,节点数为 1000(IEEE 118 + 扩展)。

配置参数

eneros.toml 中拓扑相关配置:

[topology]
# 拓扑缓存大小(拓扑快照数)
cache_size = 8
# 是否启用电气岛增量索引
incremental_island_index = true
# 拓扑变更事件订阅者上限
max_subscribers = 1024
# 序列化格式:cim_xml / cim_json / cgmes / binary
default_format = "binary"
# 是否启用拓扑变更审计日志
audit_log = true
# 拓扑快照自动保存间隔(秒)
snapshot_interval_secs = 300
参数类型默认值说明
cache_sizeu328缓存的拓扑快照数量
incremental_island_indexbooltrue启用增量电气岛索引,加速变更后重算
max_subscribersu321024单个拓扑事件最大订阅者数
default_formatenumbinary默认序列化格式
audit_logbooltrue是否记录拓扑变更审计日志
snapshot_interval_secsu32300自动快照间隔

与其他能力的关系

关联能力互动方式
物理约束决策拓扑变更触发约束重算
设备模型库母线/支路引用设备模型参数
时序原生操作拓扑变更事件写入时序存储
数字孪生引擎孪生镜像基于拓扑构建
安全守卫操作票校验依赖拓扑连通性
多智能体协作Agent 通过拓扑定位管辖范围
实时双执行域拓扑变更实时同步到实时域
多租户与隔离拓扑按租户命名空间隔离

相关文档