Пример #1
0
def polarizability_CM(d, m):
    """Calculates Clausius-Mossoti polarizability of dipoles.

    Calcualtes Clausius-Mossoti Polarizability of dipole array according
    to their refractive indexes `m` and lattice spacing `d`.

    Parameters
    ----------
    d : float
        Dipole lattice spacing
    m : array_like
        List of dipole refractive indexes
    Returns
    -------
    alph: list
        List of dipole polarizabilities
    Notes
    -----
    Currently only supports isotropic polarizabilities,
    extending to anisotropic polarizabilities should be trivial,

    References
    ----------
    .. [1] Purcell, Edward M., and Carlton R. Pennypacker.
    "Scattering and absorption of light by nonspherical dielectric grains."
    The Astrophysical Journal 186 (1973): 705-714.

    """

    pow2 = misc.power_function(2)
    pow3 = misc.power_function(3)

    N = m.size
    msqr = pow2(m)
    dcube = pow3(d)

    alpha_CM = numpy.divide(
        numpy.multiply(msqr - 1, 3 * dcube / (4 * numpy.pi)),
        (msqr + 2))  # Clausius-Mossotti

    alph = numpy.zeros([3 * N], dtype=numpy.complex128)

    # assuming same polarizability in x, y & z directions
    for j in range(N):
        alph[3 * (j - 1) + 0] = alpha_CM[j]
        alph[3 * (j - 1) + 1] = alpha_CM[j]
        alph[3 * (j - 1) + 2] = alpha_CM[j]

    return alph
Пример #2
0
def objective_collection(k, dipoles, P, NA, dist, samples=15):
    pow2 = misc.power_function(2)

    weights, r, theta = disk_quadrature.disk_quadrature_rule(samples, samples)

    alpha = numpy.arcsin(NA)
    maxradius = numpy.tan(alpha)*dist
    r *= maxradius

    rE = numpy.zeros([pow2(samples), 3])
    for n in range(samples):
        for m in range(samples):
            rE[n*samples + m, 0] = numpy.sqrt(pow2(dist) + pow2(r[n]))
            rE[n*samples + m, 1] = theta[m]
            rE[n*samples + m, 2] = numpy.arctan(r[n]/dist)

    # calculate scattered field as a function of angles

    Esca = numpy.zeros([pow2(samples), 3], dtype=numpy.complex128)
    for ix, r_e in enumerate(rE):
        r_E = numpy.zeros(3)
        r_E[0], r_E[1], r_E[2] = misc.rtp2xyz(r_e[0], r_e[1], r_e[2])
        Esca[ix, 0], Esca[ix, 1], Esca[ix, 2] = dda_funcs.E_sca_FF(k, dipoles, P, r_E)

    weights /= numpy.pi * pow2(maxradius)

    I = 0
    for n in range(samples):
        for m in range(samples):
            I += pow2(k) * (rE[n*samples + m, 0]).T * numpy.dot(Esca[n*samples + m].conj(), Esca[n*samples + m])*weights[n]
    return I
Пример #3
0
def evanescent_E(E1s, E1p, theta_1, n1, n2):
    # E1p : TM E-field amplitude
    # E1s : TE E-field amplitude
    # theta_1 : incident angle
    # n1 : substrate reflective index
    # n2 : reflective index of the medium above the substrate, e.g., air
    # k2 : wave vector above the substrate
    # E2p : TM E-field vector
    # E2s : TE E-field vector

    pow2 = misc.power_function(2)

    k2, ep, es = evanescent_k_e(theta_1, n1, n2)

    T2s = (2 * n1 * numpy.cos(theta_1)) / (
        n1 * numpy.cos(theta_1) +
        numpy.sqrt(pow2(n2) - pow2(n1 * numpy.sin(theta_1)) + 0j)) * E1s
    T2p = (2 * n1 * numpy.cos(theta_1)) / (
        n2 * numpy.cos(theta_1) + (n1 / n2) *
        numpy.sqrt(pow2(n2) - pow2(n1 * numpy.sin(theta_1)) + 0j)) * E1p

    E2s = es * T2s
    E2p = ep * T2p

    return k2, E2s, E2p
Пример #4
0
def objective_collection_si(k, dipoles, P, n1, NA, dist, samples=15):
    pow2 = misc.power_function(2)

    weights, r, theta = disk_quadrature.disk_quadrature_rule(samples, samples)

    alpha = numpy.arcsin(NA)
    maxradius = numpy.tan(alpha)*dist
    r *= maxradius

    rE = numpy.zeros([samples*samples, 3])
    for n in range(samples):
        for m in range(samples):
            rE[n*samples + m, 0] = numpy.sqrt(pow2(dist) + pow2(r[n]))
            rE[n*samples + m, 1] = theta[m]
            rE[n*samples + m, 2] = numpy.arctan(r[n]/dist)

    # calculate scattered field as a function of angles
    # parallel to incident plane

    #Esca = numpy.zeros([pow2(samples), 3])
    Esca = dda_si_funcs.E_sca_SI(k, dipoles, P, rE[:, 0], rE[:, 1], rE[:, 2], n1)

    weights /= numpy.pi * pow2(maxradius)

    I = 0
    for n in range(samples):
        for m in range(samples):
            I += pow2(k) * (rE[n*samples + m, 0]).T * numpy.dot(Esca[n*samples + m].conj(), Esca[n*samples + m])*weights[n]
    return I
