1use crate::y::build_y;
2use anyhow::Result;
3use num_complex::Complex64;
4use power_flow_data::{BusNum, FixedShunt, Generator, Load, Network};
5use sparsetools::csr::CSR;
6use sparsetools::Complex;
7use std::collections::HashMap;
8use sundials::context::Context;
9use sundials::nvector;
10use sundials::nvector::NVector;
11
12#[derive(Clone)]
13pub(super) struct UserData {
14 pub(super) s_base: f64,
18 pub(super) loads: Vec<Load>,
19 pub(super) generators: Vec<Generator>,
20 pub(super) fixed_shunts: Vec<FixedShunt>,
21
22 pub(super) a: HashMap<BusNum, usize>,
23 pub(super) v: HashMap<BusNum, usize>,
24 pub(super) q: HashMap<usize, usize>,
25 pub(super) p: HashMap<usize, usize>,
26 pub(super) slack: BusNum,
27
28 pub(super) ang0: HashMap<BusNum, f64>, pub(super) y_mat: CSR<usize, Complex64>,
32}
33
34impl UserData {
36 pub(super) fn new(network: Network) -> Self {
38 let mut a = HashMap::default();
39 let mut v = HashMap::default();
40 let mut q: HashMap<usize, usize> = HashMap::default();
41 let mut p: HashMap<usize, usize> = HashMap::default();
42 let mut ang0 = HashMap::default();
44
45 let nb = network.buses.len();
46 let ng = network.generators.len();
47 let slack: Vec<BusNum> = network
57 .buses
58 .iter()
59 .filter(|bus| bus.ide == 3)
60 .map(|bus| bus.i)
61 .collect();
62 assert_eq!(slack.len(), 1);
63 let slack = slack[0];
64
65 let mut k = 0;
68 for (i, bus) in network.buses.iter().enumerate() {
71 a.insert(bus.i, i);
73 v.insert(bus.i, nb + i);
74
75 ang0.insert(bus.i, bus.va.to_radians());
77 }
79 for (j, gen) in network.generators.iter().enumerate() {
80 q.insert(j, 2 * nb + j);
81 if gen.i == slack {
85 p.insert(j, 2 * nb + ng + k);
86 k += 1;
87 }
88 }
89 let y_mat = build_y(&network, &a );
93
94 println!("a: {:?}", a);
96 println!("v: {:?}", v);
97 println!("q: {:?}", q);
98 println!("p: {:?}", p);
99 Self {
102 s_base: network.caseid.sbase,
104
105 loads: network.loads.clone(),
106 generators: network.generators.clone(),
107 fixed_shunts: network.fixed_shunts.clone(),
108
109 a,
110 v,
111 q,
112 p,
113 slack,
114 ang0,
116
117 y_mat,
118 }
119 }
120}
121
122pub struct Flow {
123 pub pi: f64,
124 pub qi: f64,
125 pub pj: f64,
126 pub qj: f64,
127 pub schgi: Complex64,
128 pub schgj: Complex64,
129}
130
131pub fn post_process(
132 network: &mut Network,
133 y: &NVector,
134 a: &HashMap<BusNum, usize>,
135 v: &HashMap<BusNum, usize>,
136 q: &HashMap<usize, usize>,
137 p: &HashMap<usize, usize>,
138 slack: BusNum,
139) -> Result<(Vec<Flow>, Vec<Flow>)> {
140 let s_base = network.caseid.sbase;
141 let yd = y.as_slice();
142
143 let mut brch_flows = Vec::with_capacity(network.branches.len());
144 let mut tfmr_flows = Vec::with_capacity(network.transformers.len());
145
146 for bus in &mut network.buses {
149 let a = a[&bus.i];
150 let v = v[&bus.i];
151
152 bus.va = yd[a].to_degrees();
153 bus.vm = yd[v];
154 }
155 for (i, gen) in &mut network.generators.iter_mut().enumerate() {
156 let q = q[&i];
158 gen.qg = yd[q] * s_base;
159
160 if gen.i == slack {
162 let p = p[&i];
163 gen.pg = yd[p] * s_base;
164 } else {
165 }
167 }
172 #[allow(non_snake_case)]
175 for tr in &mut network.transformers {
176 let Sb = Complex64::new(s_base, 0.0);
184
185 let (g, b) = match tr.cm {
186 1 => (tr.mag1, tr.mag2),
187 _ => {
188 panic!("cm must be 1: {}", tr.cm);
189 }
190 };
191
192 let y0 = 0.5 * Complex64::new(g, b);
193 let y12 = 1.0 / Complex64::new(tr.r1_2, tr.x1_2);
194
195 let tap = tr.windv1;
196 let phi = tr.ang1;
197 let m = Complex64::from_polar(tap, phi.to_radians());
198 let mconj = m.conj();
199 let m2 = Complex64::new(m.norm().powi(2), 0.0);
200
201 let a1 = a[&tr.i];
202 let a2 = a[&tr.j];
203 let v1 = v[&tr.i];
204 let v2 = v[&tr.j];
205
206 let V1 = Complex64::new(yd[v1], yd[a1]);
207 let V2 = Complex64::new(yd[v2], yd[a2]);
208
209 let I1 = (V1 * ((y12 + y0) / m2)) - (V2 * (y12 / mconj));
210 let I2 = (V2 * (y12 + y0)) - (V1 * (y12 / m));
211 let S1 = V1 * I1.conj() * Sb;
212 let S2 = V2 * I2.conj() * Sb;
213
214 tfmr_flows.push(Flow {
215 pi: S1.real(),
216 qi: S1.imag(),
217 pj: S2.real(),
218 qj: S2.imag(),
219 schgi: y0 * (V1.powi(2) / m2) * Sb,
220 schgj: y0 * V2.powi(2) * Sb,
221 });
222 }
223 #[allow(non_snake_case)]
226 for l in &network.branches {
227 let Sb = Complex64::new(s_base, 0.0);
235
236 let y0 = 0.5 * Complex64::new(0.0, l.b);
237 let y1 = Complex64::new(l.gi, l.bi);
240 let y2 = Complex64::new(l.gj, l.bj);
241 let y12 = Complex64::new(1.0, 0.0) / Complex64::new(l.r, l.x);
242
243 let a1 = a[&l.i];
244 let a2 = a[&l.j];
245 let v1 = v[&l.i];
246 let v2 = v[&l.j];
247
248 let V1 = Complex64::new(yd[v1], yd[a1]);
249 let V2 = Complex64::new(yd[v2], yd[a2]);
250
251 let I1 = (V1 * (y12 + y0 + y1)) - (V2 * y12);
252 let I2 = (V2 * (y12 + y0 + y2)) - (V1 * y12);
253 let S1 = V1 * I1.conj() * Sb;
254 let S2 = V2 * I2.conj() * Sb;
255
256 brch_flows.push(Flow {
257 pi: S1.real(),
258 qi: S1.imag(),
259 pj: S2.real(),
260 qj: S2.imag(),
261 schgi: Complex64::new(l.gi, l.bi) * V1.powi(2) * Sb,
262 schgj: Complex64::new(l.gj, l.bj) * V2.powi(2) * Sb,
263 });
264 }
265
266 let mut cg = HashMap::<BusNum, Vec<usize>>::new();
272 for (j, gen) in network.generators.iter().enumerate() {
273 cg.entry(gen.i).or_insert_with(Vec::new).push(j);
278 }
279
280 for (_, l) in &cg {
281 if l.len() < 2 {
282 continue;
283 }
284 let mut qg_tot: f64 = 0.0; for &g in l {
286 qg_tot += network.generators[g].qg;
287 }
288
289 let mut m: f64 = 0.0;
293 for &j in l {
294 let pv = &network.generators[j];
295 let mut mj = pv.qg.abs();
296 if !pv.qt.is_infinite() {
297 mj += pv.qt.abs();
298 }
299 if !pv.qb.is_infinite() {
300 mj += pv.qb.abs();
301 }
302 m += mj
303 }
304 let mut q_min = vec![0.0; l.len()];
305 let mut q_max = vec![0.0; l.len()];
306 for (i, j) in l.iter().enumerate() {
307 let pv = &network.generators[*j];
308
309 q_min[i] = pv.qb;
310 q_max[i] = pv.qt;
311
312 if pv.qb == f64::INFINITY {
313 q_min[i] = m;
314 }
315 if pv.qb == f64::NEG_INFINITY {
316 q_min[i] = -m;
317 }
318 if pv.qt == f64::INFINITY {
319 q_max[i] = m;
320 }
321 if pv.qt == f64::NEG_INFINITY {
322 q_max[i] = -m;
323 }
324 }
325 let qg_min: f64 = q_min.iter().sum(); let qg_max: f64 = q_max.iter().sum(); if (qg_min - qg_max).abs() > 1e-13 {
329 let q = (qg_tot - qg_min) / (qg_max - qg_min);
330 for (i, &j) in l.iter().enumerate() {
331 network.generators[j].qg = q_min[i] + (q * (q_max[i] - q_min[i]));
333 }
334 } else {
335 let mis = (qg_tot - qg_min) / (l.len() as f64);
340 for (i, &j) in l.iter().enumerate() {
341 network.generators[j].qg = q_min[i] + mis;
342 }
343 }
344 }
345
346 Ok((brch_flows, tfmr_flows))
347}
348
349pub fn u0(
350 ctx: &Context,
351 network: &Network,
352 a: &HashMap<BusNum, usize>,
353 v: &HashMap<BusNum, usize>,
354 q: &HashMap<usize, usize>,
355 p: &HashMap<usize, usize>,
356 ang0: &HashMap<BusNum, f64>,
357 slack: BusNum,
358) -> NVector {
359 let s_base = network.caseid.sbase;
361
362 let n = a.len() + v.len() + q.len() + p.len();
363 let v0 = nvector::NVector::new_serial(n as i64, ctx).unwrap(); let data = v0.as_slice_mut();
365
366 for bus in &network.buses {
367 let a = a[&bus.i];
368 let v = v[&bus.i];
369 let ang0 = ang0[&bus.i];
370
371 data[a] = ang0;
372 if bus.vm != 0.0 {
373 data[v] = bus.vm;
374 } else {
375 data[v] = 1.0;
376 }
377 }
378
379 for (i, gen) in network.generators.iter().enumerate() {
380 if gen.vs != 0.0 {
381 let v = v[&gen.i];
382 data[v] = gen.vs;
383 }
384
385 let qg = q[&i];
386 data[qg] = gen.qg / s_base;
387
388 if gen.i == slack {
389 let pg = p[&i];
390 data[pg] = gen.pg / s_base;
391 }
392 }
393
394 println!("v0: {:?}", data);
396
397 v0
398}