cgmes_area_probe/
cgmes_area_probe.rs1use std::path::{Path, PathBuf};
4fn main() {
5 let root =
6 Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/data/CGMES-Test-Configurations/v3.0");
7 for name in std::env::args().skip(1) {
8 let dir = root.join(&name);
9 if !dir.is_dir() {
10 println!("{name}: absent");
11 continue;
12 }
13 let mut paths: Vec<PathBuf> = std::fs::read_dir(&dir)
14 .unwrap()
15 .filter_map(|e| e.ok().map(|e| e.path()))
16 .filter(|p| p.extension().is_some_and(|x| x == "xml"))
17 .collect();
18 paths.sort();
19 let refs: Vec<&Path> = paths.iter().map(|p| p.as_path()).collect();
20 let ds = gridoxide::cgmes::load_profiles(&refs).expect("load");
21 let net = gridoxide::cgmes::cgmes_to_network(&ds, 100e6).expect("convert");
22 let areas = gridoxide::cgmes::cgmes_control_areas(&ds, &net, 100e6).expect("areas");
23 println!("=== {name}");
24 println!(" {:?}", areas.report);
25 let report = gridoxide::run_power_flow(
26 net.buses.clone(),
27 &net.lines,
28 &net.transformers,
29 &net.shunts,
30 gridoxide::TapData::none(),
31 gridoxide::PowerFlowOptions {
32 tol: 1e-8,
33 max_iter: 40,
34 ..Default::default()
35 },
36 );
37 let x = gridoxide::outerloop::AreaInterchange::measure(
38 &report.buses,
39 &net.lines,
40 &net.transformers,
41 &areas.of_bus,
42 areas.ids.len(),
43 );
44 println!(" solve {:?}", report.stats.status);
45 let unassigned: Vec<usize> = areas
47 .of_bus
48 .iter()
49 .enumerate()
50 .filter(|(_, a)| a.is_none())
51 .map(|(i, _)| i)
52 .collect();
53 let inj: f64 = unassigned.iter().map(|&i| report.buses[i].p_spec).sum();
54 println!(
55 " {} bus(es) in no area, injecting {:.3} MW between them",
56 unassigned.len(),
57 inj * 100.0
58 );
59 println!(
60 " sum of area positions: {:.3} MW",
61 x.iter().sum::<f64>() * 100.0
62 );
63 for (i, (mrid, nm)) in areas.ids.iter().enumerate() {
64 let buses = areas.of_bus.iter().filter(|a| **a == Some(i)).count();
65 println!(
66 " {:<4} ({}) {:>4} bus(es) scheduled export {:>10.3} MW actual {:>10.3} MW",
67 nm,
68 &mrid[..8.min(mrid.len())],
69 buses,
70 areas.targets[i] * 100.0,
71 x[i] * 100.0
72 );
73 }
74 }
75}