Example #1
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
Example #2
0
def besselh_derivative(n, k, z):
    """ Derivative of besselh
    """
    if k == 2:
        return special.h2vp(n,z)
    elif 0 == 1:
        return special.h1vp(n,z)
    else:
        raise TypeError("Only second or first kind.")
Example #3
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)
Example #4
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
Example #5
0
def circ_radial_weights(N, kr, setup):
    r"""Radial weighing functions.

    Computes the radial weighting functions for diferent array types

    For instance for an rigid array

    .. math::

        b_n(kr) = J_n(kr) - \frac{J_n^\prime(kr)}{H_n^{(2)\prime}(kr)}H_n^{(2)}(kr)

    Parameters
    ----------
    N : int
        Maximum order.
    kr : (M,) array_like
        Wavenumber * radius.
    setup : {'open', 'card', 'rigid'}
        Array configuration (open, cardioids, rigid).

    Returns
    -------
    bn : (M, 2*N+1) numpy.ndarray
        Radial weights for all orders up to N and the given wavenumbers.

    """
    kr = util.asarray_1d(kr)
    n = np.arange(N + 1)
    Bns = np.zeros((len(kr), N + 1), dtype=complex)
    for i, x in enumerate(kr):
        Jn = special.jv(n, x)
        if setup == 'open':
            bn = Jn
        elif setup == 'card':
            bn = Jn - 1j * special.jvp(n, x, n=1)
        elif setup == 'rigid':
            if x == 0:
                # Hn(x)/Hn'(x) -> 0 for x -> 0
                bn = Jn
            else:
                Jnd = special.jvp(n, x, n=1)
                Hn = special.hankel2(n, x)
                Hnd = special.h2vp(n, x)
                bn = Jn - Jnd / Hnd * Hn
        else:
            raise ValueError('setup must be either: open, card or rigid')
        Bns[i, :] = bn
    Bns = np.concatenate((Bns, (Bns * (-1)**np.arange(N + 1))[:, :0:-1]),
                         axis=-1)
    return np.squeeze(Bns)
Example #6
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
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
Example #8
0
#omega = np.linspace(0,2*np.pi*Fs,n)

