Beispiel #1
0
    def test_pol(self):

        # polarization not a string
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, self.dl, self.NPML, 5)

        # polarization not the right string
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, self.dl, self.NPML,
                       'WrongPolarization')
Beispiel #2
0
    def test_dl(self):

        # negative dl
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, -self.dl, self.NPML, self.pol)

        # list of dl
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, [1e-4, 1e-5], self.NPML,
                       self.pol)
Beispiel #3
0
    def test_eps(self):

        # negative epsilon
        with self.assertRaises(ValueError):
            Simulation(self.omega, -self.eps_r, self.dl, self.NPML, self.pol)

        # list epsilon instead of numpy array
        with self.assertRaises(ValueError):
            Simulation(self.omega, list(self.eps_r), self.dl, self.NPML,
                       self.pol)
Beispiel #4
0
    def test_freq(self):

        # negative frequency
        with self.assertRaises(ValueError):
            Simulation(-self.omega, self.eps_r, self.dl, self.NPML, self.pol)

        # list of frequencies
        with self.assertRaises(ValueError):
            Simulation([100, 200, 300], self.eps_r, self.dl, self.NPML,
                       self.pol)
Beispiel #5
0
    def test_NPML(self):

        # NPML a number
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, self.dl, 10, self.pol)

        # NPML too many elements
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, self.dl, [10, 10, 10], self.pol)

        # NPML larger than domain
        with self.assertRaises(ValueError):
            Simulation(self.omega, self.eps_r, self.dl, [200, 200], self.pol)
Beispiel #6
0
    def test_born_newton(self):
        """Tests whether born and newton methods get the same result"""

        n0 = 3.4
        omega = 2*np.pi*200e12
        dl = 0.01
        chi3 = 2.8E-18

        width = 1
        L = 5
        L_chi3 = 4

        width_voxels = int(width/dl)
        L_chi3_voxels = int(L_chi3/dl)

        Nx = int(L/dl)
        Ny = int(3.5*width/dl)

        eps_r = np.ones((Nx, Ny))
        eps_r[:, int(Ny/2-width_voxels/2):int(Ny/2+width_voxels/2)] = np.square(n0)

        nl_region = np.zeros(eps_r.shape)
        nl_region[int(Nx/2-L_chi3_voxels/2):int(Nx/2+L_chi3_voxels/2), int(Ny/2-width_voxels/2):int(Ny/2+width_voxels/2)] = 1

        simulation = Simulation(omega, eps_r, dl, [15, 15], 'Ez')
        simulation.add_mode(n0, 'x', [17, int(Ny/2)], width_voxels*3)
        simulation.setup_modes()
        simulation.add_nl(chi3, nl_region, eps_scale=True, eps_max=np.max(eps_r))

        srcval_vec = np.logspace(1, 3, 3)
        pwr_vec = np.array([])
        T_vec = np.array([])
        for srcval in srcval_vec:
            simulation.setup_modes()
            simulation.src *= srcval

            # Newton
            simulation.solve_fields_nl(solver_nl='newton')
            E_newton = simulation.fields["Ez"]

            # Born
            simulation.solve_fields_nl(solver_nl='born')
            E_born = simulation.fields["Ez"]

            # More solvers (if any) should be added here with corresponding calls to assert_allclose() below

            assert_allclose(E_newton, E_born, rtol=1e-3)
