lnoi400 2.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. lnoi400-2.1.1/LICENSE +21 -0
  2. lnoi400-2.1.1/PKG-INFO +218 -0
  3. lnoi400-2.1.1/README.md +166 -0
  4. lnoi400-2.1.1/_utils/__init__.py +0 -0
  5. lnoi400-2.1.1/_utils/bends.py +109 -0
  6. lnoi400-2.1.1/_utils/cell_info.py +17 -0
  7. lnoi400-2.1.1/_utils/chip_floorplan.py +66 -0
  8. lnoi400-2.1.1/_utils/cross_section.py +316 -0
  9. lnoi400-2.1.1/_utils/edge_couplers.py +169 -0
  10. lnoi400-2.1.1/_utils/grating_couplers.py +126 -0
  11. lnoi400-2.1.1/_utils/gsg_rf.py +1429 -0
  12. lnoi400-2.1.1/_utils/models.py +214 -0
  13. lnoi400-2.1.1/_utils/mzm.py +495 -0
  14. lnoi400-2.1.1/_utils/optical_resonators.py +182 -0
  15. lnoi400-2.1.1/_utils/spline.py +151 -0
  16. lnoi400-2.1.1/_utils/thermal_phase_shifters.py +292 -0
  17. lnoi400-2.1.1/lnoi400/__init__.py +56 -0
  18. lnoi400-2.1.1/lnoi400/_builders/grating_couplers.py +49 -0
  19. lnoi400-2.1.1/lnoi400/cells.py +1788 -0
  20. lnoi400-2.1.1/lnoi400/config.py +23 -0
  21. lnoi400-2.1.1/lnoi400/layers.yaml +27 -0
  22. lnoi400-2.1.1/lnoi400/models.py +325 -0
  23. lnoi400-2.1.1/lnoi400/mzm_with_pads.py +159 -0
  24. lnoi400-2.1.1/lnoi400/tech.py +320 -0
  25. lnoi400-2.1.1/lnoi400.egg-info/PKG-INFO +218 -0
  26. lnoi400-2.1.1/lnoi400.egg-info/SOURCES.txt +44 -0
  27. lnoi400-2.1.1/lnoi400.egg-info/dependency_links.txt +1 -0
  28. lnoi400-2.1.1/lnoi400.egg-info/requires.txt +18 -0
  29. lnoi400-2.1.1/lnoi400.egg-info/top_level.txt +6 -0
  30. lnoi400-2.1.1/ltoi300/__init__.py +57 -0
  31. lnoi400-2.1.1/ltoi300/_builders/edge_couplers.py +49 -0
  32. lnoi400-2.1.1/ltoi300/_builders/mmis.py +116 -0
  33. lnoi400-2.1.1/ltoi300/_builders/mzms.py +463 -0
  34. lnoi400-2.1.1/ltoi300/_builders/phase_modulators.py +474 -0
  35. lnoi400-2.1.1/ltoi300/_builders/straights.py +42 -0
  36. lnoi400-2.1.1/ltoi300/cells.py +835 -0
  37. lnoi400-2.1.1/ltoi300/config.py +23 -0
  38. lnoi400-2.1.1/ltoi300/layers.yaml +35 -0
  39. lnoi400-2.1.1/ltoi300/models.py +701 -0
  40. lnoi400-2.1.1/ltoi300/tech.py +276 -0
  41. lnoi400-2.1.1/pyproject.toml +145 -0
  42. lnoi400-2.1.1/setup.cfg +4 -0
  43. lnoi400-2.1.1/tests/test_chip_edge.py +68 -0
  44. lnoi400-2.1.1/tests/test_components.py +251 -0
  45. lnoi400-2.1.1/tests/test_mzm_with_pads.py +53 -0
  46. lnoi400-2.1.1/tests/test_ring_resonator_slab.py +56 -0
