import numpy as np
import gdsfactory as gf
@gf.cell
def coupler_bent_half(
gap: float = 0.200,
radius: float = 26,
length: float = 8.6,
width1: float = 0.400,
width2: float = 0.400,
length_straight: float = 10,
cross_section: str = "xs_sc",
) -> gf.Component:
"""Returns Broadband SOI curved / straight directional coupler.
Args:
gap: gap.
radius: radius coupling.
length: coupler_length.
width1: width1.
width2: width2.
length_straight: input and output straight length.
cross_section: cross_section.
"""
R1 = radius + (width1 + gap) / 2
R2 = radius - (width2 + gap) / 2
alpha = round(np.rad2deg(length / (2 * radius)), 4)
beta = alpha
c = gf.Component()
xs = gf.get_cross_section(cross_section)
xs1 = xs.copy(radius=R1, width=width1)
xs2 = xs.copy(radius=R2, width=width2)
outer_bend = c << gf.components.bend_circular(
angle=np.round(-alpha, 3),
cross_section=xs1,
)
inner_bend = c << gf.components.bend_circular(
angle=-alpha,
cross_section=xs2,
)
outer_bend.movey(+(width1 + gap) / 2)
inner_bend.movey(-(width2 + gap) / 2)
outer_straight = c << gf.components.straight(
length=length,
cross_section=xs1,
npoints=100,
)
inner_straight = c << gf.components.straight(
length=length,
cross_section=xs2,
npoints=100,
)
outer_straight.connect(port="o1", destination=outer_bend.ports["o2"])
inner_straight.connect(port="o1", destination=inner_bend.ports["o2"])
outer_exit_bend = c << gf.components.bend_circular(
angle=alpha,
cross_section=xs1,
)
inner_exit_bend_down = c << gf.components.bend_circular(
angle=-beta,
cross_section=xs2,
)
inner_exit_bend_up = c << gf.components.bend_circular(
angle=alpha + beta,
cross_section=xs2,
)
outer_exit_bend.connect(port="o1", destination=outer_straight.ports["o2"])
inner_exit_bend_down.connect(port="o1", destination=inner_straight.ports["o2"])
inner_exit_bend_up.connect(port="o1", destination=inner_exit_bend_down.ports["o2"])
inner_exit_straight = c << gf.components.straight(
length=length_straight,
cross_section=gf.cross_section.cross_section(width=width2),
npoints=100,
)
inner_exit_straight.connect(port="o1", destination=inner_exit_bend_up.ports["o2"])
outer_exit_straight = c << gf.components.straight(
length=abs(inner_exit_straight.ports["o2"].x - outer_exit_bend.ports["o2"].x),
cross_section=gf.cross_section.cross_section(width=width1),
npoints=100,
)
outer_exit_straight.connect(port="o1", destination=outer_exit_bend.ports["o2"])
c.add_port("o1", port=outer_bend.ports["o1"])
c.add_port("o2", port=inner_bend.ports["o1"])
c.add_port("o3", port=outer_exit_straight.ports["o2"])
c.add_port("o4", port=inner_exit_straight.ports["o2"])
c.absorb(outer_exit_bend)
c.absorb(inner_exit_bend_down)
c.absorb(inner_exit_bend_up)
return c.flatten()
[docs]
@gf.cell
def coupler_bent(
gap: float = 0.200,
radius: float = 26,
length: float = 8.6,
width1: float = 0.400,
width2: float = 0.400,
length_straight: float = 10,
cross_section: str = "xs_sc",
) -> gf.Component:
"""Returns Broadband SOI curved / straight directional coupler.
based on: https://doi.org/10.1038/s41598-017-07618-6
Args:
gap: gap.
radius: radius coupling.
length: coupler_length.
width1: width1.
width2: width2.
length_straight: input and output straight length.
cross_section: cross_section.
"""
c = gf.Component()
right_half = c << coupler_bent_half(
gap=gap,
radius=radius,
length=length,
width1=width1,
width2=width2,
length_straight=length_straight,
cross_section=cross_section,
)
left_half = c << coupler_bent_half(
gap=gap,
radius=radius,
length=length,
width1=width1,
width2=width2,
length_straight=length_straight,
cross_section=cross_section,
)
left_half.mirror_x()
left_half.connect(port="o1", destination=right_half.ports["o1"])
c = c.flatten()
c.add_port("o1", port=left_half.ports["o3"])
c.add_port("o2", port=left_half.ports["o4"])
c.add_port("o3", port=right_half.ports["o3"])
c.add_port("o4", port=right_half.ports["o4"])
return c
if __name__ == "__main__":
# c = coupler_bent_half()
c = coupler_bent(cross_section="xs_rc")
c.show(show_ports=False)