Exemplo n.º 1
0
 def test_no_forward_injection_in_2D(self):
     """ Test no forward injection in 2D with mode source in vacuum. """
     self.fom = ModeMatch(monitor_name = 'figure_of_merit',
                          mode_number = 2, # evanescent mode
                          direction = 'Forward',
                          multi_freq_src = False,
                          target_T_fwd = lambda wl: np.ones(wl.size),
                          norm_p = 1)
     Optimization.set_source_wavelength(self.sim, 'source', self.fom.multi_freq_src, len(self.wavelengths))
     self.sim.fdtd.setnamed('FDTD','dimension','2D')
     self.fom.add_to_sim(self.sim)
     self.sim.run(name = 'modematch_no_forward_injection_in_2D', iter = 3)
     FOM = self.fom.get_fom(self.sim)
     self.assertAlmostEqual(FOM, 0.0, 5)
Exemplo n.º 2
0
 def test_backward_injection_in_3D(self):
     """ Test backward injection in 3D with mode source in dielectric region. """
     self.fom = ModeMatch(monitor_name = 'figure_of_merit',
                          mode_number = 1,
                          direction = 'Backward',
                          multi_freq_src = True,
                          target_T_fwd = lambda wl: np.ones(wl.size),
                          norm_p = 1)
     Optimization.set_source_wavelength(self.sim, 'source', self.fom.multi_freq_src, len(self.wavelengths))
     self.sim.fdtd.setnamed('FDTD','dimension','3D')
     self.sim.fdtd.setnamed('source', 'x', -self.sim.fdtd.getnamed('source','x'))
     self.sim.fdtd.setnamed('source','direction','Backward')
     self.sim.fdtd.setnamed('figure_of_merit','x', -self.sim.fdtd.getnamed('figure_of_merit','x'))
     self.fom.add_to_sim(self.sim)
     self.sim.run(name = 'modematch_backward_injection_in_3D', iter = 1)
     FOM = self.fom.get_fom(self.sim)
     self.assertAlmostEqual(FOM, self.ref_fom, 5)
 def test_forward_injection_in_2D(self):
     """ Test forward injection in 2D with mode source in vacuum. """
     self.fom = ModeMatch(monitor_name='figure_of_merit',
                          mode_number=1,
                          direction='Forward',
                          multi_freq_src=True,
                          target_T_fwd=lambda wl: np.ones(wl.size),
                          norm_p=1)
     Optimization.set_source_wavelength(self.sim, 'source',
                                        self.fom.multi_freq_src,
                                        len(self.wavelengths))
     self.sim.fdtd.setnamed('FDTD', 'dimension', '2D')
     self.fom.initialize(self.sim)
     self.fom.make_forward_sim(self.sim)
     self.sim.run(name='modematch_forward_injection_in_2D', iter=2)
     FOM = self.fom.get_fom(self.sim)
     self.assertAlmostEqual(FOM, self.ref_fom, 4)
    def setUp(self):
        # Base simulation project files
        self.base_TE_sim = os.path.join(
            self.file_dir,
            'co_optimization_parallel_plate_waveguide_TE_base.fsp')
        self.base_TM_sim = os.path.join(
            self.file_dir,
            'co_optimization_parallel_plate_waveguide_TM_base.fsp')
        # Simulation bandwidth
        self.wavelengths = Wavelengths(start=1500e-9, stop=1600e-9, points=12)
        # Polygon defining a rectangle that can grow or shrink along the y-axis to fill the gap
        self.mesh_del = 10.0e-9
        # must be kept in sych with self.base_script
        initial_points_y = np.array(
            [1.75 * self.mesh_del, 0.01 * self.mesh_del])

        def wall(param=initial_points_y):
            assert param.size == 2, "walls defined by two points."
            self.wg_gap = 10.0 * self.mesh_del  # must be kept in sych
            points_x = 0.5 * np.array(
                [-self.wg_gap, self.wg_gap, self.wg_gap, -self.wg_gap])
            points_y = np.array([-param[0], -param[1], param[1], param[0]])
            polygon_points = [(x, y) for x, y in zip(points_x, points_y)]
            return np.array(polygon_points)

        self.wg_width = 50.0 * self.mesh_del  # must be kept in synch
        bounds = [(0.0, self.wg_width / 2.0)] * initial_points_y.size
        self.geometry = FunctionDefinedPolygon(
            func=wall,
            initial_params=initial_points_y,
            bounds=bounds,
            z=0.0,  # must be kept in sych
            depth=self.wg_width,
            eps_out=Material(base_epsilon=1.0**2,
                             name='<Object defined dielectric>',
                             mesh_order=2),  # must be kept in synch
            eps_in=Material(base_epsilon=4.0**2,
                            name='<Object defined dielectric>',
                            mesh_order=1),  # must be kept in sych
            edge_precision=50,
            dx=1.0e-10)
        # Figure of merit
        self.fom = ModeMatch(
            monitor_name='fom',  # must be kept in sych
            mode_number=1,  # must be kept in sych
            direction='Forward',
            multi_freq_src=True,
            target_T_fwd=lambda wl: np.ones(wl.size),
            norm_p=1)
        # Scipy optimizer
        self.optimizer = ScipyOptimizers(max_iter=5,
                                         method='L-BFGS-B',
                                         scaling_factor=1.0e7,
                                         pgtol=1.0e-5,
                                         ftol=1.0e-12,
                                         target_fom=0.0,
                                         scale_initial_gradient_to=None)
Exemplo n.º 5
0
 def test_single_wavelength_fom_integral(self):
     """ Test FOM integral for single wavelength case: result should be input FOM for backward compatibility. """
     exact_fom = 0.4896
     fom = ModeMatch.fom_wavelength_integral(
         T_fwd_vs_wavelength=np.array([exact_fom]),
         wavelengths=np.array([1300e-9]),
         target_T_fwd=lambda wl: 0.5 * np.ones(wl.size),
         norm_p=1)  # unused
     self.assertAlmostEqual(fom, exact_fom, 15)
Exemplo n.º 6
0
 def test_single_wavelength_gradient_integral(self):
     """ Test FOM gradient integral for single wavelength case. """
     fom_grad = ModeMatch.fom_gradient_wavelength_integral_impl(
         T_fwd_vs_wavelength=np.array([0.2851]),
         T_fwd_partial_derivs_vs_wl=np.array([2.0]),
         target_T_fwd_vs_wavelength=np.array([1.0]),
         wl=np.array([1800e-9]),
         norm_p=1)
     exact_fom_grad = -1.0 * np.sign(0.2851 - 1.0) * 2.0
     self.assertAlmostEqual(fom_grad[0], exact_fom_grad, 15)
