Skip to main content

v0.34.0 Release Notes

EnerOS v0.34.0

Release Date: 2026-03-21 Codename: Adapt Git Tag: v0.34.0 Support Status: Stable Total Crates: 72 (6 new) Test Cases: 9300+ (700 new)

Overview

EnerOS v0.34.0 “Adapt” is an adaptive dispatching-focused release, upgrading grid dispatching from “preset strategies + manual intervention” to a “topology-aware + real-time optimization + automatic adjustment” adaptive dispatching system. Based on the AI Agent capabilities from v0.31.0 and the ML runtime from v0.32.0, this release builds an intelligent dispatching kernel that dynamically adjusts dispatching strategies based on grid operation status, load changes, and renewable energy fluctuations.

The core design philosophy of the Adapt release is “topology as strategy” — dispatching strategies are no longer fixed rule tables, but are derived in real-time from grid topology, equipment status, and constraint boundaries. When topology changes (switch operations, equipment commissioning/decommissioning, renewable energy integration), dispatching strategies are automatically recalculated and issued without manual reconfiguration. This enables EnerOS to handle the frequent topology changes and bidirectional power flow brought by high-penetration renewable energy integration.

This release introduces five core capabilities: Adaptive Dispatching Engine, Dynamic Topology Awareness, Load Balancer, Optimized Dispatching Strategy Library, and Real-time Adjustment Executor. All capabilities are implemented through five new crates: eneros-adapt, eneros-adapt-topology, eneros-adapt-balance, eneros-adapt-strategy, and eneros-adapt-executor.

Key Metrics

MetricValueDescription
Dispatching strategy calculation latency45ms1000 nodes
Topology change response< 200msStrategy recompute
Renewable energy utilization improvement8.3%Compared with fixed strategy
Line load balancing degree0.92Gini coefficient
New Crates6Dispatching-related
New tests700+Includes 110 end-to-end

New Features

1. Adaptive Dispatching Engine

Adds the eneros-adapt crate, providing a kernel-native adaptive dispatching engine that replaces traditional fixed-strategy dispatchers. The engine takes grid topology, real-time power flow, load forecasts, and constraint boundaries as input, and outputs optimal generation output allocation and power flow control commands.

Dispatching Optimization Objectives

ObjectiveWeightDescription
Economy30%Minimize generation cost
Safety25%Maximize constraint margin
Renewable utilization20%Minimize wind/solar curtailment
Network loss15%Minimize transmission loss
Balance10%Line load balancing

Dispatching Engine API

use eneros_adapt::{AdaptiveScheduler, ScheduleConfig, Objective};

let scheduler = AdaptiveScheduler::new(&ctx)
    .config(ScheduleConfig {
        objective: Objective::MultiObjective {
            economic: 0.30,
            safety: 0.25,
            renewable: 0.20,
            loss: 0.15,
            balance: 0.10,
        },
        horizon: Duration::minutes(15),
        resolution: Duration::minutes(5),
        solver: Solver::InteriorPoint,
        max_iter: 200,
        tolerance: 1e-6,
    })
    .build().await?;

// Execute adaptive dispatching
let schedule = scheduler.optimize().await?;

println!("Dispatching plan:");
for unit in &schedule.generator_dispatch {
    println!("  {} -> {:.1} MW (cost: {:.2} CNY/MWh)",
        unit.bus_id, unit.target_mw, unit.cost);
}
println!("Total generation cost: {:.0} CNY", schedule.total_cost);
println!("Renewable utilization: {:.1}%", schedule.renewable_utilization * 100.0);
println!("Max line loading: {:.1}%", schedule.max_line_loading * 100.0);

Dispatching Cycles

CycleTime ScaleTriggerOptimization Scope
Ultra-short-term5-15 minutesReal-timeWhole network
Short-term15 minutes - 4 hoursScheduled/eventElectrical island
Medium-term4-24 hoursScheduledRegion
Long-term1-7 daysDailySystem

2. Dynamic Topology Awareness

Adds the eneros-adapt-topology crate, enabling the dispatching engine to sense topology changes in real-time and automatically recompute strategies. When switch operations, equipment commissioning/decommissioning, or fault isolation cause topology changes, dispatching strategies complete recomputation and issuance within 200ms.

Topology Change Response

use eneros_adapt_topology::{TopologyAwareScheduler, TopologyEvent};

