use std::collections::BTreeMap;
use powerio_core::{Diagnostic, Error};
use powerio_tx::{
BalancedNetwork, BusId, BusMergeRule, MergeSurvivor, RemovalReason, ZeroImpedanceRule,
};
use crate::diagnostics::codes;
#[derive(Clone, Debug, Default, PartialEq)]
#[non_exhaustive]
pub struct ZeroImpedanceMerge {
pub merged_buses: BTreeMap<BusId, BusId>,
pub removed_branches: Vec<String>,
}
pub fn merge_zero_impedance_buses(
network: &BalancedNetwork,
) -> Result<(BalancedNetwork, ZeroImpedanceMerge, Vec<Diagnostic>), Error> {
let rule = BusMergeRule::new(false, Some(ZeroImpedanceRule::Exact))
.with_survivor(MergeSurvivor::SmallestId);
let merge = network
.merge_buses(&rule)
.map_err(|error| Error::new(error.code(), error.to_string()))?;
let mut diagnostics = Vec::with_capacity(merge.removed_branches.len());
for removed in &merge.removed_branches {
if removed.reason == RemovalReason::ZeroImpedance {
diagnostics.push(Diagnostic::of(
&codes::CANONICALIZE_MERGE_ZERO_IMPEDANCE,
format!(
"zero impedance branch `{}` between buses {} and {} was merged; its flow is not a variable of any derived calculation",
removed.identity, removed.from, removed.to
),
));
}
}
diagnostics.extend(
merge
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.code() != codes::CANONICALIZE_MERGE_ZERO_IMPEDANCE.code)
.cloned(),
);
let removed_branches = merge
.removed_branches
.iter()
.map(|removed| removed.identity.clone())
.collect();
Ok((
merge.network,
ZeroImpedanceMerge {
merged_buses: merge.merged_buses,
removed_branches,
},
diagnostics,
))
}