Photonics

Photonics

Photonic Crystal VCSEL simulations

Tagged: 

    • Chris Chase
      Subscriber

      Hi. I am trying to solve transverse modes of a VCSEL. I was looking at a similar example https://optics.ansys.com/hc/en-us/articles/1500008021762-Photonic-Crystal-VCSEL-simulations.  Can I please have guide for how to setup and run the simulation as well as the examples files, as stated in last sentence of the first paragraph of the above webpage?

    • Guilin Sun
      Ansys Employee

      Unfortunately the simulation file is not available right now. Please send us an email if you have the premium support. Basically you need to set up the DFB stacks, and a cavity. Since this is a cavity, it has resonance mode. The transverse mode is waveguide mode. they are different. The transverse mode can be obtained through a mode source, or mode epxnsion monitor, or FDE solver placed on the waveguide you want to get the trasversal mode. It is also possible to get a cross section of the resonance mode, once you know resonance peak location and place the DFT monitor there.

    • Chris Chase
      Subscriber

      1) I meant for large oxide aperture of a VCSEL there may 2 modes having slightly different effective refractive index ,due to distinctively different in-plane/transverse characteristics but very close frequency as seen from resonance finder.   Following this example and photonic crystal cavity example, i found this frequencies of modes by resonance finder. But in 2nd simulation when I put a frequency domain field profile monitor at this frequencies, I find the in-plane shape is same. How do I get the correct in-plane spatial distribution for these modes?

       

      2) What is webpage/email to subscribe to premium support? Is it directly from Lumerical or through an external channel partner?

    • Guilin Sun
      Ansys Employee

      Do you mean the mode profile (in the cross section of the cavity) is very similar at the two wavelength? if so, it is normal, since the two wavelengths have very similar refractive index.

      If you have the premium privilege, you can register support by following this How to register for support with Lumerical

    • Chris Chase
      Subscriber

      How do we make sure that horizontal lines of mesh are aligned to horizontal vcsel  layer boundaries? Does it effect resonant peaks if it does not align?

    • Guilin Sun
      Ansys Employee

      FDTD is a discretized method. Therefore the meshing can affect the result. You know the locations of the VCSEL layers. If they can hold integer number of meshes, it is better to use override mesh to have conformal mesh to the layer interfaces. For the DBR reflectors you can also use the two alternative layers to have integer number of meshes if each layer cannot hold, if possible.  If not, the conformal variant 0 can be used by default, to resolve sub-mesh size. With higher mesh accuracy or smaller mesh size the resonant wavelength can shift a little, but it should be very close to experiment.

    • Chris Chase
      Subscriber

      2 Questions :

      1. How do I ensure integer number of mesh ? Currently I use mesh override, but I can only see  "set maximum mesh step". So even if I set this number equal to size for integer number of mesh, its maximum,  so actual step may not be this number and hence mesh and edge does not align. Is there any other settings?

      2. We are currently in trial version. We want to verify if we can solve the problem by Lumerical, before buying it. Is there technical support available for our specific case?

    • Guilin Sun
      Ansys Employee

      As you know, the override mesh can specify mesh size. So you know the layer thickenss and you know the approximate mesh size, you can use the thicknes divided by an integer to be close to the desired mesh size. "set maximum mesh step" is the mesh size to be used.

      If you are a commercial user or want to buy commercial license, you can contact sales. https://www.ansys.com/contact-us

       

    • Chris Chase
      Subscriber
      I see that if there are 2 dbrs back to back, the mesh size is set internally to a common value even though mesh sizes are overridden in 2 dbrs individually by mesh override region, for integer number of mesh cells per period. Is it a bug or there is some other way to get desired value. My python script is below :
       
       
       
      import importlib.util 
      spec_win = importlib.util.spec_from_file_location('lumapi', 'C:\\Program Files\\Lumerical\\v222\\api\\python\\lumapi.py')
      import numpy as np
      lumapi = importlib.util.module_from_spec(spec_win) 
      spec_win.loader.exec_module(lumapi)
      if not ( 'fdtd' in locals()  or 'fdtd' in globals()  ):
          fdtd = lumapi.FDTD("A")   
      ##############################################    
      N_DBR1=4
      N_DBR2=3
      n1= 3.487
      n2= 2.941
      n3= 2.990
      NUM_MESH_PER_DBR_PERIOD=6
      ################################################
      fdtd.switchtolayout();
      fdtd.deleteall();
      ##################   declare simulation, structure and mesh groups
      props={"dimension":"2D","x": 0, "x span" :2e-6, "y min": 0, "y max": 4e-6,
             "z": 0, "mesh accuracy":1,"set simulation bandwidth":1,
             "simulation wavelength min":1e-6,"simulation wavelength max":1.1e-6} 
      fdtd.addfdtd (properties=props);
      props={"x": 0,"y": 0, "z": 0,"name":"epilayer_struct"} 
      fdtd.addstructuregroup(properties=props);
      props={"x": 0,"y": 0, "z": 0,"name":"mesh_group",} 
      fdtd.addgroup (properties=props);
      ################# draw substrate
      y_pos=0e-6; 
      t=2e-6; 
      props = {"x":0,"z":0,"x span":1e-6,"z":0,"z span":0, 
               "y min": y_pos,"y max": y_pos+t,"index" : n1 , "name":"substrate" } ;
      fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
      y_pos+=t
      ################################################################################
      #######   DBR 1
      ###############################################################################
      print("DBR1 bot : " + str(y_pos) )
      y_pos_DBR1_bot=y_pos
      for k in np.arange(N_DBR1):
          t=89.3e-9; 
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos,  "y max": y_pos+t, 
                    "index" : n2,"name":"DBR1_n2",  "alpha":0.2} ;
          fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
          t=75.3e-9; 
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos, "y max": y_pos+t, 
                    "index" : n1,"name":"DBR1_n1"} ;
          fdtd.addrect(properties=props);fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
      y_pos_DBR1_top=y_pos
      print("DBR1 top : " + str(y_pos) )
      ####### add mesh DBR1
      dy=(y_pos_DBR1_top-y_pos_DBR1_bot)/N_DBR1/NUM_MESH_PER_DBR_PERIOD
      print("dy mesh DBR1 : " + str(dy))
      props = {"x":0,"z":0,"x span":1.5e-6   ,"y min": y_pos_DBR1_bot, "y max": y_pos_DBR1_top,  
                "name":"mesh_DBR1","set maximum mesh step":1,
                "override y mesh":1,"override x mesh":0,"override z mesh":0,"dy":dy} ;
      fdtd.addmesh(properties=props); fdtd.addtogroup("mesh_group");
      ###############################################################################
      #######   DBR 2
      ###############################################################################
      print("DBR2 bot : " + str(y_pos) )
      y_pos_DBR2_bot=y_pos
      for k in np.arange(N_DBR2):
          t=87.8e-9; 
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos,"y max": y_pos+t, 
                    "index" : n3, "name":"DBR2_n3","alpha":0.5} ;
          fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
          t=75.3e-9; 
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos,"y max": y_pos+t, 
                    "index" : n1,"name":"DBR2_n1"} ;
          fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
      y_pos_DBR2_top=y_pos
      print("DBR2 top : " + str(y_pos) )  
      ####### add mesh DBR2  
      dy=(y_pos_DBR2_top-y_pos_DBR2_bot)/N_DBR2/NUM_MESH_PER_DBR_PERIOD
      print("dy mesh DBR2 : " + str(dy))
      props = {"x":0,"z":0,"x span":1.5e-6   ,"y min": y_pos_DBR2_bot,"y max": y_pos_DBR2_top,  
                "name":"mesh_DBR2","set maximum mesh step":1,
                "override y mesh":1,"override x mesh":0, "override z mesh":0,"dy":dy          } ;
      fdtd.addmesh(properties=props); fdtd.addtogroup("mesh_struct");
      ##############################################################################
      #### LINE MONITOR to get y mesh 
      ##############################################################################
      props = {"monitor type":"Linear Y","x":0,"z":0,"y min":1.5e-6   ,"y max": 4e-6} ;
      fdtd.addpower(properties=props);
      ##########################
      fdtd.run();
      ######### y mesh
      y=fdtd.getresult("monitor","y") ;print( np.diff(y[:,0]) )

       

    • Guilin Sun
      Ansys Employee

      Unfortunately, if you overlap the two override regions, only the finer one is applied, and the overlap region will have 2 mesh cells buffer.

      I would suggest that you manually test the meshing and make sure it works as expected.

    • Chris Chase
      Subscriber

      I introduced gap of 1 full period ~ 6 mesh shells between 2 override regions. I still find that uniform mesh step got applied across both DBR periods. The value of actual step was different from both the steps I put in 2 mesh override region. My python script is as below

       

      import importlib.util 
      spec_win = importlib.util.spec_from_file_location('lumapi', 'C:\\Program Files\\Lumerical\\v222\\api\\python\\lumapi.py')
      import numpy as np
      lumapi = importlib.util.module_from_spec(spec_win) 
      spec_win.loader.exec_module(lumapi)
      if not ( 'fdtd' in locals()  or 'fdtd' in globals()  ):
          fdtd = lumapi.FDTD("A")   
      ##############################################    
      N_DBR1=4
      N_DBR2=3
      n1= 3.487
      n2= 2.941
      n3= 2.990
      NUM_MESH_PER_DBR_PERIOD=6
      ################################################
      fdtd.switchtolayout();
      fdtd.deleteall();
      ##################   declare simulation, structure and mesh groups
      props={"dimension":"2D","x": 0, "x span" :2e-6, "y min": 0, "y max": 4e-6,
             "z": 0, "mesh accuracy":1,"set simulation bandwidth":1,
             "simulation wavelength min":1e-6,"simulation wavelength max":1.1e-6} 
      fdtd.addfdtd (properties=props);
      props={"x": 0,"y": 0, "z": 0,"name":"epilayer_struct"} 
      fdtd.addstructuregroup(properties=props);
      props={"x": 0,"y": 0, "z": 0,"name":"mesh_group",} 
      fdtd.addgroup (properties=props);
      ################# draw substrate
      y_pos=0e-6; 
      t=2e-6; 
      props = {"x":0,"z":0,"x span":1e-6,"z":0,"z span":0, 
               "y min": y_pos,"y max": y_pos+t,"index" : n1 , "name":"substrate" } ;
      fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
      y_pos+=t
      ################################################################################
      #######   DBR 1
      ###############################################################################
      print("DBR1 bot : " + str(y_pos) )
      y_pos_DBR1_bot=y_pos
      for k in np.arange(N_DBR1):
          t=89.3e-9;  
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos,  "y max": y_pos+t, 
                    "index" : n2,"name":"DBR1_n2",  "alpha":0.2} ;
          fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
          t=75.3e-9;  
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos, "y max": y_pos+t, 
                    "index" : n1,"name":"DBR1_n1"} ;
          fdtd.addrect(properties=props);fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
      y_pos_DBR1_top=y_pos
      print("DBR1 top : " + str(y_pos) )
      ####### add mesh DBR1
      dy=(y_pos_DBR1_top-y_pos_DBR1_bot)/N_DBR1/NUM_MESH_PER_DBR_PERIOD
      print("dy mesh DBR1 : " + str(dy))
      props = {"x":0,"z":0,"x span":1.5e-6   ,"y min": y_pos_DBR1_bot, "y max": y_pos_DBR1_top,  
                "name":"mesh_DBR1","set maximum mesh step":1,
                "override y mesh":1,"override x mesh":0,"override z mesh":0,"dy":dy} ;
      fdtd.addmesh(properties=props); fdtd.addtogroup("mesh_group");
      ###############################################################################
      #######   DBR 2
      ###############################################################################
      print("DBR2 bot : " + str(y_pos) )
      y_pos_DBR2_bot=y_pos
      for k in np.arange(N_DBR2):
          t1=87.8e-9; 
          t=t1;
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos,"y max": y_pos+t, 
                    "index" : n3, "name":"DBR2_n3","alpha":0.5} ;
          fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
          t2=75.3e-9; 
          t=t2;
          props = {"x":0,"z":0, "x span":1e-6,"y min": y_pos,"y max": y_pos+t, 
                    "index" : n1,"name":"DBR2_n1"} ;
          fdtd.addrect(properties=props); fdtd.addtogroup("epilayer_struct");
          y_pos+=t
          ####################
      y_pos_DBR2_top=y_pos
      print("DBR2 top : " + str(y_pos) )  
      ####### add mesh DBR2  
      dy=(y_pos_DBR2_top-y_pos_DBR2_bot)/N_DBR2/NUM_MESH_PER_DBR_PERIOD
      print("dy mesh DBR2 : " + str(dy))
      #introduce gap in 2 mesh override regions
      props = {"x":0,"z":0,"x span":1.5e-6   ,"y min": y_pos_DBR2_bot + (t1+t2) ,"y max": y_pos_DBR2_top ,  
                "name":"mesh_DBR2","set maximum mesh step":1,
                "override y mesh":1,"override x mesh":0, "override z mesh":0,"dy":dy          } ;
      fdtd.addmesh(properties=props); fdtd.addtogroup("mesh_struct");
      ##############################################################################
      #### LINE MONITOR to get y mesh 
      ##############################################################################
      props = {"monitor type":"Linear Y","x":0,"z":0,"y min":1.5e-6   ,"y max": 4e-6} ;
      fdtd.addpower(properties=props);
      ##########################
      fdtd.run();
      ######### y mesh
      y=fdtd.getresult("monitor","y") ;print( np.diff(y[:,0]) )

       

    • Guilin Sun
      Ansys Employee

      did you check the uniform mesh size and compared with the override mesh size? As I suggested, please manually set the override mesh and make sure it works. then you can use python and check if the resulting meshing is the same. if not, it might indicate a bug: python cannot set it correctly.

    • Chris Chase
      Subscriber

      I added the override region manually. It has same result as python based override region. I see that  the bottom edge of override region, starts in a gap inside a mesh cell. Is there a way to fix it?

    • Guilin Sun
      Ansys Employee

      I am not sure what problem do you want to fix? you can change the override region dimension and location, the same as a rectangle geometry. please refer  Ansys Insight: About override mesh in FDTD: its use and settings

      https://optics.ansys.com/hc/en-us/articles/360034382634-Understanding-the-non-uniform-mesh-in-FDTD

    • Chris Chase
      Subscriber

      I mean my dbr is on a substrate. Even though I overide only dbr region. The  bottom edge of dbr fall between 2 orange horizontal mesh cell lines. Does it help in getting periodicity of mesh right  in dbr, if bottom edge of dbr aligns with a mesh horiztal line?

    • Guilin Sun
      Ansys Employee

      If one period can have integer number of meshes, it will preserve the periodicity. You may need to use finer mesh size.

      please try.

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