Пример #5
0
def legendre_ek_compute(n):
    """
    Gauss-Legendre, Elhay-Kautsky method.
    :param n: number of samples
    :return: x, points
    :return: w, weights
    """

    pow2 = misc.power_function(2)

    zemu = 2.0

    bj = numpy.zeros(n)
    for i in numpy.arange(n):
        ip1 = i + 1.
        bj[i] = numpy.sqrt(pow2(ip1) / (4. * pow2(ip1) - 1.))

    x = numpy.zeros(n)
    w = numpy.zeros(n)
    w[0] = numpy.sqrt(zemu)

    x_r, w_r = imtqlx(x, bj, w)
    w_r = pow2(w_r)

    return x_r, w_r
Пример #6
0
def precalc_Somm(r, k1, k2, use_mex=False):
    # r: dipole coordinates
    # k1: wave number in substrate
    # k2: wave number in upper medium, e.g., air, water etc.

    pow2 = misc.power_function(2)

    # global use_mex
    N = r.shape[0]

    zr = numpy.zeros([N * N, 2])

    ix = 0
    for j in numpy.arange(N):
        # sprintf('precalc zph rho. %d of %d',j,N)
        for k in numpy.arange(N):
            r_j = r[j, :]
            r_k = r[k, :]
            zph = r_j[2] + r_k[2]
            rho = numpy.sqrt(pow2(r_j[0] - r_k[0]) + pow2(r_j[1] - r_k[1]))

            # round to 4 decimal places
            # zph = round2(zph,.0001);
            # rho = round2(rho,.0001);

            zr[ix, :] = numpy.asarray([zph, rho])  # TODO: Get rid of asarray
            ix += 1

    zr0 = zr
    #zr, m, n = numpy.unique(zr, return_index=True, return_inverse=True)
    zr, m, n = misc.unique_rows(zr, return_index=True, return_inverse=True)
    L = zr.shape[0]

    S = numpy.zeros([L, 4], dtype=numpy.complex128)

    for j in numpy.arange(L):
        # sprintf('precalc S. %d of %d',j,L)
        if use_mex:
            raise Exception("Some unknown function")
            # I = somm(numpy.real(k1), numpy.imag(k1),k2,zr[j,1],zr[j,2])
            # IV_rho = I[1] + 1j*I[2]
            # IV_z  = I[3] + 1j*I[4]
            # IH_rho  = I[5] + 1j*I[6]
            # IH_phi  = I[7] + 1j*I[8]
        else:
            IV_rho, IV_z, IH_rho, IH_phi = evlua(zph, rho, k1, k2)

        S[j, :] = [IV_rho, IV_z, IH_rho, IH_phi]

    return S, n
Пример #7
0
def Fresnel_coeff_n(n_r, theta):
    # n_r : relative refractive index bottom substrate medium
    # theta : incident angle (from surface normal)

    pow2 = misc.power_function(2)

    R_TM = (numpy.sqrt(1 - pow2(numpy.sin(theta) / n_r)) -
            n_r * numpy.cos(theta)) / (numpy.sqrt(1 - pow2(
                (numpy.sin(theta) / n_r))) + n_r * numpy.cos(theta))
    R_TE = (
        numpy.cos(theta) - n_r * numpy.sqrt(1 - pow2(numpy.sin(theta) / n_r))
    ) / (numpy.cos(theta) + n_r * numpy.sqrt(1 - pow2(numpy.sin(theta) / n_r)))

    return R_TE, R_TM  # R_s, R_p
Пример #8
0
def scatter_spectrum(diameter, diameter_2, n_dipoles, refractive_index, lambda_range):
    pow1d3 = misc.power_function(1./3.)
    pow3 = misc.power_function(3)

    k = 2 * numpy.pi  # wave number
    # r, N, d_old = scatterer.dipole_sphere(10, diameter)
    r, N, d_old = scatterer.dipole_spheroid(n_dipoles, diameter, diameter_2, testsphere=False)

    I_scat_p = numpy.zeros(lambda_range.size)
    I_scat_s = numpy.zeros(lambda_range.size)

    # Incident plane wave
    # Incident field wave vector angle
    gamma_deg = 22.5
    gamma = gamma_deg / 180 * numpy.pi
    kvec = k * numpy.asarray([0, numpy.sin(gamma), -numpy.cos(gamma)])  # wave vector [x y z]

    n = refractive_index * numpy.ones([N])  # refractive index of sphere

    for i, lam in enumerate(lambda_range):
        d_new = pow1d3((4 / 3) * (numpy.pi / N) * (diameter/2 * diameter/2 * diameter_2/2 / pow3(lam)))
        r = (d_new/d_old) * r
        d_old = d_new

        #
        # p
        #
        E0 = numpy.asarray([1, 0, 0])  # E-field [x y z]  # s-pol
        I_scat_p[i] = scatter_intensity(r, n, d_new, E0, kvec, k)

        #
        # s
        #
        E0 = numpy.asarray([0, numpy.cos(gamma), numpy.sin(gamma)])  # p-pol
        I_scat_s[i] = scatter_intensity(r, n, d_new, E0, kvec, k)

    return I_scat_s, I_scat_p
