use crate::error::Result;
use crate::network::topology::PowerNetwork;
use num_complex::Complex64;
use sprs::{CsMat, TriMat};
pub fn build_y_bus(network: &PowerNetwork) -> Result<CsMat<Complex64>> {
let n = network.bus_count();
let mut ybus = TriMat::new((n, n));
for branch in &network.branches {
if !branch.status {
continue;
}
let i = network.bus_index(branch.from_bus)?;
let j = network.bus_index(branch.to_bus)?;
let ys = Complex64::new(branch.r, branch.x).inv(); let bc = Complex64::new(0.0, branch.b / 2.0);
let tap = branch.tap_complex();
let tap_conj = tap.conj();
let tap_mag_sq = tap.norm_sqr();
let yii = ys / tap_mag_sq + bc;
let yjj = ys + bc;
let yij = -ys / tap_conj;
let yji = -ys / tap;
ybus.add_triplet(i, i, yii);
ybus.add_triplet(j, j, yjj);
ybus.add_triplet(i, j, yij);
ybus.add_triplet(j, i, yji);
}
for (i, bus) in network.buses.iter().enumerate() {
if bus.gs != 0.0 || bus.bs != 0.0 {
let y_shunt = Complex64::new(bus.gs, bus.bs) / network.base_mva;
ybus.add_triplet(i, i, y_shunt);
}
}
Ok(ybus.to_csc())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::network::branch::Branch;
use crate::network::bus::{Bus, BusType};
#[test]
fn test_simple_2bus_ybus() {
let mut net = PowerNetwork::new(100.0);
net.buses.push(Bus::new(1, BusType::Slack));
net.buses.push(Bus::new(2, BusType::PQ));
net.branches.push(Branch {
from_bus: 1,
to_bus: 2,
r: 0.01,
x: 0.1,
b: 0.02,
rate_a: 100.0,
rate_b: 100.0,
rate_c: 100.0,
tap: 0.0,
shift: 0.0,
status: true,
});
let ybus = build_y_bus(&net).unwrap();
assert_eq!(ybus.rows(), 2);
assert_eq!(ybus.cols(), 2);
let ys = Complex64::new(0.01, 0.1).inv();
let y12 = *ybus.get(0, 1).unwrap_or(&Complex64::new(0.0, 0.0));
assert!((y12 + ys).norm() < 1e-10);
}
}