Пример #1
0
def integral_project_fields_onto(E,
                                 r,
                                 k,
                                 ftype,
                                 n,
                                 m,
                                 mode=vsh.vsh_mode.outgoing,
                                 spherical=False):
    """Project fields onto a given mode using integral method

    Arguments:
        E[3,Ntheta,Nphi]     electric field values on the surface of a sphere
        r                    radius
        k                    wavenumber
        ftype                'electric' or 'magnetic'
        n                    vsh order (1, 2, ...)
        m                    vsh orientation (-n, -n+1, ..., n)
        mode: vsh_mode       type of VSH (outgoing, incident) (default: outgoing)
        spherical            If true, E should be in spherical components (default: False (cartesian))
    """
    Ntheta, Nphi = E.shape[1:]
    sampling = Ntheta
    THETA, PHI = coordinates.sphere_mesh(sampling)

    tau = np.linspace(-1, 1, sampling)
    phi = np.linspace(0, 2 * np.pi, 2 * sampling)

    N, M = vsh.VSH(n, m, mode)
    if ftype == 'electric':
        base_function = N
    elif ftype == 'magnetic':
        base_function = M

    vsh_data = base_function(r, THETA, PHI, k).squeeze()

    if not spherical:
        E = coordinates.vec_cart_to_sph(E, THETA, PHI)

    Emn_val = vsh.Emn(m, n)

    if mode == vsh.vsh_mode.outgoing:
        factor = 1 / (1j * Emn_val)
    elif mode in (vsh.vsh_mode.incident, vsh.vsh_mode.ingoing):
        factor = -1 / (1j * Emn_val)
    else:
        raise ValueError(
            '{mode} is not a valid type of mode'.format(mode=mode))

    norm = vsh.vsh_normalization_values(mode, ftype, n, m, r, k)

    proj_data = np.sum(E * np.conj(vsh_data), axis=0)
    integrated = vsh.misc.trapz_2d(tau, phi, proj_data)

    return factor * integrated / norm
Пример #2
0
def integral_project_source_far(src, k, lmax, sampling=20, theta_0=np.pi / 2):
    """Decompose a source object into VSHs using integral method in the far-field
    Returns p[2,rmax]

    Arguments:
        src        source object
        k          wavenumber
        lmax       maximum number of multipoles
        sampling   number of points to sample between 0 and pi (default: 20)
        theta_0    integral performed from theta_0 to pi (default: pi/2)
    """
    rmax = vsh.lmax_to_rmax(lmax)

    theta = np.linspace(theta_0, np.pi, sampling)
    phi = np.linspace(0, 2 * np.pi, 2 * sampling)
    THETA, PHI = np.meshgrid(theta, phi, indexing='ij')
    rad = 1
    rhat, *_ = coordinates.sph_basis_vectors(THETA, PHI)
    Esrc = src.angular_spectrum(THETA, PHI, k) * np.exp(-1j * k) / rad

    p0 = np.zeros((2, rmax) + THETA.shape, dtype=complex)
    E0 = src.E0(k) * np.exp(1j * src.phase)

    for i, n, m in vsh.mode_indices(lmax):
        Emn_val = vsh.Emn(m, n)
        factor = E0 * k**2 * 1j**(2 - n) * np.abs(Emn_val) / (4 * np.pi)
        N, M = vsh.VSH_far(n, m, vsh.vsh_mode.ingoing)

        E = N(rad, THETA, PHI, k)
        U = np.sum(Esrc * np.conjugate(E), axis=0) * np.sin(THETA)
        integrand = U * rad**2
        p0[0, i] = 2 * factor * integrand

        E = M(rad, THETA, PHI, k)
        U = np.sum(Esrc * np.conjugate(E), axis=0) * np.sin(THETA)
        integrand = U * rad**2
        p0[1, i] = 2 * factor * integrand

    def f(origin):
        p = np.zeros([2, rmax], dtype=complex)

        phase = k * np.einsum('i...,i', rhat, -origin)
        exp_phase = np.exp(1j * phase)

        for i in range(rmax):
            p[0, i] = vsh.misc.trapz_2d(theta, phi, p0[0, i] * exp_phase)
            p[1, i] = vsh.misc.trapz_2d(theta, phi, p0[1, i] * exp_phase)

        return p

    return f
