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 __init__(self): self.gap_width = None self.gap_height = None self.core_width = None self.inner_radius = None self.outer_radius = None self.core_radius = None femm.openfemm() femm.newdocument(0) femm.mi_probdef(0, 'millimeters', 'axi', 1.e-8, 0, 30)
def main(): fe.openfemm() fe.newdocument(0) rotor = PM_Rotor(dri=50, dm=10, dmp=3, alpha_m=60, p=2, OR=100) rotor.draw() rotor.set_materials('test', 'test') fe.mi_zoomnatural()
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 creation_FEMM(self): """Méthode permettant de générer une simulation FEMM""" # Permet de lancer le logiciel FEMM. femm.openfemm() # Création d'un problème de magnétostatique ( = 0 ). femm.newdocument(0) # Définition du problème. Magnetostatique, Unités mètres, Problème plan, # Precision de 10^(-8), longueur active de 1m, angle de contraintes de 30deg femm.mi_probdef(0, 'meters', 'planar', 1e-8, 1, 30)
# that are 20 um wide and 2 um thick, separated by a 4 um # distance. The traces are laying centered atop of a 20 um # by 200 um slab with a relative permeability of 4. The # slab rests on an infinite ground plane. We will consider # a 1m depth in the into-the-page direction. # # This program sets up the problem and solves two different # cases with different voltages applied to the conductors # Becuase of symmetry, this yields enough information to # deduce the 4x4 capacitance matrix # Start up and connect to FEMM femm.openfemm() # Create a new electrostatics problem femm.newdocument(1) # 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
import femm import sys femm.openfemm() femm.newdocument(0) simulation = sys.argv[1] # define problem parameters femm.mi_probdef(0, 'millimeters', 'planar', 1.e-8, 0, 30) def up_down(side): return ((-2 * side) + 1) def convert_measures(cm): return cm * 400 / 19 ## Materials femm.mi_addmaterial('Air', 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0) femm.mi_addmaterial('Coil', 1, 1, 0, 0, 58 * 0.65, 0, 0, 1, 0, 0, 0) femm.mi_addmaterial('Hiperco-50', 3520, 3520, 0, 0, 0, 0, 0, 1, 0, 0, 0) femm.mi_addmaterial('Magnet', 1.05, 1.05, 905659, 0, 0.667, 0, 0, 1, 0, 0, 0) bdata = [ 0.000000, 0.290730, 0.428710, 0.589560, 0.796270, 1.020100, 1.198100, 1.398900, 1.559600, 1.783500, 1.898500, 1.990700, 2.054400, 2.118400, 2.147700, 2.177000, 2.206500, 2.241700, 2.271200, 2.289000, 2.312600, 2.341000 ]
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 initial_setup(limite_externe, voltage_high, **kwargs): '''Start femm and setup problem definition and set boundary condition.''' if kwargs.get('hide') is True: femm.openfemm(1) femm.main_minimize() else: femm.openfemm() # newdocument(doctype) # From manual: Creates a new preprocessor document and opens up a new # preprocessor window. Specify doctype to be 0 for a magnetics problem, 1 # for an electrostatics problem, 2 for a heat flow problem, or 3 for a # current flow problem. An alternative syntax for this command is # create(doctype) femm.newdocument(1) # ei probdef(units,type,precision,(depth),(minangle)) # From manual: changes the problem definition. The units parameter # specifies the units used for measuring length in the problem domain. # Valid "units" entries are "inches", "millimeters", "centimeters", "mils", # "meters, and "micrometers". Set problemtype to "planar" for a 2-D planar # problem, or to "axi" for an axisymmetric problem. The precision parameter # dictates the precision required by the solver. For example, entering # 1.E-8 requires the RMS of the residual to be less than 10^-8. A fourth # parameter, representing the depth of the problem in the into-thepage # direction for 2-D planar problems, can also be specified for planar # problems. A sixth parameter represents the minimum angle constraint sent # to the mesh generator. if 'precision' in kwargs: precision = kwargs['precision'] else: precision = 1e-9 if 'min_angle' in kwargs: min_angle = kwargs['min_angle'] else: min_angle = 30 femm.ei_probdef('millimeters', 'axi', precision, 100, min_angle) # Circuit parameters # From manual: ei_addconductorprop("conductorname", Vc, qc, conductortype) # adds a new conductor property with name "conductorname" with either a # prescribed voltage or a prescribed total charge. Set the unused property # to zero. The conductortype parameter is 0 for prescribed charge and 1 for # prescribed voltage femm.ei_addconductorprop('high', voltage_high, 0, 1) femm.ei_addconductorprop('zero', 0, 0, 1) # Add materials properties used in the simulation # ei_addmaterial(’matname’, ex, ey, qv) # From manual: adds a new material with called ’matname’ with the material # properties: # ex Relative permittivity in the x- or r-direction. # ey Relative permittivity in the y- or z-direction. # qv Volume charge density in units of C/m3 femm.ei_addmaterial('air', 1, 1, 0) femm.ei_addmaterial('fr4', 4.4, 4.4, 0) femm.ei_addmaterial('polysterimide', 3.5, 3.5, 0) femm.ei_addmaterial('teflon', 2.1, 2.1, 0) femm.ei_addmaterial('silgel', 2.7, 2.7, 0) femm.ei_addmaterial('midel', 3.15, 3.15, 0) if 'material' in kwargs: for m in kwargs['material']: femm.ei_addmaterial(*m) # Boundary conditions # ei makeABC(n,R,x,y,bc) # From manual: creates a series of circular shells that emulate the # impedance of an unbounded domain (i.e. an Improvised Asymptotic Boundary # Condition). The n parameter contains the number of shells to be used # (should be between 1 and 10), R is the radius of the solution domain, and # (x,y) denotes the center of the solution domain. The bc parameter should # be specified as 0 for a Dirichlet outer edge or 1 for a Neumann outer # edge. If the function is called without all the parameters, the function # makes up reasonable values for the missing parameters. femm.ei_makeABC(7, limite_externe, 0, 0, 0)
# an iron bar 80 mm long with a radius of 10 mm centered co- # axially with the coil. The objective of the analysis is to # determine the flux density at the center of the iron bar, # and to plot the field along the r=0 axis. This analysis # defines a nonlinear B-H curve for the iron and employs an # asymptotic boundary condition to approximate an "open" # boundary condition on the edge of the solution domain. import femm import matplotlib.pyplot as plt # 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); # Define the problem type. Magnetostatic; Units of mm; Axisymmetric; # 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', 'axi', 1.e-8, 0, 30); # Draw a rectangle for the steel bar on the axis; femm.mi_drawrectangle(0, -40, 10, 40); # Draw a rectangle for the coil; femm.mi_drawrectangle(50, -50, 100, 50); # Define an "open" boundary condition using the built-in function: femm.mi_makeABC()
if where is None: where = self.get_midpoint() self.addblocklabel(where.x, where.y) self.selectlabel(where.x, where.y) if self.problemType is ProblemType.ElectroStatic: femm.ei_setblockprop(material, 1, 0, self.index) elif self.problemType is ProblemType.MagnetoStatic: assert turns is not None assert circuit is not None # blockname, automesh, meshsize, incircuit, magdir, group, turns femm.mi_setblockprop(material, 1, 0, circuit, 0, self.index, turns) self.clearselected() if __name__ == "__main__": femm.openfemm() # We need to create a new Electrostatic (ei) document to work on. femm.newdocument(ProblemType.ElectroStatic.value) femm.ei_addmaterial('Air', 1, 1, 0) # Define the problem type. Units of mm; Axisymmetric; # Precision of 10^(-8) for the linear solver; a placeholder of 0 for # the depth dimension, and an angle constraint of 30 degrees femm.ei_probdef('centimeters', 'planar', 1.e-8, 0, 30) Rectangle.problemType = ProblemType.ElectroStatic rectangle = Rectangle(0, 0, 10, 10) rectangle.assign_material('Air') femm.ei_zoomnatural() femm.closefemm()
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()
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
D9 = 3.6 D10 = 2 Depth = 4 Turns = 210 core_gap = [0.1, 0.5, 1, 2] coil_gap = 0.05 air_margin = 1 ExcitationCurrent = 3 CoreMaterial = "M-15 Steel" CoilMaterial = "Copper" Params.core_gap.sort() femm.openfemm() femm.newdocument(ProblemType.MagnetoStatic.value) Rectangle.problemType = ProblemType.MagnetoStatic femm.mi_probdef(0, 'centimeters', 'planar', 1.e-8, Params.Depth, 30) femm.mi_getmaterial(Params.CoreMaterial) femm.mi_getmaterial(Params.CoilMaterial) femm.mi_getmaterial('Air') femm.mi_addcircprop('Circuit', Params.ExcitationCurrent, 1) # 0 = paralel, 1 = series # name, A0, A1, A2, Phi, Mu, Sig, c0, c1, BdryFormat, ia, oa femm.mi_addboundprop('Boundary', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # define air around everything
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
def initial_setup(boundary, currents, **kwargs): '''Start femm and setup problem definition and set boundary condition.''' if kwargs.get('hide') is True: femm.openfemm(1) femm.main_minimize() else: femm.openfemm() # newdocument(doctype) # From manual: Creates a new preprocessor document and opens up a new # preprocessor window. Specify doctype to be 0 for a magnetics problem, 1 # for an electrostatics problem, 2 for a heat flow problem, or 3 for a # current flow problem. An alternative syntax for this command is # create(doctype) femm.newdocument(0) # ei probdef(units,type,precision,(depth),(minangle)) # From manual: changes the problem definition. The units parameter # specifies the units used for measuring length in the problem domain. # Valid "units" entries are "inches", "millimeters", "centimeters", "mils", # "meters, and "micrometers". Set problemtype to "planar" for a 2-D planar # problem, or to "axi" for an axisymmetric problem. The precision parameter # dictates the precision required by the solver. For example, entering # 1.E-8 requires the RMS of the residual to be less than 10^-8. A fourth # parameter, representing the depth of the problem in the into-thepage # direction for 2-D planar problems, can also be specified for planar # problems. A sixth parameter represents the minimum angle constraint sent # to the mesh generator. if 'frequency' in kwargs: freq = kwargs['frequency'] else: freq = 6.78e6 if 'precision' in kwargs: precision = kwargs['precision'] else: precision = 5e-9 if 'min_angle' in kwargs: min_angle = kwargs['min_angle'] else: min_angle = 30 femm.mi_probdef(freq, 'millimeters', 'axi', precision, 50, min_angle) # Circuit parameters # mi addcircprop("circuitname", i, circuittype) # From manual: adds a new circuit property with name "circuitname" with a # prescribed current, i. The circuittype parameter is 0 for a # parallel-connected circuit and 1 for a series-connected circuit. # The currents in the primary and secondary circuits are set I1, I2 = currents femm.mi_addcircprop('phase_prim', I1, 1) femm.mi_addcircprop('phase_sec', I2, 1) # Add materials properties used in the simulation # mi addmaterial("materialname", mu x, mu y, H c, J, Cduct, Lam d, # Phi hmax, lam fill, LamType, Phi hx, Phi hy,NStrands,WireD) # From manual: adds a newmaterial with called "materialname" with the # material properties: # – mu x Relative permeability in the x- or r-direction. # – mu y Relative permeability in the y- or z-direction. # – H c Permanent magnet coercivity in Amps/Meter. # – J Real Applied source current density in Amps/mm2. # – Cduct Electrical conductivity of the material in MS/m. # – Lam d Lamination thickness in millimeters. # – Phi hmax Hysteresis lag angle in degrees, used for nonlinear BH curves. # – Lam fill Fraction of the volume occupied per lamination that is # actually filled with iron (Note that this parameter defaults to 1 the # femm preprocessor dialog box because, by default, iron completely fills # the volume) # – Lamtype Set to # ? 0 – Not laminated or laminated in plane # ? 1 – laminated x or r # ? 2 – laminated y or z # ? 3 – Magnet wire # ? 4 – Plain stranded wire # ? 5 – Litz wire # ? 6 – Square wire # – Phi hx Hysteresis lag in degrees in the x-direction for linear problems # – Phi hy Hysteresis lag in degrees in the y-direction for linear problems # – NStrands Number of strands in the wire build. Should be 1 for Magnet or # Square wire. # – WireD Diameter of each wire constituent strand in millimeters. femm.mi_addmaterial('air', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) femm.mi_addmaterial('fr4', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) femm.mi_addmaterial('copper', 1, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0) femm.mi_addmaterial('polysterimide', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) femm.mi_addmaterial('teflon', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) femm.mi_addmaterial('silgel', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) if 'material' in kwargs: for m in kwargs['material']: femm.mi_addmaterial(*m) # Boundary condition # ei makeABC(n,R,x,y,bc) # From manual: creates a series of circular shells that emulate the # impedance of an unbounded domain (i.e. an Improvised Asymptotic Boundary # Condition). The n parameter contains the number of shells to be used # (should be between 1 and 10), R is the radius of the solution domain, and # (x,y) denotes the center of the solution domain. The bc parameter should # be specified as 0 for a Dirichlet outer edge or 1 for a Neumann outer # edge. If the function is called without all the parameters, the function # makes up reasonable values for the missing parameters. femm.mi_makeABC(7, boundary, 0, 0, 0)
# The problem consider an axisymmetric magnetostatic problem # of a 'N48' neodymium ring magnet with a height of 5mm, an # inner radius of 6 mm, and an outer radius of 15 mm. The objective of the analysis is to # determine the flux density at the center of the ring magnet, # and to plot the field along the r=0 axis. This analysis # uses Femm materials library for material properties and employs an # asymptotic boundary condition to approximate an "open" # boundary condition on the edge of the solution domain. import femm import matplotlib.pyplot as plt femm.openfemm() # create an instance of femm without GUI # problem definition femm.newdocument(0) # create new magnetic problem preprocessor document femm.mi_probdef( 0, 'millimeters', 'axi', 1.e-8, 0, 30 ) # Define the problem type. Magnetostatic; Units of mm; Axisymmetric; Precision of 10^(-8) for the linear solver; a placeholder of 0 for the depth dimension, and an angle constraint of 30 degrees # geometry definition femm.mi_drawrectangle(6, 0, 15, 5) # draw a rectangle for the ring magnet; # boundaries conditions femm.mi_makeABC() # simulate an open boundary condition # materials properties femm.mi_addblocklabel(1, 1) # air block (airbox) femm.mi_addblocklabel(10, 3) # ring block (neodymium)