powerio-prob 0.7.2

Problem instance builders for power system analysis and optimization.
Documentation
1
2
3
4
5
6
7
8
9
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
use powerio::BusId;
use serde::{Deserialize, Serialize};

/// One bus row: `(i, uid, v_min, v_max)`.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfBusRow {
    pub i: BusId,
    pub uid: String,
    pub v_min: f64,
    pub v_max: f64,
}

/// One shunt row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfShuntRow {
    pub uid: String,
    pub bus: BusId,
    pub g_sh: f64,
    pub b_sh: f64,
}

/// One AC line row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfAcLineRow {
    pub j_ln: usize,
    pub uid: String,
    pub to_bus: BusId,
    pub fr_bus: BusId,
    pub c_su: f64,
    pub c_sd: f64,
    pub s_max: f64,
    pub g_sr: f64,
    pub b_sr: f64,
    pub b_ch: f64,
    pub g_fr: f64,
    pub g_to: f64,
    pub b_fr: f64,
    pub b_to: f64,
}

/// One two winding transformer row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfTransformerRow {
    pub j_xf: usize,
    pub uid: String,
    pub to_bus: BusId,
    pub fr_bus: BusId,
    pub c_su: f64,
    pub c_sd: f64,
    pub s_max: f64,
    pub g_sr: f64,
    pub b_sr: f64,
    pub b_ch: f64,
    pub g_fr: f64,
    pub g_to: f64,
    pub b_fr: f64,
    pub b_to: f64,
}

/// One DC line row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfDcLineRow {
    pub j_dc: usize,
    pub uid: String,
    pub pdc_max: f64,
    pub qdc_fr_min: f64,
    pub qdc_to_min: f64,
    pub qdc_fr_max: f64,
    pub qdc_to_max: f64,
    pub to_bus: BusId,
    pub fr_bus: BusId,
}

/// A transformer with a variable phase-shift control range (`vpd`).
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfVariablePhaseRow {
    pub j_xf: usize,
    pub phi_min: f64,
    pub phi_max: f64,
}

/// A transformer with a fixed phase shift (`fpd`).
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfFixedPhaseRow {
    pub j_xf: usize,
    pub phi_o: f64,
}

/// A transformer with a variable winding ratio control range (`vwr`).
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfVariableRatioRow {
    pub j_xf: usize,
    pub tau_min: f64,
    pub tau_max: f64,
}

/// A transformer with a fixed winding ratio (`fwr`).
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfFixedRatioRow {
    pub j_xf: usize,
    pub tau_o: f64,
}

/// One simple dispatchable device row.
///
/// Producers and consumers share this layout. Vector fields use the internal
/// zero based period order.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfDeviceRow {
    pub bus: BusId,
    pub uid: String,
    pub c_on: f64,
    pub c_su: f64,
    pub c_sd: f64,
    pub p_ru: f64,
    pub p_rd: f64,
    pub p_ru_su: f64,
    pub p_rd_sd: f64,
    pub c_rgu: Vec<f64>,
    pub c_rgd: Vec<f64>,
    pub c_scr: Vec<f64>,
    pub c_nsc: Vec<f64>,
    pub c_rru_on: Vec<f64>,
    pub c_rru_off: Vec<f64>,
    pub c_rrd_on: Vec<f64>,
    pub c_rrd_off: Vec<f64>,
    pub c_qru: Vec<f64>,
    pub c_qrd: Vec<f64>,
    pub p_rgu_max: f64,
    pub p_rgd_max: f64,
    pub p_scr_max: f64,
    pub p_nsc_max: f64,
    pub p_rru_on_max: f64,
    pub p_rru_off_max: f64,
    pub p_rrd_on_max: f64,
    pub p_rrd_off_max: f64,
    pub p_0: f64,
    pub q_0: f64,
    pub p_max: Vec<f64>,
    pub p_min: Vec<f64>,
    pub q_max: Vec<f64>,
    pub q_min: Vec<f64>,
    pub sus: Vec<Vec<f64>>,
}

