def generate(self): rl_max = np.max(self.length) # finger 2 x = 0.5*rl_max y = 0.5*self.space[2] start = [x - self.length[2], y, self.metal_z[0]]; y += self.width[2] stop = [x + self.length[2], y, self.metal_z[1]]; openems.Box(self.em, 'r2', self.metal_name, self.priority, start, stop).duplicate('r2m').mirror('xy') # finger 1 x += rl_max y += self.space[1] start = [x - self.length[1], y, self.metal_z[0]]; y += self.width[1] stop = [x + self.length[1], y, self.metal_z[1]]; openems.Box(self.em, 'r1', self.metal_name, self.priority, start, stop).duplicate('r1m').mirror('xy') # finger 0 (half length coupling) x += rl_max y += self.space[0] start = [x - self.length[0], y, self.metal_z[0]]; y += self.width[0] stop = [x, y, self.metal_z[1]]; openems.Box(self.em, 'r0', self.metal_name, self.priority, start, stop).duplicate('r0m').mirror('xy') self.xmax = x self.ymax = y
def generate(self): d1 = 0.5 * self.box_size d2 = d1 - self.port_length d3 = d2 - 0.2 * mm d4 = -0.5 * self.ms_width + self.miter # substrate start = np.array([0.5 * self.box_size, 0.5 * self.box_size, self.z[0]]) stop = np.array( [-0.5 * self.box_size, -0.5 * self.box_size, self.z[1]]) openems.Box(self.em, 'substrate', self.substrate_name, 1, start, stop) # port pads start = np.array([0.5 * self.ms_width, d2, self.z[1]]) stop = np.array([-0.5 * self.ms_width, d3, self.z[2]]) openems.Box(self.em, 'pad_1', self.metal_name, self.priority, start, stop, padname='1') start = np.array([d2, 0.5 * self.ms_width, self.z[1]]) stop = np.array([d3, -0.5 * self.ms_width, self.z[2]]) openems.Box(self.em, 'pad_2', self.metal_name, self.priority, start, stop, padname='2') # line openems.Polygon(self.em, name='miter_line', material=self.metal_name, priority=self.priority, points=np.array( [[-0.5 * self.ms_width, d2], [0.5 * self.ms_width, d2], [0.5 * self.ms_width, 0.5 * self.ms_width], [d2, 0.5 * self.ms_width], [d2, -0.5 * self.ms_width], [d4, -0.5 * self.ms_width], [-0.5 * self.ms_width, d4]]), elevation=self.z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001) # ports start = np.array([0.5 * self.ms_width, d1, self.z[1]]) stop = np.array([-0.5 * self.ms_width, d2, self.z[2]]) openems.Port(self.em, start, stop, direction='y', z=50) start = np.array([d1, 0.5 * self.ms_width, self.z[1]]) stop = np.array([d2, -0.5 * self.ms_width, self.z[2]]) openems.Port(self.em, start, stop, direction='x', z=50)
def generate(self): # substrate start = np.array( [0.5 * self.box_length, 0.5 * self.box_width, self.z[0]]) stop = np.array( [-0.5 * self.box_length, -0.5 * self.box_width, self.z[1]]) openems.Box(self.em, 'sub', self.substrate_name, 1, start, stop) # pads x0 = -0.5 * self.box_length x1 = x0 + self.port_length x2 = x1 + self.ms_width start = np.array([x1, 0.5 * self.ms_width, self.z[1]]) stop = np.array([x2, -0.5 * self.ms_width, self.z[2]]) l1 = openems.Box(self.em, 'line_p1', self.metal_name, self.priority, start, stop, padname='1') l2 = l1.duplicate("line_p2") l2.mirror('x') l2.padname = '2' x = x1 points = np.zeros((2 * len(self.section), 2)) i = 0 for s in self.section: points[i, 0] = x x += s[0] points[i + 1, 0] = x points[i, 1] = 0.5 * s[1] points[i + 1, 1] = 0.5 * s[1] i += 2 print points points = np.concatenate((points, points[::-1] * [1, -1.0])) print points openems.Polygon(self.em, name='f', material=self.metal_name, priority=self.priority, points=points, elevation=self.z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001 * mm) # main line ports start = [x0, -0.5 * self.ms_width, self.z[1]] stop = [x1, 0.5 * self.ms_width, self.z[2]] openems.Port(self.em, start, stop, direction='x', z=50).duplicate().mirror('x')
def generate( em, sub, z, # [bottom of substrate, top of substrate, top of metal] port_length, ms_width, section, # pairs of x and y size of a segment box_width): box_length = 2.0*(port_length) + np.sum(section[:,0]) pec = openems.Metal(em, 'pec') # substrate start = np.array([ 0.5*box_length, 0.5*box_width, z[0]]) stop = np.array([-0.5*box_length, -0.5*box_width, z[1]]) openems.Box(sub, 1, start, stop) # pads x0 = -0.5*box_length x1 = x0 + port_length x2 = x1 + ms_width start = np.array([x1, 0.5*ms_width, z[1]]) stop = np.array([x2, -0.5*ms_width, z[2]]) l1 = openems.Box(pec, 9, start, stop, padname = '1') l2 = l1.duplicate("line_p2").mirror('x') l2.padname = '2' x = x1 points = np.zeros((2*len(section),2)) i = 0 for s in section: points[i,0] = x x += s[0] points[i+1,0] = x points[i,1] = 0.5*s[1] points[i+1,1] = 0.5*s[1] i += 2 print(points) points = np.concatenate((points, points[::-1]*[1,-1.0])) print(points) pec.AddPolygon( points = points, priority = 9, elevation = z[1:], normal_direction = 'z', pcb_layer = 'F.Cu', pcb_width = 1e-5) # main line ports start = [x0, -0.5*ms_width, z[1]] stop = [x1, 0.5*ms_width, z[2]] em.AddPort(start, stop, direction='x', z=50).duplicate().mirror('x')
def ecbpf(em, rl, rw, space, feedwidth, portlength, z, ms50w = 0.5*mm): rl_max = np.max(rl) # finger 2 x = 0.5*rl_max y = 0.5*space[2] start = [x - rl[2], y, z[1]]; y += rw[2] stop = [x + rl[2], y, z[2]]; openems.Box(em, 'r2', 'pec', 9, start, stop).duplicate('r2m').mirror('xy') # finger 1 x += rl_max y += space[1] start = [x - rl[1], y, z[1]]; y += rw[1] stop = [x + rl[1], y, z[2]]; openems.Box(em, 'r1', 'pec', 9, start, stop).duplicate('r1m').mirror('xy') # finger 0 (half length coupling) x += rl_max y += space[0] start = [x - rl[0], y, z[1]]; stop = [x, y+rw[0], z[2]]; openems.Box(em, 'r0', 'pec', 9, start, stop).duplicate().mirror('xy') # ports ext start = [x, y, z[1]]; stop = [x + rw[0], y+rw[0], z[2]]; openems.Box(em, 'pext', 'pec', 9, start, stop).duplicate().mirror('xy') # ports ext x += rw[0] start = [x, y+rw[0], z[1]]; stop = [x + 0.5*mm, y+rw[0]-ms50w, z[2]]; openems.Box(em, 'pext2', 'pec', 9, start, stop).duplicate().mirror('xy') x += 0.5*mm # ports start = [x, y+rw[0], z[1]]; stop = [x+0.2*mm, y+rw[0]-ms50w, z[2]]; openems.Port(em, start, stop, direction='x', z=50).duplicate().mirror('xy') x += 0.2*mm y += 0.5*mm y += 0.25*mm # substrate start = [x, y, z[0]] stop = [-x, -y, z[1]] sub = openems.Box(em, None, 'sub', 1, start, stop);
def generate(self): x0 = self.endspace x1 = -1.0 * self.fork_length x2 = x1 - self.ms_width_70 x4 = x2 - self.endspace x3 = x4 + self.port_length y1 = self.resistor_gap y2 = y1 + self.ms_width_70 y4 = y2 + self.endspace y3 = y4 - self.port_length # substrate start = np.array([x0, y4, self.z[0]]) stop = np.array([x4, -1.0 * y4, self.z[1]]) openems.Box(self.em, 'wilkinson_sub', self.substrate_name, 1, start, stop) # common port line (pad 1) start = np.array([x1, 0.5 * self.ms_width, self.z[1]]) stop = np.array([x3, -0.5 * self.ms_width, self.z[2]]) openems.Box(self.em, 'line_common', self.metal_name, self.priority, start, stop, padname='1') # fork line openems.Polygon(self.em, name='forkline', material=self.metal_name, priority=self.priority, points=np.array([[0, y1], [0, y2], [x2 + self.miter, y2], [x2, y2 - self.miter], [x2, self.miter - y2], [x2 + self.miter, -1.0 * y2], [0, -1.0 * y2], [0, -1.0 * y1], [x1, -1.0 * y1], [x1, y1]]), elevation=self.z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001) # output lines start = np.array([-0.5 * self.ms_width, y1, self.z[1]]) stop = np.array([0.5 * self.ms_width, y3, self.z[2]]) lp2 = openems.Box(self.em, 'line_p2', self.metal_name, self.priority, start, stop, padname='2') lp3 = lp2.duplicate("line_p3") lp3.mirror('y') lp3.padname = '3' # main line port start = [x3, -0.5 * self.ms_width, self.z[1]] stop = [x4, 0.5 * self.ms_width, self.z[2]] openems.Port(self.em, start, stop, direction='x', z=50) # coupled line ports start = [-0.5 * self.ms_width, y3, self.z[1]] stop = [0.5 * self.ms_width, y4, self.z[2]] openems.Port(self.em, start, stop, direction='y', z=50).duplicate().mirror('y') # resistor self.em.add_resistor('r1', origin=np.array([0, 0, self.z[2]]), direction='y', value=100.0, invert=False, priority=9, dielectric_name='alumina', metal_name=self.metal_name, element_down=False)
def generate( em, # openems instance metal_name='pec', # metal instance, define with openems.Metal() z=[], # z position vector, z[0] = substrate bottom, z[1] = substrate top, z[2] = foil top space=None, # space between stub and coplanar ground width=0.25, # width of stub length=5.0, # length of stub priority=9, # openems priority of all filter metal portlength=0.2 * mm, # length of the openems port feedwidth=0.85 * mm, # width of the trace leaving the filter and port feedgap=0.2 * mm, # space from trace leaving the filter to via ring via_radius=0.15 * mm, # radius of the via drills via_padradius=0.3 * mm, # radius of the via pads mask_thickness=0, # set to non-zero to enable solder mask over filter inner_metal=False, # set to True to enable inner metal layers in via ring inner_metal_z=[[]]): ymin = -1.0 * (0.5 * feedwidth + feedgap + 2.0 * via_padradius) ymax = length + 2.0 * via_padradius xmax = 0.5 * width + space + 2.0 * via_padradius # stub line x1 = xmax - portlength x2 = 0.5 * width ppoints = np.array([[x1, -0.5 * feedwidth], [x1, 0.5 * feedwidth], [x2, 0.5 * feedwidth], [x2, ymax], [-1.0 * x2, ymax], [-1.0 * x2, 0.5 * feedwidth], [-1.0 * x1, 0.5 * feedwidth], [-1.0 * x1, -0.5 * feedwidth]]) openems.Polygon(em, name='stub', material=metal_name, priority=priority, points=ppoints, elevation=z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001 * mm) # feed lines start = [x1, 0.5 * feedwidth, z[1]] stop = [x1 - feedwidth, -0.5 * feedwidth, z[2]] box2 = openems.Box(em, 'pe1', metal_name, priority, start, stop, padname='1').duplicate('pe2').mirror('x') box2.padname = '2' # ports start = [x1, 0.5 * feedwidth, z[1]] stop = [x1 + portlength, -0.5 * feedwidth, z[2]] openems.Port(em, start, stop, direction='x', z=50).duplicate().mirror('x') # metal ring (sides) start = [xmax - 2.0 * via_padradius, 0.5 * feedwidth + feedgap, z[1]] stop = [xmax, ymax, z[2]] openems.Box(em, 'ring1', metal_name, priority, start, stop, padname='3').duplicate('ring2').mirror('x') # metal ring (bottom) start = [xmax, length, z[1]] stop = [-1.0 * xmax, ymax, z[2]] openems.Box(em, 'ring3', metal_name, priority, start, stop, padname='3') # metal ring (top) start = [xmax, -0.5 * feedwidth - feedgap, z[1]] stop = [-1.0 * xmax, ymin, z[2]] box = openems.Box(em, 'ring4', metal_name, priority, start, stop, padname='3') # substrate start = np.array([-1.0 * xmax, ymin, z[0]]) stop = np.array([xmax, ymax, z[1]]) openems.Box(em, 'sub1', 'sub', 1, start, stop) # mask if mask_thickness > 0.0: start[2] = z[1] stop[2] = z[1] + mask_thickness openems.Box(em, 'mask', 'mask', 1, start, stop) # vias (along y) via_z = [[z[0], z[2]]] #, [z[1], z[2]]] y_start = ymax - via_padradius y_stop = 0.5 * feedwidth + feedgap + via_padradius x = xmax - via_padradius n_via = 0 n_vias = 1 + np.floor(np.abs(y_start - y_stop) / (2.0 * via_padradius)) print "n vias Y = ", n_vias for y in np.linspace(y_start, y_stop, n_vias): v = openems.Via(em, 'via{}'.format(n_via), 'pec', 2, x=x, y=y, z=via_z, drillradius=via_radius, padradius=via_padradius, padname='3') v.duplicate('via{}'.format(n_via + 1)).mirror('x') n_via += 2 # vias (along )x y = y_start x_start = x x_stop = -1.0 * x_start n_vias = 1 + np.floor(np.abs(x_start - x_stop) / (2.0 * via_padradius)) print "n vias X = ", n_vias for x in np.linspace(x_start, x_stop, n_vias)[1:-1]: v = openems.Via(em, 'via{}'.format(n_via), 'pec', 2, x=x, y=y, z=via_z, drillradius=via_radius, padradius=via_padradius, padname='3') n_via += 1 y = ymin + via_padradius for x in np.linspace(x_start, x_stop, n_vias): v = openems.Via(em, 'via{}'.format(n_via), 'pec', 2, x=x, y=y, z=via_z, drillradius=via_radius, padradius=via_padradius, padname='3') n_via += 1
def generate(self): ring_ix = 0.5 * (np.max(self.rl) + self.end_gap) ring_ox = ring_ix + 2.0 * self.via_padradius via_z = [[self.z[0], self.z[2]], [self.z[1], self.z[2]]] # fingers y = -0.5 * self.space[-1:][0] mirror = False mirrorstring = ['', 'x'] for i in range(len(self.space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - self.rl[i] y += self.space[i] start = [x1, y, self.z[1]] y += self.rw[i] stop = [x2, y, self.z[2]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname='2') box.mirror(mirrorstring[mirror]) mirror = not mirror box2 = box.duplicate() box2.mirror('xy') v = openems.Via(self.em, None, 'pec', 2, x=ring_ix + self.via_padradius, y=y - 0.5 * self.rw[i], z=via_z, drillradius=self.via_radius, padradius=self.via_padradius, padname='2') v.mirror(mirrorstring[not mirror]) v2 = v.duplicate() v2.mirror('xy') mirror = not mirror # ports y1 = y y -= 0.5 * self.rw[0] # center of line y2 = y + 0.5 * self.feedwidth + self.ring_y_width # y outside px = ring_ix - self.tapoffset py = y2 - self.portlength start = [px + 0.5 * self.feedwidth, y2, self.z[1]] stop = [px - 0.5 * self.feedwidth, py, self.z[2]] p = openems.Port(self.em, start, stop, direction='y', z=50) p.mirror(mirrorstring[mirror]) p2 = p.duplicate().mirror('xy') # feed lines start = [px + 0.5 * self.feedwidth, py, self.z[1]] stop = [px - 0.5 * self.feedwidth, py - self.feedwidth, self.z[2]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname='1') box.mirror(mirrorstring[mirror]) box2 = box.duplicate() box2.mirror('xy') box2.padname = '3' tie = openems.Polygon(self.em, points=[[-px + 0.5 * self.feedwidth, py], [-px - 0.5 * self.feedwidth, py], [-px - 0.5 * self.feedwidth, y1], [-px + 0.5 * self.feedwidth, y1]], elevation=[self.z[1], self.z[2]], priority=9) tie2 = tie.duplicate().mirror('xy') # substrate start = np.array([ring_ox, y2, self.z[0]]) stop = openems.mirror(start, 'xy') stop[2] = self.z[1] sub = openems.Box(self.em, None, 'sub', 1, start, stop) # mask if self.mask_thickness > 0.0: start = np.array([ring_ox, y2, self.z[1]]) stop = openems.mirror(start, 'xy') stop[2] += self.mask_thickness openems.Box(self.em, None, 'mask', 1, start, stop)
def generate(self): # substrate start = np.array([0.5 * self.box_length, self.box_y[0], self.z[0]]) stop = np.array([-0.5 * self.box_length, self.box_y[1], self.z[1]]) openems.Box(self.em, 'coupler_sub', self.substrate_name, 1, start, stop) # through line ends (pads) x0 = -0.5 * self.box_length x1 = x0 + self.port_length start = np.array([x1, 0.5 * self.ms_width, self.z[1]]) stop = np.array( [x1 + self.pin_length, -0.5 * self.ms_width, self.z[2]]) l1 = openems.Box(self.em, 'line_p1', self.metal_name, self.priority, start, stop, padname='1') l2 = l1.duplicate("line_p2") l2.mirror('x') l2.padname = '2' xc1 = -0.5 * self.coupler_length - 0.5 * self.ms_width xc2 = xc1 + self.ms_width xm = xc1 + self.miter # through line middle diff = 0.5 * np.abs(self.ms_width - self.main_line_width) ppoints = np.array( [[x1, 0.5 * self.ms_width], [-1.0 * x1, 0.5 * self.ms_width], [-1.0 * x1, -0.5 * self.ms_width], [-1.0 * xm + diff, -0.5 * self.ms_width], [-1.0 * xm - diff, 0.5 * self.ms_width - self.main_line_width], [1.0 * xm + diff, 0.5 * self.ms_width - self.main_line_width], [xm - diff, -0.5 * self.ms_width], [x1, -0.5 * self.ms_width]]) openems.Polygon(self.em, name='throughline', material=self.metal_name, priority=self.priority, points=ppoints, elevation=self.z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001 * mm) # coupled line yc0 = 0.5 * self.ms_width + self.coupler_gap yc1 = yc0 + self.coupler_width yc4 = self.box_y[1] yc3 = yc4 - self.port_length yc2 = yc3 - self.pin_length # pads start = np.array([xc1, yc2, self.z[1]]) stop = np.array([xc2, yc3, self.z[2]]) l3 = openems.Box(self.em, 'line_p3', self.metal_name, self.priority, start, stop, padname='3') l4 = l3.duplicate("line_p4") l4.mirror('x') l4.padname = '4' if self.dual: l5 = l3.duplicate().mirror('y') l5.padname = '5' l6 = l4.duplicate().mirror('y') l6.padname = '6' p = openems.Polygon(self.em, name='coupledline', material=self.metal_name, priority=self.priority, points=np.array([[xc1 + self.miter, yc0], [xc1, yc0 + self.miter], [xc1, yc3], [xc2, yc3], [xc2, yc1], [-1.0 * xc2, yc1], [-1.0 * xc2, yc3], [-1.0 * xc1, yc3], [-1.0 * xc1, yc0 + self.miter], [-1.0 * xc1 - self.miter, yc0]]), elevation=self.z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001 * mm) if self.dual: p.duplicate().mirror('y') if not self.feed_coupled: # main line ports start = [x0, -0.5 * self.ms_width, self.z[1]] stop = [x1, 0.5 * self.ms_width, self.z[2]] openems.Port(self.em, start, stop, direction='x', z=50).duplicate().mirror('x') # coupled line ports start = [xc1, yc4, self.z[1]] stop = [xc2, yc3, self.z[2]] cp1 = openems.Port(self.em, start, stop, direction='y', z=50) cp2 = cp1.duplicate().mirror('x') if self.dual: cp1.duplicate().mirror('y') cp2.duplicate().mirror('y') if self.feed_coupled: # main line ports start = [x0, -0.5 * self.ms_width, self.z[1]] stop = [x1, 0.5 * self.ms_width, self.z[2]] openems.Port(self.em, start, stop, direction='x', z=50).duplicate().mirror('x') # ground via if self.cpw_gap != None: start = np.array([ -0.5 * self.box_length, -0.5 * self.ms_width - self.cpw_gap, self.z[0] ]) stop = np.array([0.5 * self.box_length, self.box_y[0], self.z[2]]) openems.Box(self.em, 'ground_lower_top', self.metal_name, self.priority, start, stop, padname=None) start = np.array([ -0.5 * self.box_length, 0.5 * self.ms_width + self.cpw_gap, self.z[0] ]) stop = np.array([xc1 - self.cpw_gap, self.box_y[1], self.z[2]]) openems.Box( self.em, 'ground_upper_left', self.metal_name, self.priority, start, stop, padname=None).duplicate('ground_upper_right').mirror('x')
# coax coax_scale = 2.0 pin_diameter = 0.5e-3 * coax_scale dielectric_diameter = 1.67e-3 * coax_scale coax_port_length = 0.2e-3 * coax_scale # dimensions Z foil_top = -0.5 * pin_diameter substrate_top = foil_top - foil_thickness substrate_bottom = substrate_top - substrate_thickness # substrate start = np.array([-0.5 * box_length, 0.5 * box_width, substrate_bottom]) stop = np.array([0.0, -0.5 * box_width, substrate_top]) openems.Box(sub, 1, start, stop) # line start = np.array( [-0.5 * box_length + port_length, 0.5 * ms_width, substrate_top]) stop = np.array([0, -0.5 * ms_width, foil_top]) openems.Box(copper, 1, start, stop, padname='1') # solder start = np.array([-0.5e-3, 0.5 * pin_diameter, foil_top + 0.5 * pin_diameter]) stop = np.array([0, -0.5 * pin_diameter, foil_top]) openems.Box(copper, 1, start, stop, padname=None) # ground via start = np.array([-0.5 * box_length, -0.5 * ms_width - 0.2e-3, foil_top]) stop = np.array([0.0, -0.5 * box_width, substrate_top])
def generate(self): # fingers y = -0.5 * self.space[-1:][0] mirror = False mirrorstring = ['', 'x'] for i in range(len(self.space))[::-1]: # reverse order x1 = 0.5 * (self.ring_ox + self.ring_ix) x2 = self.ring_ix - self.rl[i] y += self.space[i] start = [x1, y, self.z[1]] y += self.rw[i] stop = [x2, y, self.z[2]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname='2') box.mirror(mirrorstring[mirror]) mirror = not mirror box2 = box.duplicate() box2.mirror('xy') if i == 0: box.padname = '1' box2.padname = '3' box.offset(self.offset) box2.offset(self.offset) # feed lines mirror = not mirror y -= 0.5 * self.rw[0] # center of line start = [self.ring_ix, y + 0.5 * self.feedwidth, self.z[1]] stop = [ self.ring_ox - self.portlength, y - 0.5 * self.feedwidth, self.z[2] ] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname='1') box.mirror(mirrorstring[mirror]) box2 = box.duplicate() box2.mirror('xy') box2.padname = '3' box.offset(self.offset) box2.offset(self.offset) # ports start = [self.ring_ox, y + 0.5 * self.feedwidth, self.z[1]] stop = [ self.ring_ox - self.portlength, y - 0.5 * self.feedwidth, self.z[2] ] p = openems.Port(self.em, start, stop, direction='x', z=50) p.mirror(mirrorstring[mirror]) p2 = p.duplicate().mirror('xy') p.offset(self.offset) p2.offset(self.offset) # metal ring (sides) y1 = y + 0.5 * self.feedwidth + self.feedgap y2 = y1 + self.ring_y_width start = [self.ring_ox, y1, self.z[1]] stop = [-1.0 * self.ring_ox, y2, self.z[2]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname='2') box.mirror(mirrorstring[mirror]) box2 = box.duplicate().mirror('xy') box.offset(self.offset) box2.offset(self.offset) # metal ring (sides) y3 = y - (0.5 * self.feedwidth + self.feedgap) start = [self.ring_ox, y3, self.z[1]] stop = [self.ring_ix, -1.0 * y2, self.z[2]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname='2') box.mirror(mirrorstring[mirror]) box2 = box.duplicate().mirror('xy') box.offset(self.offset) box2.offset(self.offset) # metal - inner ends if self.inner_metal: for z in self.inner_metal_z: start = [self.ring_ox, y1, z[0]] stop = [-1.0 * self.ring_ox, y2, z[1]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname=None) box2 = box.duplicate().mirror('xy') box.offset(self.offset) box2.offset(self.offset) start = [self.ring_ox, y2, z[0]] stop = [self.ring_ix, -1.0 * y2, z[1]] box = openems.Box(self.em, None, self.metal_name, self.priority, start, stop, padname=None) box2 = box.duplicate().mirror('xy') box.offset(self.offset) box2.offset(self.offset) # substrate start = np.array([self.ring_ox, y2, self.z[0]]) stop = openems.mirror(start, 'xy') stop[2] = self.z[1] sub = openems.Box(self.em, None, 'sub', 1, start, stop) sub.offset(self.offset) # mask if self.mask_thickness > 0.0: start = np.array([self.ring_ox, y2, self.z[1]]) stop = openems.mirror(start, 'xy') stop[2] += self.mask_thickness openems.Box(self.em, None, 'mask', 1, start, stop) # vias (along y) via_z = [[self.z[0], self.z[2]]] #, [self.z[1], self.z[2]]] y_start = y3 - self.via_padradius y_stop = -1.0 * y1 - self.via_padradius x = self.ring_ix + self.via_padradius if not self.via_radius: return n_via = 0 n_vias = 1 + np.floor( np.abs(y_start - y_stop) / (2.0 * self.via_padradius)) for y in np.linspace(y_start, y_stop, n_vias): v = openems.Via(self.em, None, 'pec', 2, x=x, y=y, z=via_z, drillradius=self.via_radius, padradius=self.via_padradius, padname='2') v.mirror(mirrorstring[mirror]) v2 = v.duplicate().mirror('xy') n_via += 2 v.offset(self.offset) v2.offset(self.offset) # vias (along x) y = y_stop x_start = self.ring_ix + self.via_padradius x_stop = self.via_padradius - self.ring_ox n_vias = 1 + np.floor( np.abs(x_start - x_stop) / (2.0 * self.via_padradius)) for x in np.linspace(x_start, x_stop, n_vias)[1:]: v = openems.Via(self.em, None, 'pec', 2, x=x, y=y, z=via_z, drillradius=self.via_radius, padradius=self.via_padradius, padname='2') v.mirror(mirrorstring[mirror]) v2 = v.duplicate().mirror('xy') n_via += 2 v.offset(self.offset) v2.offset(self.offset)
def generate(self): pec = openems.Metal(self.em, 'pec_filter') ring_ix = 0.5 * (np.max(self.rl) + self.end_gap) ring_ox = ring_ix + 2.0 * self.via_padradius via_z = [[self.z[0], self.z[1] + self.lidz], [self.z[1], self.z[2]]] # fingers y = -0.5 * self.space[-1:][0] mirror = False mirrorstring = ['', 'x'] for i in range(len(self.space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - self.rl[i] y += self.space[i] start = [x1, y, self.z[1]] y += self.rw[i] stop = [x2, y, self.z[2]] box = openems.Box(pec, 9, start, stop, padname='poly', pcb_layer=self.pcb_layer) box.mirror(mirrorstring[mirror]) mirror = not mirror box2 = box.duplicate() box2.mirror('xy') v = openems.Via(pec, priority=2, x=ring_ix + self.via_padradius, y=y - 0.5 * self.rw[i], z=via_z, drillradius=self.via_radius, padradius=self.via_padradius, padname='2') if not mirror: v.mirror('x') v.duplicate().mirror('xy') if self.endmetal: v.duplicate().mirror('y') v.duplicate().mirror('x') mirror = not mirror # ports y1 = y y -= 0.5 * self.rw[0] # center of line y2 = y + 0.5 * self.feedwidth + self.ring_y_width # y outside px = ring_ix - self.tapoffset py = y2 - self.portlength start = [px + 0.5 * self.feedwidth, y2, self.z[1]] stop = [px - 0.5 * self.feedwidth, py, self.z[2]] p = openems.Port(self.em, start, stop, direction='y', z=50) p.mirror(mirrorstring[mirror]) p2 = p.duplicate().mirror('xy') # feed lines start = [px + 0.5 * self.feedwidth, py, self.z[1]] stop = [px - 0.5 * self.feedwidth, y - 0.5 * self.rw[0], self.z[2]] box = openems.Box(pec, 9, start, stop, padname='1', pcb_layer=self.pcb_layer) box.mirror(mirrorstring[mirror]) box2 = box.duplicate() box2.mirror('xy') box2.padname = '3' # substrate start = np.array([ring_ox, y2, self.z[0]]) stop = openems.mirror(start, 'xy') stop[2] = self.z[1] + self.lidz sub = openems.Box(self.sub, 1, start, stop) # mask if self.mask_thickness > 0.0: start = np.array([ring_ox, y2, self.z[1]]) stop = openems.mirror(start, 'xy') stop[2] += self.mask_thickness openems.Box(mask, 1, start, stop) # grounded end metal if self.endmetal: em1 = openems.Box( pec, 9, start=[ring_ix, y2, self.z[1]], stop=[ring_ix + 2.0 * self.via_padradius, -y2, self.z[2]], padname='2', pcb_layer=self.pcb_layer) em1.duplicate().mirror('x')
def idbpf( em, # openems instance sub, # substrate, define with openems.Dielectric() z=[], # z position, z[0] = sub bottom, z[1] = sub top, z[2] = foil top lidz=0, # upper substrate thickness rl=[], # length of resonator fingers rw=[], # width of resonator fingers space=[], # space between resonator fingers endmetal=True, # add metal to filter ends portlength=0.2 * mm, # length of the openems port feedwidth=0.85 * mm, # width of the trace leaving the filter and port end_gap=0.3 * mm, # space between the end of a resonator and ground via_radius=0.15 * mm, # radius of the via drills via_padradius=0.3 * mm, # radius of the via pads pcb_layer='F.Cu', # Kicad layer mask=None, # mask, define with openems.Dielectric() mask_thickness=0, # set to non-zero to enable solder mask over filter ): edge_space = 0.5 * mm pec = openems.Metal(em, 'pec_filter') ring_ix = 0.5 * (np.max(rl) + end_gap) ring_ox = ring_ix + 2.0 * via_padradius via_z = [[z[0], z[1] + lidz], [z[1], z[2]]] # fingers y = -0.5 * space[-1:][0] mirror = False mirrorstring = ['', 'x'] for i in range(len(space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - rl[i] y += space[i] start = [x1, y, z[1]] y += rw[i] stop = [x2, y, z[2]] box = openems.Box(pec, 9, start, stop, padname='poly', pcb_layer=pcb_layer) box.mirror(mirrorstring[mirror]) mirror = not mirror box2 = box.duplicate() box2.mirror('xy') if i == 0: continue v = openems.Via(pec, priority=2, x=ring_ix + via_padradius, y=y - 0.5 * rw[i], z=via_z, drillradius=via_radius, padradius=via_padradius, padname='2') if not mirror: v.mirror('x') v.duplicate().mirror('xy') mirror = not mirror # ports y1 = y + feedwidth - rw[0] # outer edge of feed y2 = y - rw[0] # inner edge px = ring_ox start = [px, y2, z[1]] stop = [px - portlength, y1, z[2]] p = openems.Port(em, start, stop, direction='x', z=50) p.mirror(mirrorstring[mirror]) p2 = p.duplicate().mirror('xy') # feed lines start = [-ring_ix + rl[0], y1, z[1]] stop = [px - portlength, y2, z[2]] box = openems.Box(pec, 9, start, stop, padname='1', pcb_layer=pcb_layer) box.mirror(mirrorstring[mirror]) box2 = box.duplicate() box2.mirror('xy') box2.padname = '3' # substrate start = np.array([ring_ox, y1 + edge_space, z[0]]) stop = openems.mirror(start, 'xy') stop[2] = z[1] + lidz sub = openems.Box(sub, 1, start, stop) # mask if mask_thickness > 0.0: start = np.array([ring_ox, y2, z[1]]) stop = openems.mirror(start, 'xy') stop[2] += mask_thickness openems.Box(mask, 1, start, stop) # grounded end metal if endmetal: em1 = openems.Box( pec, 9, start=[ring_ix, -y2 + space[0], z[1]], stop=[ring_ix + 2.0 * via_padradius, y1 + edge_space, z[2]], padname='2', pcb_layer=pcb_layer) em1.duplicate().mirror('xy')
def idbpf(em, # openems instance sub, # substrate, define with openems.Dielectric() lidz = 0.0, z = [], # z position, z[0] = sub bottom, z[1] = sub top, z[2] = foil top space = [], # space between resonator fingers rl = [], # length of resonator fingers rw = [], # width of resonator fingers portlength = 0.2*mm, # length of the openems port feedwidth = 0.85*mm, # width of the trace leaving the filter and port tapoffset = 1.0*mm, # offset of tap from end of resonator end_gap = 0.3*mm, # space between the end of a resonator and ground via_radius = 0.15*mm, # radius of the via drills via_padradius = 0.3*mm, # radius of the via pads pcb_layer = 'F.Cu', # Kicad layer mask_thickness = 0, # set to non-zero to enable solder mask over filter mask = None, # mask, define with openems.Dielectric() endmetal = True, # add metal to filter ends ): pec = openems.Metal(em, 'pec_filter') ring_y_width = via_padradius * 2.0 ring_ix = 0.5 * (np.max(rl) + end_gap) ring_ox = ring_ix + 2.0 * via_padradius via_z = [[z[0], z[1]+lidz], [z[1], z[2]]] # fingers y = -0.5*space[-1:][0] mirror = np.array([1,1,1]) if len(space) % 2 == 0: mirror[0] *= -1 for i in range(len(space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - rl[i] y += space[i] start = [x1, y, z[1]]; y += rw[i] stop = [x2, y, z[2]]; for m in [np.array([1,1,1]),np.array([-1,-1,1])]: m *= mirror openems.Box(pec, 9, start*m, stop*m, padname = 'poly', pcb_layer=pcb_layer) openems.Via(pec, priority=2, x=m[0]*(ring_ix+via_padradius), y=m[1]*(y-0.5*rw[i]), z=via_z, drillradius=via_radius, padradius=via_padradius, padname='2') mirror[0] *= -1 if endmetal: v.duplicate().mirror('y') v.duplicate().mirror('x') mirror *= [-1,1,1] # ports y1 = y y -= 0.5*rw[0] # center of line y2 = y + 0.5*feedwidth + ring_y_width # y outside px = ring_ix - tapoffset py = y2 - portlength for m in [-1,1]: start = [m*(px + 0.5*feedwidth), m*y2, z[1]] stop = [m*(px - 0.5*feedwidth), m*py, z[2]] openems.Port(em, start, stop, direction='y', z=50) # feed lines start = [m*(px + 0.5*feedwidth), m*py, z[1]] stop = [m*(px - 0.5*feedwidth), m*(y-0.5*rw[0]), z[2]] openems.Box(pec, 9, start, stop, padname = '1' if m==1 else '3', pcb_layer=pcb_layer) # substrate start = np.array([ring_ox, y2, z[0]]) stop = openems.mirror(start, 'xy') stop[2] = z[1]+lidz sub = openems.Box(sub, 1, start, stop) # mask if mask_thickness > 0.0: start = np.array([ring_ox, y2, z[1]]) stop = openems.mirror(start, 'xy') stop[2] += mask_thickness openems.Box(mask, 1, start, stop) # grounded end metal if endmetal: for xm in [-1,1]: em1 = openems.Box(pec, 9, start = [xm*ring_ix, y2, z[1]], stop = [xm*(ring_ix + 2.0*via_padradius), -y2, z[2]], padname = '2', pcb_layer=pcb_layer)
def generate( em, sub, mask, min_width, # minimum copper width, typically design rule minimum cutout_width, # width of ground plane cutouts inductors, capacitors, z, # bottom of [air below, bottom metal, substrate, top metal, air above, lid] port_length, ms_width, box_width, half_fan_angle=0.25*np.pi): em.mesh.AddLine('z', z[0]) # air above, below em.mesh.AddLine('z', z[5]) em.mesh.AddLine('z', 0.5*(z[2]+z[3])) em.mesh.AddLine('z', 0.25*(3*z[2]+z[3])) em.mesh.AddLine('z', 0.25*(z[2]+3*z[3])) em.mesh.AddLine('y', -0.5*min_width) em.mesh.AddLine('y', 0.5*min_width) box_length = 2.0*(np.sum(inductors) + capacitors[0] + 0.5e-3) x0 = -0.5*box_length x1 = x0 + port_length x2 = x1 + ms_width yb = 0.5*cutout_width yo = -0.1e-3 # overlap pec = openems.Metal(em, 'pec') # substrate start = np.array([ 0.5*box_length, 0.5*box_width, z[2]]) stop = np.array([-0.5*box_length, -0.5*box_width, z[3]]) openems.Box(sub, 1, start, stop) # solder mask if mask != None: start[2] = z[3] + 25e-6 openems.Box(mask, 1, start, stop) # top copper polygon points = np.zeros((6+10*len(inductors),2)) points[0] = [x1, 0.5*ms_width] x = -np.sum(inductors) points[1] = [x - 0.5*ms_width, 0.5*ms_width] points[2:10] = arc(x, 0, capacitors[0], 0.5*np.pi+half_fan_angle, 0.5*np.pi-half_fan_angle, npoints = 8) points[10] = [x + 0.5*min_width, 0.5*min_width] i = 11 x += inductors[0] for j in range(1, len(inductors)): points[i+0] = [x-0.5*min_width, 0.5*min_width] points[i+1:i+9] = arc(x, 0, capacitors[j], 0.5*np.pi+half_fan_angle, 0.5*np.pi-half_fan_angle, npoints = 8) points[i+9] = [x+0.5*min_width, 0.5*min_width] i += 10 x += inductors[j] # center cap points[i+0] = [-0.5*min_width, 0.5*min_width] points[i+1:i+5] = arc(0, 0, capacitors[-1], 0.5*np.pi+half_fan_angle, 0.5*np.pi + 0.001, npoints = 4) print(points) points = np.concatenate((points, points[::-1]*[-1,1])) points = np.concatenate((points, points[::-1]*[1,-1])) pec.AddPolygon( points = points, priority = 9, elevation = z[3:5], pcb_layer = 'F.Cu') # ground plane gpec = openems.Metal(em, 'ground_plane') points = np.zeros((2+6*len(inductors),2)) points[0] = [x0, 0.5*box_width] points[1] = [x0, yo] i = 2 x = -np.sum(inductors) for l in inductors: hmw = 0.5*min_width xl = x + hmw points[i+0] = [xl,yo] points[i+1] = [xl,hmw] xl = x + yb points[i+2] = [xl,yb] xl = x + l - yb points[i+3] = [xl,yb] xl = x + l - hmw points[i+4] = [xl,hmw] points[i+5] = [xl,yo] i += 6 x += l print("ground plane",points) for ym in [1,-1]: gpec.AddPolygon( points = [1,ym] * np.concatenate((points, points[::-1]*[-1,1])), priority = 9, elevation = z[1:3], pcb_layer = 'B.Cu', is_custom_pad = True, x=0, y=ym*(yb+0.1e-3), pad_name='3', ) for (xm,padname) in [(-1,2),(1,1)]: # main line ports start = [x0*xm, -0.5*ms_width, z[3]] stop = [x1*xm, 0.5*ms_width, z[4]] em.AddPort(start, stop, direction='x', z=50) # pads start[0] = x2*xm l1 = openems.Box(pec, 9, start, stop, padname=padname)