def draw_guard_ring(distance, gap, radius, polarity, label_name, label_dict): '''Draw circular shape of guard ring in the problem and add a label. Args: distance (float): distance in r-plane from edge of PCB to edge of guard ring gap (float): distance in z-plane from edge of PCB to edge of guard ring radius (float): radius of the guard ring conductor polarity (int): attach the gaurd ring to high side or low side. Polarity higher than zero sets the guard ring to the upper side of the dielectric. Else the guard ring is set to lower side. label_name (str): name of this conductor that is stored in the label dictionary label_dict (dict): stores label coordinates ''' max_angle = 1 # arc_section angle, affects finess of mesh. # high or low side? if polarity > 0: origin = label_dict['PCB_prim'] origin = np.array((origin[2], origin[1])) point1 = origin + np.array((radius + distance, gap)) point2 = point1 + np.array((0, 2 * radius)) in_conductor = 'high' else: origin = label_dict['PCB_sec'] origin = np.array((origin[2], origin[1])) point1 = origin + np.array((radius + distance, -gap)) point2 = point1 + np.array((0, -2 * radius)) in_conductor = 'zero' label_dict[label_name + 'surface'] = point1 # ei_drawarc(x1,y1,x2,y2,angle,maxseg) # From manual: Adds nodes at (x1,y1) and (x2,y2) and adds an arc of the # specified angle and discretization connecting the nodes. femm.ei_drawarc(point1[0], point1[1], point2[0], point2[1], 180, max_angle) femm.ei_addarc(point2[0], point2[1], point1[0], point1[1], 180, max_angle) # Add label and block property to guard ring label_coord = np.average((point1, point2), axis=0) femm.ei_addblocklabel(*label_coord) femm.ei_selectlabel(*label_coord) femm.ei_setblockprop('<No Mesh>', 1, 0, 'guards') femm.ei_clearselected() label_dict[label_name] = label_coord # Set boundry based on coordinates # ei_setarcsegmentprop(maxsegdeg, ’propname’, hide, group, ’inconductor’) # From manual: Set the selected arc segments to: # Meshed with elements that span at most maxsegdeg degrees per element # Boundary property ’propname’ # hide: 0 = not hidden in post-processor, 1 == hidden in post processor # A member of group number group # A member of the conductor specified by the string ’inconductor’. If the # segment is not part of a conductor, this parameter can be specified # as ’<None>’. femm.ei_selectarcsegment(label_coord[0] - radius, label_coord[1]) femm.ei_selectarcsegment(label_coord[0] + radius, label_coord[1]) femm.ei_setarcsegmentprop(max_angle, 'None', 0, 'None', in_conductor) femm.ei_clearselected()
def round_conductor_edges(tg, label_dict, segment_angle): '''Round the edges of conductors that are critical to the peak field calculations. These conductors will be the ones closest to the dielectric material, and both inner and outer conductor corners Args: tg (:obj:'TransformerGeometry'): contains all geometry information needed to build conductors in the problem. label_dict (dict): stores coordinates ''' # Define parameters of the rounding conductor_height = tg.height_copper conductor_width = tg.width_copper corner_radius = .2 * conductor_height # percentage of conductor height segment_length = 0.004 if segment_angle is None: segment_angle = 1 # Find primary side corners and add new labels for the rounded edge turns = tg.turns_primary label_dict['edge0'] = (np.array(label_dict['prim0']) + np.array( (-conductor_width[0], -conductor_height)) / 2.0) label_dict['edge1'] = (np.array(label_dict['prim' + str(turns - 1)]) + np.array( (conductor_width[0], -conductor_height)) / 2.0) # Find secondary side corners and add new labels for the rounded edge turns = tg.turns_secondary label_dict['edge2'] = (np.array(label_dict['sec0']) + np.array( (-conductor_width[1], conductor_height)) / 2.0) label_dict['edge3'] = (np.array(label_dict['sec' + str(turns - 1)]) + np.array( (conductor_width[1], conductor_height)) / 2.0) # Round edges and set arcsegment properties for e in ['edge0', 'edge1']: corner = label_dict[e] femm.ei_createradius(corner[0], corner[1], corner_radius) femm.ei_selectarcsegment(*corner) femm.ei_setarcsegmentprop(segment_angle, '<None>', 0, 0, 'high') femm.ei_clearselected() for e in ['edge2', 'edge3']: corner = label_dict[e] femm.ei_createradius(corner[0], corner[1], corner_radius) femm.ei_selectarcsegment(*corner) femm.ei_setarcsegmentprop(segment_angle, '<None>', 0, 0, 'zero') femm.ei_clearselected() increase_pcb_mesh(conductor_height, conductor_height * 2, segment_length, label_dict)
def _modify_tracks_round(tg, track, coords, segment_angle): # Define parameters of the rounding corner_radius = .2 * tg.height_copper # percentage of conductor height if track.side_v == 'high': delta_vert = -tg.height_copper / 2.0 volt_potential = 'high' else: delta_vert = tg.height_copper / 2.0 volt_potential = 'zero' if track.rounding in ['single', 'both']: corner = coords + np.array((0, delta_vert)) femm.ei_createradius(corner[0], corner[1], corner_radius) femm.ei_selectarcsegment(*corner) femm.ei_setarcsegmentprop(segment_angle, '<None>', 0, 0, volt_potential) if track.rounding == 'both': corner = coords - np.array((0, delta_vert)) femm.ei_createradius(corner[0], corner[1], corner_radius) femm.ei_selectarcsegment(*corner) femm.ei_setarcsegmentprop(segment_angle, '<None>', 0, 0, volt_potential)
# Draw the geometry femm.ei_probdef('micrometers', 'planar', 10**(-8), 10**6, 30) femm.ei_drawrectangle(2, 0, 22, 2) femm.ei_drawrectangle(2 + 24, 0, 22 + 24, 2) femm.ei_drawrectangle(-2, 0, -22, 2) femm.ei_drawrectangle(-2 - 24, 0, -22 - 24, 2) femm.ei_drawrectangle(-100, -20, 100, 0) femm.ei_drawline(-120, -20, 120, -20) femm.ei_drawarc(120, -20, -120, -20, 180, 2.5) femm.ei_drawarc(100, 100, 120, 100, 180, 2.5) femm.ei_drawline(100, 100, 120, 100) # Create and assign a "periodic" boundary condition to # model an unbounded problem via the Kelvin Transformation femm.ei_addboundprop('periodic', 0, 0, 0, 0, 3) femm.ei_selectarcsegment(0, 100) femm.ei_selectarcsegment(110, 80) femm.ei_setarcsegmentprop(2.5, 'periodic', 0, 0, '<none>') femm.ei_clearselected() # Define the ground plane in both the geometry and the exterior region femm.ei_addboundprop('ground', 0, 0, 0, 0, 0) femm.ei_selectsegment(0, -20) femm.ei_selectsegment(110, -20) femm.ei_selectsegment(-110, -20) femm.ei_selectsegment(110, 100) femm.ei_setsegmentprop('ground', 0, 1, 0, 0, '<none>') femm.ei_clearselected() # Add block labels for each strip and mark them with "No Mesh" for k in range(0, 4):
def analyseCapacitor(flexPercent): # Create a new electrostatics problem femm.newdocument(1) # Draw the geometry femm.ei_probdef('centimeters', 'axi', 10**(-8), 30) femm.ei_drawrectangle(0, -SPACE, RADIUS, -DISTANCE) # bottom plate and dielectric # femm.ei_drawline(0,0,RADIUS,0) # top plate for i in range(0, NODECOUNT): femm.ei_drawline(i * dr, getPlateZ(flexPercent, i * dr), (i + 1) * dr, getPlateZ(flexPercent, (i + 1) * dr)) femm.ei_drawarc(0, -RADIUS * 5, 0, RADIUS * 5, 180, 2.5) # arc boundary femm.ei_drawline(0, -RADIUS * 5, 0, RADIUS * 5) # line boundary # Create and assign a "fixed voltage" boundary condition to curve femm.ei_addboundprop('Fixed Voltage', 0.5, 0, 0, 0, 0) femm.ei_selectarcsegment(0, -RADIUS * 5) femm.ei_setarcsegmentprop(2.5, 'Fixed Voltage', 0, 0, '<none>') femm.ei_clearselected() # Add and assign the block labels for the air and dielectric regions femm.ei_addmaterial('air', 1, 1, 0) femm.ei_addmaterial('dielectric', 3, 3, 0) femm.ei_addblocklabel(10, 10) femm.ei_selectlabel(10, 10) femm.ei_setblockprop('air', 0, 1, 0) femm.ei_clearselected() femm.ei_addblocklabel(RADIUS / 2, -DISTANCE + DI_WIDTH / 2) femm.ei_selectlabel(RADIUS / 2, -DISTANCE + DI_WIDTH / 2) femm.ei_setblockprop('dielectric', 0, 1, 0) femm.ei_clearselected() # Add a "Conductor Property" for each of the plates femm.ei_addconductorprop('anode', 1, 0, 1) femm.ei_addconductorprop('cathode', 0, 0, 1) # Assign the anode properties to all sides of the first strip # femm.ei_selectsegment(RADIUS/2,0) for i in range(0, NODECOUNT): femm.ei_selectsegment((i + 0.5) * dr, getPlateZ(flexPercent, (i + 0.5) * dr)) femm.ei_setsegmentprop('<None>', 0.25, 0, 0, 0, 'anode') femm.ei_clearselected() # Assign the cathode properties to all sides of the fourth strip femm.ei_selectsegment(RADIUS / 2, -DISTANCE) femm.ei_setsegmentprop('<None>', 0.25, 0, 0, 0, 'cathode') femm.ei_clearselected() femm.ei_zoomnatural() # Save the geometry to disk so we can analyze it femm.ei_saveas('capacitors/capacitorflex' + str(flexPercent) + '.fee') femm.ei_analyze() femm.ei_loadsolution() femm.eo_selectblock(10, 10) energy = femm.eo_blockintegral(0)[0] return energy
def draw_guard_trench(tg, trench, label_name, label_dict): '''Draw a trench on the outside of turn closest to the dielectric. Args: tg (:obj:'TransformerGeometry'): contains all geometry information trench (:obj:'GuardTrench'): trench guard geometry label_name (str): label that identifies the guard in the dict label_dict (dict): stores label coordinates ''' conductor_height = tg.height_copper conductor_width = tg.width_copper max_angle = 2 elementsize = 0.05 if trench.inner: sign = -1 turns = 1 else: sign = 1 turns = tg.turns_primary # find starting point if trench.polarity: node0 = (np.array(label_dict['prim' + str(turns - 1)]) + np.array( (conductor_width[0] * sign, conductor_height)) / 2.0 + np.array( (trench.distance * sign, 0))) in_conductor = 'high' pm = 1 # polarity multiplier else: node0 = (np.array(label_dict['sec' + str(turns - 1)]) + np.array( (conductor_width[1] * sign, -conductor_height)) / 2.0 + np.array( (trench.distance * sign, 0))) in_conductor = 'zero' pm = -1 # polarity multiplier # draw four/five points and lines between points 1 to last to 0 nodes = [(0, 0), (trench.width * sign, 0), (trench.width * sign, trench.depth * pm), (0, trench.depth * pm)] if trench.drill_angle > 90: alpha = (1.0 - trench.drill_angle / 180.) * pi depth_added = trench.width / (2.0 * np.tan(alpha)) nodes.insert(-1, (trench.width / 2.0 * sign, (trench.depth + depth_added) * pm)) nodes = [node0 + np.array(n) for n in nodes] for idx, n in enumerate(nodes): femm.ei_addnode(*n) label_dict[label_name + 'node' + str(idx)] = n ind = range(1, len(nodes)) + [ 0, ] segment_gen = (np.concatenate((nodes[ind[idx]], nodes[ind[idx + 1]])) for idx in range(len(nodes) - 1)) for n in segment_gen: femm.ei_addsegment(*n) femm.ei_selectsegment(*(np.mean((n[:2], n[2:]), axis=0))) femm.ei_setsegmentprop('None', elementsize, 0, 0, 'None', in_conductor) femm.ei_clearselected() # remove existing segment of the PCB femm.ei_selectsegment(*(np.mean((nodes[0:2]), axis=0))) femm.ei_deleteselectedsegments() # draw circular top if (pm == 1 and sign == 1) or (pm == -1 and sign == -1): femm.ei_addarc(nodes[0][0], nodes[0][1], nodes[1][0], nodes[1][1], trench.outer_angle, max_angle) else: femm.ei_addarc(nodes[1][0], nodes[1][1], nodes[0][0], nodes[0][1], trench.outer_angle, max_angle) # set conductor properties on the boundries femm.ei_selectarcsegment(*(np.mean((nodes[0:2]), axis=0))) femm.ei_setarcsegmentprop(max_angle, 'None', 0, 'None', in_conductor) # add label and set material label_dict[label_name] = (nodes[0] + np.array( (trench.width / 2. * sign, trench.depth * pm / 2.))) femm.ei_addblocklabel(*label_dict[label_name]) femm.ei_selectlabel(*label_dict[label_name]) femm.ei_setblockprop(trench.material, 1, 0, 'None') femm.ei_clearselected()
def trapezoidal_conductor_edges(tg, label_dict): '''Make the edges of conductors trapezoidal for those that are critical to the peak field calculations. These conductors will be the ones closest to the dielectric material, and both inner and outer conductor corners. Args: tg (:obj:'TransformerGeometry'): contains all geometry information needed to build conductors in the problem. label_dict (dict): stores label coordinates ''' # Define parameters of the rounding turns = tg.turns_primary conductor_height = tg.height_copper conductor_width = tg.width_copper cut_in_length = 2 * conductor_height # percentage of conductor height corner_radius = 1.7 * conductor_height ledge_height = 0.005 ledge_radius = 0.004 segment_length = 0.004 angle_max = 1 # Make trapezaoidal corners on primary side corners and add new labels for # the new points. Sequence: -> find corner to be moved -> set segment props # -> make ledge -> move corner to make trapezoid -> add nodes for edge and # edge corner -> repeat for all corners -> set all segment props -> round # all edges -> set all arcsegment props -> set segment props along pcb for # all trapezoidal conductor edges. # Primary inner corner inner_corner = (np.array(label_dict['prim0']) + np.array( (-conductor_width / 2., -conductor_height / 2.))) femm.ei_selectsegment(*(inner_corner + np.array((0, conductor_height / 2.)))) femm.ei_setsegmentprop('<None>', segment_length, 0, 0, 0, 'high') label_dict['ledge0corner'] = (inner_corner + np.array( (0, conductor_height - ledge_height))) femm.ei_addnode(*label_dict['ledge0corner']) femm.ei_selectnode(*inner_corner) femm.ei_movetranslate(cut_in_length, 0) label_dict['edge0'] = (np.array(label_dict['prim0']) + np.array( ((-conductor_width + cut_in_length) / 2., 0))) label_dict['edge0corner'] = inner_corner + np.array((cut_in_length, 0)) # Primary outer corner outer_corner = (np.array(label_dict['prim' + str(turns - 1)]) + np.array( (conductor_width / 2., -conductor_height / 2.))) femm.ei_selectsegment(*(outer_corner + np.array((0, conductor_height / 2.)))) femm.ei_setsegmentprop('<None>', segment_length, 0, 0, 0, 'high') label_dict['ledge1corner'] = (outer_corner + np.array( (0, conductor_height - ledge_height))) femm.ei_addnode(*label_dict['ledge1corner']) femm.ei_selectnode(*outer_corner) femm.ei_movetranslate(-cut_in_length, 0) label_dict['edge1'] = (np.array(label_dict['prim' + str(turns - 1)]) + np.array( ((conductor_width - cut_in_length) / 2., 0))) label_dict['edge1corner'] = outer_corner + np.array((-cut_in_length, 0)) # Secondary inner corner turns = tg.turns_secondary inner_corner = (np.array(label_dict['sec0']) + np.array( (-conductor_width / 2., conductor_height / 2.))) femm.ei_selectsegment(*(inner_corner + np.array((0, -conductor_height / 2.)))) femm.ei_setsegmentprop('<None>', segment_length, 0, 0, 0, 'zero') label_dict['ledge2corner'] = (inner_corner + np.array( (0, ledge_height - conductor_height))) femm.ei_addnode(*label_dict['ledge2corner']) femm.ei_selectnode(*inner_corner) femm.ei_movetranslate(cut_in_length, 0) label_dict['edge2'] = (np.array(label_dict['sec0']) + np.array( ((-conductor_width + cut_in_length) / 2., 0))) label_dict['edge2corner'] = inner_corner + np.array((cut_in_length, 0)) # Secondary outer corner outer_corner = (np.array(label_dict['sec' + str(turns - 1)]) + np.array( (conductor_width / 2., conductor_height / 2.))) femm.ei_selectsegment(*(outer_corner + np.array((0, -conductor_height / 2.)))) femm.ei_setsegmentprop('<None>', segment_length, 0, 0, 0, 'zero') label_dict['ledge3corner'] = (outer_corner + np.array( (0, ledge_height - conductor_height))) femm.ei_addnode(*label_dict['ledge3corner']) femm.ei_selectnode(*outer_corner) femm.ei_movetranslate(-cut_in_length, 0) label_dict['edge3'] = (np.array(label_dict['sec' + str(turns - 1)]) + np.array( ((conductor_width - cut_in_length) / 2., 0))) label_dict['edge3corner'] = outer_corner + np.array((-cut_in_length, 0)) # Set segment size for diagonal line to decrease mesh sizing femm.ei_selectsegment(*label_dict['edge0']) femm.ei_selectsegment(*label_dict['edge1']) femm.ei_setsegmentprop('<None>', segment_length, 0, 0, 0, 'high') femm.ei_clearselected() femm.ei_selectsegment(*label_dict['edge2']) femm.ei_selectsegment(*label_dict['edge3']) femm.ei_setsegmentprop('<None>', segment_length, 0, 0, 0, 'zero') femm.ei_clearselected() # Round new edge on primary and secondary and set arcangle for idx in range(4): node = label_dict['edge' + str(idx) + 'corner'] femm.ei_createradius(node[0], node[1], corner_radius) node = label_dict['ledge' + str(idx) + 'corner'] femm.ei_createradius(node[0], node[1], ledge_radius) # Set arcsegment properties segments = [ str(x) + str(y) + 'corner' for x in ['edge', 'ledge'] for y in range(2) ] for s in segments: femm.ei_selectarcsegment(*label_dict[s]) femm.ei_setarcsegmentprop(angle_max, '<None>', 0, 0, 'high') femm.ei_clearselected() segments = [ str(x) + str(y) + 'corner' for x in ['edge', 'ledge'] for y in range(2, 4) ] for s in segments: femm.ei_selectarcsegment(*label_dict[s]) femm.ei_setarcsegmentprop(angle_max, '<None>', 0, 0, 'zero') femm.ei_clearselected() # Set segment size to decrease mesh size along edge of PCB where the field # is high increase_pcb_mesh(cut_in_length, conductor_height, segment_length, label_dict)