Esempio n. 1
0
def point_25d(omega, x0, n0, xs, *, xref=[0, 0, 0], c=None):
    r"""Driving function for 2.5-dimensional SDM for a virtual point source.

    Parameters
    ----------
    omega : float
        Angular frequency of point source.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    n0 : (N, 3) array_like
        Sequence of normal vectors of secondary sources.
    xs: (3,) array_like
        Position of virtual point source.
    xref : (3,) array_like, optional
        Reference point for synthesized sound field.
    c : float, optional
        Speed of sound.

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing ``True`` or ``False`` depending on
        whether the corresponding secondary source is "active" or not.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    The secondary sources have to be located on the x-axis (y0=0).
    Driving function from :cite:`Spors2010`, Eq.(24).

    Examples
    --------
    .. plot::
        :context: close-figs

        d, selection, secondary_source = sfs.fd.sdm.point_25d(
            omega, array.x, array.n, xs, xref=[0, -1, 0])
        plot(d, selection, secondary_source)

    """
    x0 = _util.asarray_of_rows(x0)
    n0 = _util.asarray_of_rows(n0)
    xs = _util.asarray_1d(xs)
    xref = _util.asarray_1d(xref)
    k = _util.wavenumber(omega, c)
    ds = x0 - xs
    r = _np.linalg.norm(ds, axis=1)
    d = 1/2 * 1j * k * _np.sqrt(xref[1] / (xref[1] - xs[1])) * \
        xs[1] / r * _hankel2(1, k * r)
    selection = _util.source_selection_all(len(x0))
    return d, selection, _secondary_source_point(omega, c)
Esempio n. 2
0
def line_2d(omega, x0, n0, xs, *, c=None):
    r"""Driving function for 2-dimensional WFS for a virtual line source.

    Parameters
    ----------
    omega : float
        Angular frequency of line source.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    n0 : (N, 3) array_like
        Sequence of normal vectors of secondary sources.
    xs : (3,) array_like
        Position of virtual line source.
    c : float, optional
        Speed of sound.

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing ``True`` or ``False`` depending on
        whether the corresponding secondary source is "active" or not.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    .. math::

        D(\x_0,\w) = \frac{\i}{2} \wc
            \frac{\scalarprod{\x-\x_0}{\n_0}}{|\x-\x_\text{s}|}
            \Hankel{2}{1}{\wc|\x-\x_\text{s}|}

    Examples
    --------
    .. plot::
        :context: close-figs

        d, selection, secondary_source = sfs.fd.wfs.line_2d(
            omega, array.x, array.n, xs)
        plot(d, selection, secondary_source)

    """
    x0 = _util.asarray_of_rows(x0)
    n0 = _util.asarray_of_rows(n0)
    xs = _util.asarray_1d(xs)
    k = _util.wavenumber(omega, c)
    ds = x0 - xs
    r = _np.linalg.norm(ds, axis=1)
    d = -1j/2 * k * _inner1d(ds, n0) / r * _hankel2(1, k * r)
    selection = _util.source_selection_line(n0, x0, xs)
    return d, selection, _secondary_source_line(omega, c)
Esempio n. 3
0
def line_2d(omega, x0, n0, xs, *, c=None):
    r"""Driving function for 2-dimensional WFS for a virtual line source.

    Parameters
    ----------
    omega : float
        Angular frequency of line source.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    n0 : (N, 3) array_like
        Sequence of normal vectors of secondary sources.
    xs : (3,) array_like
        Position of virtual line source.
    c : float, optional
        Speed of sound.

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing ``True`` or ``False`` depending on
        whether the corresponding secondary source is "active" or not.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    .. math::

        D(\x_0,\w) = \frac{\i}{2} \wc
            \frac{\scalarprod{\x-\x_0}{\n_0}}{|\x-\x_\text{s}|}
            \Hankel{2}{1}{\wc|\x-\x_\text{s}|}

    Examples
    --------
    .. plot::
        :context: close-figs

        d, selection, secondary_source = sfs.fd.wfs.line_2d(
            omega, array.x, array.n, xs)
        plot(d, selection, secondary_source)

    """
    x0 = _util.asarray_of_rows(x0)
    n0 = _util.asarray_of_rows(n0)
    xs = _util.asarray_1d(xs)
    k = _util.wavenumber(omega, c)
    ds = x0 - xs
    r = _np.linalg.norm(ds, axis=1)
    d = -1j / 2 * k * _inner1d(ds, n0) / r * _hankel2(1, k * r)
    selection = _util.source_selection_line(n0, x0, xs)
    return d, selection, _secondary_source_line(omega, c)