Пример #9
0
def evanescent_k_e(theta_1, n1, n2):
    # theta_1 : incident angle
    # n1 : substrate reflective index
    # n2 : reflective index of the medium above the substrate, e.g., air

    # k2 : wave vector above the substrate
    # ep : TM polarisation vector
    # es : TE polarisation vector

    pow2 = misc.power_function(2)

    k0 = 2 * numpy.pi  # wave number in vacuum
    theta_c = numpy.arcsin(n2 / n1 + 0j)  # critical angle
    sin_theta_2 = (n1 / n2) * numpy.sin(theta_1)
    theta_2 = numpy.arcsin(sin_theta_2 + 0j)

    # This is correct regardless of incident angle. Has round-off error.
    # Use this for the general case
    # k2 = [0 n2*k0*sin_theta_2 n2*k0*cos(theta_2)];

    # This is only correct beyond the critical angle;
    # the sign for k_z is opposite otherwise. However, no round-off error.
    if numpy.isreal(theta_2):
        k2 = numpy.asarray([
            0, n1 * k0 * numpy.sin(theta_1),
            1j * k0 * numpy.sqrt(pow2(n1 * numpy.sin(theta_1)) - pow2(n2))
        ],
                           dtype=numpy.complex128)
    else:
        k2 = numpy.asarray([
            0, n1 * k0 * numpy.sin(theta_1),
            -1j * k0 * numpy.sqrt(pow2(n1 * numpy.sin(theta_1)) - pow2(n2))
        ],
                           dtype=numpy.complex128)

    ep = numpy.asarray([
        0, 1j * numpy.sqrt(pow2(n1 / n2 * numpy.sin(theta_1)) - 1),
        n1 / n2 * numpy.sin(theta_1)
    ],
                       dtype=numpy.complex128)
    es = numpy.asarray([1, 0, 0], dtype=numpy.complex128)

    return k2, ep, es
Пример #10
0
def polarizability_LDR(d, m, kvec, E0=None):
    """Calculates Lattice Dispersion Relation polarizability of dipoles.

    Calcualtes Lattice Dispersion Relation polarizability of dipole array according
    to their refractive indexes `m` and lattice spacing `d`.

    Parameters
    ----------
    d : float
        Dipole lattice spacing
    m : array_like
        List of dipole refractive indexes
    kvec : (3, 1) array_like
        Wave vector [kx ky kz]     e.g. [0 0 1] z-direction
    E0 : (3, 1) array_like
        E-field polarization [Ex Ey Ez]   e.g. [1 0 0] x-polarized,
        [1 i 0] left-handed circ pol.

    Returns
    -------
    alph: list
        List of dipole polarizabilities
    Notes
    -----
    Currently only supports isotropic polarizabilities,
    extending to anisotropic polarizabilities should be trivial,

    References
    ----------
    .. [1] Draine, Bruce T., and Jeremy Goodman. "Beyond Clausius-Mossotti-Wave propagation on a
    polarizable point lattice and the discrete dipole approximation."
    The Astrophysical Journal 405 (1993): 685-697.

    """

    pow2 = misc.power_function(2)
    pow3 = misc.power_function(3)

    k0 = 2 * numpy.pi
    N = m.size  # number of dipoles
    b1 = -1.8915316
    b2 = 0.1648469
    b3 = -1.7700004
    msqr = pow2(m)
    dcube = pow3(d)

    if E0 is not None:  # we have polarization info
        a_hat = kvec / numpy.linalg.norm(kvec)
        e_hat = E0 / numpy.linalg.norm(E0)
        S = 0
        for j in range(3):
            S += (a_hat[j] * e_hat[j])**2
    else:  # use randomly-oriented value; also for non-plane wave
        S = .2

    alpha_CM = numpy.divide(3 * dcube / (4 * numpy.pi) * (msqr - 1),
                            (msqr + 2))  # Clausius-Mossotti
    alpha_LDR = numpy.divide(alpha_CM, (1 + numpy.multiply(
        (alpha_CM / dcube), ((b1 + msqr * b2 + msqr * b3 * S) *
                             (k0 * d)**2 - 2 / 3 * 1j * k0**3 * dcube))))

    alph = numpy.zeros([3 * N], dtype=numpy.complex128)
    # assuming same polarizability in x, y & z directions
    for j in range(N):
        alph[3 * (j - 1) + 0] = alpha_LDR[j]
        alph[3 * (j - 1) + 1] = alpha_LDR[j]
        alph[3 * (j - 1) + 2] = alpha_LDR[j]

    return alph
