Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lumerical multi layer #171

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions BPG/lumerical/code_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,9 @@ def import_material_file(self, material_dict) -> None:
material_dict : dict
dict of dicts specifying the materials to be created
"""
for key, value in material_dict.items():
self.import_material_from_dict(material_name=key, prop_dict=value)
if material_dict is not None:
for key, value in material_dict.items():
self.import_material_from_dict(material_name=key, prop_dict=value)

def export_to_lsf(self):
file = self.get_file_header()
Expand Down
200 changes: 119 additions & 81 deletions BPG/lumerical/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,49 +554,62 @@ def lsf_export(cls,
spx, spy = spx * 1e-6, spy * 1e-6
lsf_code = []

if rin == 0:
for x_count in range(nx):
for y_count in range(ny):
lsf_code.append('\n')
lsf_code.append('addcircle;\n')
if not isinstance(layer_prop['z_min'], list):
z_min_list = [layer_prop['z_min']]
else:
z_min_list = layer_prop['z_min']
if not isinstance(layer_prop['z_max'], list):
z_max_list = [layer_prop['z_max']]
else:
z_max_list = layer_prop['z_max']

# Set material properties
lsf_code.append('set("material", "{}");\n'.format(layer_prop['material']))
lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha']))
for z_min_val, z_max_val in zip(z_min_list, z_max_list):
z_min = CoordBase(z_min_val).meters
z_max = CoordBase(z_max_val).meters

# Set radius
lsf_code.append('set(radius, {});\n'.format(rout * 1e-6))
if rin == 0:
for x_count in range(nx):
for y_count in range(ny):
lsf_code.append('\n')
lsf_code.append('addcircle;\n')

# Compute the x and y coordinates for each rectangle
lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count))
lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count))
# Set material properties
lsf_code.append('set("material", "{}");\n'.format(layer_prop['material']))
lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha']))

# Extract the thickness values from the layermap file
lsf_code.append('set("z min", {});\n'.format(layer_prop['z_min'] * 1e-6))
lsf_code.append('set("z max", {});\n'.format(layer_prop['z_max'] * 1e-6))
else:
for x_count in range(nx):
for y_count in range(ny):
lsf_code.append('\n')
lsf_code.append('addring;\n')
# Set radius
lsf_code.append('set(radius, {});\n'.format(rout * 1e-6))

# Set material properties
lsf_code.append('set("material", "{}");\n'.format(layer_prop['material']))
lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha']))
# Compute the x and y coordinates for each rectangle
lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count))
lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count))

# Set dimensions/angles
lsf_code.append('set("outer radius", {});\n'.format(rout * 1e-6))
lsf_code.append('set("inner radius", {});\n'.format(rin * 1e-6))
lsf_code.append('set("theta start", {});\n'.format(theta0))
lsf_code.append('set("theta stop", {});\n'.format(theta1))
# Extract the thickness values from the layermap file
lsf_code.append('set("z min", {});\n'.format(z_min))
lsf_code.append('set("z max", {});\n'.format(z_max))
else:
for x_count in range(nx):
for y_count in range(ny):
lsf_code.append('\n')
lsf_code.append('addring;\n')

# Compute the x and y coordinates for each rectangle
lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count))
lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count))
# Set material properties
lsf_code.append('set("material", "{}");\n'.format(layer_prop['material']))
lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha']))

# Extract the thickness values from the layermap file
lsf_code.append('set("z min", {});\n'.format(layer_prop['z_min'] * 1e-6))
lsf_code.append('set("z max", {});\n'.format(layer_prop['z_max'] * 1e-6))
# Set dimensions/angles
lsf_code.append('set("outer radius", {});\n'.format(rout * 1e-6))
lsf_code.append('set("inner radius", {});\n'.format(rin * 1e-6))
lsf_code.append('set("theta start", {});\n'.format(theta0))
lsf_code.append('set("theta stop", {});\n'.format(theta1))

# Compute the x and y coordinates for each rectangle
lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count))
lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count))

# Extract the thickness values from the layermap file
lsf_code.append('set("z min", {});\n'.format(z_min))
lsf_code.append('set("z max", {});\n'.format(z_max))

return lsf_code

Expand Down Expand Up @@ -721,6 +734,8 @@ def lsf_export(cls, bbox, layer_prop, nx=1, ny=1, spx=0.0, spy=0.0) -> List[str]
lsf_code : List[str]
list of str containing the lsf code required to create specified rectangles
"""
# Write the lumerical code for each rectangle in the array
lsf_code = []

# Calculate the width and length of the rectangle in meters
x_span = CoordBase(bbox[1][0] - bbox[0][0]).meters
Expand All @@ -730,32 +745,39 @@ def lsf_export(cls, bbox, layer_prop, nx=1, ny=1, spx=0.0, spy=0.0) -> List[str]
base_x_center = CoordBase((bbox[1][0] + bbox[0][0]) / 2).meters
base_y_center = CoordBase((bbox[1][1] + bbox[0][1]) / 2).meters