Beispiel #7
0
    def test_chi3(self):
        """Tests whether we get a nonlinear phase shift (self phase modulation) which agrees with analytical predictions"""

        # Set simulation parameters
        n0 = 3.4
        omega = 2 * pi * 200e12
        dl = 0.01
        chi3 = 2.8E-18

        width = 1  # WG width
        L = 5  # WG length
        L_chi3 = 4  # WG nonlinear length

        # Convert to voxels
        width_voxels = int(width / dl)
        L_chi3_voxels = int(L_chi3 / dl)
        Nx = int(L / dl)
        Ny = int(3.5 * width / dl)

        # Setup
        eps_r = ones((Nx, Ny))
        eps_r[:,
              int(Ny / 2 -
                  width_voxels / 2):int(Ny / 2 +
                                        width_voxels / 2)] = square(n0)
        nl_region = zeros(eps_r.shape)
        nl_region[int(Nx / 2 - L_chi3_voxels / 2):int(Nx / 2 +
                                                      L_chi3_voxels / 2),
                  int(Ny / 2 - width_voxels / 2):int(Ny / 2 +
                                                     width_voxels / 2)] = 1
        simulation = Simulation(omega, eps_r, dl, [15, 15], 'Ez')
        simulation.add_mode(n0, 'x', [17, int(Ny / 2)], width_voxels * 3)
        simulation.setup_modes()
        simulation.solve_fields()

        # Probe field from linear simulation to get phase
        fld0 = simulation.fields['Ez'][20, int(Ny / 2)]
        fld1 = simulation.fields['Ez'][Nx - 20, int(Ny / 2)]
        T_linear = fld1 / fld0

        # Set nonlinear functions
        kerr_nonlinearity = lambda e: 3 * chi3 / square(simulation.L0
                                                        ) * square(abs(e))
        dkerr_de = lambda e: 3 * chi3 / square(simulation.L0) * conj(e)

        # Sweep source power and record nonlinear phase accumulation
        srcval_vec = logspace(1, 3, 3)
        pwr_vec = array([])
        T_vec = array([])
        for srcval in srcval_vec:
            simulation.setup_modes()
            simulation.src *= srcval
            simulation.solve_fields_nl(kerr_nonlinearity,
                                       nl_region,
                                       dnl_de=dkerr_de,
                                       timing=False,
                                       averaging=True,
                                       Estart=None,
                                       solver_nl='newton')
            fld0 = simulation.fields['Ez'][20, int(Ny / 2)]
            fld1 = simulation.fields['Ez'][Nx - 20, int(Ny / 2)]
            T_vec = append(T_vec, fld1 / fld0)
            pwr = simulation.flux_probe('x', [Nx - 20, int(Ny / 2)],
                                        width_voxels * 3)
            pwr_vec = append(pwr_vec, pwr)

        # Analytically calculate the expected nonlinear phase accumulation
        n2 = 12 * square(pi) * chi3 * 1e4 / square(n0)
        n2 *= 1e-4 / square(simulation.L0)

        width = dl * width_voxels
        height = width
        Aeff = width * height

        L = dl * L_chi3_voxels
        gamma_spm = (omega / 299792458 * simulation.L0) * n2 / Aeff

        P = pwr_vec * height  # Power
        Phi_fdfd = -unwrap(angle(T_vec) -
                           angle(T_linear)) / pi  # Nonlinear phase in FDFD
        Phi_analytic = (
            pwr_vec * height) * L * gamma_spm / pi  # Analytic nonlinear phase

        # If our simulation is correct, these values should be equal
        assert_allclose(Phi_fdfd, Phi_analytic, rtol=1e-3)
Beispiel #8
0
    def test_flux(self):
        """Tests whether we can reduce the mesh resolution and get the same flux_probe output"""

        omega = 2 * pi * 200e12
        dl = 0.01
        eps_r = ones((300, 100))
        eps_r[:, 40:60] = 12.25
        NPML = [15, 15]

        simulation1 = Simulation(omega, eps_r, dl, NPML, 'Ez')
        simulation1.add_mode(3.5, 'x', [20, 50], 60, scale=1)
        simulation1.setup_modes()
        simulation1.solve_fields()
        flux1 = simulation1.flux_probe('x', [150, 50], 60)

        omega = 2 * pi * 200e12
        dl = 0.005
        eps_r = ones((600, 200))
        eps_r[:, 80:120] = 12.25
        NPML = [15, 15]
        simulation2 = Simulation(omega, eps_r, dl, NPML, 'Ez')
        simulation2.add_mode(3.5, 'x', [20, 100], 120, scale=1)
        simulation2.setup_modes()
        simulation2.solve_fields()
        flux2 = simulation2.flux_probe('x', [300, 100], 120)

        assert_allclose(flux1, flux2, rtol=1e-3)