Ejemplo n.º 1
0
def esa_edge_2d_line(omega, x0, xs, alpha=3/2*np.pi, Nc=None, c=None):
    """Line source by two-dimensional ESA for an edge-shaped secondary source
       distribution constisting of monopole line sources.

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

    Derived from :cite:`Spors2016`

    Parameters
    ----------
    omega : float
        Angular frequency.
    x0 : int(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
    -------
    (N,) numpy.ndarray
        Complex weights of secondary sources.

    """
    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.sin(nu*phi_s) * np.cos(nu*phi) * nu/r
        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])

    d[phi > 0] = -d[phi > 0]

    return -1j*np.pi/alpha * d
Ejemplo n.º 2
0
def scatter_dielectric_cylinder(R,
                                phi,
                                wavelength,
                                radius,
                                er=1.0,
                                ur=1.0,
                                E0=1.0,
                                N=N0):
    '''Scattered field from a dielectric cylinder'''
    Ezs = 0
    Ezint = 0
    k = 2 * np.pi / wavelength
    kd = k * np.sqrt(ur * er)
    a = radius
    for n in range(-N, N):
        hn2 = hankel2(n, k * a)
        dr = 0.001 * k * a
        hn2p = (hankel2(n, k * a + dr) - hankel2(n, k * a - dr)) / (2 * dr)

        an_n = np.sqrt(ur) * jvp(n, k * a) * jv(n, kd * a) - np.sqrt(er) * jv(
            n, k * a) * jvp(n, kd * a)
        an_d = np.sqrt(ur) * hn2p * jv(n, kd * a) - np.sqrt(er) * hn2 * jvp(
            n, kd * a)
        an = -(1.j)**-n * an_n / an_d
        Ezs += E0 * an * hankel2(n, k * R) * np.exp(1.j * n * phi)

        cn_n = 2 * np.sqrt(ur)
        cn_d = np.sqrt(ur) * hn2p * jv(n, kd * a) - np.sqrt(er) * hn2 * jvp(
            n, kd * a)
        cn = (1.j)**-(n + 1) / (np.pi * k * a) * cn_n / cn_d
        Ezint += E0 * cn * jv(n, kd * R) * np.exp(1.j * n * phi)
    Ezs[R < a] = Ezint[R < a]
    return Ezint, Ezs
def get_weight_vector():
    _, valid_freq_array = get_valid_freq_array_and_index()
    kr_array = 2 * np.pi * valid_freq_array / c.speed_of_sound * c.array_radius
    n = 3  # warning: magic number
    weight_vector = 1 / kr_array ** 2 / (np.sqrt(np.pi / (2 * kr_array)) * (
                n / kr_array * hankel2(n + 1 / 2, kr_array) - hankel2(n + 3 / 2, kr_array)))
    return np.abs(weight_vector)
Ejemplo n.º 4
0
def get_bn(freq, order):
    kr = 2 * np.pi * freq * c.array_radius / c.speed_of_sound + (
        freq == 0) * np.finfo(float).eps
    _t = sqrt(np.pi / (2 * kr)) * (order / kr * hankel2(order + 1 / 2, kr) -
                                   hankel2(order + 3 / 2, kr))
    bn = 1j**(order - 1) / (kr**2 * _t)
    return bn
def construct_g_D(pos_D, k, n):
	# pos_D : N X 2 vector containing position of each grid
	# n : size of each grid
	# k : wavevector
	a = (n**2/np.pi)**0.5
	N = np.shape(pos_D)[0]
	L = np.int32(N**0.5)

	pos_D_x, pos_D_y = np.reshape(pos_D[:,0], [L,L]), np.reshape(pos_D[:,1], [L,L])
	g_D = np.zeros([2*L-1,2*L-1],dtype=np.complex128)
	g_D[0,0] = -1j*0.5*(np.pi*k*a*sc.hankel2(1,k*a) - 2*1j)
	for i in range(L):
		for j in range(1,L):			
			rho_ij = np.abs(pos_D_x[i,j]-pos_D_x[0,0])**2 + np.abs(pos_D_y[i,j]-pos_D_y[0,0])**2 
			rho_ij = np.float32(rho_ij**0.5)
			g_D[i,j] = -1j*0.5*np.pi*k*a*sc.j1(k*a)*sc.hankel2(0,k*rho_ij)

	for i in range(1,L):
		rho_ij = np.abs(pos_D_x[i,0]-pos_D_x[0,0])**2 + np.abs(pos_D_y[i,0]-pos_D_y[0,0])**2 
		rho_ij = np.float32(rho_ij**0.5)
		g_D[i,0] = -1j*0.5*np.pi*k*a*sc.j1(k*a)*sc.hankel2(0,k*rho_ij)

	for i in range(L,2*L-1):
		for j in range(L, 2*L-1):
			g_D[i,j] = g_D[abs(i+1-2*L),abs(j+1-2*L)]
	for i in range(L, 2*L-1):
		for j in range(L):
			g_D[i,j] = g_D[abs(i+1-2*L),j]
	for i in range(L):
		for j in range(L, 2*L-1):
			g_D[i,j] = g_D[i,abs(j+1-2*L)]
	g_D_fft = fftpack.fftn(g_D)
	g_D_fft_conj = fftpack.fftn(g_D.conj())
	return g_D, g_D_fft, g_D_fft_conj
