88Note that mode-matching (such as NFC-HOA, SDM) are equivalent
99to ESA in their specific geometries (spherical/circular, planar/linear).
1010
11+ .. plot::
12+ :context: reset
13+
14+ import matplotlib.pyplot as plt
15+ import numpy as np
16+ import sfs
17+
18+ plt.rcParams['figure.figsize'] = 6, 6
19+
20+ f = 343 # Hz
21+ omega = 2 * np.pi * f # rad / s
22+ k = omega / sfs.default.c # rad / m
23+
24+ npw = sfs.util.direction_vector(np.radians(-45))
25+ xs = np.array([-0.828427, 0.828427, 0])
26+
27+ grid = sfs.util.xyz_grid([-1, 5], [-5, 1], 0, spacing=0.02)
28+ dx, L = 0.05, 4 # m
29+ N = int(L / dx)
30+ array = sfs.array.edge(N, dx, center=[0, 0, 0],
31+ orientation=[0, -1, 0])
32+
33+ xref = np.array([2, -2, 0])
34+ x_norm = np.linalg.norm(xs - xref)
35+ norm_ls = (np.sqrt(8 * np.pi * k * x_norm) *
36+ np.exp(+1j * np.pi / 4) *
37+ np.exp(-1j * k * x_norm))
38+ norm_pw = np.exp(+1j * 4*np.pi*np.sqrt(2))
39+
40+
41+ def plot(d, selection, secondary_source, norm_ref):
42+ # the series expansion is numerically tricky, hence
43+ d = np.nan_to_num(d)
44+ # especially handle the origin loudspeaker
45+ d[N] = 0 # as it tends to nan/inf
46+ p = sfs.fd.synthesize(d, selection, array, secondary_source, grid=grid)
47+ sfs.plot2d.amplitude(p * norm_ref, grid)
48+ sfs.plot2d.loudspeakers(array.x, array.n,
49+ selection * array.a, size=0.15)
50+ plt.xlim(-0.5, 4.5)
51+ plt.ylim(-4.5, 0.5)
52+ plt.grid(True)
53+
1154"""
1255import numpy as _np
1356from scipy .special import jn as _jn , hankel2 as _hankel2
@@ -59,6 +102,15 @@ def plane_2d_edge(omega, x0, n=[0, 1, 0], *, alpha=_np.pi*3/2, Nc=None,
59102
60103 Derived from :cite:`Spors2016`
61104
105+ Examples
106+ --------
107+ .. plot::
108+ :context: close-figs
109+
110+ d, selection, secondary_source = sfs.fd.esa.plane_2d_edge(
111+ omega, array.x, npw, alpha=np.pi*3/2)
112+ plot(d, selection, secondary_source, norm_pw)
113+
62114 """
63115 x0 = _np .asarray (x0 )
64116 n = _util .normalize_vector (n )
@@ -71,7 +123,7 @@ def plane_2d_edge(omega, x0, n=[0, 1, 0], *, alpha=_np.pi*3/2, Nc=None,
71123 phi = _np .where (phi < 0 , phi + 2 * _np .pi , phi )
72124
73125 if Nc is None :
74- Nc = _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi )
126+ Nc = int ( _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi ) )
75127
76128 epsilon = _np .ones (Nc ) # weights for series expansion
77129 epsilon [0 ] = 2
@@ -130,6 +182,15 @@ def plane_2d_edge_dipole_ssd(omega, x0, n=[0, 1, 0], *, alpha=_np.pi*3/2,
130182
131183 Derived from :cite:`Spors2016`
132184
185+ Examples
186+ --------
187+ .. plot::
188+ :context: close-figs
189+
190+ d, selection, secondary_source = sfs.fd.esa.plane_2d_edge_dipole_ssd(
191+ omega, array.x, npw, alpha=np.pi*3/2)
192+ plot(d, selection, secondary_source, norm_ref=1)
193+
133194 """
134195 x0 = _np .asarray (x0 )
135196 n = _util .normalize_vector (n )
@@ -142,7 +203,7 @@ def plane_2d_edge_dipole_ssd(omega, x0, n=[0, 1, 0], *, alpha=_np.pi*3/2,
142203 phi = _np .where (phi < 0 , phi + 2 * _np .pi , phi )
143204
144205 if Nc is None :
145- Nc = _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi )
206+ Nc = int ( _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi ) )
146207
147208 epsilon = _np .ones (Nc ) # weights for series expansion
148209 epsilon [0 ] = 2
@@ -153,7 +214,8 @@ def plane_2d_edge_dipole_ssd(omega, x0, n=[0, 1, 0], *, alpha=_np.pi*3/2,
153214 d = d + 1 / epsilon [m ] * _np .exp (1j * nu * _np .pi / 2 ) * _np .cos (nu * phi_s ) \
154215 * _np .cos (nu * phi ) * _jn (nu , k * r )
155216
156- return 4 * _np .pi / alpha * d
217+ selection = _util .source_selection_all (len (x0 ))
218+ return 4 * _np .pi / alpha * d , selection , _secondary_source_line (omega , c )
157219
158220
159221def line_2d_edge (omega , x0 , xs , * , alpha = _np .pi * 3 / 2 , Nc = None , c = None ):
@@ -197,6 +259,15 @@ def line_2d_edge(omega, x0, xs, *, alpha=_np.pi*3/2, Nc=None, c=None):
197259
198260 Derived from :cite:`Spors2016`
199261
262+ Examples
263+ --------
264+ .. plot::
265+ :context: close-figs
266+
267+ d, selection, secondary_source = sfs.fd.esa.line_2d_edge(
268+ omega, array.x, xs, alpha=np.pi*3/2)
269+ plot(d, selection, secondary_source, norm_ls)
270+
200271 """
201272 x0 = _np .asarray (x0 )
202273 k = _util .wavenumber (omega , c )
@@ -211,7 +282,7 @@ def line_2d_edge(omega, x0, xs, *, alpha=_np.pi*3/2, Nc=None, c=None):
211282 phi = _np .where (phi < 0 , phi + 2 * _np .pi , phi )
212283
213284 if Nc is None :
214- Nc = _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi )
285+ Nc = int ( _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi ) )
215286
216287 epsilon = _np .ones (Nc ) # weights for series expansion
217288 epsilon [0 ] = 2
@@ -272,6 +343,15 @@ def line_2d_edge_dipole_ssd(omega, x0, xs, *, alpha=_np.pi*3/2, Nc=None,
272343
273344 Derived from :cite:`Spors2016`
274345
346+ Examples
347+ --------
348+ .. plot::
349+ :context: close-figs
350+
351+ d, selection, secondary_source = sfs.fd.esa.line_2d_edge_dipole_ssd(
352+ omega, array.x, xs, alpha=np.pi*3/2)
353+ plot(d, selection, secondary_source, norm_ref=1)
354+
275355 """
276356 x0 = _np .asarray (x0 )
277357 k = _util .wavenumber (omega , c )
@@ -286,7 +366,7 @@ def line_2d_edge_dipole_ssd(omega, x0, xs, *, alpha=_np.pi*3/2, Nc=None,
286366 phi = _np .where (phi < 0 , phi + 2 * _np .pi , phi )
287367
288368 if Nc is None :
289- Nc = _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi )
369+ Nc = int ( _np .ceil (2 * k * _np .max (r ) * alpha / _np .pi ) )
290370
291371 epsilon = _np .ones (Nc ) # weights for series expansion
292372 epsilon [0 ] = 2
@@ -299,7 +379,8 @@ def line_2d_edge_dipole_ssd(omega, x0, xs, *, alpha=_np.pi*3/2, Nc=None,
299379 d [idx ] = d [idx ] + f [idx ] * _jn (nu , k * r [idx ]) * _hankel2 (nu , k * r_s )
300380 d [~ idx ] = d [~ idx ] + f [~ idx ] * _jn (nu , k * r_s ) * _hankel2 (nu , k * r [~ idx ])
301381
302- return - 1j * _np .pi / alpha * d
382+ selection = _util .source_selection_all (len (x0 ))
383+ return - 1j * _np .pi / alpha * d , selection , _secondary_source_line (omega , c )
303384
304385
305386def point_25d_edge (omega , x0 , xs , * , xref = [2 , - 2 , 0 ], alpha = _np .pi * 3 / 2 ,
@@ -346,6 +427,15 @@ def point_25d_edge(omega, x0, xs, *, xref=[2, -2, 0], alpha=_np.pi*3/2,
346427
347428 Derived from :cite:`Spors2016`
348429
430+ Examples
431+ --------
432+ .. plot::
433+ :context: close-figs
434+
435+ d, selection, secondary_source = sfs.fd.esa.point_25d_edge(
436+ omega, array.x, xs, xref=xref, alpha=np.pi*3/2)
437+ plot(d, selection, secondary_source, norm_ref=1)
438+
349439 """
350440 x0 = _np .asarray (x0 )
351441 xs = _np .asarray (xs )
0 commit comments