def runSim(params,
           eps_bg,
           eps_wg,
           x_pos,
           y_pos,
           size_x,
           filter_R,
           beta_start=1):

    ######## DEFINE A 2D TOPOLOGY OPTIMIZATION REGION ########
    geometry = TopologyOptimization2D(params=params,
                                      eps_min=eps_bg,
                                      eps_max=eps_wg,
                                      x=x_pos,
                                      y=y_pos,
                                      z=0,
                                      filter_R=filter_R,
                                      beta=beta_start)

    ######## DEFINE FIGURE OF MERIT ########
    # The base simulation script defines a field monitor named 'fom' at the point where we want to modematch to the fundamental TE mode
    fom = ModeMatch(monitor_name='fom',
                    mode_number='Fundamental TE mode',
                    direction='Forward',
                    norm_p=2)

    ######## DEFINE OPTIMIZATION ALGORITHM ########
    optimizer = ScipyOptimizers(max_iter=50,
                                method='L-BFGS-B',
                                scaling_factor=1,
                                pgtol=1e-6,
                                ftol=1e-4,
                                target_fom=0.5,
                                scale_initial_gradient_to=0.25)

    ######## LOAD TEMPLATE SCRIPT AND SUBSTITUTE PARAMETERS ########
    script = load_from_lsf(
        os.path.join(CONFIG['root'],
                     'examples/Ysplitter/splitter_base_2D_TE_topology.lsf'))
    script = script.replace('opt_size_x=3.5e-6',
                            'opt_size_x={:1.6g}'.format(size_x))

    wavelengths = Wavelengths(start=1450e-9, stop=1650e-9, points=11)
    opt = Optimization(base_script=script,
                       wavelengths=wavelengths,
                       fom=fom,
                       geometry=geometry,
                       optimizer=optimizer,
                       use_deps=False,
                       hide_fdtd_cad=True,
                       plot_history=False,
                       store_all_simulations=False)

    ######## RUN THE OPTIMIZER ########
    opt.run()
Exemplo n.º 8
0
 def test_fom_integral_norm_p1(self):
     """ Test FOM integral with norm p = 1. """
     wl_points = 5
     fom = ModeMatch.fom_wavelength_integral(
         T_fwd_vs_wavelength=np.ones(wl_points),
         wavelengths=np.linspace(1300e-9, 1800e-9, wl_points),
         target_T_fwd=lambda wl: np.power(
             np.sin(np.pi * (wl - wl.min()) / (wl.max() - wl.min())), 2),
         norm_p=1)
     exact_fom = 0.0
     self.assertAlmostEqual(fom, exact_fom, 15)
Exemplo n.º 9
0
 def test_fom_gradient_integral_p1(self):
     """ Test FOM gradient integral with norm p = 1. """
     wl_points = 3
     wavelengths = np.linspace(1300e-9, 1800e-9, wl_points)
     target_T_fwd = lambda wl: np.linspace(0.0, 1.0, wl.size)
     fom_grad = ModeMatch.fom_gradient_wavelength_integral_impl(
         T_fwd_vs_wavelength=0.25 * np.ones(wl_points),
         T_fwd_partial_derivs_vs_wl=np.ones((1, wl_points)),
         target_T_fwd_vs_wavelength=target_T_fwd(wavelengths),
         wl=wavelengths,
         norm_p=1)
     self.assertAlmostEqual(fom_grad[0], 0.5, 15)
Exemplo n.º 10
0
 def test_fom_integral_norm_p2(self):
     """ Test FOM integral with norm p = 2. """
     wl_points = 5000
     fom = ModeMatch.fom_wavelength_integral(
         T_fwd_vs_wavelength=0.5 * np.ones(wl_points),
         wavelengths=np.linspace(1.0e-9, 1.0e-8, wl_points),
         target_T_fwd=lambda wl: np.exp(-1.0 * (wl - wl.min()) /
                                        (wl.max() - wl.min())),
         norm_p=2)
     exact_fom = 0.5 * np.exp(-1) * (
         np.sqrt(2.0 * (np.exp(2.0) - 1.0)) -
         np.sqrt(4.0 * np.exp(1.0) - np.exp(2.0) - 2.0))
     self.assertAlmostEqual(fom, exact_fom, 7)
Exemplo n.º 11
0
 def test_fom_gradient_integral_p2(self):
     """ Test FOM gradient integral with norm p = 2. """
     wl_points = 5000
     wavelengths = np.linspace(1.0e-9, 1.0e-8, wl_points)
     target_T_fwd = lambda wl: np.exp(-1.0 * (wl - wl.min()) /
                                      (wl.max() - wl.min()))
     fom_grad = ModeMatch.fom_gradient_wavelength_integral_impl(
         T_fwd_vs_wavelength=0.5 * np.ones(wl_points),
         T_fwd_partial_derivs_vs_wl=np.ones((1, wl_points)),
         target_T_fwd_vs_wavelength=target_T_fwd(wavelengths),
         wl=wavelengths,
         norm_p=2)
     exact_fom_grad = (np.exp(1.0) - 2.0) / np.sqrt(4.0 * np.exp(1.0) -
                                                    np.exp(2.0) - 2.0)
     self.assertAlmostEqual(fom_grad[0], exact_fom_grad, 7)