epsilon = 1 / (0.2 * n * t)
omega = 2 * np.pi * freq[0:n // 2 + 1] - 1j * epsilon

k = omega / bbeta
pome = 2 * np.pi * 0.1
R = 2 * omega**2 / (np.pi**0.5 * pome**3) * np.exp(-omega**2 / pome**2)

for m in range(-N, N + 1):
    print('m=', m)
    alpha = -spf.jvp(m, k * a) / spf.yvp(m, k * a)
    beta = (spf.jv(m, k * rs) + alpha * spf.yv(m, k * rs)) / spf.hankel2(
        m, k * rs)
    c1 = (spf.jvp(m, k * rs) + alpha * spf.yvp(m, k * rs) -
          beta * spf.h2vp(m, k * rs))**(-1) / (k * mu * 2 * np.pi * rs) * R
    c2 = alpha * c1
    c3 = beta * c1
    if r < a:
        disp_m = 0
    elif r >= a and r < rs:
        disp_m = c1 * spf.jv(m, k * r) + c2 * spf.yv(m, k * r)
    elif rs <= r:
        disp_m = c3 * spf.hankel2(m, k * r)
    disp_m = np.append(disp_m, np.conj(disp_m[::-1][0:-1]))
    disp_t = np.fft.ifft(disp_m) * np.exp(epsilon * T)

    U = U + disp_t * np.exp(1j * m * theta)

plt.plot(T, U.real)
print('First arrival should be %.2f' % arrival, ' (s)')
Example #9
0
def cylindrical_scatterer(mic_dirs_rad, src_dirs_rad, R, N_order, N_filt, fs):
    """
    Compute the pressure due to a cylindrical scatterer

    The function computes the impulse responses of the pressure measured
    at some points in the field with a cylindrical rigid scatterer centered
    at the origin and due to incident plane waves.

    Parameters
    ----------
    mic_dirs_rad: ndarray
        Position of microphone capsules. Dimension = (N_mic, C-1).
        Positions are expected in radians, expressed in pairs [azimuth, distance].
    src_dirs_rad: ndarray
        Direction of arrival of the indicent plane waves. Dimension = (N_doa).
        Directions (azimuths) are expected in radians.
    R: float
        Radius of the array sphere, in meter.
    N_order: int
        Maximum cylindrical harmonic expansion order.
    N_filt : int
        Number of frequencies where to compute the response. It must be even.
    fs: int
        Sample rate.

    Returns
    -------
    h_mic: ndarray
        Computed IRs in time-domain. Dimension = (N_filt, Nmic, Ndoa)
    H_mic: ndarray, dtype='complex'
        Frequency responses of the computed IRs. Dimension = (N_filt//2+1, N_mic, N_doa).

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

    """

    _validate_ndarray_2D('mic_dirs_rad', mic_dirs_rad, shape1=masp.C - 1)
    _validate_ndarray_1D('src_dirs_rad', src_dirs_rad)
    _validate_float('R', R, positive=True)
    _validate_int('N_order', N_order, positive=True)
    _validate_int('N_filt', N_filt, positive=True, parity='even')
    _validate_int('fs', fs, positive=True)
    if np.any(mic_dirs_rad[:, 1] < R):
        raise ValueError(
            'mic_dirs_rad: The distance of the measurement point cannot be less than the radius:'
            + str(R))

    K = N_filt // 2 + 1
    f = np.arange(K) * fs / N_filt
    kR = 2 * np.pi * f * R / masp.c
    N_mic = mic_dirs_rad.shape[0]
    N_doa = src_dirs_rad.size

    # Check if all microphones at same radius
    same_radius = np.sum(mic_dirs_rad[1:, 1] - mic_dirs_rad[:-1, 1]) == 0
    if same_radius:
        # Cylindrical modal coefs for rigid sphere
        b_N = np.zeros((K, N_order + 1), dtype='complex')
        r = mic_dirs_rad[0, 1]
        kr = 2 * np.pi * f * r / masp.c

        # Similar to the cyl_modal_coefs for the rigid case
        for n in range(N_order + 1):
            jn = jv(n, kr)
            jnprime = jvp(n, kR, 1)
            hn = hankel2(n, kr)
            hnprime = h2vp(n, kR, 1)
            b_N[:, n] = np.power(1j, n) * (jn - (jnprime / hnprime) * hn)

    else:
        # Cylindrical modal coefs for rigid cylinder, but at different distances
        b_N = np.zeros((K, N_order + 1, N_mic), dtype='complex')
        for nm in range(N_mic):
            r = mic_dirs_rad[nm, 1]
            kr = 2 * np.pi * f * r / masp.c

            # Similar to the sph_modal_coefs for the rigid case
            for n in range(N_order + 1):
                jn = jv(n, kr)
                jnprime = jvp(n, kR, 1)
                hn = hankel2(n, kr)
                hnprime = h2vp(n, kR, 1)
                b_N[:, n,
                    nm] = np.power(1j, n) * (jn - (jnprime / hnprime) * hn)

    # Avoid NaNs for very high orders, instead of (very) very small values
    b_N[np.isnan(b_N)] = 0.

    # Compute angular-dependent part of the microphone responses
    H_mic = np.zeros((K, N_mic, N_doa), dtype='complex')
    for nd in range(N_doa):
        # Unit vectors of DOAs and microphones
        azi0 = src_dirs_rad[nd]
        azi = mic_dirs_rad[:, 0]
        angle = azi - azi0

        C = np.zeros((N_order + 1, N_mic))
        for n in range(N_order + 1):
            # Jacobi-Anger expansion
            if n == 0:
                C[n, :] = np.ones(angle.shape)
            else:
                C[n, :] = 2 * np.cos(n * angle)
        # Accumulate across orders
        if same_radius:
            H_mic[:, :, nd] = np.matmul(b_N, C)
        else:
            for nm in range(N_mic):
                H_mic[:, nm, nd] = np.matmul(b_N[:, :, nm], C[:, nm])

    # Handle Nyquist for real impulse response
    tempH_mic = H_mic.copy()
    # TODO: in `simulate_sph_array()` it was real, not abs. Why?
    tempH_mic[-1, :] = np.abs(tempH_mic[-1, :])
    # Conjugate ifft and fftshift for causal IR
    h_mic = np.real(
        np.fft.fftshift(np.fft.ifft(np.append(tempH_mic,
                                              np.conj(tempH_mic[-2:0:-1, :]),
                                              axis=0),
                                    axis=0),
                        axes=0))

    return h_mic, H_mic
Example #10
0
                  ],
                  [
                      spf.jvp(m, k0 * a1),
                      spf.yvp(m, k0 * a1),
                      -mu1 / mu0 * bbeta0 / bbeta1 * spf.jvp(m, k1 * a1),
                      -mu1 / mu0 * bbeta0 / bbeta1 * spf.yvp(m, k1 * a1), 0
                  ],
                  [
                      0, 0,
                      spf.jn(m, k1 * rs),
                      spf.yn(m, k1 * rs), -spf.hankel2(m, k1 * rs)
                  ],
                  [
                      0, 0,
                      spf.jvp(m, k1 * rs),
                      spf.yvp(m, k1 * rs), -spf.h2vp(m, k1 * rs)
                  ]])

    b = [0, 0, 0, 0, 1 / (mu1 * k1 * 2 * np.pi * rs)]
    c = np.dot(inv(A), b)

    disp0_m = c[0] * spf.jn(m, k0 * R[:, i_a0:i_a1]) + c[1] * spf.yn(
        m, k0 * R[:, i_a0:i_a1])
    disp1_m = c[2] * spf.jn(m, k1 * R[:, i_a1:i_rs]) + c[3] * spf.yn(
        m, k1 * R[:, i_a1:i_rs])
    disp2_m = c[4] * spf.hankel2(m, k1 * R[:, i_rs:-1])

    disp_m[:, i_a0:i_a1] = disp0_m
    disp_m[:, i_a1:i_rs] = disp1_m

    dis1_ratio = np.linalg.norm(disp1_m[:, 0] - disp0_m[:, -1],
Example #11
0
U = np.zeros(np.shape(T))

#omega = np.linspace(0,2*np.pi*Fs,n)

epsilon = 1/(0.2*n*t)
omega = 2*np.pi*freq[0:n//2+1]-1j*epsilon

k = omega/bbeta
pome = 2*np.pi*1
R = 2*omega**2/(np.pi**0.5*pome**3)*np.exp(-omega**2/pome**2)


for m in range(-N,N+1):
    print('m=',m)    
    alpha = spf.jv(m,k*rs)/spf.hankel2(m,k*rs)
    c1 = (alpha*spf.h2vp(m,k*rs)-spf.jvp(m,k*rs))**(-1)/(k*mu*2*np.pi*rs)*R
    c2 = alpha*c1      
    if r<a:
        disp_m = 0
    elif r>=a and r<rs:
        disp_m = c1*spf.jv(m,k*r)
        
    elif rs<=r:
        disp_m = c2*spf.hankel2(m,k*r)
        
    disp_m = np.append(disp_m,np.conj(disp_m[::-1][0:-1]))
    disp_t = np.fft.ifft(disp_m)*np.exp(epsilon*T)
    
    U = U + disp_t*np.exp(1j*m*theta)
    
plt.plot(T,U.real)
Example #12
0
X = R * np.cos(Th)
Y = R * np.sin(Th)
U = np.zeros(np.shape(X))

sig1 = (R < rs)
sig2 = (R >= rs)

U = np.zeros(np.shape(X))
mlist = list(range(-N, N + 1))

k = omega / bbeta

for m in mlist:
    print('m=', m)
    alpha = spf.jn(m, k * rs) / spf.hankel2(m, k * rs)
    c1 = (alpha * spf.h2vp(m, k * rs) -
          spf.jvp(m, k * rs))**(-1) / (k * mu * 2 * np.pi * rs)

    c2 = alpha * c1
    disp1_m = c1 * spf.jn(m, k * R)
    disp2_m = c2 * spf.hankel2(m, k * R)

    disp_m = disp1_m * sig1.astype(int) + disp2_m * sig2.astype(int)

    U = U + disp_m * np.exp(1j * m * Th)

plt.contourf(X, Y, abs(U))

plt.colorbar()
plt.show()
	
	
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])))
Example #14
0
def radial_velocity_expansion(k, coefficients, z0, radius, theta):
    return (1j * sum(coef * h2vp(n, k * radius) * np.cos(n * theta)
                     for coef, n in zip(coefficients, count())) / z0)
