Files
mxpic_forge/mxpic/components/others/simulation/DualPortElements.py
T
2026-06-04 23:21:39 +08:00

735 lines
28 KiB
Python

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 Any, Literal, Optional
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: str,device: Any,simu_xs: str="strip",
port_width: int=3,path: Optional[str]=None,wl: list=[1.5,1.6],
mesh_order: int=5,layer_heights: list=[0.22],FDTD_height: int=2,
material: str="Si (Silicon) - Palik",
CladMaterial: str = "SiO2 (Glass) - Palik",
modeIdx: list=[1,2,3,4],
sourceMode: int = 1,
ports_extend: list=["a1"],
SimuBox: Any = None,
port_radius: dict={"a1":0},
sample_points: int = 101,
Field_sample: int = 3,
FDTDBuild: bool = False,
LumericalPATH: Any = None,
runFDTD: bool = False,
GPUOn: bool = True,
port_names: list = ["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: str, device: Any, r_ring: float,port_distance: int=6,Aport: Any=None,
simu_xs: str="strip", port_width: int=3,
path: Optional[str]=None, wl: list=[1.5, 1.6], mesh_order: int=5, layer_heights: list=[0.22],
FDTD_height: int=2,
material: str="Si (Silicon) - Palik",
CladMaterial: str="SiO2 (Glass) - Palik",
modeIdx: list=[1, 2, 3, 4],
sample_points: int=101,
FDTDBuild: bool = False,
LumericalPATH: Any = None,
GPUOn: bool = True,
runFDTD: bool = 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: str, device: Any, simu_xs: str="strip", port_width: int=3, path: Optional[str]=None,
wl: list=[1.5, 1.6], mesh_order: int=5, layer_heights: list=[0.22], FDTD_height: int=2,
material: str="Si (Silicon) - Palik", CladMaterial: str="SiO2 (Glass) - Palik",
modeIdx: list=[1, 2, 3, 4],
sample_points: int=101,
sourceMode: int = 1,
FDTDBuild: bool = False,
LumericalPATH: Any = None,
runFDTD: bool = False,
GPUOn: bool = 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: str, device: Any, simu_xs: str="strip",
port_width: int=3, path: Optional[str]=None, wl: list=[1.5, 1.6],
mesh_order: int=5, layer_heights: list=[0.22],
FDTD_height: int=2, material: str="Si (Silicon) - Palik",
CladMaterial: str="SiO2 (Glass) - Palik",
modeIdx: list=[1, 2, 3, 4],
SimuBox: Any=None,
sample_points: int=101,
FDTDBuild: bool = False,
LumericalPATH: Any = None,
GPUOn: bool=True,
runFDTD: bool = 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: str, device: Any, simu_xs: str="strip",
port_width: int=3, path: Optional[str]=None, wl: list=[1.5, 1.6],
mesh_order: int=5, layer_heights: list=[0.22],
FDTD_height: int=2, material: str="Si (Silicon) - Palik",
CladMaterial: str="SiO2 (Glass) - Palik",
modeIdx: list=[1, 2, 3, 4],
SimuBox: Any=None,
sample_points: int=101,
FDTDBuild: bool = False,
LumericalPATH: Any = None,
GPUOn: bool = True,
runFDTD: bool = 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: str, device: Any,
simu_xs: str="strip", port_width: int=3,
path: Optional[str]=None, wl: list=[1.5, 1.6],
mesh_order: int=5, layer_heights: list=[0.22],
FDTD_height: int=2, material: str="Si (Silicon) - Palik", CladMaterial: str="SiO2 (Glass) - Palik",
modeIdx: list=[1, 2, 3, 4],
ports_extend: list=["a1"],
sample_points: int=10001,
SimuBox: Any=None,
FDTDBuild: bool = False,
LumericalPATH: Any = None,
runFDTD: bool = 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: str, device: Any, simu_xs: str="strip",
port_width: int=3, path: Optional[str]=None, wl: list=[1.5, 1.6],
mesh_order: int=5, layer_heights: list=[0.22],
FDTD_height: int=2,
material: str="Si (Silicon) - Palik",
CladMaterial: str="SiO2 (Glass) - Palik",
modeIdx: list=[1, 2, 3, 4],
SimuBox: Any=None,
port_radius: dict={ "a1": 0 },
sample_points: int=101,
FDTDBuild: bool=False,
LumericalPATH: Any=None,
runFDTD: bool=False,
GPUOn: bool = 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)