/// One active power zonal reserve row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfActiveReserveRow {
    pub n_p: usize,
    pub uid: String,
    pub c_rgu: f64,
    pub c_rgd: f64,
    pub c_scr: f64,
    pub c_nsc: f64,
    pub c_rru: f64,
    pub c_rrd: f64,
    pub sigma_rgu: f64,
    pub sigma_rgd: f64,
    pub sigma_scr: f64,
    pub sigma_nsc: f64,
    pub p_rru_min: Vec<f64>,
    pub p_rrd_min: Vec<f64>,
}

/// One reactive (reactive-power) zonal reserve row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfReactiveReserveRow {
    pub n_q: usize,
    pub uid: String,
    pub c_qru: f64,
    pub c_qrd: f64,
    pub q_qru_min: Vec<f64>,
    pub q_qrd_min: Vec<f64>,
}

/// One (bus, active reserve zone, device) membership row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfActiveReserveSetRow {
    pub i: BusId,
    pub n_p: usize,
    pub uid: String,
}

/// One (bus, reactive reserve zone, device) membership row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfReactiveReserveSetRow {
    pub i: BusId,
    pub n_q: usize,
    pub uid: String,
}

/// Set sizes for each indexed device class.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfLengths {
    pub l_j_xf: usize,
    pub l_j_ln: usize,
    pub l_j_ac: usize,
    pub l_j_dc: usize,
    pub l_j_br: usize,
    pub l_j_cs: usize,
    pub l_j_pr: usize,
    pub l_j_cspr: usize,
    pub l_j_sh: usize,
    /// Bus count.
    pub i: usize,
    pub l_t: usize,
    pub l_n_p: usize,
    pub l_n_q: usize,
}

/// Static buses, branches, devices, controls, reserves, and memberships.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfStaticData {
    pub bus: Vec<ScopfBusRow>,
    pub shunt: Vec<ScopfShuntRow>,
    pub acl_branch: Vec<ScopfAcLineRow>,
    pub acx_branch: Vec<ScopfTransformerRow>,
    pub vpd: Vec<ScopfVariablePhaseRow>,
    pub fpd: Vec<ScopfFixedPhaseRow>,
    pub vwr: Vec<ScopfVariableRatioRow>,
    pub fwr: Vec<ScopfFixedRatioRow>,
    pub dc_branch: Vec<ScopfDcLineRow>,
    pub prod: Vec<ScopfDeviceRow>,
    pub cons: Vec<ScopfDeviceRow>,
    pub active_reserve: Vec<ScopfActiveReserveRow>,
    pub reactive_reserve: Vec<ScopfReactiveReserveRow>,
    pub active_reserve_set_pr: Vec<ScopfActiveReserveSetRow>,
    pub active_reserve_set_cs: Vec<ScopfActiveReserveSetRow>,
    pub reactive_reserve_set_pr: Vec<ScopfReactiveReserveSetRow>,
    pub reactive_reserve_set_cs: Vec<ScopfReactiveReserveSetRow>,
}

/// One device energy cost curve. `cost[t][m]` is `[c_en, p_max]` for price
/// block `m` in period `t`.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub(super) struct ScopfCostRow {
    pub(super) bus: BusId,
    pub(super) uid: String,
    pub(super) cost: Vec<Vec<[f64; 2]>>,
}

/// Static index sets and the cost vectors used by the price block projection.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub(super) struct ScopfStaticDataProjection {
    pub(super) static_data: ScopfStaticData,
    pub(super) lengths: ScopfLengths,
    pub(super) cost_vector_pr: Vec<ScopfCostRow>,
    pub(super) cost_vector_cs: Vec<ScopfCostRow>,
}

macro_rules! energy_window_row {
    ($name:ident, $ind_field:ident, $start_field:ident, $end_field:ident, $bound_field:ident) => {
        #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
        pub struct $name {
            pub $ind_field: usize,
            pub uid: String,
            pub $start_field: f64,
            pub $end_field: f64,
            pub $bound_field: f64,
        }
    };
}

energy_window_row!(
    ScopfEnergyWindowMaxPrRow,
    w_en_max_pr_ind,
    a_en_max_start,
    a_en_max_end,
    e_max
);
energy_window_row!(
    ScopfEnergyWindowMaxCsRow,
    w_en_max_cs_ind,
    a_en_max_start,
    a_en_max_end,
    e_max
);
energy_window_row!(
    ScopfEnergyWindowMinPrRow,
    w_en_min_pr_ind,
    a_en_min_start,
    a_en_min_end,
    e_min
);
energy_window_row!(
    ScopfEnergyWindowMinCsRow,
    w_en_min_cs_ind,
    a_en_min_start,
    a_en_min_end,
    e_min
);