Пример #11
0
def evlua(zph, rho, k1, k2):
    # radiating dipole, k
    # receiving dipole, j
    # zph = z_j + z_k
    # rho = radial coordinate for cylindrical system
    # k1 = wave number in slab medium
    # k2 = wave number in top medium

    # int i, jump;
    # static double del, slope, rmis;
    # static complex double cp1, cp2, cp3, bk, delta, delta2, sum[6], ans[6];

    pow2 = misc.power_function(2)

    conj_e = 1
    bk = 0
    # suminc = zeros(6,1);
    answer = numpy.zeros([6])

    tkmag = 100 * numpy.abs(k1)

    delt = zph
    if rho > delt:
        delt = rho

    if zph >= 2 * rho:
        # bessel function form of sommerfeld integrals
        jh = 0
        a = 0
        delt = 1 / delt

        if delt > tkmag:
            b = .1 * (1 - 1j) * tkmag  # b=cmplx(.1*tkmag,-.1*tkmag);
            suminc = rom1(6, 2, zph, rho, k1, k2, a, b, jh)
            a = b
            b = delt * (1 - 1j)
            answer = rom1(6, 2, zph, rho, k1, k2, a, b, jh)
            # for i = 0; i < 6; i++ )
            #    sum[i] += ans[i];
            #    end
            suminc = suminc + answer
        else:
            b = delt * (1 - 1j)
            suminc = rom1(6, 2, zph, rho, k1, k2, a, b, jh)

            delta = .2 * numpy.pi * delt
            answer = gshank(b, delta, answer, 6, suminc, 0, b, b, zph, rho, k1,
                            k2, jh)  # gshank(b,delta,ans,6,sum,0,b,b);
            answer[5] = answer[5] * k1  # ans[5] *= k1;

        if conj_e:
            # conjugate since nec uses exp(+jwt)
            erv = numpy.conj(pow2(k1) * answer[2])  # *erv=conj(ck1sq*ans[2]);
            ezv = numpy.conj(pow2(k1) * (answer[1] + pow2(k2) * answer[4])
                             )  # *ezv=conj(ck1sq*(ans[1]+ck2sq*ans[4]));
            erh = numpy.conj(
                pow2(k2) *
                (answer[0] + answer[5]))  # *erh=conj(ck2sq*(ans[0]+ans[5]));
            eph = -numpy.conj(
                pow2(k2) *
                (answer[3] + answer[5]))  # *eph=-conj(ck2sq*(ans[3]+ans[5]));
        else:
            # unconjugated
            erv = pow2(k1) * answer[2]  # *erv=conj(ck1sq*ans[2]);
            ezv = pow2(k1) * (answer[1] + pow2(k2) * answer[3]
                              )  # *ezv=conj(ck1sq*(ans[1]+ck2sq*ans[4]));
            erh = pow2(k2) * (answer[0] + answer[5]
                              )  # *erh=conj(ck2sq*(ans[0]+ans[5]));
            eph = -pow2(k2) * (answer[3] + answer[5]
                               )  # *eph=-conj(ck2sq*(ans[3]+ans[5]));

        return erv, ezv, erh, eph
        # # } /* if(zph >= 2.*rho) */
    else:
        # hankel function form of sommerfeld integrals
        jh = 1
        cp1 = .4 * k2 * 1j  # cp1=cmplx(0.0,.4*ck2);
        cp2 = .6 * k2 - .2 * k2 * 1j  # cp2=cmplx(.6*ck2,-.2*ck2);
        cp3 = 1.02 * k2 - .2 * k2 * 1j  # cp3=cmplx(1.02*ck2,-.2*ck2);
        a = cp1
        b = cp2
        suminc = rom1(6, 2, zph, rho, k1, k2, a, b, jh)
        a = cp2
        b = cp3
        answer = rom1(6, 2, zph, rho, k1, k2, a, b, jh)

        # for( i = 0; i < 6; i++ )
        #     sum[i]=-(sum[i]+ans[i]);
        suminc = -(suminc + answer)

        # path from imaginary axis to -infinity
        if zph > .001 * rho:
            slope = rho / zph
        else:
            slope = 1000

        delt = .2 * numpy.pi / delt
        delta = (-1 + slope * 1j) * delt / numpy.sqrt(1 + pow2(slope))
        delta2 = -numpy.conj(delta)
        answer = gshank(cp1, delta, answer, 6, suminc, 0, bk, bk, zph, rho, k1,
                        k2, jh)  # gshank(cp1,delta,ans,6,sum,0,bk,bk);
        rmis = rho * (numpy.real(k1) - k2)

        jump = 0
        # jump = FALSE;
        if (rmis >= 2 * k2) and (rho >= 1E-10):
            if (zph >= 1E-10):
                bk = (-zph + rho * 1j) * (k1 - cp3
                                          )  # bk=cmplx(-zph,rho)*(ck1-cp3);
                rmis = -numpy.real(bk) / numpy.abs(
                    numpy.imag(bk))  # rmis=-creal(bk)/fabs(cimag(bk));
                if (rmis > 4 * rho / zph):
                    jump = 1  # jump = TRUE;

            if not jump:  # if( ! jump )
                # integrate up between branch cuts, then to + infinity
                cp1 = k1 - (.1 + .2 * 1j)  # cp1=ck1-(.1+.2fj);
                cp2 = cp1 + .2
                bk = delt * 1j  # bk=cmplx(0.,del);
                suminc = gshank(cp1, bk, suminc, 6, answer, 0, bk, bk, zph,
                                rho, k1, k2,
                                jh)  # gshank(cp1,bk,sum,6,ans,0,bk,bk);
                a = cp1
                b = cp2
                answer = rom1(6, 1, zph, rho, k1, k2, a, b, jh)
                # for( i = 0; i < 6; i++ )
                #     ans[i] -= sum[i];
                answer = answer - suminc

                suminc = gshank(cp3, bk, suminc, 6, answer, 0, bk, bk, zph,
                                rho, k1, k2,
                                jh)  # gshank(cp3,bk,sum,6,ans,0,bk,bk);
                answer = gshank(cp2, delta2, answer, 6, suminc, 0, bk, bk, zph,
                                rho, k1, k2,
                                jh)  # gshank(cp2,delta2,ans,6,sum,0,bk,bk);

            jump = 1  # jump = TRUE;

        # /* if( (rmis >= 2.*ck2) || (rho >= 1.e-10) ) */
        else:
            jump = 0  # jump = FALSE;

        if not jump:  # ( ! jump )
            ##{
            # integrate below branch points, then to + infinity
            #     for( i = 0; i < 6; i++ )
            #       sum[i]=-ans[i];
            suminc = -answer

            rmis = numpy.real(k1) * 1.01  # rmis=creal(ck1)*1.01;
            #     if( (ck2+1.) > rmis )
            #       rmis=ck2+1.;
            if (k2 + 1) > rmis:
                rmis = k2 + 1

            bk = rmis + .99 * numpy.imag(
                k1) * 1j  # bk=cmplx(rmis,.99*cimag(ck1));
            delta = bk - cp3
            delta = delta * delt / numpy.abs(
                delta)  # delta *= del/cabs(delta);
            answer = gshank(cp3, delta, answer, 6, suminc, 1, bk, delta2, zph,
                            rho, k1, k2,
                            jh)  # gshank(cp3,delta,ans,6,sum,1,bk,delta2);
            # /* if( ! jump ) */

        answer[5] = answer[5] * k1  # ans[5] *= ck1;

        if conj_e:
            # conjugate since nec uses exp(+jwt)
            erv = numpy.conj(pow2(k1) * answer[2])  # *erv=conj(ck1sq*ans[2]);
            ezv = numpy.conj(pow2(k1) * (answer[1] + pow2(k2) * answer[4])
                             )  # *ezv=conj(ck1sq*(ans[1]+ck2sq*ans[4]));
            erh = numpy.conj(
                pow2(k2) *
                (answer[0] + answer[5]))  # *erh=conj(ck2sq*(ans[0]+ans[5]));
            eph = -numpy.conj(
                pow2(k2) *
                (answer[3] + answer[5]))  # *eph=-conj(ck2sq*(ans[3]+ans[5]));
        else:
            # unconjugated
            erv = pow2(k1) * answer[2]
            ezv = pow2(k1) * (answer[1] + pow2(k2) * answer[4])
            erh = pow2(k2) * (answer[0] + answer[5])
            eph = -pow2(k2) * (answer[3] + answer[5])

        return erv, ezv, erh, eph
