frequenz_microgrid/quantity/
power.rs1use super::{Current, Energy, Voltage};
7
8qty_ctor! {
9 #[doc = "A physical quantity representing active power."]
10 Power => {
11 (from_milliwatts, as_milliwatts, "mW", 1e-3),
12 (from_watts, as_watts, "W", 1e0),
13 (from_kilowatts, as_kilowatts, "kW", 1e3),
14 (from_megawatts, as_megawatts, "MW", 1e6),
15 (from_gigawatts, as_gigawatts, "GW", 1e9),
16 }
17}
18
19impl std::ops::Div<Voltage> for Power {
20 type Output = Current;
21
22 fn div(self, voltage: Voltage) -> Self::Output {
23 Current::from_amperes(self.as_watts() / voltage.as_volts())
24 }
25}
26
27impl std::ops::Div<Current> for Power {
28 type Output = Voltage;
29
30 fn div(self, current: Current) -> Self::Output {
31 Voltage::from_volts(self.as_watts() / current.as_amperes())
32 }
33}
34
35impl std::ops::Mul<std::time::Duration> for Power {
36 type Output = Energy;
37
38 fn mul(self, duration: std::time::Duration) -> Self::Output {
39 Energy::from_watthours(self.as_watts() * duration.as_secs_f32() / 3600.0)
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::Power;
46 use super::{Current, Energy, Voltage};
47 use crate::quantity::Percentage;
48 use crate::quantity::{Quantity as _, test_utils::assert_f32_eq};
49
50 #[test]
51 fn test_power() {
52 let power_1 = Power::from_watts(1000.0);
53 assert_f32_eq(power_1.as_milliwatts(), 1_000_000.0);
54 assert_f32_eq(power_1.as_watts(), 1000.0);
55 assert_f32_eq(power_1.as_kilowatts(), 1.0);
56 assert_f32_eq(power_1.as_megawatts(), 0.001);
57 assert_f32_eq(power_1.as_gigawatts(), 0.000_001);
58
59 let power_2 = Power::from_milliwatts(1_200_000.0);
60 assert_f32_eq(power_2.as_watts(), 1200.0);
61 let power_2 = Power::from_kilowatts(1.2);
62 assert_f32_eq(power_2.as_watts(), 1200.0);
63 let power_2 = Power::from_megawatts(0.001_2);
64 assert_f32_eq(power_2.as_watts(), 1200.0);
65 let power_2 = Power::from_gigawatts(0.000_001_2);
66 assert_f32_eq(power_2.as_watts(), 1200.0);
67
68 assert!(power_1 < power_2);
69 assert!(power_2 > power_1);
70
71 assert_f32_eq((power_1 + power_2).as_watts(), 2200.0);
72 assert_f32_eq((power_2 - power_1).as_watts(), 200.0);
73 assert_f32_eq((power_2 * 2.0).as_watts(), 2400.0);
74 assert_f32_eq((power_2 / 2.0).as_watts(), 600.0);
75 assert_f32_eq(
76 (power_2 * Percentage::from_percentage(80.0)).as_watts(),
77 960.0,
78 );
79 assert_f32_eq(power_2 / power_1, 1.2);
80
81 assert_f32_eq(Power::zero().as_watts(), 0.0);
82 }
83
84 #[test]
85 fn test_power_voltage_current() {
86 let power = Power::from_kilowatts(2.0);
87 let voltage = Voltage::from_volts(400.0);
88 let current = Current::from_amperes(5.0);
89
90 let computed_current = power / voltage;
91 assert_f32_eq(computed_current.as_amperes(), 5.0);
92
93 let computed_voltage = power / current;
94 assert_f32_eq(computed_voltage.as_volts(), 400.0);
95 }
96
97 #[test]
98 fn test_power_energy_duration() {
99 let power = Power::from_kilowatts(0.5);
100 let duration = std::time::Duration::from_secs(7200);
101 let energy = Energy::from_kilowatthours(1.0);
102
103 let computed_energy = power * duration;
104 assert_f32_eq(computed_energy.as_kilowatthours(), 1.0);
105
106 let computed_power = energy / duration;
107 assert_f32_eq(computed_power.as_kilowatts(), 0.5);
108 }
109
110 #[test]
111 fn test_power_formatting() {
112 let s = |value| Power::from_watts(value).to_string();
113 let p = |value, prec| format!("{:.prec$}", Power::from_watts(value), prec = prec);
114 assert_eq!(s(0.0), "0 mW");
115
116 assert_eq!(s(1.558), "1.558 W");
117 assert_eq!(p(1.558, 1), "1.6 W");
118
119 assert_eq!(s(1.5508), "1.551 W");
120 assert_eq!(p(1.5508, 5), "1.5508 W");
121
122 assert_eq!(s(2030.0), "2.03 kW");
123
124 assert_eq!(s(2_030_022.0), "2.03 MW");
125 assert_eq!(s(2_030_022_123.0), "2.03 GW");
126 assert_eq!(p(2_030_022_123.0, 6), "2.030022 GW");
127
128 assert_eq!(s(-1.558), "-1.558 W");
129 assert_eq!(p(-1.558, 1), "-1.6 W");
130
131 assert_eq!(s(-2030.0), "-2.03 kW");
132 assert_eq!(p(-2030.0, 1), "-2 kW");
133
134 assert_eq!(s(-2_030_022.0), "-2.03 MW");
135 assert_eq!(s(-2_030_022_123.0), "-2.03 GW");
136 assert_eq!(p(-2_030_022_123.0, 6), "-2.030022 GW");
137 }
138}