def test_co_optimization_in_2D(self): print("2D TE-TM co-optimization (use_deps = True): ") #base_script, wavelengths, fom, geometry, optimizer, use_var_fdtd = False, hide_fdtd_cad = False, use_deps = True, plot_history = True, store_all_simulations = True optTE = Optimization(base_script=self.base_TE_sim, wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, use_var_fdtd=False, hide_fdtd_cad=True, use_deps=True, plot_history=False, store_all_simulations=False) optTM = Optimization(base_script=self.base_TM_sim, wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, use_var_fdtd=False, hide_fdtd_cad=True, use_deps=True, plot_history=False, store_all_simulations=False) opt = optTE + optTM fom, params = opt.run() self.assertGreaterEqual(fom, 1.99990) reference_value = self.wg_width / 2.0 * self.optimizer.scaling_factor[0] self.assertAlmostEqual(params[0], reference_value) self.assertAlmostEqual(params[1], reference_value)
def test_shape_boundary_approximation_in_3D(self): print( "3D optimization with shape boundary approximation (use_deps = False): " ) self.geometry.bounds = [(0.0, self.wg_width / 2.0 - self.mesh_del) ] * len(self.geometry.bounds) # Note: bounds are tweaked since the shape boundary approximation method does not work # when the shape under optimization touches the boundary of the FDTD region. opt = Optimization(base_script=self.base_script + "setnamed('FDTD','dimension','3D');", wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, hide_fdtd_cad=True, use_deps=False, plot_history=False, store_all_simulations=False) fom, params = opt.run() self.assertGreaterEqual(fom, 0.972) self.assertAlmostEqual(params[0], (self.wg_width / 2.0 - self.mesh_del) * self.optimizer.scaling_factor) self.assertAlmostEqual(params[1], (self.wg_width / 2.0 - self.mesh_del) * self.optimizer.scaling_factor)
def test_shape_boundary_approximation(self): print( "varFDTD optimization with shape boundary approximation (use_deps = False): " ) self.geometry.bounds = [ (self.mesh_del, self.wg_width / 2.0 - self.mesh_del) ] * len(self.geometry.bounds) opt = Optimization(base_script=self.base_script, wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, use_var_fdtd=True, hide_fdtd_cad=True, use_deps=False, plot_history=False, store_all_simulations=False) fom, params = opt.run() self.assertGreaterEqual(fom, 0.972) self.assertAlmostEqual(params[0], (self.wg_width / 2.0 - self.mesh_del) * self.optimizer.scaling_factor) self.assertAlmostEqual(params[1], (self.wg_width / 2.0 - self.mesh_del) * self.optimizer.scaling_factor)
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()
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 = 3) # simulation self.sim = Simulation(workingDir = self.file_dir, hide_fdtd_cad = True) self.sim.fdtd.eval(self.base_script) Optimization.set_global_wavelength(self.sim, self.wavelengths) # reference self.ref_fom = 0.6643986
def test_broadband(self): print("Broadband optimization results:") opt = Optimization(base_script = self.base_script, wavelengths = self.wavelengths, fom = self.fom, geometry = self.geometry, optimizer = self.optimizer, hide_fdtd_cad = True, use_deps = True) fom, params = opt.run() self.assertAlmostEqual(params[0], 2.050400e-7 * self.optimizer.scaling_factor, 5) self.assertGreaterEqual(fom, 0.4618)
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)
def test_broadband_optimization(self): print("Broadband optimization results (use_deps = True):") opt = Optimization(base_script=self.base_script, wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, use_var_fdtd=False, hide_fdtd_cad=True, use_deps=True, plot_history=False, store_all_simulations=False) fom, params = opt.run() self.assertAlmostEqual(params[0], 2.050375e-7 * self.optimizer.scaling_factor[0], 4) self.assertGreaterEqual(fom, 0.461815)
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_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_single_frequency(self): print("Single frequency optimization results:") self.fom.target_T_fwd = lambda wl: np.ones(wl.size) self.fom.multi_freq_src = False self.wavelengths = 1550.0e-9 self.optimizer.scaling_factor = 2.0e7 self.optimizer.pgtol = 3.1e-2 opt = Optimization(base_script = self.base_script, wavelengths = self.wavelengths, fom = self.fom, geometry = self.geometry, optimizer = self.optimizer, hide_fdtd_cad = True, use_deps = True) fom, params = opt.run() self.assertAlmostEqual(params[0], 2.058006e-7 * self.optimizer.scaling_factor, 5) self.assertGreaterEqual(fom, 0.9192)
def test_permittivity_derivatives_in_2D(self): print( "2D optimization with permittivity derivatives (use_deps = True): " ) opt = Optimization(base_script=self.base_script + "setnamed('FDTD','dimension','2D');", wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, hide_fdtd_cad=True, use_deps=True) fom, params = opt.run() self.assertGreaterEqual(fom, 0.99991) self.assertAlmostEqual( params[0], self.wg_width / 2.0 * self.optimizer.scaling_factor) self.assertAlmostEqual( params[1], self.wg_width / 2.0 * self.optimizer.scaling_factor)
def test_permittivity_derivatives(self): print( "varFDTD optimization with permittivity derivatives (use_deps = True): " ) opt = Optimization(base_script=self.base_script, wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, use_var_fdtd=True, hide_fdtd_cad=True, use_deps=True, plot_history=False, store_all_simulations=False) fom, params = opt.run() self.assertGreaterEqual(fom, 0.99991) self.assertAlmostEqual( params[0], self.wg_width / 2.0 * self.optimizer.scaling_factor) self.assertAlmostEqual( params[1], self.wg_width / 2.0 * self.optimizer.scaling_factor)
def test_single_wavelength_legacy_optimization(self): print("Single wavelength optimization results (use_deps = False):") self.fom.target_T_fwd = lambda wl: np.ones(wl.size) self.fom.multi_freq_src = False self.wavelengths = 1550.0e-9 self.optimizer.scaling_factor = np.array(2.0e7) self.optimizer.pgtol = 3.1e-2 opt = Optimization(base_script=self.base_script, wavelengths=self.wavelengths, fom=self.fom, geometry=self.geometry, optimizer=self.optimizer, use_var_fdtd=False, hide_fdtd_cad=True, use_deps=False, plot_history=False, store_all_simulations=False) fom, params = opt.run() self.assertAlmostEqual(params[0], 2.05609116e-7 * self.optimizer.scaling_factor, 4) self.assertGreaterEqual(fom, 0.91905)
def __init__(self, max_iter, method, scaling_factor, pgtol, ftol, wavelength_start, wavelength_stop, wavelength_points, build_simulation, fom, geometry, hide_fdtd_cad): # The optimizer must be generated anew at each iteration self._new_local_optimizer = ScipyOptimizers( max_iter=max_iter, method=method, scaling_factor=scaling_factor, ftol=ftol, pgtol=pgtol) self._wl = Wavelengths(start=wavelength_start, stop=wavelength_stop, points=wavelength_points) self._optimization = Optimization(base_script=build_simulation, wavelengths=self._wl, fom=fom, geometry=geometry, optimizer=self._new_local_optimizer, hide_fdtd_cad=hide_fdtd_cad, use_deps=True)
######## 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, method='L-BFGS-B', scaling_factor=1e6, pgtol=1e-9) optimizer_2 = ScipyOptimizers(max_iter=40, method='L-BFGS-B', scaling_factor=1e6, pgtol=1e-9) ######## PUT EVERYTHING TOGETHER ######## opt_1 = Optimization(base_script=script_1, wavelengths=wavelengths, fom=fom_1, geometry=geometry_1, optimizer=optimizer_1, hide_fdtd_cad=False, use_deps=True) opt_2 = Optimization(base_script=script_2, wavelengths=wavelengths, fom=fom_2, geometry=geometry_2, optimizer=optimizer_2, hide_fdtd_cad=False, use_deps=True) opt = opt_1 + opt_2 ######## RUN THE OPTIMIZER ######## opt.run()
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, optimizer=optimizer_2) opt = opt_1 + opt_2 ######## RUN THE OPTIMIZER ######## opt.run()
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()
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() ## opt.initialize() eps,x,y,z=opt.geometry.get_eps() x_geo=opt.geometry.x y_geo=opt.geometry.y print 'ha'
######## 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, method='L-BFGS-B', scaling_factor=1e6, pgtol=1e-9) optimizer_1310 = ScipyOptimizers(max_iter=40, method='L-BFGS-B', scaling_factor=1e6, pgtol=1e-9) ######## PUT EVERYTHING TOGETHER ######## opt_1550 = Optimization(base_script=script_1550, wavelengths=wavelengths_1551, fom=fom_1550, geometry=geometry_1550, optimizer=optimizer_1550, hide_fdtd_cad=False, use_deps=True) opt_1310 = Optimization(base_script=script_1310, wavelengths=wavelengths_1310, fom=fom_1310, geometry=geometry_1310, optimizer=optimizer_1310, hide_fdtd_cad=False, use_deps=True) opt = opt_1550 + opt_1310 ######## RUN THE OPTIMIZER ######## opt.run()
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 ######## opt.run()
depth=220.0e-9, eps_out=1.44**2, eps_in=2.8**2, edge_precision=5, dx=0.1e-9) ######## DEFINE FIGURE OF MERIT ######## mode_fom = ModeMatch(monitor_name='fom', mode_number=2, direction='Forward', target_T_fwd=lambda wl: np.ones(wl.size), norm_p=1) ######## DEFINE OPTIMIZATION ALGORITHM ######## scipy_optimizer = ScipyOptimizers(max_iter=20, method='L-BFGS-B', scaling_factor=1e6, pgtol=1e-9) ######## PUT EVERYTHING TOGETHER ######## opt = Optimization(base_script=crossing_base, wavelengths=wavelengths, fom=mode_fom, geometry=polygon_geometry, optimizer=scipy_optimizer, hide_fdtd_cad=False, use_deps=True) ######## RUN THE OPTIMIZER ######## opt.run()
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.1e-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=3, 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=30, method='L-BFGS-B', scaling_factor=1e6, pgtol=1e-9) ######## PUT EVERYTHING TOGETHER ######## opt = Optimization(base_script=base_script, wavelengths=wavelengths, fom=fom, geometry=geometry, optimizer=optimizer) ######## RUN THE OPTIMIZER ######## opt.run()
#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()
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()
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()
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, hide_fdtd_cad=False, use_deps=True) ######## RUN THE OPTIMIZER ######## opt.run()
class LumericalInverseDesign: """ Wrapper for Lumerical lumopt (part of it) Parameters ---------- max_iter: int method: string scaling_factor: float pgtol: float ftol: float wavelength_start: float wavelength_stop: float wavelength_points: float build_simulation: string fom: obj geometry: obj hide_fdtd_cad: bool """ def __init__(self, max_iter, method, scaling_factor, pgtol, ftol, wavelength_start, wavelength_stop, wavelength_points, build_simulation, fom, geometry, hide_fdtd_cad): # The optimizer must be generated anew at each iteration self._new_local_optimizer = ScipyOptimizers( max_iter=max_iter, method=method, scaling_factor=scaling_factor, ftol=ftol, pgtol=pgtol) self._wl = Wavelengths(start=wavelength_start, stop=wavelength_stop, points=wavelength_points) self._optimization = Optimization(base_script=build_simulation, wavelengths=self._wl, fom=fom, geometry=geometry, optimizer=self._new_local_optimizer, hide_fdtd_cad=hide_fdtd_cad, use_deps=True) def run(self): """ Run the lumopt optimization Returns ------- res: array The figure of merit of the optimized device param: numpy array The optimized parameters """ results = self._optimization.run() self._optimization.sim.fdtd.close() # plot optimization recap figure plt.show() return [results[0], np.array(results[1])] def _cleanup(self): ''' Remove all the folders generated by lumopt ''' # folder for the file local_folder = os.path.realpath( os.path.join(os.getcwd(), os.path.dirname(__file__))) subdir_list = os.listdir(local_folder) for folder in subdir_list: if folder.startswith('opts_') or (folder.startswith('optimization') and folder.endswith('.png')): shutil.rmtree(local_folder + '\\' + folder, ignore_errors=True) def __del__(self): # Remove objects to delete pointers or pickle could have problems del self._optimization del self._wl del self._new_local_optimizer self._cleanup()