vectorwaves 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,193 @@
1
+ import numpy as np
2
+ import time
3
+ from dataclasses import dataclass
4
+
5
+ def _kernel_grid_rect(x_vec, y_vec, z, t, kx, ky, kz, cx, cy, cz, w, inv_w,
6
+ need_b, need_derivs,
7
+ E_out, B_out, dx_out, dy_out, dz_out):
8
+ """
9
+ Vectorized grid kernel.
10
+ """
11
+ kx_v = kx[:, None, None]
12
+ ky_v = ky[:, None, None]
13
+ kz_v = kz[:, None, None]
14
+ w_v = w[:, None, None]
15
+
16
+ X = x_vec[None, None, :]
17
+ Y = y_vec[None, :, None]
18
+
19
+ phase = (kx_v * X) + (ky_v * Y) + (kz_v * z) - (w_v * t)
20
+ wf = np.exp(1j * phase)
21
+
22
+ E_out[0] += np.sum(cx[:, None, None] * wf, axis=0)
23
+ E_out[1] += np.sum(cy[:, None, None] * wf, axis=0)
24
+ E_out[2] += np.sum(cz[:, None, None] * wf, axis=0)
25
+
26
+ if need_b:
27
+ bx_c = ((ky * cz - kz * cy) * inv_w)[:, None, None]
28
+ by_c = ((kz * cx - kx * cz) * inv_w)[:, None, None]
29
+ bz_c = ((kx * cy - ky * cx) * inv_w)[:, None, None]
30
+
31
+ B_out[0] += np.sum(bx_c * wf, axis=0)
32
+ B_out[1] += np.sum(by_c * wf, axis=0)
33
+ B_out[2] += np.sum(bz_c * wf, axis=0)
34
+
35
+ if need_derivs:
36
+ ikx = (1j * kx)[:, None, None]
37
+ iky = (1j * ky)[:, None, None]
38
+ ikz = (1j * kz)[:, None, None]
39
+
40
+ cx_v = cx[:, None, None]
41
+ cy_v = cy[:, None, None]
42
+ cz_v = cz[:, None, None]
43
+
44
+ dx_out[0] += np.sum(ikx * cx_v * wf, axis=0)
45
+ dx_out[1] += np.sum(ikx * cy_v * wf, axis=0)
46
+ dx_out[2] += np.sum(ikx * cz_v * wf, axis=0)
47
+
48
+ dy_out[0] += np.sum(iky * cx_v * wf, axis=0)
49
+ dy_out[1] += np.sum(iky * cy_v * wf, axis=0)
50
+ dy_out[2] += np.sum(iky * cz_v * wf, axis=0)
51
+
52
+ dz_out[0] += np.sum(ikz * cx_v * wf, axis=0)
53
+ dz_out[1] += np.sum(ikz * cy_v * wf, axis=0)
54
+ dz_out[2] += np.sum(ikz * cz_v * wf, axis=0)
55
+
56
+ def _kernel_cloud_flat(x_arr, y_arr, z_arr, t, kx, ky, kz, cx, cy, cz, w, inv_w,
57
+ need_b, need_derivs,
58
+ E_out, B_out, dx_out, dy_out, dz_out):
59
+ """
60
+ Vectorized cloud kernel.
61
+ """
62
+ kx_v = kx[:, None]; ky_v = ky[:, None]; kz_v = kz[:, None]; w_v = w[:, None]
63
+
64
+ x = x_arr[None, :]
65
+ y = y_arr[None, :]
66
+ z = z_arr[None, :]
67
+
68
+ phase = (kx_v * x) + (ky_v * y) + (kz_v * z) - (w_v * t)
69
+ wf = np.exp(1j * phase)
70
+
71
+ E_out[0] = np.sum(cx[:, None] * wf, axis=0)
72
+ E_out[1] = np.sum(cy[:, None] * wf, axis=0)
73
+ E_out[2] = np.sum(cz[:, None] * wf, axis=0)
74
+
75
+ if need_b:
76
+ bx_c = ((ky * cz - kz * cy) * inv_w)[:, None]
77
+ by_c = ((kz * cx - kx * cz) * inv_w)[:, None]
78
+ bz_c = ((kx * cy - ky * cx) * inv_w)[:, None]
79
+
80
+ B_out[0] = np.sum(bx_c * wf, axis=0)
81
+ B_out[1] = np.sum(by_c * wf, axis=0)
82
+ B_out[2] = np.sum(bz_c * wf, axis=0)
83
+
84
+ if need_derivs:
85
+ ikx = (1j * kx)[:, None]
86
+ iky = (1j * ky)[:, None]
87
+ ikz = (1j * kz)[:, None]
88
+
89
+ cx_v = cx[:, None]; cy_v = cy[:, None]; cz_v = cz[:, None]
90
+
91
+ dx_out[0] = np.sum(ikx * cx_v * wf, axis=0)
92
+ dx_out[1] = np.sum(ikx * cy_v * wf, axis=0)
93
+ dx_out[2] = np.sum(ikx * cz_v * wf, axis=0)
94
+
95
+ dy_out[0] = np.sum(iky * cx_v * wf, axis=0)
96
+ dy_out[1] = np.sum(iky * cy_v * wf, axis=0)
97
+ dy_out[2] = np.sum(iky * cz_v * wf, axis=0)
98
+
99
+ dz_out[0] = np.sum(ikz * cx_v * wf, axis=0)
100
+ dz_out[1] = np.sum(ikz * cy_v * wf, axis=0)
101
+ dz_out[2] = np.sum(ikz * cz_v * wf, axis=0)
102
+
103
+ def _kernel_point(x, y, z, t, kx, ky, kz, cx, cy, cz, w, inv_w, need_b, need_derivs):
104
+ phase = (kx * x + ky * y + kz * z) - (w * t)
105
+ wf = np.exp(1j * phase)
106
+
107
+ ex = np.sum(cx * wf)
108
+ ey = np.sum(cy * wf)
109
+ ez = np.sum(cz * wf)
110
+
111
+ E = np.array([ex, ey, ez], dtype=np.complex128)
112
+
113
+ B = np.empty(3, dtype=np.complex128)
114
+ if need_b:
115
+ bx = np.sum(((ky * cz - kz * cy) * inv_w) * wf)
116
+ by = np.sum(((kz * cx - kx * cz) * inv_w) * wf)
117
+ bz = np.sum(((kx * cy - ky * cx) * inv_w) * wf)
118
+ B[:] = [bx, by, bz]
119
+
120
+ dx = np.empty(3, dtype=np.complex128)
121
+ dy = np.empty(3, dtype=np.complex128)
122
+ dz = np.empty(3, dtype=np.complex128)
123
+
124
+ if need_derivs:
125
+ ikx, iky, ikz = 1j*kx, 1j*ky, 1j*kz
126
+ dx[:] = [np.sum(ikx*cx*wf), np.sum(ikx*cy*wf), np.sum(ikx*cz*wf)]
127
+ dy[:] = [np.sum(iky*cx*wf), np.sum(iky*cy*wf), np.sum(iky*cz*wf)]
128
+ dz[:] = [np.sum(ikz*cx*wf), np.sum(ikz*cy*wf), np.sum(ikz*cz*wf)]
129
+
130
+ return E, (dx, dy, dz), B
131
+
132
+ class NumpyMethods:
133
+ def __init__(self, beam, max_points_per_batch=4096):
134
+ self.kx, self.ky, self.kz = beam.k
135
+ self.cx, self.cy, self.cz = beam.c
136
+ self.w, self.inv_w = beam.w, beam.inv_w
137
+ self.max_batch_size = max_points_per_batch
138
+
139
+ def _allocate_arrays(self, shape):
140
+ return tuple(np.zeros((3,*shape), dtype=np.complex128) for _ in range(5))
141
+
142
+ def compute_cloud(self, x, y, z, t, need_b=True, need_derivs=True, progress_callback=None):
143
+ total_points = len(x)
144
+ batch_size = self.max_batch_size
145
+ if progress_callback:
146
+ batch_size = min(self.max_batch_size, max(1, total_points // 5))
147
+
148
+ E, B, dx, dy, dz = self._allocate_arrays((total_points,))
149
+
150
+ for i in range(0, total_points, batch_size):
151
+ end = min(i + batch_size, total_points)
152
+ _kernel_cloud_flat(
153
+ x[i:end], y[i:end], z[i:end], t,
154
+ self.kx, self.ky, self.kz, self.cx, self.cy, self.cz, self.w, self.inv_w,
155
+ need_b, need_derivs,
156
+ E[:][:, i:end], B[:][:, i:end], dx[:][:, i:end], dy[:][:, i:end], dz[:][:, i:end]
157
+ )
158
+ if progress_callback: progress_callback(end-i)
159
+
160
+ D = (dx, dy, dz) if need_derivs else (None, None, None)
161
+ B = B if need_b else None
162
+
163
+ return E, D, B
164
+
165
+ def compute_grid(self, x_vec, y_vec, z, t, need_b=True, need_derivs=True, progress_callback=None):
166
+ nx, ny = len(x_vec), len(y_vec)
167
+ rows_per_batch = max(1, self.max_batch_size // nx)
168
+
169
+ E, B, dx, dy, dz = self._allocate_arrays((ny, nx))
170
+
171
+ for i in range(0, ny, rows_per_batch):
172
+ end = min(i + rows_per_batch, ny)
173
+ _kernel_grid_rect(
174
+ x_vec, y_vec[i:end], z, t,
175
+ self.kx, self.ky, self.kz, self.cx, self.cy, self.cz, self.w, self.inv_w,
176
+ need_b, need_derivs,
177
+ E[:][:, i:end, :], B[:][:, i:end, :], dx[:][:, i:end, :], dy[:][:, i:end, :], dz[:][:, i:end, :]
178
+ )
179
+ if progress_callback: progress_callback(end - i)
180
+
181
+ D = (dx, dy, dz) if need_derivs else (None, None, None)
182
+ B = B if need_b else None
183
+
184
+ return E, D, B
185
+
186
+ def compute_point(self, x, y, z, t, need_b=True, need_derivs=True):
187
+ E, D, B = _kernel_point(
188
+ x, y, z, t, self.kx, self.ky, self.kz, self.cx, self.cy, self.cz,
189
+ self.w, self.inv_w, need_b, need_derivs
190
+ )
191
+ if not need_derivs: D = (None, None, None)
192
+ if not need_b: B = None
193
+ return E, D, B