lnoi400-2.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023-2026 Luxtelligence
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
lnoi400-2.1.1/PKG-INFO ADDED
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.4
2
+ Name: lnoi400
3
+ Version: 2.1.1
4
+ Summary: Luxtelligence gdsfactory PDK
5
+ Author-email: Luxtelligence <foundry@luxtelligence.ai>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2023-2026 Luxtelligence
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Keywords: python
29
+ Classifier: Programming Language :: Python :: 3.11
30
+ Classifier: Programming Language :: Python :: 3.12
31
+ Classifier: Operating System :: OS Independent
32
+ Requires-Python: ~=3.12.0
33
+ Description-Content-Type: text/markdown
34
+ License-File: LICENSE
35
+ Requires-Dist: gdsfactory~=9.51.0
36
+ Requires-Dist: gdsfactoryplus
37
+ Requires-Dist: gplugins[sax]~=2.1.0
38
+ Provides-Extra: dev
39
+ Requires-Dist: pre-commit; extra == "dev"
40
+ Requires-Dist: pytest; extra == "dev"
41
+ Requires-Dist: pytest-cov; extra == "dev"
42
+ Requires-Dist: pytest_regressions; extra == "dev"
43
+ Requires-Dist: towncrier; extra == "dev"
44
+ Provides-Extra: docs
45
+ Requires-Dist: jupyter; extra == "docs"
46
+ Requires-Dist: mkdocs-material; extra == "docs"
47
+ Requires-Dist: mkdocs-with-pdf; extra == "docs"
48
+ Requires-Dist: nbconvert; extra == "docs"
49
+ Requires-Dist: mkdocstrings[python]>=0.27.0; extra == "docs"
50
+ Requires-Dist: zensical<0.1.0,>=0.0.40; extra == "docs"
51
+ Dynamic: license-file
52
+
53
+ # Luxtelligence Process Design Kit (PDK) for gdsfactory
54
+
55
+ Luxtelligence's PDK is built on a lithium tantalate/lithium niobate electro-optic platform, leveraging their large Pockels coefficients for high-speed modulation.
56
+
57
+ <!-- BADGES:START -->
58
+ [![Docs](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/pages.yml/badge.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/pages.yml)
59
+ [![Tests](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/test_code.yml/badge.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/test_code.yml)
60
+ [![DRC](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/drc.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/drc.yml)
61
+ [![Model Regression](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/model_regression.yml/badge.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/model_regression.yml)
62
+ [![Test Coverage](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/coverage.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/test_coverage.yml)
63
+ [![Model Coverage](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/model_coverage.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/model_coverage.yml)
64
+ [![Issues](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/issues.svg)](https://github.com/gdsfactory/lxt_pdk_gf/issues)
65
+ [![PRs](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/prs.svg)](https://github.com/gdsfactory/lxt_pdk_gf/pulls)
66
+ <!-- BADGES:END -->
67
+
68
+
69
+ ![Luxtelligence](LXT_Logo.png)
70
+
71
+ [Luxtelligence](https://luxtelligence.ai/) Process Design Kit (PDK) for gdsfactory. The Luxtelligence PDK contains a library of components that facilitate the design of photonic integrated circuits for Luxtelligence's foundry service. The PDK includes both electrical and optical building blocks that leverage Lithium Tantalate and Lithium Niobate's electro-optic effect and attractive optical properties. Each building block consists of a geometrical layout, defining the starting point for microfabrication of the integrated circuit, and a compact circuit model that approximates the real frequency-domain behaviour of the component.
72
+
73
+ The `lxt_pdk_gf` PDK is released open-source to allow users to easily evaluate a sample of what Luxtelligence has to offer. Please [contact us](mailto:foundry@luxtelligence.ai) for information on advanced building blocks and variations on the standard PDK geometry.
74
+
75
+ ## Installation
76
+
77
+ We recommend [KLayout](https://www.klayout.de/) as a layout viewer and editor for GDS and OASIS files. gdsfactory itself is based on and closely integrated with KLayout.
78
+
79
+ Python 3.12 is required. We recommend [VSCode](https://code.visualstudio.com/) or [Google Antigravity](https://antigravity.google/) as IDEs.
80
+
81
+ If you do not have Python installed, you can [download Anaconda](https://www.anaconda.com/download/). Once Python is available, clone the repository and install the package in editable mode:
82
+
83
+ ```
84
+ git clone https://github.com/Luxtelligence/lxt_pdk_gf.git
85
+ cd lxt_pdk_gf
86
+ pip install -e .
87
+ python install_tech.py
88
+ ```
89
+
90
+ Restart KLayout afterwards to ensure the newly installed technology appears.
91
+
92
+ ## KLayout Layer Properties
93
+
94
+ Each PDK has a `klayout/` folder containing `.lyp` layer property files (e.g. `ltoi300/klayout/` and `lnoi400/klayout/`). These files define the colours, fill patterns, and display names for every process layer.
95
+
96
+ To activate them in KLayout:
97
+
98
+ 1. Open KLayout and go to **File → Setup**.
99
+ 2. Navigate to the **Application** section and select **Layer Properties**.
100
+ 3. Under **Default layer properties file**, click **Browse** and point it to the `.lyp` file for your PDK (e.g. `lxt_pdk_gf/ltoi300/klayout/ltoi300.lyp`).
101
+ 4. Click **Apply** and **OK**. Restart KLayout to apply the changes.
102
+
103
+ ## KLayout DRC
104
+
105
+ Design Rule Check (DRC) runsets for KLayout can be downloaded from [resources.luxtelligence.ai](https://resources.luxtelligence.ai/request-access?resource=drc). The files have a `.lydrc` extension and are specific to the technology stack you are using.
106
+
107
+ **Installation:**
108
+
109
+ Place the downloaded `.lydrc` file(s) in your local KLayout DRC folder:
110
+
111
+ ```
112
+ <user home folder>/Klayout/drc/
113
+ ```
114
+
115
+ > **Note:** KLayout has a known issue where only the first DRC file in the `drc/` folder is actually used. It is recommended to keep **only one `.lydrc` file** in that folder at a time. If you need to switch between DRC scripts for different stacks, simply replace the file.
116
+
117
+ **Running the DRC in KLayout:**
118
+
119
+ 1. Open your GDS layout in KLayout.
120
+ 2. Go to **Tools → DRC**.
121
+ 3. Click **Edit DRC Script** and select the `.lydrc` file corresponding to your process stack.
122
+ 4. Run the script. The results will appear in a dedicated DRC results window, where violations are listed and can be highlighted in the layout.
123
+
124
+ > **Important:** Not every flagged violation necessarily needs to be corrected — some rules may be advisory or context-dependent. Conversely, the DRC script does not guarantee that all possible design errors are caught. Always review results in the context of your specific design intent and consult Luxtelligence if in doubt.
125
+
126
+ ## Examples
127
+
128
+ ### Chip edge, singulation, and polishing
129
+
130
+ For LNOI400 edge couplers, **the outside edge of layer 6/1
131
+ (`CHIP_EXCLUSION_ZONE`) is the physical chip edge**. Layer 6/0
132
+ (`CHIP_CONTOUR`) serves other layout purposes and does not define the
133
+ straight tip extension.
134
+
135
+ The coupler tip extends **5 µm outside layer 6/1**, regardless of the total
136
+ straight tip length. At least **5 µm of constant-width straight** remains
137
+ inside that edge for successful singulation:
138
+
139
+ | Process | Total straight tip (`input_ext`) | Outside 6/1 | Inside 6/1 |
140
+ | --- | --- | --- | --- |
141
+ | Singulation without polishing | 10 µm | 5 µm | 5 µm |
142
+ | Singulation with polishing allowance | Approximately 30 µm | 5 µm | Approximately 25 µm |
143
+
144
+ The longer polishing option keeps the width at the polished facet constant.
145
+ Do not use the longer straight by default when polishing is not planned:
146
+ the large tip mode interacts with silicon over a longer distance, which can
147
+ increase edge-coupler insertion loss. The required polishing allowance depends
148
+ on the planned process; approximately 30 µm is a guide, not a predicted loss
149
+ or a fixed polishing removal depth.
150
+
151
+ `lnoi400.cells.die_phix_rf()` uses the standard LXT chip frame and the 10 µm
152
+ straight tip by default. For polishing, keep the same 5 µm facet offset and
153
+ change only the straight length:
154
+
155
+ ```python
156
+ import lnoi400
157
+ from lnoi400 import cells
158
+
159
+ lnoi400.PDK.activate()
160
+ die = cells.die_phix_rf(
161
+ edge_coupler={
162
+ "component": "double_linear_inverse_taper_mirror",
163
+ "settings": {"input_ext": 30.0},
164
+ },
165
+ fiber_coupler_xoffset=5.0,
166
+ )
167
+ ```
168
+
169
+ Both right and optional left coupler arrays use this outward offset from 6/1.
170
+ Custom couplers must supply at least 10 µm of constant-width straight tip.
171
+ The low-level unmirrored `double_linear_inverse_taper` retains its zero-extension
172
+ default; set `input_ext` explicitly when using it at a singulated chip edge.
173
+
174
+ The die wrapper follows `chip_frame` dimension restrictions: nominal dimensions
175
+ of 5000, 10000, and 20000 µm map to layer-6/0 extents of 4950, 10000, and
176
+ 20100 µm respectively, within the frame's existing tolerances. A nominal
177
+ 5000-by-5000 µm die is unsupported. Layer 6/1 adds `exclusion_zone_width` on
178
+ each side. Pad offsets remain referenced to layer 6/0.
179
+
180
+ After installing the PDK, you can verify that it is working correctly by running the Jupyter notebooks in the [docs/notebooks](https://github.com/Luxtelligence/lxt_pdk_gf/tree/main/docs/notebooks) folder.
181
+
182
+ ## Documentation
183
+
184
+ - [PDK documentation](https://luxtelligence.github.io/lxt_pdk_gf/)
185
+ - [gdsfactory documentation](https://gdsfactory.github.io/gdsfactory/)
186
+
187
+ ## Pre-commit
188
+
189
+ Pre-commit hooks are centrally maintained in [pdk-ci-workflow-public](https://github.com/doplaydo/pdk-ci-workflow-public). `make dev` fetches the canonical config and installs the git hook.
190
+
191
+ ```bash
192
+ make dev
193
+ ```
194
+
195
+ ## Tests
196
+
197
+ Run the test suite:
198
+
199
+ ```bash
200
+ make test
201
+ ```
202
+
203
+ ## Release
204
+
205
+ 1. Bump the version:
206
+
207
+ ```bash
208
+ tbump 0.0.1
209
+ ```
210
+
211
+ 2. Push the tag:
212
+
213
+ ```bash
214
+ git push --tags
215
+ ```
216
+ This triggers the release workflow that builds wheels and uploads them.
217
+
218
+ 3. Create a pull request with the updated changelog since last release.
@@ -0,0 +1,166 @@
1
+ # Luxtelligence Process Design Kit (PDK) for gdsfactory
2
+
3
+ Luxtelligence's PDK is built on a lithium tantalate/lithium niobate electro-optic platform, leveraging their large Pockels coefficients for high-speed modulation.
4
+
5
+ <!-- BADGES:START -->
6
+ [![Docs](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/pages.yml/badge.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/pages.yml)
7
+ [![Tests](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/test_code.yml/badge.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/test_code.yml)
8
+ [![DRC](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/drc.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/drc.yml)
9
+ [![Model Regression](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/model_regression.yml/badge.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/model_regression.yml)
10
+ [![Test Coverage](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/coverage.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/test_coverage.yml)
11
+ [![Model Coverage](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/model_coverage.svg)](https://github.com/gdsfactory/lxt_pdk_gf/actions/workflows/model_coverage.yml)
12
+ [![Issues](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/issues.svg)](https://github.com/gdsfactory/lxt_pdk_gf/issues)
13
+ [![PRs](https://github.com/gdsfactory/lxt_pdk_gf/raw/badges/prs.svg)](https://github.com/gdsfactory/lxt_pdk_gf/pulls)
14
+ <!-- BADGES:END -->
15
+
16
+
17
+ ![Luxtelligence](LXT_Logo.png)
18
+
19
+ [Luxtelligence](https://luxtelligence.ai/) Process Design Kit (PDK) for gdsfactory. The Luxtelligence PDK contains a library of components that facilitate the design of photonic integrated circuits for Luxtelligence's foundry service. The PDK includes both electrical and optical building blocks that leverage Lithium Tantalate and Lithium Niobate's electro-optic effect and attractive optical properties. Each building block consists of a geometrical layout, defining the starting point for microfabrication of the integrated circuit, and a compact circuit model that approximates the real frequency-domain behaviour of the component.
20
+
21
+ The `lxt_pdk_gf` PDK is released open-source to allow users to easily evaluate a sample of what Luxtelligence has to offer. Please [contact us](mailto:foundry@luxtelligence.ai) for information on advanced building blocks and variations on the standard PDK geometry.
22
+
23
+ ## Installation
24
+
25
+ We recommend [KLayout](https://www.klayout.de/) as a layout viewer and editor for GDS and OASIS files. gdsfactory itself is based on and closely integrated with KLayout.
26
+
27
+ Python 3.12 is required. We recommend [VSCode](https://code.visualstudio.com/) or [Google Antigravity](https://antigravity.google/) as IDEs.
28
+
29
+ If you do not have Python installed, you can [download Anaconda](https://www.anaconda.com/download/). Once Python is available, clone the repository and install the package in editable mode:
30
+
31
+ ```
32
+ git clone https://github.com/Luxtelligence/lxt_pdk_gf.git
33
+ cd lxt_pdk_gf
34
+ pip install -e .
35
+ python install_tech.py
36
+ ```
37
+
38
+ Restart KLayout afterwards to ensure the newly installed technology appears.
39
+
40
+ ## KLayout Layer Properties
41
+
42
+ Each PDK has a `klayout/` folder containing `.lyp` layer property files (e.g. `ltoi300/klayout/` and `lnoi400/klayout/`). These files define the colours, fill patterns, and display names for every process layer.
43
+
44
+ To activate them in KLayout:
45
+
46
+ 1. Open KLayout and go to **File → Setup**.
47
+ 2. Navigate to the **Application** section and select **Layer Properties**.
48
+ 3. Under **Default layer properties file**, click **Browse** and point it to the `.lyp` file for your PDK (e.g. `lxt_pdk_gf/ltoi300/klayout/ltoi300.lyp`).
49
+ 4. Click **Apply** and **OK**. Restart KLayout to apply the changes.
50
+
51
+ ## KLayout DRC
52
+
53
+ Design Rule Check (DRC) runsets for KLayout can be downloaded from [resources.luxtelligence.ai](https://resources.luxtelligence.ai/request-access?resource=drc). The files have a `.lydrc` extension and are specific to the technology stack you are using.
54
+
55
+ **Installation:**
56
+
57
+ Place the downloaded `.lydrc` file(s) in your local KLayout DRC folder:
58
+
59
+ ```
60
+ <user home folder>/Klayout/drc/
61
+ ```
62
+
63
+ > **Note:** KLayout has a known issue where only the first DRC file in the `drc/` folder is actually used. It is recommended to keep **only one `.lydrc` file** in that folder at a time. If you need to switch between DRC scripts for different stacks, simply replace the file.
64
+
65
+ **Running the DRC in KLayout:**
66
+
67
+ 1. Open your GDS layout in KLayout.
68
+ 2. Go to **Tools → DRC**.
69
+ 3. Click **Edit DRC Script** and select the `.lydrc` file corresponding to your process stack.
70
+ 4. Run the script. The results will appear in a dedicated DRC results window, where violations are listed and can be highlighted in the layout.
71
+
72
+ > **Important:** Not every flagged violation necessarily needs to be corrected — some rules may be advisory or context-dependent. Conversely, the DRC script does not guarantee that all possible design errors are caught. Always review results in the context of your specific design intent and consult Luxtelligence if in doubt.
73
+
74
+ ## Examples
75
+
76
+ ### Chip edge, singulation, and polishing
77
+
78
+ For LNOI400 edge couplers, **the outside edge of layer 6/1
79
+ (`CHIP_EXCLUSION_ZONE`) is the physical chip edge**. Layer 6/0
80
+ (`CHIP_CONTOUR`) serves other layout purposes and does not define the
81
+ straight tip extension.
82
+
83
+ The coupler tip extends **5 µm outside layer 6/1**, regardless of the total
84
+ straight tip length. At least **5 µm of constant-width straight** remains
85
+ inside that edge for successful singulation:
86
+
87
+ | Process | Total straight tip (`input_ext`) | Outside 6/1 | Inside 6/1 |
88
+ | --- | --- | --- | --- |
89
+ | Singulation without polishing | 10 µm | 5 µm | 5 µm |
90
+ | Singulation with polishing allowance | Approximately 30 µm | 5 µm | Approximately 25 µm |
91
+
92
+ The longer polishing option keeps the width at the polished facet constant.
93
+ Do not use the longer straight by default when polishing is not planned:
94
+ the large tip mode interacts with silicon over a longer distance, which can
95
+ increase edge-coupler insertion loss. The required polishing allowance depends
96
+ on the planned process; approximately 30 µm is a guide, not a predicted loss
97
+ or a fixed polishing removal depth.
98
+
99
+ `lnoi400.cells.die_phix_rf()` uses the standard LXT chip frame and the 10 µm
100
+ straight tip by default. For polishing, keep the same 5 µm facet offset and
101
+ change only the straight length:
102
+
103
+ ```python
104
+ import lnoi400
105
+ from lnoi400 import cells
106
+
107
+ lnoi400.PDK.activate()
108
+ die = cells.die_phix_rf(
109
+ edge_coupler={
110
+ "component": "double_linear_inverse_taper_mirror",
111
+ "settings": {"input_ext": 30.0},
112
+ },
113
+ fiber_coupler_xoffset=5.0,
114
+ )
115
+ ```
116
+
117
+ Both right and optional left coupler arrays use this outward offset from 6/1.
118
+ Custom couplers must supply at least 10 µm of constant-width straight tip.
119
+ The low-level unmirrored `double_linear_inverse_taper` retains its zero-extension
120
+ default; set `input_ext` explicitly when using it at a singulated chip edge.
121
+
122
+ The die wrapper follows `chip_frame` dimension restrictions: nominal dimensions
123
+ of 5000, 10000, and 20000 µm map to layer-6/0 extents of 4950, 10000, and
124
+ 20100 µm respectively, within the frame's existing tolerances. A nominal
125
+ 5000-by-5000 µm die is unsupported. Layer 6/1 adds `exclusion_zone_width` on
126
+ each side. Pad offsets remain referenced to layer 6/0.
127
+
128
+ After installing the PDK, you can verify that it is working correctly by running the Jupyter notebooks in the [docs/notebooks](https://github.com/Luxtelligence/lxt_pdk_gf/tree/main/docs/notebooks) folder.
129
+
130
+ ## Documentation
131
+
132
+ - [PDK documentation](https://luxtelligence.github.io/lxt_pdk_gf/)
133
+ - [gdsfactory documentation](https://gdsfactory.github.io/gdsfactory/)
134
+
135
+ ## Pre-commit
136
+
137
+ Pre-commit hooks are centrally maintained in [pdk-ci-workflow-public](https://github.com/doplaydo/pdk-ci-workflow-public). `make dev` fetches the canonical config and installs the git hook.
138
+
139
+ ```bash
140
+ make dev
141
+ ```
142
+
143
+ ## Tests
144
+
145
+ Run the test suite:
146
+
147
+ ```bash
148
+ make test
149
+ ```
150
+
151
+ ## Release
152
+
153
+ 1. Bump the version:
154
+
155
+ ```bash
156
+ tbump 0.0.1
157
+ ```
158
+
159
+ 2. Push the tag:
160
+
161
+ ```bash
162
+ git push --tags
163
+ ```
164
+ This triggers the release workflow that builds wheels and uploads them.
165
+
166
+ 3. Create a pull request with the updated changelog since last release.
File without changes
@@ -0,0 +1,109 @@
1
+ import gdsfactory as gf
2
+ import numpy as np
3
+ from gdsfactory.cross_section import (
4
+ CrossSection,
5
+ )
6
+ from gdsfactory.typings import CrossSectionSpec
7
+
8
+ from _utils.spline import (
9
+ bend_S_spline,
10
+ spline_clamped_path,
11
+ )
12
+
13
+
14
+ def L_turn_bend(
15
+ radius: float = 80.0,
16
+ p: float = 1.0,
17
+ with_arc_floorplan: bool = True,
18
+ cross_section: CrossSectionSpec = "xs_rwg700",
19
+ **kwargs,
20
+ ) -> gf.Component:
21
+ """
22
+ A 90-degrees bend following an Euler path, with linearly-varying curvature
23
+ (increasing and decreasing).
24
+ """
25
+
26
+ npoints = int(np.round(200 * radius / 80.0))
27
+ angle = 90.0
28
+
29
+ return gf.components.bend_euler(
30
+ radius=radius,
31
+ angle=angle,
32
+ p=p,
33
+ with_arc_floorplan=with_arc_floorplan,
34
+ npoints=npoints,
35
+ cross_section=cross_section,
36
+ **kwargs,
37
+ )
38
+
39
+
40
+ def S_bend_vert(
41
+ v_offset: float = 25.0,
42
+ h_extent: float = 100.0,
43
+ dx_straight: float = 5.0,
44
+ cross_section: CrossSectionSpec = "xs_rwg700",
45
+ ) -> gf.Component:
46
+ """A spline bend that bridges a vertical displacement."""
47
+
48
+ if np.abs(v_offset) < 10.0:
49
+ raise ValueError(
50
+ f"The vertical distance bridged by the S-bend ({v_offset}) is too small."
51
+ )
52
+
53
+ if np.abs(h_extent / v_offset) < 3.5 or h_extent < 90.0:
54
+ raise ValueError(
55
+ f"The bend would be too tight. Increase h_extent from its current value of {h_extent}."
56
+ )
57
+
58
+ S_bend = gf.components.extend_ports(
59
+ bend_S_spline(
60
+ size=(h_extent, v_offset),
61
+ cross_section=cross_section,
62
+ npoints=int(np.round(2.5 * h_extent)),
63
+ path_method=spline_clamped_path,
64
+ ),
65
+ length=dx_straight,
66
+ cross_section=cross_section,
67
+ )
68
+
69
+ bend_cell = gf.Component()
70
+ bend_ref = bend_cell << S_bend
71
+ bend_ref.dmove(bend_ref.ports["o1"].dcenter, (0.0, 0.0))
72
+ bend_cell.add_port(name="o1", port=bend_ref.ports["o1"])
73
+ bend_cell.add_port(name="o2", port=bend_ref.ports["o2"])
74
+ bend_cell.flatten()
75
+
76
+ return bend_cell
77
+
78
+
79
+ def bend_euler_tapered(
80
+ radius: float = 45.0,
81
+ w0: float = 3.0,
82
+ wc: float = 1.0,
83
+ cross_section: CrossSection = None,
84
+ ) -> gf.Component:
85
+ """A tapered bend following an Euler path."""
86
+
87
+ euler_path = gf.path.euler(
88
+ radius=radius,
89
+ angle=180.0,
90
+ p=1,
91
+ use_eff=True,
92
+ )
93
+ euler_path.start_angle = 0.0
94
+ euler_path.end_angle = 180.0
95
+
96
+ def width_fun(t):
97
+ if any(t > 1) or any(t < 0):
98
+ raise ValueError()
99
+ y = np.zeros_like(t)
100
+ y[t <= 0.5] = w0 + (wc - w0) * 2 * t[t <= 0.5]
101
+ y[t > 0.5] = -(wc - w0) * 2 * t[t > 0.5] + 2 * wc - w0
102
+ return y
103
+
104
+ if not cross_section:
105
+ raise ValueError("cross_section is required")
106
+
107
+ xs_tapered = cross_section(width_function=width_fun)
108
+
109
+ return euler_path.extrude(cross_section=xs_tapered)
@@ -0,0 +1,17 @@
1
+ from gdsfactory import Component
2
+
3
+
4
+ def copy_info(dst: Component, src: Component, prefix: str | None = None) -> None:
5
+ """Copy `src.info` entries into `dst.info` with a prefix.
6
+
7
+ By default, the prefix is derived from `src.function_name` when available.
8
+ """
9
+ if not hasattr(dst, "info") or not hasattr(src, "info"):
10
+ raise ValueError("Both dst and src must expose an 'info' attribute.")
11
+
12
+ src_prefix = prefix or getattr(src, "function_name", None) or "cell"
13
+ src_data = (
14
+ src.info.model_dump() if hasattr(src.info, "model_dump") else dict(src.info)
15
+ )
16
+
17
+ dst.info.update({f"{src_prefix}_{key}": value for key, value in src_data.items()})
@@ -0,0 +1,66 @@
1
+ import gdsfactory as gf
2
+
3
+
4
+ @gf.cell(tags=["chip_floorplan"])
5
+ def chip_frame(
6
+ size: tuple[float, float] = (10_000, 5000),
7
+ exclusion_zone_width: float = 50,
8
+ center: tuple[float, float] = None,
9
+ chip_contour_layer: tuple[int, int] = (6, 0),
10
+ chip_exclusion_zone_layer: tuple[int, int] = (6, 1),
11
+ ) -> gf.Component:
12
+ """Provide the chip extent and the exclusion zone around the chip frame.
13
+
14
+ @tags lnoi400-chip-edge
15
+
16
+ The outside edge of chip_exclusion_zone_layer (6/1) is the physical chip
17
+ edge. chip_contour_layer (6/0) is a separate design contour, not the facet.
18
+ In the exclusion zone, only the edge couplers routing to the chip facet should be placed.
19
+ Allowed chip dimensions (in either direction): 5000 um, 10000 um, 20000 um."""
20
+
21
+ # Check that the chip dimensions have the admissible values.
22
+
23
+ snapped_size = []
24
+
25
+ if size[0] <= 5050 and size[1] <= 5050:
26
+ raise (ValueError(f"The chip frame size {size} is not supported."))
27
+
28
+ if size[0] > 20200 or size[1] > 20200:
29
+ raise (ValueError(f"The chip frame size {size} is not supported."))
30
+
31
+ else:
32
+ for s in size:
33
+ if abs(s - 5000.0) <= 50.0:
34
+ snapped_size.append(4950.0)
35
+ elif abs(s - 10000.0) <= 100.0:
36
+ snapped_size.append(10000)
37
+ elif abs(s - 20000.0) <= 200:
38
+ snapped_size.append(20100)
39
+ else:
40
+ raise (ValueError(f"The chip frame size {size} is not supported."))
41
+
42
+ # Chip frame elements
43
+
44
+ inner_box = gf.components.rectangle(
45
+ size=tuple(snapped_size),
46
+ layer=chip_contour_layer,
47
+ centered=True,
48
+ )
49
+
50
+ outer_box = gf.components.rectangle(
51
+ size=tuple(s + 2 * exclusion_zone_width for s in snapped_size),
52
+ layer=chip_exclusion_zone_layer,
53
+ centered=True,
54
+ )
55
+
56
+ c = gf.Component()
57
+ ib = c << inner_box
58
+ ob = c << outer_box
59
+
60
+ if center:
61
+ ib.dmove(origin=(0.0, 0.0), destination=center)
62
+ ob.dmove(origin=(0.0, 0.0), destination=center)
63
+
64
+ c.flatten()
65
+
66
+ return c