Пример #12
0
def saoa(t, zph, rho, k1, k2, a, b, jh):
    # %   double xlr, sign;
    # %   static complex double xl, dxl, cgam1, cgam2, b0, b0p, com, dgam, den1, den2;

    pow2 = misc.power_function(2)
    pow4 = misc.power_function(4)
    pow6 = misc.power_function(6)

    tsmag = 100 * k1 * numpy.conj(k1)
    cksm = pow2(k2) / (pow2(k1) + pow2(k2))  # cksm=ck2sq/(ck1sq+ck2sq);
    ct1 = .5 * (pow2(k1) - pow2(k2))  # ct1=.5*(ck1sq-ck2sq)
    # % erv=ck1sq*ck1sq;
    # % ezv=ck2sq*ck2sq;
    # % ct2=.125*(erv-ezv);
    ct2 = .125 * (pow4(k1) - pow4(k2))
    # % erv *= ck1sq;
    # % ezv *= ck2sq;
    # % ct3=.0625*(erv-ezv);
    ct3 = .0625 * (pow6(k1) - pow6(k2))

    xl, dxl = lambd(t, a, b)  # lambda(t, &xl, &dxl);

    if jh == 0:
        # bessel function form
        b0, b0p = ott_funcs.bessel0(xl * rho)  # bessel(xl*rho, &b0, &b0p);
        b0 *= 2.  # b0  *=2.
        b0p *= 2.  # b0p *=2.
        cgam1 = numpy.sqrt(pow2(xl) - pow2(k1))  # cgam1=csqrt(xl*xl-ck1sq)
        cgam2 = numpy.sqrt(pow2(xl) - pow2(k2))  # cgam2=csqrt(xl*xl-ck2sq)
        if numpy.real(cgam1) == 0:  # if(creal(cgam1) == 0.):
            cgam1 = numpy.abs(
                numpy.imag(cgam1)) * 1j  # cgam1=cmplx(0.,-fabs(cimag(cgam1)))
        if numpy.real(cgam2) == 0:  # if(creal(cgam2) == 0.):
            cgam2 = numpy.abs(
                numpy.imag(cgam2)) * 1j  # cgam2=cmplx(0.,-fabs(cimag(cgam2)))
    else:
        # hankel function form
        b0, b0p = ott_funcs.hankel0(xl * rho)  # hankel(xl*rho, &b0, &b0p);
        com = xl - k1  # com=xl-ck1;
        cgam1 = numpy.sqrt(xl + k1) * numpy.sqrt(
            com)  # cgam1=csqrt(xl+ck1)*csqrt(com);
        if (numpy.real(com) <
                0) and (numpy.imag(com) >=
                        0):  # if(creal(com) < 0. && cimag(com) >= 0.)
            cgam1 = -cgam1

        com = xl - k2  # com=xl-ck2;
        cgam2 = numpy.sqrt(xl + k2) * numpy.sqrt(
            com)  # cgam2=csqrt(xl+ck2)*csqrt(com);
        if (numpy.real(com) <
                0) and (numpy.imag(com) >=
                        0):  # if(creal(com) < 0. && cimag(com) >= 0.)
            cgam2 = -cgam2

    xlr = xl * numpy.conj(xl)
    if xlr >= tsmag:
        if numpy.imag(xl) >= 0:
            xlr = numpy.real(xl)
            if xlr >= k2:
                if (xlr <= numpy.realk1):  # if(xlr <= ck1r):
                    dgam = cgam2 - cgam1
                else:
                    sign = 1
                    dgam = 1 / (pow2(xl))  # dgam=1./(xl*xl)
                    dgam = sign * ((ct3 * dgam + ct2) * dgam + ct1) / xl
            else:
                sign = -1
                dgam = 1 / pow2(xl)  # dgam=1./(xl*xl)
                dgam = sign * ((ct3 * dgam + ct2) * dgam + ct1) / xl
                # /* if(xlr >= ck2) */
                # /* if(cimag(xl) >= 0.) */
        else:
            sign = 1
            dgam = 1 / pow2(xl)  # dgam=1./(xl*xl)
            dgam = sign * ((ct3 * dgam + ct2) * dgam + ct1) / xl
    # % /* if(xlr < tsmag) */
    else:
        dgam = cgam2 - cgam1

    den2 = cksm * dgam / (cgam2 * (pow2(k1) * cgam2 + pow2(k2) * cgam1)
                          )  # den2=cksm*dgam/(cgam2*(ck1sq*cgam2+ck2sq*cgam1))
    den1 = 1 / (cgam1 + cgam2) - cksm / cgam2
    com = dxl * xl * numpy.exp(-cgam2 * zph)

    answer = numpy.zeros([6], dtype=numpy.complex128)

    answer[5] = com * b0 * den1 / k1  # ans[5] = com*b0*den1/ck1
    com = com * den2  # com *= den2

    if rho != 0:  # if(rho != 0.)
        b0p /= rho
        answer[0] = -com * xl * (b0p + b0 * xl)  # ans[0]=-com*xl*(b0p+b0*xl)
        answer[3] = com * xl * b0p  # ans[3]=com*xl*b0p
    else:
        answer[0] = -com * xl * xl * .5  # ans[0]=-com*xl*xl*.5
        answer[3] = answer[0]  # ans[3]=ans[0]

    answer[1] = com * cgam2 * cgam2 * b0  # ans[1]=com*cgam2*cgam2*b0
    answer[2] = -answer[3] * cgam2 * rho  # ans[2]=-ans[3]*cgam2*rho
    answer[4] = com * b0  # ans[4]=com*b0
    return answer
