Skip to content

Commit c60b86d

Browse files
committed
Update esa.py
- add examples in docstring - fix np.ceil -> int - fix dipole driving function to be compatible with >=0.5 version
1 parent 95ee0ab commit c60b86d

File tree

1 file changed

+96
-6
lines changed

1 file changed

+96
-6
lines changed

sfs/fd/esa.py

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,49 @@
88
Note that mode-matching (such as NFC-HOA, SDM) are equivalent
99
to 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
"""
1255
import numpy as _np
1356
from 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

159221
def 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

305386
def 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

Comments
 (0)