macro_rules! energy_window_period_row {
    ($name:ident, $ind_field:ident) => {
        /// Period membership of one energy window: the period belongs when
        /// its midpoint falls within the window's `(start, end]` interval.
        #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
        pub struct $name {
            pub $ind_field: usize,
            pub uid: String,
            pub t: usize,
            pub dt: f64,
        }
    };
}

energy_window_period_row!(ScopfEnergyWindowPeriodMaxPrRow, w_en_max_pr_ind);
energy_window_period_row!(ScopfEnergyWindowPeriodMaxCsRow, w_en_max_cs_ind);
energy_window_period_row!(ScopfEnergyWindowPeriodMinPrRow, w_en_min_pr_ind);
energy_window_period_row!(ScopfEnergyWindowPeriodMinCsRow, w_en_min_cs_ind);

/// Energy requirement windows and their period memberships.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfEnergyWindows {
    pub w_en_max_pr: Vec<ScopfEnergyWindowMaxPrRow>,
    pub w_en_max_cs: Vec<ScopfEnergyWindowMaxCsRow>,
    pub w_en_min_pr: Vec<ScopfEnergyWindowMinPrRow>,
    pub w_en_min_cs: Vec<ScopfEnergyWindowMinCsRow>,
    pub t_w_en_max_pr: Vec<ScopfEnergyWindowPeriodMaxPrRow>,
    pub t_w_en_max_cs: Vec<ScopfEnergyWindowPeriodMaxCsRow>,
    pub t_w_en_min_pr: Vec<ScopfEnergyWindowPeriodMinPrRow>,
    pub t_w_en_min_cs: Vec<ScopfEnergyWindowPeriodMinCsRow>,
}

/// One flattened device, period, and price block row.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfPriceBlockRow {
    pub flat_k: usize,
    pub uid: String,
    pub t: usize,
    pub m: usize,
    pub c_en: f64,
    pub p_max: f64,
}

/// Flattened producer and consumer price blocks.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfPriceBlocks {
    pub producer: Vec<ScopfPriceBlockRow>,
    pub consumer: Vec<ScopfPriceBlockRow>,
}

/// One AC line surviving a contingency.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfAcLineSurvivorRow {
    pub ctg: usize,
    pub j_ln: usize,
    pub uid: String,
    pub to_bus: BusId,
    pub fr_bus: BusId,
    pub b_sr: f64,
    pub s_max_ctg: f64,
}

/// One transformer surviving a contingency.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfTransformerSurvivorRow {
    pub ctg: usize,
    pub j_xf: usize,
    pub uid: String,
    pub to_bus: BusId,
    pub fr_bus: BusId,
    pub b_sr: f64,
    pub s_max_ctg: f64,
}

/// Per-contingency surviving AC lines and transformers, one group per
/// contingency in `reliability.contingency` document order.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfAcContingencySurvivors {
    pub ln: Vec<Vec<ScopfAcLineSurvivorRow>>,
    pub xf: Vec<Vec<ScopfTransformerSurvivorRow>>,
}

/// One surviving DC line in one contingency and period.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfDcContingencyFlowRow {
    pub flat_jtk_dc: usize,
    pub ctg: usize,
    pub j_dc: usize,
    pub to_bus: BusId,
    pub fr_bus: BusId,
    pub t: usize,
    pub dt: f64,
}

/// Matrix free SCOPF input data.
///
/// Internal class, period, contingency, window, and flattened row indices are
/// zero based. Source UIDs and external bus IDs remain separate fields.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScopfInstance {
    /// Buses, branches, devices, controls, reserves, and memberships.
    pub static_data: ScopfStaticData,
    pub lengths: ScopfLengths,
    pub energy_windows: ScopfEnergyWindows,
    pub price_blocks: ScopfPriceBlocks,
    pub ac_contingency_survivors: ScopfAcContingencySurvivors,
    pub dc_contingency_flows: Vec<ScopfDcContingencyFlowRow>,
}