Skip to main content

powerio_prob/instance/
constraints.rs

1//! Active constraint selections for the optimal power flow instances.
2//!
3//! Physical limit values stay on the network so every calculation reuses
4//! them; an OPF instance selects which of those limits are active
5//! constraints, by stable element identity, without copying the numerical
6//! bounds.
7
8use serde::{Deserialize, Serialize};
9
10/// Which elements of one constraint family are active, by stable element
11/// identity (the payload `uid`, else `{table}:{row}`; buses by their id).
12#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
13#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
14#[serde(rename_all = "snake_case", tag = "select", content = "identities")]
15#[non_exhaustive]
16pub enum ConstraintSelection {
17    /// Every element with a stated limit.
18    #[default]
19    All,
20    /// No element; the family is relaxed.
21    None,
22    /// Exactly the named elements.
23    Only(Vec<String>),
24}
25
26impl ConstraintSelection {
27    /// Whether the named element's limit is an active constraint.
28    #[must_use]
29    pub fn selects(&self, identity: &str) -> bool {
30        match self {
31            Self::All => true,
32            Self::None => false,
33            Self::Only(identities) => identities.iter().any(|selected| selected == identity),
34        }
35    }
36}
37
38/// The active constraint families of a balanced OPF instance.
39#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
40#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
41#[non_exhaustive]
42pub struct ActiveConstraints {
43    /// Generator capability bounds (active and reactive limits).
44    pub generator_capability: ConstraintSelection,
45    /// Bus voltage magnitude bounds.
46    pub voltage_bounds: ConstraintSelection,
47    /// Branch thermal limits.
48    pub thermal_limits: ConstraintSelection,
49    /// Branch angle difference bounds.
50    pub angle_bounds: ConstraintSelection,
51}
52
53/// The active constraint families of a multiconductor OPF instance.
54#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
55#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
56#[non_exhaustive]
57pub struct MulticonductorActiveConstraints {
58    /// Terminal voltage magnitude bounds.
59    pub terminal_voltage_bounds: ConstraintSelection,
60    /// Conductor current or apparent power limits.
61    pub conductor_limits: ConstraintSelection,
62    /// Per phase generator capability bounds.
63    pub generator_capability: ConstraintSelection,
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn selections_answer_by_identity() {
72        assert!(ConstraintSelection::All.selects("branches:3"));
73        assert!(!ConstraintSelection::None.selects("branches:3"));
74        let only = ConstraintSelection::Only(vec!["branches:3".to_owned()]);
75        assert!(only.selects("branches:3"));
76        assert!(!only.selects("branches:4"));
77    }
78}