Skip to content

Commit

Permalink
Squashed commit of several new features and enhancements from Lumerical:
Browse files Browse the repository at this point in the history
 - Support for a broadband figure of merit with no additional FDTD simulations. Uses the time domain simulation to extract a user specified number of frequency samples to compute a figure of merit over a spectrum. Figure of merit is specified as the mean of the target spectrum minus the error p-norm
 - Restored the fixed and adaptive step gradient descent optimization algorithms as alternatives to SciPy
 - Added a new example of a splitter with output arms included in the optimized shape
 - Improved performance of mesh (use_deps=True) by only producing mesh at a single frequency
 - Added flag to hide FDTD Solutions graphical interface
  • Loading branch information
areid-van authored and crees-lumerical committed Feb 20, 2019
1 parent c9447b7 commit 8f779f8
Show file tree
Hide file tree
Showing 42 changed files with 1,833 additions and 861 deletions.
Empty file added QA/__init__.py
Empty file.
14 changes: 14 additions & 0 deletions QA/qatools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os as _os
import unittest as _unittest
import xmlrunner

TestCase = _unittest.TestCase

def run(filenames):
for filename in filenames:
_os.chdir(_os.path.abspath(_os.path.dirname(filename)))
filename = _os.path.basename(filename)
module_name = filename.replace(".py", "")
suite = _unittest.TestLoader().loadTestsFromName(module_name)
with open(module_name+".xml", "w") as output:
xmlrunner.XMLTestRunner(output=output, verbosity=2).run(suite)
77 changes: 77 additions & 0 deletions QA/robust_coupler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
""" Copyright chriskeraly
Copyright (c) 2019 Lumerical Inc. """

######## IMPORTS ########
# General purpose imports
import os
import numpy as np
import scipy as sp

from lumopt.utilities.load_lumerical_scripts import load_from_lsf
from lumopt.utilities.wavelengths import Wavelengths
from lumopt.geometries.polygon import FunctionDefinedPolygon
from lumopt.figures_of_merit.modematch import ModeMatch
from lumopt.optimizers.generic_optimizers import ScipyOptimizers
from lumopt.optimization import Optimization

######## DEFINE SPECTRAL RANGE #########
wavelengths = Wavelengths(start = 1550e-9, stop = 1550e-9, points = 1)

######## DEFINE BASE SIMULATION ########
# Use the same script for both simulations, but it's just to keep the example simple. You could use two.
script_1 = load_from_lsf(os.path.join(os.path.dirname(__file__), 'splitter_base_TE_modematch.lsf'))
script_2 = load_from_lsf(os.path.join(os.path.dirname(__file__), 'splitter_base_TE_modematch_25nmoffset.lsf'))

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

