Ejemplo n.º 1
0
def test_group_shape_array():
    with goos.OptimizationPlan() as plan:
        shape1, flow1, grad1 = make_cuboid_flow_grad(1)
        shape2, flow2, grad2 = make_cuboid_flow_grad(2)
        shape3, flow3, grad3 = make_cuboid_flow_grad(3)
        group = goos.GroupShape([shape1, goos.GroupShape([shape2, shape3])])

        inputs = [flow1, goos.ArrayFlow([flow2, flow3])]
        assert group.eval(inputs) == goos.ArrayFlow([flow1, flow2, flow3])
        assert (group.grad(inputs, goos.ArrayFlow.Grad(
            [grad1, grad2,
             grad3])) == [grad1, goos.ArrayFlow.Grad([grad2, grad3])])
Ejemplo n.º 2
0
def main(save_folder: str,
         min_feature: float = 100,
         sim_3d: bool = False,
         visualize: bool = False) -> None:
    goos.util.setup_logging(save_folder)

    with goos.OptimizationPlan(save_path=save_folder) as plan:
        wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]),
                            extents=goos.Constant([3000, 400, 220]),
                            material=goos.material.Material(index=3.45))
        wg_out = goos.Cuboid(pos=goos.Constant([0, 2000, 0]),
                             extents=goos.Constant([400, 3000, 220]),
                             material=goos.material.Material(index=3.45))

        def initializer(size):
            return np.random.random(size) * 0.2 + 0.5

        # Continuous optimization.
        var, design = goos.cubic_param_shape(
            initializer=initializer,
            pos=goos.Constant([0, 0, 0]),
            extents=[2000, 2000, 220],
            pixel_spacing=40,
            control_point_spacing=1.5 * min_feature,
            material=goos.material.Material(index=1),
            material2=goos.material.Material(index=3.45),
            var_name="var_cont")

        sigmoid_factor = goos.Variable(4, parameter=True, name="discr_factor")
        design = goos.cast(goos.Sigmoid(sigmoid_factor * (2 * design - 1)),
                           goos.Shape)
        eps = goos.GroupShape([wg_in, wg_out, design])

        # This node is purely for debugging purposes.
        eps_rendered = maxwell.RenderShape(
            design,
            region=goos.Box3d(center=[0, 0, 0], extents=[3000, 3000, 0]),
            mesh=maxwell.UniformMesh(dx=40),
            wavelength=1550,
        )
        if visualize:
            goos.util.visualize_eps(eps_rendered.get().array[2])

        obj, sim = make_objective_fdtd(eps, "cont", sim_3d=sim_3d)

        for factor in [4, 8]:
            sigmoid_factor.set(factor)
            goos.opt.scipy_minimize(
                obj,
                "L-BFGS-B",
                monitor_list=[sim["eps"], sim["field"], sim["overlap"], obj],
                max_iters=6,
                name="opt_cont{}".format(factor))

        plan.save()
        plan.run()

        if visualize:
            goos.util.visualize_eps(eps_rendered.get().array[2])
Ejemplo n.º 3
0
def test_group_shape_1_shape():
    with goos.OptimizationPlan() as plan:
        shape, shape_flow, shape_grad = make_cuboid_flow_grad(1)
        group = goos.GroupShape([shape])

        inputs = [shape_flow]

        assert group.eval(inputs) == goos.ArrayFlow([shape_flow])

        assert group.grad(inputs,
                          goos.ArrayFlow.Grad([shape_grad])) == [shape_grad]
Ejemplo n.º 4
0
def test_group_shape_2_shape_priority():
    with goos.OptimizationPlan() as plan:
        shape1, flow1, grad1 = make_cuboid_flow_grad(1, priority=1)
        shape2, flow2, grad2 = make_cuboid_flow_grad(2)
        group = goos.GroupShape([shape1, shape2])

        inputs = [flow1, flow2]
        assert group.eval(inputs) == goos.ArrayFlow([flow2, flow1])

        assert group.grad(inputs,
                          goos.ArrayFlow.Grad([grad2,
                                               grad1])) == [grad1, grad2]