Пример #3
0
def far_field_point_matching(source, position, radius, k, lmax, sampling=6):
    """Decompose a source into VSHs using the point matching method in the far field
       Returns p_src[2,rmax]
       
       Arguments:
           source      source object
           position    position around which to decompose
           radius      radius of sphere for sampling the source field
           k           medium wavenumber
           lmax        maximum number of multipoles
           sampling    angular points sampled per pi radians (default: 5)
    """
    position = np.asarray(position)

    points = sample_sphere_point_matching(position, radius, sampling)
    Npoints = points.shape[1]
    X = points[0]
    Y = points[1]
    Z = points[2]
    _, THETA, PHI = coordinates.cart_to_sph(X, Y, Z, origin=position)

    rmax = vsh.lmax_to_rmax(lmax)

    E_src = np.zeros([2, Npoints], dtype=complex)
    E_vsh = np.zeros([2, Npoints, 2, rmax], dtype=complex)

    # fields in the upper-hemisphere are zero
    idx = THETA >= np.pi / 2
    E_src[:, idx] = source.spherical_ingoing(THETA[idx], PHI[idx], k)

    # phase correction for moving away from the center of the source
    rhat, *_ = coordinates.sph_basis_vectors(THETA, PHI)
    delta = source.center - position
    phase = k * np.einsum('ij,i', rhat, delta)
    E_src *= np.exp(1j * phase)

    for i, n, m in vsh.mode_indices(lmax):
        Nfunc, Mfunc = vsh.VSH(n, m, mode=vsh.vsh_mode.ingoing)
        Emn_val = vsh.Emn(m, n)
        E_vsh[..., 0, i] = -1j * Emn_val * Nfunc(radius, THETA, PHI, k)[1:]
        E_vsh[..., 1, i] = -1j * Emn_val * Mfunc(radius, THETA, PHI, k)[1:]

    column = E_src.reshape([2 * Npoints])
    matrix = E_vsh.reshape([2 * Npoints, 2 * rmax])
    sol = np.linalg.lstsq(matrix, column, rcond=None)
    p_src = sol[0]

    return np.reshape(p_src, [2, rmax])
Пример #4
0
    def f(rad, theta, phi):
        (rad, theta, phi) = map(lambda A: np.asarray(A, dtype=float),
                                (rad, theta, phi))
        E_sph = np.zeros(shape=(3, ) + theta.shape, dtype=complex)

        for i, n, m in vsh.mode_indices(lmax):
            Nfunc, Mfunc = vsh.VSH(n, m, mode=mode)

            Emn_val = vsh.Emn(m, n)

            N = Nfunc(rad, theta, phi, k)
            M = Mfunc(rad, theta, phi, k)

            E_sph += factor * Emn_val * (p[0, i] * N + p[1, i] * M)

        return E_sph
Пример #5
0
def near_field_point_matching(source, position, size, k, lmax, sampling):
    """Decompose a source into VSHs using the point matching method in the near field
       Returns p_src[2,rmax]
       
       Arguments:
           source      source object
           position    position around which to decompose
           size        size of xy planar region to perform point matching over
           k           medium wavenumber
           lmax        maximum number of multipoles
           sampling    number of sampling points along a dimension
    """
    points = sample_plane_point_matching(position, size, sampling)
    Npoints = points.shape[1]
    X = points[0]
    Y = points[1]
    Z = points[2]
    RAD, THETA, PHI = coordinates.cart_to_sph(X, Y, Z + 1e-9, origin=position)

    rmax = vsh.lmax_to_rmax(lmax)

    E_src = source.E_field(X, Y, Z, k)[:2]
    H_src = source.H_field(X, Y, Z, k)[:2]
    # TODO: is this true?
    # H_src = E_src[::-1]
    E_vsh = np.zeros([2, Npoints, 2, rmax], dtype=complex)

    for i, n, m in vsh.mode_indices(lmax):
        Nfunc, Mfunc = vsh.VSH(n, m, mode=vsh.vsh_mode.incident)
        Emn_val = vsh.Emn(m, n)
        E_vsh[..., 0, i] = -1j * Emn_val * coordinates.vec_sph_to_cart(
            Nfunc(RAD, THETA, PHI, k), THETA, PHI)[:2]
        E_vsh[..., 1, i] = -1j * Emn_val * coordinates.vec_sph_to_cart(
            Mfunc(RAD, THETA, PHI, k), THETA, PHI)[:2]

    H_vsh = -1j * E_vsh[..., ::-1, :]

    column = np.concatenate([E_src.reshape([-1]), H_src.reshape([-1])])
    matrix = np.concatenate(
        [E_vsh.reshape([-1, 2 * rmax]),
         H_vsh.reshape([-1, 2 * rmax])])
    sol = np.linalg.lstsq(matrix, column, rcond=None)
    p_src = sol[0]

    return np.reshape(p_src, [2, rmax])
Пример #6
0
    def f(rad, theta, phi):
        (rad, theta, phi) = map(lambda A: np.asarray(A, dtype=float),
                                (rad, theta, phi))

        E_sph = np.zeros(shape=(3, ) + theta.shape, dtype=complex)
        factor = np.exp(1j * k * rad) / (k * rad)

        for i, n, m in vsh.mode_indices(lmax):
            Emn_val = vsh.Emn(m, n)

            pi = vsh.special.pi_func(n, m, theta)
            tau = vsh.special.tau_func(n, m, theta)

            E_sph[1] += 1j * factor * Emn_val * (-1j)**(n) * (
                p_scat[0, i] * tau + p_scat[1, i] * pi) * np.exp(1j * m * phi)
            E_sph[2] += -factor * Emn_val * (-1j)**(n) * (
                p_scat[0, i] * pi + p_scat[1, i] * tau) * np.exp(1j * m * phi)

        return E_sph