Example #1
0
def create_adjoint_sources(
        monitors: Iterable[ObjectiveQuantity],
        monitor_values_grad: onp.ndarray) -> List[mp.Source]:
    monitor_values_grad = onp.asarray(
        monitor_values_grad,
        dtype=onp.complex64 if mp.is_single_precision() else onp.complex128)
    if not onp.any(monitor_values_grad):
        raise RuntimeError(
            'The gradient of all monitor values is zero, which '
            'means that no adjoint sources can be placed to set '
            'up an adjoint simulation in Meep. Possible causes '
            'could be:\n\n'
            ' * the forward simulation was not run for long enough '
            'to allow the input pulse(s) to reach the monitors'
            ' * the monitor values are disconnected from the '
            'objective function output.')
    adjoint_sources = []
    for monitor_idx, monitor in enumerate(monitors):
        # `dj` for each monitor will have a shape of (num frequencies,)
        dj = onp.asarray(monitor_values_grad[monitor_idx],
                         dtype=onp.complex64
                         if mp.is_single_precision() else onp.complex128)
        if onp.any(dj):
            adjoint_sources += monitor.place_adjoint_source(dj)
    assert adjoint_sources
    return adjoint_sources
 def test_1d_slice_user_array(self):
     self.sim.run(until_after_sources=0)
     arr = np.zeros(
         126, dtype=np.float32 if mp.is_single_precision() else np.float64)
     vol = mp.Volume(center=self.center_1d, size=self.size_1d)
     self.sim.get_array(mp.Hz, vol, arr=arr)
     tol = 1e-5 if mp.is_single_precision() else 1e-8
     self.assertClose(self.expected_1d, arr, epsilon=tol)
    def test_adjoint_solver_eigenmode(self):
        print("*** TESTING EIGENMODE ADJOINT ***")

        ## test the single frequency and multi frequency case
        for frequencies in [[fcen], [1 / 1.58, fcen, 1 / 1.53]]:
            ## compute gradient using adjoint solver
            adjsol_obj, adjsol_grad = adjoint_solver(p,
                                                     MonitorObject.EIGENMODE,
                                                     frequencies)

            ## compute unperturbed S12
            S12_unperturbed = forward_simulation(p, MonitorObject.EIGENMODE,
                                                 frequencies)

            ## compare objective results
            print(
                "S12 -- adjoint solver: {}, traditional simulation: {}".format(
                    adjsol_obj, S12_unperturbed))
            self.assertClose(adjsol_obj, S12_unperturbed, epsilon=1e-6)

            ## compute perturbed S12
            S12_perturbed = forward_simulation(p + dp, MonitorObject.EIGENMODE,
                                               frequencies)

            ## compare gradients
            if adjsol_grad.ndim < 2:
                adjsol_grad = np.expand_dims(adjsol_grad, axis=1)
            adj_scale = (dp[None, :] @ adjsol_grad).flatten()
            fd_grad = S12_perturbed - S12_unperturbed
            print(
                "Directional derivative -- adjoint solver: {}, FD: {}".format(
                    adj_scale, fd_grad))
            tol = 0.04 if mp.is_single_precision() else 0.01
            self.assertClose(adj_scale, fd_grad, epsilon=tol)
    def test_complex_fields(self):
        print("*** TESTING COMPLEX FIELDS ***")

        for frequencies in [[fcen], [1 / 1.58, fcen, 1 / 1.53]]:
            ## compute gradient using adjoint solver
            adjsol_obj, adjsol_grad = adjoint_solver_complex_fields(
                p, frequencies)

            ## compute unperturbed |Ez|^2
            Ez2_unperturbed = forward_simulation_complex_fields(p, frequencies)

            ## compare objective results
            print(
                "Ez2 -- adjoint solver: {}, traditional simulation: {}".format(
                    adjsol_obj, Ez2_unperturbed))
            self.assertClose(adjsol_obj, Ez2_unperturbed, epsilon=1e-6)

            ## compute perturbed |Ez|^2
            Ez2_perturbed = forward_simulation_complex_fields(
                p + dp, frequencies)

            ## compare gradients
            if adjsol_grad.ndim < 2:
                adjsol_grad = np.expand_dims(adjsol_grad, axis=1)
            adj_scale = (dp[None, :] @ adjsol_grad).flatten()
            fd_grad = Ez2_perturbed - Ez2_unperturbed
            print(
                "Directional derivative -- adjoint solver: {}, FD: {}".format(
                    adj_scale, fd_grad))
            tol = 0.018 if mp.is_single_precision() else 0.002
            self.assertClose(adj_scale, fd_grad, epsilon=tol)
