use crate::zip::make_sdzip;
use caseformat::{Bus, Gen};
use num_complex::Complex64;
#[derive(PartialEq)]
pub enum LoadZone {
Area = 0,
All = 1,
Bus = 2,
}
#[derive(PartialEq)]
pub enum LoadType {
Both = 0,
Fixed = 1,
Dispatchable = 2,
}
pub fn total_load(
bus: &[Bus],
gen: Option<&[Gen]>,
load_zone: LoadZone,
_load_zones: Option<&[Option<usize>]>,
load_type: LoadType,
nominal: bool,
pw: Option<[f64; 3]>,
qw: Option<[f64; 3]>,
want_q: bool,
) -> (Vec<f64>, Option<Vec<f64>>) {
let nb = bus.len();
let want_fixed = match load_type {
LoadType::Both | LoadType::Fixed => true,
_ => false,
};
let want_disp = match load_type {
LoadType::Both | LoadType::Dispatchable => true,
_ => false,
};
let lz = match load_zone {
LoadZone::Bus => Vec::from_iter(0..nb), LoadZone::All => vec![1; nb], LoadZone::Area => bus.iter().map(|b| b.bus_area).collect(),
};
let nz = *lz.iter().max().unwrap_or(&0);
let (p_df, q_df) = if want_fixed {
let (sd_z, sd_i, sd_p) = make_sdzip(1.0, bus, pw, qw);
let vm: Vec<Complex64> = bus.iter().map(|b| Complex64::new(b.vm, 0.0)).collect();
let s_bus_d = (0..nb)
.map(|i| sd_p[i] + sd_i[i] * vm[i] + sd_z[i] * (vm[i] * vm[i]))
.collect::<Vec<Complex64>>();
let p_df = s_bus_d.iter().map(|s| s.re).collect(); let q_df = if want_q {
Some(s_bus_d.iter().map(|s| s.im).collect()) } else {
None
};
(p_df, q_df)
} else {
let p_df = vec![0.0; nb];
let q_df = if want_q { Some(vec![0.0; nb]) } else { None };
(p_df, q_df)
};
let (p_dd, q_dd) = if want_disp {
let mut p_dd = vec![0.0; nb];
let mut q_dd = if want_q { Some(vec![0.0; nb]) } else { None };
if let Some(gen) = gen {
for g in gen {
if g.is_load() && g.is_on() {
if nominal {
p_dd[g.gen_bus] += -g.pmin;
if want_q {
let q_dd = q_dd.as_mut().unwrap();
if g.qmin == 0.0 {
q_dd[g.gen_bus] += g.qmax;
} else if g.qmax == 0.0 {
q_dd[g.gen_bus] += g.qmin;
}
}
} else {
p_dd[g.gen_bus] += -g.pg;
if want_q {
let q_dd = q_dd.as_mut().unwrap();
q_dd[g.gen_bus] += -g.qg;
}
}
}
}
}
(p_dd, q_dd)
} else {
let p_dd = vec![0.0; nb];
let q_dd = if want_q { Some(vec![0.0; nb]) } else { None };
(p_dd, q_dd)
};
if load_zone == LoadZone::Bus {
let p_d = bus
.iter()
.enumerate()
.map(|(i, b)| {
if b.bus_type != 4 {
p_df[i] + p_dd[i]
} else {
0.0
}
})
.collect();
let q_d = if want_q {
Some(
bus.iter()
.enumerate()
.map(|(i, b)| {
if b.bus_type != 4 {
let q_df = q_df.as_ref().unwrap();
let q_dd = q_dd.as_ref().unwrap();
q_df[i] + q_dd[i]
} else {
0.0
}
})
.collect(),
)
} else {
None
};
(p_d, q_d)
} else {
let mut p_d = vec![0.0; nz];
let mut q_d = if want_q { Some(vec![0.0; nz]) } else { None };
for k in 0..nz {
for (i, b) in bus.iter().enumerate() {
if lz[i] == k && b.bus_type != 4 {
p_d[k] += p_df[i] + p_dd[i];
if want_q {
let qd = q_d.as_mut().unwrap();
let q_df = q_df.as_ref().unwrap();
let q_dd = q_dd.as_ref().unwrap();
qd[k] += q_df[i] + q_dd[i]; }
}
}
}
(p_d, q_d)
}
}