Skip to main content

aeon_tk/kernel/
weights.rs

1use crate::kernel::{Border, Interpolant, Kernel};
2use aeon_macros::{derivative, second_derivative};
3
4/// Unimplemented Kernel (used for debugging)
5#[derive(Clone)]
6pub struct Unimplemented(pub usize);
7
8impl Kernel for Unimplemented {
9    fn border_width(&self) -> usize {
10        unimplemented!("Kernel is unimplemented for order {}", self.0)
11    }
12
13    fn interior(&self) -> &[f64] {
14        unimplemented!("Kernel is unimplemented for order {}", self.0)
15    }
16
17    fn free(&self, _border: Border) -> &[f64] {
18        unimplemented!("Kernel is unimplemented for order {}", self.0)
19    }
20
21    fn scale(&self, _spacing: f64) -> f64 {
22        unimplemented!("Kernel is unimplemented for order {}", self.0)
23    }
24}
25
26impl Interpolant for Unimplemented {
27    fn border_width(&self) -> usize {
28        unimplemented!("Kernel is unimplemented for order {}", self.0)
29    }
30
31    fn interior(&self) -> &[f64] {
32        unimplemented!("Kernel is unimplemented for order {}", self.0)
33    }
34
35    fn free(&self, _border: Border) -> &[f64] {
36        unimplemented!("Kernel is unimplemented for order {}", self.0)
37    }
38
39    fn scale(&self) -> f64 {
40        unimplemented!("Kernel is unimplemented for order {}", self.0)
41    }
42}
43
44/// Value operation.
45#[derive(Clone)]
46pub struct Value;
47
48impl Kernel for Value {
49    fn border_width(&self) -> usize {
50        0
51    }
52
53    fn interior(&self) -> &[f64] {
54        &[1.0]
55    }
56
57    fn free(&self, _border: Border) -> &[f64] {
58        &[1.0]
59    }
60
61    fn scale(&self, _spacing: f64) -> f64 {
62        1.0
63    }
64}
65
66/// Derivative operation of a given order.
67#[derive(Clone)]
68pub struct Derivative<const ORDER: usize>;
69
70impl<const ORDER: usize> Kernel for Derivative<ORDER> {
71    fn border_width(&self) -> usize {
72        ORDER / 2
73    }
74
75    fn interior(&self) -> &[f64] {
76        match ORDER {
77            2 => &derivative!(1, 1, 0),
78            4 => &derivative!(2, 2, 0),
79            6 => &derivative!(3, 3, 0),
80            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
81        }
82    }
83
84    fn free(&self, border: Border) -> &[f64] {
85        match ORDER {
86            2 => match border {
87                Border::Negative(_) => &derivative!(0, 2, 0),
88                Border::Positive(_) => &derivative!(2, 0, 0),
89            },
90            4 => match border {
91                Border::Negative(0) => &derivative!(0, 4, 0),
92                Border::Negative(_) => &derivative!(0, 4, 1),
93                Border::Positive(0) => &derivative!(4, 0, 0),
94                Border::Positive(_) => &derivative!(4, 0, -1),
95            },
96            6 => match border {
97                Border::Negative(0) => &derivative!(0, 6, 0),
98                Border::Negative(1) => &derivative!(0, 6, 1),
99                Border::Negative(_) => &derivative!(0, 6, 2),
100                Border::Positive(0) => &derivative!(6, 0, 0),
101                Border::Positive(1) => &derivative!(6, 0, -1),
102                Border::Positive(_) => &derivative!(6, 0, -2),
103            },
104            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
105        }
106    }
107
108    fn scale(&self, spacing: f64) -> f64 {
109        1.0 / spacing
110    }
111}
112
113/// Second derivative operator of a given order.
114#[derive(Clone)]
115pub struct SecondDerivative<const ORDER: usize>;
116
117impl<const ORDER: usize> Kernel for SecondDerivative<ORDER> {
118    fn border_width(&self) -> usize {
119        ORDER / 2
120    }
121
122    fn interior(&self) -> &[f64] {
123        match ORDER {
124            2 => &second_derivative!(1, 1, 0),
125            4 => &second_derivative!(2, 2, 0),
126            6 => &second_derivative!(3, 3, 0),
127            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
128        }
129    }
130
131    fn free(&self, border: Border) -> &[f64] {
132        match ORDER {
133            2 => match border {
134                Border::Negative(_) => &second_derivative!(0, 3, 0),
135                Border::Positive(_) => &second_derivative!(3, 0, 0),
136            },
137            4 => match border {
138                Border::Negative(0) => &second_derivative!(0, 5, 0),
139                Border::Negative(_) => &second_derivative!(0, 5, 1),
140                Border::Positive(0) => &second_derivative!(5, 0, 0),
141                Border::Positive(_) => &second_derivative!(5, 0, -1),
142            },
143            6 => match border {
144                Border::Negative(0) => &second_derivative!(0, 7, 0),
145                Border::Negative(1) => &second_derivative!(0, 7, 1),
146                Border::Negative(_) => &second_derivative!(0, 7, 2),
147                Border::Positive(0) => &second_derivative!(7, 0, 0),
148                Border::Positive(1) => &second_derivative!(7, 0, -1),
149                Border::Positive(_) => &second_derivative!(7, 0, -2),
150            },
151            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
152        }
153    }
154
155    fn scale(&self, spacing: f64) -> f64 {
156        1.0 / (spacing * spacing)
157    }
158}
159
160/// Kriss Olgier dissipation of the given order.
161#[derive(Clone)]
162pub struct Dissipation<const ORDER: usize>;
163
164impl<const ORDER: usize> Kernel for Dissipation<ORDER> {
165    fn border_width(&self) -> usize {
166        ORDER / 2
167    }
168
169    fn interior(&self) -> &[f64] {
170        match ORDER {
171            4 => &[1.0, -4.0, 6.0, -4.0, 1.0],
172            6 => &[1.0, -6.0, 15.0, -20.0, 15.0, -6.0, 1.0],
173            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
174        }
175    }
176
177    fn free(&self, border: Border) -> &[f64] {
178        match ORDER {
179            4 => match border {
180                Border::Negative(0) => &[3.0, -14.0, 26.0, -24.0, 11.0, -2.0],
181                Border::Negative(_) => &[2.0, -9.0, 16.0, -14.0, 6.0, -1.0],
182                Border::Positive(0) => &[-2.0, 11.0, -24.0, 26.0, -14.0, 3.0],
183                Border::Positive(_) => &[-1.0, 6.0, -14.0, 16.0, -9.0, 2.0],
184            },
185            6 => match border {
186                Border::Negative(0) => &[4.0, -27.0, 78.0, -125.0, 120.0, -69.0, 22.0, -3.0],
187                Border::Negative(1) => &[3.0, -20.0, 57.0, -90.0, 85.0, -48.0, 15.0, -2.0],
188                Border::Negative(_) => &[2.0, -13.0, 36.0, -55.0, 50.0, -27.0, 8.0, -1.0],
189                Border::Positive(0) => &[-3.0, 22.0, -69.0, 120.0, -125.0, 78.0, -27.0, 4.0],
190                Border::Positive(1) => &[-2.0, 15.0, -48.0, 85.0, -90.0, 57.0, -20.0, 3.0],
191                Border::Positive(_) => &[-1.0, 8.0, -27.0, 50.0, -55.0, 36.0, -13.0, 2.0],
192            },
193            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
194        }
195    }
196
197    fn scale(&self, _spacing: f64) -> f64 {
198        match ORDER {
199            4 => -1.0 / 16.0,
200            6 => 1.0 / 64.0,
201            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
202        }
203    }
204}
205
206#[derive(Clone)]
207pub struct Interpolation<const ORDER: usize>;
208
209impl<const ORDER: usize> Interpolant for Interpolation<ORDER> {
210    fn border_width(&self) -> usize {
211        ORDER / 2
212    }
213
214    fn interior(&self) -> &[f64] {
215        match ORDER {
216            2 => &[-1.0, 9.0, 9.0, -1.0],
217            4 => &[3.0, -25.0, 150.0, 150.0, -25.0, 3.0],
218            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
219        }
220    }
221
222    fn free(&self, border: Border) -> &[f64] {
223        match ORDER {
224            2 => match border {
225                Border::Positive(_) => &[1.0, -5.0, 15.0, 5.0],
226                Border::Negative(_) => &[5.0, 15.0, -5.0, 1.0],
227            },
228            4 => match border {
229                Border::Negative(0) => &[63.0, 315.0, -210.0, 126.0, -45.0, 7.0],
230                Border::Negative(_) => &[-7.0, 105.0, 210.0, -70.0, 21.0, -3.0],
231                Border::Positive(0) => &[7.0, -45.0, 126.0, -210.0, 315.0, 63.0],
232                Border::Positive(_) => &[-3.0, 21.0, -70.0, 210.0, 105.0, -7.0],
233            },
234            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
235        }
236    }
237
238    fn scale(&self) -> f64 {
239        match ORDER {
240            2 => 1.0 / 16.0,
241            4 => 1.0 / 256.0,
242            _ => unimplemented!("Kernel is unimplemented for order {}", ORDER),
243        }
244    }
245}