Example #5
0
    def test_resonant_modes(self):
        self.sim.sources = [
            mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df), mp.Hz,
                      mp.Vector3())
        ]

        self.sim.symmetries = [
            mp.Mirror(mp.Y, phase=-1),
            mp.Mirror(mp.X, phase=-1)
        ]

        self.sim.use_output_directory(self.temp_dir)
        h = mp.Harminv(mp.Hz, mp.Vector3(), self.fcen, self.df)
        self.sim.run(mp.at_beginning(mp.output_epsilon),
                     mp.after_sources(h),
                     until_after_sources=400)

        expected = [
            0.23445415346009466,
            -3.147812367338531e-4,
            372.40808234438254,
            5.8121430334347135,
            -3.763107485715599,
            -4.429450156854109,
        ]

        m = h.modes[0]
        res = [m.freq, m.decay, m.Q, abs(m.amp), m.amp.real, m.amp.imag]

        tol = 1e-6 if mp.is_single_precision() else 1e-8
        self.assertClose(expected, res, epsilon=tol)
    def test_damping(self):
        print("*** TESTING CONDUCTIVITIES ***")

        for frequencies in [[1 / 1.58, fcen, 1 / 1.53]]:
            ## compute gradient using adjoint solver
            adjsol_obj, adjsol_grad = adjoint_solver_damping(p, frequencies)

            ## compute unperturbed S12
            S12_unperturbed = forward_simulation_damping(p, frequencies)

            ## compare objective results
            print(
                "S12 -- adjoint solver: {}, traditional simulation: {}".format(
                    adjsol_obj, S12_unperturbed))
            self.assertClose(adjsol_obj, S12_unperturbed, epsilon=1e-6)

            ## compute perturbed S12
            S12_perturbed = forward_simulation_damping(p + dp, frequencies)

            ## compare gradients
            if adjsol_grad.ndim < 2:
                adjsol_grad = np.expand_dims(adjsol_grad, axis=1)
            adj_scale = (dp[None, :] @ adjsol_grad).flatten()
            fd_grad = S12_perturbed - S12_unperturbed
            print(
                "Directional derivative -- adjoint solver: {}, FD: {}".format(
                    adj_scale, fd_grad))
            tol = 0.06 if mp.is_single_precision() else 0.03
            self.assertClose(adj_scale, fd_grad, epsilon=tol)
Example #7
0
    def test_fields_at_kx(self):
        self.sim.k_point = mp.Vector3(3.5)
        h = mp.Harminv(mp.Hz, mp.Vector3(0.1234), self.fcen, self.df)
        self.sim.run(mp.after_sources(h), until_after_sources=300)

        expected = [
            (0.19990240131986522, 3.8522735413802275e-8),
            (0.3050067740183294, 4.720168254531566e-7),
            (0.4396104226078593, 1.6233300291010948e-6),
            (0.4582004346509184, 4.7150006592976396e-7),
            (0.5006556112859917, -0.0014396635723422887),
            (0.7405953267896378, -4.553109069353934e-5),
            (0.7627621012715363, -0.006700351645723407),
            (0.8243404528365005, -5.174379068176951e-4),
            (0.8255990399390389, -0.0016256261502000271),
            (0.9494859645499801, -0.005325208458639275),
            (0.9726561278186849, -0.0031192234222098274),
            (0.9855957702101914, -0.003945157134867143),
        ]

        self.assertTrue(h.modes)
        places = 4 if mp.is_single_precision() else 7
        for (r, i), m in zip(expected, h.modes):
            self.assertAlmostEqual(m.freq, r, places=places)
            self.assertAlmostEqual(m.decay, i, places=places)
Example #8
0
    def test_adjoint_solver_cyl_n2f_fields(self):
        print("*** TESTING CYLINDRICAL Near2Far ADJOINT FEATURES ***")
        adjsol_obj, adjsol_grad = adjoint_solver(p)

        ## compute unperturbed S12
        S12_unperturbed = forward_simulation(p)

        ## compare objective results
        print(
            "|Er|^2 -- adjoint solver: {}, traditional simulation: {}".format(
                adjsol_obj, S12_unperturbed))
        self.assertClose(adjsol_obj, S12_unperturbed, epsilon=1e-3)

        ## compute perturbed S12
        S12_perturbed = forward_simulation(p + dp)

        ## compare gradients
        if adjsol_grad.ndim < 2:
            adjsol_grad = np.expand_dims(adjsol_grad, axis=1)
        adj_scale = (dp[None, :] @ adjsol_grad).flatten()
        fd_grad = S12_perturbed - S12_unperturbed
        print("Directional derivative -- adjoint solver: {}, FD: {}".format(
            adj_scale, fd_grad))
        tol = 0.2 if mp.is_single_precision() else 0.1
        self.assertClose(adj_scale, fd_grad, epsilon=tol)