Exemplo n.º 12
0
 def setUp(self):
     # Base simulation script
     self.base_script = load_from_lsf(os.path.join(self.file_dir, 'optimization_waveguide_filter_TM_2D_base.lsf'))
     # Simulation bandwidth
     self.wavelengths = Wavelengths(start = 1300e-9,
                                    stop = 1800e-9,
                                    points = 41)
     # Polygons to form the two gaps
     self.mesh_del = 20.0e-9; # must be kept in sych with self.base_script
     initial_param = 10.0 * np.array([self.mesh_del])
     def rectangle(param = initial_param, offset = 0.0):
         assert param.size == 1, "rectangle grows along a single dimension."
         wg_width = 35.0 * self.mesh_del # must be kept in synch
         points_x = 0.5 * np.array([-wg_width,  wg_width, wg_width, -wg_width])
         points_y = 0.5 * np.array([-param, -param, param,  param]) + offset
         polygon_points = [(x, y) for x, y in zip(points_x, points_y)]
         return np.array(polygon_points)
     bounds = [(self.mesh_del, 20.0 * self.mesh_del)]
     z = 0.0 # must be kept in sych
     depth = 200.0 * self.mesh_del # must be kept in sych
     eps_in = Material(base_epsilon = 1.44 ** 2, mesh_order = 1) # must be kept in sych with
     eps_out = Material(base_epsilon = 2.8 ** 2, mesh_order = 1) # must be kept in sych with
     edge_precision = 25
     dx = 1.0e-10
     self.geometry = (FunctionDefinedPolygon(func = lambda param: rectangle(param[0], 2.0 * param[0]), initial_params = initial_param, bounds = bounds, z = z, depth = depth, eps_out = eps_out, eps_in = eps_in, edge_precision = edge_precision, dx = dx) *
                      FunctionDefinedPolygon(func = lambda param: rectangle(param[0],-2.0 * param[0]), initial_params = initial_param, bounds = bounds, z = z, depth = depth, eps_out = eps_out, eps_in = eps_in, edge_precision = edge_precision, dx = dx))
     # Broadband figure of merit
     target_T_fwd = lambda wl: 0.3 + 0.65*np.power(np.sin(np.pi * (wl - wl.min()) / (wl.max() - wl.min())), 6)
     self.fom = ModeMatch(monitor_name = 'FOM', # must be kept in sych
                          mode_number = 1, # must be kept in sych
                          direction = 'Backward',
                          multi_freq_src = True,
                          target_T_fwd = target_T_fwd,
                          norm_p = 1)
     # Scipy optimzier
     self.optimizer = ScipyOptimizers(max_iter = 10, 
                                      method = 'L-BFGS-B',
                                      scaling_factor = 1.0e7,
                                      pgtol = 5.6e-3)
Exemplo n.º 13
0
bounds = [(-1.0, 1.0)]*16
initial_params = np.array([0.0]*16)
grating_number = 16
designarealength = 1.12e-6
width_max = 0.07e-6
center_x_start = -designarealength/2 + width_max/2
center_y_start = 0
i = 0
Polygon_Series = FunctionDefinedPolygon(func = make_polygon_func(center_x_start,center_y_start,i), initial_params = initial_params, bounds = bounds, z = 0, depth = 220e-9, eps_out = 2.8 ** 2, eps_in = 1.44 ** 2, edge_precision = 5, dx = 0.1e-9)
for i in range(1,grating_number):
    center_x_start += width_max
    Polygon_Series = Polygon_Series * FunctionDefinedPolygon(func = make_polygon_func(center_x_start,center_y_start,i), initial_params = initial_params, bounds = bounds, z = 0, depth = 220e-9, eps_out = 2.8 ** 2, eps_in = 1.44 ** 2, edge_precision = 5, dx = 0.1e-9)



######## DEFINE FIGURE OF MERIT ########
# Although we are optimizing for the same thing, two separate fom objects must be created.

fom_1550 = ModeMatch(monitor_name = 'fom', mode_number = 1, direction = 'Forward', target_T_fwd = lambda wl: np.ones(wl.size), norm_p = 1)

######## DEFINE OPTIMIZATION ALGORITHM ########
#For the optimizer, they should all be set the same, but different objects. Eventually this will be improved
optimizer_1550 = GLOptimizer(max_iter = 10, method = 'L-BFGS-B', scaling_factor = 1e-6, pgtol = 1e-9)

######## PUT EVERYTHING TOGETHER ########
opt_1550 = Optimization(base_script = script_1550, wavelengths = wavelengths_1550, fom = fom_1550, geometry = Polygon_Series, optimizer = optimizer_1550, hide_fdtd_cad = False, use_deps = True)
opt = opt_1550

######## RUN THE OPTIMIZER ########
opt.run()
Exemplo n.º 14
0
# Function to build the geometry to optimized
parSet.study.geometry_function = FunctionDefinedPolygon(
    func=taper_splitter,
    initial_params=np.ones(10, ) * 0.75e-6,
    bounds=param_bounds,
    z=0,
    depth=220e-9,
    eps_out=1.44**2,
    eps_in=2.85**2,
    edge_precision=5,
    dx=0.1e-9)
# A name to identify the simulation results
parSet.study.fom_name = 'mode_match'
# Figure of merit
parSet.study.fom_function = ModeMatch(monitor_name='fom',
                                      mode_number=2,
                                      direction='Forward')
# Hide GUI during simulation
parSet.study.hide_gui = False

## Sampler settings
parSet.sampler.type = 'random-lumopt'
# Parameters bounds for global search
parSet.sampler.global_parameters_bounds = param_bounds

# Function to filter simulation results after local search (optional)
parSet.sampler.local_result_constraint = lambda res: res > 0.95
# lumopt parameters
parSet.sampler.local_max_iterations = 50
parSet.sampler.local_ftol = 1e-3
parSet.sampler.local_pgtol = 1e-3
Exemplo n.º 15
0
bounds = [(-0.25e-6, 0.25e-6)]*10

#final value from splitter_opt_2D.py optimization
initial_params=np.linspace(0,0.24e-6,10)
#initial_params=np.linspace(-0.25e-6,0.25e-6,10)
geometry_1550_lower =  function_defined_Polygon(func=lower_coupler_arm,initial_params=initial_params,eps_out=1.44 ** 2, eps_in=2.8 ** 2,bounds=bounds,depth=220e-9,edge_precision=5)
geometry_1550_upper =  function_defined_Polygon(func=upper_coupler_arm,initial_params=initial_params,eps_out=1.44 ** 2, eps_in=2.8 ** 2,bounds=bounds,depth=220e-9,edge_precision=5)
geometry_1550=geometry_1550_lower*geometry_1550_upper
geometry_1310_lower =  function_defined_Polygon(func=lower_coupler_arm,initial_params=initial_params,eps_out=1.44 ** 2, eps_in=2.8 ** 2,bounds=bounds,depth=220e-9,edge_precision=5)
geometry_1310_upper =  function_defined_Polygon(func=upper_coupler_arm,initial_params=initial_params,eps_out=1.44 ** 2, eps_in=2.8 ** 2,bounds=bounds,depth=220e-9,edge_precision=5)
geometry_1310=geometry_1310_lower*geometry_1310_upper

