def addLineZZ(n1, n2, group=-1): if group == -1: group = femmgroupmode femm.mi_addsegment(n1.real, n1.imag, n2.real, n2.imag) # select middle of arc for adding group n = (n1.real + n2.real) / 2 + ((n1.imag + n2.imag) / 2) * 1j femm.mi_selectsegment(n.real, n.imag) femm.mi_setgroup(group) femm.mi_clearselected()
def addLine(r1, phi1, r2, phi2, group=-1): if group == -1: group = femmgroupmode n1 = cmath.rect(r1, rad(phi1)) n2 = cmath.rect(r2, rad(phi2)) femm.mi_addsegment(n1.real, n1.imag, n2.real, n2.imag) # select middle of arc for adding group # todo: better guess at point on line (unpredictable if phi1 != phi2) n = cmath.rect((r1 + r2) / 2., rad((phi1 + phi2) / 2.)) femm.mi_selectsegment(n.real, n.imag) femm.mi_setgroup(group) femm.mi_clearselected()
def conditions_limites(self): """Méthode permettant d'attribuer les conditions aux limites""" femm.mi_addboundprop('lim', 0, 0, 0, 0, 0, 0, 0, 0, 0) femm.mi_selectsegment(0, self.hauteur / 2) femm.mi_selectsegment(0, -self.hauteur / 2) femm.mi_selectsegment(self.largeur / 2, 0) femm.mi_selectsegment(-self.largeur / 2, 0) femm.mi_setsegmentprop('lim', 0, 1, 0, 0) femm.mi_clearselected()
def drawCoil(self): """Draw the coil Draws the coil in the FEMM instance Raises: Exception -- The coil is not defined, please call defineCoil before. """ if self.Lb is not None: femm.mi_clearselected() femm.mi_addmaterial("Cuivre", 1, 1, 0, 0, 1 / self.rho * 10**-6, 0, 0, 1, 3 if self.wire_type == "round" else 6, 0, 0, 1, self.phi) femm.mi_addnode(self.Rbi, -self.Lb / 2) femm.mi_addnode(self.Rbo, -self.Lb / 2) femm.mi_addnode(self.Rbi, self.Lb / 2) femm.mi_addnode(self.Rbo, self.Lb / 2) femm.mi_addsegment(self.Rbi, -self.Lb / 2, self.Rbo, -self.Lb / 2) femm.mi_addsegment(self.Rbo, -self.Lb / 2, self.Rbo, self.Lb / 2) femm.mi_addsegment(self.Rbo, self.Lb / 2, self.Rbi, self.Lb / 2) femm.mi_addsegment(self.Rbi, -self.Lb / 2, self.Rbi, self.Lb / 2) femm.mi_selectnode(self.Rbi, -self.Lb / 2) femm.mi_selectnode(self.Rbo, -self.Lb / 2) femm.mi_selectnode(self.Rbi, self.Lb / 2) femm.mi_selectnode(self.Rbo, self.Lb / 2) femm.mi_selectsegment(self.Rbi, 0) femm.mi_selectsegment((self.Rbi + self.Rbo) / 2, -self.Lb / 2) femm.mi_selectsegment(self.Rbo, 0) femm.mi_selectsegment((self.Rbi + self.Rbo) / 2, self.Lb / 2) femm.mi_setgroup(2) femm.mi_addblocklabel((self.Rbi + self.Rbo) / 2, 0) femm.mi_selectlabel((self.Rbi + self.Rbo) / 2, -self.Lb / 2) femm.mi_setblockprop("Cuivre", 0, self.meshsize, "Bobine", 0, 2, self.n) femm.mi_clearselected() else: raise Exception("No coil defined.")
def drawProjectile(self): """Draw projectile Draws the projectil in the FEMM instance Raises: Exception -- Projectile is not defined """ if self.Lp is not None: femm.mi_addmaterial("Projectile", self.mu, self.mu, 0, 0, 0, 0, 0, 1, 0, 0, 0) femm.mi_clearselected() femm.mi_addnode(0, -self.Lp / 2) femm.mi_addnode(self.Rp, -self.Lp / 2) femm.mi_addnode(0, self.Lp / 2) femm.mi_addnode(self.Rp, self.Lp / 2) femm.mi_addsegment(0, -self.Lp / 2, self.Rp, -self.Lp / 2) femm.mi_addsegment(self.Rp, -self.Lp / 2, self.Rp, self.Lp / 2) femm.mi_addsegment(self.Rp, self.Lp / 2, 0, self.Lp / 2) femm.mi_addsegment(0, self.Lp / 2, 0, -self.Lp / 2) femm.mi_selectnode(0, -self.Lp / 2) femm.mi_selectnode(self.Rp, -self.Lp / 2) femm.mi_selectnode(0, self.Lp / 2) femm.mi_selectnode(self.Rp, self.Lp / 2) femm.mi_selectsegment(0, 0) femm.mi_selectsegment(self.Rp / 2, -self.Lp / 2) femm.mi_selectsegment(self.Rp, 0) femm.mi_selectsegment(self.Rp / 2, self.Lp / 2) femm.mi_setgroup(1) femm.mi_addblocklabel(self.Rp / 2, 0) femm.mi_selectlabel(self.Rp / 2, 0) femm.mi_setblockprop("Projectile", 0, self.meshsize, "<None>", 0, 1, 0) femm.mi_clearselected() else: raise Exception("No projectile defined.")
def drawroundedcorner_box(femm, group, width, length, x_center, y_center, corner_radius, one_sided): x1 = x_center - width / 2 y1 = y_center - length / 2 x2 = x1 + width y2 = y1 + length # mc = .02 * inches mc = corner_radius # first create nodes at the 4 corners # because they will be joined by an arc segment c1_x = x1 c1_y = y1 c2_x = x2 c2_y = y1 c3_x = x2 c3_y = y2 c4_x = x1 c4_y = y2 # now make blunted edge magnet based on it n1x = c1_x n1y = c1_y + mc n2x = c1_x + mc n2y = c1_y n3x = c2_x - mc n3y = c2_y n4x = c2_x n4y = c2_y + mc n5x = c3_x n5y = c3_y - mc n6x = c3_x - mc n6y = c3_y n7x = c4_x + mc n7y = c4_y n8x = c4_x n8y = c4_y - mc # If drawing all 4 corners if (one_sided == 0): femm.mi_addnode(n1x, n1y) femm.mi_addnode(n2x, n2y) femm.mi_addnode(n3x, n3y) femm.mi_addnode(n4x, n4y) femm.mi_addnode(n5x, n5y) femm.mi_addnode(n6x, n6y) femm.mi_addnode(n7x, n7y) femm.mi_addnode(n8x, n8y) femm.mi_addarc(n1x, n1y, n2x, n2y, 90, 3) femm.mi_addsegment(n2x, n2y, n3x, n3y) femm.mi_addarc(n3x, n3y, n4x, n4y, 90, 3) femm.mi_addsegment(n4x, n4y, n5x, n5y) femm.mi_addarc(n5x, n5y, n6x, n6y, 90, 3) femm.mi_addsegment(n6x, n6y, n7x, n7y) femm.mi_addarc(n7x, n7y, n8x, n8y, 90, 3) femm.mi_addsegment(n8x, n8y, n1x, n1y) femm.mi_clearselected() # femm.mi_drawrectangle(x1, mag_y1, mag_x2, mag_y2) # femm.mi_selectrectangle(x1, mag_y1, mag_x2, mag_y2,0) femm.mi_selectsegment(c1_x, c1_y) femm.mi_setgroup(group) femm.mi_selectsegment(c1_x + width / 4, c1_y) femm.mi_setgroup(group) femm.mi_selectsegment(c2_x, c2_y) femm.mi_setgroup(group) femm.mi_selectsegment(c3_x, c3_y + length / 2) femm.mi_setgroup(group) femm.mi_selectsegment(c3_x, c3_y) femm.mi_setgroup(group) femm.mi_selectsegment(c3_x - width / 4, c3_y) femm.mi_setgroup(group) femm.mi_selectsegment(c4_x, c4_y) femm.mi_setgroup(group) femm.mi_selectsegment(c4_x, c4_y - length / 2) femm.mi_setgroup(group) #femm.mi_clearselected() # if drawing only rounded corners on far side # because location is on axis. if (one_sided == 1): femm.mi_addnode(c1_x, c1_y) femm.mi_addnode(n3x, n3y) femm.mi_addnode(n4x, n4y) femm.mi_addnode(n5x, n5y) femm.mi_addnode(n6x, n6y) femm.mi_addnode(c4_x, c4_y) femm.mi_addsegment(c4_x, c4_y, c1_x, c1_y) femm.mi_addsegment(c1_x, c1_y, n3x, n3y) femm.mi_addarc(n3x, n3y, n4x, n4y, 90, 3) femm.mi_addsegment(n4x, n4y, n5x, n5y) femm.mi_addarc(n5x, n5y, n6x, n6y, 90, 3) femm.mi_addsegment(n6x, n6y, c4_x, c4_y) femm.mi_clearselected() femm.mi_selectsegment(c1_x, c1_y + length / 2) femm.mi_setgroup(group) femm.mi_selectsegment(c1_x + width / 2, c1_y) femm.mi_setgroup(group) femm.mi_selectsegment(c2_x, c2_y) femm.mi_setgroup(group) femm.mi_selectsegment(c2_x, c2_y + length / 2) femm.mi_setgroup(group) femm.mi_selectsegment(c3_x, c3_y) femm.mi_setgroup(group) femm.mi_selectsegment(c3_x - width / 2, c3_y) femm.mi_setgroup(group)
def draw_FEMM( self, nodeprop=None, propname=None, elementsize=None, automesh=None, hide=False, group=None, ): """< Draw the segment in FEMM and assign the property Parameters ---------- nodeprop : Nodal property (Default value = None) propname : Boundary property ’propname’ (Default value = None) elementsize : Local element size along segment no greater than elementsize (Default value = None) automesh : 0 = mesher defers to the element constraint defined by elementsize, 1 = mesher automatically chooses mesh size along the selected segments (Default value = None) hide : 0 = not hidden in post-processor, 1 == hidden in post processorc (Default value = False) group : group the segment belongs (Default value = None) Returns ------- """ # Get BC (if any) if self.label in boundary_prop: propname = boundary_prop[self.label] # Add the nodes X1, Y1 = self.begin.real, self.begin.imag X2, Y2 = self.end.real, self.end.imag femm.mi_addnode(X1, Y1) femm.mi_selectnode(X1, Y1) femm.mi_setnodeprop(nodeprop, group) femm.mi_clearselected() femm.mi_addnode(X2, Y2) femm.mi_selectnode(X2, Y2) femm.mi_setnodeprop(nodeprop, group) femm.mi_clearselected() # add the segment femm.mi_addsegment(X1, Y1, X2, Y2) # Set property femm.mi_selectsegment((X1 + X2) / 2, (Y1 + Y2) / 2) femm.mi_setsegmentprop(propname, elementsize, automesh, hide, group) femm.mi_clearselected()
def draw_FEMM( output, is_mmfr, is_mmfs, sym, is_antiper, type_calc_leakage, is_remove_vent=False, is_remove_slotS=False, is_remove_slotR=False, type_BH_stator=0, type_BH_rotor=0, kgeo_fineness=1, kmesh_fineness=1, user_FEMM_dict={}, path_save="FEMM_model.fem", is_sliding_band=True, transform_list=[], rotor_dxf=None, stator_dxf=None, ): """Draws and assigns the property of the machine in FEMM Parameters ---------- output : Output Output object is_mmfr : bool 1 to compute the rotor magnetomotive force / rotor magnetic field is_mmfs : bool 1 to compute the stator magnetomotive force/stator magnetic field type_calc_leakage : int 0 no leakage calculation 1 calculation using single slot is_remove_vent : bool True to remove the ventilation ducts in FEMM (Default value = False) is_remove_slotS : bool True to solve without slot effect on the Stator (Default value = False) is_remove_slotR : bool True to solve without slot effect on the Rotor (Default value = False) type_BH_stator: int 2 Infinite permeability, 1 to use linear B(H) curve according to mur_lin, 0 to use the B(H) curve type_BH_rotor: bool 2 Infinite permeability, 1 to use linear B(H) curve according to mur_lin, 0 to use the B(H) curve kgeo_fineness : float global coefficient to adjust geometry fineness in FEMM (1: default ; > 1: finner ; < 1: less fine) kmesh_fineness : float global coefficient to adjust mesh fineness in FEMM (1: default ; > 1: finner ; < 1: less fine) sym : int the symmetry applied on the stator and the rotor (take into account antiperiodicity) is_antiper: bool To apply antiperiodicity boundary conditions rotor_dxf : DXFImport To use a dxf version of the rotor instead of build_geometry stator_dxf : DXFImport To use a dxf version of the stator instead of build_geometry Returns ------- FEMM_dict : dict Dictionnary containing the main parameters of FEMM (including circuits and materials) """ # Initialization from output for readibility BHs = output.geo.stator.BH_curve # Stator B(H) curve BHr = output.geo.rotor.BH_curve # Rotor B(H) curve Is = output.elec.Is # Stator currents waveforms Ir = output.elec.Ir # Rotor currents waveforms machine = output.simu.machine # Computing parameter (element size, arcspan...) needed to define the simulation FEMM_dict = comp_FEMM_dict(machine, kgeo_fineness, kmesh_fineness, type_calc_leakage) FEMM_dict.update(user_FEMM_dict) # Overwrite some values if needed # The package must be initialized with the openfemm command. try: femm.openfemm() except Exception as e: raise FEMMError( "ERROR: Unable to open FEMM, please check that FEMM is correctly installed\n" + str(e)) # We need to create a new Magnetostatics document to work on. femm.newdocument(0) # Minimize the main window for faster geometry creation. femm.main_minimize() # defining the problem femm.mi_probdef(0, "meters", FEMM_dict["pbtype"], FEMM_dict["precision"]) # Modifiy the machine to match the conditions machine = type(machine)(init_dict=machine.as_dict()) if is_remove_slotR: # Remove all slots on the rotor lam_dict = machine.rotor.as_dict() machine.rotor = Lamination(init_dict=lam_dict) if is_remove_slotS: # Remove all slots on the stator lam_dict = machine.stator.as_dict() machine.stator = Lamination(init_dict=lam_dict) if is_remove_vent: # Remove all ventilations machine.rotor.axial_vent = list() machine.stator.axial_vent = list() # Building geometry of the (modified) stator and the rotor surf_list = list() lam_list = machine.get_lam_list() lam_int = lam_list[0] lam_ext = lam_list[1] # Adding no_mesh for shaft if needed if lam_int.Rint > 0 and sym == 1: surf_list.append( Circle(point_ref=0, radius=lam_int.Rint, label="No_mesh")) # adding the Airgap surface if is_sliding_band: surf_list.extend( get_sliding_band(sym=sym, lam_int=lam_int, lam_ext=lam_ext)) else: surf_list.extend(get_airgap_surface(lam_int=lam_int, lam_ext=lam_ext)) # adding Both laminations surfaces (or import from DXF) if rotor_dxf is not None: femm.mi_readdxf(rotor_dxf.file_path) surf_list.extend(rotor_dxf.get_surfaces()) else: surf_list.extend(machine.rotor.build_geometry(sym=sym)) if stator_dxf is not None: femm.mi_readdxf(stator_dxf.file_path) surf_list.extend(stator_dxf.get_surfaces()) else: surf_list.extend(machine.stator.build_geometry(sym=sym)) # Applying user defined modifications for transfrom in transform_list: for surf in surf_list: if transfrom["label"] in surf.label and transfrom[ "type"] == "rotate": surf.rotate(transfrom["value"]) elif transfrom["label"] in surf.label and transfrom[ "type"] == "translate": surf.translate(transfrom["value"]) # Creation of all the materials and circuit in FEMM prop_dict, materials, circuits = create_FEMM_materials( machine, surf_list, Is, Ir, BHs, BHr, is_mmfs, is_mmfr, type_BH_stator, type_BH_rotor, is_eddies, j_t0=0, ) create_FEMM_boundary_conditions(sym=sym, is_antiper=is_antiper) # Draw and assign all the surfaces of the machine for surf in surf_list: label = surf.label # Get the correct element size and group according to the label surf.draw_FEMM( nodeprop="None", maxseg=FEMM_dict["arcspan"], # max span of arc element in degrees propname="None", FEMM_dict=FEMM_dict, hide=False, ) assign_FEMM_surface(surf, prop_dict[label], FEMM_dict, machine.rotor, machine.stator) # Apply BC for DXF import if rotor_dxf is not None: for BC in rotor_dxf.BC_list: if BC[1] is True: # Select Arc femm.mi_selectarcsegment(BC[0].real, BC[0].imag) femm.mi_setarcsegmentprop(FEMM_dict["arcspan"], BC[2], False, None) else: # Select Line femm.mi_selectsegment(BC[0].real, BC[0].imag) femm.mi_setsegmentprop(BC[2], None, None, False, None) femm.mi_clearselected() femm.mi_zoomnatural() # Zoom out femm.mi_probdef( FEMM_dict["freqpb"], "meters", FEMM_dict["pbtype"], FEMM_dict["precision"], FEMM_dict["Lfemm"], FEMM_dict["minangle"], FEMM_dict["acsolver"], ) femm.smartmesh(FEMM_dict["smart_mesh"]) femm.mi_saveas(path_save) # Save # femm.mi_close() FEMM_dict["materials"] = materials FEMM_dict["circuits"] = circuits return FEMM_dict