Ejemplo n.º 5
0
def test_group_shape_3_shape_priority_stable_sort():
    with goos.OptimizationPlan() as plan:
        shape1, flow1, grad1 = make_cuboid_flow_grad(1, priority=2)
        shape2, flow2, grad2 = make_cuboid_flow_grad(2, priority=1)
        shape3, flow3, grad3 = make_cuboid_flow_grad(3, priority=1)
        group = goos.GroupShape([shape1, shape2, shape3])

        inputs = [flow1, flow2, flow3]
        assert group.eval(inputs) == goos.ArrayFlow([flow2, flow3, flow1])
        assert group.grad(inputs,
                          goos.ArrayFlow.Grad([grad2, grad3, grad1
                                               ])) == [grad1, grad2, grad3]
Ejemplo n.º 6
0
def test_group_shape_array_priority():
    with goos.OptimizationPlan() as plan:
        shape1, flow1, grad1 = make_cuboid_flow_grad(1, priority=2)
        shape2, flow2, grad2 = make_cuboid_flow_grad(2)
        shape3, flow3, grad3 = make_cuboid_flow_grad(3, priority=1)
        shape4, flow4, grad4 = make_cuboid_flow_grad(4)
        group = goos.GroupShape([
            goos.GroupShape([shape1, shape2]), shape3,
            goos.GroupShape([shape4])
        ])

        inputs = [
            goos.ArrayFlow([flow1, flow2]), flow3,
            goos.ArrayFlow([flow4])
        ]
        assert group.eval(inputs) == goos.ArrayFlow(
            [flow2, flow4, flow3, flow1])
        assert (group.grad(inputs,
                           goos.ArrayFlow.Grad(
                               [grad2, grad4, grad3, grad1])) == [
                                   goos.ArrayFlow.Grad([grad1, grad2]), grad3,
                                   goos.ArrayFlow.Grad([grad4])
                               ])
Ejemplo n.º 7
0
def main(save_folder: str, visualize: bool = False) -> None:
    goos.util.setup_logging(save_folder)

    params = Options()

    with goos.OptimizationPlan(save_path=save_folder) as plan:
        substrate = goos.Cuboid(
            pos=goos.Constant([
                params.coupler_len / 2, 0,
                -params.box_size - params.wg_thickness / 2 - 5000
            ]),
            extents=goos.Constant([params.coupler_len + 10000, 1000, 10000]),
            material=goos.material.Material(index=params.eps_wg))
        waveguide = goos.Cuboid(
            pos=goos.Constant([-params.wg_len / 2, 0, 0]),
            extents=goos.Constant(
                [params.wg_len, params.wg_width, params.wg_thickness]),
            material=goos.material.Material(index=params.eps_wg))

        wg_bottom = goos.Cuboid(
            pos=goos.Constant([
                params.coupler_len / 2, 0,
                -params.wg_thickness / 2 * params.etch_frac
            ]),
            extents=goos.Constant([
                params.coupler_len, params.wg_width,
                params.wg_thickness * (1 - params.etch_frac)
            ]),
            material=goos.material.Material(index=params.eps_wg))

        def initializer(size):
            return np.random.random(size)

        # Continuous optimization.
        var, design = goos.pixelated_cont_shape(
            initializer=initializer,
            pos=goos.Constant([
                params.coupler_len / 2, 0,
                params.wg_thickness / 2 * (1 - params.etch_frac)
            ]),
            extents=[
                params.coupler_len, params.wg_width,
                params.wg_thickness * params.etch_frac
            ],
            material=goos.material.Material(index=params.eps_bg),
            material2=goos.material.Material(index=params.eps_wg),
            pixel_size=[
                params.pixel_size, params.wg_width, params.wg_thickness
            ])

        obj, sim = make_objective(
            goos.GroupShape([substrate, waveguide, wg_bottom, design]), "cont",
            params)

        goos.opt.scipy_minimize(
            obj,
            "L-BFGS-B",
            monitor_list=[sim["eps"], sim["field"], sim["overlap"], obj],
            max_iters=60,
            name="opt_cont")

        # Prevent optimization from optimizing over continuous variable.
        var.freeze()

        # Run discretization.
        grating_var, height_var, design_disc = goos.grating.discretize_to_pixelated_grating(
            var,
            height_fracs=[0, 1],
            pixel_size=params.pixel_size,
            start_height_ind=1,
            end_height_ind=1,
            min_features=params.min_features,
            pos=[
                params.coupler_len / 2, 0,
                params.wg_thickness / 2 * (1 - params.etch_frac)
            ],
            extents=[
                params.coupler_len, params.wg_width,
                params.wg_thickness * params.etch_frac
            ],
            material=goos.material.Material(index=params.eps_bg),
            material2=goos.material.Material(index=params.eps_wg),
            grating_dir=0,
            grating_dir_spacing=20,
            etch_dir=2,
            etch_dir_divs=1)

        obj, sim = make_objective(
            goos.GroupShape([substrate, waveguide, wg_bottom, design_disc]),
            "disc", params)

        goos.opt.scipy_minimize(
            obj,
            "L-BFGS-B",
            monitor_list=[sim["eps"], sim["field"], sim["overlap"], obj],
            max_iters=100,
            name="opt_disc",
            ftol=1e-8)

        plan.save()
        plan.run()

        if visualize:
            goos.util.visualize_eps(sim["eps"].get().array[2])