Esempio n. 4
0
def plane_25d(omega, x0, n0, n=[0, 1, 0], *, xref=[0, 0, 0], c=None):
    r"""Driving function for 2.5-dimensional SDM for a virtual plane wave.

    Parameters
    ----------
    omega : float
        Angular frequency of plane wave.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    n0 : (N, 3) array_like
        Sequence of normal vectors of secondary sources.
    n: (3,) array_like, optional
        Normal vector (traveling direction) of plane wave.
    xref : (3,) array_like, optional
        Reference point for synthesized sound field.
    c : float, optional
        Speed of sound.

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing ``True`` or ``False`` depending on
        whether the corresponding secondary source is "active" or not.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    The secondary sources have to be located on the x-axis (y0=0).
    Eq.(3.79) from :cite:`Ahrens2012`.

    Examples
    --------
    .. plot::
        :context: close-figs

        d, selection, secondary_source = sfs.fd.sdm.plane_25d(
            omega, array.x, array.n, npw, xref=[0, -1, 0])
        plot(d, selection, secondary_source)

    """
    x0 = _util.asarray_of_rows(x0)
    n0 = _util.asarray_of_rows(n0)
    n = _util.normalize_vector(n)
    xref = _util.asarray_1d(xref)
    k = _util.wavenumber(omega, c)
    d = 4j * _np.exp(-1j*k*n[1]*xref[1]) / _hankel2(0, k*n[1]*xref[1]) * \
        _np.exp(-1j*k*n[0]*x0[:, 0])
    selection = _util.source_selection_all(len(x0))
    return d, selection, _secondary_source_point(omega, c)
Esempio n. 5
0
def line_2d_edge_dipole_ssd(omega, x0, xs, *, alpha=_np.pi*3/2, Nc=None,
                            c=None):
    r"""Driving function for 2-dimensional line source with edge dipole ESA.

    Driving function for a virtual line source using the 2-dimensional ESA
    for an edge-shaped secondary source distribution consisting of dipole line
    sources.

    Parameters
    ----------
    omega : float
        Angular frequency.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    xs : (3,) array_like
        Position of synthesized line source.
    alpha : float, optional
        Outer angle of edge.
    Nc : int, optional
        Number of elements for series expansion of driving function. Estimated
        if not given.
    c : float, optional
        Speed of sound

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing ``True`` or ``False`` depending on
        whether the corresponding secondary source is "active" or not.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    One leg of the secondary sources has to be located on the x-axis (y0=0),
    the edge at the origin.

    Derived from :cite:`Spors2016`

    """
    x0 = _np.asarray(x0)
    k = _util.wavenumber(omega, c)
    phi_s = _np.arctan2(xs[1], xs[0])
    if phi_s < 0:
        phi_s = phi_s + 2 * _np.pi
    r_s = _np.linalg.norm(xs)
    L = x0.shape[0]

    r = _np.linalg.norm(x0, axis=1)
    phi = _np.arctan2(x0[:, 1], x0[:, 0])
    phi = _np.where(phi < 0, phi + 2 * _np.pi, phi)

    if Nc is None:
        Nc = _np.ceil(2 * k * _np.max(r) * alpha / _np.pi)

    epsilon = _np.ones(Nc)  # weights for series expansion
    epsilon[0] = 2

    d = _np.zeros(L, dtype=complex)
    idx = (r <= r_s)
    for m in _np.arange(Nc):
        nu = m * _np.pi / alpha
        f = 1/epsilon[m] * _np.cos(nu*phi_s) * _np.cos(nu*phi)
        d[idx] = d[idx] + f[idx] * _jn(nu, k*r[idx]) * _hankel2(nu, k*r_s)
        d[~idx] = d[~idx] + f[~idx] * _jn(nu, k*r_s) * _hankel2(nu, k*r[~idx])

    return -1j*_np.pi/alpha * d