######## DEFINE FIGURE OF MERIT ########
# Although we are optimizing for the same thing, two separate fom objects must be create

fom_1550=ModeMatch(modeorder=2,wavelength=1550e-9,monitor_name='fom_1550')
fom_1310=ModeMatch(modeorder=2,wavelength=1310e-9,monitor_name='fom_1310')

######## DEFINE OPTIMIZATION ALGORITHM ########
#For the optimizer, they should all be set the same, but different objects. Eventually this will be improved
optimizer_1550=ScipyOptimizers(max_iter=40)
optimizer_1310=ScipyOptimizers(max_iter=40)

######## PUT EVERYTHING TOGETHER ########
opt_1550=Optimization(base_script=script_1550,fom=fom_1550,geometry=geometry_1550,optimizer=optimizer_1550)
opt_1310=Optimization(base_script=script_1310,fom=fom_1310,geometry=geometry_1310,optimizer=optimizer_1310)

opt=opt_1550+opt_1310

######## RUN THE OPTIMIZER ########
opt.run()
Exemplo n.º 16
0
geometry = function_defined_Polygon(func=taper_splitter,
                                    initial_params=initial_params,
                                    eps_out=1.44**2,
                                    eps_in='Si (Silicon) - Palik',
                                    bounds=bounds,
                                    depth=220e-9,
                                    edge_precision=5)
# We must define the permittivities of the material making the optimizable
# geometry and of that surrounding it. Since this is a 2D simulation, the depth has no importance.
# edge_precision defines the discretization of the edges forming the optimizable polygon. It should be set such
# that there are at least a few points per mesh cell. An effective index of 2.8 is user to simulate a 2D slab of
# 220 nm thick

######## DEFINE FIGURE OF MERIT ########

fom = ModeMatch(modeorder=1, monitor_name='fom', wavelength=1550e-9)
# The base simulation script defines a field monitor named 'fom' at the point where we want to
# modematch to the 3rd order mode (fundamental TE mode)

######## DEFINE OPTIMIZATION ALGORITHM ########
optimizer = ScipyOptimizers(max_iter=20, method='L-BFGS-B', scaling_factor=1e6)
# This will run Scipy's implementation of the L-BFGS-B algoithm for at least 40 iterations. Since the variables are on the
# order of 1e-6, we scale them up to be on the order of 1

######## PUT EVERYTHING TOGETHER ########
opt = Optimization(base_script=script,
                   fom=fom,
                   geometry=geometry,
                   optimizer=optimizer)

######## RUN THE OPTIMIZER ########
Exemplo n.º 17
0
def runGratingOptimization(bandwidth_in_nm, etch_depth_shallow, etch_depth_deep, n_grates, initial_params = None):
    ### Yet another parametrization which allows to enforce minimum feature size when the optimizer only supports box constraints  
    ### params = [x0, a1, b1, ..., aN]
    if initial_params is None:
        params = np.zeros(4*n_grates)

        for i in range(n_grates):
            params[i*4]   = 0.2     #< Width up
            params[i*4+1] = 0.4*(i/n_grates)     #< Width of the shallow etch
            params[i*4+2] = 0.1    #< Width up
            params[i*4+3] = 0.4*(i/n_grates)     #< Width of the deep etch

        params[0] = 0      #< Overwrite the first since it has a special meaning: Start of the grating at 0um
    else:
        params = initial_params

    bounds = [(0, 1)]*(4*n_grates)  
    bounds[0] = (-3,3)

    def grating_params_pos(params, output_waveguide_length = 0.5e-6, height = 220e-9, y0 = 0):
        x_begin = -3e-6

        y3 = y0+height
        y2 = y3-etch_depth_deep
        y1 = y3-etch_depth_shallow

        x0 = params[0]*1e-6     #< First parameter is the starting position
        verts = np.array( [ [x_begin,y0],[x_begin,y3],[x0,y3],[x0,y1] ] )
        
        ## Iterate over all but the last
        for i in range(n_grates-1):
            x1 = x0 + params[i*4+1]*1e-6    #< Width of the deep etch
            x2 = x1 + params[i*4+2]*1e-6    #< Width up
            x3 = x2 + params[i*4+3]*1e-6    #< Width of the shallow etch
            x4 = x3 + params[i*4+4]*1e-6    #< Width up
            verts = np.concatenate((verts,[[x1,y1],[x1,y3],[x2,y3],[x2,y2],[x3,y2],[x3,y3],[x4,y3],[x4,y1]]),axis=0)
            x0 = x4

        x1 = x0 + params[(n_grates-1)*4+1]*1e-6    #< Width of the deep etch
        x2 = x1 + params[(n_grates-1)*4+2]*1e-6    #< Width up
        x3 = x2 + params[(n_grates-1)*4+3]*1e-6    #< Width of the shallow etch
        x_end   = x3+output_waveguide_length
        verts = np.concatenate((verts,[[x1,y1],[x1,y3],[x2,y3],[x2,y2],[x3,y2],[x3,y3],[x_end,y3],[x_end,y0]]),axis=0) 

        return verts

    geometry = FunctionDefinedPolygon(func = grating_params_pos, initial_params = params, bounds = bounds, z = 0.0, depth = 220e-9, eps_out = 1.44 ** 2, eps_in = 3.47668 ** 2, edge_precision = 5, dx = 1e-3)

    ######## DEFINE FIGURE OF MERIT ########
    fom = ModeMatch(monitor_name = 'fom', mode_number = 1, direction = 'Backward', target_T_fwd = lambda wl: np.ones(wl.size), norm_p = 1)

    ######## DEFINE OPTIMIZATION ALGORITHM ########
    optimizer = ScipyOptimizers(max_iter = 250, method = 'L-BFGS-B', scaling_factor = 1, pgtol = 1e-6) #SLSQP

    ######## DEFINE BASE SIMULATION ########
    base_script = load_from_lsf(os.path.join(os.path.dirname(__file__), 'grating_coupler_2D_2etch.lsf'))

    ######## PUT EVERYTHING TOGETHER ########
    lambda_start = 1550 - bandwidth_in_nm/2
    lambda_end   = 1550 + bandwidth_in_nm/2
    lambda_pts   = int(bandwidth_in_nm/10)+1
    wavelengths = Wavelengths(start = lambda_start*1e-9, stop = lambda_end*1e-9, points = lambda_pts)
    opt = Optimization(base_script = base_script, wavelengths = wavelengths, fom = fom, geometry = geometry, optimizer = optimizer, hide_fdtd_cad = True, use_deps = True)

    ######## RUN THE OPTIMIZER ########
    opt.run()
