rill_core_wdf/
adapters.rs1use crate::WdfElement;
2use parking_lot::RwLock;
3use rill_core::Transcendental;
4use std::sync::Arc;
5
6#[derive(Clone)]
11pub struct SeriesAdapter<T: Transcendental> {
12 elements: Vec<Arc<RwLock<dyn WdfElement<T>>>>,
13 port_resistance: T,
14}
15
16impl<T: Transcendental> std::fmt::Debug for SeriesAdapter<T> {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("SeriesAdapter")
19 .field("num_elements", &self.elements.len())
20 .field("port_resistance", &self.port_resistance)
21 .finish()
22 }
23}
24
25impl<T: Transcendental> SeriesAdapter<T> {
26 pub fn new(elements: Vec<Arc<RwLock<dyn WdfElement<T>>>>) -> Self {
28 let port_resistance: T = elements
29 .iter()
30 .map(|e| e.read().port_resistance())
31 .fold(T::ZERO, |a, b| a + b);
32
33 Self {
34 elements,
35 port_resistance,
36 }
37 }
38
39 pub fn elements(&self) -> &[Arc<RwLock<dyn WdfElement<T>>>] {
41 &self.elements
42 }
43}
44
45impl<T: Transcendental> WdfElement<T> for SeriesAdapter<T> {
46 fn port_resistance(&self) -> T {
47 self.port_resistance
48 }
49
50 fn process_incident(&mut self, a: T) -> T {
51 let total_r = self.port_resistance;
52 let mut b_total = T::ZERO;
53
54 for element in &self.elements {
55 let r_i = element.read().port_resistance();
56 let a_i = a * (r_i / total_r);
57
58 let b_i = element.write().process_incident(a_i);
59 b_total += b_i * (r_i / total_r);
60 }
61
62 b_total
63 }
64
65 fn update_state(&mut self) {
66 for element in &self.elements {
67 element.write().update_state();
68 }
69 }
70
71 fn voltage(&self) -> T {
72 self.elements
73 .iter()
74 .map(|e| e.read().voltage())
75 .fold(T::ZERO, |a, b| a + b)
76 }
77
78 fn current(&self) -> T {
79 self.elements
80 .first()
81 .map(|e| e.read().current())
82 .unwrap_or(T::ZERO)
83 }
84
85 fn reset(&mut self) {
86 for element in &self.elements {
87 element.write().reset();
88 }
89 }
90}
91
92#[derive(Clone)]
97pub struct ParallelAdapter<T: Transcendental> {
98 elements: Vec<Arc<RwLock<dyn WdfElement<T>>>>,
99 port_resistance: T,
100}
101
102impl<T: Transcendental> std::fmt::Debug for ParallelAdapter<T> {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("ParallelAdapter")
105 .field("num_elements", &self.elements.len())
106 .field("port_resistance", &self.port_resistance)
107 .finish()
108 }
109}
110
111impl<T: Transcendental> ParallelAdapter<T> {
112 pub fn new(elements: Vec<Arc<RwLock<dyn WdfElement<T>>>>) -> Self {
114 let inv_port_resistance: T = elements
115 .iter()
116 .map(|e| T::ONE / e.read().port_resistance())
117 .fold(T::ZERO, |a, b| a + b);
118
119 let port_resistance = T::ONE / inv_port_resistance;
120
121 Self {
122 elements,
123 port_resistance,
124 }
125 }
126
127 pub fn elements(&self) -> &[Arc<RwLock<dyn WdfElement<T>>>] {
129 &self.elements
130 }
131}
132
133impl<T: Transcendental> WdfElement<T> for ParallelAdapter<T> {
134 fn port_resistance(&self) -> T {
135 self.port_resistance
136 }
137
138 fn process_incident(&mut self, a: T) -> T {
139 let total_g: T = self
140 .elements
141 .iter()
142 .map(|e| T::ONE / e.read().port_resistance())
143 .fold(T::ZERO, |a, b| a + b);
144
145 let two = T::from_f32(2.0);
146 let alpha: Vec<T> = self
147 .elements
148 .iter()
149 .map(|e| {
150 let g_i = T::ONE / e.read().port_resistance();
151 two * g_i / total_g
152 })
153 .collect();
154
155 let mut sum_alpha_b = T::ZERO;
156 for (i, element) in self.elements.iter().enumerate() {
157 let b_i = element.write().process_incident(a);
158 sum_alpha_b += alpha[i] * b_i;
159 }
160
161 sum_alpha_b - a
162 }
163
164 fn update_state(&mut self) {
165 for element in &self.elements {
166 element.write().update_state();
167 }
168 }
169
170 fn voltage(&self) -> T {
171 self.elements
172 .first()
173 .map(|e| e.read().voltage())
174 .unwrap_or(T::ZERO)
175 }
176
177 fn current(&self) -> T {
178 self.elements
179 .iter()
180 .map(|e| e.read().current())
181 .fold(T::ZERO, |a, b| a + b)
182 }
183
184 fn reset(&mut self) {
185 for element in &self.elements {
186 element.write().reset();
187 }
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194 use crate::elements::{Capacitor, Resistor};
195
196 #[test]
197 fn test_series_adapter() {
198 let sample_rate = 44100.0;
199
200 let resistor: Arc<RwLock<dyn WdfElement<f64>>> =
201 Arc::new(RwLock::new(Resistor::new(1000.0)));
202 let capacitor: Arc<RwLock<dyn WdfElement<f64>>> =
203 Arc::new(RwLock::new(Capacitor::new(1e-6, sample_rate)));
204
205 let elements = vec![resistor.clone(), capacitor.clone()];
206 let adapter: SeriesAdapter<f64> = SeriesAdapter::new(elements);
207
208 let total_r = adapter.port_resistance();
209 let r1 = resistor.read().port_resistance();
210 let r2 = capacitor.read().port_resistance();
211
212 assert!((total_r - (r1 + r2)).abs() < 1e-10);
213 }
214}