Exemple #1
0
    def structure(self, position, k, lmax):
        position = np.asarray(position)
        Nparticles = len(position)

        rmax = miepy.vsh.lmax_to_rmax(lmax)
        p_src = np.zeros([Nparticles, 2, rmax], dtype=complex)
        factor = self.amplitude*np.exp(1j*self.phase)

        for i in range(Nparticles):
            dr = position[i] - self.center

            if not np.any(dr):
                for r,n,m in miepy.mode_indices(lmax):
                    if n == self.n and m == self.m:
                        Emn = miepy.vsh.Emn(m, n)
                        p_src[i,0,r] = 1/(-1j*Emn)
            else:
                rad, theta, phi = miepy.coordinates.cart_to_sph(*dr)
                for r,n,m in miepy.mode_indices(lmax):
                    Emn = miepy.vsh.Emn(self.m, self.n)
                    Euv = miepy.vsh.Emn(m, n)
                    A, B = miepy.cpp.vsh_translation.vsh_translation(m, n, self.m, self.n, rad, theta, phi, k, self.mode)
                    p_src[i,0,r] = A/(-1j*Emn)
                    p_src[i,1,r] = B/(-1j*Emn)

        if self.ftype == 'magnetic':
            p_src = p_src[:, ::-1]

        return factor*p_src
Exemple #2
0
def tmatrix_core_shell(radius, thickness, wavelength, eps_core, eps_shell,
                       eps_m, lmax):
    """Compute the T-matrix of a core-shell, using regular Mie theory

    Arguments:
        radius      core radius
        wavelength  incident wavelength
        eps_core    particle permittivity
        eps_shell  shell permittivity
        eps_m       medium permittivity
        lmax        maximum number of multipoles
    """
    rmax = miepy.vsh.lmax_to_rmax(lmax)
    tmatrix = np.zeros([2, rmax, 2, rmax], dtype=complex)
    k_medium = 2 * np.pi * eps_m**0.5 / wavelength

    particle = miepy.single_mie_core_shell(
        radius,
        radius + thickness,
        material_in=miepy.dielectric(eps=eps_core),
        material_out=miepy.dielectric(eps=eps_shell),
        medium=miepy.dielectric(eps=eps_m),
        lmax=lmax,
        wavelength=wavelength)

    particle.solve()

    for i, n, m in miepy.mode_indices(lmax):
        tmatrix[0, i, 0, i] = -1j * particle.an[0, n - 1]
        tmatrix[1, i, 1, i] = -1j * particle.bn[0, n - 1]

    return tmatrix
Exemple #3
0
    def _solve_interactions(self):
        if self.symmetry is None:
            agg_tmatrix = miepy.interactions.sphere_aggregate_tmatrix(
                self.position, self.mie_scat, self.material_data.k_b)
        else:
            agg_tmatrix = miepy.interactions.sphere_aggregate_tmatrix_periodic(
                self.position, self.mie_scat, self.material_data.k_b,
                self.symmetry, self.source.k_hat)

        if self.interface is not None:
            r0 = self.interface.reflection_coefficients(
                theta=0, wavelength=self.wavelength, medium=self.medium)[0]
            z = self.interface.z
            R_matrix = miepy.interactions.reflection_matrix_nia(
                self.position, self.mie_scat, self.material_data.k_b, r0, z)
            agg_tmatrix -= R_matrix

        self.p_inc[...] = miepy.interactions.solve_linear_system(
            agg_tmatrix, self.p_src, method=miepy.solver.bicgstab)

        for r, n, m in miepy.mode_indices(self.lmax):
            self.p_scat[...,
                        r] = self.p_inc[..., r] * self.mie_scat[..., n - 1]
            self.p_int[...,
                       r] = self.p_inc[..., r] * self.mie_int[:, ::-1, n - 1]