Ejemplo n.º 6
0
def admitant_2d_matrix_element_bm(mesh, row_idx, col_idx, z0, k, coupling_sign):
    n, ns = mesh.normals[row_idx], mesh.normals[col_idx]
    r = mesh.centers[row_idx]
    corners, admittance = mesh.corners[col_idx], mesh.admittances[col_idx]
    singular = row_idx == col_idx

    if singular:
        element_vector = corners[1] - corners[0]
        length = np.sqrt(element_vector.dot(element_vector))
        lk2 = length * k / 2
        return (
            +(z0 * admittance * np.pi * length * k / 8)
            * (+hankel2(0, lk2) * struve(-1, lk2) + hankel2(1, lk2) * struve(0, lk2))
            - coupling_sign
            * fixed_quad(regularized_hypersingular_bm_part, 0, lk2)[0]
            / 2
            + coupling_sign * 2j / (np.pi * k * length)
            + (1 - coupling_sign * z0 * admittance) / 2
        )

    else:

        def integral_function(rs):
            return (
                hs_2d(ns, k, r, rs)
                - 1j * k * z0 * admittance * g_2d(k, r, rs)
                + coupling_sign * z0 * admittance * h_2d(n, k, r, rs)
                + coupling_sign * 1j / k * hypersingular(k, r, rs, n, ns)
            )

        return line_integral(integral_function, corners[0], corners[1], singular)
Ejemplo n.º 7
0
def hypersingular(k, r, rs, n, ns):
    vector = r - rs
    distance = np.sqrt(vector.dot(vector))
    kdist = k * distance
    return (1j * k / (4 * distance ** 2)) * (
        distance * hankel2(1, kdist) * n.dot(ns)
        - k * hankel2(2, kdist) * n.dot(vector) * ns.dot(vector)
    )
Ejemplo n.º 8
0
def scatter_conducting_cylinder(R, phi, wavelength, radius, E0=1.0, N=N0):
    '''Scattered field from a conducting cylinder'''
    Ez = 0
    k = 2 * np.pi / wavelength
    for n in range(-N, N):
        an = -(1.j)**-n * jv(n, k * radius) / hankel2(n, k * radius)
        Ez += E0 * an * hankel2(n, k * R) * np.exp(1.j * n * phi)
    Ez[R < radius] = 0
    return Ez
Ejemplo n.º 9
0
def theo_fun(k):
    '''Returns Theodorsen function at a reduced frequency k'''

    H1 = scsp.hankel2(1, k)
    H0 = scsp.hankel2(0, k)

    C = H1 / (H1 + j * H0)

    return C
Ejemplo n.º 10
0
def sMatrixElementCoefficients(k, n1, n2, m):
    A = -n1 * hankel2(m, n2 * k) * jvp(m, n1 * k) + n2 * jn(m, n1 * k) * h2vp(
        m, n2 * k)
    B = n1 * hankel1(m, n2 * k) * jvp(m, n1 * k) - n2 * jn(m, n1 * k) * h1vp(
        m, n2 * k)
    Ap = -n1 * n1 * jvp(m, n1 * k, 2) * hankel2(m, n2 * k) + n2 * n2 * jn(
        m, n1 * k) * h2vp(m, n2 * k, 2)
    Bp = n1 * n1 * jvp(m, n1 * k, 2) * hankel1(m, n2 * k) - n2 * n2 * jn(
        m, n1 * k) * h1vp(m, n2 * k, 2)
    return A, B, Ap, Bp
Ejemplo n.º 11
0
def compute_total_field(x,
                        y,
                        radius,
                        an,
                        cn,
                        N,
                        wavenumber_b,
                        wavenumber_d,
                        magnitude,
                        theta=None):
    """Summarize the method."""
    E0 = magnitude
    kb, kd = wavenumber_b, wavenumber_d
    a = radius

    if theta is None:
        rho, phi = cart2pol(x, y)
        et = np.zeros(rho.shape, dtype=complex)
        i = 0
        for n in range(-N, N + 1):

            et[rho > a] = et[rho > a] + (E0 * 1j**(-n) *
                                         (jv(n, kb * rho[rho > a]) + an[i] *
                                          hankel2(n, kb * rho[rho > a])) *
                                         np.exp(1j * n * phi[rho > a]))

            et[rho <= a] = et[rho <= a] + (E0 * 1j**(-n) * cn[i] * jv(
                n, kd * rho[rho <= a]) * np.exp(1j * n * phi[rho <= a]))

            i += 1

    else:
        S = theta.size
        et = np.zeros((x.size, S), dtype=complex)
        for s in range(S):
            xp, yp = rotate_axis(theta[s], x.reshape(-1), y.reshape(-1))
            rho, phi = cart2pol(xp, yp)
            i = 0
            for n in range(-N, N + 1):

                et[rho > a,
                   s] = et[rho > a, s] + (E0 * 1j**(-n) *
                                          (jv(n, kb * rho[rho > a]) + an[i] *
                                           hankel2(n, kb * rho[rho > a])) *
                                          np.exp(1j * n * phi[rho > a]))

                et[rho <= a,
                   s] = et[rho <= a, s] + (E0 * 1j**(-n) * cn[i] * jv(
                       n, kd * rho[rho <= a]) * np.exp(1j * n * phi[rho <= a]))

                i += 1
    return et
Ejemplo n.º 12
0
def test_cylindrical_hankel_2():
    order = np.random.randint(0, 6)
    value = np.random.rand(1).item() * 10
    assert (roundComplex(complex(NumCpp.cyclic_hankel_2_Scaler(order, value)), NUM_DECIMALS_ROUND) ==
            roundComplex(sp.hankel2(order, value), NUM_DECIMALS_ROUND))

    shapeInput = np.random.randint(20, 100, [2, ])
    shape = NumCpp.Shape(shapeInput[0].item(), shapeInput[1].item())
    order = np.random.randint(0, 6)
    value = NumCpp.NdArray(shape)
    valuePy = np.random.rand(shape.rows, shape.cols) * 10
    value.setArray(valuePy)
    assert np.array_equal(roundComplexArray(NumCpp.cyclic_hankel_2_Array(order, value), NUM_DECIMALS_ROUND),
                          roundComplexArray(sp.hankel2(order, valuePy), NUM_DECIMALS_ROUND))
