Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ MadNLP = "0.10"
MadNLPGPU = "0.10"
julia = "1.11"

# The two-stage SCOPF (scopf_twostage_model) needs MadNLP's SchurComplementKKTSystem
# support for design-only constraints + the deterministic GPU Schur assembly, which live
# on the `schur-design-constraints` branch (not yet released). Pin both MadNLP and the
# MadNLPGPU subpackage to that branch so `Pkg.test()` (local and CI) resolves it instead
# of the registry release. Remove once these land in a tagged MadNLP/MadNLPGPU.
[sources]
MadNLP = {url = "https://github.com/MadNLP/MadNLP.jl", rev = "schur-design-constraints"}
MadNLPGPU = {url = "https://github.com/MadNLP/MadNLP.jl", rev = "schur-design-constraints", subdir = "lib/MadNLPGPU"}

[extras]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e"
Expand Down
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,65 @@ model, cons, vars, lengths, sc_data_array = goc3_model(
result = madnlp(model; tol=1e-4)
```

### Generic N-1 security-constrained OPF

Independent of the GOC3 formulation, `scopf_model` builds a lightweight, hard-constrained
N-1 SCOPF. Each contingency is a generator or branch (line) outage; the base case plus all
contingencies are solved together as one AC OPF, with bounded corrective generator redispatch
in the post-contingency scenarios. Line outages are applied by zeroing the branch admittance
(so its flows are forced to zero), and MATPOWER `rateA = 0` ("unlimited") is mapped to a large
finite rating.

```julia
using ExaModelsPower, MadNLP, DelimitedFiles

# One outage per entry; (type = :gen, idx = g) is also supported.
idxs = vec(readdlm("data/case118.Ctgs", Int)) # 1-based branch indices
contingencies = [(type = :branch, idx = l) for l in idxs]

model, vars, cons = scopf_model("case118.m", contingencies; form = :polar)
result = madnlp(model; tol = 1e-4)

# On a GPU backend, solve the condensed KKT system with cuDSS:
using MadNLPGPU, CUDA, CUDSS
model, vars, cons = scopf_model("case118.m", contingencies; backend = CUDABackend())
result = madnlp(model;
kkt_system = MadNLP.SparseCondensedKKTSystem,
linear_solver = MadNLPGPU.CUDSSSolver,
tol = 1e-4)
```

#### Two-stage / Schur form

`scopf_twostage_model` builds the same problem on a `TwoStageExaCore` (base case = first stage,
each contingency = a scenario) so it can be solved with MadNLP's `SchurComplementKKTSystem`,
which factorizes the per-contingency blocks in parallel. It returns an extra `post_solve_info`
NamedTuple with the Schur dimensions:

```julia
model, vars, cons, info = scopf_twostage_model("case118.m", contingencies; backend = CUDABackend())
result = madnlp(model;
kkt_system = SchurComplementKKTSystem,
linear_solver = MadNLPGPU.CUDSSSolver,
kkt_options = Dict(:schur_ns => info.ns, :schur_nv => info.nv,
:schur_nd => info.nd, :schur_nc => info.nc))
```

> **Note.** The base-case physics are first-stage *design* constraints. The current
> `SchurComplementKKTSystem` does not yet support design-only constraint rows (solving asserts
> `m == ns*nc`, off by exactly `info.nc_design`). The model is structurally correct; the Schur
> solve is gated on upstream support for design-only constraints.

A runnable example covering both formulations (`--mode single`/`twostage`/`compare`), both
coordinate systems (`--form polar`/`rect`), and a choice of case (`--case case9`/`case118`) is in
[`examples/scopf.jl`](examples/scopf.jl). Options are ArgParse CLI flags:

```bash
julia --project=./examples examples/scopf.jl --help
julia --project=./examples examples/scopf.jl --case case9 --mode twostage --form rect
julia --project=./examples examples/scopf.jl --gpu --inertia free
```

### Multi-period optimal power flow
```julia
model, vars, cons = mpopf_model(
Expand Down
176 changes: 176 additions & 0 deletions data/case118.Ctgs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
2
3
4
5
6
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
178
179
180
181
182
185
186
Loading
Loading