<commit_before>from types import LambdaType
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

import nlopt
import numpy as np
from numpy import ndarray
from meep import Block, EigenModeSource, MaterialGrid, Simulation, Vector3, Volume
from meep.adjoint import DesignRegion, EigenmodeCoefficient, OptimizationProblem
from meep.visualization import get_2D_dimensions

import gdsfactory as gf
from gdsfactory import Component
from gdsfactory.simulation.gmeep import get_simulation
from gdsfactory.tech import LayerStack
from gdsfactory.types import Layer


def get_meep_adjoint_optimizer(
    component: Component,
    objective_function: List[Callable],
    design_regions: List[DesignRegion],
    design_variables: List[MaterialGrid],
    design_update: np.ndarray,
    TE_mode_number: int = 1,
    resolution: int = 30,
    cell_size: Optional[Tuple] = None,
    extend_ports_length: Optional[float] = 10.0,
    layer_stack: Optional[LayerStack] = None,
    zmargin_top: float = 3.0,
    zmargin_bot: float = 3.0,
    tpml: float = 1.5,
    clad_material: str = "SiO2",
    is_3d: bool = False,
    wavelength_start: float = 1.5,
    wavelength_stop: float = 1.6,
    wavelength_points: int = 50,
    dfcen: float = 0.2,
    port_source_name: str = "o1",
    port_margin: float = 3,
    distance_source_to_monitors: float = 0.2,
    port_source_offset: float = 0,
    port_monitor_offset: float = 0,
    dispersive: bool = False,
    material_name_to_meep: Optional[Dict[str, Union[str, float]]] = None,
    **settings,
) -> OptimizationProblem:
    """Return a Meep `OptimizationProblem` object.

    Args:
        component: gdsfactory component
        objective_function: functions must be composed of "field functions" that transform the recorded fields
        design_regions: list of DesignRegion objects
        design_variables: list of MaterialGrid objects
        design_update: ndarray to intializethe optimization
        TE_mode_number: TE mode number
        resolution: in pixels/um (20: for coarse, 120: for fine)
        cell_size: tuple of Simulation object dimensions in um
        extend_ports_length: to extend ports beyond the PML.
        layer_stack: contains layer to thickness, zmin and material.
            Defaults to active pdk.layer_stack.
        zmargin_top: thickness for cladding above core.
        zmargin_bot: thickness for cladding below core.
        tpml: PML thickness (um).
        clad_material: material for cladding.
        is_3d: if True runs in 3D.
        wavelength_start: wavelength min (um).
        wavelength_stop: wavelength max (um).
        wavelength_points: wavelength steps.
        dfcen: delta frequency.
        port_source_name: input port name.
        port_margin: margin on each side of the port.
        distance_source_to_monitors: in (um) source goes before.
        port_source_offset: offset between source GDS port and source MEEP port.
        port_monitor_offset: offset between monitor GDS port and monitor MEEP port.
        dispersive: use dispersive material models (requires higher resolution).
        material_name_to_meep: map layer_stack names with meep material database name
            or refractive index. dispersive materials have a wavelength dependent index.

    Keyword Args:
        settings: extra simulation settings (resolution, symmetries, etc.)

    Returns:
        opt: OptimizationProblem object
    """
    sim_dict = get_simulation(
        component,
        resolution=resolution,
        extend_ports_length=extend_ports_length,
        layer_stack=layer_stack,
        zmargin_top=zmargin_top,
        zmargin_bot=zmargin_bot,
        tpml=tpml,
        clad_material=clad_material,
        is_3d=is_3d,
        wavelength_start=wavelength_start,
        wavelength_stop=wavelength_stop,
        wavelength_points=wavelength_points,
        dfcen=dfcen,
        port_source_name=port_source_name,
        port_margin=port_margin,
        distance_source_to_monitors=distance_source_to_monitors,
        port_source_offset=port_source_offset,
        port_monitor_offset=port_monitor_offset,
        dispersive=dispersive,
        material_name_to_meep=material_name_to_meep,
        **settings,
    )
    sim = sim_dict["sim"]

    # Instantiate objective arguments
    monitors = sim_dict["monitors"]
    ob_list = [
        EigenmodeCoefficient(
            sim,
            Volume(
                center=monitor.regions[0].center,
                size=monitor.regions[0].size,
            ),
            TE_mode_number,
        )
        for monitor in monitors.values()
    ]

    # Instantiate design regions and add to simulation. Extend Component to include the design regions
    c = component.copy()
    for design_region, design_variable in zip(design_regions, design_variables):
        sim.geometry.append(
            Block(design_region.size, design_region.center, material=design_variable)
        )
        block = c << gf.components.rectangle(
            (design_region.size[0], design_region.size[1])
        )
        block.center = (design_region.center[0], design_region.center[1])

    # Extend simulation cell size to include the design regions
    cell_thickness = sim.cell_size[2]
    if not cell_size:
        sim.cell_size = Vector3(
            c.xsize + 2 * sim.boundary_layers[0].thickness,
            c.ysize + 2 * sim.boundary_layers[0].thickness,
            cell_thickness,
        )
    else:
        sim.cell_size = Vector3(*cell_size)

    # Redefine source to work with OptimizationProblem
    source = [
        EigenModeSource(
            sim.sources[0].src,
            eig_band=1,
            direction=sim.sources[0].direction,
            eig_kpoint=Vector3(1, 0, 0),
            size=sim.sources[0].size,
            center=sim.sources[0].center,
        )
    ]
    sim.sources = source

    opt = OptimizationProblem(
        simulation=sim,
        objective_functions=objective_function,
        objective_arguments=ob_list,
        design_regions=design_regions,
        frequencies=sim_dict["freqs"],
        decay_by=1e-5,
    )
    opt.plot2D(True)
    opt.update_design([design_update])

    return opt