def f0(x, v):
    if v == 0:
        return f(x)
    elif v == 1:
        return spec.jn(10, x)
    elif v == 2:
        return spec.hankel1(0, x)
    elif v == 3:
        return spec.hankel1(10, x)
    elif v == 4:
        return spec.hankel2(0, x)
    elif v == 5:
        return spec.hankel2(10, x)
    else:
        return spec.airy(x)
Ejemplo n.º 14
0
def radar_cross_section(frequency, radius, incident_angle, observation_angle,
                        number_of_modes):
    """
    Calculate the bistatic radar cross section for the infinite cylinder with oblique incidence.
    :param frequency: The frequency of the incident energy (Hz).
    :param radius: The radius of the cylinder (m).
    :param incident_angle: The angle of incidence from z-axis (deg).
    :param observation_angle: The observation angle (deg).
    :param number_of_modes: The number of terms to take in the summation.
    :return: The bistatic radar cross section for the infinite cylinder (m^2).
    """
    # Wavelength
    wavelength = c / frequency

    # Wavenumber
    k = 2.0 * pi / wavelength

    modes = range(number_of_modes + 1)

    # Initialize the sum
    s_tm = 0
    s_te = 0

    phi = radians(observation_angle)
    theta_i = radians(incident_angle)

    # Argument for Bessel and Hankel functions
    z = k * radius * sin(theta_i)

    for n in modes:
        en = 2.0
        if n == 0:
            en = 1.0

        an = jv(n, z) / hankel2(n, z)

        jp = n * jv(n, z) / z - jv(n + 1, z)
        hp = n * hankel2(n, z) / z - hankel2(n + 1, z)

        bn = -jp / hp

        s_tm += en * an * cos(n * phi)
        s_te += en * bn * cos(n * phi)

    rcs_tm = 2.0 * wavelength / (pi * sin(theta_i)) * abs(s_tm)**2
    rcs_te = 2.0 * wavelength / (pi * sin(theta_i)) * abs(s_te)**2

    return rcs_te, rcs_tm
Ejemplo n.º 15
0
def my_Hankel(n, k, abs_R):
    z = k * k
    if (np.imag(z) > 0):
        ret = sf.hankel1(n, k * abs_R)
    else:
        ret = -sf.hankel2(n, k * abs_R)
    return ret
Ejemplo n.º 16
0
    def _minimum_norm(self, et):
        """Evaluate the Minimum Norm formulation.

        In this formulation, the trial function is defined as the kernel
        function.

        Parameters
        ----------
            et : :class:`numpy.ndarray`
                Total field matrix.
        """
        N = self._u.size
        Q, P = self.discretization
        kb = self.configuration.kb
        Kpq = np.zeros((P * Q, N), dtype=complex)
        s = 0
        for i in range(P * Q):
            R = np.sqrt((self._xpq[i] - self._u)**2 +
                        (self._ypq[i] - self._v)**2)
            Kpq[i, :] = -kb**2 * 1j / 4 * hankel2(0, kb * R) * et[:, s]
            if s == self.configuration.NS - 1:
                s = 0
            else:
                s += 1
        return Kpq
Ejemplo n.º 17
0
    def _get_kernel(self, et, resolution):
        r"""Compute kernel function.

        Evaluate the kernel function of the integral operator. The
        kernel is defined as:

        .. math:: K(x, y, u, v) = j\omega\mu_b E(\phi, u, v)\frac{j}{4}
        H_0^{(2)}(k_b|\sqrt{(x-u)^2 + (y-v)^2}|)

        Parameters
        ----------
            et : :class:`numpy.ndarray`
                Total field matrix.

            resolution : 2-tuple
                Image discretization in y and x directions,
                respectively.
        """
        NS = self.configuration.NS
        kb = self.configuration.kb
        K = np.zeros(self._R.shape, dtype=complex)
        L = et.shape[1]
        s = 0
        for i in range(K.shape[0]):
            K[i, :] = -kb**2 * 1j / 4 * hankel2(0, kb * self._R[i, :]) * et[:,
                                                                            s]
            # Matching the measurement-source indexation
            if s == L - 1:
                s = 0
            else:
                s += 1
        return K
Ejemplo n.º 18
0
def line_dipole(omega, x0, n0, grid, *, c=None):
    r"""Line source with dipole characteristics parallel to the z-axis.

    Parameters
    ----------
    omega : float
        Frequency of source.
    x0 : (3,) array_like
        Position of source. Note: third component of x0 is ignored.
    x0 : (3,) array_like
        Normal vector of the source.
    grid : triple of array_like
        The grid that is used for the sound field calculations.
        See `sfs.util.xyz_grid()`.
    c : float, optional
        Speed of sound.

    Notes
    -----
    .. math::

        G(\x-\x_0,\w) = \frac{\i k}{4} \Hankel{2}{1}{\wc|\x-\x_0|} \cos{\phi}

    """
    k = _util.wavenumber(omega, c)
    x0 = _util.asarray_1d(x0)[:2]  # ignore z-components
    n0 = _util.asarray_1d(n0)[:2]
    grid = _util.as_xyz_components(grid)
    dx = grid[:2] - x0

    r = _np.linalg.norm(dx)
    p = 1j * k / 4 * _special.hankel2(1, k * r) * _np.inner(dx, n0) / r
    return _duplicate_zdirection(p, grid)
Ejemplo n.º 19
0
def _spherical_hankel(n, z, kind):
    if kind == 1:
        hankel = _spspecial.hankel1(n + 0.5, z)
    elif kind == 2:
        hankel = _spspecial.hankel2(n + 0.5, z)
    hankel = np.sqrt(np.pi / 2 / z) * hankel

    return hankel
