vpp_sim/sim/
event.rs

1/// External demand response event requesting temporary load reduction.
2#[derive(Debug, Clone, Copy)]
3pub struct DemandResponseEvent {
4    /// Start timestep (inclusive).
5    pub start_step: usize,
6    /// End timestep (exclusive).
7    pub end_step: usize,
8    /// Requested reduction while event is active.
9    pub requested_reduction_kw: f32,
10}
11
12impl DemandResponseEvent {
13    pub fn new(start_step: usize, end_step: usize, requested_reduction_kw: f32) -> Self {
14        assert!(start_step < end_step);
15        assert!(requested_reduction_kw >= 0.0);
16
17        Self {
18            start_step,
19            end_step,
20            requested_reduction_kw,
21        }
22    }
23
24    pub fn is_active(&self, timestep: usize) -> bool {
25        timestep >= self.start_step && timestep < self.end_step
26    }
27
28    pub fn requested_reduction_at_kw(&self, timestep: usize) -> f32 {
29        if self.is_active(timestep) {
30            self.requested_reduction_kw
31        } else {
32            0.0
33        }
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::DemandResponseEvent;
40
41    #[test]
42    fn active_only_inside_window() {
43        let event = DemandResponseEvent::new(5, 8, 2.0);
44        assert!(!event.is_active(4));
45        assert!(event.is_active(5));
46        assert!(event.is_active(7));
47        assert!(!event.is_active(8));
48    }
49
50    #[test]
51    fn reduction_is_zero_outside_window() {
52        let event = DemandResponseEvent::new(10, 12, 1.5);
53        assert_eq!(event.requested_reduction_at_kw(9), 0.0);
54        assert_eq!(event.requested_reduction_at_kw(10), 1.5);
55        assert_eq!(event.requested_reduction_at_kw(11), 1.5);
56        assert_eq!(event.requested_reduction_at_kw(12), 0.0);
57    }
58}