Example #9
0
    def test_refl_angular(self, theta):
        fmeep, tmeep, Rmeep = self.refl_angular(theta)

        # angle of refracted planewave in medium n2 for an
        # incident planewave in medium n1 at angle theta_in
        theta_out = lambda theta_in: math.asin(self.n1 * math.sin(theta_in) /
                                               self.n2)

        # Fresnel reflectance for P polarization in medium n2 for
        # an incident planewave in medium n1 at angle theta_in
        Rfresnel = lambda theta_in: (math.fabs(
            (self.n1 * math.cos(theta_out(theta_in)) - self
             .n2 * math.cos(theta_in)) / (self.n1 * math.cos(
                 theta_out(theta_in)) + self.n2 * math.cos(theta_in)))**2)

        Ranalytic = np.empty((self.nfreq, ))
        print(
            "refl:, wavelength (μm), incident angle (°), reflectance (Meep), reflectance (analytic), error"
        )
        for i in range(self.nfreq):
            Ranalytic[i] = Rfresnel(tmeep[i])
            err = abs(Rmeep[i] - Ranalytic[i]) / Ranalytic[i]
            print("refl:, {:4.2f}, {:4.2f}, {:8.6f}, {:8.6f}, {:6.4f}".format(
                1 / fmeep[i], math.degrees(tmeep[i]), Rmeep[i], Ranalytic[i],
                err))

        tol = 0.005 if mp.is_single_precision() else 0.004
        self.assertClose(Rmeep, Ranalytic, epsilon=tol)
    def test_integrate2_field_function(self):
        sim = self.init2()
        sim.run(until_after_sources=10)
        fields2 = sim.fields
        sim.reset_meep()
        sim.run(until_after_sources=10)

        res1 = sim.integrate2_field_function(fields2, [mp.Ez], [mp.Ez], f2)
        places = 6 if mp.is_single_precision() else 7
        self.assertAlmostEqual(res1, 0.17158099566244897, places=places)
Example #11
0
    def test_gradient_backpropagation(self):
        print("*** TESTING BACKPROP ***")

        for frequencies in [[fcen], [1 / 1.58, fcen, 1 / 1.53]]:
            ## filter/thresholding parameters
            filter_radius = 0.21985
            eta = 0.49093
            beta = 4.0698

            mapped_p = mapping(p, filter_radius, eta, beta)

            ## compute gradient using adjoint solver
            adjsol_obj, adjsol_grad = adjoint_solver(mapped_p,
                                                     MonitorObject.EIGENMODE,
                                                     frequencies)

            ## backpropagate the gradient
            if len(frequencies) > 1:
                bp_adjsol_grad = np.zeros(adjsol_grad.shape)
                for i in range(len(frequencies)):
                    bp_adjsol_grad[:, i] = tensor_jacobian_product(mapping, 0)(
                        p, filter_radius, eta, beta, adjsol_grad[:, i])
            else:
                bp_adjsol_grad = tensor_jacobian_product(mapping,
                                                         0)(p, filter_radius,
                                                            eta, beta,
                                                            adjsol_grad)

            ## compute unperturbed S12
            S12_unperturbed = forward_simulation(mapped_p,
                                                 MonitorObject.EIGENMODE,
                                                 frequencies)

            ## compare objective results
            print(
                "S12 -- adjoint solver: {}, traditional simulation: {}".format(
                    adjsol_obj, S12_unperturbed))
            self.assertClose(adjsol_obj, S12_unperturbed, epsilon=1e-6)

            ## compute perturbed S12
            S12_perturbed = forward_simulation(
                mapping(p + dp, filter_radius, eta, beta),
                MonitorObject.EIGENMODE, frequencies)

            if bp_adjsol_grad.ndim < 2:
                bp_adjsol_grad = np.expand_dims(bp_adjsol_grad, axis=1)
            adj_scale = (dp[None, :] @ bp_adjsol_grad).flatten()
            fd_grad = S12_perturbed - S12_unperturbed
            print(
                "Directional derivative -- adjoint solver: {}, FD: {}".format(
                    adj_scale, fd_grad))
            tol = 0.02 if mp.is_single_precision() else 0.01
            self.assertClose(adj_scale, fd_grad, epsilon=tol)
Example #12
0
    def test_divide_parallel_processes(self):
        resolution = 20

        sxy = 4
        dpml = 1
        cell = mp.Vector3(sxy + 2 * dpml, sxy + 2 * dpml)

        pml_layers = [mp.PML(dpml)]

        n = mp.divide_parallel_processes(2)
        fcen = 1.0 / (n + 1)

        sources = [
            mp.Source(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen),
                      center=mp.Vector3(),
                      component=mp.Ez)
        ]

        symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)]

        self.sim = mp.Simulation(cell_size=cell,
                                 resolution=resolution,
                                 sources=sources,
                                 symmetries=symmetries,
                                 boundary_layers=pml_layers)

        flux_box = self.sim.add_flux(fcen,
                                     0,
                                     1,
                                     mp.FluxRegion(mp.Vector3(y=0.5 * sxy),
                                                   size=mp.Vector3(sxy)),
                                     mp.FluxRegion(mp.Vector3(y=-0.5 * sxy),
                                                   size=mp.Vector3(sxy),
                                                   weight=-1),
                                     mp.FluxRegion(mp.Vector3(0.5 * sxy),
                                                   size=mp.Vector3(y=sxy)),
                                     mp.FluxRegion(mp.Vector3(-0.5 * sxy),
                                                   size=mp.Vector3(y=sxy),
                                                   weight=-1),
                                     decimation_factor=1)

        self.sim.run(until_after_sources=30)

        tot_flux = mp.get_fluxes(flux_box)[0]

        tot_fluxes = mp.merge_subgroup_data(tot_flux)
        fcens = mp.merge_subgroup_data(fcen)

        self.assertEqual(fcens[0], 1)
        self.assertEqual(fcens[1], 0.5)
        places = 4 if mp.is_single_precision() else 7
        self.assertAlmostEqual(tot_fluxes[0], 9.8628728533, places=places)
        self.assertAlmostEqual(tot_fluxes[1], 19.6537275387, places=places)