Ejemplo n.º 8
0
'''
Define the constant background structures that will not be changed
during the design. In this case, these are the input and output waveguides.
'''
with plan:
    # Define input waveguide.
    wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]),
                        extents=goos.Constant([3000, 400, 220]),
                        material=goos.material.Material(index=1))
    # Define output waveguide.
    wg_out = goos.Cuboid(pos=goos.Constant([0, 2000, 0]),
                         extents=goos.Constant([400, 3000, 220]),
                         material=goos.material.Material(index=1))

    # Group these background structures together.
    eps_background_structures = goos.GroupShape([wg_in, wg_out])
    '''
Visualize the constant background structures we just defined.
'''
with plan:
    eps_rendered = maxwell.RenderShape(
        eps_background_structures,
        region=goos.Box3d(center=[0, 0, 0], extents=[3000, 3000, 0]),
        mesh=maxwell.UniformMesh(dx=40),
        wavelength=635,
    )

    goos.util.visualize_eps(eps_rendered.get().array[2])
'''
Define and initialize the design region.
'''
Ejemplo n.º 9
0
def test_simulate_wg_opt():
    with goos.OptimizationPlan() as plan:
        wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]),
                            extents=goos.Constant([3000, 800, 40]),
                            material=goos.material.Material(index=3.45))
        wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]),
                             extents=goos.Constant([3000, 800, 40]),
                             material=goos.material.Material(index=3.45))

        def initializer(size):
            # Set the seed immediately before calling `random` to ensure
            # reproducibility.
            np.random.seed(247)
            return np.random.random(size) * 0.1 + np.ones(size) * 0.7

        var, design = goos.pixelated_cont_shape(
            initializer=initializer,
            pos=goos.Constant([0, 0, 0]),
            extents=[1000, 800, 40],
            pixel_size=[40, 40, 40],
            material=goos.material.Material(index=1),
            material2=goos.material.Material(index=3.45),
        )
        eps = goos.GroupShape([wg_in, wg_out, design])
        sim = meep.FdtdSimulation(
            eps=eps,
            sources=[
                meep.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                    wavelength=1550,
                    bandwidth=100,
                )
            ],
            sim_space=meep.SimulationSpace(
                dx=40,
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 0],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            sim_timing=meep.SimulationTiming(stopping_conditions=[
                meep.StopWhenFieldsDecayed(
                    time_increment=50,
                    component=2,
                    pos=[0, 0, 0],
                    threshold=1e-6,
                )
            ], ),
            background=goos.material.Material(index=1.0),
            outputs=[
                meep.Epsilon(wavelength=1550),
                meep.ElectricField(wavelength=1550),
                meep.WaveguideModeOverlap(wavelength=1550,
                                          center=[1000, 0, 0],
                                          extents=[0, 2500, 0],
                                          normal=[1, 0, 0],
                                          mode_num=0,
                                          power=1),
            ])

        obj = -goos.abs(sim[2])

        import meep as mp
        mp.quiet()
        goos.opt.scipy_minimize(obj,
                                "L-BFGS-B",
                                monitor_list=[obj],
                                max_iters=5)
        plan.run()

        # Check that we can optimize. We choose something over 60% as
        # incorrect gradients will typically not reach this point.
        assert obj.get().array < -0.85

        # As a final check, compare simulation results against Maxwell.
        # Note that dx = 40 for Meep is actually too innaccurate. We therefore
        # resimulate the final structure for both Meep and Maxwell.
        from spins.goos_sim import maxwell
        sim_fdfd = maxwell.fdfd_simulation(
            wavelength=1550,
            eps=eps,
            sources=[
                maxwell.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                )
            ],
            simulation_space=maxwell.SimulationSpace(
                mesh=maxwell.UniformMesh(dx=20),
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 0],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            background=goos.material.Material(index=1.0),
            outputs=[
                maxwell.Epsilon(),
                maxwell.ElectricField(),
                maxwell.WaveguideModeOverlap(center=[1000, 0, 0],
                                             extents=[0, 2500, 0],
                                             normal=[1, 0, 0],
                                             mode_num=0,
                                             power=1),
            ],
            solver="local_direct")

        sim_fdtd_hi = meep.FdtdSimulation(
            eps=eps,
            sources=[
                meep.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                    wavelength=1550,
                    bandwidth=100,
                )
            ],
            sim_space=meep.SimulationSpace(
                dx=20,
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 0],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            sim_timing=meep.SimulationTiming(stopping_conditions=[
                meep.StopWhenFieldsDecayed(
                    time_increment=50,
                    component=2,
                    pos=[0, 0, 0],
                    threshold=1e-6,
                )
            ], ),
            background=goos.material.Material(index=1.0),
            outputs=[
                meep.Epsilon(wavelength=1550),
                meep.ElectricField(wavelength=1550),
                meep.WaveguideModeOverlap(wavelength=1550,
                                          center=[1000, 0, 0],
                                          extents=[0, 2500, 0],
                                          normal=[1, 0, 0],
                                          mode_num=0,
                                          power=1),
            ])
        fdtd_hi_power = goos.abs(sim_fdtd_hi[2])**2
        fdfd_power = goos.abs(sim_fdfd[2])**2

        # Check that power is correct within 0.5%.
        assert np.abs(fdfd_power.get().array - fdtd_hi_power.get().array) < 0.005
