1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::{
macros::{generate_propagation_matrix, set_from_complex_drive},
Backend, Complex, Transpose, VectorXc,
};
use anyhow::Result;
use autd3_core::{
gain::Gain,
geometry::{Geometry, Vector3},
hardware_defined::{DataArray, NUM_TRANS_IN_UNIT},
};
use autd3_traits::Gain;
use nalgebra::ComplexField;
use std::marker::PhantomData;
#[derive(Gain)]
pub struct Gs<B: Backend> {
data: Vec<DataArray>,
built: bool,
foci: Vec<Vector3>,
amps: Vec<f64>,
repeat: usize,
backend: PhantomData<B>,
}
impl<B: Backend> Gs<B> {
pub fn new(foci: Vec<Vector3>, amps: Vec<f64>) -> Self {
Self::with_param(foci, amps, 100)
}
pub fn with_param(foci: Vec<Vector3>, amps: Vec<f64>, repeat: usize) -> Self {
assert!(foci.len() == amps.len());
Self {
data: vec![],
built: false,
foci,
amps,
repeat,
backend: PhantomData,
}
}
#[allow(clippy::many_single_char_names)]
#[allow(clippy::unnecessary_wraps)]
fn calc(&mut self, geometry: &Geometry) -> Result<()> {
let m = self.foci.len();
let n = geometry.num_devices() * NUM_TRANS_IN_UNIT;
let g = generate_propagation_matrix(geometry, &self.foci);
let q0 = VectorXc::from_element(n, Complex::new(1., 0.));
let mut q = q0.clone();
let mut gamma = VectorXc::zeros(m);
let mut p = VectorXc::zeros(m);
let mut xi = VectorXc::zeros(n);
for _ in 0..self.repeat {
B::matrix_mul_vec(
Transpose::NoTrans,
Complex::new(1., 0.),
&g,
&q,
Complex::new(0., 0.),
&mut gamma,
);
for i in 0..m {
p[i] = gamma[i] / gamma[i].abs() * self.amps[i];
}
B::matrix_mul_vec(
Transpose::ConjTrans,
Complex::new(1., 0.),
&g,
&p,
Complex::new(0., 0.),
&mut xi,
);
for i in 0..n {
q[i] = xi[i] / xi[i].abs() * q0[i];
}
}
set_from_complex_drive(&mut self.data, &q, true, 1.0);
self.built = true;
Ok(())
}
}