Beispiel #1
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])
Beispiel #2
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])
Beispiel #3
0
def cluster_coefficients(positions, p_scat, k, origin, lmax=None):
    """Solve for the cluster scattering coefficients of N particles around an origin

    Arguments:
        positions[N,3]   particle positions
        p_scat[N,2,rmax]   scattering coefficients 
        k                medium wavenumber
        origin           position around which to calculate the cluster coefficients
        lmax             (optional) compute scattering for up to lmax terms (default: lmax of input p/q)
    """

    Nparticles = positions.shape[0]
    rmax_in = p_scat.shape[-1]
    lmax_in = vsh.rmax_to_lmax(rmax_in)

    if lmax is None:
        lmax = lmax_in

    rmax = vsh.lmax_to_rmax(lmax)
    p_cluster = np.zeros([2, rmax], dtype=complex)

    for i in range(Nparticles):
        if np.all(positions[i] == origin):
            p_cluster[0, :rmax_in] += p_scat[i, 0, :rmax_in]
            p_cluster[1, :rmax_in] += p_scat[i, 1, :rmax_in]
            continue

        rij = origin - positions[i]
        rad, theta, phi = coordinates.cart_to_sph(*rij)

        for r, n, m in vsh.mode_indices(lmax):
            for rp, v, u in vsh.mode_indices(lmax_in):
                a = p_scat[i, 0, rp]
                b = p_scat[i, 1, rp]

                A, B = vsh.vsh_translation(m, n, u, v, rad, theta, phi, k,
                                           vsh.vsh_mode.incident)

                p_cluster[0, r] += a * A + b * B
                p_cluster[1, r] += a * B + b * A

    return p_cluster