use crate::network::power_injections;
use crate::types::BusType;
use super::{Invalidates, OuterLoop, OuterLoopContext, OuterLoopStatus};
#[derive(Clone, Debug, Default)]
pub struct QLimitReport {
pub switches: Vec<usize>,
}
#[derive(Clone, Debug, Default)]
pub struct ReactiveLimits {
switches: Vec<usize>,
}
impl ReactiveLimits {
pub fn new() -> Self {
Self::default()
}
pub fn report(&self) -> QLimitReport {
QLimitReport {
switches: self.switches.clone(),
}
}
pub fn switches(&self) -> &[usize] {
&self.switches
}
}
impl OuterLoop for ReactiveLimits {
fn name(&self) -> &'static str {
"ReactiveLimits"
}
fn invalidates(&self) -> Invalidates {
Invalidates::Pattern
}
fn check(&mut self, ctx: &mut OuterLoopContext<'_, '_>) -> OuterLoopStatus {
let (_, q_calc) = power_injections(ctx.net.buses, ctx.net.ybus);
let mut switched = false;
for b in ctx.net.buses.iter_mut() {
if b.bus_type != BusType::PV {
continue;
}
let q = q_calc[b.idx];
if q < b.q_min {
b.bus_type = BusType::PQ;
b.q_spec = b.q_min;
self.switches.push(b.idx);
switched = true;
} else if q > b.q_max {
b.bus_type = BusType::PQ;
b.q_spec = b.q_max;
self.switches.push(b.idx);
switched = true;
}
}
if switched {
OuterLoopStatus::Unstable
} else {
OuterLoopStatus::Stable
}
}
}