Ejemplo n.º 10
0
def main(save_folder: str,
         min_feature: float = 100,
         use_cubic: bool = True,
         visualize: bool = False) -> None:
    goos.util.setup_logging(save_folder)

    with goos.OptimizationPlan(save_path=save_folder) as plan:
        wg_1 = goos.Cuboid(pos=goos.Constant([1600, -4500, 0]),
                           extents=goos.Constant([600, 1000, 230]),
                           material=goos.material.Material(index=3.45))
        wg_2 = goos.Cuboid(pos=goos.Constant([-1600, -4500, 0]),
                           extents=goos.Constant([600, 1000, 230]),
                           material=goos.material.Material(index=3.45))
        wg_3 = goos.Cuboid(pos=goos.Constant([1600, 4500, 0]),
                           extents=goos.Constant([600, 1000, 230]),
                           material=goos.material.Material(index=3.45))
        wg_4 = goos.Cuboid(pos=goos.Constant([-1600, 4500, 0]),
                           extents=goos.Constant([600, 1000, 230]),
                           material=goos.material.Material(index=3.45))
        wg_5 = goos.Cuboid(pos=goos.Constant([4500, -1600, 0]),
                           extents=goos.Constant([1000, 600, 230]),
                           material=goos.material.Material(index=3.45))
        wg_6 = goos.Cuboid(pos=goos.Constant([4500, 1600, 0]),
                           extents=goos.Constant([1000, 600, 230]),
                           material=goos.material.Material(index=3.45))
        wg_7 = goos.Cuboid(pos=goos.Constant([-4500, 0, 0]),
                           extents=goos.Constant([1000, 600, 230]),
                           material=goos.material.Material(index=3.45))
        substrate = goos.Cuboid(pos=goos.Constant([0, 0, -500]),
                                extents=goos.Constant([11000, 11000, 770]),
                                material=goos.material.Material(index=1.4))

        def initializer(size):
            # Set the seed immediately before calling `random` to ensure
            # reproducibility.
            #np.random.seed(247)
            return np.ones(size) * 0.5
            #return np.random.random(size) * 0.2 + 0.5

        # Continuous optimization.
        var, design = goos.pixelated_cont_shape(
            initializer=initializer,
            pos=goos.Constant([0, 0, 0]),
            extents=[8000, 8000, 230],
            material=goos.material.Material(index=1),
            material2=goos.material.Material(index=3.45),
            pixel_size=[50, 50, 230],
            var_name="var_cont")

        sigmoid_factor = goos.Variable(4, parameter=True, name="discr_factor")
        design = goos.cast(goos.Sigmoid(sigmoid_factor * (2 * design - 1)),
                           goos.Shape)
        eps = goos.GroupShape(
            [wg_1, wg_2, wg_3, wg_4, wg_5, wg_6, wg_7, design, substrate])

        # This node is purely for debugging purposes.
        eps_rendered = maxwell.RenderShape(
            eps,
            region=goos.Box3d(center=[0, 0, 0], extents=[10000, 10000, 0]),
            mesh=maxwell.UniformMesh(dx=50),
            wavelength=635,
        )
        if visualize:
            goos.util.visualize_eps(eps_rendered.get().array[2])

        obj, sim1, sim2, sim3, sim4, sim5, sim6, sim7 = make_objective(
            eps, "cont")

        for factor in [4, 8, 12]:
            sigmoid_factor.set(factor)
            goos.opt.scipy_minimize(
                obj,
                "L-BFGS-B",
                monitor_list=[
                    sim1["eps"], sim1["field"], sim1["overlap1"],
                    sim1["overlap2"], sim1["overlap3"], sim1["overlap4"],
                    sim1["overlap5"], sim1["overlap6"], sim1["overlap7"],
                    sim2["eps"], sim2["field"], sim2["overlap1"],
                    sim2["overlap2"], sim2["overlap3"], sim2["overlap4"],
                    sim2["overlap5"], sim2["overlap6"], sim2["overlap7"],
                    sim3["eps"], sim3["field"], sim3["overlap1"],
                    sim3["overlap2"], sim3["overlap3"], sim3["overlap4"],
                    sim3["overlap5"], sim3["overlap6"], sim3["overlap7"],
                    sim4["eps"], sim4["field"], sim4["overlap1"],
                    sim4["overlap2"], sim4["overlap3"], sim4["overlap4"],
                    sim4["overlap5"], sim4["overlap6"], sim4["overlap7"],
                    sim5["eps"], sim5["field"], sim5["overlap1"],
                    sim5["overlap2"], sim5["overlap3"], sim5["overlap4"],
                    sim5["overlap5"], sim5["overlap6"], sim5["overlap7"],
                    sim6["eps"], sim6["field"], sim6["overlap1"],
                    sim6["overlap2"], sim6["overlap3"], sim6["overlap4"],
                    sim6["overlap5"], sim6["overlap6"], sim6["overlap7"],
                    sim7["eps"], sim7["field"], sim7["overlap1"],
                    sim7["overlap2"], sim7["overlap3"], sim7["overlap4"],
                    sim7["overlap5"], sim7["overlap6"], sim7["overlap7"], obj
                ],
                max_iters=25,
                name="opt_cont{}".format(factor))

        plan.save()
        plan.run()

        if visualize:
            goos.util.visualize_eps(eps_rendered.get().array[2])
