def cubic_param_shape( initializer: Callable, extents: np.ndarray, pixel_spacing: float, control_point_spacing: float, pos: Union[np.ndarray, goos.Function], var_name: Optional[str] = None, reflection_symmetry: List[int] = None, periods: List[int] = None, **kwargs, ) -> Tuple[goos.Variable, Shape]: """Creates a new continuous parametrization using bicubic interpolation. The values of the parametrization are governed by bicubic interpolation on certain control points. Control points are defined with spacing given by `control_point_spacing`. Args: initializer: A callable to initialize values for the shape. This should accept a single argument `size` and return an array of values with shape `size`. extents: Extents of the shape. pixel_spacing: The pixel size will be given by `(pixel_spacing, pixel_spacing, extents[2])`. control_point_spacing: Spacing between two control points. var_name: Name to give the variable. pos: Position of the shape. **kwargs: Additional argument to pass to shape constructor. Returns: A tuple `(var, shape)` where `var` is the variable containing the values and `shape` is the newly created shape. """ # TODO(vcruysse): Stop using the old parametrization implementation. from spins.goos import compat from spins.invdes.problem_graph import optplan if not isinstance(pos, goos.Function): pos = goos.Constant(pos) return compat.compat_param( param=optplan.CubicParametrization( undersample=control_point_spacing / pixel_spacing, reflection_symmetry=reflection_symmetry, periods=periods), initializer=initializer, extents=extents, pixel_size=[pixel_spacing, pixel_spacing, extents[2]], pos=pos, var_name=var_name, **kwargs)
def create_transformations( obj: optplan.Function, monitors: List[optplan.Monitor], sim_space: optplan.SimulationSpaceBase, cont_iters: int, # require more to optimise power better num_stages: int = 3, min_feature: float = 100, ) -> List[optplan.Transformation]: """Creates a list of transformations for the device optimization. The transformations dictate the sequence of steps used to optimize the device. The optimization uses `num_stages` of continuous optimization. For each stage, the "discreteness" of the structure is increased (through controlling a parameter of a sigmoid function). Args: opt: The objective function to minimize. monitors: List of monitors to keep track of. sim_space: Simulation space ot use. cont_iters: Number of iterations to run in continuous optimization total across all stages. num_stages: Number of continuous stages to run. The more stages that are run, the more discrete the structure will become. min_feature: Minimum feature size in nanometers. Returns: A list of transformations. """ # Setup empty transformation list. trans_list = [] # First do continuous relaxation optimization. # This is done through cubic interpolation and then applying a sigmoid # function. param = optplan.CubicParametrization( # Specify the coarseness of the cubic interpolation points in terms # of number of Yee cells. Feature size is approximated by having # control points on the order of `min_feature / GRID_SPACING`. undersample=3.5 * min_feature / GRID_SPACING, simulation_space=sim_space, init_method=optplan.UniformInitializer(min_val=0.6, max_val=0.9), ) iters = max(cont_iters // num_stages, 1) for stage in range(num_stages): trans_list.append( optplan.Transformation( name="opt_cont{}".format(stage), parametrization=param, transformation=optplan.ScipyOptimizerTransformation( optimizer="L-BFGS-B", objective=obj, monitor_lists=optplan.ScipyOptimizerMonitorList( callback_monitors=monitors, start_monitors=monitors, end_monitors=monitors), optimization_options=optplan.ScipyOptimizerOptions( maxiter=iters), ), )) if stage < num_stages - 1: # Make the structure more discrete. trans_list.append( optplan.Transformation( name="sigmoid_change{}".format(stage), parametrization=param, # The larger the sigmoid strength value, the more "discrete" # structure will be. transformation=optplan.CubicParamSigmoidStrength( value=4 * (stage + 1)), )) return trans_list
def create_transformations( obj: optplan.Function, monitors: List[optplan.Monitor], sim_space: optplan.SimulationSpaceBase, cont_iters: int, num_stages: int = 3, min_feature: float = 100, ) -> List[optplan.Transformation]: """Creates a list of transformations for the device optimization. The transformations dictate the sequence of steps used to optimize the device. The optimization uses `num_stages` of continuous optimization. For each stage, the "discreteness" of the structure is increased (through controlling a parameter of a sigmoid function). Args: obj: The objective function to minimize. monitors: List of monitors to keep track of. sim_space: Simulation space ot use. cont_iters: Number of iterations to run in continuous optimization total across all stages. num_stages: Number of continuous stages to run. The more stages that are run, the more discrete the structure will become. min_feature: Minimum feature size in nanometers. fab_obj: Objective including fabrication penalties to be used in the second half of the optimization Returns: A list of transformations. """ # Setup empty transformation list. trans_list = [] # First do continuous relaxation optimization. # This is done through cubic interpolation and then applying a sigmoid # function. param = optplan.CubicParametrization( # Specify the coarseness of the cubic interpolation points in terms # of number of Yee cells. Feature size is approximated by having # control points on the order of `min_feature / GRID_SPACING`. undersample=3.5 * min_feature / GRID_SPACING, simulation_space=sim_space, init_method=optplan.WaveguideInitializer3(lower_min=0, lower_max=.2, upper_min=.7, upper_max=1, extent_frac_x=1, extent_frac_y=1 / 2, center_frac_x=1 / 2, center_frac_y=1 / 2), # init_method=optplan.GradientInitializer(min=0, max=1, random=0.3, extent_frac_x=1, extent_frac_y=0.4, # center_frac_x=0.5, center_frac_y=0.55) # init_method=optplan.UniformInitializer(min_val=0, max_val=0) # init_method=optplan.PeriodicInitializer(random=0.2, min=0, max=1, period=400, sim_width=6000, # center_frac_y=0.5, extent_frac_y=0.4) ) trans_list.append( optplan.Transformation( name="sigmoid_change_init", parametrization=param, # The larger the sigmoid strength value, the more "discrete" # structure will be. transformation=optplan.CubicParamSigmoidStrength(value=4, ))) iters = max(cont_iters // num_stages, 1) for stage in range(num_stages): trans_list.append( optplan.Transformation( name="opt_cont{}".format(stage), parametrization=param, transformation=optplan.ScipyOptimizerTransformation( optimizer="L-BFGS-B", objective=obj, monitor_lists=optplan.ScipyOptimizerMonitorList( callback_monitors=monitors, start_monitors=monitors, end_monitors=monitors), optimization_options=optplan.ScipyOptimizerOptions( maxiter=iters), ), )) if stage < num_stages - 1: # Make the structure more discrete. trans_list.append( optplan.Transformation( name="sigmoid_change{}".format(stage), parametrization=param, # The larger the sigmoid strength value, the more "discrete" # structure will be. transformation=optplan.CubicParamSigmoidStrength( value=2 * (stage + 3)), )) return trans_list