Ejemplo n.º 20
0
def get_coefficients(Nterms, wavenumber_b, wavenumber_d, radius, epsilon_d,
                     epsilon_b):
    """Summarize the method."""
    n = np.arange(-Nterms, Nterms + 1)
    kb, kd = wavenumber_b, wavenumber_d
    a = radius

    an = (-jv(n, kb * a) / hankel2(n, kb * a) *
          ((epsilon_d * jvp(n, kd * a) /
            (epsilon_b * kd * a * jv(n, kd * a)) - jvp(n, kb * a) /
            (kb * a * jv(n, kb * a))) /
           (epsilon_d * jvp(n, kd * a) /
            (epsilon_b * kd * a * jv(n, kd * a)) - h2vp(n, kb * a) /
            (kb * a * hankel2(n, kb * a)))))

    cn = 1 / jv(n, kd * a) * (jv(n, kb * a) + an * hankel2(n, kb * a))

    return an, cn
Ejemplo n.º 21
0
def construct_G_D(pos_D, k, n):
    # pos_D : N X 2 vector containing position of each grid
    # n : size of each grid
    # k : wavevector
    a = (n**2 / np.pi)**0.5
    N = np.shape(pos_D)[0]

    G_D = np.zeros([N, N], dtype=np.complex128)
    for i in range(N):
        for j in range(N):
            if i == j:
                G_D[i, j] = -1j * 0.5 * (np.pi * k * a * sc.hankel2(1, k * a) -
                                         2 * 1j)
            else:
                rho_ij = linalg.norm(pos_D[i, :] - pos_D[j, :], 2)
                G_D[i,
                    j] = -1j * 0.5 * np.pi * k * a * sc.j1(k * a) * sc.hankel2(
                        0, k * rho_ij)
    return G_D
Ejemplo n.º 22
0
def um(r, m):
    T = 1000
    f = 1 / T
    omega = 2 * np.pi * f
    a = 3480.
    rs = 6271.
    omega = 0.05
    bbeta = 6.5
    mu = 80

    if r < a:
        um = 0
        return um

    elif a <= r and r < rs:
        um = -1. / (16 * mu) * 1j * (
            2 * spf.hankel1(m, omega * r / bbeta) + a * omega *
            (-spf.hankel1(m - 1, a * omega / bbeta) +
             spf.hankel1(m + 1, a * omega / bbeta)) *
            spf.hankel2(m, r * omega / bbeta) /
            (a * omega * spf.hankel2(m - 1, a * omega / bbeta) -
             m * bbeta * spf.hankel2(m, a * omega / bbeta))) * spf.hankel2(
                 m, rs * omega / bbeta)
        #  um = -1./(16*mu)*1j*(2*spf.hankel1(m,r*omega/bbeta)+  a*omega*(-spf.hankel1(m-1,a*omega/bbeta)+spf.hankel1(m+1,a*omega/bbeta))*spf.hankel2(m,r*omega/bbeta) /  (a*omega*spf.hankel2(m-1,a*omega/bbeta)-m*bbeta*spf.hankel2(m,a*omega/bbeta)) )*spf.hankel2(m,rs*omega/bbeta)

        #  *spf.hankel1(m,omega*rs/bbeta)*(2*spf.hankel2(m,omega*r/bbeta)+omega*a*spf.hankel1(m,omega*r/bbeta)*(spf.hankel2(m+1,omega*a/bbeta)-spf.hankel2(m-1,omega*a/bbeta))/(omega*a*spf.hankel1(m-1,omega*a/bbeta)-m*bbeta*spf.hankel1(m,omega*a/bbeta)))

        #        1./(16*mu)*1j*spf.hankel1(m,omega*rs/bbeta)*(2*spf.hankel2(m,omega*r/bbeta)+omega*a*spf.hankel1(m,omega*r/bbeta)*(spf.hankel2(m+1,omega*a/bbeta)-spf.hankel2(m-1,omega*a/bbeta))/(omega*a*spf.hankel1(m-1,omega*a/bbeta)-m*bbeta*spf.hankel1(m,omega*a/bbeta)))
        return um

    elif rs <= r:
        um = -1 / 16. * 1j * a * omega * spf.hankel2(m, r * omega / bbeta) * (
            (-spf.hankel1(m - 1, a * omega / bbeta) +
             spf.hankel1(m + 1, a * omega / bbeta)) * spf.hankel2(
                 m, rs * omega / bbeta) + spf.hankel1(m, rs * omega / bbeta) *
            (spf.hankel2(m - 1, a * omega / bbeta) -
             spf.hankel2(m + 1, a * omega / bbeta))) / (
                 a * mu * omega * spf.hankel2(m - 1, a * omega / bbeta) -
                 m * bbeta * mu * spf.hankel2(m, a * omega / bbeta))
        #-1./16.*a*omega*spf.hankel2(m,r*omega/bbeta)*((-spf.hankel1(m-1,a*omega/bbeta)+spf.hankel1(m+1,a*omega/bbeta))*spf.hankel2(m,rs*omega/bbeta)+spf.hankel1(m,rs*omega)*(spf.hankel2(m-1,a*omega/bbeta)-spf.hankel2(m+1,a*omega/bbeta)))/(a*mu*omega*spf.hankel2(m-1,a*omega/bbeta)-m*bbeta*mu*spf.hankel2(m,a*omega/bbeta))
        #    -1/(16*mu)*1j*a*omega*spf.hankel1(m,omega*r/bbeta)*((-spf.hankel1(m-1,a*omega/bbeta)+spf.hankel1(m+1,a*omega/bbeta))*spf.hankel2(m,rs*omega/bbeta)+spf.hankel1(m,rs*omega/bbeta)*(spf.hankel2(m-1,a*omega/bbeta)-spf.hankel2(m+1,a*omega/bbeta)))/(a*omega*spf.hankel1(m-1,omega*a/bbeta)-m*bbeta*spf.hankel1(m,a*omega/bbeta))
        #-1/(16*mu)*1j*a*omega*spf.hankel1(m,omega*r/bbeta)*((-spf.hankel1(m-1,a*omega/bbeta)+spf.hankel1(m+1,a*omega/bbeta))*spf.hankel2(m,rs*omega/bbeta)+spf.hankel1(m,rs*omega/bbeta)*(spf.hankel2(m-1,a*omega/bbeta)-spf.hankel2(m+1,a*omega/bbeta)))/(a*omega*spf.hankel1(m-1,omega*a/bbeta)-m*bbeta*spf.hankel1(m,a*omega/bbeta))
        return um