let topo_scheduler = TopologyAwareScheduler::new(&scheduler, &network);

// Subscribe to topology change events
network.on_event(|event: TopologyEvent| {
    match event {
        TopologyEvent::SwitchOpened(switch_id) => {
            // Switch opened, may change electrical island structure
            topo_scheduler.trigger_recompute(
                Reason::TopologyChange,
                Priority::High,
            );
        }
        TopologyEvent::GeneratorTripped(bus_id) => {
            // Generator tripped, emergency re-dispatch
            topo_scheduler.trigger_recompute(
                Reason::GeneratorLoss(bus_id),
                Priority::Critical,
            );
        }
        TopologyEvent::RenewableSurge(bus_id, mw) => {
            // Renewable output surge, adjust utilization strategy
            topo_scheduler.trigger_recompute(
                Reason::RenewableSpike(bus_id, mw),
                Priority::Medium,
            );
        }
        _ => {}
    }
});

Electrical Island-aware Dispatching

// Dispatching engine senses electrical island boundaries, avoiding cross-island dispatching
let islands = network.topology().find_islands();

for island in &islands {
    let island_schedule = scheduler.optimize_island(island).await?;
    // Self-balance within island, support via tie lines when necessary
}

Topology Change Scenarios

ScenarioResponse StrategyLatency
Switch operationRecompute electrical islands, rebalance< 200ms
Generator tripEmergency load shedding/reserve deployment< 100ms
Line faultFault isolation, load transfer< 150ms
Renewable integrationUpdate utilization strategy< 500ms
Equipment commissioning/decommissioningAdjust adjustable resource pool< 300ms

3. Load Balancer

Adds the eneros-adapt-balance crate, explicitly considering line load balancing in dispatching optimization to avoid single line overload while other lines are lightly loaded.

Balancing Algorithms

AlgorithmPrincipleApplicable Scenario
Even distributionDistribute by line capacity ratioRoutine
Weighted least loadSelect path with maximum remaining capacityReal-time
Topology optimizationAdjust switch states to change power flow distributionPlanning
Sensitivity methodBased on generation shift factorsOptimization

Load Balancing API

use eneros_adapt_balance::{LoadBalancer, BalanceConfig, BalanceMetric};

let balancer = LoadBalancer::new(&ctx)
    .config(BalanceConfig {
        metric: BalanceMetric::GiniCoefficient,
        target: 0.90,        // Target Gini coefficient
        max_loading: 0.85,   // Max single-line load rate
        sensitivity: true,   // Enable sensitivity analysis
    })
    .build().await?;

// Calculate current balance
let balance = balancer.evaluate(&network).await?;
println!("Current Gini coefficient: {:.3}", balance.gini);
println!("Max load rate: {:.1}%", balance.max_loading * 100.0);
println!("Overloaded lines: {:?}", balance.overloaded_lines);

// Generate balancing suggestions
let suggestions = balancer.suggest(&network).await?;
for s in &suggestions {
    println!("Suggestion: {} (expected improvement {:.1}%)",
        s.description, s.improvement);
}

4. Optimized Dispatching Strategy Library

Adds the eneros-adapt-strategy crate, with built-in classic power domain dispatching strategies, supporting strategy combination and dynamic switching.

Strategy Matrix

StrategyTypeApplicable ScenarioComputational Complexity
Economic Dispatch (ED)ClassicNormal operationLow
Optimal Power Flow (OPF)ClassicRefined operationMedium
Unit Commitment (UC)ClassicDay-ahead planningHigh
Deep Reinforcement LearningAIComplex scenariosMedium (inference)
Fuzzy ControlIntelligentUncertain scenariosLow
Multi-objective ParetoOptimizationDecision supportHigh

Strategy Selection and Switching

use eneros_adapt_strategy::{StrategyRegistry, Strategy, StrategySelector};

let mut registry = StrategyRegistry::new();
registry.register(Strategy::economic_dispatch())?;
registry.register(Strategy::optimal_power_flow())?;
registry.register(Strategy::reinforcement_learning("rl-dqn-v2"))?;
registry.register(Strategy::multi_objective_pareto())?;

