Optical

Optical

Inverse design of polymer y-branch – modify the example provided

    • taige.li
      Subscriber

      Hi all,

      I tried to optimize a polymer y-branch according to the example here (https://optics.ansys.com/hc/en-us/articles/360042305274).

      Since polymer (SU-8) has a much lower refractive index, the main different is the size. I modified all sizes in the base setup .py file and the simulation .py file, yet error occured saying "The initial X is infeasible.  Restart with its projection." As a result, the polygon structure extends beyond the bounds defined, and FoM could not be calculated.

      Attached please find the screenshot and codes. Please help to check if I made anything wrong.

      Thank you very much!

      [File 1]

      #############################################################################

      # Scriptfile: y_branch_opt_2D.py

      #

      # Description:

      # This script sets up and runs the adjoint shape-based optimization for inverse

      # design of the SOI Y-branch in 2D

      #

      # Steps include:

      # 1. Define the base simulation

      # 2. Define the optimizable geometry and optimization parameters

      # 3. Run optimization

      # 4. Save results

      #

      # Copyright 2019, Lumerical Solutions, Inc.

      # Copyright chriskeraly

      ##############################################################################

       

      import os, sys

      import numpy as np

      import scipy as sp

      import lumapi

       

      from lumopt.utilities.wavelengths import Wavelengths

      from lumopt.geometries.polygon import FunctionDefinedPolygon

      from lumopt.utilities.materials import Material

      from lumopt.figures_of_merit.modematch import ModeMatch

      from lumopt.optimizers.generic_optimizers import ScipyOptimizers

      from lumopt.optimization import Optimization

       

      ######## BASE SIMULATION ########

      sys.path.append(os.path.dirname(__file__))

      from varFDTD_y_branch import y_branch_init_

      y_branch_base = y_branch_init_

       

      ######## DIRECTORY FOR GDS EXPORT #########

      example_directory = os.getcwd()

       

      ######## SPECTRAL RANGE #########

      wavelengths = Wavelengths(start = 1530e-9, stop = 1570e-9, points = 21)

       

      ######## DEFINE OPTIMIZABLE GEOMETRY ########

      # The class FunctionDefinedPolygon needs a parameterized Polygon (with points ordered

      # in a counter-clockwise direction). Here the geometry is defined by 10 parameters defining

      # the knots of a spline, and the resulting Polygon has 200 edges, making it quite smooth.

       

      # Define the span and number of points

      initial_points_x = np.linspace(-12.5e-6, 12.5e-6, 10)

      initial_points_y = np.linspace(5e-6, 5e-6, initial_points_x.size)

      def splitter(params):

      ''' Defines a taper where the paramaters are the y coordinates of the nodes of a cubic spline. '''

       

      ## Include two set points based on the initial guess. The should attach the optimizeable geometry to the input and output

      points_x = np.concatenate(([initial_points_x.min() - 0.01e-6], initial_points_x, [initial_points_x.max() + 0.01e-6]))

      points_y = np.concatenate(([initial_points_y.min()], params, [initial_points_y.max()]))

       

      ## Up sample the polygon points for a smoother curve. Some care should be taken with interp1d object. Higher degree fit

      # "cubic", and "quadratic" can vary outside of the footprint of the optimization. The parameters are bounded, but the

      # interpolation points are not. This can be particularly problematic around the set points.

      n_interpolation_points = 100

      polygon_points_x = np.linspace(min(points_x), max(points_x), n_interpolation_points)

      interpolator = sp.interpolate.interp1d(points_x, points_y, kind = 'cubic')

      polygon_points_y = interpolator(polygon_points_x)

      print(polygon_points_y)

       

      ### Zip coordinates into a list of tuples, reflect and reorder. Need to be passed ordered in a CCW sense

      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

       

      # L-BFGS methods allows the parameters to be bound. These should enforse the optimization footprint defined in the setup

      bounds = [(0.2e-6, 0.8e-6)] * initial_points_y.size

      print("Bounds:")

      print(bounds)

       

      #Load from 2D results if availble

      try:

      prev_results = np.loadtxt('2D_parameters.txt')

      except:

      print("Couldn't find the file containing 2D optimization parameters. Starting with default parameters")

      prev_results = initial_points_y

       

      # Set device and cladding materials, as well as as device layer thickness

      eps_in = Material(name = 'SU-8')

      eps_out = Material(name = 'air')

      depth = 2e-6

       

      # Initialize FunctionDefinedPolygon class

      polygon = FunctionDefinedPolygon(func = splitter,

      initial_params = prev_results,

      bounds = bounds,

      z = 0.0,

      depth = depth,

      eps_out = eps_out, eps_in = eps_in,

      edge_precision = 5,

      dx = 1.0e-9)

       

       

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

      fom = ModeMatch(monitor_name = 'fom',

      mode_number = 'fundamental mode',

      direction = 'Forward',

      target_T_fwd = lambda wl: np.ones(wl.size),

      norm_p = 1)

       

      ######## OPTIMIZATION ALGORITHM ########

      optimizer = ScipyOptimizers(max_iter = 30,

      method = 'L-BFGS-B',

      #scaling_factor = scaling_factor,

      pgtol = 1.0e-5,

      ftol = 1.0e-5,

      #target_fom = 0.0,

      scale_initial_gradient_to = 0.0)

       

      ######## PUT EVERYTHING TOGETHER ########

      opt = Optimization(base_script = y_branch_base,

      wavelengths = wavelengths,

      fom = fom,

      geometry = polygon,

      optimizer = optimizer,

      use_var_fdtd = True,

      hide_fdtd_cad = False,

      use_deps = True,

      plot_history = True,

      store_all_simulations = False)

       

      ######## RUN THE OPTIMIZATION ########

      results = opt.run()

       

      ######## SAVE THE BEST PARAMETERS TO FILE ########

      np.savetxt('../2D_parameters.txt', results[1])

       

      ######## EXPORT OPTIMIZED STRUCTURE TO GDS ########

      gds_export_script = str("gds_filename = 'y_branch_2D.gds';" +

      "top_cell = 'model';" +

      "layer_def = [1, {0}, {1}];".format(-depth/2, depth/2) +

      "n_circle = 64;" +

      "n_ring = 64;" +

      "n_custom = 64;" +

      "n_wg = 64;" +

      "round_to_nm = 1;" +

      "grid = 1e-9;" +

      "max_objects = 10000;" +

      "Lumerical_GDS_auto_export;")

       

      with lumapi.MODE(hide = False) as mode:

      mode.cd(example_directory)

      y_branch_init_(mode)

      mode.addpoly(vertices = splitter(results[1]))

      mode.set('x', 0.0)

      mode.set('y', 0.0)

      mode.set('z', 0.0)

      mode.set('z span', depth)

      mode.set('material','SU-8')

      mode.save("y_branch_2D_FINAL")

      input('Enter...')

      mode.eval(gds_export_script)

       

       

    • taige.li
      Subscriber

      [File 2]

      #############################################################################

      # Python Module: varFDTD_y_branch.py

      #

      # Description:

      # This module defines the y_brach_init_() function used in the

      # optimization for inverse design of the SOI Y-branch in 2D

      #

      # Steps include:

      # 1. Define the base simulation parameters

      # 2. Add non-dispersive materials

      # 2. Define the geometry of input and output waveguides

      # 3. Set up source and monitors and simulation region

      #

      # Copyright 2019, Lumerical Solutions, Inc.

      ##############################################################################

       

      ######## IMPORTS ########

      # General purpose imports

      import lumapi

      import numpy as np

      from scipy.constants import c

       

      def y_branch_init_(mode):

       

      ## CLEAR SESSION

      mode.switchtolayout()

      mode.selectall()

      mode.delete()

       

      ## SIM PARAMS

      size_x=40e-6;

      size_y=20e-6;

      mesh_x=200e-9;

      mesh_y=200e-9;

      finer_mesh_size=19e-6;

      mesh_accuracy=4;

      lam_c = 1.550e-6;

      thickness=2e-6;

      separation=5e-6; #waveguide separation

      coupler_length=24e-6;

      width=2.4e-6; #waveguide

      length=10e-6; #connecting waveguide

       

      ## MATERIAL

      opt_material=mode.addmaterial('Dielectric');

      mode.setmaterial(opt_material,'name','Si: non-dispersive');

      n_opt = mode.getindex('Si (Silicon) - Palik',c/lam_c);

      mode.setmaterial('Si: non-dispersive','Refractive Index',n_opt);

      #print(n_opt);

       

      sub_material=mode.addmaterial('Dielectric');

      mode.setmaterial(sub_material,'name','SiO2: non-dispersive');

      n_sub = mode.getindex('SiO2 (Glass) - Palik',c/lam_c);

      mode.setmaterial('SiO2: non-dispersive','Refractive Index',n_sub);

      mode.setmaterial('SiO2: non-dispersive',"color", np.array([0, 0, 0, 0]));

       

      air_material=mode.addmaterial('Dielectric');

      mode.setmaterial(opt_material,'name','air');

      mode.setmaterial('air','Refractive Index',1);

       

      wg_material=mode.addmaterial('Dielectric');

      mode.setmaterial(opt_material,'name','SU-8');

      mode.setmaterial('SU-8','Refractive Index',1.573);

       

      ## GEOMETRY

       

      #INPUT WAVEGUIDE

       

      mode.addrect();

      mode.set('name','input wg');

      mode.set('x span',10e-6);

      mode.set('y span',width);

      mode.set('z span',thickness);

      mode.set('y',-separation/2);

      mode.set('x',-coupler_length/2-length/2);

      mode.set('z',0);

      mode.set('material','SU-8');

       

      mode.addrect();

      mode.set('name','input wg 2');

      mode.set('x span',10e-6);

      mode.set('y span',width);

      mode.set('z span',thickness);

      mode.set('y',separation/2);

      mode.set('x',-coupler_length/2-length/2);

      mode.set('z',0);

      mode.set('material','SU-8');

       

      #OUTPUT WAVEGUIDES

       

      mode.addrect();

      mode.set('name','output wg top');

      mode.set('x span',10e-6);

      mode.set('y span',width);

      mode.set('z span',thickness);

      mode.set('y',separation/2);

      mode.set('x',coupler_length/2+length/2);

      mode.set('z',0);

      mode.set('material','SU-8');

       

      mode.addrect();

      mode.set('name','output wg bottom');

      mode.set('x span',10e-6);

      mode.set('y span',width);

      mode.set('z span',thickness);

      mode.set('y',-separation/2);

      mode.set('x',coupler_length/2+length/2);

      mode.set('z',0);

      mode.set('material','SU-8');

       

      mode.addrect();

      mode.set('name','sub');

      mode.set('x span',100e-6);

      mode.set('y span',100e-6);

      mode.set('z span',10e-6);

      mode.set('y',0);

      mode.set('x',0);

      mode.set('z',0);

      mode.set('material','SiO2: non-dispersive');

      mode.set('override mesh order from material database',1);

      mode.set('mesh order',3);

      mode.set('alpha',0.8);

       

      ## varFDTD

      mode.addvarfdtd();

      mode.set('mesh accuracy',mesh_accuracy);

      mode.set('x min',-size_x/2);

      mode.set('x max',size_x/2);

      mode.set('y min',-size_y/2);

      mode.set('y max',size_y/2);

      mode.set('z',0);

      mode.set('z span',4e-6);

       

      mode.set('effective index method','variational');

      mode.set('can optimize mesh algorithm for extruded structures',1);

      mode.set('clamp values to physical material properties',1);

       

      mode.set('x0',-1.3e-6);

      mode.set('number of test points',4);

      mode.set('test points',np.array([[0, 0],[1.3e-6, 0.4e-6], [1.3e-6, -0.4e-6], [1.3e-6, 0]]));

       

      ## SOURCE

      mode.addmodesource();

      mode.set('direction','Forward');

      mode.set('injection axis','x-axis');

      #mode.set('polarization angle',0);

      mode.set('y',-separation/2);

      mode.set("y span",width);

      mode.set('x',-coupler_length/2-5e-6);

      mode.set('center wavelength',1550e-9);

      mode.set('wavelength span',0);

      mode.set('mode selection','fundamental mode');

       

       

      ## MESH IN OPTIMIZABLE REGION

      mode.addmesh();

      mode.set('x',0);

      mode.set('x span',finer_mesh_size);

      mode.set('y',0);

      mode.set('y span',finer_mesh_size);

      mode.set('dx',mesh_x);

      mode.set('dy',mesh_y);

      mode.set('z span',4e-6);

       

      ## OPTIMIZATION FIELDS MONITOR IN OPTIMIZABLE REGION

       

      mode.addpower();

      mode.set('name','opt_fields');

      mode.set('monitor type','2D Z-normal');

      mode.set('x',0);

      mode.set('x span',0.95*size_x);

      mode.set('y',0);

      mode.set('y span',0.95* size_y);

      mode.set('z',0);

       

      ## FOM FIELDS

       

      mode.addpower();

      mode.set('name','fom');

      mode.set('monitor type','Linear Y');

      mode.set('x',coupler_length/2+1.5e-6);

      mode.set('y',0);

      mode.set('y span',size_y);

      mode.set('z',0);

       

       

      if __name__ == "__main__":

      mode = lumapi.MODE(hide = False)

      y_branch_init_(mode)

      input('Press Enter to escape...')

       

       

    • Guilin Sun
      Ansys Employee

      I just found your post which is in the wrong forum. Lumerical has dedicated English, Chinese and Korean forums:

      https://forum.ansys.com/forums/forum/discuss-simulation/photonics/

      https://forum.ansys.com/forums/forum/discuss-simulation/photonics/photonics-chinese/

      https://forum.ansys.com/forums/forum/discuss-simulation/photonics/photonics-korean/

      Next time please post in the proper forum in order to get quick reply.

       

      You may find more resources online  https://github.com/chriskeraly/BerkeleyPhotonicInverseDesign

      I would recommend that you modify the structure gradually one by one from small changes.  Before you are skillful, please follow the examples, do minor change and see what happens.

      Please write new post in the correct forum if you have questions.

Viewing 2 reply threads
  • You must be logged in to reply to this topic.