Beispiel #1
0
def test_eval():
    param = parametrization.DirectParam((1, 2, 3, 4, 5))
    x = problem.Variable(5)
    obj = (x[0] * x[1] - x[2]**2) * (x[3] + 2 * x[4])

    assert graph_executor.eval_fun(obj, param) == -98
    np.testing.assert_array_equal(graph_executor.eval_grad(obj, param),
                                  [28, 14, -84, -7, -14])
Beispiel #2
0
def test_eval_old_in_new():
    """Tests evals when a new-style function depends on old-style function."""
    param = parametrization.DirectParam((3, 2))
    x = problem.Variable(2)
    obj = OldPower(x[0], 2) + x[0]

    assert graph_executor.eval_fun(obj, param) == 12
    np.testing.assert_array_equal(graph_executor.eval_grad(obj, param), [7, 0])
Beispiel #3
0
def test_eval_multiple():
    param = parametrization.DirectParam((1, 2, 3, 4, 5))
    x = problem.Variable(5)
    obj_part1 = x[3] + 2 * x[4]
    obj_part2 = x[0] * x[1] - x[2]**2
    obj = obj_part1 * obj_part2

    assert graph_executor.eval_fun([obj, obj_part1, obj_part2],
                                   param) == [-98, 14, -7]
Beispiel #4
0
def test_eval_heavy_compute_end_on_heavy():
    param = parametrization.DirectParam((-3, 2))
    x = problem.Variable(2)

    obj = HeavyIdentity(x[0] * x[1])

    np.testing.assert_array_almost_equal(graph_executor.eval_fun(obj, param),
                                         -6)
    np.testing.assert_array_equal(graph_executor.eval_grad(obj, param),
                                  [2, -3])
Beispiel #5
0
    def calculate_objective_function(self, param: Parametrization) -> float:
        """Computes the objective function value.

        Args:
            param: Parametrization.

        Returns:
            A single float representing objective function value.
        """
        return graph_executor.eval_fun(self, param)
Beispiel #6
0
def test_eval_fun_no_in_node_works():
    """Tests when no input node is found.

    This can happen if the input node is fed only to the old-style function,
    which does not list its dependencies. Consequently, no input node can be
    found.
    """
    param = parametrization.DirectParam((2, ))
    x = problem.Variable(1)
    obj = OldPower(x[0], 2) + OldPower(x[0], 3)

    assert graph_executor.eval_fun(obj, param) == 12
    np.testing.assert_array_equal(graph_executor.eval_grad(obj, param), [16])
Beispiel #7
0
def test_eval_heavy_compute():
    param = parametrization.DirectParam((-1, 2, 1.2, 3, 5.1))
    x = problem.Variable(5)

    obj = HeavyIdentity(x[1] * x[0] * x[3])

    obj2 = HeavyIdentity(x[3] + x[1]**3)

    obj3 = obj * (x[0] + 2) + obj2 - x[4]

    np.testing.assert_array_almost_equal(graph_executor.eval_fun(obj3, param),
                                         -0.1)
    np.testing.assert_array_equal(graph_executor.eval_grad(obj3, param),
                                  [0, 9, 0, -1, -1])
Beispiel #8
0
    def write(self,
              event: Dict,
              param: parametrization.Parametrization,
              monitor_list: List[str] = None) -> None:
        """Write monitor data to log file.

        Args:
            event: Transformation-specific information about the event.
            param: Parametrization that has to be evaluated.
            monitor_list: List of monitor names to be evaluated.
        """
        # Increment log_counter.
        self._log_counter += 1

        # Get monitor data.
        monitor_data = {}
        if monitor_list:
            mon_vals = graph_executor.eval_fun(
                [self._work.get_object(mon) for mon in monitor_list], param)
            for mon, mon_val in zip(monitor_list, mon_vals):
                monitor_data[mon.name] = mon_val

        # Get workspace parameters.
        parameter_data = {}
        parameter_list = self._work.get_objects_by_type(optplan.Parameter)
        for param_name, param_obj in parameter_list.items():
            parameter_data[
                param_name] = param_obj.calculate_objective_function(param)

        # Make a log entry.
        data = {
            "transformation": self._transform_name,
            "event": event,
            "time": str(datetime.now()),
            "parametrization": param.serialize(),
            "parameters": parameter_data,
            "monitor_data": monitor_data,
            "log_counter": self._log_counter
        }

        self._logger.info(
            "Saving monitors for transformation %s with event info %s [%d].",
            self._transform_name, event, self._log_counter)

        # Save the data.
        file_path = os.path.join(
            self._path, os.path.join("step{}.pkl".format(self._log_counter)))
        with open(file_path, "wb") as handle:
            pickle.dump(data, handle)