Ejemplo n.º 23
0
def directwave(wav, trav, nt, dt, nfft=None, dist=None, kind='2d'):
    r"""Analytical direct wave

    Compute analytical 2d or 3d Green's function in frequency domain given
    a wavelet ``wav``, traveltime curve ``trav`` and distance ``dist``
    (for 3d case only).

    Parameters
    ----------
    wav : :obj:`numpy.ndarray`
        Wavelet in time domain to apply to direct arrival when created
        using ``trav``. Phase will be discarded resulting in a zero-phase
        wavelet with same amplitude spectrum as provided by ``wav``
    trav : :obj:`numpy.ndarray`
        Traveltime of first arrival from subsurface point to
        surface receivers of size :math:`\lbrack nr \times 1 \rbrack`
    nt : :obj:`float`, optional
        Number of samples in time
    dt : :obj:`float`, optional
        Sampling in time
    nfft : :obj:`int`, optional
        Number of samples in fft time (if ``None``, :math:`nfft=nt`)
    dist: :obj:`numpy.ndarray`
        Distance between subsurface point to
        surface receivers of size :math:`\lbrack nr \times 1 \rbrack`
    kind : :obj:`str`, optional
        2-dimensional (``2d``) or 3-dimensional (``3d``)

    Returns
    -------
    direct : :obj:`numpy.ndarray`
        Direct arrival in time domain of size
        :math:`\lbrack nt \times nr \rbrack`

    """
    nr = len(trav)
    nfft = nt if nfft is None or nfft < nt else nfft
    W = np.abs(np.fft.rfft(wav, nfft)) * dt
    f = 2 * np.pi * np.arange(nfft) / (dt * nfft)

    direct = np.zeros((nfft, nr), dtype=np.complex128)
    for it in range(len(W)):
        if kind == '2d':
            #direct[it] = W[it] * 1j * f[it] * np.exp(-1j * ((f[it] * trav) \
            #             + np.sign(f[it]) * np.pi / 4)) / \
            #             np.sqrt(8 * np.pi * np.abs(f[it]) * trav + 1e-10)
            direct[it] = W[it] * 1j * f[it] * (-1j) * \
                         hankel2(0, f[it] * trav + 1e-10) / 4
        else:
            direct[it] = W[it] * np.exp(
                -1j * f[it] * trav) / (4 * np.pi * dist)

    direct = np.fft.irfft(direct, nfft, axis=0) / dt
    direct = np.real(direct[:nt])
    return direct
Ejemplo n.º 24
0
def calc_coefficiencts(k, radius, z0, amplitude, admittance, max_order):
    orders = np.arange(max_order + 1)
    thetas = np.pi * orders / len(orders)
    rhs = (amplitude * np.exp(1j * k * radius * np.cos(thetas)) *
           (np.cos(thetas) / z0 - admittance))
    matrix = np.array([[
        np.cos(n * theta) *
        (1j * h2vp(n, k * radius) / z0 + admittance * hankel2(n, k * radius))
        for n in orders
    ] for theta in thetas])
    return np.linalg.solve(matrix, rhs)
Ejemplo n.º 25
0
def theo_fun(k):
    r"""Returns the value of Theodorsen's function at a reduced frequency :math:`k`.

    .. math:: \mathcal{C}(jk) = \frac{H_1^{(2)}(k)}{H_1^{(2)}(k) + jH_0^{(2)}(k)}

    where :math:`H_0^{(2)}(k)` and :math:`H_1^{(2)}(k)` are Hankel functions of the second kind.

    Args:
        k (np.array): Reduced frequency/frequencies at which to evaluate the function.

    Returns:
        np.array: Value of Theodorsen's function evaluated at the desired reduced frequencies.

    """

    H1 = scsp.hankel2(1, k)
    H0 = scsp.hankel2(0, k)

    C = H1 / (H1 + j * H0)

    return C
Ejemplo n.º 26
0
def besselh(n, k, z):
    """ Hankel function
        n - real order
        k - kind (1,2)
        z - complex argument
    """
    if k == 2:
        return special.hankel2(n,z)
    elif 0 == 1:
        return special.hankel1(n,z)
    else:
        raise TypeError("Only second or first kind.")
Ejemplo n.º 27
0
def construct_G_S(pos_D, pos_S, k, n):
    M = np.shape(pos_S)[0]
    N = np.shape(pos_D)[0]
    G_S = np.zeros([M, N], dtype=np.complex128)
    a = (n**2 / np.pi)**0.5

    for i in range(M):
        for j in range(N):
            rho_ij = linalg.norm(pos_S[i, :] - pos_D[j, :], 2)
            G_S[i, j] = -1j * 0.5 * np.pi * k * a * sc.j1(k * a) * sc.hankel2(
                0, k * rho_ij)
    return G_S