Example #13
0
    def test_user_material_func(self):
        sim = mp.Simulation(cell_size=self.cell,
                            resolution=self.resolution,
                            symmetries=self.symmetries,
                            boundary_layers=self.boundary_layers,
                            sources=self.sources,
                            material_function=my_material_func)

        sim.run(until=200)
        fp = sim.get_field_point(mp.Ez, mp.Vector3(x=1))

        places = 3 if mp.is_single_precision() else 7
        self.assertAlmostEqual(fp, 4.816403627871773e-4, places=places)
Example #14
0
    def test_3rd_harm_1d(self):

        expected_harmonics = [0.01, 1.0, 221.89548712071553, 1.752960413399477]

        self.sim.run(
            until_after_sources=mp.stop_when_fields_decayed(
                50, mp.Ex, mp.Vector3(0, 0, (0.5 * self.sz) - self.dpml - 0.5), 1e-6
            )
        )

        harmonics = [self.k, self.amp, mp.get_fluxes(self.trans1)[0], mp.get_fluxes(self.trans3)[0]]

        tol = 3e-5 if mp.is_single_precision() else 1e-7
        self.assertClose(expected_harmonics, harmonics, epsilon=tol)
Example #15
0
    def test_pw_source(self):
        self.sim.run(mp.at_end(mp.output_efield_z), until=400)

        v1 = mp.Vector3(0.5 * self.s, 0)
        v2 = mp.Vector3(0.5 * self.s, 0.5 * self.s)

        pt1 = self.sim.get_field_point(mp.Ez, v1)
        pt2 = self.sim.get_field_point(mp.Ez, v2)

        tol = 1e-4 if mp.is_single_precision() else 1e-9
        self.assertClose(pt1 / pt2, 27.557668029008262, epsilon=tol)

        self.assertAlmostEqual(cmath.exp(1j * self.k.dot(v1 - v2)),
                               0.7654030066070924 - 0.6435512702783076j)
Example #16
0
    def test_offdiagonal(self):
        print("*** TESTING OFFDIAGONAL COMPONENTS ***")
        filt = lambda x: mpa.conic_filter(x.reshape(
            (Nx, Ny)), 0.25, design_region_size.x, design_region_size.y,
                                          design_region_resolution).flatten()

        ## test the single frequency and multi frequency case
        for frequencies in [[fcen], [1 / 1.58, fcen, 1 / 1.53]]:
            ## compute gradient using adjoint solver
            adjsol_obj, adjsol_grad = adjoint_solver(filt(p),
                                                     MonitorObject.EIGENMODE,
                                                     frequencies, sapphire)

            ## backpropagate the gradient
            if len(frequencies) > 1:
                bp_adjsol_grad = np.zeros(adjsol_grad.shape)
                for i in range(len(frequencies)):
                    bp_adjsol_grad[:, i] = tensor_jacobian_product(filt, 0)(
                        p, adjsol_grad[:, i])
            else:
                bp_adjsol_grad = tensor_jacobian_product(filt, 0)(p,
                                                                  adjsol_grad)

            ## compute unperturbed S12
            S12_unperturbed = forward_simulation(filt(p),
                                                 MonitorObject.EIGENMODE,
                                                 frequencies, sapphire)

            ## compare objective results
            print(
                "S12 -- adjoint solver: {}, traditional simulation: {}".format(
                    adjsol_obj, S12_unperturbed))
            self.assertClose(adjsol_obj, S12_unperturbed, epsilon=1e-6)

            ## compute perturbed S12
            S12_perturbed = forward_simulation(filt(p + dp),
                                               MonitorObject.EIGENMODE,
                                               frequencies, sapphire)

            ## compare gradients
            if bp_adjsol_grad.ndim < 2:
                bp_adjsol_grad = np.expand_dims(bp_adjsol_grad, axis=1)
            adj_scale = (dp[None, :] @ bp_adjsol_grad).flatten()
            fd_grad = S12_perturbed - S12_unperturbed
            print(
                "Directional derivative -- adjoint solver: {}, FD: {}".format(
                    adj_scale, fd_grad))
            tol = 0.1 if mp.is_single_precision() else 0.04
            self.assertClose(adj_scale, fd_grad, epsilon=tol)