Beispiel #9
0
def test_eval_fun_multiple_variables_raises_value_error():
    with pytest.raises(ValueError, match=r"Multiple Variable"):
        param = parametrization.DirectParam((1, 2))
        x = problem.Variable(2)
        y = problem.Variable(2)
        graph_executor.eval_fun(x + y, param)
Beispiel #10
0
def test_straight_waveguide_power():
    """Tests that a straight waveguide with a single source and overlap."""

    # TODO(logansu): Refactor.
    class Simspace:
        def __init__(self, filepath, params: optplan.SimulationSpace):
            # Setup the grid.
            self._dx = params.mesh.dx
            from spins.invdes.problem_graph.simspace import _create_edge_coords
            self._edge_coords = _create_edge_coords(params.sim_region,
                                                    self._dx)
            self._ext_dir = gridlock.Direction.z  # Currently always extrude in z.
            # TODO(logansu): Factor out grid functionality and drawing.
            # Create a grid object just so we can calculate dxes.
            self._grid = gridlock.Grid(self._edge_coords,
                                       ext_dir=self._ext_dir,
                                       num_grids=3)

            self._pml_layers = params.pml_thickness
            self._filepath = filepath
            self._eps_bg = params.eps_bg

        @property
        def dx(self) -> float:
            return self._dx

        @property
        def dxes(self) -> fdfd_tools.GridSpacing:
            return [self._grid.dxyz, self._grid.autoshifted_dxyz()]

        @property
        def pml_layers(self) -> fdfd_tools.PmlLayers:
            return self._pml_layers

        @property
        def dims(self) -> Tuple[int, int, int]:
            return [
                len(self._edge_coords[0]) - 1,
                len(self._edge_coords[1]) - 1,
                len(self._edge_coords[2]) - 1
            ]

        @property
        def edge_coords(self) -> fdfd_tools.GridSpacing:
            return self._edge_coords

        def __call__(self, wlen: float):
            from spins.invdes.problem_graph.simspace import _create_grid
            from spins.invdes.problem_graph.simspace import SimulationSpaceInstance
            eps_bg = _create_grid(self._eps_bg, self._edge_coords, wlen,
                                  self._ext_dir, self._filepath)
            return SimulationSpaceInstance(eps_bg=eps_bg,
                                           selection_matrix=None)

    space = Simspace(
        TESTDATA,
        optplan.SimulationSpace(
            pml_thickness=[10, 10, 10, 10, 0, 0],
            mesh=optplan.UniformMesh(dx=40),
            sim_region=optplan.Box3d(
                center=[0, 0, 0],
                extents=[5000, 5000, 40],
            ),
            eps_bg=optplan.GdsEps(
                gds="straight_waveguide.gds",
                mat_stack=optplan.GdsMaterialStack(
                    background=optplan.Material(mat_name="air"),
                    stack=[
                        optplan.GdsMaterialStackLayer(
                            gds_layer=[100, 0],
                            extents=[-80, 80],
                            foreground=optplan.Material(mat_name="Si"),
                            background=optplan.Material(mat_name="air"),
                        ),
                    ],
                ),
            ),
        ))

    source = creator_em.WaveguideModeSource(
        optplan.WaveguideModeSource(
            power=1.0,
            extents=[40, 1500, 600],
            normal=[1.0, 0.0, 0.0],
            center=[-1770, 0, 0],
            mode_num=0,
        ))

    overlap = creator_em.WaveguideModeOverlap(
        optplan.WaveguideModeOverlap(
            power=1.0,
            extents=[40, 1500, 600],
            normal=[1.0, 0.0, 0.0],
            center=[1770, 0, 0],
            mode_num=0,
        ))

    wlen = 1550
    eps_grid = space(wlen).eps_bg.grids
    source_grid = source(space, wlen)
    overlap_grid = overlap(space, wlen)

    eps = problem.Constant(fdfd_tools.vec(eps_grid))
    sim = creator_em.FdfdSimulation(
        eps=eps,
        solver=local_matrix_solvers.DirectSolver(),
        wlen=wlen,
        source=fdfd_tools.vec(source_grid),
        simspace=space,
    )
    overlap_fun = creator_em.OverlapFunction(sim, fdfd_tools.vec(overlap_grid))

    efield_grid = fdfd_tools.unvec(graph_executor.eval_fun(sim, None),
                                   eps_grid[0].shape)

    # Calculate emitted power.
    edotj = np.real(
        fdfd_tools.vec(efield_grid) *
        np.conj(fdfd_tools.vec(source_grid))) * 40**3
    power = -0.5 * np.sum(edotj)
    # Allow for 4% error in emitted power.
    assert power > 0.96 and power < 1.04

    # Check that overlap observes nearly unity power.
    np.testing.assert_almost_equal(np.abs(
        graph_executor.eval_fun(overlap_fun, None))**2,
                                   1,
                                   decimal=2)