Ejemplo n.º 28
0
def cyl_modal_coefs(N, kr, arrayType):
    """
    Modal coefficients for rigid or open cylindrical array

    Parameters
    ----------
    N : int
        Maximum spherical harmonic expansion order.
    kr: ndarray
        Wavenumber-radius product. Dimension = (l).
    arrayType: str
        'open' or 'rigid'.

    Returns
    -------
    b_N : ndarray
        Modal coefficients. Dimension = (l, N+1)

    Raises
    -----
    TypeError, ValueError: if method arguments mismatch in type, dimension or value.

    Notes
    -----
    The `arrayType` options are:
    - 'open' for open array of omnidirectional sensors
    - 'rigid' for sensors mounted on a rigid baffle.

    """

    _validate_int('N', N)
    _validate_ndarray_1D('kr', kr, positive=True)
    _validate_string('arrayType', arrayType, choices=['open', 'rigid'])

    b_N = np.zeros((kr.size, N + 1), dtype='complex')

    for n in range(N + 1):

        if arrayType is 'open':
            b_N[:, n] = np.power(1j, n) * jv(n, kr)

        elif arrayType is 'rigid':
            jn = jv(n, kr)
            jnprime = jvp(n, kr, 1)
            hn = hankel2(n, kr)
            hnprime = h2vp(n, kr, 1)

            temp = np.power(1j, n) * (jn - (jnprime / hnprime) * hn)
            temp[np.where(kr == 0)] = 1 if n == 0 else 0.
            b_N[:, n] = temp

    return b_N
Ejemplo n.º 29
0
def line_velocity(omega, x0, grid, *, c=None, rho0=None):
    """Velocity of line source parallel to the z-axis.

    Parameters
    ----------
    omega : float
        Frequency of source.
    x0 : (3,) array_like
        Position of source. Note: third component of x0 is ignored.
    grid : triple of array_like
        The grid that is used for the sound field calculations.
        See `sfs.util.xyz_grid()`.
    c : float, optional
        Speed of sound.

    Returns
    -------
    `XyzComponents`
        Particle velocity at positions given by *grid*.

    Examples
    --------
    The particle velocity can be plotted on top of the sound pressure:

    .. plot::
        :context: close-figs

        v = sfs.fd.source.line_velocity(omega, x0, vgrid)
        sfs.plot2d.amplitude(p * normalization_line, grid)
        sfs.plot2d.vectors(v * normalization_line, vgrid)
        plt.title("Sound Pressure and Particle Velocity")

    """
    if c is None:
        c = _default.c
    if rho0 is None:
        rho0 = _default.rho0
    k = _util.wavenumber(omega, c)
    x0 = _util.asarray_1d(x0)[:2]  # ignore z-component
    grid = _util.as_xyz_components(grid)

    offset = grid[:2] - x0
    r = _np.linalg.norm(offset)
    v = -1 / (4 * c * rho0) * _special.hankel2(1, k * r)
    v = [v * o / r for o in offset]

    assert v[0].shape == v[1].shape

    if len(grid) > 2:
        v.append(_np.zeros_like(v[0]))

    return _util.XyzComponents([_duplicate_zdirection(vi, grid) for vi in v])
def eq(x, r, n, coef):
    """
    计算均衡矩阵中各元素数值

    argument:
    x: 某一单一频率值
    r: 球形阵列半径
    n: 阶数
    coef: 均衡系数

    return:
    out:均衡矩阵的一个元素
    """
    kr = 2 * np.pi * x * r / 344 + (x == 0) * np.finfo(float).eps
    hnde = math.sqrt(np.pi /
                     (2 * kr)) * (n / kr * special.hankel2(n + 1 / 2, kr) -
                                  special.hankel2(n + 3 / 2, kr))
    bn = (-1j)**(n + 1) * (-1)**n / (kr**2 * hnde)
    #    bn = 1j/(kr**2*hnde)
    out = np.conjugate(bn) / ((abs(bn))**2 + coef**2)
    #out = (np.conjugate(1j/hnde)*(kr**2))/((coef**2)*(kr**4)-1/(hnde**2))/(-1j)**n
    return out
Ejemplo n.º 31
0
	def itf_worker(self,input_array,lock_input_array,output_dictionary,lock_output_dictionary,itf2):
		while len(input_array)>0:
			time_fi=0
			if len(input_array)>0:
				with lock_input_array:
					if len(input_array)>0:
						time_fi=input_array.pop(0)
			if time_fi!=0:
				itf1 = -1j*pi*self.CONST_MU0*time_fi/2/self.magnetic_altitude(time_fi)/self.phase_velocity(time_fi)
				itf3 = special.hankel2([1],[2*pi*self.r*time_fi/self.phase_velocity(time_fi)])
				itf4 = exp(-self.attenuation_factor(time_fi)*self.r)
				output_res=itf1*itf3*itf4*itf2
				with lock_output_dictionary:
					output_dictionary[time_fi]=output_res
Ejemplo n.º 32
0
def wfs_2d_line(omega, x0, n0, xs, c=None):
    """Line source by 2-dimensional WFS.

    ::

        D(x0,k) = j/2 k (x0-xs) n0 / |x0-xs| * H1(k |x0-xs|)

    """
    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)
    return -1j/2 * k * inner1d(ds, n0) / r * hankel2(1, k * r)
Ejemplo n.º 33
0
def sdm_25d_plane(omega, x0, n0, n=[0, 1, 0], xref=[0, 0, 0], c=None):
    """Plane wave by 2.5-dimensional SDM.

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

        D_2.5D(x0,w) =

    """
    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)
    return 4j * np.exp(-1j*k*n[1]*xref[1]) / hankel2(0, k*n[1]*xref[1]) * \
        np.exp(-1j*k*n[0]*x0[:, 0])
Ejemplo n.º 34
0
def sdm_2d_line(omega, x0, n0, xs, c=None):
    """Line source by two-dimensional SDM.

    The secondary sources have to be located on the x-axis (y0=0).
    Derived from :cite:`Spors2009`, Eq.(9), Eq.(4)::

        D(x0,k) =

    """
    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)
    return - 1j/2 * k * xs[1] / r * hankel2(1, k * r)
