Skip to main content

powerio_prob/matrix/
mod.rs

1//! Sparse projections and bundle output for problem instances.
2
3mod bundle;
4
5use powerio_matrix::matrix::incidence::diagonal;
6use powerio_matrix::matrix::triplet::CooBuilder;
7use powerio_matrix::{
8    SparseMatrix, build_flow_map, build_weighted_laplacian, ground_at_each, reference_indicator,
9};
10
11use crate::DcOpfInstance;
12
13pub use bundle::{DcOpfBundleMetadata, DcOpfBundleOptions, DcOpfOutputs, write_dcopf_bundle};
14
15/// Sparse matrices for a DC OPF instance.
16#[derive(Debug, Clone)]
17#[non_exhaustive]
18pub struct DcOpfMatrices {
19    pub incidence: SparseMatrix,
20    pub laplacian: SparseMatrix,
21    pub grounded_laplacian: SparseMatrix,
22    pub flow_map: SparseMatrix,
23    pub generator_bus: SparseMatrix,
24    /// Generator space quadratic cost diagonal.
25    pub generator_cost: SparseMatrix,
26    pub reference_selector: Vec<f64>,
27}
28
29/// Build sparse matrices without reading the source network again.
30#[must_use]
31pub fn build_dc_opf_matrices(instance: &DcOpfInstance) -> DcOpfMatrices {
32    let n = instance.n_buses;
33    let m = instance.n_branches();
34    let mut incidence = CooBuilder::with_capacity_rect(n, m, 2 * m);
35    for column in 0..m {
36        incidence.add(instance.branches.from_bus[column], column, 1.0);
37        incidence.add(instance.branches.to_bus[column], column, -1.0);
38    }
39    let incidence = incidence.finish_csr();
40    let laplacian = build_weighted_laplacian(&incidence, &instance.branches.b);
41    let grounded_laplacian = ground_at_each(&laplacian, instance.reference_buses.as_ref());
42    let flow_map = build_flow_map(&incidence, &instance.branches.b);
43
44    let n_gen = instance.n_generators();
45    let mut generator_bus = CooBuilder::with_capacity_rect(n, n_gen, n_gen);
46    for (column, &bus) in instance.generators.bus_of_gen.iter().enumerate() {
47        generator_bus.add(bus, column, 1.0);
48    }
49
50    DcOpfMatrices {
51        incidence,
52        laplacian,
53        grounded_laplacian,
54        flow_map,
55        generator_bus: generator_bus.finish_csr(),
56        generator_cost: diagonal(&instance.generators.q),
57        reference_selector: reference_indicator(n, instance.reference_buses.as_ref()),
58    }
59}