frequenz_microgrid/quantity/
voltage.rs

1// License: MIT
2// Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
4//! This module defines the `Voltage` quantity and its operations.
5
6use super::{Current, Power};
7
8qty_ctor! {
9    #[doc = "A physical quantity representing voltage."]
10    Voltage => {
11        (from_millivolts, as_millivolts, "mV", 1e-3),
12        (from_volts, as_volts, "V", 1e0),
13        (from_kilovolts, as_kilovolts, "kV", 1e3),
14    }
15}
16
17impl std::ops::Mul<Current> for Voltage {
18    type Output = Power;
19
20    fn mul(self, current: Current) -> Self::Output {
21        Power::from_watts(self.as_volts() * current.as_amperes())
22    }
23}
24
25#[cfg(test)]
26mod tests {
27    use crate::quantity::{
28        Current, Percentage, Power, Quantity as _, Voltage, test_utils::assert_f32_eq,
29    };
30
31    #[test]
32    fn test_voltage() {
33        let voltage_1 = Voltage::from_volts(1000.0);
34
35        assert_f32_eq(voltage_1.as_millivolts(), 1_000_000.0);
36        assert_f32_eq(voltage_1.as_volts(), 1000.0);
37        assert_f32_eq(voltage_1.as_kilovolts(), 1.0);
38
39        let voltage_2 = Voltage::from_millivolts(1_200_000.0);
40        assert_f32_eq(voltage_2.as_volts(), 1200.0);
41
42        let voltage_2 = Voltage::from_kilovolts(1.2);
43        assert_f32_eq(voltage_2.as_volts(), 1200.0);
44
45        assert!(voltage_1 < voltage_2);
46        assert!(voltage_2 > voltage_1);
47
48        assert_f32_eq((voltage_1 + voltage_2).as_volts(), 2200.0);
49        assert_f32_eq((voltage_2 - voltage_1).as_volts(), 200.0);
50        assert_f32_eq((voltage_1 * 2.0).as_volts(), 2000.0);
51        assert_f32_eq((voltage_2 / 2.0).as_volts(), 600.0);
52        assert_f32_eq(
53            (voltage_2 * Percentage::from_percentage(50.0)).as_volts(),
54            600.0,
55        );
56        assert_f32_eq(voltage_2 / voltage_1, 1.2);
57
58        assert_f32_eq(Voltage::zero().as_volts(), 0.0);
59    }
60
61    #[test]
62    fn test_voltage_current_power() {
63        let voltage = Voltage::from_volts(230.0);
64        let current = Current::from_amperes(10.0);
65        let power = Power::from_watts(2300.0);
66
67        assert_f32_eq((voltage * current).as_watts(), 2300.0);
68        assert_f32_eq((power / voltage).as_amperes(), 10.0);
69        assert_f32_eq((power / current).as_volts(), 230.0);
70    }
71
72    #[test]
73    fn test_voltage_formatting() {
74        let s = |value| Voltage::from_volts(value).to_string();
75        let p = |value, prec| format!("{:.prec$}", Voltage::from_volts(value), prec = prec);
76        assert_eq!(s(0.0), "0 mV");
77
78        assert_eq!(s(0.000_5), "0.5 mV");
79        assert_eq!(p(0.000_5, 1), "0.5 mV");
80        assert_eq!(s(0.5), "500 mV");
81
82        assert_eq!(s(1.558), "1.558 V");
83        assert_eq!(p(1.558, 1), "1.6 V");
84        assert_eq!(s(1_558.0), "1.558 kV");
85        assert_eq!(p(1_558.0, 1), "1.6 kV");
86
87        assert_eq!(s(1.5508), "1.551 V");
88        assert_eq!(p(1.5508, 5), "1.5508 V");
89
90        assert_eq!(s(2_030_000.0), "2030 kV");
91
92        assert_eq!(s(-0.000_5), "-0.5 mV");
93        assert_eq!(p(-0.000_5, 1), "-0.5 mV");
94        assert_eq!(s(-0.5), "-500 mV");
95
96        assert_eq!(s(-1.558), "-1.558 V");
97        assert_eq!(p(-1.558, 1), "-1.6 V");
98        assert_eq!(s(-1_558.0), "-1.558 kV");
99        assert_eq!(p(-1_558.0, 1), "-1.6 kV");
100        assert_eq!(s(-2_030_000.0), "-2030 kV");
101    }
102}