vpp_sim/devices/types.rs
1//! Common types and traits for device simulation components.
2
3use rand::{RngExt, rngs::StdRng};
4
5/// Contextual information passed to devices during power calculations.
6/// Includes the current timestep and optional setpoints for controllable devices.
7/// # Fields
8/// * `timestep` - Current simulation timestep
9/// * `setpoint_kw` - Optional power setpoint for controllable devices (kW)
10pub struct DeviceContext {
11 pub timestep: usize,
12 pub setpoint_kw: Option<f32>,
13}
14
15impl DeviceContext {
16 /// Creates a new DeviceContext with the given timestep and no setpoint.
17 pub fn new(timestep: usize) -> Self {
18 Self {
19 timestep,
20 setpoint_kw: None,
21 }
22 }
23
24 /// Creates a new DeviceContext with the given timestep and setpoint.
25 pub fn with_setpoint(timestep: usize, setpoint_kw: f32) -> Self {
26 Self {
27 timestep,
28 setpoint_kw: Some(setpoint_kw),
29 }
30 }
31}
32
33/// Trait defining a device that can produce or consume electricity.
34///
35/// This trait provides a common interface for all devices in the simulation,
36/// allowing them to be used interchangeably in power flow calculations.
37pub trait Device {
38 /// Returns the power value at the specified time step.
39 ///
40 /// Positive values indicate power consumption (load),
41 /// negative values indicate power generation.
42 ///
43 /// # Arguments
44 ///
45 /// * `context` - Contextual information about the device and simulation state, like:
46 /// - `timestep`: Current simulation time step
47 /// - `setpoint_kw`: Optional power setpoint for controllable devices
48 ///
49 /// # Returns
50 ///
51 /// Power in kilowatts (kW) at the specified time step
52 fn power_kw(&mut self, context: &DeviceContext) -> f32;
53
54 /// Returns a human-readable type name for the device.
55 fn device_type(&self) -> &'static str;
56}
57
58/// Utility function to generate Gaussian noise using Box-Muller transform.
59///
60/// # Arguments
61///
62/// * `rng` - Random number generator
63/// * `std_dev` - Standard deviation of the noise
64///
65/// # Returns
66///
67/// Random value from a Gaussian distribution with mean 0 and specified standard deviation
68pub fn gaussian_noise(rng: &mut StdRng, std_dev: f32) -> f32 {
69 if std_dev <= 0.0 {
70 return 0.0;
71 }
72
73 let u1: f32 = rng.random::<f32>().clamp(1e-6, 1.0);
74 let u2: f32 = rng.random::<f32>();
75 let z0 = (-2.0_f32 * u1.ln()).sqrt() * (2.0_f32 * std::f32::consts::PI * u2).cos();
76 z0 * std_dev
77}