Example #15
0
Y = R*np.sin(Th)
U = np.zeros(np.shape(X)) 

sig1 = (R>=a)*(R<rs)
sig2 = (R>=rs)

U = np.zeros(np.shape(X))
mlist = list(range(-N,N+1))

k = omega/bbeta

for m in mlist:
    print('m=',m)
    alpha = -spf.jvp(m,k*a)/spf.yvp(m,k*a)
    beta = (spf.jn(m,k*rs)+alpha*spf.yn(m,k*rs))/spf.hankel2(m,k*rs)
    c1 = (spf.jvp(m,k*rs)+alpha*spf.yvp(m,k*rs)-beta*spf.h2vp(m,k*rs))**(-1)/(k*mu*2*np.pi*rs)
    c2 = alpha*c1
    c3 = beta*c1
    disp1_m = c1*spf.jn(m,k*R)+c2*spf.yn(m,k*R)
    disp2_m = c3*spf.hankel2(m,k*R)
    disp_m = disp1_m*sig1.astype(int)+disp2_m*sig2.astype(int)
    
    U = U + disp_m*np.exp(1j*m*Th)


    
#    alpha = -spf.h1vp(m,k*a)/spf.h2vp(m,k*a)
#    beta = (spf.hankel1(m,k*rs)+alpha*spf.hankel2(m,k*rs))/spf.hankel2(m,k*rs)
#    c1 = (spf.h1vp(m,k*rs)+alpha*spf.h2vp(m,k*rs)-beta*spf.h2vp(m,k*rs))**(-1)/(k*mu*2*np.pi*rs)
#    c2 = alpha*c1
#    c3 = beta*c1