Ejemplo n.º 11
0
def test_simulate_wg_opt():
    with goos.OptimizationPlan() as plan:
        wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]),
                            extents=goos.Constant([3000, 800, 220]),
                            material=goos.material.Material(index=3.45))
        wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]),
                             extents=goos.Constant([3000, 800, 220]),
                             material=goos.material.Material(index=3.45))

        def initializer(size):
            # Set the seed immediately before calling `random` to ensure
            # reproducibility.
            np.random.seed(247)
            return np.random.random(size) * 0.1 + np.ones(size) * 0.5

        var, design = goos.pixelated_cont_shape(
            initializer=initializer,
            pos=goos.Constant([0, 0, 0]),
            extents=[1000, 800, 220],
            pixel_size=[40, 40, 40],
            material=goos.material.Material(index=1),
            material2=goos.material.Material(index=3.45),
        )
        eps = goos.GroupShape([wg_in, wg_out, design])
        sim = maxwell.fdfd_simulation(
            eps=eps,
            wavelength=1550,
            solver="local_direct",
            sources=[
                maxwell.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                )
            ],
            simulation_space=maxwell.SimulationSpace(
                mesh=maxwell.UniformMesh(dx=40),
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 40],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            background=goos.material.Material(index=1.0),
            outputs=[
                maxwell.Epsilon(),
                maxwell.ElectricField(),
                maxwell.WaveguideModeOverlap(wavelength=1550,
                                             center=[1000, 0, 0],
                                             extents=[0, 2500, 0],
                                             normal=[1, 0, 0],
                                             mode_num=0,
                                             power=1),
            ])

        obj = -goos.abs(sim[2])

        goos.opt.scipy_minimize(obj,
                                "L-BFGS-B",
                                monitor_list=[obj],
                                max_iters=15)
        plan.run()

        assert obj.get().array < -0.90