def run_meep_adjoint_optimizer(
    number_of_params: int,
    cost_function: LambdaType,
    update_variable: np.ndarray,
    maximize_cost_function: bool = True,
    algorithm: int = nlopt.LD_MMA,
    lower_bound: Any = 0,<commit_msg>Update meep_adjoint_optimization.py<commit_after>from types import LambdaType
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

import nlopt
import numpy as np
from numpy import ndarray
from meep import Block, EigenModeSource, MaterialGrid, Simulation, Vector3, Volume
from meep.adjoint import DesignRegion, EigenmodeCoefficient, OptimizationProblem
from meep.visualization import get_2D_dimensions

import gdsfactory as gf
from gdsfactory import Component
from gdsfactory.simulation.gmeep import get_simulation
from gdsfactory.tech import LayerStack
from gdsfactory.types import Layer


def get_meep_adjoint_optimizer(
    component: Component,
    objective_function: List[Callable],
    design_regions: List[DesignRegion],
    design_variables: List[MaterialGrid],
    design_update: np.ndarray,
    TE_mode_number: int = 1,
    resolution: int = 30,
    cell_size: Optional[Tuple] = None,
    extend_ports_length: Optional[float] = 10.0,
    layer_stack: Optional[LayerStack] = None,
    zmargin_top: float = 3.0,
    zmargin_bot: float = 3.0,
    tpml: float = 1.5,
    clad_material: str = "SiO2",
    is_3d: bool = False,
    wavelength_start: float = 1.5,
    wavelength_stop: float = 1.6,
    wavelength_points: int = 50,
    dfcen: float = 0.2,
    port_source_name: str = "o1",
    port_margin: float = 3,
    distance_source_to_monitors: float = 0.2,
    port_source_offset: float = 0,
    port_monitor_offset: float = 0,
    dispersive: bool = False,
    material_name_to_meep: Optional[Dict[str, Union[str, float]]] = None,
    **settings,
) -> OptimizationProblem:
    """Return a Meep `OptimizationProblem` object.

    Args:
        component: gdsfactory component
        objective_function: functions must be composed of "field functions" that transform the recorded fields
        design_regions: list of DesignRegion objects
        design_variables: list of MaterialGrid objects
        design_update: ndarray to intializethe optimization
        TE_mode_number: TE mode number
        resolution: in pixels/um (20: for coarse, 120: for fine)
        cell_size: tuple of Simulation object dimensions in um
        extend_ports_length: to extend ports beyond the PML.
        layer_stack: contains layer to thickness, zmin and material.
            Defaults to active pdk.layer_stack.
        zmargin_top: thickness for cladding above core.
        zmargin_bot: thickness for cladding below core.
        tpml: PML thickness (um).
        clad_material: material for cladding.
        is_3d: if True runs in 3D.
        wavelength_start: wavelength min (um).
        wavelength_stop: wavelength max (um).
        wavelength_points: wavelength steps.
        dfcen: delta frequency.
        port_source_name: input port name.
        port_margin: margin on each side of the port.
        distance_source_to_monitors: in (um) source goes before.
        port_source_offset: offset between source GDS port and source MEEP port.
        port_monitor_offset: offset between monitor GDS port and monitor MEEP port.
        dispersive: use dispersive material models (requires higher resolution).
        material_name_to_meep: map layer_stack names with meep material database name
            or refractive index. dispersive materials have a wavelength dependent index.

    Keyword Args:
        settings: extra simulation settings (resolution, symmetries, etc.)

    Returns:
        opt: OptimizationProblem object
    """
    sim_dict = get_simulation(
        component,
        resolution=resolution,
        extend_ports_length=extend_ports_length,
        layer_stack=layer_stack,
        zmargin_top=zmargin_top,
        zmargin_bot=zmargin_bot,
        tpml=tpml,
        clad_material=clad_material,
        is_3d=is_3d,
        wavelength_start=wavelength_start,
        wavelength_stop=wavelength_stop,
        wavelength_points=wavelength_points,
        dfcen=dfcen,
        port_source_name=port_source_name,
        port_margin=port_margin,
        distance_source_to_monitors=distance_source_to_monitors,
        port_source_offset=port_source_offset,
        port_monitor_offset=port_monitor_offset,
        dispersive=dispersive,
        material_name_to_meep=material_name_to_meep,
        **settings,
    )
    sim = sim_dict["sim"]

    # Instantiate objective arguments
    monitors = sim_dict["monitors"]
    ob_list = [
        EigenmodeCoefficient(
            sim,
            Volume(
                center=monitor.regions[0].center,
                size=monitor.regions[0].size,
            ),
            TE_mode_number,
        )
        for monitor in monitors.values()
    ]

    # Instantiate design regions and add to simulation. Extend Component to include the design regions
    c = component.copy()
    for design_region, design_variable in zip(design_regions, design_variables):
        sim.geometry.append(
            Block(design_region.size, design_region.center, material=design_variable)
        )
        block = c << gf.components.rectangle(
            (design_region.size[0], design_region.size[1])
        )
        block.center = (design_region.center[0], design_region.center[1])

    # Extend simulation cell size to include the design regions
    cell_thickness = sim.cell_size[2]
    if not cell_size:
        sim.cell_size = Vector3(
            c.xsize + 2 * sim.boundary_layers[0].thickness,
            c.ysize + 2 * sim.boundary_layers[0].thickness,
            cell_thickness,
        )
    else:
        sim.cell_size = Vector3(*cell_size)

    # Redefine source to work with OptimizationProblem
    source = [
        EigenModeSource(
            sim.sources[0].src,
            eig_band=1,
            direction=sim.sources[0].direction,
            eig_kpoint=Vector3(1, 0, 0),
            size=sim.sources[0].size,
            center=sim.sources[0].center,
        )
    ]
    sim.sources = source

    opt = OptimizationProblem(
        simulation=sim,
        objective_functions=objective_function,
        objective_arguments=ob_list,
        design_regions=design_regions,
        frequencies=sim_dict["freqs"],
        decay_by=1e-5,
    )
    opt.update_design([design_update])

    opt.plot2D(True)

    return opt


def run_meep_adjoint_optimizer(
    number_of_params: int,
    cost_function: LambdaType,
    update_variable: np.ndarray,
    maximize_cost_function: bool = True,
    algorithm: int = nlopt.LD_MMA,
    lower_bound: Any = 0,
{'fraction_non_alphanumeric': 0.07289806692027016, 'fraction_numerical': 0.010092384131666797, 'mean_word_length': 2.8638272345530895, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '413253', 'n_tokens_mistral': 3906, 'n_tokens_neox': 3753, 'n_words': 970}