Esempio n. 6
0
def plane_2d(omega, x0, r0, n=[0, 1, 0], *, max_order=None, c=None):
    r"""Driving function for 2-dimensional NFC-HOA for a virtual plane wave.

    Parameters
    ----------
    omega : float
        Angular frequency of plane wave.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    r0 : float
        Radius of circular secondary source distribution.
    n : (3,) array_like, optional
        Normal vector (traveling direction) of plane wave.
    max_order : float, optional
        Maximum order of circular harmonics used for the calculation.
    c : float, optional
        Speed of sound.

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing only ``True`` indicating that
        all secondary source are "active" for NFC-HOA.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    .. math::

        D(\phi_0, \omega) =
        -\frac{2\i}{\pi r_0}
        \sum_{m=-M}^M
        \frac{\i^{-m}}{\Hankel{2}{m}{\wc r_0}}
        \e{\i m (\phi_0 - \phi_\text{pw})}

    See :sfs:`d_nfchoa/#equation-fd-nfchoa-plane-2d`

    Examples
    --------
    .. plot::
        :context: close-figs

        d, selection, secondary_source = sfs.fd.nfchoa.plane_2d(
            omega, array.x, R, npw)
        plot(d, selection, secondary_source)

    """
    if max_order is None:
        max_order = _util.max_order_circular_harmonics(len(x0))

    x0 = _util.asarray_of_rows(x0)
    k = _util.wavenumber(omega, c)
    n = _util.normalize_vector(n)
    phi, _, r = _util.cart2sph(*n)
    phi0 = _util.cart2sph(*x0.T)[0]
    d = 0
    for m in range(-max_order, max_order + 1):
        d += 1j**-m / _hankel2(m, k * r0) * _np.exp(1j * m * (phi0 - phi))
    selection = _util.source_selection_all(len(x0))
    return -2j / (_np.pi * r0) * d, selection, _secondary_source_line(omega, c)
Esempio n. 7
0
def line_2d_edge_dipole_ssd(omega,
                            x0,
                            xs,
                            *,
                            alpha=_np.pi * 3 / 2,
                            Nc=None,
                            c=None):
    r"""Driving function for 2-dimensional line source with edge dipole ESA.

    Driving function for a virtual line source using the 2-dimensional ESA
    for an edge-shaped secondary source distribution consisting of dipole line
    sources.

    Parameters
    ----------
    omega : float
        Angular frequency.
    x0 : (N, 3) array_like
        Sequence of secondary source positions.
    xs : (3,) array_like
        Position of synthesized line source.
    alpha : float, optional
        Outer angle of edge.
    Nc : int, optional
        Number of elements for series expansion of driving function. Estimated
        if not given.
    c : float, optional
        Speed of sound

    Returns
    -------
    d : (N,) numpy.ndarray
        Complex weights of secondary sources.
    selection : (N,) numpy.ndarray
        Boolean array containing ``True`` or ``False`` depending on
        whether the corresponding secondary source is "active" or not.
    secondary_source_function : callable
        A function that can be used to create the sound field of a
        single secondary source.  See `sfs.fd.synthesize()`.

    Notes
    -----
    One leg of the secondary sources has to be located on the x-axis (y0=0),
    the edge at the origin.

    Derived from :cite:`Spors2016`

    """
    x0 = _np.asarray(x0)
    k = _util.wavenumber(omega, c)
    phi_s = _np.arctan2(xs[1], xs[0])
    if phi_s < 0:
        phi_s = phi_s + 2 * _np.pi
    r_s = _np.linalg.norm(xs)
    L = x0.shape[0]

    r = _np.linalg.norm(x0, axis=1)
    phi = _np.arctan2(x0[:, 1], x0[:, 0])
    phi = _np.where(phi < 0, phi + 2 * _np.pi, phi)

    if Nc is None:
        Nc = _np.ceil(2 * k * _np.max(r) * alpha / _np.pi)

    epsilon = _np.ones(Nc)  # weights for series expansion
    epsilon[0] = 2

    d = _np.zeros(L, dtype=complex)
    idx = (r <= r_s)
    for m in _np.arange(Nc):
        nu = m * _np.pi / alpha
        f = 1 / epsilon[m] * _np.cos(nu * phi_s) * _np.cos(nu * phi)
        d[idx] = d[idx] + f[idx] * _jn(nu, k * r[idx]) * _hankel2(nu, k * r_s)
        d[~idx] = d[~idx] + f[~idx] * _jn(nu, k * r_s) * _hankel2(
            nu, k * r[~idx])

    return -1j * _np.pi / alpha * d