Пример #13
0
def interaction_AR(k1, k2, r, alph):
    # % AR is 3N x 3N matrix
    # % k1 = wave number in bottom medium (substrate)
    # % k2 = wave number in top medium (could be air/vacuum)
    # % r: N x 3 matrix, for x_j, y_j, z_j coordinates
    # % N: number of dipoles
    # % j = 1..N
    # % AR means A + R
    # % A is as per Eqn(6) plus the inverse polarizability dagonal in
    # % Draine & Flatau,
    # % Discrete-dipole approximation for scattering calculations
    # % pgs 1491-1499, Vol. 11, No. 4 (1994), J. Opt. Soc. Am. A
    #
    # % the Rjk component represents radiating and receiving dipole interactions
    # % via substrate surface reflection; refer to:
    # % Roland Schmehl, Brent M. Nebeker, and E. Dan Hirleman
    # % "Discrete-dipole approximation for scattering by features on surfaces
    # % by means of a two-dimensional fast Fourier transform technique"
    # % J. Opt. Soc. Am. A 14, 3026-3036 (1997)

    pow2 = misc.power_function(2)
    pow_m1 = misc.power_function(-1)
    pow_m2 = misc.power_function(-2)

    k0 = 2 * numpy.pi
    N = r[:, 1].size
    AR = numpy.zeros([3 * N, 3 * N], dtype=numpy.complex128)
    I = numpy.eye(3)

    S, nS = precalc_Somm(r, k1, k2)

    iS = 0  # dipole combination counter
    # % nS(iS) determines which set of precalculated Sommmerfeld integrals to use
    # tic
    for jj in numpy.arange(N):
        # sprintf('Interaction matrix, dipole %d of %d',jj,N)
        for kk in numpy.arange(N):
            Rjk = reflection_Rjk(k1, k2, r[jj, :], r[kk, :],
                                 S[nS[iS], :])  # Schmehl et al.
            iS += 1
            if jj != kk:  # off-diagonal
                rk_to_rj = r[jj, :] - r[kk, :]
                rjk = numpy.linalg.norm(
                    rk_to_rj)  # sqrt(sum((r(jj,:)-r(kk,:)).^2))
                rjk_hat = (rk_to_rj) / rjk
                rjkrjk = numpy.outer(rjk_hat, rjk_hat)

                Ajk = numpy.exp(1j * k0 * rjk) / rjk * (
                    pow2(k0) * (rjkrjk - I) + (1j * k0 * rjk - 1) / pow2(rjk) *
                    (3 * rjkrjk - I))  # %Draine & Flatau

                # % beta, gamma see Schmehl's thesis (1.27)
                rjk_x = rk_to_rj[0] / rjk
                rjk_y = rk_to_rj[1] / rjk
                rjk_z = rk_to_rj[2] / rjk
                beta = (1 - pow_m2(k0 * rjk) + 1j * pow_m1(k0 * rjk))
                gamma = -(1 - 3 * pow_m2(k0 * rjk) + 1j * 3 * pow_m1(k0 * rjk))
                Ajk_BG = -numpy.exp(1j * k0 * rjk) / rjk * pow2(
                    k0) * numpy.asarray([[(beta + gamma * pow2(rjk_x)),
                                          (gamma * rjk_x * rjk_y),
                                          (gamma * rjk_x * rjk_z)],
                                         [(gamma * rjk_y * rjk_x),
                                          (beta + gamma * pow2(rjk_y)),
                                          (gamma * rjk_y * rjk_z)],
                                         [(gamma * rjk_z * rjk_x),
                                          (gamma * rjk_z * rjk_y),
                                          (beta + gamma * pow2(rjk_z))]])

                AR[jj * 3 + 0:(jj + 1) * 3,
                   kk * 3 + 0:(kk + 1) * 3] = (Ajk + Rjk)
            else:
                AR[jj * 3 + 0, kk * 3 + 0] = 1. / alph[jj * 3 + 0]
                AR[jj * 3 + 1, kk * 3 + 1] = 1. / alph[jj * 3 + 1]
                AR[jj * 3 + 2, kk * 3 + 2] = 1. / alph[jj * 3 + 2]
                AR[jj * 3 + 0:(jj + 1) * 3, kk * 3 + 0:(kk + 1) *
                   3] += Rjk  # + AR[(jj) * 3 + 0:(jj + 1) * 3, kk * 3 + 0:(kk + 1) * 3]
    return AR
