# gridoxide
`gridoxide` is an AC power flow and state estimation tool written in Rust. It solves the power flow equations for
an electrical grid with the Newton-Raphson method, using a sparse Jacobian throughout ā assembly,
factorization, and solve.
š **[Documentation](https://m-mirz.github.io/gridoxide/)** ā the full book covers the method, the
solver backends, the CGMES importer, and the benchmark results. Its source lives in [`docs/`](docs/).
## Quick start
Rust ā you need the [Rust toolchain](https://rustup.rs/), nothing else for a default build:
```bash
cargo build --release
cargo test
```
Python:
```bash
pip install gridoxide
```
```python
import gridoxide
model = gridoxide.PowerFlowModel.from_pgm_json("grid.json", backend="klu_native")
model.solve()
print(model.voltage_mag(), model.voltage_ang())
```
Chat ā `gridmcp` is an [MCP](https://modelcontextprotocol.io) server that lets an LLM chat find,
summarise and solve the networks in a directory. Install the
[VS Code extension](https://marketplace.visualstudio.com/items?itemName=m-mirz.gridoxide), or
register it with any other client:
```bash
claude mcp add gridoxide -- uvx --from gridoxide-mcp gridmcp
```
See [Building and Running](docs/src/getting_started/building.md),
[Python Bindings](docs/src/getting_started/python.md) and
[MCP Server](docs/src/getting_started/mcp.md).
## What it does
- **Newton-Raphson AC power flow**, symmetric and asymmetric, with a sparse Jacobian and symbolic
factorization reused across both NR iterations and repeated solves
(`solver::PersistentSolver`) ā see [Backends and Factorization Reuse](docs/src/solvers/backends.md).
- **Two linear power flows**, both first-class modes rather than internal warm starts:
[DC (BĪø)](docs/src/powerflow/dc.md) ā real, lossless, one factorization and no iterations, with
phase shifters, both of powsybl's susceptance variants, and
[PTDF/LODF sensitivity factors](docs/src/powerflow/dc.md#sensitivity-factors-ptdf-and-lodf) for
contingency screening ā and [the constant-admittance
linearization](docs/src/powerflow/linear_impedance.md), which keeps resistance and produces
voltage magnitudes (power-grid-model's `CalculationMethod.linear`). Either can also warm-start
Newton.
- **Weighted-least-squares state estimation** ā recovers the most likely grid state from noisy,
redundant, partial measurements, with [observability analysis and bad-data
detection](docs/src/state_estimation/diagnostics.md) and zero injections enforced as hard
constraints rather than high-weight guesses. Validated against power-grid-model's own fixtures; see
[The State Estimation Problem](docs/src/state_estimation/index.md).
- **RMS (phasor-domain) dynamic simulation** (`--features dynamics`) ā what the network does over
*time* after a fault, rather than at one instant. The differential-algebraic system is solved
simultaneously, one Newton per step over machine states and network voltages together, with
classical, transient and subtransient machines, exciters, governors and stabilizers, and
scheduled faults, trips and load steps. Reads its own JSON, PSS/E `.dyr` and Dynawo `.dyd`/`.par`.
Gated against the equal-area criterion's closed-form critical clearing time and against
[Dynawo's own published answer](docs/src/dynamics/validation.md) for Kundur's Example 13.2 ā
see [The RMS Simulation Problem](docs/src/dynamics/index.md).
- **Small-signal (modal) analysis** on the same system ā eigenvalues, damping ratios,
participation factors naming the states each mode belongs to, and mode shapes saying how the
rotors move, from the very Jacobian blocks the time-domain solve already assembles. Dense below a
couple of thousand states; past that, **sparse shift-invert Arnoldi** takes over and returns the
modes near a named frequency without ever forming the state matrix ā 20 480 states in under 15 s, and
cross-checked against ARPACK on the identical operator. With **eigenvalue sensitivities**: how far
a mode moves, and how much damping it gains, per unit of a machine parameter. See
[Small-Signal Analysis](docs/src/dynamics/smallsignal.md).
- **Five interchangeable linear-solver backends** ā `faer` (`Scalar`), a hand-written block LU
(`Block`), vendored SuiteSparse KLU over FFI (`Klu`), a from-scratch Rust translation of KLU
(`KluNative`, always built), and Intel oneMKL PARDISO (`Pardiso`). All five produce identical
converged voltages; the choice is purely performance.
- **Three input formats** ā its own JSON, [power-grid-model](https://github.com/PowerGridModel/power-grid-model)
JSON, and [CGMES RDF/XML](docs/src/cgmes/index.md) (`--features cgmes`) with node-breaker
reduction, all four phase-tap-changer flavors, 3-winding star resolution, HVDC, and SVC.
- **Modeling features beyond the plain formulation** ā
[reactive power limits](docs/src/powerflow/q_limits.md) (PVāPQ switching),
[zero-impedance branches](docs/src/powerflow/zero_impedance_branches.md), and
[multi-island solves](docs/src/powerflow/multi_island.md) with a per-island status report.
- **Batched solving and N-1/N-k contingency screening** over one shared topology, parallel across
cores via rayon. AC contingencies keep the symbolic factorization across a whole outage sweep
(`batch::BatchSolver::solve_contingencies`, 2.0ā2.7x single-threaded before parallelism); in DC a
whole batch shares a *single* numeric factorization (`linear::batch::DcBatchSolver`, 9ā55x per
scenario), and outages need no re-solve at all ā N-1 via `DcSensitivity::outage_flows`, N-k via
the generalized `multi_outage_flows`.
[Feature Comparison](docs/src/reference/feature_comparison.md) is a detailed survey against five
other power flow tools, including the gaps gridoxide hasn't closed.
## Benchmarks
`scripts/bench/README.md` is the single source of truth for every benchmark number in this project;
[Benchmarking and Profiling](docs/src/reference/benchmarking.md) is a map into it. In short:
gridoxide is one of two solvers out of six that converge on all 12 real IEEE/MATPOWER test cases, and
its `Klu` backend is frequently faster than lightsim2grid's own KLU-backed C++ solver on real
transmission topology ā while power-grid-model remains clearly faster on synthetic radial
distribution grids, a real standing gap.
On **state estimation** the same pattern holds in both directions: gridoxide's Newton-Raphson
estimator is the only one of the two that answers at all above 300 buses, where power-grid-model's
raises `SparseMatrixError` on documents its own iterative-linear method estimates from without
complaint; on iterative-linear itself power-grid-model is 1.6-2.0x faster across an order of
magnitude of problem size, the clearest standing gap on that side. That gap is a convergence-rate
one, not a linear-algebra one ā gridoxide's iterations are 30-40% cheaper and it takes three times
as many of them.
## License
gridoxide's own code is Apache-2.0 ([`LICENSE`](LICENSE)). A **default** build always includes
`crates/gridoxide-sparse/src/klu_native/`, a from-scratch Rust translation of vendored SuiteSparse AMD/BTF/KLU source, so
`Cargo.toml`'s license field is `Apache-2.0 AND BSD-3-Clause AND LGPL-2.1-or-later` ā accurate for
every default build, not just an opt-in one.
Building with `--features klu` compiles the vendored SuiteSparse C itself, adding LGPL relinking
obligations for anyone distributing the resulting binary (a `klu-dynamic` sub-feature exists for
that case). Building with `--features pardiso` dynamically links a locally-installed Intel oneMKL
under Intel's own proprietary license; nothing MKL-derived is vendored or shipped by this repo.
See [Provenance and Licensing](docs/src/reference/provenance.md) for the full breakdown, and the
`PROVENANCE.md` files under `crates/gridoxide-sparse/src/klu_native/` and `crates/gridoxide-sparse/vendor/suitesparse/` for per-file detail.