Ejemplo n.º 35
0
def hankel2(n, z):
    """Bessel function of third kind (Hankel function) of order n at kr.
    Wraps scipy.special.hankel2(n, z)

    Parameters
    ----------
    n : array_like
       Order
    z: array_like
       Argument

    Returns
    -------
    H2 : array_like
       Values of Hankel function of order n at position z
    """
    return scy.hankel2(n, z)
Ejemplo n.º 36
0
def sdm_25d_point(omega, x0, n0, xs, xref=[0, 0, 0], c=None):
    """Point source by 2.5-dimensional SDM.

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

        D(x0,k) =

    """
    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)
    return 1/2 * 1j * k * np.sqrt(xref[1] / (xref[1] - xs[1])) * \
        xs[1] / r * hankel2(1, k * r)
Ejemplo n.º 37
0
def line_dipole(omega, x0, n0, grid, *, c=None):
    r"""Line source with dipole characteristics parallel to the z-axis.

    Note: third component of x0 is ignored.

    Notes
    -----
    .. math::

        G(\x-\x_0,\w) = \frac{\i k}{4} \Hankel{2}{1}{\wc|\x-\x_0|} \cos{\phi}

    """
    k = _util.wavenumber(omega, c)
    x0 = _util.asarray_1d(x0)[:2]  # ignore z-components
    n0 = _util.asarray_1d(n0)[:2]
    grid = _util.as_xyz_components(grid)
    dx = grid[:2] - x0

    r = _np.linalg.norm(dx)
    p = 1j*k/4 * _special.hankel2(1, k * r) * _np.inner(dx, n0) / r
    return _duplicate_zdirection(p, grid)
Ejemplo n.º 38
0
def line_velocity(omega, x0, grid, *, c=None, rho0=None):
    """Velocity of line source parallel to the z-axis.

    Returns
    -------
    `XyzComponents`
        Particle velocity at positions given by *grid*.

    Examples
    --------
    The particle velocity can be plotted on top of the sound pressure:

    .. plot::
        :context: close-figs

        v = sfs.fd.source.line_velocity(omega, x0, vgrid)
        sfs.plot2d.amplitude(p * normalization_line, grid)
        sfs.plot2d.vectors(v * normalization_line, vgrid)
        plt.title("Sound Pressure and Particle Velocity")

    """
    if c is None:
        c = _default.c
    if rho0 is None:
        rho0 = _default.rho0
    k = _util.wavenumber(omega, c)
    x0 = _util.asarray_1d(x0)[:2]  # ignore z-component
    grid = _util.as_xyz_components(grid)

    offset = grid[:2] - x0
    r = _np.linalg.norm(offset)
    v = -1/(4 * c * rho0) * _special.hankel2(1, k * r)
    v = [v * o / r for o in offset]

    assert v[0].shape == v[1].shape

    if len(grid) > 2:
        v.append(_np.zeros_like(v[0]))

    return _util.XyzComponents([_duplicate_zdirection(vi, grid) for vi in v])
Ejemplo n.º 39
0
def line_dipole(omega, x0, n0, grid, c=None):
    """Line source with dipole characteristics parallel to the z-axis.

    Note: third component of x0 is ignored.

    ::

                           (2)
        G(x-x0, w) = jk/4 H1  (w/c |x-x0|) cos(phi)


    """
    k = util.wavenumber(omega, c)
    x0 = util.asarray_1d(x0)
    x0 = x0[:2]  # ignore z-component
    n0 = n0[:2]
    grid = util.asarray_of_arrays(grid)
    dx = grid[:2] - x0
    r = np.linalg.norm(dx)
    p = 1j*k/4 * special.hankel2(1, k * r) * np.inner(dx, n0) / r
    p = _duplicate_zdirection(p, grid)
    return np.squeeze(p)
Ejemplo n.º 40
0
def line(omega, x0, n0, grid, c=None):
    """Line source parallel to the z-axis.

    Note: third component of x0 is ignored.

    ::

                           (2)
        G(x-x0, w) = -j/4 H0  (w/c |x-x0|)

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

        p_line = sfs.mono.source.line(omega, x0, None, grid)
        sfs.plot.soundfield(p_line, grid)
        plt.title("Line Source at {} m".format(x0[:2]))

    Normalization ...

    .. plot::
        :context: close-figs

        p_line *= np.exp(-1j*7*np.pi/4) / np.sqrt(1/(8*np.pi*omega/sfs.defs.c))
        sfs.plot.soundfield(p_line, grid)
        plt.title("Line Source at {} m (normalized)".format(x0[:2]))

    """
    k = util.wavenumber(omega, c)
    x0 = util.asarray_1d(x0)
    x0 = x0[:2]  # ignore z-component
    grid = util.asarray_of_arrays(grid)

    r = np.linalg.norm(grid[:2] - x0)
    p = -1j/4 * special.hankel2(0, k * r)
    p = _duplicate_zdirection(p, grid)
    return np.squeeze(p)
Ejemplo n.º 41
0
def nfchoa_2d_plane(omega, x0, r0, n=[0, 1, 0], max_order=None, c=None):
    r"""Plane wave by two-dimensional NFC-HOA.

    .. 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 http://sfstoolbox.org/#equation-D.nfchoa.pw.2D.

    """
    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]
    M = _max_order_circular_harmonics(len(x0), max_order)
    d = 0
    for m in range(-M, M + 1):
        d += 1j**-m / hankel2(m, k * r0) * np.exp(1j * m * (phi0 - phi))
    return -2j / (np.pi*r0) * d
Ejemplo n.º 42
0
def hankel2p(m, z):
    return hankel2(m - 1, z) - hankel2(m, z) * m / z
Ejemplo n.º 43
0
def hankel(j, nu, z):
    if j==1:
        return hankel1(nu, z)
    elif j==2:
        return hankel2(nu, z)
    raise ValueError("j must be either 1 or 2")
