Esempio n. 1
0
    def get_operators(self, omega=OMEGA_1550):

        total_length = self.device_length + 2 * self.buffer_length + 2 * self.npml

        perms = np.ones((total_length, total_length), dtype=np.float64)

        start = self.npml + self.buffer_length
        end = start + self.device_length

        # set permittivity and reflection zone
        perms[:, :start] = self.buffer_permittivity
        perms[:start, :] = self.buffer_permittivity
        perms[:, end:] = self.buffer_permittivity
        perms[end:, :] = self.buffer_permittivity

        sim = Simulation(omega,
                         perms,
                         self.dl, [self.npml, self.npml],
                         self.mode,
                         L0=self.L0,
                         use_dirichlet_bcs=self.use_dirichlet_bcs)

        Dyb, Dxb, Dxf, Dyf = unpack_derivs(sim.derivs)

        N = np.asarray(perms.shape)
        M = np.prod(N)

        vector_eps_z = EPSILON0 * self.L0 * perms.reshape((-1, ))
        T_eps_z = sp.spdiags(vector_eps_z, 0, M, M, format='csr')

        curl_curl = (Dxf @ Dxb + Dyf @ Dyb)

        other = omega**2 * MU0 * self.L0 * T_eps_z

        return curl_curl.todense(), other.todense()
Esempio n. 2
0
def adjoint_linear_Hz(simulation, b_aj, averaging=False, solver=DEFAULT_SOLVER, matrix_format=DEFAULT_MATRIX_FORMAT):
    # Compute the adjoint field for a linear problem
    # Note: the correct definition requires simulating with the transpose matrix A.T
    EPSILON_0_ = EPSILON_0*simulation.L0
    MU_0_ = MU_0*simulation.L0
    omega = simulation.omega

    (Nx, Ny) = (simulation.Nx, simulation.Ny)
    M = Nx*Ny
    A = simulation.A

    hz = solver_direct(A.T, b_aj, solver=solver)
    (Dyb, Dxb, Dxf, Dyf) = unpack_derivs(simulation.derivs) 
    (Dyb_T, Dxb_T, Dxf_T, Dyf_T) = (Dyb.T, Dxb.T, Dxf.T, Dyf.T)

    if averaging:
        vector_eps_x = grid_average(EPSILON_0_*simulation.eps_r, 'x').reshape((-1,))
        vector_eps_y = grid_average(EPSILON_0_*simulation.eps_r, 'y').reshape((-1,))
    else:
        vector_eps_x = EPSILON_0_*simulation.eps_r.reshape((-1,))
        vector_eps_y = EPSILON_0_*simulation.eps_r.reshape((-1,))

    T_eps_x_inv = sp.spdiags(1/vector_eps_x, 0, M, M, format=matrix_format)
    T_eps_y_inv = sp.spdiags(1/vector_eps_y, 0, M, M, format=matrix_format)
    
    # Note: to get the correct gradient in the end, we must use Dxf, Dyf here   
    ex =  1/1j/omega * T_eps_y_inv.dot(Dyf_T).dot(hz).T
    ey = -1/1j/omega * T_eps_x_inv.dot(Dxf_T).dot(hz).T

    Ex = ex.reshape((Nx, Ny))
    Ey = ey.reshape((Nx, Ny))

    return (Ex, Ey)
Esempio n. 3
0
    def solve_fields(self,
                     include_nl=False,
                     timing=False,
                     averaging=False,
                     matrix_format=DEFAULT_MATRIX_FORMAT):
        # performs direct solve for A given source

        EPSILON_0_ = EPSILON_0 * self.L0
        MU_0_ = MU_0 * self.L0

        if include_nl == False:
            eps_tot = self.eps_r
            X = solver_direct(self.A,
                              self.src * 1j * self.omega,
                              timing=timing)
        else:
            eps_tot = self.eps_r + self.eps_nl
            X = solver_direct(self.A + self.Anl,
                              self.src * 1j * self.omega,
                              timing=timing)

        (Nx, Ny) = self.src.shape
        M = Nx * Ny
        (Dyb, Dxb, Dxf, Dyf) = unpack_derivs(self.derivs)

        if self.pol == 'Hz':
            if averaging:
                eps_x = grid_average(EPSILON_0_ * (eps_tot), 'x')
                vector_eps_x = eps_x.reshape((-1, ))
                eps_y = grid_average(EPSILON_0_ * (eps_tot), 'y')
                vector_eps_y = eps_y.reshape((-1, ))
            else:
                vector_eps_x = EPSILON_0_ * (eps_tot).reshape((-1, ))
                vector_eps_y = EPSILON_0_ * (eps_tot).reshape((-1, ))

            T_eps_x_inv = sp.spdiags(1 / vector_eps_x,
                                     0,
                                     M,
                                     M,
                                     format=matrix_format)
            T_eps_y_inv = sp.spdiags(1 / vector_eps_y,
                                     0,
                                     M,
                                     M,
                                     format=matrix_format)

            ex = 1 / 1j / self.omega * T_eps_y_inv.dot(Dyb).dot(X)
            ey = -1 / 1j / self.omega * T_eps_x_inv.dot(Dxb).dot(X)

            Ex = ex.reshape((Nx, Ny))
            Ey = ey.reshape((Nx, Ny))
            Hz = X.reshape((Nx, Ny))

            if include_nl == False:
                self.fields['Ex'] = Ex
                self.fields['Ey'] = Ey
                self.fields['Hz'] = Hz

            return (Ex, Ey, Hz)

        elif self.pol == 'Ez':
            hx = -1 / 1j / self.omega / MU_0_ * Dyb.dot(X)
            hy = 1 / 1j / self.omega / MU_0_ * Dxb.dot(X)

            Hx = hx.reshape((Nx, Ny))
            Hy = hy.reshape((Nx, Ny))
            Ez = X.reshape((Nx, Ny))

            if include_nl == False:
                self.fields['Hx'] = Hx
                self.fields['Hy'] = Hy
                self.fields['Ez'] = Ez

            return (Hx, Hy, Ez)

        else:
            raise ValueError('Invalid polarization: {}'.format(str(self.pol)))