Esempio n. 1
0
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)
Esempio n. 2
0
    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()
Esempio n. 3
0
 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)
Esempio n. 4
0
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 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)
Esempio n. 6
0
    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)
Esempio n. 7
0
# The objective of this program is to find the capacitance
# matrix associated with a set of four microstrip lines on
# top of a dielectric substrate. We will consider lines
# 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)
Esempio n. 8
0
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)
Esempio n. 9
0
# of a cylindrical coil with an axial length of 100 mm, an
# inner radius of 50 mm, and an outer radius of 100 mm.  The
# coil has 200 turns and the coil current is 20 Amps. There is
# 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);
Esempio n. 10
0
# # dir_run = r'D:\femm42\PS_Qr36_NoEndRing_M15_17303l_DPNV\static-femm/'
# dir_run = r'D:\femm42\PS_Qr32_NoEndRing_M19Gauge29_DPNV_1e3Hz\static-femm\sweeping/'

id_solver = int(sys.argv[1])
number_of_instances = int(sys.argv[2])
dir_run = sys.argv[3]
print('ParaSolve', id_solver)

handle_torque = open(dir_run + "static_results_%d.txt" % (id_solver), 'a')
# handle_stator_B_data = open(dir_run + "static_results_stator_B_data_%d.txt"%(id_solver), 'a') # use 'ab' for np.savetxt https://stackoverflow.com/questions/27786868/python3-numpy-appending-to-a-file-using-numpy-savetxt
# handle_rotor_B_data = open(dir_run + "static_results_rotor_B_data_%d.txt"%(id_solver), 'a')

fem_file_list = os.listdir(dir_run)
fem_file_list = [f for f in fem_file_list if '.fem' in f]

femm.openfemm(True)  # bHide
femm.callfemm_noeval('smartmesh(0)')

# this is essential to reduce elements counts from >50000 to ~20000.
print('mi_smartmesh is off')

for i in range(id_solver, len(fem_file_list), number_of_instances):

    output_file_name = dir_run + fem_file_list[i][:-4]

    if not os.path.exists(output_file_name + '.ans'):
        tic = time()
        femm.opendocument(output_file_name + '.fem')
        # femm.callfemm_noeval('mi_smartmesh(0)')
        try:
            # femm.mi_createmesh() # [useless]
Esempio n. 11
0
        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)

        #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,
Esempio n. 12
0
    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()
Esempio n. 13
0
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
Esempio n. 14
0
# if __name__ == '__main__':
#     DEBUG_MODE = True

if DEBUG_MODE == False:
    number_of_instantces = int(sys.argv[1])
    dir_femm_temp = sys.argv[2]
    stack_length = float(sys.argv[3])
    VAREPSILON = 0.255  # difference between 1st and 2nd max torque slip frequencies
else:
    #debug
    number_of_instantces = 5
    dir_femm_temp = "D:/OneDrive - UW-Madison/c/csv_opti/run#114/femm_temp/"  # modify as expected
    stack_length = 186.4005899999999940
    VAREPSILON = 0.02

femm.openfemm(True)
femm.opendocument(dir_femm_temp + 'femm_temp.fem')

# here, the only variable for an individual is frequency, so pop = list of frequencies
freq_begin = 1.  # hz
freq_end = freq_begin + number_of_instantces - 1.  # 5 Hz

list_torque = []
list_slipfreq = []
list_solver_id = []
list_done_id = []
count_loop = 0
while True:
    # freq_step can be negative!
    freq_step = (freq_end - freq_begin) / (number_of_instantces - 1)
Esempio n. 15
0
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
Esempio n. 16
0
# This program is inspired of pyfemm exemple demo2, although a lot simpler.
# 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)
Esempio n. 17
0
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)
Esempio n. 18
0
    def open_previous(self, fname):

        fe.openfemm()
        fe.opendocument(fname)
        self.fname = fname