Exemple #4
0
    def structure(self, position, k, lmax):
        position = np.asarray(position)

        Nparticles = len(position)
        rmax = miepy.vsh.lmax_to_rmax(lmax)

        p_src = np.empty([Nparticles, 2, rmax], dtype=complex)

        for j in range(Nparticles):
            phase = k * (self.k_hat[0] * position[j, 0] +
                         self.k_hat[1] * position[j, 1] +
                         self.k_hat[2] * position[j, 2]) + self.phase

            for i, n, m in miepy.mode_indices(lmax):
                pi_value = pi_func(n, m, self.theta)
                tau_value = tau_func(n, m, self.theta)
                Emn = np.abs(miepy.vsh.Emn(m, n))
                factor = self.amplitude * np.exp(1j *
                                                 (phase - m * self.phi)) * Emn

                p_src[j, 0,
                      i] = factor * (tau_value * self.polarization[0] -
                                     1j * pi_value * self.polarization[1])
                p_src[j, 1,
                      i] = factor * (pi_value * self.polarization[0] -
                                     1j * tau_value * self.polarization[1])

        return p_src
Exemple #5
0
    def _solve_without_interactions(self):
        self.p_inc[...] = self.p_src

        for r, n, m in miepy.mode_indices(self.lmax):
            self.p_scat[...,
                        r] = self.p_inc[..., r] * self.mie_scat[..., n - 1]
            self.p_int[...,
                       r] = self.p_inc[..., r] * self.mie_int[:, ::-1, n - 1]
