qiskit_metal.qlibrary.QNLMetal.inlineidc

InlineIDC (Interdigitated Capacitor).

`cpw0`
            / 
      __   /  __ 
    /  /      \  
   /  /        \  \ 
  /  /          \  
 /__/__ _ _ _ ___\__\ 
|      | | | |      |
|      ||||||||     |
|      ||||*|||     |
|      ||||||||     |
|       | | | |     |
 \‾‾\‾‾ ‾ ‾ ‾  ‾‾/‾‾/
  \  \          /  /  
   \  \        /  /   
    \  \      /  /
     ‾‾   /    ‾‾
         /
      `cpw1'
  1# This code was written by Deval Deliwala.
  2# 
  3# This code is to be used by QNL. 
  4# 
  5# Any modifications or derivative works of this code must retain this 
  6# notice, and modified files need to carry a notice indicating 
  7# that they have been altered from the originals. 
  8
  9""" InlineIDC (Interdigitated Capacitor). 
 10
 11.. code-block::  
 12
 13                       `cpw0`
 14                         / 
 15                   __   /  __ 
 16                 /  /      \  
 17                /  /        \  \ 
 18               /  /          \  
 19              /__/__ _ _ _ ___\__\ 
 20             |      | | | |      |
 21             |      ||||||||     |
 22             |      ||||*|||     |
 23             |      ||||||||     |
 24             |       | | | |     |
 25              \‾‾\‾‾ ‾ ‾ ‾  ‾‾/‾‾/
 26               \  \          /  /  
 27                \  \        /  /   
 28                 \  \      /  /
 29                  ‾‾   /    ‾‾
 30                      /
 31                   `cpw1'
 32                  
 33""" 
 34
 35import numpy as np 
 36from qiskit_metal import draw, Dict 
 37from qiskit_metal.qlibrary.core import QComponent 
 38from qiskit_metal.toolbox_python.utility_functions import rotate_point
 39
 40class InlineIDC(QComponent): 
 41    """ 
 42    Inherits `QComponent` Class. 
 43
 44    Description: 
 45        Inline IDC (interdigitated capacitor) component. 
 46
 47    Options: 
 48        * cpw_width: The width of the CPW trace 
 49        * cpw_gap  : The CPW gap of the connected trace
 50        * taper_length  : The length of the taper segment 
 51        * taper_gap     : The gap between inner trace & ground plane at widest point 
 52        * fingers_num   : The number of fingers 
 53        * fingers_width : The finger width 
 54        * fingers.length: The finger length  
 55        * fingers_horizontal_gap : Horizontal gap between fingers  
 56        * fingers_vertical_gap   : Vertical gap between fingers 
 57            * Note `Horizontal` & `Vertical` refer to default orientation 
 58        * pos_x/_y: position of the bandage on chip
 59        * orientation : 0-> is parallel to x-axis, with orientation (in degrees) counterclockwise 
 60        * layer: The layer for the Inline IDC
 61
 62    """
 63
 64    # Default Drawing options 
 65    default_options = Dict(
 66        cpw_width    = '30um', 
 67        cpw_gap      = '17.5um', 
 68        taper_length = '200um', 
 69        taper_gap    = '87.5um', 
 70        fingers_num  = '18',  
 71        fingers_width= '5um', 
 72        fingers_length         = '200um', 
 73        fingers_horizontal_gap ='5um', 
 74        fingers_vertical_gap   ='10um', 
 75        pos_x = '0um', 
 76        pos_y = '0um', 
 77        orientation = '0', 
 78        layer = '1', 
 79    ) 
 80
 81    # Component metadata
 82    # Name prefix for component, if user doesn't provide name 
 83    component_metadata = Dict( 
 84        short_name='InlineIDC', 
 85        _qgeometry_table_poly='True', 
 86    )
 87
 88    def make(self): 
 89        """ Converts self.options into QGeometry. """ 
 90        p = self.parse_options() 
 91        nodes = Dict()
 92
 93        cpw_width = p.cpw_width 
 94        cpw_gap   = p.cpw_gap 
 95        taper_length = p.taper_length 
 96        taper_gap    = p.taper_gap 
 97        fingers_num  = p.fingers_num 
 98        fingers_width  = p.fingers_width 
 99        fingers_length = p.fingers_length 
100        fingers_horizontal_gap = p.fingers_horizontal_gap 
101        fingers_vertical_gap   = p.fingers_vertical_gap 
102        pos_x = p.pos_x 
103        pos_y = p.pos_y 
104        orientation = p.orientation 
105        layer = p.layer 
106
107        ## Meandering Portion 
108        ## ------------------
109
110        # Encompassing Central Box Dimensions 
111        box_width  = fingers_length 
112        inner_box_length = fingers_num*fingers_horizontal_gap+(fingers_num-1)*fingers_width
113        outer_box_length = taper_gap 
114        box_length = inner_box_length + 2*outer_box_length
115
116        # Build box and initialize CPW finger dimensions 
117        box = draw.rectangle(box_length, box_width) 
118        finger = draw.rectangle(
119            fingers_horizontal_gap, 
120            fingers_length - fingers_vertical_gap,  
121        ) 
122
123        # X positions for each finger 
124        finger_x_positions = [
125            -inner_box_length/2+fingers_horizontal_gap/2+i*(fingers_horizontal_gap+fingers_width)
126            for i in range(int(fingers_num))
127        ] 
128
129        # Iteratively add each finger to list, alternating y-positions to create a meander
130        finger_list = []
131        for idx in range(int(fingers_num)): 
132            if idx%2 == 0: 
133                finger_list.append(
134                    draw.translate(
135                        finger, 
136                        finger_x_positions[idx], 
137                        -fingers_vertical_gap/2, 
138                    )
139                ) 
140            else: 
141                finger_list.append( 
142                    draw.translate(
143                        finger, 
144                        finger_x_positions[idx], 
145                        +fingers_vertical_gap/2, 
146                    )
147                )
148
149        # Combine all unions into one component 
150        fingers = draw.union(finger_list) 
151        # Create the meandering inner portion of encompassing box
152        box = draw.subtract(box, fingers) 
153
154        ## Tapering End Portion 
155        ## -------------------- 
156
157        # Building the cutoff triangles to create a taper 
158        right_triangle = draw.Polygon([
159            (-cpw_width/2, +box_width/2+taper_length), 
160            (-cpw_width/2, +box_width/2), 
161            (-inner_box_length/2, +box_width/2), 
162        ])
163
164        left_triangle = draw.Polygon([
165            (-cpw_width/2-cpw_gap, +box_width/2+taper_length), 
166            (-box_length/2, +box_width/2+taper_length), 
167            (-box_length/2, +box_width/2), 
168        ])
169        cutoff_triangles = draw.union([left_triangle, right_triangle]) 
170
171        # Initialize Encompassing Taper Box
172        taper = draw.rectangle(-cpw_width/2 + box_length/2, taper_length) 
173
174        # Center of mass locations for taper 
175        x_centroid = -cpw_width/2-0.25*(-cpw_width + box_length) 
176        y_centroid = (taper_length + box_width)/2
177        taper = draw.translate(taper, x_centroid, y_centroid) 
178        
179        # Final Taper object
180        taper1 = draw.subtract(taper, cutoff_triangles) 
181
182        # Placing tapers on edges with proper orientation 
183        taper2 = draw.scale(taper1, xfact=-1, origin=(0,0))
184        taper3 = draw.scale(taper1, yfact=-1, origin=(0,0)) 
185        taper4 = draw.scale(taper1, xfact=-1, yfact=-1, origin=(0,0)) 
186        tapers = draw.union([taper1, taper2, taper3, taper4]) 
187
188        # Final InlineIDC component 
189        inlineIDC = draw.union([box, tapers]) 
190
191        # Translations \& Rotations 
192        inlineIDC = draw.rotate(inlineIDC, orientation, origin=(0, 0)) 
193        inlineIDC = draw.translate(inlineIDC, pos_x, pos_y) 
194
195        # Converting to QGeometry
196        self.add_qgeometry('poly', {'InlineIDC': inlineIDC}, layer=layer)
197
198        ## Positioning Nodes 
199        ## -----------------
200
201        nodes.origin = np.zeros(2) 
202        nodes.cpw0 = nodes.origin + [0, box_width/2 + taper_length] 
203        nodes.cpw1 = -nodes.cpw0 
204
205        # Moving nodes along with component  
206        translation_vec = np.array((p.pos_x, p.pos_y)) 
207        theta = np.deg2rad(p.orientation) 
208
209        for key, point in nodes.items():
210            rotated = rotate_point(point, theta) 
211            nodes[key] = rotated + translation_vec
212
213        self.nodes = nodes 
214        return 
215
216    def node(self, key): 
217        return self.nodes.get(key, None)
class InlineIDC(qiskit_metal.qlibrary.core.base.QComponent):
 41class InlineIDC(QComponent): 
 42    """ 
 43    Inherits `QComponent` Class. 
 44
 45    Description: 
 46        Inline IDC (interdigitated capacitor) component. 
 47
 48    Options: 
 49        * cpw_width: The width of the CPW trace 
 50        * cpw_gap  : The CPW gap of the connected trace
 51        * taper_length  : The length of the taper segment 
 52        * taper_gap     : The gap between inner trace & ground plane at widest point 
 53        * fingers_num   : The number of fingers 
 54        * fingers_width : The finger width 
 55        * fingers.length: The finger length  
 56        * fingers_horizontal_gap : Horizontal gap between fingers  
 57        * fingers_vertical_gap   : Vertical gap between fingers 
 58            * Note `Horizontal` & `Vertical` refer to default orientation 
 59        * pos_x/_y: position of the bandage on chip
 60        * orientation : 0-> is parallel to x-axis, with orientation (in degrees) counterclockwise 
 61        * layer: The layer for the Inline IDC
 62
 63    """
 64
 65    # Default Drawing options 
 66    default_options = Dict(
 67        cpw_width    = '30um', 
 68        cpw_gap      = '17.5um', 
 69        taper_length = '200um', 
 70        taper_gap    = '87.5um', 
 71        fingers_num  = '18',  
 72        fingers_width= '5um', 
 73        fingers_length         = '200um', 
 74        fingers_horizontal_gap ='5um', 
 75        fingers_vertical_gap   ='10um', 
 76        pos_x = '0um', 
 77        pos_y = '0um', 
 78        orientation = '0', 
 79        layer = '1', 
 80    ) 
 81
 82    # Component metadata
 83    # Name prefix for component, if user doesn't provide name 
 84    component_metadata = Dict( 
 85        short_name='InlineIDC', 
 86        _qgeometry_table_poly='True', 
 87    )
 88
 89    def make(self): 
 90        """ Converts self.options into QGeometry. """ 
 91        p = self.parse_options() 
 92        nodes = Dict()
 93
 94        cpw_width = p.cpw_width 
 95        cpw_gap   = p.cpw_gap 
 96        taper_length = p.taper_length 
 97        taper_gap    = p.taper_gap 
 98        fingers_num  = p.fingers_num 
 99        fingers_width  = p.fingers_width 
100        fingers_length = p.fingers_length 
101        fingers_horizontal_gap = p.fingers_horizontal_gap 
102        fingers_vertical_gap   = p.fingers_vertical_gap 
103        pos_x = p.pos_x 
104        pos_y = p.pos_y 
105        orientation = p.orientation 
106        layer = p.layer 
107
108        ## Meandering Portion 
109        ## ------------------
110
111        # Encompassing Central Box Dimensions 
112        box_width  = fingers_length 
113        inner_box_length = fingers_num*fingers_horizontal_gap+(fingers_num-1)*fingers_width
114        outer_box_length = taper_gap 
115        box_length = inner_box_length + 2*outer_box_length
116
117        # Build box and initialize CPW finger dimensions 
118        box = draw.rectangle(box_length, box_width) 
119        finger = draw.rectangle(
120            fingers_horizontal_gap, 
121            fingers_length - fingers_vertical_gap,  
122        ) 
123
124        # X positions for each finger 
125        finger_x_positions = [
126            -inner_box_length/2+fingers_horizontal_gap/2+i*(fingers_horizontal_gap+fingers_width)
127            for i in range(int(fingers_num))
128        ] 
129
130        # Iteratively add each finger to list, alternating y-positions to create a meander
131        finger_list = []
132        for idx in range(int(fingers_num)): 
133            if idx%2 == 0: 
134                finger_list.append(
135                    draw.translate(
136                        finger, 
137                        finger_x_positions[idx], 
138                        -fingers_vertical_gap/2, 
139                    )
140                ) 
141            else: 
142                finger_list.append( 
143                    draw.translate(
144                        finger, 
145                        finger_x_positions[idx], 
146                        +fingers_vertical_gap/2, 
147                    )
148                )
149
150        # Combine all unions into one component 
151        fingers = draw.union(finger_list) 
152        # Create the meandering inner portion of encompassing box
153        box = draw.subtract(box, fingers) 
154
155        ## Tapering End Portion 
156        ## -------------------- 
157
158        # Building the cutoff triangles to create a taper 
159        right_triangle = draw.Polygon([
160            (-cpw_width/2, +box_width/2+taper_length), 
161            (-cpw_width/2, +box_width/2), 
162            (-inner_box_length/2, +box_width/2), 
163        ])
164
165        left_triangle = draw.Polygon([
166            (-cpw_width/2-cpw_gap, +box_width/2+taper_length), 
167            (-box_length/2, +box_width/2+taper_length), 
168            (-box_length/2, +box_width/2), 
169        ])
170        cutoff_triangles = draw.union([left_triangle, right_triangle]) 
171
172        # Initialize Encompassing Taper Box
173        taper = draw.rectangle(-cpw_width/2 + box_length/2, taper_length) 
174
175        # Center of mass locations for taper 
176        x_centroid = -cpw_width/2-0.25*(-cpw_width + box_length) 
177        y_centroid = (taper_length + box_width)/2
178        taper = draw.translate(taper, x_centroid, y_centroid) 
179        
180        # Final Taper object
181        taper1 = draw.subtract(taper, cutoff_triangles) 
182
183        # Placing tapers on edges with proper orientation 
184        taper2 = draw.scale(taper1, xfact=-1, origin=(0,0))
185        taper3 = draw.scale(taper1, yfact=-1, origin=(0,0)) 
186        taper4 = draw.scale(taper1, xfact=-1, yfact=-1, origin=(0,0)) 
187        tapers = draw.union([taper1, taper2, taper3, taper4]) 
188
189        # Final InlineIDC component 
190        inlineIDC = draw.union([box, tapers]) 
191
192        # Translations \& Rotations 
193        inlineIDC = draw.rotate(inlineIDC, orientation, origin=(0, 0)) 
194        inlineIDC = draw.translate(inlineIDC, pos_x, pos_y) 
195
196        # Converting to QGeometry
197        self.add_qgeometry('poly', {'InlineIDC': inlineIDC}, layer=layer)
198
199        ## Positioning Nodes 
200        ## -----------------
201
202        nodes.origin = np.zeros(2) 
203        nodes.cpw0 = nodes.origin + [0, box_width/2 + taper_length] 
204        nodes.cpw1 = -nodes.cpw0 
205
206        # Moving nodes along with component  
207        translation_vec = np.array((p.pos_x, p.pos_y)) 
208        theta = np.deg2rad(p.orientation) 
209
210        for key, point in nodes.items():
211            rotated = rotate_point(point, theta) 
212            nodes[key] = rotated + translation_vec
213
214        self.nodes = nodes 
215        return 
216
217    def node(self, key): 
218        return self.nodes.get(key, None)

Inherits QComponent Class.

Description: Inline IDC (interdigitated capacitor) component.

Options: * cpw_width: The width of the CPW trace * cpw_gap : The CPW gap of the connected trace * taper_length : The length of the taper segment * taper_gap : The gap between inner trace & ground plane at widest point * fingers_num : The number of fingers * fingers_width : The finger width * fingers.length: The finger length
* fingers_horizontal_gap : Horizontal gap between fingers
* fingers_vertical_gap : Vertical gap between fingers * Note Horizontal & Vertical refer to default orientation * pos_x/_y: position of the bandage on chip * orientation : 0-> is parallel to x-axis, with orientation (in degrees) counterclockwise * layer: The layer for the Inline IDC

default_options = {'cpw_width': '30um', 'cpw_gap': '17.5um', 'taper_length': '200um', 'taper_gap': '87.5um', 'fingers_num': '18', 'fingers_width': '5um', 'fingers_length': '200um', 'fingers_horizontal_gap': '5um', 'fingers_vertical_gap': '10um', 'pos_x': '0um', 'pos_y': '0um', 'orientation': '0', 'layer': '1'}

Default drawing options

component_metadata = {'short_name': 'InlineIDC', '_qgeometry_table_poly': 'True'}

Component metadata

def make(self):
 89    def make(self): 
 90        """ Converts self.options into QGeometry. """ 
 91        p = self.parse_options() 
 92        nodes = Dict()
 93
 94        cpw_width = p.cpw_width 
 95        cpw_gap   = p.cpw_gap 
 96        taper_length = p.taper_length 
 97        taper_gap    = p.taper_gap 
 98        fingers_num  = p.fingers_num 
 99        fingers_width  = p.fingers_width 
100        fingers_length = p.fingers_length 
101        fingers_horizontal_gap = p.fingers_horizontal_gap 
102        fingers_vertical_gap   = p.fingers_vertical_gap 
103        pos_x = p.pos_x 
104        pos_y = p.pos_y 
105        orientation = p.orientation 
106        layer = p.layer 
107
108        ## Meandering Portion 
109        ## ------------------
110
111        # Encompassing Central Box Dimensions 
112        box_width  = fingers_length 
113        inner_box_length = fingers_num*fingers_horizontal_gap+(fingers_num-1)*fingers_width
114        outer_box_length = taper_gap 
115        box_length = inner_box_length + 2*outer_box_length
116
117        # Build box and initialize CPW finger dimensions 
118        box = draw.rectangle(box_length, box_width) 
119        finger = draw.rectangle(
120            fingers_horizontal_gap, 
121            fingers_length - fingers_vertical_gap,  
122        ) 
123
124        # X positions for each finger 
125        finger_x_positions = [
126            -inner_box_length/2+fingers_horizontal_gap/2+i*(fingers_horizontal_gap+fingers_width)
127            for i in range(int(fingers_num))
128        ] 
129
130        # Iteratively add each finger to list, alternating y-positions to create a meander
131        finger_list = []
132        for idx in range(int(fingers_num)): 
133            if idx%2 == 0: 
134                finger_list.append(
135                    draw.translate(
136                        finger, 
137                        finger_x_positions[idx], 
138                        -fingers_vertical_gap/2, 
139                    )
140                ) 
141            else: 
142                finger_list.append( 
143                    draw.translate(
144                        finger, 
145                        finger_x_positions[idx], 
146                        +fingers_vertical_gap/2, 
147                    )
148                )
149
150        # Combine all unions into one component 
151        fingers = draw.union(finger_list) 
152        # Create the meandering inner portion of encompassing box
153        box = draw.subtract(box, fingers) 
154
155        ## Tapering End Portion 
156        ## -------------------- 
157
158        # Building the cutoff triangles to create a taper 
159        right_triangle = draw.Polygon([
160            (-cpw_width/2, +box_width/2+taper_length), 
161            (-cpw_width/2, +box_width/2), 
162            (-inner_box_length/2, +box_width/2), 
163        ])
164
165        left_triangle = draw.Polygon([
166            (-cpw_width/2-cpw_gap, +box_width/2+taper_length), 
167            (-box_length/2, +box_width/2+taper_length), 
168            (-box_length/2, +box_width/2), 
169        ])
170        cutoff_triangles = draw.union([left_triangle, right_triangle]) 
171
172        # Initialize Encompassing Taper Box
173        taper = draw.rectangle(-cpw_width/2 + box_length/2, taper_length) 
174
175        # Center of mass locations for taper 
176        x_centroid = -cpw_width/2-0.25*(-cpw_width + box_length) 
177        y_centroid = (taper_length + box_width)/2
178        taper = draw.translate(taper, x_centroid, y_centroid) 
179        
180        # Final Taper object
181        taper1 = draw.subtract(taper, cutoff_triangles) 
182
183        # Placing tapers on edges with proper orientation 
184        taper2 = draw.scale(taper1, xfact=-1, origin=(0,0))
185        taper3 = draw.scale(taper1, yfact=-1, origin=(0,0)) 
186        taper4 = draw.scale(taper1, xfact=-1, yfact=-1, origin=(0,0)) 
187        tapers = draw.union([taper1, taper2, taper3, taper4]) 
188
189        # Final InlineIDC component 
190        inlineIDC = draw.union([box, tapers]) 
191
192        # Translations \& Rotations 
193        inlineIDC = draw.rotate(inlineIDC, orientation, origin=(0, 0)) 
194        inlineIDC = draw.translate(inlineIDC, pos_x, pos_y) 
195
196        # Converting to QGeometry
197        self.add_qgeometry('poly', {'InlineIDC': inlineIDC}, layer=layer)
198
199        ## Positioning Nodes 
200        ## -----------------
201
202        nodes.origin = np.zeros(2) 
203        nodes.cpw0 = nodes.origin + [0, box_width/2 + taper_length] 
204        nodes.cpw1 = -nodes.cpw0 
205
206        # Moving nodes along with component  
207        translation_vec = np.array((p.pos_x, p.pos_y)) 
208        theta = np.deg2rad(p.orientation) 
209
210        for key, point in nodes.items():
211            rotated = rotate_point(point, theta) 
212            nodes[key] = rotated + translation_vec
213
214        self.nodes = nodes 
215        return 

Converts self.options into QGeometry.

def node(self, key):
217    def node(self, key): 
218        return self.nodes.get(key, None)