1use qsim_core::{GridElement, StateStore};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Branch {
9 pub from_bus: usize,
11 pub to_bus: usize,
13 pub resistance: f64,
15 pub reactance: f64,
17 pub susceptance: f64,
19 pub tap_ratio: f64,
21 pub phase_shift: f64,
23 pub in_service: bool,
25}
26
27impl Branch {
28 pub fn line(from_bus: usize, to_bus: usize, resistance: f64, reactance: f64) -> Self {
30 Self {
31 from_bus,
32 to_bus,
33 resistance,
34 reactance,
35 susceptance: 0.0,
36 tap_ratio: 1.0,
37 phase_shift: 0.0,
38 in_service: true,
39 }
40 }
41
42 pub fn line_with_charging(
44 from_bus: usize,
45 to_bus: usize,
46 resistance: f64,
47 reactance: f64,
48 susceptance: f64,
49 ) -> Self {
50 Self {
51 from_bus,
52 to_bus,
53 resistance,
54 reactance,
55 susceptance,
56 tap_ratio: 1.0,
57 phase_shift: 0.0,
58 in_service: true,
59 }
60 }
61
62 pub fn transformer(
64 from_bus: usize,
65 to_bus: usize,
66 resistance: f64,
67 reactance: f64,
68 tap_ratio: f64,
69 ) -> Self {
70 Self {
71 from_bus,
72 to_bus,
73 resistance,
74 reactance,
75 susceptance: 0.0,
76 tap_ratio,
77 phase_shift: 0.0,
78 in_service: true,
79 }
80 }
81
82 pub fn impedance(&self) -> f64 {
84 (self.resistance.powi(2) + self.reactance.powi(2)).sqrt()
85 }
86
87 pub fn admittance(&self) -> (f64, f64) {
89 let z2 = self.resistance.powi(2) + self.reactance.powi(2);
90 if z2 > 0.0 {
91 (self.resistance / z2, -self.reactance / z2)
92 } else {
93 (0.0, 0.0)
94 }
95 }
96}
97
98impl GridElement for Branch {
99 fn element_type(&self) -> &'static str {
100 if (self.tap_ratio - 1.0).abs() < 1e-6 {
101 "Branch::Line"
102 } else {
103 "Branch::Transformer"
104 }
105 }
106
107 fn apply(&self, _state: &mut StateStore) {
108 }
110}