Exemplo n.º 18
0
# per mesh cell. An effective index of 2.8 is user to simulate a 2D slab of 220 nm thickness.
geometry = FunctionDefinedPolygon(func=taper_splitter,
                                  initial_params=inital_params,
                                  bounds=bounds,
                                  z=0.0,
                                  depth=220e-9,
                                  eps_out=1.44**2,
                                  eps_in=2.8**2,
                                  edge_precision=5,
                                  dx=0.01e-9)

######## DEFINE FIGURE OF MERIT ########
# The base simulation script defines a field monitor named 'fom' at the point where we want to modematch to the 3rd mode (fundamental TE mode).
fom = ModeMatch(monitor_name='fom',
                mode_number=2,
                direction='Forward',
                multi_freq_src=False,
                target_T_fwd=lambda wl: np.ones(wl.size),
                norm_p=1)

######## DEFINE OPTIMIZATION ALGORITHM ########
# This will run Scipy's implementation of the L-BFGS-B algoithm for at least 40 iterations. Since the variables are on the
# order of 1e-6, thery are scale up to be on the order of 1.
optimizer = ScipyOptimizers(max_iter=500,
                            method='L-BFGS-B',
                            scaling_factor=1e6,
                            pgtol=1e-9)

######## PUT EVERYTHING TOGETHER ########
opt = Optimization(base_script=base_script,
                   wavelengths=wavelengths,
                   fom=fom,
Exemplo n.º 19
0
                                         eps_out=silicon,
                                         eps_in=oxide,
                                         bounds=bounds,
                                         depth=1e-6,
                                         edge_precision=edge_precision)
    full_geometry = full_geometry * new_tooth

# We must define the permittivities of the material making the optimizable
# geometry and of that surrounding it. Since this is a 2D simulation, the depth has no importance.
# edge_precision defines the discretization of the edges forming the optimizable polygon. It should be set such
# that there are at least a few points per mesh cell. An effective index of 2.8 is user to simulate a 2D slab of
# 220 nm thick

######## DEFINE FIGURE OF MERIT ########

fom = ModeMatch(modeorder=1, monitor_name='fom',
                wavelength=1550e-9)  #,direction='Backward')
# The base simulation script defines a field monitor named 'fom' at the point where we want to
# modematch to the 3rd order mode (fundamental TE mode)

######## DEFINE OPTIMIZATION ALGORITHM ########
optimizer = ScipyOptimizers(max_iter=30, method='L-BFGS-B', scaling_factor=1e6)
#optimizer = FixedStepGradientDescent(max_iter=40,max_dx=20e-9)#ScipyOptimizers(max_iter=30,method='L-BFGS-B',scaling_factor=1e6)
# This will run Scipy's implementation of the L-BFGS-B algoithm for at least 40 iterations. Since the variables are on the
# order of 1e-6, we scale them up to be on the order of 1

######## PUT EVERYTHING TOGETHER ########
opt = Optimization(base_script=script,
                   fom=fom,
                   geometry=full_geometry,
                   optimizer=optimizer)