Example #17
0
    def test_numpy_epsilon(self):
        sim = self.init_simple_simulation()
        eps_input_fname = 'cyl-ellipsoid-eps-ref.h5'
        eps_input_dir = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
                         '..', 'tests'))
        eps_input_path = os.path.join(eps_input_dir, eps_input_fname)

        with h5py.File(eps_input_path, 'r') as f:
            sim.default_material = f['eps'][()]

        sim.run(until=200)
        fp = sim.get_field_point(mp.Ez, mp.Vector3(x=1))

        places = 6 if mp.is_single_precision() else 7
        self.assertAlmostEqual(fp, -0.002989654055823199, places=places)
    def call_chi1(self,material,frequency):

        sim = mp.Simulation(cell_size=mp.Vector3(1,1,1),
                    default_material=material,
                    resolution=20)

        sim.init_sim()
        v3 = mp.py_v3_to_vec(sim.dimensions, mp.Vector3(0,0,0), sim.is_cylindrical)
        chi1inv = np.zeros((3,3),dtype=np.complex128)
        for i, com in enumerate([mp.Ex,mp.Ey,mp.Ez]):
            for k, dir in enumerate([mp.X,mp.Y,mp.Z]):
                chi1inv[i,k] = sim.structure.get_chi1inv(com,dir,v3,frequency)
        n = np.real(np.sqrt(np.linalg.inv(chi1inv.astype(np.complex128))))

        n_actual = np.real(np.sqrt(material.epsilon(frequency).astype(np.complex128)))

        tol = 1e-6 if mp.is_single_precision() else 1e-8
        self.assertClose(n, n_actual, epsilon=tol)
Example #19
0
    def test_ring_cyl(self):
        expected = [
            0.11835455441250553,
            -6.907792691629741e-4,
            85.66741917133473,
            0.025701906263451237,
            -0.024027038833537524,
            -0.009126302124459489,
        ]

        h = mp.Harminv(mp.Ez, mp.Vector3(self.r + 0.1), self.fcen, self.df)
        self.sim.run(mp.after_sources(h), until_after_sources=200)

        m = h.modes[0]
        res = [m.freq, m.decay, m.Q, abs(m.amp), m.amp.real, m.amp.imag]

        tol = 1e-6 if mp.is_single_precision() else 1e-7
        self.assertClose(expected, res, epsilon=tol)
Example #20
0
    def test_force(self):

        self.sim.run(until_after_sources=mp.stop_when_fields_decayed(
            50, mp.Ez, mp.Vector3(), 1e-6))

        # Test store and load of force as numpy array
        fdata = self.sim.get_force_data(self.myforce)
        self.sim.load_force_data(self.myforce, fdata)

        self.sim.display_forces(self.myforce)
        f = mp.get_forces(self.myforce)

        self.assertAlmostEqual(f[0], -0.11039089113393187)

        places = 6 if mp.is_single_precision() else 7
        self.assertAlmostEqual(f[0],
                               mp.get_forces(self.myforce_decimated)[0],
                               places=places)
Example #21
0
    def test_custom_source(self):
        n = 3.4
        w = 1
        r = 1
        pad = 4
        dpml = 2
        sxy = 2 * (r + w + pad + dpml)

        cell = mp.Vector3(sxy, sxy)

        geometry = [
            mp.Cylinder(r + w, material=mp.Medium(index=n)),
            mp.Cylinder(r, material=mp.air)
        ]

        boundary_layers = [mp.PML(dpml)]
        resolution = 10
        fcen = 0.15
        df = 0.1

        # Bump function
        def my_src_func(t):
            if t > 0 and t < 2:
                return math.exp(-1 / (1 - ((t - 1)**2)))
            return 0j

        sources = [mp.Source(src=mp.CustomSource(src_func=my_src_func, end_time=100),
                             component=mp.Ez, center=mp.Vector3(r + 0.1))]

        symmetries = [mp.Mirror(mp.Y)]

        sim = mp.Simulation(cell_size=cell,
                            resolution=resolution,
                            geometry=geometry,
                            boundary_layers=boundary_layers,
                            sources=sources,
                            symmetries=symmetries)

        h = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df)
        sim.run(mp.after_sources(h), until_after_sources=200)
        fp = sim.get_field_point(mp.Ez, mp.Vector3(1))

        self.assertAlmostEqual(fp, -0.021997617628500023 + 0j, 5 if mp.is_single_precision() else 7)
Example #22
0
    def test_physical(self):

        a = 10.0
        ymax = 3.0
        xmax = 8.0
        dx = 2.0
        w = 0.30

        cell_size = mp.Vector3(xmax, ymax)
        pml_layers = [mp.PML(ymax / 3.0)]

        sources = [
            mp.Source(src=mp.ContinuousSource(w),
                      component=mp.Ez,
                      center=mp.Vector3(-dx),
                      size=mp.Vector3())
        ]

        sim = mp.Simulation(cell_size=cell_size,
                            resolution=a,
                            boundary_layers=pml_layers,
                            sources=sources,
                            force_complex_fields=True)
        sim.init_sim()
        sim.solve_cw(tol=1e-5 if mp.is_single_precision() else 1e-6)

        p1 = mp.Vector3()
        p2 = mp.Vector3(dx)

        amp1 = sim.get_field_point(mp.Ez, p1)
        amp2 = sim.get_field_point(mp.Ez, p2)

        ratio = abs(amp1) / abs(amp2)
        ratio = ratio**2  # in 2d, decay is ~1/sqrt(r), so square to get 1/r

        fail_fmt = "Failed: amp1 = ({}, {}), amp2 = ({}, {})\nabs(amp1/amp2){} = {}, too far from 2.0"
        fail_msg = fail_fmt.format(amp1.real, amp1, amp2.real, amp2, "^2",
                                   ratio)

        self.assertTrue(ratio <= 2.12 and ratio >= 1.88, fail_msg)
