Skip to main content

Power-Native First

Core Concepts

Power-Native First

Power-Native First is EnerOS’s most core design philosophy: the domain knowledge of power systems is not a bolt-on library or configuration file, but a native abstraction of the OS kernel. This means that core power domain concepts such as grid topology, power flow calculation, security constraints, equipment models, and time-series data enjoy first-class kernel-space citizenship, just like traditional OS concepts such as file systems, process management, and network stacks.

Design Motivation

The Dilemma of Traditional Power Software

Traditional power software places grid domain knowledge at the application layer, leading to a series of long-standing problems:

  • Redundant Modeling: Each application (EMS, DMS, SCADA, distribution automation) maintains its own grid model, with redundant and inconsistent data
  • Validation Omissions: Physical constraint validation is scattered across applications, easily omitted during deployment, and only exposed after accidents
  • Agent Silos: Agents cannot share a unified grid worldview; cross-application collaboration requires complex interface integration
  • Performance Loss: Each operation needs to rebuild grid context at the application layer, unable to leverage kernel-space optimization
  • Difficult Evolution: Grid model changes require synchronous modifications to multiple applications, with long iteration cycles

Power-Native Solution

EnerOS pushes power domain knowledge down to the OS kernel, and all upper-layer applications access the same grid abstraction via system calls:

┌──────────────────────────────────────────────────┐
│              Application Layer (Agents)           │
│  DispatchAgent / SelfHealingAgent / TradingAgent │
├──────────────────────────────────────────────────┤
│              Agent Runtime                        │
│  eneros-agent / eneros-tool / eneros-reasoning   │
├──────────────────────────────────────────────────┤
│         Power-Native Core                         │
│  ├─ NetworkGraph      (Topology graph)            │
│  ├─ PowerFlowSolver   (Power flow solver)         │
│  ├─ ConstraintEngine  (Constraint engine)         │
│  ├─ EquipmentLibrary  (Equipment model library)   │
│  ├─ TimeSeriesEngine  (Time-series storage)       │
│  └─ TopologyAwareBus  (Event bus)                 │
├──────────────────────────────────────────────────┤
│              Infrastructure Layer                 │
│  eneros-os / eneros-trust / eneros-multiregion   │
└──────────────────────────────────────────────────┘

Four Pillars of Power-Native

1. Grid Topology as First-Class Citizen

Grid topology is no longer a CIM/XML file on disk or a data structure in application memory, but a graph structure in kernel space. All Agents and all applications share the same topology view and perceive its changes.

Kernel Topology Data Structure

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

// The topology graph is a kernel first-class citizen, loaded at process startup
let mut network = NetworkGraph::new();

// Add buses (nodes)
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)))?;

// Add branches (edges)
network.add_branch(Branch::new(1, 2, BranchParams::line(r=0.01, x=0.05, b=0.02)))?;
network.add_branch(Branch::new(2, 3, BranchParams::transformer(r=0.0, x=0.1, ratio=1.0)))?;

// The kernel maintains topology consistency: add/delete/modify automatically triggers connectivity analysis
let topology = network.topology();
let islands = topology.find_islands();
let reachable = topology.reachable(bus_id_1, bus_id_2);

// All Agents share the same topology view, modifications are broadcast in real time
let snapshot = network.snapshot(); // CoW snapshot, zero-copy read

Topology-Aware System Calls

// Agents access topology via system calls, no need to rebuild it themselves
impl Agent for DispatchAgent {
    async fn run(&mut self, ctx: &mut AgentContext) -> AgentResult<()> {
        // Get the electrical island it belongs to
        let island = ctx.syscall(TopologySyscall::GetIsland {
            bus: self.bus_id,
        }).await?;

        // Enumerate all generators in the island
        let generators = ctx.syscall(TopologySyscall::ListGenerators {
            island_id: island.id,
        }).await?;

        // Perform economic dispatch
        let dispatch = self.economic_dispatch(&generators, &island.load)?;
        ctx.syscall(TopologySyscall::ApplyDispatch(dispatch)).await?;

        Ok(())
    }
}

2. Physical Constraints as Law

Physical constraints (voltage limit violations, branch overloads, frequency deviations) are not optional validation steps at the application layer, but laws enforced by the kernel. Any operation that violates a constraint is directly rejected in kernel space, and when necessary, projected to the nearest feasible solution.

use eneros_constraint::{ConstraintEngine, Constraint, Violation};

// The constraint engine is bound to the kernel topology, automatically validating all write operations
let constraint_engine = ConstraintEngine::new(&network);

// Register constraints (can also be batch loaded via configuration file)
constraint_engine.register(Constraint::voltage()
    .min(0.95).max(1.05)
    .buses(network.all_buses()))?;

constraint_engine.register(Constraint::thermal()
    .branch(branch_id)
    .limit_mva(100.0))?;