// Dynamic strategy selector
let selector = StrategySelector::new()
    .rule(|ctx| {
        if ctx.renewable_ratio > 0.4 {
            Strategy::reinforcement_learning("rl-dqn-v2")  // High renewable ratio uses RL
        } else if ctx.has_congestion {
            Strategy::optimal_power_flow()  // Congestion uses OPF
        } else {
            Strategy::economic_dispatch()   // Normal uses ED
        }
    });

// Auto-select and execute
let strategy = selector.select(&ctx).await?;
let schedule = strategy.execute(&ctx).await?;

Strategy Evaluation Comparison

// Compare effects of different strategies
let comparison = registry.compare_all(&ctx).await?;

println!("Strategy comparison:");
println!("{:<20} {:<10} {:<10} {:<10} {:<10}",
    "Strategy", "Cost(CNY)", "Util%", "Loss", "Balance");
for result in &comparison {
    println!("{:<20} {:<10.0} {:<10.1}% {:<10.2} {:<10.3}",
        result.strategy_name, result.cost,
        result.renewable_pct, result.loss_mw, result.gini);
}

5. Real-time Adjustment Executor

Adds the eneros-adapt-executor crate, converting dispatching strategies into executable device control commands and monitoring execution effectiveness in real-time to form a closed loop.

Execution Loop

use eneros_adapt_executor::{Executor, ExecutionResult};

let executor = Executor::new(&ctx)
    .max_ramp_rate(0.05)   // Max 5% adjustment per minute
    .dead_band(0.02)       // 2% dead band
    .feedback_loop(true)   // Enable closed-loop feedback
    .build().await?;

// Execute dispatching plan
let result = executor.execute(&schedule).await?;

match result {
    ExecutionResult::Success => {
        println!("Dispatching plan executed successfully");
    }
    ExecutionResult::Partial(failures) => {
        for f in &failures {
            println!("Device {} execution failed: {}", f.bus_id, f.reason);
        }
        // Auto-rollback to last feasible plan
        executor.rollback().await?;
    }
    ExecutionResult::Rejected(reason) => {
        println!("Plan rejected by constraint engine: {}", reason);
    }
}

Execution Safety Constraints

ConstraintDescriptionDefault
Ramp rateGenerator output change rate5%/min
Dead bandMinimum adjustment2%
DelayDevice action interval30s
ConcurrencySimultaneous adjusting devices10
ValidationPre-execution constraint checkMandatory

Closed-loop Feedback

// Monitor effects after execution, auto-correct when deviation is too large
executor.on_feedback(|feedback| {
    let deviation = (feedback.actual - feedback.target).abs() / feedback.target;
    if deviation > 0.05 {
        // Deviation exceeds 5%, trigger correction
        executor.correct(feedback).await?;
    }
}).await?;

Improvements

  • Power Flow Calculation: Newton’s method solver adds sparse matrix preprocessing, 118-node calculation reduced from 32ms to 18ms
  • Constraint Engine: Added transient stability constraint, supporting 3-second dynamic safety validation
  • Timeseries Engine: Real-time data writes support WAL async flushing, throughput improved 30%
  • Agent Runtime: Dispatching Agent supports priority preemption, urgent tasks can interrupt lower priority
  • Observability: Full-chain tracing of dispatching flow, supporting plan replay and comparison

Bug Fixes

  • Fixed eneros-adapt incorrect inter-island power exchange calculation in multi-island scenarios (#3404)
  • Fixed eneros-adapt-topology topology change events being lost in concurrent scenarios (#3410)
  • Fixed eneros-adapt-balance Gini coefficient calculation divide-by-zero in single-line scenarios (#3416)
  • Fixed eneros-adapt-strategy strategy selector frequently switching at high renewable ratios (#3422)
  • Fixed eneros-adapt-executor ramp rate limit not correctly applied with concurrent multi-device (#3428)

Breaking Changes

  • AdaptiveScheduler::optimize: Return type changed from Schedule to Result<Schedule>
  • Strategy trait: Added evaluate method, effect evaluation must be implemented
  • Executor::execute: Parameter changed from &Schedule to &SchedulePlan

Upgrade Guide

  1. Update the eneros dependency in Cargo.toml to 0.34.0
  2. Run eneros adapt init to initialize adaptive dispatching configuration
  3. Configure dispatching strategies and safety parameters in eneros.toml
  4. Refer to eneros adapt benchmark to evaluate old vs new strategy effects

Acknowledgments

Thanks to the 30 contributors who submitted 450+ commits, and to dispatching automation experts for strategy validation.