Exemple #6
0
    def get_Q(p, q):
        Q = np.zeros([2, rmax, 2, rmax], dtype=complex)
        p_modes = ingoing if p == 1 else outgoing
        q_modes = ingoing if q == 1 else outgoing

        for r1, n1, m1 in miepy.mode_indices(lmax):
            M1_p_k2 = p_modes.M_k2[r1]
            N1_p_k2 = p_modes.N_k2[r1]
            M1_p_k1 = p_modes.M_k1[r1]
            N1_p_k1 = p_modes.N_k1[r1]

            for r2, n2, m2 in miepy.mode_indices(lmax):
                M2_q_k2 = q_modes.M_k2[r2]
                N2_q_k2 = q_modes.N_k2[r2]
                M2_q_k1 = q_modes.M_k1[r2]
                N2_q_k1 = q_modes.N_k1[r2]

                # factor = (-1)**(m2 - m1)
                factor = 1

                integrand = np.sum(np.cross(dS, M2_q_k2, axis=0)*N1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, N2_q_k2, axis=0)*M1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[1, r1, 1,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

                integrand = np.sum(np.cross(dS, N2_q_k2, axis=0)*N1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, M2_q_k2, axis=0)*M1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[1, r1, 0,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

                integrand = np.sum(np.cross(dS, M2_q_k2, axis=0)*M1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, N2_q_k2, axis=0)*N1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[0, r1, 1,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

                integrand = np.sum(np.cross(dS, N2_q_k2, axis=0)*M1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, M2_q_k2, axis=0)*N1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[0, r1, 0,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

        return Q
Exemple #7
0
def sphere_aggregate_tmatrix_periodic(positions, mie, k, symmetry, k_hat):
    """Obtain the particle-centered aggregate T-matrix for a cluster of spheres with a given periodic symmetry
       Returns T[N,2,rmax,N,2,rmax]
    
       Arguments:
           positions[N,3]      particles positions
           mie[N,2,lmax]       mie scattering coefficients
           k                   medium wavenumber
           symmetry            type of symmetry
           k_hat               unit k-vector
    """

    Nparticles = positions.shape[0]
    lmax = mie.shape[-1]
    rmax = miepy.vsh.lmax_to_rmax(lmax)
    # agg_tmatrix = np.zeros(shape=(Nparticles, 2, rmax, Nparticles, 2, rmax), dtype=complex)
    agg_tmatrix = sphere_aggregate_tmatrix(positions, mie, k)

    xpos, ypos, zpos = symmetry.generate(5000) 
    cells = np.array([xpos,ypos,zpos]).T


    for i in range(Nparticles):
        for j in range(Nparticles):
            dr = positions[i] - (cells + positions[j])
            rad, theta, phi = miepy.coordinates.cart_to_sph(dr[:,0], dr[:,1], dr[:,2])
            for r,n,m in miepy.mode_indices(lmax):
                for s,v,u in miepy.mode_indices(lmax):
                    phase_factor = np.exp(-1j*k*(k_hat[0]*xpos + k_hat[1]*ypos + k_hat[2]*zpos))
                    A_transfer, B_transfer = vsh_translation(m, n, u, v, 
                            rad, theta, phi, k, miepy.vsh_mode.outgoing)
                    for a in range(2):
                        for b in range(2):
                            val = (A_transfer, B_transfer)[(a+b)%2]*phase_factor
                            agg_tmatrix[i,a,r,j,b,s] += np.sum(val)*mie[j,b,v-1]

    return agg_tmatrix
Exemple #8
0
    def structure(self, position, k, lmax):
        rmax = miepy.vsh.lmax_to_rmax(lmax)
        p_src = np.zeros([2, rmax], dtype=complex)
        phase = k * (self.k_hat[0] * position[0] + self.k_hat[1] * position[1]
                     + self.k_hat[2] * position[2]) + self.phase

        for i, n, m in miepy.mode_indices(lmax):
            pi_value = pi_func(n, m, self.theta)
            tau_value = tau_func(n, m, self.theta)
            Emn = np.abs(miepy.vsh.Emn(m, n))
            factor = self.amplitude * np.exp(1j * (phase - m * self.phi)) * Emn

            p_src[0, i] = factor * (tau_value * self.polarization[0] -
                                    1j * pi_value * self.polarization[1])
            p_src[1, i] = factor * (pi_value * self.polarization[0] -
                                    1j * tau_value * self.polarization[1])

        return p_src
Exemple #9
0
def tmatrix_sphere(radius, wavelength, eps, eps_m, lmax, conducting=False):
    """Compute the T-matrix of a sphere, using regular Mie theory

    Arguments:
        radius      sphere radius
        wavelength  incident wavelength
        eps         particle permittivity
        eps_m       medium permittivity
        lmax        maximum number of multipoles
        conducting  if True, calculate for conducting sphere (default: False)
    """
    rmax = miepy.vsh.lmax_to_rmax(lmax)
    tmatrix = np.zeros([2, rmax, 2, rmax], dtype=complex)
    k_medium = 2 * np.pi * eps_m**0.5 / wavelength

    for i, n, m in miepy.mode_indices(lmax):
        an, bn = miepy.mie_single.mie_sphere_scattering_coefficients(
            radius, n, eps, 1, eps_m, 1, k_medium, conducting=conducting)
        tmatrix[0, i, 0, i] = an
        tmatrix[1, i, 1, i] = bn

    return tmatrix
Exemple #10
0
def cluster_cross_sections(p_cluster, p_src, k):
    """Compute the scattering, absorption, and extinction cross-sections for a cluster
       Return (scat[2,lmax], abs[2,lmax], extinct[2,lmax])
       
       Arguments:
           p_cluster[2,rmax]  cluster scattering coefficients
           p_src[2,rmax]      source scattering coefficients at origin
           k                  wavenumber
    """
    lmax = miepy.vsh.rmax_to_lmax(p_cluster.shape[1])

    Cscat = np.zeros([2, lmax], dtype=float)
    Cext = np.zeros([2, lmax], dtype=float)

    factor = 4 * np.pi / k**2

    for r, n, m in miepy.mode_indices(lmax):
        Cscat[:, n - 1] += factor * np.abs(p_cluster[:, r])**2
        Cext[:, n -
             1] += factor * np.real(np.conj(p_src[:, r]) * p_cluster[:, r])

    Cabs = Cext - Cscat
    return cross_sections(Cscat, Cabs, Cext)
Exemple #11
0
def rotate_tmatrix(tmatrix, quat):
    """Rotate a T-matrix
    
    Arguments:
        tmatrix    tmatrix to be rotated
        quat       quaternion representing the rotation

    Returns:
        The rotated T-matrix
    """
    rmax = tmatrix.shape[1]
    lmax = miepy.vsh.rmax_to_lmax(rmax)

    R = np.zeros([rmax, rmax], dtype=complex)

    for i, n, m in miepy.mode_indices(lmax):
        r = miepy.vsh.lmax_to_rmax(n)
        idx = np.s_[r - (2 * n + 1):r]
        R[idx, idx] = miepy.vsh.vsh_rotation_matrix(n, quat)

    tmatrix_rot = np.einsum('ms,uw,asbw->ambu', R, np.conjugate(R), tmatrix)

    return tmatrix_rot
Exemple #12
0
    def structure(self, position, k, lmax):
        position = np.asarray(position)
        Nparticles = len(position)

        rmax = miepy.vsh.lmax_to_rmax(lmax)
        p_src = np.zeros([Nparticles, 2, rmax], dtype=complex)
        factor = self.amplitude * np.exp(1j * self.phase)

        for i in range(Nparticles):
            dr = position[i] - self.position
            rad, theta, phi = miepy.coordinates.cart_to_sph(*dr)

            for r, n, m in miepy.mode_indices(lmax):
                for u in [-1, 0, 1]:
                    A, B = miepy.cpp.vsh_translation.vsh_translation(
                        m, n, u, 1, rad, theta, phi, k,
                        miepy.vsh_mode.outgoing)
                    p_src[i, 0, r] += -A * self.weight[u]
                    p_src[i, 1, r] += -B * self.weight[u]

        if self.mode == 'magnetic':
            p_src = p_src[:, ::-1]

        return factor * p_src
Exemple #13
0
def get_tmatrix(rad, dS, eps, eps_m, wavelength, lmax):
    _, Ntheta, Nphi = dS.shape
    theta = np.linspace(0, np.pi, Ntheta)
    phi = np.linspace(0, 2 * np.pi, Nphi)
    THETA, PHI = np.meshgrid(theta, phi, indexing='ij')
    dS = miepy.coordinates.vec_cart_to_sph(dS, THETA, PHI)

    rmax = lmax * (lmax + 2)
    k1 = 2 * np.pi / wavelength
    k2 = 2 * np.pi * np.sqrt(eps) / wavelength

    class ingoing:
        M_k2 = np.empty((rmax, 3) + THETA.shape, dtype=complex)
        N_k2 = np.empty((rmax, 3) + THETA.shape, dtype=complex)
        M_k1 = np.empty((rmax, 3) + THETA.shape, dtype=complex)
        N_k1 = np.empty((rmax, 3) + THETA.shape, dtype=complex)

    class outgoing:
        M_k2 = np.empty((rmax, 3) + THETA.shape, dtype=complex)
        N_k2 = np.empty((rmax, 3) + THETA.shape, dtype=complex)
        M_k1 = np.empty((rmax, 3) + THETA.shape, dtype=complex)
        N_k1 = np.empty((rmax, 3) + THETA.shape, dtype=complex)

    for r, n, m in miepy.mode_indices(lmax):
        Emn = miepy.vsh.Emn(m, n)

        Nfunc, Mfunc = miepy.vsh.VSH(n, m, miepy.vsh_mode.incident)
        ingoing.M_k2[r] = Emn * Mfunc(rad, THETA, PHI, k2)
        ingoing.N_k2[r] = Emn * Nfunc(rad, THETA, PHI, k2)
        ingoing.M_k1[r] = Emn * Mfunc(rad, THETA, PHI, k1)
        ingoing.N_k1[r] = Emn * Nfunc(rad, THETA, PHI, k1)

        Nfunc, Mfunc = miepy.vsh.VSH(n, m, miepy.vsh_mode.outgoing)
        outgoing.M_k2[r] = Emn * Mfunc(rad, THETA, PHI, k2)
        outgoing.N_k2[r] = Emn * Nfunc(rad, THETA, PHI, k2)
        outgoing.M_k1[r] = Emn * Mfunc(rad, THETA, PHI, k1)
        outgoing.N_k1[r] = Emn * Nfunc(rad, THETA, PHI, k1)

    def get_Q(p, q):
        Q = np.zeros([2, rmax, 2, rmax], dtype=complex)
        p_modes = ingoing if p == 1 else outgoing
        q_modes = ingoing if q == 1 else outgoing

        for r1, n1, m1 in miepy.mode_indices(lmax):
            M1_p_k2 = p_modes.M_k2[r1]
            N1_p_k2 = p_modes.N_k2[r1]
            M1_p_k1 = p_modes.M_k1[r1]
            N1_p_k1 = p_modes.N_k1[r1]

            for r2, n2, m2 in miepy.mode_indices(lmax):
                M2_q_k2 = q_modes.M_k2[r2]
                N2_q_k2 = q_modes.N_k2[r2]
                M2_q_k1 = q_modes.M_k1[r2]
                N2_q_k1 = q_modes.N_k1[r2]

                # factor = (-1)**(m2 - m1)
                factor = 1

                integrand = np.sum(np.cross(dS, M2_q_k2, axis=0)*N1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, N2_q_k2, axis=0)*M1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[1, r1, 1,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

                integrand = np.sum(np.cross(dS, N2_q_k2, axis=0)*N1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, M2_q_k2, axis=0)*M1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[1, r1, 0,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

                integrand = np.sum(np.cross(dS, M2_q_k2, axis=0)*M1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, N2_q_k2, axis=0)*N1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[0, r1, 1,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

                integrand = np.sum(np.cross(dS, N2_q_k2, axis=0)*M1_p_k1, axis=0) \
                            + np.sqrt(eps/eps_m)*np.sum(np.cross(dS, M2_q_k2, axis=0)*N1_p_k1, axis=0)
                integrand *= 1j * k1**2 / np.pi * factor
                Q[0, r1, 0,
                  r2] = miepy.vsh.misc.trapz_2d(theta, phi, integrand)

        return Q

    Q31 = -get_Q(3, 1)
    Q11 = get_Q(1, 1)

    T = -np.einsum('aibj,bjck->aick', Q11, np.linalg.tensorinv(Q31))

    return T
Exemple #14
0
def nfmds_solver(lmax,
                 input_kwargs,
                 solver=tmatrix_solvers.axisymmetric,
                 extended_precision=False):
    """Return the T-matrix using the Null-Field Method with discrete sources (NFM-DS)
       
    Arguments:
        lmax           maximum number of multipoles
        input_kwargs   keyword arguments forwarded to solver.input_function
        solver         type of solver to use (default: axisymmetric)
        extended_precision (bool)    whether to use extended precision (default: False)
    """
    rmax = miepy.vsh.lmax_to_rmax(lmax)

    if 'conducting' in input_kwargs and input_kwargs['conducting']:
        input_kwargs['index'] = 1

    ### create temporary directory tree
    with tempfile.TemporaryDirectory() as direc:
        ### create 4 sub-directories
        input_files_dir = '{direc}/INPUTFILES'.format(direc=direc)
        os.makedirs(input_files_dir)

        out_dir = '{direc}/OUTPUTFILES'.format(direc=direc)
        os.makedirs(out_dir)

        tmatrix_output_dir = '{direc}/TMATFILES'.format(direc=direc)
        os.makedirs(tmatrix_output_dir)

        sources_dir = '{direc}/TMATSOURCES'.format(direc=direc)
        os.makedirs(sources_dir)

        ### write 3 input files
        with open(
                '{input_files_dir}/Input.dat'.format(
                    input_files_dir=input_files_dir), 'w') as f:
            f.write(main_input_file())

        with open(
                '{input_files_dir}/InputSCT.dat'.format(
                    input_files_dir=input_files_dir), 'w') as f:
            f.write(sct_input_file())

        with open(
                '{input_files_dir}/Input{name}.dat'.format(
                    input_files_dir=input_files_dir, name=solver.name),
                'w') as f:
            f.write((solver.input_function(Nrank=lmax, **input_kwargs)))

        ### execute program and communicate
        install_path = miepy.__path__[0]
        if extended_precision:
            command = '{install_path}/bin/tmatrix_extended'.format(
                install_path=install_path)
        else:
            command = '{install_path}/bin/tmatrix'.format(
                install_path=install_path)

        proc = subprocess.Popen([command],
                                cwd=sources_dir,
                                stdout=subprocess.PIPE,
                                stdin=subprocess.PIPE)
        proc.communicate(str(solver.number).encode())
        proc.wait()

        ### read T-matrix dimensions
        with open(
                '{tmatrix_output_dir}/Infotmatrix.dat'.format(
                    tmatrix_output_dir=tmatrix_output_dir), 'r') as f:
            lines = f.readlines()

            ### last entries in the final two lines give Nrank, Mrank, respectively
            m_rank_str = lines[-1].split()[-1]
            n_rank_str = lines[-2].split()[-1]

            ### Remove the pesky comma and period from the string
            m_rank = int(m_rank_str[:-1])
            n_rank = int(n_rank_str[:-1])

        ### read T-matrix output
        tmatrix_file = '{tmatrix_output_dir}/tmatrix.dat'.format(
            tmatrix_output_dir=tmatrix_output_dir)
        data = pandas.read_csv(
            tmatrix_file, skiprows=3, delim_whitespace=True,
            header=None).values.flatten()  # read as flat array
        data = data[~np.isnan(data)]  # throw out the NaNs
        data_real = data[::2]  # every other element is the real part
        data_imag = data[1::2]

        ### restructure T-matrix
        T = np.zeros((2, rmax, 2, rmax), dtype=complex)

        if solver == tmatrix_solvers.axisymmetric:
            T_nfmds = np.reshape(data_real, (-1, 2*n_rank)) \
                      + 1j*np.reshape(data_imag, (-1, 2*n_rank))  # reshape the final result to have 2*n_rank columns

            for r1, n1, m1 in miepy.mode_indices(lmax,
                                                 m_start=-m_rank,
                                                 m_stop=m_rank):
                for r2, n2, m2 in miepy.mode_indices(lmax,
                                                     m_start=-m_rank,
                                                     m_stop=m_rank):
                    if m1 != m2:
                        continue

                    n_max = n_rank - max(1, abs(m1)) + 1
                    l1 = n1 - max(1, abs(m1))
                    l2 = n2 - max(1, abs(m2))

                    x = 2 * n_rank * abs(m1) + l1
                    y = l2

                    factor = -1j**(n2 - n1)
                    T[1, r1, 1, r2] = T_nfmds[x, y] * factor
                    T[0, r1, 0, r2] = T_nfmds[x + n_max, y + n_max] * factor
                    T[0, r1, 1,
                      r2] = T_nfmds[x + n_max, y] * factor * np.sign(m1)
                    T[1, r1, 0,
                      r2] = T_nfmds[x, y + n_max] * factor * np.sign(m2)
        else:

            def rindex(n, m):
                return (n - 1) * (n + 2) + m + 1

            M = (data_real + 1j * data_imag).reshape([2 * rmax, 2 * rmax])

            m1p, n1p = 0, 1
            for i in range(rmax):
                if n1p > n_rank:
                    if m1p >= 0:
                        m1p = -(m1p + 1)
                    else:
                        m1p = -m1p
                    n1p = abs(m1p)

                m2p, n2p = 0, 1
                for j in range(rmax):
                    if n2p > n_rank:
                        if m2p >= 0:
                            m2p = -(m2p + 1)
                        else:
                            m2p = -m2p
                        n2p = abs(m2p)

                    r1 = rindex(n1p, m1p)
                    r2 = rindex(n2p, m2p)

                    factor = -1j**(n2p - n1p)
                    f1 = 1
                    f2 = 1
                    if m1p % 2 == 1 and m2p % 2 == 1:
                        f1 *= np.sign(m1p * m2p)**(n1p + n2p + 1)
                        f2 *= np.sign(m1p * m2p)**(n1p + n2p)

                    T[0, r1, 0, r2] = M[rmax + i, rmax + j] * factor * f1
                    T[1, r1, 1, r2] = M[i, j] * factor * f1
                    T[0, r1, 1, r2] = -M[i + rmax, j] * factor * f2
                    T[1, r1, 0, r2] = -M[i, j + rmax] * factor * f2

                    n2p += 1

                n1p += 1

        return T