def test_render_pixelated_cont_shape(): with goos.OptimizationPlan() as plan: def initializer(size): return [[1, 0], [0.5, 0.75], [0, 0.8], [1, 0.8]] var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([200, 0, 0]), extents=[1000, 1000, 220], material=goos.material.Material(index=2), material2=goos.material.Material(index=4), pixel_size=[250, 500, 220]) rect = goos.Cuboid(extents=goos.Constant([1000, 1000, 220]), pos=goos.Constant([200, 0, 0]), material=goos.material.Material(index=2)) render = maxwell.RenderShape( design, region=goos.Box3d(center=[0, 0, 0], extents=[1500, 1500, 200]), mesh=maxwell.UniformMesh(dx=40), background=goos.material.Material(index=1.0), wavelength=1550) np.testing.assert_almost_equal( np.real(render.get().array[2][10:, 8, 3]), [ 1., 8.5, 16., 16., 16., 16., 16., 14.5, 10., 10., 10., 10., 10., 10., 4., 4., 4., 4., 4., 4., 13., 16., 16., 16., 16., 16., 8.5 ])
def test_render_pixelated_cont_shape_grad(): with goos.OptimizationPlan() as plan: def initializer(size): return [[1, 0], [0.5, 0.75], [0, 0.8], [1, 0.8]] var, design = goos.pixelated_cont_shape( initializer=initializer, pos=[200, 0, 0], extents=[1000, 1000, 220], material=goos.material.Material(index=2), material2=goos.material.Material(index=4), pixel_size=[250, 500, 220]) render = maxwell.RenderShape( design, region=goos.Box3d(center=[0, 0, 0], extents=[1500, 1500, 200]), mesh=maxwell.UniformMesh(dx=40), background=goos.material.Material(index=1.0), wavelength=1550) # Compute a random objective function to test gradient. np.random.seed(247) obj = goos.dot(np.random.random(render.get().array.shape), render) adjoint_grad = obj.get_grad([var])[0].array_grad # Calculate brute force gradient. var_val = var.get().array eps = 0.001 num_grad = np.zeros_like(var_val) for i in range(var_val.shape[0]): for j in range(var_val.shape[1]): temp_val = var_val.copy() temp_val[i, j] += eps var.set(temp_val) fplus = obj.get(run=True).array temp_val = var_val.copy() temp_val[i, j] -= eps var.set(temp_val) fminus = obj.get(run=True).array num_grad[i, j] = (fplus - fminus) / (2 * eps) np.testing.assert_array_almost_equal(adjoint_grad, num_grad)
def main(save_folder: str, visualize: bool = False) -> None: goos.util.setup_logging(save_folder) params = Options() with goos.OptimizationPlan(save_path=save_folder) as plan: substrate = goos.Cuboid( pos=goos.Constant([ params.coupler_len / 2, 0, -params.box_size - params.wg_thickness / 2 - 5000 ]), extents=goos.Constant([params.coupler_len + 10000, 1000, 10000]), material=goos.material.Material(index=params.eps_wg)) waveguide = goos.Cuboid( pos=goos.Constant([-params.wg_len / 2, 0, 0]), extents=goos.Constant( [params.wg_len, params.wg_width, params.wg_thickness]), material=goos.material.Material(index=params.eps_wg)) wg_bottom = goos.Cuboid( pos=goos.Constant([ params.coupler_len / 2, 0, -params.wg_thickness / 2 * params.etch_frac ]), extents=goos.Constant([ params.coupler_len, params.wg_width, params.wg_thickness * (1 - params.etch_frac) ]), material=goos.material.Material(index=params.eps_wg)) def initializer(size): return np.random.random(size) # Continuous optimization. var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([ params.coupler_len / 2, 0, params.wg_thickness / 2 * (1 - params.etch_frac) ]), extents=[ params.coupler_len, params.wg_width, params.wg_thickness * params.etch_frac ], material=goos.material.Material(index=params.eps_bg), material2=goos.material.Material(index=params.eps_wg), pixel_size=[ params.pixel_size, params.wg_width, params.wg_thickness ]) obj, sim = make_objective( goos.GroupShape([substrate, waveguide, wg_bottom, design]), "cont", params) goos.opt.scipy_minimize( obj, "L-BFGS-B", monitor_list=[sim["eps"], sim["field"], sim["overlap"], obj], max_iters=60, name="opt_cont") # Prevent optimization from optimizing over continuous variable. var.freeze() # Run discretization. grating_var, height_var, design_disc = goos.grating.discretize_to_pixelated_grating( var, height_fracs=[0, 1], pixel_size=params.pixel_size, start_height_ind=1, end_height_ind=1, min_features=params.min_features, pos=[ params.coupler_len / 2, 0, params.wg_thickness / 2 * (1 - params.etch_frac) ], extents=[ params.coupler_len, params.wg_width, params.wg_thickness * params.etch_frac ], material=goos.material.Material(index=params.eps_bg), material2=goos.material.Material(index=params.eps_wg), grating_dir=0, grating_dir_spacing=20, etch_dir=2, etch_dir_divs=1) obj, sim = make_objective( goos.GroupShape([substrate, waveguide, wg_bottom, design_disc]), "disc", params) goos.opt.scipy_minimize( obj, "L-BFGS-B", monitor_list=[sim["eps"], sim["field"], sim["overlap"], obj], max_iters=100, name="opt_disc", ftol=1e-8) plan.save() plan.run() if visualize: goos.util.visualize_eps(sim["eps"].get().array[2])
with plan: # Use random initialization, where each pixel is randomly assigned # a value in the range [0.3,0.7]. def initializer(size): # Set the seed immediately before calling `random` to ensure # reproducibility. np.random.seed(247) return np.random.random(size) * 0.2 + 0.5 # Define the design region as a pixelated continuous shape, which is composed # of voxels whose permittivities can take on any value between `material` and # `material2`. var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[2000, 2000, 220], material=goos.material.Material(index=1), material2=goos.material.Material(index=1), pixel_size=[40, 40, 220], var_name="var_cont") eps = goos.GroupShape([ design, ]) """ Visualize the design region as a sanity check. """ with plan: eps_rendered = maxwell.RenderShape( eps, region=goos.Box3d(center=[0, 0, 0], extents=[3000, 3000, 0]), mesh=maxwell.UniformMesh(dx=40),
def test_simulate_wg_opt(): with goos.OptimizationPlan() as plan: wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]), extents=goos.Constant([3000, 800, 40]), material=goos.material.Material(index=3.45)) wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]), extents=goos.Constant([3000, 800, 40]), material=goos.material.Material(index=3.45)) def initializer(size): # Set the seed immediately before calling `random` to ensure # reproducibility. np.random.seed(247) return np.random.random(size) * 0.1 + np.ones(size) * 0.7 var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[1000, 800, 40], pixel_size=[40, 40, 40], material=goos.material.Material(index=1), material2=goos.material.Material(index=3.45), ) eps = goos.GroupShape([wg_in, wg_out, design]) sim = meep.FdtdSimulation( eps=eps, sources=[ meep.WaveguideModeSource( center=[-1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=2, power=1, wavelength=1550, bandwidth=100, ) ], sim_space=meep.SimulationSpace( dx=40, sim_region=goos.Box3d( center=[0, 0, 0], extents=[4000, 4000, 0], ), pml_thickness=[400, 400, 400, 400, 0, 0]), sim_timing=meep.SimulationTiming(stopping_conditions=[ meep.StopWhenFieldsDecayed( time_increment=50, component=2, pos=[0, 0, 0], threshold=1e-6, ) ], ), background=goos.material.Material(index=1.0), outputs=[ meep.Epsilon(wavelength=1550), meep.ElectricField(wavelength=1550), meep.WaveguideModeOverlap(wavelength=1550, center=[1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=0, power=1), ]) obj = -goos.abs(sim[2]) import meep as mp mp.quiet() goos.opt.scipy_minimize(obj, "L-BFGS-B", monitor_list=[obj], max_iters=5) plan.run() # Check that we can optimize. We choose something over 60% as # incorrect gradients will typically not reach this point. assert obj.get().array < -0.85 # As a final check, compare simulation results against Maxwell. # Note that dx = 40 for Meep is actually too innaccurate. We therefore # resimulate the final structure for both Meep and Maxwell. from spins.goos_sim import maxwell sim_fdfd = maxwell.fdfd_simulation( wavelength=1550, eps=eps, sources=[ maxwell.WaveguideModeSource( center=[-1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=2, power=1, ) ], simulation_space=maxwell.SimulationSpace( mesh=maxwell.UniformMesh(dx=20), sim_region=goos.Box3d( center=[0, 0, 0], extents=[4000, 4000, 0], ), pml_thickness=[400, 400, 400, 400, 0, 0]), background=goos.material.Material(index=1.0), outputs=[ maxwell.Epsilon(), maxwell.ElectricField(), maxwell.WaveguideModeOverlap(center=[1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=0, power=1), ], solver="local_direct") sim_fdtd_hi = meep.FdtdSimulation( eps=eps, sources=[ meep.WaveguideModeSource( center=[-1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=2, power=1, wavelength=1550, bandwidth=100, ) ], sim_space=meep.SimulationSpace( dx=20, sim_region=goos.Box3d( center=[0, 0, 0], extents=[4000, 4000, 0], ), pml_thickness=[400, 400, 400, 400, 0, 0]), sim_timing=meep.SimulationTiming(stopping_conditions=[ meep.StopWhenFieldsDecayed( time_increment=50, component=2, pos=[0, 0, 0], threshold=1e-6, ) ], ), background=goos.material.Material(index=1.0), outputs=[ meep.Epsilon(wavelength=1550), meep.ElectricField(wavelength=1550), meep.WaveguideModeOverlap(wavelength=1550, center=[1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=0, power=1), ]) fdtd_hi_power = goos.abs(sim_fdtd_hi[2])**2 fdfd_power = goos.abs(sim_fdfd[2])**2 # Check that power is correct within 0.5%. assert np.abs(fdfd_power.get().array - fdtd_hi_power.get().array) < 0.005
def main(save_folder: str, min_feature: float = 100, use_cubic: bool = True, visualize: bool = False) -> None: goos.util.setup_logging(save_folder) with goos.OptimizationPlan(save_path=save_folder) as plan: wg_1 = goos.Cuboid(pos=goos.Constant([1600, -4500, 0]), extents=goos.Constant([600, 1000, 230]), material=goos.material.Material(index=3.45)) wg_2 = goos.Cuboid(pos=goos.Constant([-1600, -4500, 0]), extents=goos.Constant([600, 1000, 230]), material=goos.material.Material(index=3.45)) wg_3 = goos.Cuboid(pos=goos.Constant([1600, 4500, 0]), extents=goos.Constant([600, 1000, 230]), material=goos.material.Material(index=3.45)) wg_4 = goos.Cuboid(pos=goos.Constant([-1600, 4500, 0]), extents=goos.Constant([600, 1000, 230]), material=goos.material.Material(index=3.45)) wg_5 = goos.Cuboid(pos=goos.Constant([4500, -1600, 0]), extents=goos.Constant([1000, 600, 230]), material=goos.material.Material(index=3.45)) wg_6 = goos.Cuboid(pos=goos.Constant([4500, 1600, 0]), extents=goos.Constant([1000, 600, 230]), material=goos.material.Material(index=3.45)) wg_7 = goos.Cuboid(pos=goos.Constant([-4500, 0, 0]), extents=goos.Constant([1000, 600, 230]), material=goos.material.Material(index=3.45)) substrate = goos.Cuboid(pos=goos.Constant([0, 0, -500]), extents=goos.Constant([11000, 11000, 770]), material=goos.material.Material(index=1.4)) def initializer(size): # Set the seed immediately before calling `random` to ensure # reproducibility. #np.random.seed(247) return np.ones(size) * 0.5 #return np.random.random(size) * 0.2 + 0.5 # Continuous optimization. var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[8000, 8000, 230], material=goos.material.Material(index=1), material2=goos.material.Material(index=3.45), pixel_size=[50, 50, 230], var_name="var_cont") sigmoid_factor = goos.Variable(4, parameter=True, name="discr_factor") design = goos.cast(goos.Sigmoid(sigmoid_factor * (2 * design - 1)), goos.Shape) eps = goos.GroupShape( [wg_1, wg_2, wg_3, wg_4, wg_5, wg_6, wg_7, design, substrate]) # This node is purely for debugging purposes. eps_rendered = maxwell.RenderShape( eps, region=goos.Box3d(center=[0, 0, 0], extents=[10000, 10000, 0]), mesh=maxwell.UniformMesh(dx=50), wavelength=635, ) if visualize: goos.util.visualize_eps(eps_rendered.get().array[2]) obj, sim1, sim2, sim3, sim4, sim5, sim6, sim7 = make_objective( eps, "cont") for factor in [4, 8, 12]: sigmoid_factor.set(factor) goos.opt.scipy_minimize( obj, "L-BFGS-B", monitor_list=[ sim1["eps"], sim1["field"], sim1["overlap1"], sim1["overlap2"], sim1["overlap3"], sim1["overlap4"], sim1["overlap5"], sim1["overlap6"], sim1["overlap7"], sim2["eps"], sim2["field"], sim2["overlap1"], sim2["overlap2"], sim2["overlap3"], sim2["overlap4"], sim2["overlap5"], sim2["overlap6"], sim2["overlap7"], sim3["eps"], sim3["field"], sim3["overlap1"], sim3["overlap2"], sim3["overlap3"], sim3["overlap4"], sim3["overlap5"], sim3["overlap6"], sim3["overlap7"], sim4["eps"], sim4["field"], sim4["overlap1"], sim4["overlap2"], sim4["overlap3"], sim4["overlap4"], sim4["overlap5"], sim4["overlap6"], sim4["overlap7"], sim5["eps"], sim5["field"], sim5["overlap1"], sim5["overlap2"], sim5["overlap3"], sim5["overlap4"], sim5["overlap5"], sim5["overlap6"], sim5["overlap7"], sim6["eps"], sim6["field"], sim6["overlap1"], sim6["overlap2"], sim6["overlap3"], sim6["overlap4"], sim6["overlap5"], sim6["overlap6"], sim6["overlap7"], sim7["eps"], sim7["field"], sim7["overlap1"], sim7["overlap2"], sim7["overlap3"], sim7["overlap4"], sim7["overlap5"], sim7["overlap6"], sim7["overlap7"], obj ], max_iters=25, name="opt_cont{}".format(factor)) plan.save() plan.run() if visualize: goos.util.visualize_eps(eps_rendered.get().array[2])
def test_simulate_wg_opt(): with goos.OptimizationPlan() as plan: wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]), extents=goos.Constant([3000, 800, 220]), material=goos.material.Material(index=3.45)) wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]), extents=goos.Constant([3000, 800, 220]), material=goos.material.Material(index=3.45)) def initializer(size): # Set the seed immediately before calling `random` to ensure # reproducibility. np.random.seed(247) return np.random.random(size) * 0.1 + np.ones(size) * 0.5 var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[1000, 800, 220], pixel_size=[40, 40, 40], material=goos.material.Material(index=1), material2=goos.material.Material(index=3.45), ) eps = goos.GroupShape([wg_in, wg_out, design]) sim = maxwell.fdfd_simulation( eps=eps, wavelength=1550, solver="local_direct", sources=[ maxwell.WaveguideModeSource( center=[-1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=2, power=1, ) ], simulation_space=maxwell.SimulationSpace( mesh=maxwell.UniformMesh(dx=40), sim_region=goos.Box3d( center=[0, 0, 0], extents=[4000, 4000, 40], ), pml_thickness=[400, 400, 400, 400, 0, 0]), background=goos.material.Material(index=1.0), outputs=[ maxwell.Epsilon(), maxwell.ElectricField(), maxwell.WaveguideModeOverlap(wavelength=1550, center=[1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=0, power=1), ]) obj = -goos.abs(sim[2]) goos.opt.scipy_minimize(obj, "L-BFGS-B", monitor_list=[obj], max_iters=15) plan.run() assert obj.get().array < -0.90
def test_simulate_wg_opt_grad(): with goos.OptimizationPlan() as plan: wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]), extents=goos.Constant([3000, 800, 220]), material=goos.material.Material(index=3.45)) wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]), extents=goos.Constant([3000, 800, 220]), material=goos.material.Material(index=3.45)) def initializer(size): # Set the seed immediately before calling `random` to ensure # reproducibility. np.random.seed(247) return np.random.random(size) var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[1000, 800, 220], pixel_size=[500, 400, 220], material=goos.material.Material(index=1), material2=goos.material.Material(index=3.45), ) eps = goos.GroupShape([wg_in, wg_out, design]) sim = maxwell.fdfd_simulation( eps=eps, wavelength=1550, solver="local_direct", sources=[ maxwell.WaveguideModeSource( center=[-1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=2, power=1, ) ], simulation_space=maxwell.SimulationSpace( mesh=maxwell.UniformMesh(dx=40), sim_region=goos.Box3d( center=[0, 0, 0], extents=[4000, 4000, 40], ), pml_thickness=[400, 400, 400, 400, 0, 0]), background=goos.material.Material(index=1.0), outputs=[ maxwell.Epsilon(), maxwell.ElectricField(), maxwell.WaveguideModeOverlap(wavelength=1550, center=[1000, 0, 0], extents=[0, 2500, 0], normal=[1, 0, 0], mode_num=0, power=1), ]) obj = -goos.abs(sim[2]) adjoint_grad = obj.get_grad([var])[0].array_grad # Calculate brute force gradient. var_val = var.get().array eps = 0.001 num_grad = np.zeros_like(var_val) for i in range(var_val.shape[0]): for j in range(var_val.shape[1]): temp_val = var_val.copy() temp_val[i, j] += eps var.set(temp_val) fplus = obj.get(run=True).array temp_val = var_val.copy() temp_val[i, j] -= eps var.set(temp_val) fminus = obj.get(run=True).array num_grad[i, j] = (fplus - fminus) / (2 * eps) np.testing.assert_array_almost_equal(adjoint_grad, num_grad, decimal=3)
def main(save_folder: str, min_feature: float = 100, use_cubic: bool = True, sim_3d: bool = False, visualize: bool = False) -> None: goos.util.setup_logging(save_folder) with goos.OptimizationPlan(save_path=save_folder) as plan: wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]), extents=goos.Constant([3000, 400, 220]), material=goos.material.Material(index=3.45)) wg_out = goos.Cuboid(pos=goos.Constant([0, 2000, 0]), extents=goos.Constant([400, 3000, 220]), material=goos.material.Material(index=3.45)) def initializer(size): # Set the seed immediately before calling `random` to ensure # reproducibility. np.random.seed(247) return np.random.random(size) * 0.2 + 0.5 # Continuous optimization. if use_cubic: var, design = goos.cubic_param_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[2000, 2000, 220], pixel_spacing=40, control_point_spacing=1.5 * min_feature, material=goos.material.Material(index=1), material2=goos.material.Material(index=3.45), var_name="var_cont") else: var, design = goos.pixelated_cont_shape( initializer=initializer, pos=goos.Constant([0, 0, 0]), extents=[2000, 2000, 220], material=goos.material.Material(index=1), material2=goos.material.Material(index=3.45), pixel_size=[40, 40, 220], var_name="var_cont") sigmoid_factor = goos.Variable(4, parameter=True, name="discr_factor") design = goos.cast(goos.Sigmoid(sigmoid_factor * (2 * design - 1)), goos.Shape) eps = goos.GroupShape([wg_in, wg_out, design]) # This node is purely for debugging purposes. eps_rendered = maxwell.RenderShape( design, region=goos.Box3d(center=[0, 0, 0], extents=[3000, 3000, 0]), mesh=maxwell.UniformMesh(dx=40), wavelength=1550, ) if visualize: goos.util.visualize_eps(eps_rendered.get().array[2]) obj, sim = make_objective(eps, "cont", sim_3d=sim_3d) for factor in [4, 6, 8]: sigmoid_factor.set(factor) goos.opt.scipy_minimize( obj, "L-BFGS-B", monitor_list=[sim["eps"], sim["field"], sim["overlap"], obj], max_iters=20, name="opt_cont{}".format(factor)) plan.save() plan.run() if visualize: goos.util.visualize_eps(eps_rendered.get().array[2])