Example #23
0
    def test_harminv(self):
        self.init()

        self.sim.run(mp.at_beginning(mp.output_epsilon),
                     mp.after_sources(self.h),
                     until_after_sources=300)

        m1 = self.h.modes[0]

        self.assertAlmostEqual(m1.freq, 0.118101315147, places=4)
        self.assertAlmostEqual(m1.decay, -0.000731513241623, places=4)
        self.assertAlmostEqual(abs(m1.amp), 0.00341267634436, places=4)
        self.assertAlmostEqual(m1.amp.real, -0.00304951667301, places=4)
        self.assertAlmostEqual(m1.amp.imag, -0.00153192946717, places=3)

        v = mp.Vector3(1, 1)
        fp = self.sim.get_field_point(mp.Ez, v)
        ep = self.sim.get_epsilon_point(v)

        places = 5 if mp.is_single_precision() else 7
        self.assertAlmostEqual(ep, 11.559999999999999, places=places)
        self.assertAlmostEqual(fp, -0.08185972142450348, places=places)
    def test_integrated_source(self):
        sources = [
            mp.Source(mp.ContinuousSource(1, is_integrated=True),
                      center=mp.Vector3(-2),
                      size=mp.Vector3(y=6),
                      component=mp.Ez)
        ]
        sim = mp.Simulation(resolution=20,
                            cell_size=(6, 6),
                            boundary_layers=[mp.PML(thickness=1)],
                            sources=sources,
                            k_point=mp.Vector3())
        sim.run(until=30)

        # field in mid-plane should be nearly constant,
        # so compute its normalized std. dev. and check << 1
        ez = sim.get_array(mp.Ez, center=mp.Vector3(2), size=mp.Vector3(y=6))
        std = np.std(ez) / np.sqrt(np.mean(ez**2))
        print("std = ", std)
        self.assertAlmostEqual(std,
                               0.0,
                               places=4 if mp.is_single_precision() else 8)
Example #25
0
    def test_epsilon_input_file(self):
        sim = self.init_simple_simulation()
        eps_input_fname = 'cyl-ellipsoid-eps-ref.h5'
        eps_input_dir = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
                         '..', 'tests'))
        eps_input_path = os.path.join(eps_input_dir, eps_input_fname)
        sim.epsilon_input_file = eps_input_path

        sim.run(until=200)
        fp = sim.get_field_point(mp.Ez, mp.Vector3(x=1))

        places = 6 if mp.is_single_precision() else 7
        self.assertAlmostEqual(fp, -0.002989654055823199, places=places)

        # Test unicode file name for Python 2
        if sys.version_info[0] == 2:
            sim = self.init_simple_simulation(
                epsilon_input_file=unicode(eps_input_path))
            sim.run(until=200)
            fp = sim.get_field_point(mp.Ez, mp.Vector3(x=1))
            self.assertAlmostEqual(fp, -0.002989654055823199)
Example #26
0
class TestEigfreq(unittest.TestCase):

    @unittest.skipIf(mp.is_single_precision(), "double-precision floating point specific test")
    def test_eigfreq(self):
        w = 1.2           # width of waveguide
        r = 0.36          # radius of holes
        d = 1.4           # defect spacing (ordinary spacing = 1)
        N = 3             # number of holes on either side of defect
        sy = 6            # size of cell in y direction (perpendicular to wvg.)
        pad = 2           # padding between last hole and PML edge
        dpml = 1          # PML thickness
        sx = 2*(pad+dpml+N)+d-1  # size of cell in x direction

        geometry = [mp.Block(size=mp.Vector3(mp.inf,w,mp.inf), material=mp.Medium(epsilon=13))]
        for i in range(N):
                geometry.append(mp.Cylinder(r, center=mp.Vector3(d/2+i)))
                geometry.append(mp.Cylinder(r, center=mp.Vector3(-(d/2+i))))

        fcen = 0.25
        df = 0.2
        src = [mp.Source(mp.GaussianSource(fcen, fwidth=df),
                        component=mp.Hz,
                        center=mp.Vector3(0),
                        size=mp.Vector3(0,0))]

        sim = mp.Simulation(cell_size=mp.Vector3(sx,sy), force_complex_fields=True,
                            geometry=geometry,
                            boundary_layers=[mp.PML(1.0)],
                            sources=src,
                            symmetries=[mp.Mirror(mp.X, phase=-1), mp.Mirror(mp.Y, phase=-1)],
                            resolution=20)
        sim.init_sim()
        eigfreq = sim.solve_eigfreq(tol=1e-6)

        self.assertAlmostEqual(eigfreq.real, 0.23445413142440263, places=5)
        self.assertAlmostEqual(eigfreq.imag, -0.0003147775697388, places=5)