## Here the two splitters just have a 25nm offset from each other, so that the result is robust
def taper_splitter_1(params,n_points=10):
points_x = np.concatenate(([-1.01e-6],np.linspace(-1.1e-6,0.9e-6,10),[1.01e-6]))
points_y = np.concatenate(([0.25e-6],params,[0.6e-6]))
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 = [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

dx=25e-9
def taper_splitter_2(params,n_points=10):
points_x = np.concatenate(([-1.01e-6],np.linspace(-1.1e-6,0.9e-6,10),[1.01e-6]))
points_y = np.concatenate(([0.25e-6+dx],params+dx,[0.6e-6+dx]))
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 = [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()
91 changes: 91 additions & 0 deletions QA/splitter_base_TE_modematch.lsf
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
switchtolayout;
selectall;
delete;

## SIM PARAMS
size_x=3e-6;
size_y=3e-6;
mesh_x=20e-9;
mesh_y=20e-9;
finer_mesh_size=2.5e-6;

## GEOMETRY

#INPUT WAVEGUIDE

addrect;
set('name','input wg');
set('x span',3e-6);
set('y span',0.5e-6);
set('z span',220e-9);
set('y',0);
set('x',-2.5e-6);
set('index',2.8);

#OUTPUT WAVEGUIDES

addrect;
set('name','output wg top');
set('x span',3e-6);
set('y span',0.5e-6);
set('z span',220e-9);
set('y',0.35e-6);
set('x',2.5e-6);
set('index',2.8);

addrect;
set('name','output wg bottom');
set('x span',3e-6);
set('y span',0.5e-6);
set('z span',220e-9);
set('y',-0.35e-6);
set('x',2.5e-6);
set('index',2.8);

## SOURCE
addmode;
set('direction','Forward');
set('injection axis','x-axis');
#set('polarization angle',0);
set('y',0);
set('x',-1.25e-6);
set('override global source settings',false);
set('mode selection','fundamental TE mode');

## FDTD
addfdtd;
set('dimension','2D');
set('background index',1.44);
set('mesh accuracy',4);
set('x min',-size_x/2);
set('x max',size_x/2);
set('y min',-size_y/2);
set('y max',size_y/2);
set('force symmetric y mesh',1);

## MESH IN OPTIMIZABLE REGION
addmesh;
set('x',0);
set('x span',finer_mesh_size);
set('y',0);
set('y span',finer_mesh_size);
set('dx',mesh_x);
set('dy',mesh_y);

## OPTIMIZATION FIELDS MONITOR IN OPTIMIZABLE REGION
addpower;
set('name','opt_fields');
set('monitor type','2D Z-normal');
set('x min',-size_x/2);
set('x max',1.1e-6);
set('y min',-size_y/2);
set('y max',size_y/2);

## FOM FIELDS

addpower;
set('name','fom');
set('monitor type','2D X-normal');
set('x',1.25e-6);
set('y min',-1e-6);
set('y max',1e-6);
93 changes: 93 additions & 0 deletions QA/splitter_base_TE_modematch_25nmoffset.lsf
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
switchtolayout;
selectall;
delete;

## SIM PARAMS
size_x=3e-6;
size_y=3e-6;
mesh_x=10e-9;
mesh_y=10e-9;
finer_mesh_size=2.5e-6;
offset=25e-9;

## GEOMETRY

#INPUT WAVEGUIDE

addrect;
set('name','input wg');
set('x span',3e-6);
set('y span',0.5e-6+2*offset);
set('z span',220e-9);
set('y',0);
set('x',-2.5e-6);
set('index',2.8);

#OUTPUT WAVEGUIDES

addrect;
set('name','output wg top');
set('x span',3e-6);
set('y span',0.5e-6+2*offset);
set('z span',220e-9);
set('y',0.35e-6);
set('x',2.5e-6);
set('index',2.8);

addrect;
set('name','output wg bottom');
set('x span',3e-6);
set('y span',0.5e-6+2*offset);
set('z span',220e-9);
set('y',-0.35e-6);
set('x',2.5e-6);
set('index',2.8);

## SOURCE
addmode;
set('direction','Forward');
set('injection axis','x-axis');
#set('polarization angle',0);
set('y',0);
set('x',-1.25e-6);
set('override global source settings',false);
set('mode selection','fundamental TE mode');

## FDTD
addfdtd;
set('dimension','2D');
set('background index',1.44);
set('mesh accuracy',4);
set('x min',-size_x/2);
set('x max',size_x/2);
set('y min',-size_y/2);
set('y max',size_y/2);
set('force symmetric y mesh',1);


## MESH IN OPTIMIZABLE REGION
addmesh;
set('x',0);
set('x span',finer_mesh_size);
set('y',0);
set('y span',finer_mesh_size);
set('dx',mesh_x);
set('dy',mesh_y);

## OPTIMIZATION FIELDS MONITOR IN OPTIMIZABLE REGION
addpower;
set('name','opt_fields');
set('monitor type','2D Z-normal');
set('x min',-size_x/2);
set('x max',1.1e-6);
set('y min',-size_y/2);
set('y max',size_y/2);

## FOM FIELDS

addpower;
set('name','fom');
set('monitor type','2D X-normal');
set('x',1.25e-6);
set('y min',-1e-6);
set('y max',1e-6);
112 changes: 112 additions & 0 deletions QA/splitter_base_TE_modematch_3D.lsf
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
switchtolayout;
selectall;
delete;

###SIM PARAMS
size_x=3e-6;
size_y=2.5e-6;
size_z=1.2e-6;
mesh_x=20e-9;
mesh_y=20e-9;
mesh_z=20e-9;
finer_mesh_size=3e-6;
finer_mesh_size_z=0.6e-6;

##GEOMETRY

#INPUT WAVEGUIDE

addrect;
set('name','input wg');
set('x span',3e-6);
set('y span',0.5e-6);
set('z span',220e-9);
set('y',0);
set('x',-2.5e-6);
set('material','Si (Silicon) - Palik');


##OUTPUT WAVEGUIDES

addrect;
set('name','output wg top');
set('x span',3e-6);
set('y span',0.5e-6);
set('z span',220e-9);
set('y',0.35e-6);
set('x',2.5e-6);
set('material','Si (Silicon) - Palik');


addrect;
set('name','output wg bottom');
set('x span',3e-6);
set('y span',0.5e-6);
set('z span',220e-9);
set('y',-0.35e-6);
set('x',2.5e-6);
set('material','Si (Silicon) - Palik');


#SOURCE
addmode;
set('direction','Forward');
set('injection axis','x-axis');
#set('polarization angle',0);
set('y',0);
set('y span',2e-6);
set('x',-1.25e-6);
set('z',0);
set('z span',1e-6);
set('override global source settings',false);
set('mode selection','fundamental TE mode');

#FDTD
addfdtd;
set('dimension','3D');
set('background index',1.44);
set('mesh accuracy',4);
set('x min',-size_x/2);
set('x max',size_x/2);
set('y min',-size_y/2);
set('y max',size_y/2);
set('z min',-size_z/2);
set('z max',size_z/2);
set('force symmetric y mesh',1);
set('force symmetric z mesh',1);
#set('z min bc','Symmetric');
#set('y min bc','Anti-Symmetric');

addmesh;
set('x',0);
set('x span',finer_mesh_size);
set('y',0);
set('y span',finer_mesh_size);
set('z',0);
set('z span',finer_mesh_size_z);
set('dx',mesh_x);
set('dy',mesh_y);
set('dx',mesh_z);

#Optimization fields
addpower;
set('name','opt_fields');
set('monitor type','3D');
set('x min',-size_x/2);
set('x max',1.1e-6);
set('y min',-size_y/2);
set('y max',size_y/2);
set('z min',-0.4e-6);
set('z max',0.4e-6);


#FOM FIELDS

addpower;
set('name','fom');
set('monitor type','2D X-normal');
set('x',1.26e-6);
set('y min',-1e-6);
set('y max',1e-6);
set('z min',-0.5e-6);
set('z max',0.5e-6);
Loading

0 comments on commit 8f779f8

Please sign in to comment.