Ejemplo n.º 12
0
def test_simulate_wg_opt_grad():
    with goos.OptimizationPlan() as plan:
        wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]),
                            extents=goos.Constant([3000, 800, 220]),
                            material=goos.material.Material(index=3.45))
        wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]),
                             extents=goos.Constant([3000, 800, 220]),
                             material=goos.material.Material(index=3.45))

        def initializer(size):
            # Set the seed immediately before calling `random` to ensure
            # reproducibility.
            np.random.seed(247)
            return np.random.random(size)

        var, design = goos.pixelated_cont_shape(
            initializer=initializer,
            pos=goos.Constant([0, 0, 0]),
            extents=[1000, 800, 220],
            pixel_size=[500, 400, 220],
            material=goos.material.Material(index=1),
            material2=goos.material.Material(index=3.45),
        )
        eps = goos.GroupShape([wg_in, wg_out, design])
        sim = maxwell.fdfd_simulation(
            eps=eps,
            wavelength=1550,
            solver="local_direct",
            sources=[
                maxwell.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                )
            ],
            simulation_space=maxwell.SimulationSpace(
                mesh=maxwell.UniformMesh(dx=40),
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 40],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            background=goos.material.Material(index=1.0),
            outputs=[
                maxwell.Epsilon(),
                maxwell.ElectricField(),
                maxwell.WaveguideModeOverlap(wavelength=1550,
                                             center=[1000, 0, 0],
                                             extents=[0, 2500, 0],
                                             normal=[1, 0, 0],
                                             mode_num=0,
                                             power=1),
            ])

        obj = -goos.abs(sim[2])

        adjoint_grad = obj.get_grad([var])[0].array_grad

        # Calculate brute force gradient.
        var_val = var.get().array
        eps = 0.001
        num_grad = np.zeros_like(var_val)
        for i in range(var_val.shape[0]):
            for j in range(var_val.shape[1]):
                temp_val = var_val.copy()
                temp_val[i, j] += eps
                var.set(temp_val)
                fplus = obj.get(run=True).array

                temp_val = var_val.copy()
                temp_val[i, j] -= eps
                var.set(temp_val)
                fminus = obj.get(run=True).array

                num_grad[i, j] = (fplus - fminus) / (2 * eps)

        np.testing.assert_array_almost_equal(adjoint_grad, num_grad, decimal=3)