Пример #14
0
def E_sca_SI(k, r, P, det_r, theta, phi, n1):
    # % k: wave vector
    # % r: dipole coordinates (N x 3 matrix)
    # % P: polarizations (vector of length 3N; Px1,Py1,Pz1 ... PxN,PyN,PzN)
    # % det_r, theta, phi: evaluation points in spherical coordinates
    # % n1: refractive index of substrate
    #
    # % Note: coordinates are relative to origin
    #
    pow2 = misc.power_function(2)

    N, cols = r.shape

    # TODO: what does this do?
    # rows, cols = theta.shape
    # if cols > rows:
    #    theta = numpy.reshape(theta, [cols, rows])
    # rows, cols = phi.shape
    # if cols > rows:
    #    phi = numpy.reshape(phi, [cols, rows])
    # rows, cols = det_r.shape
    # if cols > rows:
    #    det_r = numpy.reshape(det_r, [cols, rows])

    # %pts = length(r_unit);
    r_sp = numpy.asarray([det_r, theta, phi],
                         dtype=numpy.complex128).T  # TODO: Get rid of asarray
    pts, cols = r_sp.shape
    r_unit = numpy.ones([pts], dtype=numpy.complex128)
    # er_sp = numpy.asarray([r_unit, theta, phi]).T
    # e1_sp = numpy.asarray([r_unit, theta + numpy.sign(theta) * numpy.pi / 2, phi]).T

    # TODO: Get rid of asarray
    r_E = numpy.asarray(misc.rtp2xyz(r_unit, theta, phi),
                        dtype=numpy.complex128).T  # er_sp
    r_E1 = numpy.asarray(misc.rtp2xyz(r_unit,
                                      theta + numpy.sign(theta) * numpy.pi / 2,
                                      phi),
                         dtype=numpy.complex128).T  # e1_sp
    er = numpy.zeros([pts, 3], dtype=numpy.complex128)
    e1 = numpy.zeros([pts, 3], dtype=numpy.complex128)
    e2 = numpy.zeros([pts, 3], dtype=numpy.complex128)

    # % r_E2 = rtp2xyz(er_sp);
    # % er2 = zeros(pts,3);
    for j in numpy.arange(pts):
        er[j, :] = r_E[j, :] / numpy.linalg.norm(r_E[j, :])
        e1[j, :] = r_E1[j, :] / numpy.linalg.norm(r_E1[j, :])
        e2[j, :] = numpy.cross(er[j, :], e1[j, :])

    E = numpy.zeros([pts, 3], dtype=numpy.complex128)

    for pt in numpy.arange(pts):
        erp = er[pt, :]  # e_r
        e1p = e1[pt, :]  # e_theta
        e2p = e2[pt, :]  # e_phi
        k_sca = (k * erp).conj()
        k_Isca = numpy.asarray([k_sca[0], k_sca[1], -k_sca[2]],
                               dtype=numpy.complex128).conj()

        #   % This is the modification was made Mitchell Short, University of Utah,
        #   % to account for the Fresnel coefficient at each angle of dipole
        #   % as opposed to single incident angle.
        ref_angle = numpy.abs((-numpy.pi / 2) + pt * numpy.pi / theta.size)
        refl_TE, refl_TM = Fresnel_coeff_n(n1, numpy.abs(ref_angle))

        # %rp = norm(r_E(pt,:));
        rp = det_r[pt]
        for j in numpy.arange(N):
            Pj = P[3 * j + 0:3 * j + 3].conj()
            rj = r[j, :]
            rIj = [rj[0], rj[1], -rj[2]]

            E[pt, :] = E[pt, :] + numpy.exp(-1j * numpy.dot(k_sca, rj)) * (
                numpy.dot(Pj, e1p) * e1p + numpy.dot(Pj, e2p) * e2p
            ) + numpy.exp(-1j * numpy.dot(k_Isca, rj)) * (refl_TM * numpy.dot(
                Pj, e1p) * e1p + refl_TE * numpy.dot(Pj, e2p) * e2p)
            # TODO: Inner Outer product?

            # E(pt,:) = E(pt,:) + ...
            # exp(-i*k_sca.*rj).*(dot(Pj,e1p)*e1p + dot(Pj,e2p)*e2p) + ...
            # exp(-i*k_sca.*rIj).*(refl_TM*dot(Pj,e1p)*e1p + refl_TE*dot(Pj,e2p)*e2p);

            # % dot(k_sca,rIj) and dot(k_Isca,rj) are equal.
            # % Refer to Schmel's thesis (2.58)
        E[pt, :] = E[pt, :] * pow2(k) * numpy.exp(
            1j * k * rp) / (4 * numpy.pi * rp)
    return E