class TestModeMatchParallelPlateWaveguideTM(TestCase):
    """ 
        Unit test for the ModeMatch class: it performs a quick check that the figure of merit is computed correctly
        using a simple a parallel plate waveguide partially filled by a dielectric. The waveguide has a material interface
        in the middle, and the figure of merit should be the same regardless of the material in which the source is placed.
        This is used to verify that the ModeMatch inputs monitor_name, direction and mode number work correctly.
    """

    file_dir = os.path.abspath(os.path.dirname(__file__))

    def setUp(self):
        # base script
        self.base_script = load_from_lsf(
            os.path.join(self.file_dir,
                         'modematch_parallel_plate_waveguide_TM_base.lsf'))
        # bandwidth
        self.wavelengths = Wavelengths(start=1540e-9, stop=1560e-9, points=11)
        # simulation
        self.sim = Simulation(workingDir=self.file_dir,
                              use_var_fdtd=False,
                              hide_fdtd_cad=True)
        self.sim.fdtd.eval(self.base_script)
        Optimization.set_global_wavelength(self.sim, self.wavelengths)
        # reference
        self.ref_fom = 0.65161635

    def test_forward_injection_in_3D(self):
        """ Test forward injection in 3D with mode source in vacuum. """
        self.fom = ModeMatch(monitor_name='figure_of_merit',
                             mode_number=1,
                             direction='Forward',
                             multi_freq_src=True,
                             target_T_fwd=lambda wl: np.ones(wl.size),
                             norm_p=1)
        Optimization.set_source_wavelength(self.sim, 'source',
                                           self.fom.multi_freq_src,
                                           len(self.wavelengths))
        self.sim.fdtd.setnamed('FDTD', 'dimension', '3D')
        self.fom.initialize(self.sim)
        self.fom.make_forward_sim(self.sim)
        self.sim.run(name='modematch_forward_injection_in_3D', iter=0)
        FOM = self.fom.get_fom(self.sim)
        self.assertAlmostEqual(FOM, self.ref_fom, 4)

    def test_backward_injection_in_3D(self):
        """ Test backward injection in 3D with mode source in dielectric region. """
        self.fom = ModeMatch(monitor_name='figure_of_merit',
                             mode_number=1,
                             direction='Backward',
                             multi_freq_src=True,
                             target_T_fwd=lambda wl: np.ones(wl.size),
                             norm_p=1)
        Optimization.set_source_wavelength(self.sim, 'source',
                                           self.fom.multi_freq_src,
                                           len(self.wavelengths))
        self.sim.fdtd.setnamed('FDTD', 'dimension', '3D')
        self.sim.fdtd.setnamed('source', 'x',
                               -self.sim.fdtd.getnamed('source', 'x'))
        self.sim.fdtd.setnamed('source', 'direction', 'Backward')
        self.sim.fdtd.setnamed('figure_of_merit', 'x',
                               -self.sim.fdtd.getnamed('figure_of_merit', 'x'))
        self.fom.initialize(self.sim)
        self.fom.make_forward_sim(self.sim)
        self.sim.run(name='modematch_backward_injection_in_3D', iter=1)
        FOM = self.fom.get_fom(self.sim)
        self.assertAlmostEqual(FOM, self.ref_fom, 4)

    def test_forward_injection_in_2D(self):
        """ Test forward injection in 2D with mode source in vacuum. """
        self.fom = ModeMatch(monitor_name='figure_of_merit',
                             mode_number=1,
                             direction='Forward',
                             multi_freq_src=True,
                             target_T_fwd=lambda wl: np.ones(wl.size),
                             norm_p=1)
        Optimization.set_source_wavelength(self.sim, 'source',
                                           self.fom.multi_freq_src,
                                           len(self.wavelengths))
        self.sim.fdtd.setnamed('FDTD', 'dimension', '2D')
        self.fom.initialize(self.sim)
        self.fom.make_forward_sim(self.sim)
        self.sim.run(name='modematch_forward_injection_in_2D', iter=2)
        FOM = self.fom.get_fom(self.sim)
        self.assertAlmostEqual(FOM, self.ref_fom, 4)

    def test_no_forward_injection_in_2D(self):
        """ Test no forward injection in 2D with mode source in vacuum. """
        self.fom = ModeMatch(
            monitor_name='figure_of_merit',
            mode_number=2,  # evanescent mode
            direction='Forward',
            multi_freq_src=False,
            target_T_fwd=lambda wl: np.ones(wl.size),
            norm_p=1)
        Optimization.set_source_wavelength(self.sim, 'source',
                                           self.fom.multi_freq_src,
                                           len(self.wavelengths))
        self.sim.fdtd.setnamed('FDTD', 'dimension', '2D')
        self.fom.initialize(self.sim)
        self.fom.make_forward_sim(self.sim)
        self.sim.run(name='modematch_no_forward_injection_in_2D', iter=3)
        FOM = self.fom.get_fom(self.sim)
        self.assertAlmostEqual(FOM, 0.0, 5)

    def test_backward_injection_in_2D(self):
        """ Test backward injection in 2D with mode source in dielectric region. """
        self.fom = ModeMatch(monitor_name='figure_of_merit',
                             mode_number=1,
                             direction='Backward',
                             multi_freq_src=True,
                             target_T_fwd=lambda wl: np.ones(wl.size),
                             norm_p=1)
        Optimization.set_source_wavelength(self.sim, 'source',
                                           self.fom.multi_freq_src,
                                           len(self.wavelengths))
        self.sim.fdtd.setnamed('FDTD', 'dimension', '2D')
        self.sim.fdtd.setnamed('source', 'x',
                               -self.sim.fdtd.getnamed('source', 'x'))
        self.sim.fdtd.setnamed('source', 'direction', 'Backward')
        self.sim.fdtd.setnamed('figure_of_merit', 'x',
                               -self.sim.fdtd.getnamed('figure_of_merit', 'x'))
        self.fom.initialize(self.sim)
        self.fom.make_forward_sim(self.sim)
        self.sim.run(name='modematch_backward_injection_in_2D', iter=4)
        FOM = self.fom.get_fom(self.sim)
        self.assertAlmostEqual(FOM, self.ref_fom, 4)
Exemplo n.º 21
0
# discretization of the edges forming the optimizable polygon. It should be set such there are at least a few points
# per mesh cell. An effective index of 2.8 is user to simulate a 2D slab of 220 nm thickness.
geometry = FunctionDefinedPolygon(func=taper_splitter,
                                  initial_params=inital_params,
                                  bounds=bounds,
                                  z=0.0,
                                  depth=220e-9,
                                  eps_out=1.44**2,
                                  eps_in=2.8**2,
                                  edge_precision=5,
                                  dx=0.01e-9)

######## DEFINE FIGURE OF MERIT ########
# The base simulation script defines a field monitor named 'fom' at the point where we want to modematch to the 3rd mode (fundamental TE mode).
fom = ModeMatch(monitor_name='fom',
                wavelengths=1550e-9,
                mode_number=2,
                direction='Forward')

######## DEFINE OPTIMIZATION ALGORITHM ########
# This will run Scipy's implementation of the L-BFGS-B algoithm for at least 40 iterations. Since the variables are on the
# order of 1e-6, thery are scale up to be on the order of 1.
optimizer = ScipyOptimizers(max_iter=500,
                            method='L-BFGS-B',
                            scaling_factor=1e6)

######## PUT EVERYTHING TOGETHER ########
opt = Optimization(base_script=base_script,
                   fom=fom,
                   geometry=geometry,
                   optimizer=optimizer)
Exemplo n.º 22
0
                                      eps_in=2.8**2,
                                      bounds=bounds,
                                      depth=220e-9,
                                      edge_precision=5)
geometry_2 = function_defined_Polygon(func=taper_splitter_2,
                                      initial_params=initial_params,
                                      eps_out=1.44**2,
                                      eps_in=2.8**2,
                                      bounds=bounds,
                                      depth=220e-9,
                                      edge_precision=5)

######## DEFINE FIGURE OF MERIT ########
# Although we are optimizing for the same thing, two separate fom objects must be create

fom_1 = ModeMatch(modeorder=3)
fom_2 = ModeMatch(modeorder=3)

######## DEFINE OPTIMIZATION ALGORITHM ########
#For the optimizer, they should all be set the same, but different objects. Eventually this will be improved
optimizer_1 = ScipyOptimizers(max_iter=40)
optimizer_2 = ScipyOptimizers(max_iter=40)

######## PUT EVERYTHING TOGETHER ########
opt_1 = Optimization(base_script=script_1,
                     fom=fom_1,
                     geometry=geometry_1,
                     optimizer=optimizer_1)
