autd3_core/devices/
autd3.rs

1use crate::{
2    common::mm,
3    geometry::{Device, Isometry3, Point3, Transducer, Translation3, UnitQuaternion},
4};
5use std::fmt::Debug;
6
7/// AUTD3 device.
8#[derive(Clone, Copy, Debug)]
9pub struct AUTD3<R: Into<UnitQuaternion> + Debug> {
10    /// The global position of the AUTD3 device.
11    pub pos: Point3,
12    /// The rotation of the AUTD3 device.
13    pub rot: R,
14}
15
16impl Default for AUTD3<UnitQuaternion> {
17    fn default() -> Self {
18        Self {
19            pos: Point3::origin(),
20            rot: UnitQuaternion::identity(),
21        }
22    }
23}
24
25impl AUTD3<UnitQuaternion> {
26    /// The number of transducers in x-axis.
27    pub const NUM_TRANS_X: usize = 18;
28    /// The number of transducers in y-axis.
29    pub const NUM_TRANS_Y: usize = 14;
30    /// The number of transducers in a unit.
31    pub const NUM_TRANS_IN_UNIT: usize = Self::NUM_TRANS_X * Self::NUM_TRANS_Y - 3;
32    /// The spacing between transducers.
33    pub const TRANS_SPACING: f32 = 10.16 * mm;
34    /// The width of the device (including the substrate).
35    pub const DEVICE_WIDTH: f32 = 192.0 * mm;
36    /// The height of the device (including the substrate).
37    pub const DEVICE_HEIGHT: f32 = 151.4 * mm;
38
39    #[must_use]
40    const fn is_missing_transducer(x: usize, y: usize) -> bool {
41        if Self::NUM_TRANS_X <= x || Self::NUM_TRANS_Y <= y {
42            return true;
43        }
44        y == 1 && (x == 1 || x == 2 || x == 16)
45    }
46
47    /// Gets the index in x- and y-axis from the transducer index.
48    #[must_use]
49    pub const fn grid_id(idx: usize) -> (usize, usize) {
50        let local_id = idx % Self::NUM_TRANS_IN_UNIT;
51        let uid = match local_id {
52            0..19 => local_id,
53            19..32 => local_id + 2,
54            _ => local_id + 3,
55        };
56        (uid % Self::NUM_TRANS_X, uid / Self::NUM_TRANS_X)
57    }
58}
59
60impl<R: Into<UnitQuaternion> + Debug> AUTD3<R> {
61    /// Create a new AUTD3 device.
62    #[must_use]
63    pub fn new(pos: Point3, rot: R) -> Self {
64        Self { pos, rot }
65    }
66}
67
68impl<R: Into<UnitQuaternion> + Debug> From<AUTD3<R>> for Device {
69    fn from(autd3: AUTD3<R>) -> Self {
70        let rot = autd3.rot.into();
71        let isometry = Isometry3 {
72            rotation: rot,
73            translation: Translation3::from(autd3.pos),
74        };
75        Self::new(
76            rot,
77            (0..AUTD3::NUM_TRANS_Y)
78                .flat_map(|y| {
79                    (0..AUTD3::NUM_TRANS_X)
80                        .filter(move |&x| !AUTD3::is_missing_transducer(x, y))
81                        .map(move |x| {
82                            isometry
83                                * Point3::new(
84                                    x as f32 * AUTD3::TRANS_SPACING,
85                                    y as f32 * AUTD3::TRANS_SPACING,
86                                    0.,
87                                )
88                        })
89                })
90                .map(Transducer::new)
91                .collect(),
92        )
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use crate::geometry::Vector3;
99
100    use super::*;
101
102    #[test]
103    fn num_devices() {
104        let dev: Device = AUTD3::default().into();
105        assert_eq!(AUTD3::NUM_TRANS_IN_UNIT, dev.num_transducers());
106    }
107
108    #[rstest::rstest]
109    #[case(
110        Point3::new(0., 0., 0.),
111        0,
112        Point3::origin(),
113        UnitQuaternion::identity()
114    )]
115    #[case(
116        Point3::new(AUTD3::TRANS_SPACING, 0., 0.),
117        1,
118        Point3::origin(),
119        UnitQuaternion::identity()
120    )]
121    #[case(
122        Point3::new(0., AUTD3::TRANS_SPACING, 0.),
123        18,
124        Point3::origin(),
125        UnitQuaternion::identity()
126    )]
127    #[case(Point3::new(17. * AUTD3::TRANS_SPACING, 13. * AUTD3::TRANS_SPACING, 0.), 248, Point3::origin(), UnitQuaternion::identity())]
128    #[case(
129        Point3::new(1., 2., 3.),
130        0,
131        Point3::new(1., 2., 3.),
132        UnitQuaternion::identity()
133    )]
134    #[case(
135        Point3::new(AUTD3::TRANS_SPACING + 1., 2., 3.),
136        1,
137        Point3::new(1., 2., 3.),
138        UnitQuaternion::identity()
139    )]
140    #[case(
141        Point3::new(1., AUTD3::TRANS_SPACING + 2., 3.),
142        18,
143        Point3::new(1., 2., 3.),
144        UnitQuaternion::identity()
145    )]
146    #[case(Point3::new(17. * AUTD3::TRANS_SPACING + 1., 13. * AUTD3::TRANS_SPACING + 2., 3.), 248, Point3::new(1., 2., 3.), UnitQuaternion::identity())]
147    #[case(
148        Point3::new(0., 0., 0.),
149        0,
150        Point3::origin(),
151        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
152    )]
153    #[case(
154        Point3::new(0., 0., -AUTD3::TRANS_SPACING),
155        1,
156        Point3::origin(),
157        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
158    )]
159    #[case(
160        Point3::new(0., AUTD3::TRANS_SPACING, 0.),
161        18,
162        Point3::origin(),
163        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
164    )]
165    #[case(Point3::new(0., 13. * AUTD3::TRANS_SPACING, -17. * AUTD3::TRANS_SPACING), 248, Point3::origin(), UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2))]
166    #[case(
167        Point3::new(1., 2., 3.),
168        0,
169        Point3::new(1., 2., 3.),
170        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
171    )]
172    #[case(
173        Point3::new(1., 2., 3. - AUTD3::TRANS_SPACING),
174        1,
175        Point3::new(1., 2., 3.),
176        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
177    )]
178    #[case(
179        Point3::new(1., 2. + AUTD3::TRANS_SPACING, 3.),
180        18,
181        Point3::new(1., 2., 3.),
182        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
183    )]
184    #[case(Point3::new(1., 2. + 13. * AUTD3::TRANS_SPACING, 3. - 17. * AUTD3::TRANS_SPACING), 248, Point3::new(1., 2., 3.), UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2))]
185    fn position(
186        #[case] expected: Point3,
187        #[case] idx: usize,
188        #[case] pos: Point3,
189        #[case] rot: impl Into<UnitQuaternion> + Debug,
190    ) {
191        let dev: Device = AUTD3 { pos, rot }.into();
192        approx::assert_relative_eq!(expected.x, dev[idx].position().x, epsilon = 1e-6);
193        approx::assert_relative_eq!(expected.y, dev[idx].position().y, epsilon = 1e-6);
194        approx::assert_relative_eq!(expected.z, dev[idx].position().z, epsilon = 1e-6);
195    }
196
197    #[rstest::rstest]
198    #[case(0, 0, false)]
199    #[case(1, 0, false)]
200    #[case(2, 0, false)]
201    #[case(3, 0, false)]
202    #[case(4, 0, false)]
203    #[case(5, 0, false)]
204    #[case(6, 0, false)]
205    #[case(7, 0, false)]
206    #[case(8, 0, false)]
207    #[case(9, 0, false)]
208    #[case(10, 0, false)]
209    #[case(11, 0, false)]
210    #[case(12, 0, false)]
211    #[case(13, 0, false)]
212    #[case(14, 0, false)]
213    #[case(15, 0, false)]
214    #[case(16, 0, false)]
215    #[case(17, 0, false)]
216    #[case(0, 1, false)]
217    #[case(1, 1, true)]
218    #[case(2, 1, true)]
219    #[case(3, 1, false)]
220    #[case(4, 1, false)]
221    #[case(5, 1, false)]
222    #[case(6, 1, false)]
223    #[case(7, 1, false)]
224    #[case(8, 1, false)]
225    #[case(9, 1, false)]
226    #[case(10, 1, false)]
227    #[case(11, 1, false)]
228    #[case(12, 1, false)]
229    #[case(13, 1, false)]
230    #[case(14, 1, false)]
231    #[case(15, 1, false)]
232    #[case(16, 1, true)]
233    #[case(17, 1, false)]
234    #[case(0, 2, false)]
235    #[case(1, 2, false)]
236    #[case(2, 2, false)]
237    #[case(3, 2, false)]
238    #[case(4, 2, false)]
239    #[case(5, 2, false)]
240    #[case(6, 2, false)]
241    #[case(7, 2, false)]
242    #[case(8, 2, false)]
243    #[case(9, 2, false)]
244    #[case(10, 2, false)]
245    #[case(11, 2, false)]
246    #[case(12, 2, false)]
247    #[case(13, 2, false)]
248    #[case(14, 2, false)]
249    #[case(15, 2, false)]
250    #[case(16, 2, false)]
251    #[case(17, 2, false)]
252    #[case(0, 3, false)]
253    #[case(1, 3, false)]
254    #[case(2, 3, false)]
255    #[case(3, 3, false)]
256    #[case(4, 3, false)]
257    #[case(5, 3, false)]
258    #[case(6, 3, false)]
259    #[case(7, 3, false)]
260    #[case(8, 3, false)]
261    #[case(9, 3, false)]
262    #[case(10, 3, false)]
263    #[case(11, 3, false)]
264    #[case(12, 3, false)]
265    #[case(13, 3, false)]
266    #[case(14, 3, false)]
267    #[case(15, 3, false)]
268    #[case(16, 3, false)]
269    #[case(17, 3, false)]
270    #[case(0, 4, false)]
271    #[case(1, 4, false)]
272    #[case(2, 4, false)]
273    #[case(3, 4, false)]
274    #[case(4, 4, false)]
275    #[case(5, 4, false)]
276    #[case(6, 4, false)]
277    #[case(7, 4, false)]
278    #[case(8, 4, false)]
279    #[case(9, 4, false)]
280    #[case(10, 4, false)]
281    #[case(11, 4, false)]
282    #[case(12, 4, false)]
283    #[case(13, 4, false)]
284    #[case(14, 4, false)]
285    #[case(15, 4, false)]
286    #[case(16, 4, false)]
287    #[case(17, 4, false)]
288    #[case(0, 5, false)]
289    #[case(1, 5, false)]
290    #[case(2, 5, false)]
291    #[case(3, 5, false)]
292    #[case(4, 5, false)]
293    #[case(5, 5, false)]
294    #[case(6, 5, false)]
295    #[case(7, 5, false)]
296    #[case(8, 5, false)]
297    #[case(9, 5, false)]
298    #[case(10, 5, false)]
299    #[case(11, 5, false)]
300    #[case(12, 5, false)]
301    #[case(13, 5, false)]
302    #[case(14, 5, false)]
303    #[case(15, 5, false)]
304    #[case(16, 5, false)]
305    #[case(17, 5, false)]
306    #[case(0, 6, false)]
307    #[case(1, 6, false)]
308    #[case(2, 6, false)]
309    #[case(3, 6, false)]
310    #[case(4, 6, false)]
311    #[case(5, 6, false)]
312    #[case(6, 6, false)]
313    #[case(7, 6, false)]
314    #[case(8, 6, false)]
315    #[case(9, 6, false)]
316    #[case(10, 6, false)]
317    #[case(11, 6, false)]
318    #[case(12, 6, false)]
319    #[case(13, 6, false)]
320    #[case(14, 6, false)]
321    #[case(15, 6, false)]
322    #[case(16, 6, false)]
323    #[case(17, 6, false)]
324    #[case(0, 7, false)]
325    #[case(1, 7, false)]
326    #[case(2, 7, false)]
327    #[case(3, 7, false)]
328    #[case(4, 7, false)]
329    #[case(5, 7, false)]
330    #[case(6, 7, false)]
331    #[case(7, 7, false)]
332    #[case(8, 7, false)]
333    #[case(9, 7, false)]
334    #[case(10, 7, false)]
335    #[case(11, 7, false)]
336    #[case(12, 7, false)]
337    #[case(13, 7, false)]
338    #[case(14, 7, false)]
339    #[case(15, 7, false)]
340    #[case(16, 7, false)]
341    #[case(17, 7, false)]
342    #[case(0, 8, false)]
343    #[case(1, 8, false)]
344    #[case(2, 8, false)]
345    #[case(3, 8, false)]
346    #[case(4, 8, false)]
347    #[case(5, 8, false)]
348    #[case(6, 8, false)]
349    #[case(7, 8, false)]
350    #[case(8, 8, false)]
351    #[case(9, 8, false)]
352    #[case(10, 8, false)]
353    #[case(11, 8, false)]
354    #[case(12, 8, false)]
355    #[case(13, 8, false)]
356    #[case(14, 8, false)]
357    #[case(15, 8, false)]
358    #[case(16, 8, false)]
359    #[case(17, 8, false)]
360    #[case(0, 9, false)]
361    #[case(1, 9, false)]
362    #[case(2, 9, false)]
363    #[case(3, 9, false)]
364    #[case(4, 9, false)]
365    #[case(5, 9, false)]
366    #[case(6, 9, false)]
367    #[case(7, 9, false)]
368    #[case(8, 9, false)]
369    #[case(9, 9, false)]
370    #[case(10, 9, false)]
371    #[case(11, 9, false)]
372    #[case(12, 9, false)]
373    #[case(13, 9, false)]
374    #[case(14, 9, false)]
375    #[case(15, 9, false)]
376    #[case(16, 9, false)]
377    #[case(17, 9, false)]
378    #[case(0, 10, false)]
379    #[case(1, 10, false)]
380    #[case(2, 10, false)]
381    #[case(3, 10, false)]
382    #[case(4, 10, false)]
383    #[case(5, 10, false)]
384    #[case(6, 10, false)]
385    #[case(7, 10, false)]
386    #[case(8, 10, false)]
387    #[case(9, 10, false)]
388    #[case(10, 10, false)]
389    #[case(11, 10, false)]
390    #[case(12, 10, false)]
391    #[case(13, 10, false)]
392    #[case(14, 10, false)]
393    #[case(15, 10, false)]
394    #[case(16, 10, false)]
395    #[case(17, 10, false)]
396    #[case(0, 11, false)]
397    #[case(1, 11, false)]
398    #[case(2, 11, false)]
399    #[case(3, 11, false)]
400    #[case(4, 11, false)]
401    #[case(5, 11, false)]
402    #[case(6, 11, false)]
403    #[case(7, 11, false)]
404    #[case(8, 11, false)]
405    #[case(9, 11, false)]
406    #[case(10, 11, false)]
407    #[case(11, 11, false)]
408    #[case(12, 11, false)]
409    #[case(13, 11, false)]
410    #[case(14, 11, false)]
411    #[case(15, 11, false)]
412    #[case(16, 11, false)]
413    #[case(17, 11, false)]
414    #[case(0, 12, false)]
415    #[case(1, 12, false)]
416    #[case(2, 12, false)]
417    #[case(3, 12, false)]
418    #[case(4, 12, false)]
419    #[case(5, 12, false)]
420    #[case(6, 12, false)]
421    #[case(7, 12, false)]
422    #[case(8, 12, false)]
423    #[case(9, 12, false)]
424    #[case(10, 12, false)]
425    #[case(11, 12, false)]
426    #[case(12, 12, false)]
427    #[case(13, 12, false)]
428    #[case(14, 12, false)]
429    #[case(15, 12, false)]
430    #[case(16, 12, false)]
431    #[case(17, 12, false)]
432    #[case(0, 13, false)]
433    #[case(1, 13, false)]
434    #[case(2, 13, false)]
435    #[case(3, 13, false)]
436    #[case(4, 13, false)]
437    #[case(5, 13, false)]
438    #[case(6, 13, false)]
439    #[case(7, 13, false)]
440    #[case(8, 13, false)]
441    #[case(9, 13, false)]
442    #[case(10, 13, false)]
443    #[case(11, 13, false)]
444    #[case(12, 13, false)]
445    #[case(13, 13, false)]
446    #[case(14, 13, false)]
447    #[case(15, 13, false)]
448    #[case(16, 13, false)]
449    #[case(17, 13, false)]
450    fn test_is_missing_transducer(#[case] x: usize, #[case] y: usize, #[case] expected: bool) {
451        assert_eq!(expected, AUTD3::is_missing_transducer(x, y));
452    }
453
454    #[test]
455    fn test_is_missing_transducer_out_of_range() {
456        (18..=256).for_each(|x| {
457            (0..=256).for_each(|y| {
458                assert!(AUTD3::is_missing_transducer(x, y));
459            });
460        });
461        (0..=256).for_each(|x| {
462            (14..=256).for_each(|y| {
463                assert!(AUTD3::is_missing_transducer(x, y));
464            });
465        });
466    }
467
468    #[rstest::rstest]
469    #[case(0, (0, 0))]
470    #[case(1, (1, 0))]
471    #[case(2, (2, 0))]
472    #[case(3, (3, 0))]
473    #[case(4, (4, 0))]
474    #[case(5, (5, 0))]
475    #[case(6, (6, 0))]
476    #[case(7, (7, 0))]
477    #[case(8, (8, 0))]
478    #[case(9, (9, 0))]
479    #[case(10, (10, 0))]
480    #[case(11, (11, 0))]
481    #[case(12, (12, 0))]
482    #[case(13, (13, 0))]
483    #[case(14, (14, 0))]
484    #[case(15, (15, 0))]
485    #[case(16, (16, 0))]
486    #[case(17, (17, 0))]
487    #[case(18, (0, 1))]
488    #[case(19, (3, 1))]
489    #[case(20, (4, 1))]
490    #[case(21, (5, 1))]
491    #[case(22, (6, 1))]
492    #[case(23, (7, 1))]
493    #[case(24, (8, 1))]
494    #[case(25, (9, 1))]
495    #[case(26, (10, 1))]
496    #[case(27, (11, 1))]
497    #[case(28, (12, 1))]
498    #[case(29, (13, 1))]
499    #[case(30, (14, 1))]
500    #[case(31, (15, 1))]
501    #[case(32, (17, 1))]
502    #[case(33, (0, 2))]
503    #[case(34, (1, 2))]
504    #[case(35, (2, 2))]
505    #[case(36, (3, 2))]
506    #[case(37, (4, 2))]
507    #[case(38, (5, 2))]
508    #[case(39, (6, 2))]
509    #[case(40, (7, 2))]
510    #[case(41, (8, 2))]
511    #[case(42, (9, 2))]
512    #[case(43, (10, 2))]
513    #[case(44, (11, 2))]
514    #[case(45, (12, 2))]
515    #[case(46, (13, 2))]
516    #[case(47, (14, 2))]
517    #[case(48, (15, 2))]
518    #[case(49, (16, 2))]
519    #[case(50, (17, 2))]
520    #[case(51, (0, 3))]
521    #[case(52, (1, 3))]
522    #[case(53, (2, 3))]
523    #[case(54, (3, 3))]
524    #[case(55, (4, 3))]
525    #[case(56, (5, 3))]
526    #[case(57, (6, 3))]
527    #[case(58, (7, 3))]
528    #[case(59, (8, 3))]
529    #[case(60, (9, 3))]
530    #[case(61, (10, 3))]
531    #[case(62, (11, 3))]
532    #[case(63, (12, 3))]
533    #[case(64, (13, 3))]
534    #[case(65, (14, 3))]
535    #[case(66, (15, 3))]
536    #[case(67, (16, 3))]
537    #[case(68, (17, 3))]
538    #[case(69, (0, 4))]
539    #[case(70, (1, 4))]
540    #[case(71, (2, 4))]
541    #[case(72, (3, 4))]
542    #[case(73, (4, 4))]
543    #[case(74, (5, 4))]
544    #[case(75, (6, 4))]
545    #[case(76, (7, 4))]
546    #[case(77, (8, 4))]
547    #[case(78, (9, 4))]
548    #[case(79, (10, 4))]
549    #[case(80, (11, 4))]
550    #[case(81, (12, 4))]
551    #[case(82, (13, 4))]
552    #[case(83, (14, 4))]
553    #[case(84, (15, 4))]
554    #[case(85, (16, 4))]
555    #[case(86, (17, 4))]
556    #[case(87, (0, 5))]
557    #[case(88, (1, 5))]
558    #[case(89, (2, 5))]
559    #[case(90, (3, 5))]
560    #[case(91, (4, 5))]
561    #[case(92, (5, 5))]
562    #[case(93, (6, 5))]
563    #[case(94, (7, 5))]
564    #[case(95, (8, 5))]
565    #[case(96, (9, 5))]
566    #[case(97, (10, 5))]
567    #[case(98, (11, 5))]
568    #[case(99, (12, 5))]
569    #[case(100, (13, 5))]
570    #[case(101, (14, 5))]
571    #[case(102, (15, 5))]
572    #[case(103, (16, 5))]
573    #[case(104, (17, 5))]
574    #[case(105, (0, 6))]
575    #[case(106, (1, 6))]
576    #[case(107, (2, 6))]
577    #[case(108, (3, 6))]
578    #[case(109, (4, 6))]
579    #[case(110, (5, 6))]
580    #[case(111, (6, 6))]
581    #[case(112, (7, 6))]
582    #[case(113, (8, 6))]
583    #[case(114, (9, 6))]
584    #[case(115, (10, 6))]
585    #[case(116, (11, 6))]
586    #[case(117, (12, 6))]
587    #[case(118, (13, 6))]
588    #[case(119, (14, 6))]
589    #[case(120, (15, 6))]
590    #[case(121, (16, 6))]
591    #[case(122, (17, 6))]
592    #[case(123, (0, 7))]
593    #[case(124, (1, 7))]
594    #[case(125, (2, 7))]
595    #[case(126, (3, 7))]
596    #[case(127, (4, 7))]
597    #[case(128, (5, 7))]
598    #[case(129, (6, 7))]
599    #[case(130, (7, 7))]
600    #[case(131, (8, 7))]
601    #[case(132, (9, 7))]
602    #[case(133, (10, 7))]
603    #[case(134, (11, 7))]
604    #[case(135, (12, 7))]
605    #[case(136, (13, 7))]
606    #[case(137, (14, 7))]
607    #[case(138, (15, 7))]
608    #[case(139, (16, 7))]
609    #[case(140, (17, 7))]
610    #[case(141, (0, 8))]
611    #[case(142, (1, 8))]
612    #[case(143, (2, 8))]
613    #[case(144, (3, 8))]
614    #[case(145, (4, 8))]
615    #[case(146, (5, 8))]
616    #[case(147, (6, 8))]
617    #[case(148, (7, 8))]
618    #[case(149, (8, 8))]
619    #[case(150, (9, 8))]
620    #[case(151, (10, 8))]
621    #[case(152, (11, 8))]
622    #[case(153, (12, 8))]
623    #[case(154, (13, 8))]
624    #[case(155, (14, 8))]
625    #[case(156, (15, 8))]
626    #[case(157, (16, 8))]
627    #[case(158, (17, 8))]
628    #[case(159, (0, 9))]
629    #[case(160, (1, 9))]
630    #[case(161, (2, 9))]
631    #[case(162, (3, 9))]
632    #[case(163, (4, 9))]
633    #[case(164, (5, 9))]
634    #[case(165, (6, 9))]
635    #[case(166, (7, 9))]
636    #[case(167, (8, 9))]
637    #[case(168, (9, 9))]
638    #[case(169, (10, 9))]
639    #[case(170, (11, 9))]
640    #[case(171, (12, 9))]
641    #[case(172, (13, 9))]
642    #[case(173, (14, 9))]
643    #[case(174, (15, 9))]
644    #[case(175, (16, 9))]
645    #[case(176, (17, 9))]
646    #[case(177, (0, 10))]
647    #[case(178, (1, 10))]
648    #[case(179, (2, 10))]
649    #[case(180, (3, 10))]
650    #[case(181, (4, 10))]
651    #[case(182, (5, 10))]
652    #[case(183, (6, 10))]
653    #[case(184, (7, 10))]
654    #[case(185, (8, 10))]
655    #[case(186, (9, 10))]
656    #[case(187, (10, 10))]
657    #[case(188, (11, 10))]
658    #[case(189, (12, 10))]
659    #[case(190, (13, 10))]
660    #[case(191, (14, 10))]
661    #[case(192, (15, 10))]
662    #[case(193, (16, 10))]
663    #[case(194, (17, 10))]
664    #[case(195, (0, 11))]
665    #[case(196, (1, 11))]
666    #[case(197, (2, 11))]
667    #[case(198, (3, 11))]
668    #[case(199, (4, 11))]
669    #[case(200, (5, 11))]
670    #[case(201, (6, 11))]
671    #[case(202, (7, 11))]
672    #[case(203, (8, 11))]
673    #[case(204, (9, 11))]
674    #[case(205, (10, 11))]
675    #[case(206, (11, 11))]
676    #[case(207, (12, 11))]
677    #[case(208, (13, 11))]
678    #[case(209, (14, 11))]
679    #[case(210, (15, 11))]
680    #[case(211, (16, 11))]
681    #[case(212, (17, 11))]
682    #[case(213, (0, 12))]
683    #[case(214, (1, 12))]
684    #[case(215, (2, 12))]
685    #[case(216, (3, 12))]
686    #[case(217, (4, 12))]
687    #[case(218, (5, 12))]
688    #[case(219, (6, 12))]
689    #[case(220, (7, 12))]
690    #[case(221, (8, 12))]
691    #[case(222, (9, 12))]
692    #[case(223, (10, 12))]
693    #[case(224, (11, 12))]
694    #[case(225, (12, 12))]
695    #[case(226, (13, 12))]
696    #[case(227, (14, 12))]
697    #[case(228, (15, 12))]
698    #[case(229, (16, 12))]
699    #[case(230, (17, 12))]
700    #[case(231, (0, 13))]
701    #[case(232, (1, 13))]
702    #[case(233, (2, 13))]
703    #[case(234, (3, 13))]
704    #[case(235, (4, 13))]
705    #[case(236, (5, 13))]
706    #[case(237, (6, 13))]
707    #[case(238, (7, 13))]
708    #[case(239, (8, 13))]
709    #[case(240, (9, 13))]
710    #[case(241, (10, 13))]
711    #[case(242, (11, 13))]
712    #[case(243, (12, 13))]
713    #[case(244, (13, 13))]
714    #[case(245, (14, 13))]
715    #[case(246, (15, 13))]
716    #[case(247, (16, 13))]
717    #[case(248, (17, 13))]
718    fn test_grid_id(#[case] idx: usize, #[case] expected: (usize, usize)) {
719        assert_eq!(expected, AUTD3::grid_id(idx));
720    }
721}