constraint_engine.register(Constraint::frequency()
    .min_hz(49.5).max_hz(50.5))?;

// Any Agent command is automatically validated when passing through the kernel
let command = Command::SetGeneration { bus: 1, mw: 80.0 };
match constraint_engine.check(&command) {
    CheckResult::Ok => { /* Passed, execute */ }
    CheckResult::Violated(v) => {
        // Automatically project to the nearest feasible solution
        let feasible = constraint_engine.project(&command)?;
        log::warn!("Command projected: {:?} -> {:?}", command, feasible);
    }
    CheckResult::Rejected(reason) => {
        return Err(EnerOSError::ConstraintRejected(reason));
    }
}

3. Standardized Equipment Models

EnerOS has a built-in unified equipment model library covering mainstream power system equipment types, with all Agents sharing the same set of parameterized models:

Equipment TypeModelKey ParametersApplicable Scenario
Transmission Lineπ-type equivalent circuitR, X, B/2, lengthTransmission grid power flow
TransformerIdeal ratio + magnetizing branchRatio, R, X, magnetizing conductance/susceptanceSubstation power flow
GeneratorSynchronous machine 6th-order modelXd, Xq, Xd’, Xq’, Td0’, Tq0’, H, DTransient stability
LoadZIP + exponential modelZ%, I%, P%, exponents α, βStatic/dynamic load
SVCStatic Var CompensatorK, T, Xc, Xl, VrefVoltage reactive power control
Wind TurbineDoubly-fed/direct-drive turbineCp(λ,β), electrical parametersRenewable energy integration
use eneros_equipment::{EquipmentLibrary, LineParams, TransformerParams};

let library = EquipmentLibrary::new();

// Standardized equipment parameters
let line = library.create_line(LineParams {
    r_per_km: 0.08,
    x_per_km: 0.40,
    b_per_km: 2.5e-6,
    length_km: 50.0,
    rating_mva: 100.0,
    nominal_kv: 110.0,
})?;

let transformer = library.create_transformer(TransformerParams {
    sn_mva: 63.0,
    vn_hv_kv: 110.0,
    vn_lv_kv: 10.0,
    uk_percent: 10.5,
    pk_kw: 280.0,
    i0_percent: 0.5,
    p0_kw: 50.0,
})?;

// Equipment models are automatically injected into the topology
network.add_branch(Branch::from_equipment(line.id(), bus_a, bus_b))?;
network.add_branch(Branch::from_equipment(transformer.id(), bus_c, bus_d))?;

4. Time-Series Data Native

All operating states of a power system (voltage, current, power, frequency) are inherently time-series data. EnerOS builds the time-series storage engine into a kernel component, providing nanosecond-precision writes and queries, without depending on external time-series databases like InfluxDB or TimescaleDB.

use eneros_timeseries::{TimeSeriesEngine, Measurement, Aggregation, Duration};

// The time-series engine is a kernel component, ready at startup
let ts = TimeSeriesEngine::open("data/eneros.db")?;

// High-throughput writes (batch interface)
ts.batch_write(&[
    Measurement::new("bus_1_voltage",    1.02,  now!()),
    Measurement::new("bus_1_frequency", 50.00,  now!()),
    Measurement::new("line_1_power",    45.50,  now!()),
    Measurement::new("bus_2_voltage",    0.99,  now!()),
])?;

// Aggregation query + downsampling integrated
let result = ts.query()
    .point("bus_1_voltage")
    .range(now!() - Duration::hours(24), now!())
    .aggregation(Aggregation::Avg, Duration::minutes(15))
    .downsample(Downsample::LTTB, 1000)
    .execute()?;

// Agents query directly via system calls
let history = ctx.syscall(TimeSeriesSyscall::Query {
    point: "total_load",
    range: (now!() - Duration::days(7), now!()),
}).await?;

Complete Comparison: Traditional vs Power-Native

DimensionTraditional Power SoftwareEnerOS Power-Native
Topology ModelingApplication-layer data structure (CIM/XML)Kernel first-class citizen (graph structure)
Topology ConsistencyManual sync per applicationKernel auto-maintained
Constraint ValidationOptional at application layer, easily omittedKernel-enforced
Constraint ProjectionUnsupported or self-implementedKernel auto-projection
Equipment ModelCustom per applicationUnified model library
Time-Series DataExternal database (InfluxDB, etc.)Kernel storage engine
Agent SharingManual synchronizationAuto-share same view
Security & ComplianceBolt-on moduleKernel-enforced
Cross-Application CollaborationComplex interface integrationSystem calls suffice
PerformanceApplication-layer rebuilds contextKernel-space zero-copy

Performance Comparison

Comparison in a standard test environment (4 cores / 8GB / Ubuntu 22.04, IEEE 118-bus system):