# Get vertical dimensions
z_min = CoordBase(layer_prop['z_min']).meters
z_max = CoordBase(layer_prop['z_max']).meters
if not isinstance(layer_prop['z_min'], list):
z_min_list = [layer_prop['z_min']]
else:
z_min_list = layer_prop['z_min']
if not isinstance(layer_prop['z_max'], list):
z_max_list = [layer_prop['z_max']]
else:
z_max_list = layer_prop['z_max']

# Write the lumerical code for each rectangle in the array
lsf_code = []
for x_count in range(nx):
for y_count in range(ny):
lsf_code.append('\n')
lsf_code.append('addrect;\n')
lsf_code.append('set("material", "{}");\n'.format(layer_prop['material']))
lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha']))
for z_min_val, z_max_val in zip(z_min_list, z_max_list):
z_min = CoordBase(z_min_val).meters
z_max = CoordBase(z_max_val).meters

for x_count in range(nx):
for y_count in range(ny):
lsf_code.append('\n')
lsf_code.append('addrect;\n')
lsf_code.append('set("material", "{}");\n'.format(layer_prop['material']))
lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha']))

# Compute the x and y coordinates for each rectangle
lsf_code.append('set("x span", {});\n'.format(x_span))
lsf_code.append('set("x", {});\n'.format(base_x_center + CoordBase(spx * x_count).meters))
lsf_code.append('set("y span", {});\n'.format(y_span))
lsf_code.append('set("y", {});\n'.format(base_y_center + CoordBase(spy * y_count).meters))
# Compute the x and y coordinates for each rectangle
lsf_code.append('set("x span", {});\n'.format(x_span))
lsf_code.append('set("x", {});\n'.format(base_x_center + CoordBase(spx * x_count).meters))
lsf_code.append('set("y span", {});\n'.format(y_span))
lsf_code.append('set("y", {});\n'.format(base_y_center + CoordBase(spy * y_count).meters))

# Extract the thickness values from the layermap file
lsf_code.append('set("z min", {});\n'.format(z_min))
lsf_code.append('set("z max", {});\n'.format(z_max))
# Extract the thickness values from the layermap file
lsf_code.append('set("z min", {});\n'.format(z_min))
lsf_code.append('set("z max", {});\n'.format(z_max))

if 'mesh_order' in layer_prop:
lsf_code.append('set("override mesh order from material database", 1);\n')
lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order']))
if 'mesh_order' in layer_prop:
lsf_code.append('set("override mesh order from material database", 1);\n')
lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order']))

return lsf_code

Expand Down Expand Up @@ -1282,30 +1304,46 @@ def lsf_export(cls, vertices, layer_prop) -> List[str]:
poly_len = len(vertices)

# Write the lumerical code for the polygon
lsf_code = ['\n',
'addpoly;\n',
'set("material", "{}");\n'.format(layer_prop['material']),
'set("alpha", {});\n'.format(layer_prop['alpha']),

# Set center reference to (0, 0) to fix lumericals relative coordinates
'set("x", 0);\n',
'set("y", 0);\n',
'set("use relative coordinates", 0);\n'

# Create matrix to hold vertices, Note that the Lumerical uses meters as the base unit
'V = matrix({},2);\n'.format(poly_len),
'V(1:{},1) = {};\n'.format(poly_len, [CoordBase(point[0]).meters for point in vertices]),
'V(1:{},2) = {};\n'.format(poly_len, [CoordBase(point[1]).meters for point in vertices]),
'set("vertices", V);\n',

# Set the thickness values from the layermap file
'set("z min", {});\n'.format(CoordBase(layer_prop['z_min']).meters),
'set("z max", {});\n'.format(CoordBase(layer_prop['z_max']).meters)
]

if 'mesh_order' in layer_prop:
lsf_code.append('set("override mesh order from material database", 1);\n')
lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order']))
lsf_code = []

if not isinstance(layer_prop['z_min'], list):
z_min_list = [layer_prop['z_min']]
else:
z_min_list = layer_prop['z_min']
if not isinstance(layer_prop['z_max'], list):
z_max_list = [layer_prop['z_max']]
else:
z_max_list = layer_prop['z_max']

for z_min_val, z_max_val in zip(z_min_list, z_max_list):
z_min = CoordBase(z_min_val).meters
z_max = CoordBase(z_max_val).meters

lsf_code.extend([
'\n',
'addpoly;\n',
'set("material", "{}");\n'.format(layer_prop['material']),
'set("alpha", {});\n'.format(layer_prop['alpha']),

# Set center reference to (0, 0) to fix lumericals relative coordinates
'set("x", 0);\n',
'set("y", 0);\n',
'set("use relative coordinates", 0);\n'

# Create matrix to hold vertices, Note that the Lumerical uses meters as the base unit
'V = matrix({},2);\n'.format(poly_len),
'V(1:{},1) = {};\n'.format(poly_len, [CoordBase(point[0]).meters for point in vertices]),
'V(1:{},2) = {};\n'.format(poly_len, [CoordBase(point[1]).meters for point in vertices]),
'set("vertices", V);\n',

# Set the thickness values from the layermap file
'set("z min", {});\n'.format(z_min),
'set("z max", {});\n'.format(z_max)
])

if 'mesh_order' in layer_prop:
lsf_code.append('set("override mesh order from material database", 1);\n')
lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order']))

return lsf_code

Expand Down