Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add grating_coupler_elliptical uniform #668

Merged
merged 1 commit into from Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@

- generate KLayout technology files (.lyp) from the gdsfactory LayerColors, add structures that let you write (almost) all of the properties that .lyp files can take, including groups of layer properties. [PR](https://github.com/gdsfactory/gdsfactory/pull/662)
- via_stack has `port_type=placement` for intermediate ports and compass has default `port_type=placement` [PR](https://github.com/gdsfactory/gdsfactory/pull/661)
- get_netlist ignores ports with port_type='placement' [PR](https://github.com/gdsfactory/gdsfactory/pull/666)
- move gdsfactory.copy to Component.copy [PR](https://github.com/gdsfactory/gdsfactory/pull/660)
- clean install.py [PR](https://github.com/gdsfactory/gdsfactory/pull/657)
- Fix a bug where calling make_symlink on an already-existing install would raise an error
Expand Down
21 changes: 18 additions & 3 deletions docs/components.rst
Expand Up @@ -467,7 +467,7 @@ compass

import gdsfactory as gf

c = gf.components.compass(size=[4.0, 2.0], layer='WG', port_type='electrical', port_inclusion=0.0, port_orientations=[180, 90, 0, -90])
c = gf.components.compass(size=[4.0, 2.0], layer='WG', port_type='placement', port_inclusion=0.0, port_orientations=[180, 90, 0, -90])
c.plot()


Expand Down Expand Up @@ -1265,6 +1265,21 @@ grating_coupler_elliptical_trenches



grating_coupler_elliptical_uniform
----------------------------------------------------

.. autofunction:: gdsfactory.components.grating_coupler_elliptical_uniform

.. plot::
:include-source:

import gdsfactory as gf

c = gf.components.grating_coupler_elliptical_uniform(n_periods=20, period=0.75, fill_factor=0.5)
c.plot()



grating_coupler_loss_fiber_array
----------------------------------------------------

Expand Down Expand Up @@ -1980,7 +1995,7 @@ rectangle

import gdsfactory as gf

c = gf.components.rectangle(size=[4.0, 2.0], layer='WG', centered=False, port_type='electrical', port_orientations=[180, 90, 0, -90])
c = gf.components.rectangle(size=[4.0, 2.0], layer='WG', centered=False, port_type='placement', port_orientations=[180, 90, 0, -90])
c.plot()


Expand Down Expand Up @@ -2805,7 +2820,7 @@ version_stamp

import gdsfactory as gf

c = gf.components.version_stamp(labels=['demo_label'], with_qr_code=False, layer='WG', pixel_size=1, version='5.20.0', text_size=10)
c = gf.components.version_stamp(labels=['demo_label'], with_qr_code=False, layer='WG', pixel_size=1, version='5.25.1', text_size=10)
c.plot()


Expand Down
19 changes: 11 additions & 8 deletions fixme/netlist_hierarchical.py
Expand Up @@ -38,12 +38,13 @@ def mmi2x2(*, coupling: float = 0.5) -> sax.SDict:
)


def bend_euler(wl=1.5, length=20.0) -> sax.SDict:
"""Returns bend Sparameters with reduced transmission compared to a straight."""
return {k: 0.99 * v for k, v in straight(wl=wl, length=length).items()}
def bend_euler(wl: float = 1.5, length: float = 20.0, loss: float = 50e-3) -> sax.SDict:
"""Returns bend Sparameters."""
amplitude = jnp.asarray(10 ** (-loss * length / 20), dtype=complex)
return {k: amplitude * v for k, v in straight(wl=wl, length=length).items()}


def phase_shifter_heater(
def phase_shifter(
wl: float = 1.55,
neff: float = 2.34,
voltage: float = 0,
Expand Down Expand Up @@ -77,15 +78,17 @@ def phase_shifter_heater(
"mmi2x2": mmi2x2,
"straight": straight,
"taper": straight,
"straight_heater_metal_undercut": phase_shifter_heater,
"straight_heater_metal_undercut": phase_shifter,
}


if __name__ == "__main__":
c = gf.components.switch_tree(bend_s=None)
n = c.get_netlist_recursive()

netlist = c.get_netlist_recursive(exclude_port_types=("electrical", "placement"))
c.show(show_ports=True)
n = netlist = c.get_netlist_recursive(
exclude_port_types=("electrical", "placement")
)
# netlist.pop(list(n.keys())[0])
mzi_circuit, _ = sax.circuit(netlist=netlist, models=models)
S = mzi_circuit(wl=1.55)
wl = np.linspace(1.5, 1.6, 256)
Expand Down
2 changes: 2 additions & 0 deletions gdsfactory/components/__init__.py
Expand Up @@ -103,6 +103,7 @@
)
from gdsfactory.components.grating_coupler_elliptical_arbitrary import (
grating_coupler_elliptical_arbitrary,
grating_coupler_elliptical_uniform,
)
from gdsfactory.components.grating_coupler_elliptical_lumerical import (
grating_coupler_elliptical_lumerical,
Expand Down Expand Up @@ -365,6 +366,7 @@
"grating_coupler_array",
"grating_coupler_elliptical",
"grating_coupler_elliptical_arbitrary",
"grating_coupler_elliptical_uniform",
"grating_coupler_elliptical_lumerical",
"grating_coupler_elliptical_te",
"grating_coupler_elliptical_tm",
Expand Down
60 changes: 57 additions & 3 deletions gdsfactory/components/grating_coupler_elliptical_arbitrary.py
Expand Up @@ -45,8 +45,8 @@ def grating_coupler_elliptical_arbitrary(
taper_angle: grating flare angle.
wavelength: grating transmission central wavelength (um).
fiber_angle: fibre angle in degrees determines ellipticity.
neff: tooth effective index.
nclad: cladding effective index.
neff: tooth effective index to compute ellipticity.
nclad: cladding effective index to compute ellipticity.
layer_slab: Optional slab.
slab_xmin: where 0 is at the start of the taper.
polarization: te or tm.
Expand Down Expand Up @@ -168,8 +168,62 @@ def grating_coupler_elliptical_arbitrary(
return c


@gf.cell
def grating_coupler_elliptical_uniform(
n_periods: int = 20,
period: float = 0.75,
fill_factor: float = 0.5,
**kwargs,
) -> Component:
r"""Grating coupler with parametrization based on Lumerical FDTD simulation.

The ellipticity is derived from Lumerical knowdledge base
it depends on fiber_angle (degrees), neff, and nclad

Args:
n_periods: number of grating periods.
period: grating pitch in um.
fill_factor: ratio of grating width vs gap.

Keyword Args:
taper_length: taper length from input.
taper_angle: grating flare angle.
wavelength: grating transmission central wavelength (um).
fiber_angle: fibre angle in degrees determines ellipticity.
neff: tooth effective index to compute ellipticity.
nclad: cladding effective index to compute ellipticity.
layer_slab: Optional slab.
slab_xmin: where 0 is at the start of the taper.
polarization: te or tm.
fiber_marker_width: in um.
fiber_marker_layer: Optional marker.
spiked: grating teeth have spikes to avoid drc errors..
bias_gap: etch gap (um).
Positive bias increases gap and reduces width to keep period constant.
cross_section: cross_section spec for waveguide port.
kwargs: cross_section settings.


.. code::

fiber

/ / / /
/ / / /

_|-|_|-|_|-|___ layer
layer_slab |
o1 ______________|

"""
widths = [period * fill_factor] * n_periods
gaps = [period * (1 - fill_factor)] * n_periods
return grating_coupler_elliptical_arbitrary(gaps=gaps, widths=widths, **kwargs)


if __name__ == "__main__":
c = grating_coupler_elliptical_arbitrary()
# c = grating_coupler_elliptical_arbitrary()
c = grating_coupler_elliptical_uniform(n_periods=3, fill_factor=0.1)
# c = grating_coupler_elliptical_arbitrary(fiber_angle=8, bias_gap=-0.05)
# c = gf.routing.add_fiber_array(grating_coupler=grating_coupler_elliptical_arbitrary)
c.show(show_ports=True)
75 changes: 75 additions & 0 deletions gdsfactory/simulation/sax/models.py
Expand Up @@ -45,6 +45,12 @@ def straight(
)


def bend(wl: float = 1.5, length: float = 20.0, loss: float = 0.0) -> SDict:
"""Returns bend Sparameters."""
amplitude = jnp.asarray(10 ** (-loss * length / 20), dtype=complex)
return {k: amplitude * v for k, v in straight(wl=wl, length=length).items()}


def attenuator(*, loss: float = 0.0) -> SDict:
"""Attenuator model.

Expand All @@ -67,6 +73,34 @@ def attenuator(*, loss: float = 0.0) -> SDict:
)


def phase_shifter(
wl: float = 1.55,
neff: float = 2.34,
voltage: float = 0,
length: float = 10,
loss: float = 0.0,
) -> SDict:
"""Returns simple phase shifter model.

Args:
wl: wavelength in um.
neff: effective index.
voltage: voltage per PI phase shift.
length: in um.
loss: in dB.
"""
deltaphi = voltage * jnp.pi
phase = 2 * jnp.pi * neff * length / wl + deltaphi
amplitude = jnp.asarray(10 ** (-loss * length / 20), dtype=complex)
transmission = amplitude * jnp.exp(1j * phase)
sdict = reciprocal(
{
("o1", "o2"): transmission,
}
)
return sdict


def grating_coupler(
*,
wl: float = 1.55,
Expand Down Expand Up @@ -207,6 +241,47 @@ def coupler_single_wavelength(*, coupling: float = 0.5) -> SDict:
)


def mmi1x2() -> SDict:
"""Returns an ideal 1x2 splitter."""
return reciprocal(
{
("o1", "o2"): 0.5**0.5,
("o1", "o3"): 0.5**0.5,
}
)


def mmi2x2(*, coupling: float = 0.5) -> SDict:
"""Returns an ideal 2x2 splitter.

Args:
coupling: power coupling coefficient.
"""
kappa = coupling**0.5
tau = (1 - coupling) ** 0.5
return reciprocal(
{
("o1", "o4"): tau,
("o1", "o3"): 1j * kappa,
("o2", "o4"): 1j * kappa,
("o2", "o3"): tau,
}
)


models = dict(
straight=straight,
bend_euler=bend,
mmi1x2=mmi1x2,
mmi2x2=mmi2x2,
attenuator=attenuator,
taper=straight,
phase_shifter=phase_shifter,
grating_coupler=grating_coupler,
coupler=coupler,
)


if __name__ == "__main__":
import gdsfactory.simulation.sax as gs

Expand Down
@@ -0,0 +1,20 @@
name: grating_coupler_ellipti_6ff6af5d
settings:
changed: {}
child: null
default:
fill_factor: 0.5
n_periods: 20
period: 0.75
full:
fill_factor: 0.5
n_periods: 20
period: 0.75
function_name: grating_coupler_elliptical_uniform
info:
polarization: te
wavelength: 1.554
info_version: 2
module: gdsfactory.components.grating_coupler_elliptical_arbitrary
name: grating_coupler_ellipti_6ff6af5d
version: 0.0.1