Example #27
0
    def test_transmission_spectrum(self):
        expected = [
            (0.15, 7.218492264696595e-6),
            (0.1504008016032064, 6.445696315927592e-6),
            (0.1508016032064128, 5.140949243632777e-6),
            (0.15120240480961922, 3.6159747936427164e-6),
            (0.15160320641282563, 2.263940553705969e-6),
            (0.15200400801603203, 1.4757165844336744e-6),
            (0.15240480961923844, 1.5491803919142815e-6),
            (0.15280561122244485, 2.612053246626972e-6),
            (0.15320641282565126, 4.577504371188737e-6),
            (0.15360721442885766, 7.1459089162998185e-6),
            (0.15400801603206407, 9.856622013418823e-6),
            (0.15440881763527048, 1.2182309227954296e-5),
            (0.1548096192384769, 1.3647726444709649e-5),
            (0.1552104208416833, 1.3947420613633674e-5),
            (0.1556112224448897, 1.303466755716231e-5),
            (0.1560120240480961, 1.115807915037775e-5),
            (0.15641282565130252, 8.832335196969796e-6),
            (0.15681362725450892, 6.743645773127985e-6),
            (0.15721442885771533, 5.605913756087576e-6),
            (0.15761523046092174, 5.996668564026961e-6),
            (0.15801603206412815, 8.209400611614078e-6),
            (0.15841683366733456, 1.2158641936828497e-5),
            (0.15881763527054096, 1.73653230513453e-5),
            (0.15921843687374737, 2.303382576477893e-5),
            (0.15961923847695378, 2.821180350795834e-5),
            (0.1600200400801602, 3.200359292911769e-5),
            (0.1604208416833666, 3.3792624373001934e-5),
            (0.160821643286573, 3.342171394788991e-5),
            (0.1612224448897794, 3.1284866146526904e-5),
            (0.16162324649298582, 2.830022088581398e-5),
            (0.16202404809619222, 2.5758413657344014e-5),
            (0.16242484969939863, 2.506899997971769e-5),
            (0.16282565130260504, 2.7453508915303887e-5),
            (0.16322645290581145, 3.365089813497114e-5),
            (0.16362725450901786, 4.370486834112e-5),
            (0.16402805611222426, 5.689050715055283e-5),
            (0.16442885771543067, 7.181133157470506e-5),
            (0.16482965931863708, 8.666168027415369e-5),
            (0.16523046092184349, 9.961094123261317e-5),
            (0.1656312625250499, 1.0923388232657953e-4),
            (0.1660320641282563, 1.1489334204708105e-4),
            (0.1664328657314627, 1.1698318060032011e-4),
            (0.16683366733466912, 1.169621456132733e-4),
            (0.16723446893787552, 1.1714995241571987e-4),
            (0.16763527054108193, 1.2030783847222252e-4),
            (0.16803607214428834, 1.2907652919660887e-4),
        ]

        self.sim.sources = [
            mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df),
                      mp.Ey,
                      mp.Vector3(self.dpml + (-0.5 * self.sx)),
                      size=mp.Vector3(0, self.w))
        ]

        self.sim.symmetries = [mp.Mirror(mp.Y, phase=-1)]

        freg = mp.FluxRegion(center=mp.Vector3((0.5 * self.sx) - self.dpml -
                                               0.5),
                             size=mp.Vector3(0, 2 * self.w))

        trans = self.sim.add_flux(self.fcen,
                                  self.df,
                                  self.nfreq,
                                  freg,
                                  decimation_factor=1)

        self.sim.run(until_after_sources=mp.stop_when_fields_decayed(
            50, mp.Ey, mp.Vector3((0.5 * self.sx) - self.dpml - 0.5, 0), 1e-1))

        res = zip(mp.get_flux_freqs(trans), mp.get_fluxes(trans))

        tol = 1e-8 if mp.is_single_precision() else 1e-10
        for e, r in zip(expected, res):
            self.assertClose(e, r, epsilon=tol)