Ejemplo n.º 44
0
	
	
if __name__ == '__main__':
	mesh = [25, 50, 100, 200, 300,500,1000,2000]
	convergence = np.zeros((0,2))
	for nPoints in mesh:
		y = homoCircle(nPoints, 1.0, 2.0, 1.0, 1.0, 1)
		scatMat = y.computeScatteringMatrix(y.Mmax)
	
		analScatMat = np.zeros(2*y.Mmax+1, dtype=complex)
		zc = y.nc*y.k
		zo = y.no*y.k
		eta = y.nc/y.no
		for i in range(2*y.Mmax+1):
			m = i-y.Mmax
			num = -(eta*jvp(m,zc)*hankel2(m,zo)-jn(m,zc)*h2vp(m,zo))
			den = eta*jvp(m,zc)*hankel1(m,zo)-jn(m,zc)*h1vp(m,zo)
			analScatMat[i] = num/den
		err = np.amax(np.abs(np.diag(analScatMat)-scatMat))
		print(err)
		print(analScatMat)

		# -- Mean areas of triangles
		convergence = np.insert(convergence, len(convergence), [np.mean(y.areas), err],axis=0)

	fig1 = plt.figure(figsize=(5,3))
	ax1 = fig1.add_subplot(111)
	plt.plot(convergence[:,0],convergence[:,1], ls='--', marker='o', label=r"Numerical Error")

	p = np.polyfit(np.log(convergence[:,0]),np.log(convergence[:,1]),1)
	ynew = np.exp(np.polyval(p,np.log(convergence[:,0])))
Ejemplo n.º 45
0
def line_dirichlet_edge(omega, x0, grid, alpha=3/2*np.pi, Nc=None, c=None):
    """Line source scattered at an edge with Dirichlet boundary conditions.

    :cite:`Moser2012`, eq.(10.18/19)

    Parameters
    ----------
    omega : float
        Angular frequency.
    x0 : (3,) array_like
        Position of line source.
    grid : triple of array_like
        The grid that is used for the sound field calculations.
        See `sfs.util.xyz_grid()`.
    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
    -------
    numpy.ndarray
        Complex pressure at grid positions.

    """
    k = util.wavenumber(omega, c)
    x0 = util.asarray_1d(x0)
    phi_s = np.arctan2(x0[1], x0[0])
    if phi_s < 0:
        phi_s = phi_s + 2*np.pi
    r_s = np.linalg.norm(x0)

    grid = util.XyzComponents(grid)

    r = np.linalg.norm(grid[:2])
    phi = np.arctan2(grid[1], grid[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

    p = np.zeros((grid[0].shape[1], grid[1].shape[0]), dtype=complex)
    idxr = (r <= r_s)
    idxa = (phi <= alpha)
    for m in np.arange(Nc):
        nu = m*np.pi/alpha
        f = 1/epsilon[m] * np.sin(nu*phi_s) * np.sin(nu*phi)
        p[idxr & idxa] = p[idxr & idxa] + f[idxr & idxa] * \
            special.jn(nu, k*r[idxr & idxa]) * special.hankel2(nu, k*r_s)
        p[~idxr & idxa] = p[~idxr & idxa] + f[~idxr & idxa] * \
            special.jn(nu, k*r_s) * special.hankel2(nu, k*r[~idxr & idxa])

    p = p * -1j*np.pi/alpha

    pl = line(omega, x0, None, grid, c=c)
    p[~idxa] = pl[~idxa]

    return p
Ejemplo n.º 46
0
def ratioHankelFunctions(m1, m2, z):
  return hankel2(m2,z)/hankel1(m1,z)
Ejemplo n.º 47
0
rt = np.sqrt(rti/pi)
print(dt*180/pi,rti,rt)
    
theta = np.linspace(0,2*pi - dt, nodeTot)

r = rd * np.sqrt( 
                ( np.cos(theta[0]) - np.cos(theta) )**2 +
                ( np.sin(theta[0]) - np.sin(theta) )**2
                )

## build coefficient matrix
r = linalg.toeplitz(r)

z = 1j  * pi**2 * rt * (er - 1) * (
                                    special.jv(1, 2*pi*rt) * 
                                    special.hankel2(0, 2 * pi * r)
                                  ) 

#diagonal
di = np.diag_indices(nodeTot)

z[di] = 1 + (er-1) * .5j * ( 2 * pi**2 * rt * special.hankel2(1, 2*pi*rt) - 2j )

cv = ei * np.exp(-2j * pi * rd * np.cos(theta))


# plt.matshow(np.imag(z))

#solve for field
e = linalg.solve(z, cv)
Ejemplo n.º 48
0
def sMatrixElementCoefficients(k,n1,n2,m):
  A = -n1*hankel2(m,n2*k)*jvp(m,n1*k)+n2*jn(m,n1*k)*h2vp(m,n2*k)
  B = n1*hankel1(m,n2*k)*jvp(m,n1*k)-n2*jn(m,n1*k)*h1vp(m,n2*k)
  Ap = -n1*n1*jvp(m,n1*k,2)*hankel2(m,n2*k)+n2*n2*jn(m,n1*k)*h2vp(m,n2*k,2)
  Bp = n1*n1*jvp(m,n1*k,2)*hankel1(m,n2*k)-n2*n2*jn(m,n1*k)*h1vp(m,n2*k,2)
  return A, B, Ap, Bp
Ejemplo n.º 49
0
def hankel2d(n, z):
    """Derivative of hankel2 (from Wolfram MathWorld)"""
    return 0.5 * (hankel2(n-1, z) - hankel2(n+1, z))
Ejemplo n.º 50
0
def p_cmpx(r,t):
    return ( 1j*rho_0*c*u_0 * hankel2(0,r*k) / hankel2(1,a*k) ) * exp(1j*w*t)
Ejemplo n.º 51
0
def u_cmpx(r,t):
    return ( u_0 * hankel2(1,r*k) / hankel2(1,a*k) ) * exp(1j*w*t)