use sprs::CsMat;
use crate::indexed::IndexedNetwork;
use crate::{Error, Result};
use super::{BuildOptions, Scheme, triplet::CooBuilder};
pub fn build_bprime(case: &IndexedNetwork, opts: &BuildOptions) -> Result<CsMat<f64>> {
let n = case.n();
let mut coo = CooBuilder::with_capacity(n, 4 * case.branches().len() + n);
for (row_idx, br) in case.in_service_branches() {
let i = case.bus_index(br.from).ok_or(Error::UnknownBus {
bus_id: br.from,
element_index: row_idx,
})?;
let j = case.bus_index(br.to).ok_or(Error::UnknownBus {
bus_id: br.to,
element_index: row_idx,
})?;
let b_off = match opts.scheme {
Scheme::Bx => {
let denom = br.r * br.r + br.x * br.x;
if denom == 0.0 {
if opts.skip_zero_impedance {
continue;
}
return Err(Error::ZeroImpedance { row: row_idx });
}
-br.x / denom
}
Scheme::Xb => {
if br.x == 0.0 {
if opts.skip_zero_impedance {
continue;
}
return Err(Error::ZeroImpedance { row: row_idx });
}
-1.0 / br.x
}
};
if !b_off.is_finite() {
return Err(Error::NonFiniteSusceptance { row: row_idx });
}
if i == j {
continue;
}
coo.add_sym(i, j, b_off);
coo.add(i, i, -b_off);
coo.add(j, j, -b_off);
}
Ok(coo.finish_csr())
}