EnerOS v0.22.0 Release Notes
Release Date: July 13, 2025 Codename: Physics Git Tag: v0.22.0 Support Status: Stable Total Crates: 52 (4 new) Test Cases: 6600+ (500+ new)
Overview
EnerOS v0.22.0 “Physics” is a specialized release for physics-constrained decision-making, upgrading power system physical constraints from “post-event validation” to a full-lifecycle decision framework of “pre-event awareness, in-event constraint, post-event traceability.” The fundamental characteristic that distinguishes power systems from general IT systems is that they are governed by physical laws: Kirchhoff’s laws constrain power flow distribution, thermodynamic laws constrain equipment current-carrying capacity, and voltage stability limits constrain operating boundaries. v0.22.0 builds these physical constraints as first-class inputs to the decision engine, making every Agent decision naturally physically feasible.
This version introduces four core capabilities: Physics-Constrained Decision framework, Power Flow Constraint Awareness, Voltage Stability Constraint, and Thermal Stability Constraint, and integrates a Constraint Optimization Solver supporting Linear Programming (LP), Quadratic Programming (QP), and Mixed-Integer Linear Programming (MILP).
In terms of design philosophy, v0.22.0 strengthens the “constraints as law” principle: any Agent decision recommendation must undergo mandatory projection through the ConstraintEngine before execution, with actions violating physical constraints automatically corrected or rejected. This ensures EnerOS maintains grid operational safety even when introducing the uncertainty of AI decision-making.
Key Metrics
| Metric | Value | Description |
|---|---|---|
| Constraint types | 12 | Voltage/current/frequency/thermal etc. |
| Constraint validation latency | < 10μs | Single constraint kernel-mode |
| LP solving (1000 variables) | 8ms | Simplex method |
| QP solving (500 variables) | 15ms | Interior point method |
| MILP solving (100 binary) | 120ms | Branch and bound |
| New Crates | 4 | Physics constraint-related |
| New tests | 500+ | Including IEEE standard cases |
New Features
1. Physics-Constrained Decision Framework
Introduced the eneros-physics-decision Crate, providing a unified physics-constrained decision framework. All Agent decisions are wrapped through PhysicsAwareDecision, automatically injecting current grid operating state and constraint boundaries.
Decision Wrapper
use eneros_physics_decision::{PhysicsAwareDecision, DecisionContext};
let ctx = DecisionContext::from_snapshot(&network_snapshot)
.with_voltage_limits(VoltageLimits {
normal: (0.95, 1.05), // pu
emergency: (0.90, 1.07),
})
.with_thermal_limits(thermal_limits_from_equipment(&library));
let decision = PhysicsAwareDecision::new(Action::AdjustGenerator {
gen_id: 1,
target_mw: 200.0,
}).with_context(&ctx);
// Automatically validate physical constraints before execution
match decision.validate().await {
Ok(projected) => ctx.syscall(Execute(projected)).await?,
Err(violations) => {
for v in violations {
log::warn!("Constraint violation: {} exceeded by {:.2}%", v.constraint, v.margin_pct);
}
}
}
Constraint Type List
| Constraint Category | Constraint Item | Validation Method |
|---|---|---|
| Voltage constraints | Bus voltage upper/lower limits | Analytical |
| Voltage constraints | Voltage change rate | Analytical |
| Current constraints | Line current-carrying capacity | Analytical |
| Current constraints | Transformer overload | Analytical |
| Frequency constraints | System frequency deviation | Analytical |
| Frequency constraints | Frequency change rate | Analytical |
| Thermal stability constraints | Equipment temperature rise | Numerical integration |
| Thermal stability constraints | Accumulated heat | Numerical integration |
| Stability constraints | Transient stability margin | Simulation |
| Stability constraints | Small-signal damping ratio | Eigenvalue |
| Reserve constraints | Spinning reserve capacity | Analytical |
| Topology constraints | Electrical island connectivity | Graph theory |
2. Power Flow Constraint Awareness
Introduced the eneros-powerflow-aware Crate, enabling Agents to perceive power flow distribution constraints during decision-making. Any action (such as adjusting generator output, shedding load, operating switches) triggers power flow sensitivity analysis to assess impact on the entire network’s power flow.
Power Flow Sensitivity
use eneros_powerflow_aware::{Sensitivity, PowerflowAware};
let aware = PowerflowAware::new(&network);
// Calculate sensitivity of generator output to line power flow
let sens: Sensitivity = aware.sensitivity()
.factor(Variable::GeneratorMW(1))
.on(Monitor::LineFlow(line_id))
.compute().await?;
// Sensitivity coefficient: impact of generator 1's 1MW adjustment on line i power flow
println!("Sensitivity coefficient: {:.6}", sens.coefficient);
Power Flow Constraint Validation
// Validate whether adjusting generator output will cause line overlimits
let action = Action::AdjustGenerator { gen_id: 1, target_mw: 250.0 };
let impact = aware.impact_of(&action).await?;
if impact.max_line_loading > 0.95 {
return Err(DecisionError::ThermalViolation {
line: impact.bottleneck_line,
loading: impact.max_line_loading,
});
}
Power Flow Constraint Metrics
| Metric | Threshold | Triggered Action |
|---|---|---|
| Line load rate | > 95% | Alarm |
| Line load rate | > 100% | Block |
| Transformer load rate | > 90% | Alarm |
| Bus voltage deviation | > 5% | Alarm |
| Bus voltage deviation | > 7% | Block |
3. Voltage Stability Constraint
Introduced the eneros-voltage-stability Crate, providing voltage stability margin assessment and constraints. Based on PV/QV curves and Continuation Power Flow (CPF) methods, it calculates system voltage stability margins in real-time.
Stability Margin Calculation
use eneros_voltage_stability::{VoltageStability, LoadingMargin};
let vs = VoltageStability::new(&network);
// Calculate P-V curve and stability margin
let margin: LoadingMargin = vs.loading_margin()
.at_bus(bus_id)
.direction(LoadIncrease::Proportional)
.compute().await?;
println!("Load margin: {:.1} MW ({:.1}%)", margin.mw, margin.percentage);
if margin.percentage < 15.0 {
return Err(DecisionError::VoltageUnstable {
margin: margin.percentage,
});
}
Sensitivity Metrics
// Calculate voltage stability index (L-index)
let l_index = vs.l_index(bus_id).await?;
// L < 0.0 stable, L = 1.0 critical
// Calculate minimum singular value
let min_svd = vs.min_singular_value().await?;
// Larger is more stable
Voltage Stability Levels
| Level | Margin | Status | Response |
|---|---|---|---|
| A | > 20% | Adequate | Normal dispatch |
| B | 15-20% | Good | Monitoring |
| C | 10-15% | Alert | Prepare adjustment |
| D | 5-10% | Warning | Active adjustment |
| E | < 5% | Emergency | Emergency control |
4. Thermal Stability Constraint
Introduced the eneros-thermal-stability Crate, providing equipment thermal stability constraints. Based on equipment thermal models (IEEE 738 standard), it calculates temperature rise and accumulated heat of lines and transformers in real-time.
Thermal Model
use eneros_thermal_stability::{ThermalModel, Conductor};
let conductor = Conductor::from_library("LGJ-400/35");
let model = ThermalModel::new(&conductor)
.ambient_temp(35.0) // Ambient temperature °C
.wind_speed(0.5) // Wind speed m/s
.solar_radiation(800.0); // Solar radiation W/m²
// Calculate steady-state temperature at current current
let steady_temp = model.steady_state_temp(current_amp: 600.0).await?;
// Calculate short-term overload allowed time
let allowed = model.emergency_rating(
current_amp: 800.0,
max_temp: 80.0,
duration: Duration::minutes(15),
).await?;
println!("Allowed overload duration: {:?}", allowed.duration);
Dynamic Line Rating
// Dynamic Line Rating (DLR) based on weather data
let dlr = model.dynamic_line_rating(&weather).await?;
println!("Dynamic line rating: {:.0} A", dlr.ampacity);
Thermal Stability Parameter Table
| Conductor Model | Steady-state Current (A) | Emergency Current (A) | Allowed Temperature (°C) |
|---|---|---|---|
| LGJ-240/30 | 410 | 550 | 70 |
| LGJ-300/25 | 480 | 640 | 70 |
| LGJ-400/35 | 580 | 780 | 70 |
| LGJ-500/45 | 660 | 880 | 70 |
| LGJ-630/55 | 760 | 1020 | 70 |
5. Constraint Optimization Solver
Introduced the eneros-constraint-solver Crate, integrating LP/QP/MILP solvers, supporting constrained optimization problems such as economic dispatch, optimal power flow, and unit commitment.
LP Solving (Economic Dispatch)
use eneros_constraint_solver::{Problem, Solver, Variable, Constraint, Objective};
let mut problem = Problem::new();
// Decision variables: generator outputs
let g1 = problem.add_var(Variable::continuous().bounds(0.0, 100.0));
let g2 = problem.add_var(Variable::continuous().bounds(0.0, 200.0));
let g3 = problem.add_var(Variable::continuous().bounds(0.0, 150.0));
// Constraint: load balance
problem.add_constraint(Constraint::equal(
vec![(g1, 1.0), (g2, 1.0), (g3, 1.0)],
350.0, // Total load 350MW
));
// Constraint: reserve capacity
problem.add_constraint(Constraint::greater_equal(
vec![(g1, 1.0), (g2, 1.0), (g3, 1.0)],
380.0, // Reserve 30MW
));
// Objective: cost minimization
problem.set_objective(Objective::minimize(vec![
(g1, 30.0), // Cost coefficients
(g2, 25.0),
(g3, 40.0),
]));
let solution = Solver::simplex().solve(&problem).await?;
println!("Optimal output: G1={:.1}, G2={:.1}, G3={:.1}",
solution.value(g1), solution.value(g2), solution.value(g3));
QP Solving (Optimal Power Flow)
// Optimal power flow: minimize network losses
let opf = OpfProblem::new(&network)
.objective(Objective::MinLoss)
.constraints(Constraints::all()) // Voltage/current/thermal stability
.solver(Solver::interior_point());
let result = opf.solve().await?;
Solver Performance
| Problem Type | Scale | Solving Time | Algorithm |
|---|---|---|---|
| LP | 1000 variables | 8ms | Simplex |
| LP | 10000 variables | 45ms | Dual simplex |
| QP | 500 variables | 15ms | Interior point |
| QP | 5000 variables | 85ms | Interior point |
| MILP | 100 binary | 120ms | Branch and bound |
| MILP | 1000 binary | 1.2s | Branch and bound + heuristics |
Improvements
- Constraint Caching: Constraint validation results cached by topology fingerprint, repeated validation reduced from 10μs to 1μs
- Incremental Validation: Only validates affected areas, reducing large grid validation time by 70%
- Parallel Solving: QP solver supports multi-threading, 3.2x speedup on 4 cores
- Constraint Explanation: Outputs human-readable explanations when constraints are violated, facilitating operations troubleshooting
Bug Fixes
- Fixed
eneros-constraintconstraint boundaries not updating during electrical island splitting (#2205) - Fixed
eneros-powerflowNewton method non-convergence in ill-conditioned systems (#2209) - Fixed
eneros-thermalnumerical oscillation during ambient temperature jumps (#2214) - Fixed
eneros-constraint-solverMILP solver infinite loop in degenerate cases (#2219)
Breaking Changes
Constraint::checkreturn type: Changed fromResult<bool>toResult<ConstraintReport>, including detailed overlimit informationPowerflowSolver::solve: Newconstraints: &ConstraintSetparameter, can pass&ConstraintSet::default()by default
Upgrade Guide
- Run
cargo update -p eneros-physics-decision - Update
Constraint::checkcalls to adapt to newConstraintReportreturn type - Provide
ConstraintSetparameter forPowerflowSolver::solve - Refer to
docs/migration/v0.22.0.mdfor detailed migration steps