repo build
This commit is contained in:
@@ -0,0 +1,734 @@
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
import sys
|
||||
import h5py
|
||||
import matplotlib.pyplot as plt
|
||||
from typing import Literal
|
||||
|
||||
def __getLumericalLibPATH__():
|
||||
path = os.path.dirname(os.path.abspath(__file__)) + "\\Lumerical\\"
|
||||
return path
|
||||
|
||||
def __checkLumericalDIR__():
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(path+"\\LumericalPATH.json") as FID:
|
||||
FILE_CONTEXT = json.load(FID)
|
||||
|
||||
DEFAULT_PATH = FILE_CONTEXT["DEFAULT_PATH"]
|
||||
for idx in range(len(DEFAULT_PATH)):
|
||||
if (os.path.exists(DEFAULT_PATH[idx])):
|
||||
return DEFAULT_PATH[idx]
|
||||
|
||||
raise Exception("NO FDTD link found using default paths")
|
||||
|
||||
|
||||
def __PathGenerate__(dev_name, path=None):
|
||||
""" creating folders """
|
||||
if (path is None):
|
||||
folder = f"{dev_name}_simu\\"
|
||||
elif (isinstance(path,str)):
|
||||
if (path.endswith("\\")):
|
||||
folder = f"{path}{dev_name}_simu\\"
|
||||
else:
|
||||
folder = f"{path}\\{dev_name}_simu\\"
|
||||
|
||||
try:
|
||||
os.makedirs(folder)
|
||||
except:
|
||||
pass
|
||||
|
||||
return folder
|
||||
|
||||
def __LoggAllAttrs__(device,folder,dev_name):
|
||||
attrs = dir(device)
|
||||
time_curr = time.strftime('%Y%m%d-%H%M%S', time.localtime())
|
||||
attrDict = {}
|
||||
attrDict["time"] = time_curr
|
||||
""" recording ALL parameters inside the device """
|
||||
for attr in attrs:
|
||||
if not attr.startswith("__"):
|
||||
attrCur = getattr(device,attr)
|
||||
if (isinstance(attrCur,float) or isinstance(attrCur,int)):
|
||||
attrDict[attr] = attrCur
|
||||
|
||||
elif (isinstance(attrCur,list)):
|
||||
if (isinstance(attrCur[0],float) or isinstance(attrCur[0],int)):
|
||||
attrDict[attr] = attrCur
|
||||
|
||||
elif (isinstance(attrCur,np.ndarray)):
|
||||
attrDict[attr] = attrCur.tolist()
|
||||
|
||||
|
||||
""" """
|
||||
with open(folder+f"{dev_name}_mxpic.json","w") as FID:
|
||||
json.dump(attrDict,FID)
|
||||
|
||||
device = device.cell
|
||||
|
||||
def PortParas(pin,width,height,radius=0):
|
||||
port_dict = {}
|
||||
port_dict["x"] = pin.x
|
||||
port_dict["y"] = pin.y
|
||||
port_dict["a"] = pin.a
|
||||
port_dict["width"] = width
|
||||
port_dict["height"] = height
|
||||
port_dict["radius"] = radius
|
||||
|
||||
|
||||
return port_dict
|
||||
|
||||
def MonitorParas(x,y,z,dx,dy,dz):
|
||||
mont_dict = {}
|
||||
mont_dict["x"] = x
|
||||
mont_dict["y"] = y
|
||||
mont_dict["z"] = z
|
||||
mont_dict["dx"] = dx
|
||||
mont_dict["dy"] = dy
|
||||
mont_dict["dz"] = dz
|
||||
|
||||
return mont_dict
|
||||
|
||||
def DEVICE_2X2_FDTD_INIT(fdtd,run=False,instrcutPATH=None,LibPATH=None):
|
||||
|
||||
fdtd.eval("newproject;")
|
||||
fdtd.eval("switchtolayout;")
|
||||
fdtd.eval("deleteall;")
|
||||
fdtd.eval("clc;")
|
||||
|
||||
if (LibPATH is None):
|
||||
fdtd.eval("ABSOLUTE_LIB_DIR = read(\'lib_path.txt\');")
|
||||
elif (isinstance(LibPATH,str)):
|
||||
if (LibPATH.endswith("\\")):
|
||||
fdtd.eval("ABSOLUTE_LIB_DIR = \'"+LibPATH+"\';")
|
||||
|
||||
else:
|
||||
fdtd.eval("ABSOLUTE_LIB_DIR = \'"+LibPATH+"\\\\\';")
|
||||
##### Install maxwell's library #####
|
||||
|
||||
fdtd.eval("PATH_LIB = ABSOLUTE_LIB_DIR + \'mx_lib_install.lsf\';")
|
||||
fdtd.eval("feval(PATH_LIB);")
|
||||
|
||||
# fdtd.eval("feval(\'GDS_SIMU_DEVICE_2X2.lsf\');")
|
||||
|
||||
fdtd.eval("FUNC_DEVICE_2X2(\'"+instrcutPATH+"\');")
|
||||
|
||||
if (run):
|
||||
|
||||
fdtd.eval("run;")
|
||||
fdtd.eval("DATA_RETRIEVE_DEVICE_2X2(\'"+instrcutPATH+"\');")
|
||||
|
||||
def tuple_to_complex(t):
|
||||
return complex(t[0], t[1])
|
||||
|
||||
def SimuDataFigurePlot(simuPath,devName,saveFlag=True,ports=["a1","b1"]):
|
||||
|
||||
if (simuPath.endswith("\\")):
|
||||
pass
|
||||
else:
|
||||
simuPath = simuPath + "\\"
|
||||
|
||||
""" data analysis """
|
||||
data = h5py.File(simuPath + devName + "_results.mat","r")
|
||||
|
||||
dataDict = {}
|
||||
for portName in ports:
|
||||
""" Getting result of transmission """
|
||||
dataDict[portName] = {}
|
||||
dataDict[portName]["trans"] = np.squeeze(data[portName]["power"]["T"][()])
|
||||
dataDict[portName]["wl"] = np.squeeze(data[portName]["power"]["lambda"][()])
|
||||
dataDict[portName]["modes"] = np.squeeze(data[portName]["modes"]["T_net"][()])
|
||||
dataDict[portName]["E"] = np.squeeze(data[portName]["E"]["E"][()])
|
||||
dataDict[portName]["H"] = np.squeeze(data[portName]["H"]["H"][()])
|
||||
|
||||
""" Calculating the propagation field """
|
||||
E_prg = np.squeeze(data["z1"]["E"]["E"][()])
|
||||
wl_prg = np.squeeze(data["z1"]["E"]["lambda"][()])
|
||||
|
||||
x = np.squeeze(data["z1"]["E"]["x"][()])
|
||||
y = np.squeeze(data["z1"]["E"]["y"][()])
|
||||
z = np.squeeze(data["z1"]["E"]["z"][()])
|
||||
|
||||
E_prg = np.vectorize(tuple_to_complex)(E_prg)
|
||||
|
||||
# plt.figure(figsize=(12,6))
|
||||
fig,ax = plt.subplots(3,3,figsize=(20, 9))
|
||||
plt.subplots_adjust(wspace=0.5, hspace=0.3)
|
||||
|
||||
manager = plt.get_current_fig_manager()
|
||||
manager.window.wm_geometry("+100+100")
|
||||
|
||||
wl_idx_plt = [0,int(np.floor(len(wl_prg)/2+1))-1,len(wl_prg)-1]
|
||||
for idx in range(len(wl_idx_plt)):
|
||||
# plt.subplot(3,2,2*idx+1)
|
||||
Ex = np.abs(E_prg[idx,0,:].reshape(len(y),len(x)))
|
||||
Ey = np.abs(E_prg[idx,1,:].reshape(len(y),len(x)))
|
||||
Ez = np.abs(E_prg[idx,2,:].reshape(len(y),len(x)))
|
||||
|
||||
E_mag = np.sqrt(np.square(Ex) + np.square(Ey) + np.square(Ez))
|
||||
|
||||
ax[0,idx].set_title(f"wavelength = {wl_prg[wl_idx_plt[idx]]*1e+9:.1f} nm")
|
||||
ax[0,idx].pcolor(np.real(E_mag))
|
||||
|
||||
""" Plotting the port transmission """
|
||||
if ("b1" in ports and "a1" in ports):
|
||||
dataDict["Ephase_11"] = np.squeeze(data["Ephase_11"][()])
|
||||
Trans_11 = dataDict["b1"]["trans"]
|
||||
Tmodes = dataDict["b1"]["modes"]
|
||||
|
||||
ax1 = ax[1,0]
|
||||
ax2 = ax[2,0]
|
||||
|
||||
ax1.set_title("a_1 to b_1 trans [Through]")
|
||||
ax1.plot(dataDict["a1"]["wl"]*1e+6,Trans_11,linewidth=3)
|
||||
|
||||
""" plotting the eigen mode decomposition """
|
||||
dataSZ = np.shape(Tmodes)
|
||||
plt_wl = dataDict["a1"]["wl"]*1e+6
|
||||
|
||||
dataPlt = []
|
||||
|
||||
""" Plotting the Mode crosstalk for target modes """
|
||||
if (len(dataSZ) > 1):
|
||||
for pltIdx in range(0,dataSZ[0]):
|
||||
_data_ = np.abs(Tmodes[pltIdx,:])
|
||||
dataPlt.append(_data_)
|
||||
else:
|
||||
_data_ = np.abs(Tmodes)
|
||||
dataPlt.append(_data_)
|
||||
|
||||
for pltIdx in range(0,len(dataPlt)):
|
||||
_data_ = dataPlt[pltIdx]
|
||||
ax1.plot(plt_wl,_data_,linewidth=3)
|
||||
Trans_dB = 10*np.log10(_data_)
|
||||
ax2.plot(plt_wl,Trans_dB,label=f"mode_{pltIdx}",linewidth=3)
|
||||
|
||||
|
||||
if ("b2" in ports and "a1" in ports):
|
||||
dataDict["Ephase_21"] = np.squeeze(data["Ephase_11"][()])
|
||||
Trans_21 = dataDict["b2"]["trans"]
|
||||
Tmodes = dataDict["b2"]["modes"]
|
||||
|
||||
ax1 = ax[1,1]
|
||||
ax2 = ax[2,1]
|
||||
|
||||
ax1.set_title("a_1 to b_1 trans [Through]")
|
||||
ax1.plot(dataDict["a1"]["wl"]*1e+6,Trans_21)
|
||||
|
||||
""" plotting the eigen mode decomposition """
|
||||
dataSZ = np.shape(Tmodes)
|
||||
plt_wl = dataDict["a1"]["wl"]*1e+6
|
||||
|
||||
dataPlt = []
|
||||
|
||||
""" Plotting the Mode crosstalk for target modes """
|
||||
if (len(dataSZ) > 1):
|
||||
for pltIdx in range(0,dataSZ[0]):
|
||||
_data_ = np.abs(Tmodes[pltIdx,:])
|
||||
dataPlt.append(_data_)
|
||||
else:
|
||||
_data_ = np.abs(Tmodes)
|
||||
dataPlt.append(_data_)
|
||||
|
||||
for pltIdx in range(0,len(dataPlt)):
|
||||
_data_ = dataPlt[pltIdx]
|
||||
ax1.plot(plt_wl,_data_,linewidth=3)
|
||||
Trans_dB = 10*np.log10(_data_)
|
||||
ax2.plot(plt_wl,Trans_dB,label=f"mode_{pltIdx}",linewidth=3)
|
||||
|
||||
if ("a2" in ports and "a1" in ports):
|
||||
Refl_21 = dataDict["a2"]["trans"]
|
||||
# fig,ax = plt.subplots(3,2,6)
|
||||
ax[1,2].set_title("a_1 to a_2 trans [Replection]")
|
||||
ax[1,2].plot(dataDict["a1"]["wl"]*1e+6,Refl_21,linewidth=3)
|
||||
|
||||
ax2 = ax[2,2]
|
||||
Trans_dB = 10*np.log10(Refl_21)
|
||||
ax2.plot(dataDict["a1"]["wl"]*1e+6,Trans_dB,linewidth=3)
|
||||
|
||||
if (saveFlag):
|
||||
""" in CPU mode, there will be no folder """
|
||||
try:
|
||||
os.makedirs(simuPath + devName + "_simu\\")
|
||||
except:
|
||||
pass
|
||||
plt.savefig(simuPath + devName + "_simu\\"+devName+"_results.jpg", format='jpg', dpi=300)
|
||||
plt.close()
|
||||
|
||||
|
||||
data.close()
|
||||
|
||||
class DEVICE_PORTS:
|
||||
def __init__(self,dev_name,device,simu_xs="strip",
|
||||
port_width=3,path=None,wl=[1.5,1.6],
|
||||
mesh_order=5,layer_heights=[0.22],FDTD_height=2,
|
||||
material="Si (Silicon) - Palik",
|
||||
CladMaterial = "SiO2 (Glass) - Palik",
|
||||
modeIdx=[1,2,3,4],
|
||||
sourceMode = 1,
|
||||
ports_extend=["a1"],
|
||||
SimuBox = None,
|
||||
|
||||
port_radius={"a1":0},
|
||||
sample_points = 101,
|
||||
Field_sample = 3,
|
||||
|
||||
FDTDBuild = False,
|
||||
LumericalPATH = None,
|
||||
runFDTD = False,
|
||||
GPUOn = True,
|
||||
port_names = ["a1","b1","a2","b2"],
|
||||
) -> None:
|
||||
|
||||
|
||||
self.dev_name = dev_name
|
||||
|
||||
|
||||
time_curr = time.strftime('%Y%m%d-%H%M%S', time.localtime())
|
||||
""" creating folders """
|
||||
folder = __PathGenerate__(path=path,dev_name=dev_name)
|
||||
|
||||
if (isinstance(device,nd.Cell)):
|
||||
device = device
|
||||
elif (hasattr(device,"cell")):
|
||||
__LoggAllAttrs__(device=device,folder=folder,dev_name=dev_name)
|
||||
device = device.cell
|
||||
""" """
|
||||
else:
|
||||
raise Exception("Argument type not recongized")
|
||||
|
||||
if (dev_name == device.cell_name):
|
||||
|
||||
self.dev_name = dev_name + "_GDS"
|
||||
dev_name = self.dev_name
|
||||
|
||||
""" exporting GDS """
|
||||
fname = f"{dev_name}.gds"
|
||||
|
||||
with nd.Cell(name=dev_name) as CELL_INSTR:
|
||||
instr = device.put()
|
||||
instr.raise_pins()
|
||||
for name in ports_extend:
|
||||
if (device.pin[name].xs is None):
|
||||
_xs_extend_ = simu_xs
|
||||
else:
|
||||
_xs_extend_ = device.pin[name].xs
|
||||
|
||||
nd.strt(xs=_xs_extend_,length=port_width*2,width=device.pin[name].width).put(instr.pin[name])
|
||||
nd.text(layer=1001,text=time_curr,height=20).put()
|
||||
|
||||
nd.export_gds(filename=folder + fname,topcells=CELL_INSTR,flat=True)
|
||||
|
||||
|
||||
jsonFile = {}
|
||||
|
||||
jsonFile["ports"] = {}
|
||||
jsonFile["mont"] = {}
|
||||
jsonFile["input"] = {}
|
||||
jsonFile["layers"] = {}
|
||||
|
||||
jsonFile["ports"]["names"] = port_names
|
||||
|
||||
for name in jsonFile["ports"]["names"]:
|
||||
jsonFile["ports"][name] = PortParas(pin=CELL_INSTR.pin[name],width=port_width,height=FDTD_height)
|
||||
|
||||
# jsonFile["ports"]["a1"] = PortParas(pin=CELL_INSTR.pin['a1'],width=port_width,height=FDTD_height)
|
||||
# jsonFile["ports"]["a2"] = PortParas(pin=CELL_INSTR.pin['a2'],width=port_width,height=FDTD_height)
|
||||
# jsonFile["ports"]["b1"] = PortParas(pin=CELL_INSTR.pin['b1'],width=port_width,height=FDTD_height)
|
||||
# jsonFile["ports"]["b2"] = PortParas(pin=CELL_INSTR.pin['b2'],width=port_width,height=FDTD_height)
|
||||
|
||||
for key in port_radius:
|
||||
jsonFile["ports"][key]["radius"] = port_radius[key]
|
||||
|
||||
""" port Z for propagation recording """
|
||||
ports = jsonFile["ports"]
|
||||
dx = abs(ports["a1"]["x"] - ports["b1"]["x"])
|
||||
cX = (ports["a1"]["x"] + ports["b1"]["x"])/2
|
||||
|
||||
if ("b2" in jsonFile["ports"]["names"]):
|
||||
dy = abs(ports["b1"]["y"] - ports["b2"]["y"])
|
||||
cY = (ports["b1"]["y"] + ports["b2"]["y"])/2
|
||||
elif (SimuBox is not None):
|
||||
dy = SimuBox["dy"]
|
||||
cY = ports["b1"]["y"]
|
||||
else:
|
||||
dy = 0
|
||||
cY = ports["b1"]["y"]
|
||||
|
||||
|
||||
FDTD = {}
|
||||
FDTD["x"] = cX
|
||||
FDTD["y"] = cY
|
||||
|
||||
FDTD["dx"] = dx
|
||||
FDTD["dy"] = dy
|
||||
FDTD["z"] = 0
|
||||
|
||||
SimuBoxKeys = ["x","y","dx","dy"]
|
||||
if (SimuBox is not None):
|
||||
for key in SimuBoxKeys:
|
||||
if (key in SimuBox.keys()):
|
||||
# if ("dx" in SimuBox.keys()):
|
||||
FDTD[key] = SimuBox[key]
|
||||
# FDTD["dy"] = SimuBox["dy"]
|
||||
# if ("x" in SimuBox.keys()):
|
||||
# FDTD["x"] = SimuBox["x"]
|
||||
# FDTD["y"] = SimuBox["y"]
|
||||
|
||||
""" expansion """
|
||||
FDTD["dx"] = FDTD["dx"] + port_width
|
||||
FDTD["dy"] = FDTD["dy"] + port_width
|
||||
|
||||
FDTD["dz"] = FDTD_height
|
||||
FDTD["wl"] = wl
|
||||
FDTD["mesh_order"] = mesh_order
|
||||
FDTD["sourceMode"] = sourceMode
|
||||
if (GPUOn is True):
|
||||
FDTD["GPUOn"] = 1
|
||||
else:
|
||||
FDTD["GPUOn"] = 0
|
||||
|
||||
FDTD["Trans_sample_points"] = sample_points
|
||||
FDTD["Field_sample_points"] = Field_sample
|
||||
|
||||
jsonFile["mont"]["z1"] = MonitorParas(x=FDTD["x"],y=FDTD["y"],z=0,dx=FDTD["dx"],dy=FDTD["dy"],dz=0)
|
||||
|
||||
""" exporting json configure files """
|
||||
|
||||
jsonFile["FDTD"] = FDTD
|
||||
|
||||
jsonFile["wafer"] = {}
|
||||
jsonFile["wafer"]["material"] = material
|
||||
|
||||
jsonFile["clad"] = {}
|
||||
jsonFile["clad"]["material"] = CladMaterial
|
||||
|
||||
|
||||
jsonFile["time"] = time_curr
|
||||
|
||||
jsonFile["geometry"] = {}
|
||||
|
||||
jsonFile["modes"] = modeIdx
|
||||
|
||||
layerNumList = []
|
||||
layerDataTypeList = []
|
||||
growxList = []
|
||||
|
||||
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=simu_xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
|
||||
layerInfo = nd.get_layer_tuple(layers)
|
||||
|
||||
layerNumList.append(layerInfo.layer)
|
||||
layerDataTypeList.append(layerInfo.datatype)
|
||||
growxList.append(b1)
|
||||
|
||||
|
||||
if (len(layer_heights) != len(layerNumList)):
|
||||
raise Exception("Input wafer heigh list is not same length as layer numbers")
|
||||
|
||||
jsonFile["layers"]["numbers"] = layerNumList
|
||||
jsonFile["layers"]["datatype"] = layerDataTypeList
|
||||
jsonFile["layers"]["growth"] = growxList
|
||||
jsonFile["layers"]["heights"] = layer_heights
|
||||
|
||||
|
||||
|
||||
|
||||
""" """
|
||||
jsonPath = folder+f"{dev_name}.json"
|
||||
with open(jsonPath,"w") as FID:
|
||||
json.dump(jsonFile,FID)
|
||||
|
||||
jsonPath = os.path.abspath(jsonPath)
|
||||
jsonPath = jsonPath.replace('\\',"\\\\")
|
||||
self.jsonPath = jsonPath
|
||||
|
||||
|
||||
|
||||
|
||||
GDSPath = folder + fname
|
||||
GDSPath = os.path.abspath(GDSPath)
|
||||
GDSPath = GDSPath.replace('\\',"\\\\")
|
||||
self.GDSPath = GDSPath
|
||||
|
||||
FolderPath = folder
|
||||
FolderPath = os.path.abspath(FolderPath)
|
||||
FolderPath = FolderPath.replace('\\',"\\\\")
|
||||
self.FolderPath = FolderPath
|
||||
|
||||
""" writing instruction to Lumerical for operation """
|
||||
instPath = f"{self.FolderPath}\\Instruction.txt"
|
||||
|
||||
self.instPath = instPath
|
||||
|
||||
with open(file=instPath,mode="w") as FInst:
|
||||
FInst.write(f'devName = \"{self.dev_name}\";\n\r')
|
||||
FInst.write(f'gdspath = \"{self.GDSPath}\";\n\r')
|
||||
FInst.write(f'folder = \"{self.FolderPath}\";\n\r')
|
||||
FInst.write(f'jsonPath = \"{self.jsonPath}\";\n\r')
|
||||
|
||||
|
||||
|
||||
""" Internal Building FDTD """
|
||||
if (FDTDBuild):
|
||||
if (LumericalPATH is None):
|
||||
LuPATH = __checkLumericalDIR__()
|
||||
else:
|
||||
if (not os.path.exists(LumericalPATH)):
|
||||
raise Exception("No Lumerical installation found in the given paths")
|
||||
LuPATH = LumericalPATH
|
||||
|
||||
sys.path.append(LuPATH)
|
||||
# sys.path.append(os.path.dirname(__file__)) #Current directory
|
||||
|
||||
# print(sys.path)
|
||||
|
||||
import lumapi
|
||||
|
||||
fdtd = lumapi.FDTD()
|
||||
|
||||
""" constructing simulation files """
|
||||
print("Building FDTD project ... ")
|
||||
DEVICE_2X2_FDTD_INIT(fdtd=fdtd,run=runFDTD,LibPATH=__getLumericalLibPATH__(),instrcutPATH=self.instPath)
|
||||
print("... FDTD Project to ",self.FolderPath)
|
||||
|
||||
|
||||
fdtd.close()
|
||||
|
||||
if (runFDTD):
|
||||
SimuDataFigurePlot(simuPath=self.FolderPath,devName=self.dev_name,ports=port_names)
|
||||
self.resultPath = self.FolderPath + "\\" + self.dev_name + "_results.mat"
|
||||
|
||||
class DEVICE_RING_BUS(DEVICE_PORTS):
|
||||
def __init__(self, dev_name, device, r_ring,port_distance=6,Aport=None,
|
||||
simu_xs="strip", port_width=3,
|
||||
path=None, wl=[1.5, 1.6], mesh_order=5, layer_heights=[0.22],
|
||||
FDTD_height=2,
|
||||
material="Si (Silicon) - Palik",
|
||||
CladMaterial="SiO2 (Glass) - Palik",
|
||||
modeIdx=[1, 2, 3, 4],
|
||||
sample_points=101,
|
||||
FDTDBuild = False,
|
||||
LumericalPATH = None,
|
||||
GPUOn = True,
|
||||
runFDTD = False,) -> None:
|
||||
|
||||
|
||||
if (isinstance(device,nd.Cell)):
|
||||
cell_dev = device
|
||||
elif (hasattr(device,"cell")):
|
||||
cell_dev = device.cell
|
||||
else:
|
||||
raise Exception("ERROR :: <device> not recongized")
|
||||
|
||||
|
||||
dx = abs(cell_dev.pin["a1"].x - cell_dev.pin["b1"].x)+port_width
|
||||
|
||||
if (Aport is None):
|
||||
|
||||
if (cell_dev.pin['b1'].x > r_ring):
|
||||
cell_dev.pin['b2'] = nd.Pin(name="b2").put(r_ring,0, 90)
|
||||
cell_dev.pin['a2'] = nd.Pin(name="a2").put(-r_ring,0, 90)
|
||||
else:
|
||||
x = cell_dev.pin['b1'].x
|
||||
y = -np.sqrt(r_ring**2 - x**2)
|
||||
a = np.arcsin(x/r_ring)/np.pi*180
|
||||
dy_ports = abs(y-cell_dev.pin['b1'].y)
|
||||
|
||||
if (dy_ports > port_distance):
|
||||
|
||||
y = cell_dev.pin['b1'].y + port_distance
|
||||
x = np.sqrt(r_ring**2 - (abs(y))**2)
|
||||
a = np.arcsin(x/r_ring)/np.pi*180
|
||||
cell_dev.pin['b2'] = nd.Pin(name="b2").put( x,y, a)
|
||||
cell_dev.pin['a2'] = nd.Pin(name="a2").put(-x,y,180-a)
|
||||
|
||||
else :
|
||||
cell_dev.pin['b2'] = nd.Pin(name="b2").put( x,y, a)
|
||||
cell_dev.pin['a2'] = nd.Pin(name="a2").put(-x,y,180-a)
|
||||
|
||||
else :
|
||||
cell_dev.pin['b2'] = nd.Pin(name="b2").put( r_ring*np.sin(Aport/180*np.pi),-r_ring*np.cos(Aport/180*np.pi), Aport)
|
||||
cell_dev.pin['a2'] = nd.Pin(name="a2").put(-r_ring*np.sin(Aport/180*np.pi),-r_ring*np.cos(Aport/180*np.pi), Aport)
|
||||
|
||||
yMax = cell_dev.pin['b2'].y
|
||||
yMin = -r_ring - port_width
|
||||
|
||||
dy = abs(yMax - yMin)
|
||||
cy = (yMax + yMin)/2
|
||||
|
||||
if (isinstance(device,nd.Cell)):
|
||||
device = cell_dev
|
||||
elif (hasattr(device,"cell")):
|
||||
device.cell = cell_dev
|
||||
|
||||
|
||||
super().__init__(dev_name=dev_name, device=device, simu_xs=simu_xs, port_width=port_width, path=path, wl=wl,
|
||||
mesh_order=mesh_order, layer_heights=layer_heights,
|
||||
FDTD_height=FDTD_height, material=material, CladMaterial=CladMaterial,
|
||||
modeIdx=modeIdx, ports_extend=["a1","b1"], SimuBox = {"dx":dx,"dy":dy,"y":cy}, port_radius={"a2":r_ring,"b2":r_ring},
|
||||
sample_points=sample_points,FDTDBuild=FDTDBuild,LumericalPATH=LumericalPATH,runFDTD=runFDTD,
|
||||
GPUOn=GPUOn,
|
||||
port_names = ["a1","b1","a2","b2"],)
|
||||
|
||||
class DEVICE_COUPLER(DEVICE_PORTS):
|
||||
|
||||
def __init__(self, dev_name, device, simu_xs="strip", port_width=3, path=None,
|
||||
wl=[1.5, 1.6], mesh_order=5, layer_heights=[0.22], FDTD_height=2,
|
||||
material="Si (Silicon) - Palik", CladMaterial="SiO2 (Glass) - Palik",
|
||||
modeIdx=[1, 2, 3, 4],
|
||||
sample_points=101,
|
||||
sourceMode = 1,
|
||||
FDTDBuild = False,
|
||||
LumericalPATH = None,
|
||||
runFDTD = False,
|
||||
GPUOn = True,
|
||||
) -> None:
|
||||
|
||||
super().__init__(dev_name, device, simu_xs, port_width, path, wl, mesh_order,
|
||||
layer_heights, FDTD_height, material, CladMaterial, modeIdx, ports_extend=["a1","a2","b1","b2"],SimuBox=None,port_radius={},
|
||||
sample_points=sample_points,FDTDBuild=FDTDBuild,LumericalPATH=LumericalPATH,runFDTD=runFDTD,GPUOn=GPUOn,
|
||||
port_names = ["a1","b1","a2","b2"],sourceMode=sourceMode)
|
||||
|
||||
class EULER_CROW_INTER_CP(DEVICE_PORTS):
|
||||
def __init__(self, dev_name, device, simu_xs="strip",
|
||||
port_width=3, path=None, wl=[1.5, 1.6],
|
||||
mesh_order=5, layer_heights=[0.22],
|
||||
FDTD_height=2, material="Si (Silicon) - Palik",
|
||||
CladMaterial="SiO2 (Glass) - Palik",
|
||||
modeIdx=[1, 2, 3, 4],
|
||||
SimuBox=None,
|
||||
sample_points=101,
|
||||
FDTDBuild = False,
|
||||
LumericalPATH = None,
|
||||
GPUOn=True,
|
||||
runFDTD = False) -> None:
|
||||
|
||||
""" Device MUST Be CROW device """
|
||||
""" The pins reconized in here is ra1,ra2,ra3,ra4 and rb1,rb2,rb3,rb4 """
|
||||
|
||||
newDev = device
|
||||
newDev.cell.pin['a1'] = device.cell.pin['ra2']
|
||||
newDev.cell.pin['a2'] = device.cell.pin['rb2']
|
||||
newDev.cell.pin['b1'] = device.cell.pin['ra4']
|
||||
newDev.cell.pin['b2'] = device.cell.pin['rb4']
|
||||
|
||||
port_radius = {"a1":device.R1, "a2": device.R1, "b1":-device.R1, "b2":-device.R1}
|
||||
|
||||
super().__init__(dev_name, newDev, simu_xs, port_width, path, wl, mesh_order, layer_heights, FDTD_height, material, CladMaterial, modeIdx,
|
||||
ports_extend=[],
|
||||
SimuBox=SimuBox, port_radius=port_radius, sample_points=sample_points,
|
||||
FDTDBuild=FDTDBuild,LumericalPATH=LumericalPATH,runFDTD=runFDTD,port_names = ["a1","b1","a2","b2"],
|
||||
GPUOn=GPUOn)
|
||||
|
||||
class EULER_CROW_BUS(DEVICE_PORTS):
|
||||
def __init__(self, dev_name, device, simu_xs="strip",
|
||||
port_width=3, path=None, wl=[1.5, 1.6],
|
||||
mesh_order=5, layer_heights=[0.22],
|
||||
FDTD_height=2, material="Si (Silicon) - Palik",
|
||||
CladMaterial="SiO2 (Glass) - Palik",
|
||||
modeIdx=[1, 2, 3, 4],
|
||||
SimuBox=None,
|
||||
sample_points=101,
|
||||
FDTDBuild = False,
|
||||
LumericalPATH = None,
|
||||
GPUOn = True,
|
||||
runFDTD = False) -> None:
|
||||
|
||||
""" Device MUST Be CROW device """
|
||||
""" The pins reconized in here is ra1,ra2,ra3,ra4 and rb1,rb2,rb3,rb4 """
|
||||
|
||||
newDev = device
|
||||
# newDev.cell.pin['a1'] = device.cell.pin['ra2']
|
||||
newDev.cell.pin['a2'] = device.cell.pin['ra2']
|
||||
# newDev.cell.pin['b1'] = device.cell.pin['ra4']
|
||||
newDev.cell.pin['b2'] = device.cell.pin['ra4']
|
||||
|
||||
port_radius = {"a2": device.R1, "b2":-device.R1}
|
||||
|
||||
if (SimuBox is None):
|
||||
yMax = newDev.cell.pin['b2'].y
|
||||
yMin = newDev.cell.pin['b1'].y - newDev.ring_cell[0].sz[1]/2 - port_width/2
|
||||
|
||||
SimuBox = {}
|
||||
SimuBox["dy"] = yMax - yMin
|
||||
SimuBox["y"] = (yMax+yMin)/2
|
||||
|
||||
super().__init__(dev_name, newDev, simu_xs, port_width, path, wl, mesh_order, layer_heights, FDTD_height, material, CladMaterial, modeIdx,
|
||||
ports_extend=["a1","b1"],
|
||||
SimuBox=SimuBox, port_radius=port_radius, sample_points=sample_points,
|
||||
FDTDBuild=FDTDBuild,LumericalPATH=LumericalPATH,runFDTD=runFDTD,port_names = ["a1","b1","a2","b2"],
|
||||
GPUOn=GPUOn)
|
||||
|
||||
|
||||
class RESONATOR(DEVICE_PORTS):
|
||||
def __init__(self, dev_name, device,
|
||||
simu_xs="strip", port_width=3,
|
||||
path=None, wl=[1.5, 1.6],
|
||||
mesh_order=5, layer_heights=[0.22],
|
||||
FDTD_height=2, material="Si (Silicon) - Palik", CladMaterial="SiO2 (Glass) - Palik",
|
||||
modeIdx=[1, 2, 3, 4],
|
||||
ports_extend=["a1"],
|
||||
sample_points=10001,
|
||||
SimuBox=None,
|
||||
FDTDBuild = False,
|
||||
LumericalPATH = None,
|
||||
runFDTD = False) -> None:
|
||||
super().__init__(dev_name, device, simu_xs, port_width, path, wl, mesh_order, layer_heights, FDTD_height, material, CladMaterial,
|
||||
modeIdx, ports_extend=["a1","a2","b1","b2"], SimuBox=SimuBox, port_radius=[], sample_points=sample_points,
|
||||
FDTDBuild=FDTDBuild,LumericalPATH=LumericalPATH,runFDTD=runFDTD,port_names = ["a1","b1","a2","b2"],)
|
||||
|
||||
class RING_PHASE(DEVICE_PORTS):
|
||||
def __init__(self, dev_name, device, simu_xs="strip",
|
||||
port_width=3, path=None, wl=[1.5, 1.6],
|
||||
mesh_order=5, layer_heights=[0.22],
|
||||
FDTD_height=2,
|
||||
material="Si (Silicon) - Palik",
|
||||
CladMaterial="SiO2 (Glass) - Palik",
|
||||
modeIdx=[1, 2, 3, 4],
|
||||
SimuBox=None,
|
||||
port_radius={ "a1": 0 },
|
||||
sample_points=101,
|
||||
FDTDBuild=False,
|
||||
LumericalPATH=None,
|
||||
runFDTD=False,
|
||||
GPUOn = True,
|
||||
) -> None:
|
||||
|
||||
|
||||
if (hasattr(device,"cell")):
|
||||
dev_cell = device.cell
|
||||
|
||||
|
||||
elif (isinstance(device,nd.Cell)):
|
||||
dev_cell = device
|
||||
|
||||
dev_cell.pin['a1'] = dev_cell.pin['r1']
|
||||
dev_cell.pin['b1'] = dev_cell.pin['r3']
|
||||
|
||||
|
||||
dy = abs(dev_cell.pin['a1'].y - dev_cell.pin['b1'].y )
|
||||
|
||||
cy = (dev_cell.pin['a1'].y + dev_cell.pin['b1'].y)/2
|
||||
if (SimuBox is None):
|
||||
SimuBox = {}
|
||||
SimuBox["dy"] = dy
|
||||
SimuBox["y"] = cy
|
||||
|
||||
if (hasattr(device,"sz")):
|
||||
SimuBox["dx"] = device.sz[0]/2
|
||||
SimuBox["x"] = -device.sz[0]/4
|
||||
# SimuBox["dx"] = dx
|
||||
|
||||
|
||||
super().__init__(dev_name, dev_cell, simu_xs, port_width, path, wl, mesh_order, layer_heights,
|
||||
FDTD_height, material, CladMaterial, modeIdx, ports_extend=[],
|
||||
SimuBox=SimuBox, port_radius=port_radius, sample_points=sample_points,
|
||||
FDTDBuild=FDTDBuild, LumericalPATH=LumericalPATH, runFDTD=runFDTD, port_names=["a1","b1"],
|
||||
GPUOn = GPUOn)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user