Beispiel #11
0
def test_straight_waveguide_power_poynting():
    """Tests that total through straight waveguide is unity."""
    space = Simspace(
        TESTDATA,
        optplan.SimulationSpace(
            pml_thickness=[10, 10, 10, 10, 0, 0],
            mesh=optplan.UniformMesh(dx=40),
            sim_region=optplan.Box3d(
                center=[0, 0, 0],
                extents=[5000, 5000, 40],
            ),
            eps_bg=optplan.GdsEps(
                gds="straight_waveguide.gds",
                mat_stack=optplan.GdsMaterialStack(
                    background=optplan.Material(mat_name="air"),
                    stack=[
                        optplan.GdsMaterialStackLayer(
                            gds_layer=[100, 0],
                            extents=[-80, 80],
                            foreground=optplan.Material(mat_name="Si"),
                            background=optplan.Material(mat_name="air"),
                        ),
                    ],
                ),
            ),
        ))

    source = creator_em.WaveguideModeSource(
        optplan.WaveguideModeSource(
            power=1.0,
            extents=[40, 1500, 600],
            normal=[1.0, 0.0, 0.0],
            center=[-1770, 0, 0],
            mode_num=0,
        ))

    wlen = 1550
    eps_grid = space(wlen).eps_bg.grids
    source_grid = source(space, wlen)

    eps = problem.Constant(fdfd_tools.vec(eps_grid))
    sim = creator_em.FdfdSimulation(
        eps=eps,
        solver=local_matrix_solvers.DirectSolver(),
        wlen=wlen,
        source=fdfd_tools.vec(source_grid),
        simspace=space,
    )
    power_fun = poynting.PowerTransmissionFunction(
        field=sim,
        simspace=space,
        wlen=wlen,
        plane_slice=grid_utils.create_region_slices(
            space.edge_coords, [1770, 0, 0], [40, 1500, 600]),
        axis=gridlock.axisvec2axis([1, 0, 0]),
        polarity=gridlock.axisvec2polarity([1, 0, 0]))
    # Same as `power_fun` but with opposite normal vector. Should give same
    # answer but with a negative sign.
    power_fun_back = poynting.PowerTransmissionFunction(
        field=sim,
        simspace=space,
        wlen=wlen,
        plane_slice=grid_utils.create_region_slices(
            space.edge_coords, [1770, 0, 0], [40, 1500, 600]),
        axis=gridlock.axisvec2axis([-1, 0, 0]),
        polarity=gridlock.axisvec2polarity([-1, 0, 0]))

    efield_grid = fdfd_tools.unvec(
        graph_executor.eval_fun(sim, None), eps_grid[0].shape)

    # Calculate emitted power.
    edotj = np.real(
        fdfd_tools.vec(efield_grid) * np.conj(
            fdfd_tools.vec(source_grid))) * 40**3
    power = -0.5 * np.sum(edotj)

    np.testing.assert_almost_equal(
        graph_executor.eval_fun(power_fun, None), power, decimal=4)
    np.testing.assert_almost_equal(
        graph_executor.eval_fun(power_fun_back, None), -power, decimal=4)