waveguide factory.py
This script mainly provides a more intelligent solution for implementing port acquisition and bend routing in automatic waveguide routing. The main components are
Straight
Define class StraightFactory
@dataclass(frozen=True)
class StraightFactory(fpt.IStraightWaveguideFactory):
def __call__(self, type: fpt.IWaveguideType, length: float):
from gpdk.components.straight.straight import Straight
straight = Straight(length=length, waveguide_type=type)
return straight, ("op_0", "op_1")
Returns straight waveguide in gpdk > components > straight > Straight and port information to provide support for port connections during automatic routing.
CircularBend
Define class CircularBendFactory:
@dataclass(frozen=True)
class CircularBendFactory(fpt.IBendWaveguideFactory):
radius_eff: float
waveguide_type: fpt.IWaveguideType = field(repr=False, compare=False)
def __call__(self, central_angle: float):
from gpdk.components.bend.bend_circular import BendCircular, BendCircular90_FWG_C_WIRE, BendCircular90_FWG_C_EXPANDED
from gpdk.technology import get_technology
TECH = get_technology()
radius_eff = self.radius_eff
bend = None
if fp.is_close(abs(central_angle), math.pi / 2):
if self.waveguide_type == TECH.WG.FWG.C.WIRE:
bend = BendCircular90_FWG_C_WIRE()
elif self.waveguide_type == TECH.WG.FWG.C.EXPANDED:
bend = BendCircular90_FWG_C_EXPANDED()
if bend and central_angle < 0:
bend = bend.v_mirrored()
if bend is None:
bend = BendCircular(degrees=math.degrees(central_angle), radius=radius_eff, waveguide_type=self.waveguide_type)
return bend, radius_eff, ("op_0", "op_1")
The parameters of the CircularBendFactory that can be set optionally are
radius_eff
waveguide_type
There are two options to apply this bend factory to waveguide routing.
Assign
CircularBendFactory(waveguide_type=waveguide_type, radius_eff=radius_eff)to the parameterbend_factoryin the routing function e.g.,Linked,create_linksandLinkBetween.Implement
CircularBendFactoryto each waveguide class (please see wg.py) and setTECH.WG.FWG.C.WIRE.BEND_CIRCULARonce you’ve returnCircularBendFactorytoBEND_CIRCULARunder the classWG.FWG.C.WIRE.
By giving a certain condition (certain waveguide type and certain bending angle, TECH.WG.FWG.C.WIRE and 90 degree bend for example), users are allowed to assign a fixed bend (either a GDS import cell or fixed cell) to this waveguide type.
This means that when the bend angle is 90 degree and the waveguide type of two connected ports are also FWG.C.WIRE, BendCircular90_FWG_C_WIRE will be automatically use.
Implementation
There are two ways to implement waveguide_factory for further use, one is to set it as default for every waveguide type, and another is to define a waveguide_factory by themselves and use it for auto-routing.
Set as default in
wg.pyHere we use the class named
CircularBendFactorywhich we just defined. You can setradius_effparameter to a value according to the technical specifications. We recommend that implementingbend_factoryfor everywaveguide_typethat you created so that you can set up several types ofbend_factoryas units in routing function.straight_factoryandbend_factoryare defined inwg.pyto automatically use the PCell ofstraightandbendin the routing.class WG: class FWG: class C(FWG_C): @fpt.staticconst def WIRE(): class WIRE(__class__): core_design_width: float = FWG_C_WIRE_WIDTH cladding_design_width: float = FWG_C_WIRE_WIDTH + FWG_C_TRENCH_WIDTH * 2 @fpt.const_property def bend_factory(self): return self.BEND_EULER @fpt.const_property def BEND_CIRCULAR(self): return CircularBendFactory(radius_eff=self.cladding_width / 2 + 1, waveguide_type=self) @fpt.const_property def BEND_EULER(self): return EulerBendFactory(radius_min=self.cladding_width / 2 + 1, l_max=5, waveguide_type=self) return WIRE()
Manually define
bend_factoryBelow scripts show how to generate a user-defined
bend_factory.@dataclass(frozen=True) class user_defined_bendfactory(fpt.IBendWaveguideFactory): radius_eff: float waveguide_type: fpt.IWaveguideType = field(repr=False, compare=False) def __call__(self, central_angle: float): from gpdk.components.bend.bend_circular import BendCircular radius_eff = self.radius_eff bend = BendCircular(degrees=math.degrees(central_angle), radius=radius_eff, waveguide_type=self.waveguide_type) return bend, radius_eff, ("op_0", "op_1") user_defined_bend_factory = user_defined_bendfactory(radius_eff=10, waveguide_type=TECH.WG.SWG.C.WIRE)
Then users can decide to use the defined
user_defined_bendfactoryin the link function or they can simply enterTECH.WG.FWG.C.WIRE.BEND_CIRCULARif they defineBEND_CIRCULARandBEND_EULERunderTECH.WG.FWG.C.WIRE. The choose of use depends entirely on the user’s consideration of the performance of the device:link1 = fp.create_links( link_type=TECH.WG.FWG.C.EXPANDED, # bend_factory=TECH.WG.FWG.C.WIRE.BEND_CIRCULAR, bend_factory=user_defined_bend_factory, specs=[ wg1["op_0"] >> wg2["op_1"], wg1["op_1"] >> wg3["op_1"], ], )