opt_2 = Optimization(base_script=script_2,
                     fom=fom_2,
                     geometry=geometry_2,
Exemplo n.º 23
0
    interpolator = sp.interpolate.interp1d(points_x, points_y, kind='cubic')
    polygon_points_y = [max(min(point,1e-6),-1e-6) for point in interpolator(polygon_points_x)]

    polygon_points_up = [(x, y) for x, y in zip(polygon_points_x, polygon_points_y)]
    polygon_points_down = [(x, -y) for x, y in zip(polygon_points_x, polygon_points_y)]
    polygon_points = np.array(polygon_points_up[::-1] + polygon_points_down)
    return polygon_points

bounds = [(0.2e-6, 1e-6)]*10
# final value from splitter_opt_2D.py optimization
initial_params = np.array([2.44788514e-07, 2.65915795e-07, 2.68748023e-07, 4.42233947e-07, 6.61232152e-07, 6.47561406e-07, 6.91473099e-07, 6.17511522e-07, 6.70669074e-07, 5.86141086e-07])
geometry_1 = FunctionDefinedPolygon(func = taper_splitter_1, initial_params = initial_params, bounds = bounds, z = 0.0, depth = 220e-9, eps_out = 1.44 ** 2, eps_in = 2.8 ** 2, edge_precision = 5, dx = 0.1e-9)
geometry_2 = FunctionDefinedPolygon(func = taper_splitter_2, initial_params = initial_params, bounds = bounds, z = 0.0, depth = 220e-9, eps_out = 1.44 ** 2, eps_in = 2.8 ** 2, edge_precision = 5, dx = 0.1e-9)

######## DEFINE FIGURE OF MERIT ########
# Although we are optimizing for the same thing, two separate fom objects must be create
fom_1 = ModeMatch(monitor_name = 'fom', mode_number = 3, direction = 'Forward')
fom_2 = ModeMatch(monitor_name = 'fom', mode_number = 3, direction = 'Forward')

######## DEFINE OPTIMIZATION ALGORITHM ########
#For the optimizer, they should all be set the same, but different objects. Eventually this will be improved
optimizer_1 = ScipyOptimizers(max_iter = 40)
optimizer_2 = ScipyOptimizers(max_iter = 40)

######## PUT EVERYTHING TOGETHER ########
opt_1 = Optimization(base_script = script_1, wavelengths = wavelengths, fom = fom_1, geometry = geometry_1, optimizer = optimizer_1)
opt_2 = Optimization(base_script = script_2, wavelengths = wavelengths, fom = fom_2, geometry = geometry_2, optimizer = optimizer_2)
opt = opt_1 + opt_2

######## RUN THE OPTIMIZER ########
opt.run()
Exemplo n.º 24
0
    # mpl.use('TkAgg')
    import numpy as np
    # from lumopt.figures_of_merit.modematch_importsource import ModeMatch
    from lumopt.figures_of_merit.modematch import ModeMatch
    from lumopt.optimization import Optimization
    from lumopt.optimizers.generic_optimizers import ScipyOptimizers, FixedStepGradientDescent
    from lumopt.utilities.load_lumerical_scripts import load_from_lsf
    import os
    from lumopt.geometries.polygon import function_defined_Polygon
    from lumopt.utilities.materials import Material
    from lumopt import CONFIG
    import scipy

    script = load_from_lsf(os.path.join(CONFIG['root'], 'examples/staight_waveguide/straight_waveguide.lsf'))

    fom = ModeMatch(modeorder=2, precision=50)
    optimizer = ScipyOptimizers(max_iter=20)
    nx=401
    ny=101
    eps = np.ones((nx, ny))*1.44 ** 2
    eps[90, 10] = 10
    geometry = ContinousEpsilon2D(eps=eps, x=np.linspace(-1e-6, 1e-6, nx), y=np.linspace(-0.4e-6, 0.4e-6, ny))
    # function_defined_Polygon(func=waveguide, initial_params=np.linspace(0.25e-6, 0.25e-6, 10),
    #                                     eps_out=Material(1.44 ** 2), eps_in=Material(2.8 ** 2, 2), bounds=bounds,
    #                                     depth=220e-9,
    #                                     edge_precision=5)

    # geometry=Polygon(eps_in=2.8**2,eps_out=1.44**2)
    opt = Optimization(base_script=script, fom=fom, geometry=geometry, optimizer=optimizer)
    # opt.run()
    ##
## Study settings
# Select study type
parSet.study.type = 'LumericalFDTD'
# Name study parameters (useful expecially when exporting data)
parSet.study.parameters_name = ['L1', 'L2', 'L3', 'L4', 'L5']
# Base file to setup initial simulation environment (lsf, fsp or python function)
parSet.study.simulation_builder = 'GratingCoupler_base_setup.fsp'
# Function to build the geometry for optimization
parSet.study.geometry_function = grating_geometry
# A name to identify the simulation results (fom can change later on)
parSet.study.fom_name = 'mode_match'
# Fom function
parSet.study.fom_function = ModeMatch(
    monitor_name='fiber_monitor',
    mode_number=1,
    direction='Forward',
    multi_freq_src=False,
    target_T_fwd=lambda wl: 1 * np.ones(wl.size),
    norm_p=1)
# Hide GUI during simulation
parSet.study.hide_gui = False
# Close simulation interface after each random restart
parSet.study.simulator_restart = False

## Sampler settings
parSet.sampler.type = 'random-lumopt'
# Parameters bounds during global search
parSet.sampler.global_parameters_bounds = param_bounds = [(0.04, 0.4)] * 5
# Function to filter simulation results in global search before starting lumopt
parSet.sampler.global_result_constraint = lambda res: res > 0.1
# Function to filter simulation results after a lumopt run
Exemplo n.º 26
0
if __name__ == '__main__':
    import numpy as np
    from lumopt.geometries.polygon import function_defined_Polygon, cross
    from lumopt.optimizers.generic_optimizers import ScipyOptimizers
    from lumopt.figures_of_merit.modematch import ModeMatch
    from lumopt.utilities.load_lumerical_scripts import load_from_lsf
    import os
    import matplotlib.pyplot as plt
    from lumopt import CONFIG

    base_script = load_from_lsf(
        os.path.join(CONFIG['root'],
                     'examples/crossing/crossing_base_TE_modematch_2D.lsf'))

    fom = ModeMatch(modeorder=2)
    optimizer = ScipyOptimizers(max_iter=20)
    # optimizer=FixedStepGradientDescent(max_dx=20e-9,max_iter=100)
    bounds = [(0.2e-6, 1e-6)] * 10
    geometry = function_defined_Polygon(func=cross,
                                        initial_params=np.linspace(
                                            0.25e-6, 0.6e-6, 10),
                                        eps_out='SiO2 (Glass) - Palik',
                                        eps_in=2.8**2,
                                        bounds=bounds,
                                        depth=220e-9,
                                        edge_precision=5)

    opt = Optimization(base_script=base_script,
                       fom=fom,
                       geometry=geometry,
Exemplo n.º 27
0
def runGratingOptimization(bandwidth_in_nm, etch_depth, n_grates, params):

    bounds = [(0.1, 1)] * 4
    bounds[0] = (-3, 3)  #< Starting position
    bounds[1] = (0, 0.1)  #< Scaling parameter R
    bounds[2] = (1.5, 3)  #< Parameter a
    bounds[3] = (0, 2)  #< Parameter b

    def grating_params_pos(params,
                           output_waveguide_length=0.5e-6,
                           height=220e-9,
                           y0=0):
        x_begin = -3e-6
        y3 = y0 + height
        y1 = y3 - etch_depth

        x_start = params[0] * 1e-6  #< First parameter is the starting position
        x0 = x_start
        R = params[1] * 1e6  #< second parameter (unit is 1/um)
        a = params[2]  #< Third parameter (dim-less)
        b = params[3]  #< Fourth parameter (dim-less)

        verts = np.array([[x_begin, y0], [x_begin, y3], [x0, y3], [x0, y1]])

        lambda_c = 1.55e-6
        F0 = 0.95

        ## Iterate over all but the last
        for i in range(n_grates - 1):
            F = F0 - R * (x0 - x_start)
            Lambda = lambda_c / (a + F * b)
            x1 = x0 + (1 - F) * Lambda  #< Width of the etched region
            x2 = x0 + Lambda  #< Rest of cell
            verts = np.concatenate(
                (verts, [[x1, y1], [x1, y3], [x2, y3], [x2, y1]]), axis=0)
            x0 = x2

        F = F0 - R * (x0 - x_start)
        Lambda = lambda_c / (a + F * b)
        x1 = x0 + (1 - F) * Lambda  #< Width of the etched region
        x_end = x1 + output_waveguide_length
        verts = np.concatenate(
            (verts, [[x1, y1], [x1, y3], [x_end, y3], [x_end, y0]]), axis=0)

        return verts

    geometry = FunctionDefinedPolygon(func=grating_params_pos,
                                      initial_params=params,
                                      bounds=bounds,
                                      z=0.0,
                                      depth=110e-9,
                                      eps_out=1.44**2,
                                      eps_in=3.47668**2,
                                      edge_precision=5,
                                      dx=1e-3)

    ######## DEFINE FIGURE OF MERIT ########
    fom = ModeMatch(monitor_name='fom',
                    mode_number=1,
                    direction='Backward',
                    target_T_fwd=lambda wl: np.ones(wl.size),
                    norm_p=1)

    ######## DEFINE OPTIMIZATION ALGORITHM ########
    optimizer = ScipyOptimizers(max_iter=25,
                                method='L-BFGS-B',
                                scaling_factor=1,
                                pgtol=1e-6)

    ######## DEFINE BASE SIMULATION ########
    base_script = load_from_lsf(
        os.path.join(os.path.dirname(__file__),
                     'grating_coupler_2D_2etch.lsf'))

    ######## PUT EVERYTHING TOGETHER ########
    lambda_start = 1550 - bandwidth_in_nm / 2
    lambda_end = 1550 + bandwidth_in_nm / 2
    lambda_pts = int(bandwidth_in_nm / 10) + 1
    wavelengths = Wavelengths(start=lambda_start * 1e-9,
                              stop=lambda_end * 1e-9,
                              points=lambda_pts)
    opt = Optimization(base_script=base_script,
                       wavelengths=wavelengths,
                       fom=fom,
                       geometry=geometry,
                       optimizer=optimizer,
                       hide_fdtd_cad=True,
                       use_deps=True)

    ######## RUN THE OPTIMIZER ########
    opt.run()
Exemplo n.º 28
0
bounds = [(0.1, 0.9)] * (2 * n_grates)

geometry = FunctionDefinedPolygon(func=grate_function,
                                  initial_params=initial_params,
                                  bounds=bounds,
                                  z=0.0,
                                  depth=wg_height,
                                  eps_out=1.0**2,
                                  eps_in=3.47668**2,
                                  edge_precision=5,
                                  dx=1.0e-5)

######## DEFINE FIGURE OF MERIT ########
fom = ModeMatch(monitor_name='fom',
                mode_number=3,
                direction='Backward',
                target_T_fwd=lambda wl: 0.5 * np.ones(wl.size),
                norm_p=1)

######## DEFINE OPTIMIZATION ALGORITHM ########
optimizer = ScipyOptimizers(max_iter=200,
                            method='L-BFGS-B',
                            scaling_factor=1.0,
                            pgtol=1.0e-4)

######## PUT EVERYTHING TOGETHER ########
opt = Optimization(base_script=base_sim,
                   wavelengths=wavelengths,
                   fom=fom,
                   geometry=geometry,
                   optimizer=optimizer,
Exemplo n.º 29
0
# it must be defined. Since this is a 2D simulation, the depth has no importance. The edge precision defines the
# discretization of the edges forming the optimizable polygon. It should be set such that there are at least a
# few points per mesh cell. An effective index of 2.8 is user to simulate a 2D slab of 220 nm thickness.
geometry = FunctionDefinedPolygon(func=taper_splitter,
                                  initial_params=initial_params,
                                  bounds=bounds,
                                  z=0.0,
                                  depth=220e-9,
                                  eps_out=1.44**2,
                                  eps_in=silicon,
                                  edge_precision=5,
                                  dx=0.1e-9)

######## DEFINE FIGURE OF MERIT ########
# The base simulation script defines a field monitor named 'fom' at the point where we want to ematch to the 3rd mode (fundamental TE mode).
fom = ModeMatch(monitor_name='fom', mode_number=1, direction='Forward')

######## DEFINE OPTIMIZATION ALGORITHM ########
# This will run Scipy's implementation of the L-BFGS-B algoithm for at least 40 iterations. Since the variables are on the
# order of 1e-6, we scale them up to be on the order of 1
optimizer = ScipyOptimizers(max_iter=20, method='L-BFGS-B', scaling_factor=1e6)

######## PUT EVERYTHING TOGETHER ########
opt = Optimization(base_script=script,
                   wavelengths=wavelengths,
                   fom=fom,
                   geometry=geometry,
                   optimizer=optimizer)

######## RUN THE OPTIMIZER ########
opt.run()