use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
#[cfg(feature = "rsparse")]
use crate::basic::ecs::network::PowerFlowSolver;
use crate::basic::ecs::{elements::*, network::apply_permutation};
use super::systems::{PowerFlowMat, init_states};
use crate::prelude::ecs::network::SolverStage::*;
#[derive(Message, Default, Debug, Clone, Copy)]
pub struct VoltageChangeEvent;
#[derive(Message, Default, Debug, Clone, Copy)]
pub struct SBusChangeEvent;
#[derive(Message, Default, Debug, Clone, Copy)]
pub struct FullRebuildEvent;
#[derive(Message, Default, Debug, Clone, Copy)]
pub struct NodeTypeChangeEvent;
#[derive(Default, Debug, Clone, Copy)]
pub struct SimStateFlags {
pub structure_dirty: bool,
pub admit_dirty: bool,
pub injection_dirty: bool,
pub voltage_dirty: bool,
}
pub fn event_update(
mut e_sbus: MessageReader<SBusChangeEvent>,
mut e_vbus: MessageReader<VoltageChangeEvent>,
mut e_full: MessageReader<FullRebuildEvent>,
mut e_node_type: MessageReader<NodeTypeChangeEvent>,
) -> SimStateFlags {
let mut flags = SimStateFlags::default();
if !e_full.is_empty() {
flags.structure_dirty = true;
flags.admit_dirty = true;
flags.injection_dirty = true;
flags.voltage_dirty = true;
} else {
if !e_node_type.is_empty() {
flags.structure_dirty = true;
}
if !e_sbus.is_empty() {
flags.injection_dirty = true;
}
if !e_vbus.is_empty() {
flags.voltage_dirty = true;
}
}
e_full.clear();
e_node_type.clear();
e_sbus.clear();
e_vbus.clear();
flags
}
pub fn reset_solvers(world: &mut World) {
use crate::basic::solver::*;
if let Some(mut solver) = world.get_resource_mut::<PowerFlowSolver>() {
solver.solver.reset();
}
}
pub fn sbus_pu_update(
mut pfmat: ResMut<PowerFlowMat>,
sbus: Query<(&BusID, &SBusInjPu), Changed<SBusInjPu>>,
) {
for (bus_id, s) in sbus {
let idx = pfmat.reorder_index(bus_id.0 as usize);
pfmat.s_bus[idx] = s.0;
}
}
pub fn vbus_pu_update(
mut pfmat: ResMut<PowerFlowMat>,
sbus: Query<(&TargetBus, &VBusPu), Changed<VBusPu>>,
) {
for (bus_id, s) in sbus {
let idx = pfmat.reorder_index(bus_id.0 as usize);
pfmat.s_bus[idx] = s.0;
}
}
pub fn structure_update(world: &mut World) {
let flags = world.run_system_cached(event_update).unwrap();
if flags.structure_dirty || flags.admit_dirty {
world.run_system_cached(reset_solvers).unwrap();
world.run_system_cached(init_states).unwrap();
world.run_system_cached(apply_permutation).unwrap();
} else {
if flags.injection_dirty {
world.run_system_cached(sbus_pu_update).unwrap();
}
if flags.voltage_dirty {
world.run_system_cached(vbus_pu_update).unwrap();
}
}
}
#[derive(Default)]
pub struct StructureUpdatePlugin;
impl Plugin for StructureUpdatePlugin {
fn build(&self, app: &mut App) {
app.add_message::<VoltageChangeEvent>();
app.add_message::<SBusChangeEvent>();
app.add_message::<FullRebuildEvent>();
app.add_message::<NodeTypeChangeEvent>();
app.add_systems(Update, structure_update.after(BeforeSolve).before(Solve));
}
}