use num_complex::Complex64;
use sparsetools::coo::Coo;
use sparsetools::csr::CSR;
use std::iter::zip;
pub fn d_imis_dv(
s_bus: &Vec<Complex64>,
y_bus: &CSR<usize, Complex64>,
v: &[Complex64],
vcart: bool,
) -> anyhow::Result<(CSR<usize, Complex64>, CSR<usize, Complex64>)> {
let n = v.len();
let (d_imis_dv1, d_imis_dv2) = if vcart {
let diag_sv2c = Coo::new(
n,
n,
(0..n).collect(),
(0..n).collect(),
zip(s_bus, v)
.map(|(s_bus, v)| s_bus / (v * v).conj())
.collect(),
)?
.to_csr();
let d_imis_dvr = y_bus + &diag_sv2c;
let d_imis_dvi = Complex64::i() * (y_bus - diag_sv2c);
(d_imis_dvr, d_imis_dvi)
} else {
let v_norm = v
.iter()
.map(|v| v / Complex64::new(v.norm(), 0.0))
.collect();
let i_bus = zip(s_bus, v).map(|(s_bus, v)| s_bus / v).collect();
let i_bus_vm: Vec<Complex64> = zip(&i_bus, v)
.map(|(i_bus, v)| i_bus / Complex64::new(v.norm(), 0.0))
.collect();
let diag_v = CSR::with_diagonal(v.to_vec());
let diag_ibus = CSR::with_diagonal(i_bus);
let diag_ibus_vm = CSR::with_diagonal(i_bus_vm);
let diag_v_norm = CSR::with_diagonal(v_norm);
let d_imis_dva = Complex64::i() * (y_bus * diag_v - diag_ibus);
let d_imis_dvm = y_bus * diag_v_norm + diag_ibus_vm;
(d_imis_dva, d_imis_dvm)
};
Ok((d_imis_dv1, d_imis_dv2))
}