Source code for gdsfactory.components.bend_s
from __future__ import annotations
import copy
import numpy as np
import gdsfactory as gf
from gdsfactory.cell import cell
from gdsfactory.component import Component
from gdsfactory.components.bezier import bezier
from gdsfactory.config import ErrorType
from gdsfactory.typings import CrossSectionSpec, Float2
[docs]
@cell
def bend_s(
size: Float2 = (11.0, 1.8),
npoints: int = 99,
cross_section: CrossSectionSpec = "xs_sc",
**kwargs,
) -> Component:
"""Return S bend with bezier curve.
stores min_bend_radius property in self.info['min_bend_radius']
min_bend_radius depends on height and length
Args:
size: in x and y direction.
npoints: number of points.
cross_section: spec.
add_pins: add pins to the component.
Keyword Args:
with_manhattan_facing_angles: bool.
start_angle: optional start angle in deg.
end_angle: optional end angle in deg.
"""
c = Component()
dx, dy = size
bend = bezier(
control_points=((0, 0), (dx / 2, 0), (dx / 2, dy), (dx, dy)),
npoints=npoints,
cross_section=cross_section,
**kwargs,
)
bend_ref = c << bend
c.add_ports(bend_ref.ports)
c.copy_child_info(bend)
return c
def get_min_sbend_size(
size: tuple[float | None, float | None] = (None, 10.0),
cross_section: CrossSectionSpec = "xs_sc",
num_points: int = 100,
**kwargs,
) -> float:
"""
Returns the minimum sbend size to comply with bend radius requirements.
Args:
size: in x and y direction. One of them is None, which is the size we need to figure out.
cross_section: spec.
num_points: number of points to iterate over between max_size and 0.1 * max_size
kwargs: cross_section settings.
"""
cross_section_f = gf.get_cross_section(cross_section, **kwargs)
if size[0] is None:
ind = 0
known_s = size[1]
elif size[1] is None:
ind = 1
known_s = size[0]
else:
raise ValueError("One of the two elements in size has to be None")
min_radius = cross_section_f.radius_min or cross_section_f.radius
if min_radius is None:
raise ValueError("The min radius for the specified layer is not known!")
min_size = np.inf
# Guess sizes, iterate over them until we cannot achieve the min radius
# the max size corresponds to an ellipsoid
max_size = 2.5 * np.sqrt(np.abs(min_radius * known_s))
sizes = np.linspace(max_size, 0.1 * max_size, num_points)
for i, s in enumerate(sizes):
sz = copy.deepcopy(size)
sz[ind] = s
# print(sz)
try:
bend_s(
size=sz,
cross_section=cross_section,
bend_radius_error_type=ErrorType.ERROR,
**kwargs,
)
# print(c.info['min_bend_radius'])
min_size = sizes[i]
except ValueError:
break
return min_size
if __name__ == "__main__":
c = bend_s(size=(10, 2.5))
# c = bend_s(bbox_offsets=[0.5], bbox_layers=[(111, 0)], width=2)
# c = bend_s(size=[10, 2.5]) # 10um bend radius
# c = bend_s(size=[20, 3], cross_section="xs_rc") # 10um bend radius
# c.pprint()
# c = bend_s_biased()
# print(c.info["min_bend_radius"])
c.show(show_ports=False)