Example #28
0
'''

import meep as mp
try:
    import meep.adjoint as mpa
except:
    import adjoint as mpa
import numpy as np
from autograd import numpy as npa
from autograd import tensor_jacobian_product
import unittest
from enum import Enum
from utils import ApproxComparisonTestCase
import parameterized

_TOL = 1e-6 if mp.is_single_precision() else 1e-14

## ensure reproducible results
rng = np.random.RandomState(9861548)


class TestAdjointUtils(ApproxComparisonTestCase):
    @parameterized.parameterized.expand([
        ('1.0_1.0_20_conic', 1.0, 1.0, 20, 0.24, mpa.conic_filter),
        ('1.0_1.0_23_conic', 1.0, 1.0, 23, 0.24, mpa.conic_filter),
        ('0.887_1.56_conic', 0.887, 1.56, 20, 0.24, mpa.conic_filter),
        ('0.887_1.56_conic', 0.887, 1.56, 31, 0.24, mpa.conic_filter),
        ('0.887_1.56_gaussian', 0.887, 1.56, 20, 0.24, mpa.gaussian_filter),
        ('0.887_1.56_cylindrical', 0.887, 1.56, 20, 0.24,
         mpa.cylindrical_filter)
    ])
Example #29
0
    def run_test(self, nfreqs):
        eps = 13
        w = 1.2
        r = 0.36
        d = 1.4
        N = 3
        sy = 6
        pad = 2
        dpml = 1
        sx = 2 * (pad + dpml + N) + d - 1

        cell = mp.Vector3(sx, sy, 0)

        geometry = [
            mp.Block(center=mp.Vector3(),
                     size=mp.Vector3(mp.inf, w, mp.inf),
                     material=mp.Medium(epsilon=eps))
        ]

        for i in range(N):
            geometry.append(mp.Cylinder(r, center=mp.Vector3(d / 2 + i)))
            geometry.append(mp.Cylinder(r, center=mp.Vector3(d / -2 - i)))

        pml_layers = mp.PML(dpml)
        resolution = 10

        fcen = 0.25
        df = 0.2

        sources = mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                            component=mp.Hz,
                            center=mp.Vector3())

        symmetries = [mp.Mirror(mp.Y, phase=-1), mp.Mirror(mp.X, phase=-1)]

        d1 = 0.2

        sim = mp.Simulation(cell_size=cell,
                            geometry=geometry,
                            sources=[sources],
                            symmetries=symmetries,
                            boundary_layers=[pml_layers],
                            resolution=resolution)

        nearfield = sim.add_near2far(
            fcen,
            0.1,
            nfreqs,
            mp.Near2FarRegion(mp.Vector3(0, 0.5 * w + d1),
                              size=mp.Vector3(2 * dpml - sx)),
            mp.Near2FarRegion(mp.Vector3(-0.5 * sx + dpml, 0.5 * w + 0.5 * d1),
                              size=mp.Vector3(0, d1),
                              weight=-1.0),
            mp.Near2FarRegion(mp.Vector3(0.5 * sx - dpml, 0.5 * w + 0.5 * d1),
                              size=mp.Vector3(0, d1)),
            decimation_factor=1)
        sim.run(until=200)
        d2 = 20
        h = 4
        vol = mp.Volume(mp.Vector3(0, (0.5 * w) + d2 + (0.5 * h)),
                        size=mp.Vector3(sx - 2 * dpml, h))
        result = sim.get_farfields(nearfield, resolution, where=vol)
        fname = 'cavity-farfield.h5' if nfreqs == 1 else 'cavity-farfield-4-freqs.h5'
        ref_file = os.path.join(self.data_dir, fname)

        with h5py.File(ref_file, 'r') as f:
            # Get reference data into memory
            ref_ex = mp.complexarray(f['ex.r'][()], f['ex.i'][()])
            ref_ey = mp.complexarray(f['ey.r'][()], f['ey.i'][()])
            ref_ez = mp.complexarray(f['ez.r'][()], f['ez.i'][()])
            ref_hx = mp.complexarray(f['hx.r'][()], f['hx.i'][()])
            ref_hy = mp.complexarray(f['hy.r'][()], f['hy.i'][()])
            ref_hz = mp.complexarray(f['hz.r'][()], f['hz.i'][()])

            tol = 1e-5 if mp.is_single_precision() else 1e-7
            self.assertClose(ref_ex, result['Ex'], epsilon=tol)
            self.assertClose(ref_ey, result['Ey'], epsilon=tol)
            self.assertClose(ref_ez, result['Ez'], epsilon=tol)
            self.assertClose(ref_hx, result['Hx'], epsilon=tol)
            self.assertClose(ref_hy, result['Hy'], epsilon=tol)
            self.assertClose(ref_hz, result['Hz'], epsilon=tol)
Example #30
0
from utils import ApproxComparisonTestCase

import jax
import jax.numpy as jnp
import meep as mp
import meep.adjoint as mpa
import numpy as onp

# The calculation of finite difference gradients requires that JAX be operated with double precision
jax.config.update('jax_enable_x64', True)

# The step size for the finite difference gradient calculation
_FD_STEP = 1e-4

# The tolerance for the adjoint and finite difference gradient comparison
_TOL = 0.1 if mp.is_single_precision() else 0.025

# We expect 3 design region monitor pointers (one for each field component)
_NUM_DES_REG_MON = 3

mp.verbosity(0)


def build_straight_wg_simulation(
    wg_width=0.5,
    wg_padding=1.0,
    wg_length=1.0,
    pml_width=1.0,
    source_to_pml=0.5,
    source_to_monitor=0.1,
    frequencies=[1 / 1.55],