rill_core_model/
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 mut alpha = [T::ZERO; 8];
148
149 for (i, e) in self.elements.iter().enumerate() {
150 let g_i = T::ONE / e.read().port_resistance();
151 alpha[i] = two * g_i / total_g;
152 }
153
154 let mut sum_alpha_b = T::ZERO;
155 for (i, element) in self.elements.iter().enumerate() {
156 let b_i = element.write().process_incident(a);
157 sum_alpha_b += alpha[i] * b_i;
158 }
159
160 sum_alpha_b - a
161 }
162
163 fn update_state(&mut self) {
164 for element in &self.elements {
165 element.write().update_state();
166 }
167 }
168
169 fn voltage(&self) -> T {
170 self.elements
171 .first()
172 .map(|e| e.read().voltage())
173 .unwrap_or(T::ZERO)
174 }
175
176 fn current(&self) -> T {
177 self.elements
178 .iter()
179 .map(|e| e.read().current())
180 .fold(T::ZERO, |a, b| a + b)
181 }
182
183 fn reset(&mut self) {
184 for element in &self.elements {
185 element.write().reset();
186 }
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193 use crate::elements::{Capacitor, Resistor};
194
195 #[test]
196 fn test_series_adapter() {
197 let sample_rate = 44100.0;
198
199 let resistor: Arc<RwLock<dyn WdfElement<f64>>> =
200 Arc::new(RwLock::new(Resistor::new(1000.0)));
201 let capacitor: Arc<RwLock<dyn WdfElement<f64>>> =
202 Arc::new(RwLock::new(Capacitor::new(1e-6, sample_rate)));
203
204 let elements = vec![resistor.clone(), capacitor.clone()];
205 let adapter: SeriesAdapter<f64> = SeriesAdapter::new(elements);
206
207 let total_r = adapter.port_resistance();
208 let r1 = resistor.read().port_resistance();
209 let r2 = capacitor.read().port_resistance();
210
211 assert!((total_r - (r1 + r2)).abs() < 1e-10);
212 }
213}