Пример #15
0
def reflection_Rjk(k1, k2, r_j, r_k, S):
    # % k1 = wave number in bottom medium (e.g. substrate)
    # % k2 = wave number in top medium (e.g. air/vacuum)
    # % r_j = receiving dipole coordinate [x y z]
    # % r_k = radiating dipole coordinate [x y z]
    # % S = precalculated Sommerfeld essential integrals

    pow2 = misc.power_function(2)
    pow_m1 = misc.power_function(-1)
    pow_m2 = misc.power_function(-2)

    k0 = 2 * numpy.pi

    # % (A9d)
    rI_k2j = [r_j[0] - r_k[0], r_j[1] - r_k[1], r_j[2] + r_k[2]]
    rIjk = numpy.linalg.norm(rI_k2j)

    # % x,y,z components vectors (A9a)
    rhat_x = rI_k2j[0] / rIjk
    rhat_y = rI_k2j[1] / rIjk
    rhat_z = rI_k2j[2] / rIjk

    # % scalars (A9b) & (A9c)
    beta = (1 - 1 * pow_m2(k0 * rIjk) + 1j * pow_m1(k0 * rIjk))
    gamma = -(1 - 3 * pow_m2(k0 * rIjk) + 1j * 3 * pow_m1(k0 * rIjk))

    zph = r_j[2] + r_k[2]
    rho = numpy.sqrt(pow2(r_j[0] - r_k[0]) + pow2(r_j[1] - r_k[1]))

    # % assign precalculated Sommerfeld essential integrals
    IV_rho = S[0]
    IV_z = S[1]
    IH_rho = S[2]
    IH_phi = S[3]
    #
    S11 = pow2(rhat_x) * IH_rho - pow2(rhat_y) * IH_phi
    S12 = rhat_x * rhat_y * (IH_rho + IH_phi)
    S13 = rhat_x * IV_rho
    S21 = rhat_x * rhat_y * (IH_rho + IH_phi)
    S22 = pow2(rhat_y) * IH_rho - pow2(rhat_x) * IH_phi
    S23 = rhat_y * IV_rho
    S31 = -rhat_x * IV_rho
    S32 = -rhat_y * IV_rho
    S33 = IV_z

    Sjk = numpy.asarray([[S11, S12, S13], [S21, S22, S23],
                         [S31, S32, S33]])  # TODO: Get rid of asarray

    G11 = -(beta + gamma * pow2(rhat_x))
    G12 = -gamma * rhat_x * rhat_y
    G13 = gamma * rhat_x * rhat_z
    G21 = -gamma * rhat_y * rhat_x
    G22 = -(beta + gamma * pow2(rhat_y))
    G23 = gamma * rhat_y * rhat_z
    G31 = -gamma * rhat_z * rhat_x
    G32 = -gamma * rhat_z * rhat_y
    G33 = beta + gamma * pow2(rhat_z)

    Gjk = numpy.asarray([[G11, G12, G13], [G21, G22, G23],
                         [G31, G32, G33]])  # TODO: Get rid of asarray
    # % to be consistent with the Draine and Flatau interraction matrix
    # % formulation we omit the (4*pi*ep)^-1 factor
    # % (A8)

    Rjk = -(Sjk + pow2(k0) * (pow2(k1) - pow2(k2)) /
            (pow2(k1) + pow2(k2)) * numpy.exp(1j * k0 * rIjk) / rIjk * Gjk
            )  # %as per Schmehl's thesis

    # % The required k0^2 factor was reported by Dr. Andrey Evlyukhin, Laser Zentrum Hannover e.V.
    # % as per Schmehl's thesis (2.41). In the previous version,
    # % Rjk = -(Sjk + (k1^2-k2^2)/(k1^2+k2^2)*exp(i*k0*rIjk)/rIjk*Gjk); % as per Schmehl (A8)
    return Rjk
Пример #16
0
def imtqlx(diagonal, subdiagonal, vec, abstol=1e-30, maxiterations=30):
    """
    Diagonalize symmetric tridiagonal matrix
    :param diagonal: matrix diagonal, size N
    :param subdiagonal: matrix subdiagonal, size N-1
    :return: lam: diagonal entries of diagonalized matrix
    :return: qtz: values of Q' * Z, where Q diagonalizes input matrix M
    """

    n = diagonal.size
    #assert subdiagonal.size == n-1
    assert vec.size == n

    pow2 = misc.power_function(2)

    lam = numpy.zeros(n, dtype=numpy.complex128)
    lam = diagonal

    qtz = numpy.zeros(n, dtype=numpy.complex128)
    qtz = vec

    if n == 1:
        return lam, qtz

    subdiagonal[n - 1] = 0

    for l in numpy.arange(1, n + 1):
        j = 0
        while True:
            for m in numpy.arange(l, n + 1):
                if m == n:
                    break

                if numpy.abs(subdiagonal[m - 1]) <= abstol * (
                        numpy.abs(lam[m - 1] + numpy.abs(lam[m]))):
                    break

            p = lam[l - 1]

            if m == l:
                break

            if j >= maxiterations:
                raise Exception("Failed to converge in {} iterations".format(
                    maxiterations))
            j += 1

            g = (lam[l] - p) / (2.0 * subdiagonal[l - 1])
            r = numpy.sqrt(pow2(g) + 1.0)

            if g < 0:
                t = g - r
            else:
                t = g + r
            g = lam[m - 1] - p + subdiagonal[l - 1] / (g + t)

            s = 1.0
            c = 1.0
            p = 0.0
            mml = m - l

            for ii in numpy.arange(1, mml + 1):
                i = m - ii
                f = s * subdiagonal[i - 1]
                b = c * subdiagonal[i - 1]

                if numpy.abs(g) <= numpy.abs(f):
                    c = g / f
                    r = numpy.sqrt(pow2(c) + 1.0)
                    subdiagonal[i] = f * r
                    s = 1.0 / r
                    c *= s
                else:
                    s = f / g
                    r = numpy.sqrt(pow2(s) + 1.0)
                    subdiagonal[i] = g * r
                    c = 1.0 / r
                    s *= c

                g = lam[i] - p
                r = (lam[i - 1] - g) * s + 2.0 * c * b
                p = s * r
                lam[i] = g + p
                g = c * r - b
                f = qtz[i]
                qtz[i] = s * qtz[i - 1] + c * f
                qtz[i - 1] = c * qtz[i - 1] - s * f

            lam[l - 1] -= p
            subdiagonal[l - 1] = g
            subdiagonal[m - 1] = 0.0

    #Sort
    for ii in numpy.arange(2, n + 1):
        i = ii - 1
        k = i
        p = lam[i - 1]

        for j in numpy.arange(ii, n + 1):

            if lam[j - 1] < p:
                k = j
                p = lam[j - 1]

        if k != i:
            lam[k - 1] = lam[i - 1]
            lam[i - 1] = p

            p = qtz[i - 1]
            qtz[i - 1] = qtz[k - 1]
            qtz[k - 1] = p

    return lam, qtz