powerio_matrix/matrix/bdoubleprime.rs
1//! FDPF `B''` matrix. Reactive power Jacobian.
2//!
3//! Per MATPOWER `makeB.m`:
4//! - **XB scheme**: `B'' = -Im(Y_bus)` with phase shifts zeroed.
5//! - **BX scheme**: `B'' = -Im(Y_bus)` with line resistance and phase shifts
6//! zeroed.
7//!
8//! Tap ratios, line charging, and bus shunts are kept in both schemes —
9//! they are what give B″ its strict diagonal dominance (full rank).
10
11use sprs::CsMat;
12
13use crate::Result;
14use crate::indexed::IndexedNetwork;
15
16use super::ybus::{YbusFlags, build_ybus_with_flags};
17use super::{BuildOptions, Scheme, negate_into};
18
19pub fn build_bdoubleprime(case: &IndexedNetwork, opts: &BuildOptions) -> Result<CsMat<f64>> {
20 let flags = YbusFlags {
21 zero_resistance: matches!(opts.scheme, Scheme::Bx),
22 zero_charging: false,
23 unity_taps: false,
24 zero_shifts: true,
25 skip_bus_shunts: false,
26 };
27 // `parts.b` is owned and discarded here, so negate it in place rather than
28 // cloning the structure.
29 let parts = build_ybus_with_flags(case, flags)?;
30 Ok(negate_into(parts.b))
31}