A Julia package for differentiable power system analysis. Compute sensitivities of power flow solutions, optimal power flow dispatch, and locational marginal prices with respect to network parameters.
- Unified sensitivity API:
calc_sensitivity(state, :operand, :parameter)withSensitivity{T}return type - DC OPF: B-theta formulation with analytical KKT sensitivities for demand, switching, cost, flow limits, and susceptances
- DC power flow: Switching and demand sensitivities via matrix perturbation theory
- AC power flow: Voltage and current sensitivities w.r.t. power injections
- AC OPF: Full sensitivity analysis (switching, demand, costs, flow limits) via implicit differentiation of KKT conditions
- LMP analysis: Locational marginal prices with energy/congestion decomposition
- Load shedding: Sensitivity of optimal load curtailment to network parameters
Requires Julia 1.10 or later.
using Pkg
Pkg.add("PowerDiff")using PowerDiff
# Parse a case into a PowerIO module
net = parse_file("case14.m")
dc_net = DCNetwork(net)
d = calc_demand_vector(net)
# Solve DC OPF and compute sensitivities
prob = DCOPFProblem(dc_net, d)
solve!(prob)
dlmp_dd = calc_sensitivity(prob, :lmp, :d) # dLMP/dd (n x n)
dpg_dsw = calc_sensitivity(prob, :pg, :sw) # dg/dsw (k x m)
dlmp_dd.formulation # :dcopf
dlmp_dd[2, 3] # dLMP_2 / dd_3See the Getting Started guide for DC/AC power flow and OPF walkthroughs.
- Getting Started — DC PF, DC OPF, AC PF, AC OPF walkthroughs
- Sensitivity API — Operand/parameter tables, valid combinations, indexing
- Mathematical Background — B-theta formulation, KKT implicit differentiation
- Advanced Topics — Type hierarchy, caching, solver configuration
- API Reference — Full docstring reference
PowerDiff reads files through PowerIO, and parse_file reads every transmission
format the linked PowerIO library does — MATPOWER .m, PSS/E .raw, PowerWorld,
PowerModels JSON, Egret JSON, pandapower, PyPSA, PSLF, gridfm, GO Challenge 3 and
the rest. The format tokens are PowerIO's, so a reader PowerIO gains works here at
once.
A path's format is inferred from its extension; a stream has no extension, so pass
from (MATPOWER is assumed otherwise). A bare json names a container rather than
a reader, so name the one you mean: from=:powermodels, :egret, :pandapower.
parse_file returns a PowerIO.PioModule. Beyond the case itself it carries
m.diagnostics, the reader's findings as records you can branch on by code and
severity; m.sources[1].format, the reader that ran; and enough for
PowerIO.emit(m, "psse", path) to write the case out again.
See CONTRIBUTING.md for how to run the tests and build the docs. Maintainers cutting a release follow RELEASING.md.
- PowerIO.jl — Parser and data layer (see PowerIO Integration)
- JuMP.jl — Optimization modeling
- ExaModels.jl — Alternative optimization modeling for GPU parallelization
- Ipopt.jl — Default solver for DC and AC OPF
Apache License 2.0