OperationTraditional SolutionEnerOS Power-NativeImprovement
Topology Loading500-1000ms (XML parsing)< 5ms (kernel binary)100x
Topology Analysis (118 nodes)50-100ms< 1ms50x
Power Flow Calculation (Newton method)100-300ms< 30ms5x
Constraint Validation (single command)1-5ms (application layer)< 10μs (kernel space)500x
Time-Series Write10-50K points/sec (network round-trip)1M points/sec (kernel space)50x
Agent Context Build50-200ms (rebuild model)< 10μs (system call)5000x
Cross-Application Event Broadcast10-50ms (message queue)< 10μs (kernel bus)1000x

Applicable Scenarios

The Power-Native architecture is particularly suitable for the following scenarios:

  • Large Interconnected Grids: Unified modeling and coordinated control across regions and voltage levels
  • High Renewable Penetration: The stochastic nature of wind and solar requires real-time power flow and constraint validation
  • Distribution Network Intelligence: Coordinated management of distributed energy, storage, and electric vehicles
  • Digital Twin: Real-time synchronization and mirror inference between the physical grid and its twin
  • Multi-Agent Collaboration: Dispatch, self-healing, trading, and other multi-agents sharing a grid worldview
  • Power Market Operation: Market clearing and settlement based on real-time topology and power flow

Limitations and Trade-offs

The Power-Native architecture is not a silver bullet and involves the following trade-offs:

Trade-offDescriptionMitigation Strategy
High Kernel ComplexityPower domain knowledge in the kernel increases kernel code volumeStrict modularization, 56 crates decoupled
Deployment ThresholdRequires power domain knowledge to configure correctlyProvide standard model library and configuration templates
Reduced GeneralityOptimized for power scenarios, not suitable for general IoTExtend non-power scenarios via plugin framework
Memory UsageKernel resident topology and time-series cacheSupports memory cap configuration and LRU eviction
Cross-Platform LimitationsReal-time domain depends on PREEMPT_RT or bare metalGeneral domain can be deployed independently on regular Linux
Upgrade ComplexityKernel upgrades require coordinating all AgentsCoW snapshots ensure hot-upgrade consistency

Kernel Architecture Layers

The layered design of the Power-Native kernel:

┌─────────────────────────────────────────┐
│  System Call Interface (Syscall ABI)    │  ← Agents access via syscall
├─────────────────────────────────────────┤
│  Power-Native Service Layer             │
│  ├─ TopologyService   (Topology R/W)    │
│  ├─ PowerFlowService  (Power flow)      │
│  ├─ ConstraintService (Constraint check)│
│  ├─ EquipmentService  (Equipment model) │
│  └─ TimeSeriesService (Time-series)     │
├─────────────────────────────────────────┤
│  Power Domain Kernel                    │
│  ├─ NetworkGraph      (CIM graph)       │
│  ├─ Solver            (Newton/PQ decomp)│
│  ├─ ConstraintEngine  (Constraint proj) │
│  ├─ EquipmentLibrary  (Equipment proto) │
│  └─ TimeSeriesEngine  (LSM-WAL storage) │
├─────────────────────────────────────────┤
│  General OS Abstraction Layer           │
│  └─ Scheduler / Memory / IPC / Network  │
└─────────────────────────────────────────┘

System Call Examples

Agents access kernel power services via system calls, without rebuilding any domain models themselves:

use eneros_os::syscall::*;

// Topology query
let bus = ctx.syscall(GetBus { id: bus_id }).await?;
let neighbors = ctx.syscall(GetNeighbors { bus: bus_id }).await?;
let island = ctx.syscall(GetIsland { bus: bus_id }).await?;

// Power flow trigger
let result = ctx.syscall(SolvePowerFlow {
    method: PowerFlowMethod::NewtonRaphson,
    max_iter: 20,
    tolerance: 1e-6,
}).await?;

// Constraint validation
let check = ctx.syscall(CheckConstraint {
    command: command.clone(),
}).await?;

// Time-series query
let series = ctx.syscall(QueryTimeSeries {
    point: "bus_1_voltage",
    range: (start, end),
    aggregation: Some((Aggregation::Avg, Duration::minutes(5))),
}).await?;

// Equipment operations
ctx.syscall(SetTapPosition { transformer_id, position: 5 }).await?;
ctx.syscall(SetGeneratorOutput { bus: 1, mw: 80.0 }).await?;

Comparison with Traditional OS

ConceptGeneral OSEnerOS Power-Native
First-Class CitizensFiles, processes, socketsBuses, branches, equipment, constraints
System Callsopen/read/write/socketGetBus/SolvePowerFlow/CheckConstraint
Scheduling ObjectsProcesses/threadsAgents (bound to electrical nodes)
Enforced ProtectionMemory isolation, permission bitsPhysical constraint enforcement
PersistenceFile systemTime-series storage engine
Event MechanismSignals, epollTopology-aware event bus

Next Steps