def initFemm(depth=50, sm=False, filename='test.fem'): femm.openfemm() femm.newdocument(0) femm.mi_probdef(0, 'millimeters', 'planar', 1.e-8, depth, 30) femm.mi_hidegrid() # femm.smartmesh(sm) femm.mi_saveas(filename)
def new(self, fname): fe.openfemm() fe.newdocument(0) fe.mi_saveas(fname) self.fname = fname #add air to problem by default air = mat.Material('Air') air.add()
def savetofile(id_solver, freq, stack_length): femm.mi_probdef( freq, 'millimeters', 'planar', 1e-8, # must < 1e-8 stack_length, 18, 1 ) # The acsolver parameter (default: 0) specifies which solver is to be used for AC problems: 0 for successive approximation, 1 for Newton. femm.mi_saveas(dir_femm_temp + 'femm_temp_%d.fem' % (id_solver))
def __init__(self, bHide=False, meshsize=config.MESHSIZE, _i0=config.CURRENT, _id=None): """Initialize a FEMM solver Open FEMM and define the key elements of the magnetic problem. The problem is considered STATIC. All measurements are in MILLIMETERS here ! Keyword Arguments: bHide {bool} -- Either to show or hide the window. Hiding it provides a nice speed improvement (default: {False}) meshsize {number} -- Size of the mesh used for the finite elements. The smaller the more precise, but it comes with a computational cost (default: {1}) _i0 {number} -- Current used in computation. Any value should do, we use 100 to avoid working with very small floats (default: {100}) _id {number} -- Some id used to save the problem, if one requires to track and come back to the FEMM model (default: {None}) """ if _id is not None: self._seed = str(_id) else: self._seed = str(numpy.random.randint(10000)) self.meshsize = meshsize self.Lb = None self.Rbi = None self.Rbo = None self.phi = None self.rho = None self.n = None self.resistance = None self.Lp = None self.Rp = None self.m_vol_fer = None self.mu = None self.mass = None self.espace = None self.wire_type = None self._i0 = _i0 self.bHide = bHide femm.openfemm(bHide) femm.create(0) femm.mi_probdef(0, "millimeters", "axi", 1E-16) femm.mi_saveas("temp/temp" + self._seed + ".fem") femm.mi_addcircprop("Bobine", self._i0, 1) femm.mi_addmaterial("Air", 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0)
femm.mi_getmaterial( 'Air') # fetches the material called air from the materials library femm.mi_getmaterial('N48') femm.mi_selectlabel(10, 3) # assign the material to the block femm.mi_setblockprop( 'N48', 0, 1, '<None>', 90, 0, 0 ) # setblockprop(’blockname’, automesh, meshsize, ’incircuit’, magdir, group, turns) femm.mi_clearselected() femm.mi_selectlabel(1, 1) femm.mi_setblockprop('Air', 0, 1, '<None>', 0, 0, 0) femm.mi_clearselected() femm.mi_zoomnatural() # to check geometry while debuging femm.mi_saveas('ring.fem') # meshing # automaticaly done by the analysis function # analysis femm.mi_analyze() # result data export femm.mi_loadsolution() # plot the flux density along z axis zee = [] bee = [] for n in range(-0, 30): b = femm.mo_getb(0, n)
def simulate(self): self.__updateDimensions() # open FEMM femm.openfemm() femm.main_maximize() # True Steady State # new Magnetostatics document femm.newdocument(0) # Define the problem type. Magnetostatic; Units of mm; 2D planar; # Precision of 10^(-8) for the linear solver; a placeholder of 0 for # the depth dimension, and an angle constraint of 30 degrees femm.mi_probdef(0, 'millimeters', 'planar', 1.e-8, 0, 30) # Import Materials femm.mi_getmaterial('Air') femm.mi_getmaterial(self.magnetType) femm.mi_getmaterial(self.windingType) # Draw geometry # Coil for coil in range(0, self.numStators): corner = Vector(coil * (self.coilLength + self.coilBufferLength), 0) femm.mi_drawrectangle(corner.x, corner.y, corner.x + self.coilLength, corner.y + self.pcbThickness) femm.mi_addblocklabel(corner.x + self.coilLength / 2, corner.y + self.pcbThickness / 2) femm.mi_selectlabel(corner.x + self.coilLength / 2, corner.y + self.pcbThickness / 2) femm.mi_setblockprop(self.windingType, 1, 0, '<None>', 0, 0, self.numWindings) # # Upper Rotor for magnet in range(0, self.numPoles): corner = Vector(magnet * (self.magnetLength + self.magnetBufferLength), self.pcbThickness + self.airGap) femm.mi_drawrectangle(corner.x, corner.y, corner.x + self.magnetLength, corner.y + self.rotorThickness) femm.mi_addblocklabel(corner.x + self.magnetLength / 2, corner.y + self.rotorThickness / 2) femm.mi_selectlabel(corner.x + self.magnetLength / 2, corner.y + self.rotorThickness / 2) if magnet % 2 == 0: femm.mi_setblockprop(self.magnetType, 1, 0, '<None>', 90, 0, 0) else: femm.mi_setblockprop(self.magnetType, 1, 0, '<None>', -90, 0, 0) if magnet == int(self.numPoles / 2): self.testPoint = Vector(corner.x, 0 + self.pcbThickness / 2) # Lower Rotor for magnet in range(0, self.numPoles): corner = Vector(magnet * (self.magnetLength + self.magnetBufferLength), -self.airGap) femm.mi_drawrectangle(corner.x, corner.y, corner.x + self.magnetLength, corner.y - self.rotorThickness) femm.mi_addblocklabel(corner.x + self.magnetLength / 2, corner.y - self.rotorThickness / 2) femm.mi_selectlabel(corner.x + self.magnetLength / 2, corner.y - self.rotorThickness / 2) if magnet % 2 == 0: femm.mi_setblockprop(self.magnetType, 1, 0, '<None>', 90, 0, 0) else: femm.mi_setblockprop(self.magnetType, 1, 0, '<None>', -90, 0, 0) # Define an "open" boundary condition using the built-in function: # Add air block label outside machine femm.mi_makeABC() airLabel = Vector((self.numStators / 2) * (self.coilLength + self.coilBufferLength), 5 * (self.rotorThickness + self.airGap)) femm.mi_addblocklabel(airLabel.x, airLabel.y) femm.mi_selectlabel(airLabel.x, airLabel.y) femm.mi_setblockprop('Air', 1, 0, '<None>', 0, 0, 0) # We have to give the geometry a name before we can analyze it. femm.mi_saveas('alternatorSim.fem') # Now,analyze the problem and load the solution when the analysis is finished femm.mi_analyze() femm.mi_loadsolution() # Now, the finished input geometry can be displayed. # femm.mo_zoom(self.testPoint.x - 2 * self.coilLength, self.testPoint.y - self.coilLength, # self.testPoint.x + 2 * self.coilLength, # self.testPoint.y + self.coilLength) # femm.mo_showdensityplot(1, 0, 1, 0, 'mag') self.fluxDensity = self.getFlux()
while (r < outer_radius): if (r == inner_radius): pass else: r = r + wire_spacing inner_edge = r outer_edge = r + wire_thickness femm.mi_drawarc(inner_edge, 0, outer_edge, 0, 180, EXPERIMENT) #mi_drawarc(x1,y1,x2,y2,angle,maxseg) femm.mi_addarc(outer_edge, 0, inner_edge, 0, 180, EXPERIMENT) #other half of circle femm.mi_addblocklabel(((inner_edge + outer_edge) / 2), 0) femm.mi_selectlabel(((inner_edge + outer_edge) / 2), 0) femm.mi_setblockprop('36awgcopper', automesh, meshsize, 'spiral', 0, 0, 1) femm.mi_clearselected() r = outer_edge #define the air femm.mi_addblocklabel((wall_radius / 2), (wall_distance / 2)) femm.mi_selectlabel((wall_radius / 2), (wall_distance / 2)) femm.mi_setblockprop('air', automesh, meshsize, 0) femm.mi_clearselected() femm.mi_makeABC(1, ((wall_distance + outer_radius + wall_radius) * 2), 0, 0, 0) femm.mi_zoomnatural() # Save the geometry to disk so we can analyze it femm.mi_saveas('spiral.fem')
import femm import matplotlib.pyplot as plt femm.openfemm() femm.opendocument("coilgun.fem") femm.mi_saveas("temp.fem") femm.mi_seteditmode("group") z = [] f = [] for n in range(0, 16): femm.mi_analyze() femm.mi_loadsolution() femm.mo_groupselectblock(1) fz = femm.mo_blockintegral(19) z.append(n * 0.1) f.append(fz) femm.mi_selectgroup(1) femm.mi_movetranslate(0, -0.1) femm.closefemm() plt.plot(z, f) plt.ylabel('Force, N') plt.xlabel('Offset, in') plt.show()
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, is_stator_linear_BH=False, is_rotor_linear_BH=False, kgeo_fineness=1, kmesh_fineness=1, user_FEMM_dict={}, path_save="FEMM_model.fem", is_sliding_band=True, ): """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) is_stator_linear_BH: bool 1 to use linear B(H) curve according to mur_lin, 0 to use the B(H) curve is_rotor_linear_BH: bool 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 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 # 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_ext = machine.get_lamination(is_internal=False) lam_int = machine.get_lamination(is_internal=True) # adding Internal Lamination surface surf_list.extend(lam_int.build_geometry(sym=sym)) # adding the Airgap surface if is_sliding_band: surf_list.extend( get_sliding_band( sym=sym, lam_int=output.simu.machine.get_lamination(True), lam_ext=output.simu.machine.get_lamination(False), ) ) else: surf_list.extend( get_airgap_surface( lam_int=output.simu.machine.get_lamination(True), lam_ext=output.simu.machine.get_lamination(False), ) ) # adding External Lamination surface surf_list.extend(lam_ext.build_geometry(sym=sym)) # 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. femm.openfemm() # 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"]) # 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, is_stator_linear_BH, is_rotor_linear_BH, 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 mesh_dict = get_mesh_param(label, FEMM_dict) surf.draw_FEMM( nodeprop="None", maxseg=FEMM_dict["arcspan"], # max span of arc element in degrees propname="None", elementsize=mesh_dict["element_size"], automesh=mesh_dict["automesh"], hide=False, group=mesh_dict["group"], ) assign_FEMM_surface( surf, prop_dict[label], mesh_dict, machine.rotor, machine.stator ) 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
femm.mi_setblockprop('Iron', 0, 1, '<None>', 0, 0, 0); femm.mi_clearselected() femm.mi_selectlabel(75,0); femm.mi_setblockprop('Coil', 0, 1, 'icoil', 0, 0, 200); femm.mi_clearselected() femm.mi_selectlabel(30,100); femm.mi_setblockprop('Air', 0, 1, '<None>', 0, 0, 0); femm.mi_clearselected() # Now, the finished input geometry can be displayed. femm.mi_zoomnatural() # We have to give the geometry a name before we can analyze it. femm.mi_saveas('coil.fem'); # Now,analyze the problem and load the solution when the analysis is finished femm.mi_analyze() femm.mi_loadsolution() # If we were interested in the flux density at specific positions, # we could inquire at specific points directly: b0=femm.mo_getb(0,0); print('Flux density at the center of the bar is %g T' % b0[1]); b1=femm.mo_getb(0,50); print('Flux density at r=0,z=50 is %g T' % b1[1]); # The program will report the terminal properties of the circuit: # current, voltage, and flux linkage
femm.mi_setblockprop('30 AWG', 1, 0, '<None>', 0, 0, 0) # Primary Coil Circuit and Block Labels femm.mi_clearselected() femm.mi_addcircprop('Primary', 1, 1) # Primary coil, 1A current, series femm.mi_addblocklabel(0.075, 0) femm.mi_selectlabel(0.075, 0) femm.mi_setblockprop('30 AWG', 1, 0, 'Primary', 0, 0, 200) # Lets make a default open air boundary femm.mi_makeABC() input('Press enter to continue...') # Save so we can analyze femm.mi_saveas('lvdt_sweep.fem') femm.mi_analyze() femm.mi_loadsolution() # Show the density plot femm.mo_showdensityplot(1, 0, 0.15, 0, 'mag') ###### MEASURE FLUX IN SIMULATION ###### # Take line integral over radius to get flux / radian in each secondary core # Top Core femm.mo_addcontour(0, 0.21) femm.mo_addcontour(0.05, 0.21) fluxPerRadianTop.append( femm.mo_lineintegral(0)[0] ) # flux/radian (indexing 0 because mo_lineintegral returns both average and total)
def closeFemm(filename='test.fem'): femm.mi_saveas(filename) femm.closefemm()
def sauvegarde_simulation(self): """Sauvegarde de la simulation (à faire avant de simuler)""" femm.mi_saveas('temp/transfo_{:0>5}.fem'.format(self.id))
def saveas(self, fname): fe.mi_saveas(fname) self.fname = fname
def save(self): fe.mi_saveas(self.fname)
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) #femm.mi_clearselected() femm.openfemm(0) femm.opendocument( "setup.fem") # Load a template that has all the required materials already # pre-loaded, i.e when calling 'femm.mi_setblockprop('NdFeB 52 MGOe'.." # This is how it knows where to get that property 'NdFeB 52 MGOe' femm.mi_saveas( "temporary.fem" ) # this changes the working file so that 'template.fem' is always whats in use # This is Wire Gauge Data from MWS industries # it may not line up exactly with the magnet wire in FEMM # so it is good to be aware of this # its 14 to 32 AWG AWG_list = np.linspace(14, 32, 32 - 14 + 1).tolist() OD_list = [ 0.06695, 0.05975, 0.0534, 0.0478, 0.04275, 0.0382, 0.03425, 0.0306, 0.02735, 0.0246, 0.02205, 0.0197, 0.01765, 0.0159, 0.01425, 0.0128, 0.01145, 0.0103, 0.00935 ] ### DEFINE THE COIL inches = 1.0 # Define units
coil_origin_y = Params.D2 - Params.D8 - Params.D3 coil_origins = [ Point(0 - Params.D4 - Params.coil_gap, coil_origin_y), Point(Params.D5 + Params.coil_gap, coil_origin_y), Point(Params.D1 - Params.coil_gap - Params.D4 - Params.D5, coil_origin_y), Point(Params.D1 + Params.coil_gap, coil_origin_y), ] for coil_origin in coil_origins: coil = Rectangle(coil_origin.x, coil_origin.y, Params.D4, Params.D3) coil.assign_material(Params.CoilMaterial, Params.Turns, 'Circuit') # Now, the finished input geometry can be displayed. femm.mi_zoomnatural() # We have to give the geometry a name before we can analyze it. femm.mi_saveas('feladat2.fem') move_vectors = [Point(0, 0)] # do it once without moving for previous, current in zip(Params.core_gap, Params.core_gap[1:]): move_vectors.append(Point(0, previous - current)) forces = {} for core_gap, move_vector in zip(Params.core_gap, move_vectors): bottom_part.move(move_vector.x, move_vector.y) femm.mi_analyze() femm.mi_loadsolution() bottom_part.select_block_for_anal() forces[core_gap] = femm.mo_blockintegral(19) # 19 means force (current, voltage, flux_linkage) = femm.mo_getcircuitproperties('Circuit') inductance = flux_linkage / current
femm.mi_addblocklabel(x_label_arms, y_label_arms) femm.mi_selectlabel(x_label_arms, y_label_arms) femm.mi_setblockprop('Hiperco-50', 0, 1, '<None>', 0, 0, 0) femm.mi_clearselected() femm.mi_addblocklabel(x_label_arms, -y_label_arms) femm.mi_selectlabel(x_label_arms, -y_label_arms) femm.mi_setblockprop('Hiperco-50', 0, 1, '<None>', 0, 0, 0) femm.mi_clearselected() # Air femm.mi_addblocklabel(0, halfHeight + 10) femm.mi_selectlabel(0, halfHeight + 10) femm.mi_setblockprop('Air', 0, 1, '<None>', 0, 0, 0) femm.mi_clearselected() #### Moviles x_movil_bar_label = gapSimulation femm.mi_addblocklabel(x_movil_bar_label, 0) femm.mi_selectlabel(x_movil_bar_label, 0) femm.mi_setblockprop('Hiperco-50', 0, 1, '<None>', 0, 0, 0) femm.mi_clearselected() femm.mi_saveas('auto-htutor.fem') x = input()
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
def calc_inductance(tg, currents, inductances=(None, None), **kwargs): ''' Setup of magneto-static problem in femm to calculate inductance and resistance of planar transformer. Args: tg (:obj:'TransformerGeometry'): tg contains all geometry information of the transformer. currents (list of float): currents in the primary and secondary side circuits on the form [I_prim, I_sec]. inductances (list of float): self-inductances of the primary and secondary side circuits on the form [L_prim, L_sec]. Used to calculate mutual inductance. Returns: (inductance, resistance): calculated self or mutual inductance and equivalent series resistance of either primary or secondary circuit. ''' etiquettes_dict = {} # Dictionary to store coordinates of nodes # initialitiation of the magneto-static problem boundary_radius = 2 * tg.radius_dielectric initial_setup(boundary_radius, currents, **kwargs) # draw geometry and add block labels add_conductors(tg, etiquettes_dict) add_pcbs(tg) add_isolation(tg) add_block_labels(tg, etiquettes_dict) # mi zoomnatural() # From manual: zooms to a “natural” view with sensible extents. femm.mi_zoomnatural() # Saving geometry file femm.mi_saveas('inductance_transformer.fem') # Meshing and analysis # From manual: Note that it is not necessary to run mesh before performing # an analysis, as mi_analyze() will make sure the mesh is up to date before # running an analysis. # mi analyze(flag) # From manual: runs fkern to solve the problem. The flag parameter controls # whether the fkern window is visible or minimized. For a visible window, # either specify no value for flag or specify 0. For a minimized window, # flag should be set to 1. femm.mi_analyze(1) # Post-processing femm.mi_loadsolution() # mo_seteditmode(mode) # From manual: Sets themode of the postprocessor to point, contour, or area # mode. Valid entries for mode are "point", "contour", and "area". femm.mo_seteditmode('area') # mo_blockintegral(type) # From manual: Calculate a block integral for the selected blocks # Type Definition # 0 A · J # 1 A # 2 Magnetic field energy # 3 Hysteresis and/or lamination losses # 4 Resistive losses # 5 Block cross-section area # 6 Total losses # 7 Total current # 8 Integral of Bx (or Br) over block # 9 Integral of By (or rBz) over block # 10 Block volume # ... # mo_getcircuitproperties("circuit") # From manual: Used primarily to obtain impedance information associated # with circuit properties. Properties are returned for the circuit property # named "circuit". Three values are returned by the function. In order, # these results are: # – current Current carried by the circuit # – volts Voltage drop across the circuit # – flux_re Circuit’s flux linkage # mo_groupselectblock(n) # From manual: Selects all the blocks that are labeled by block labels # that are members of group n. If no number is specified (i.e. # mo_groupselectblock() ), all blocks are selected. # Calculate the inductance of the circuit with non-zero current. If both # currents are given, we calculate the mutual inductance. L1, L2 = inductances if (currents[0] > 0) and (currents[1] == 0): circ = femm.mo_getcircuitproperties('phase_prim') resistance = circ[1].real inductance = abs(circ[2] / circ[0]) elif (currents[0] == 0) and (currents[1] > 0): circ = femm.mo_getcircuitproperties('phase_sec') resistance = circ[1].real inductance = abs(circ[2] / circ[0]) else: femm.mo_groupselectblock() # axisymmetric problem, integral is multiplied by 2 Wm = femm.mo_blockintegral(2) * 2 inductance = ((Wm - 0.5 * (L1 * currents[1]**2 + L2 * currents[0]**2)) / (currents[0] * currents[1])) resistance = 0 femm.mo_clearblock() if kwargs.get('close') is True: femm.closefemm() return (inductance, resistance)
def sauvegarde_simulation(self): """Sauvegarde de la simulation (à faire avant de simuler)""" femm.mi_saveas('transfo.fem')