Ejemplo n.º 1
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)
Ejemplo n.º 2
0
def set_FEMM_circuit_prop(circuits, Clabel, I, is_mmf, Npcpp, j_t0):
    """Create or update the property of a circuit

    Parameters
    ----------
    circuits: list
        list the name of all circuits
    label: str
        the label of the related surface
    q_id : int
        Index of the phase
    I : Data
        Lamination currents waveforms
    is_mmf: bool
        1 to compute the lamination magnetomotive
        force / lamination magnetic field
    Npcpp: int
        number of parallel circuits  per phase (maximum 2p)
    j_t0 : int
        time step for winding current calculation

    Returns
    -------
    circuits : list
        list the name of the circuits in FEMM

    """

    q_id = int(Clabel[5:])
    if I is not None:
        I = I.values
    if Clabel in circuits:
        if I is not None and I.size != 0 and LA.norm(I) != 0:
            # Update existing circuit
            femm.mi_modifycircprop(Clabel, 1, is_mmf * I[q_id, j_t0] / Npcpp)
    else:
        # Create new circuit
        femm.mi_addcircprop(Clabel, 0, 1)
        circuits.append(Clabel)

    return circuits
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
            -halfWidth + leftCurrentGap + (iman *
                                           (bodyWidth + innerStatorGap)),
            (halfHeight - barHeight - currentHeight) * up_down(side),
            -halfWidth + leftCurrentGap + currentWidth +
            (iman * (bodyWidth + innerStatorGap)),
            (halfHeight - barHeight - currentHeight) * up_down(side),
        )

        current_x_label = -halfWidth + leftCurrentGap + (currentWidth / 2) + (
            iman * (bodyWidth + innerStatorGap))
        current_y_label = (halfHeight - barHeight -
                           (currentHeight / 2)) * up_down(side)

        femm.mi_addblocklabel(current_x_label, current_y_label)

        femm.mi_addcircprop(f"circuit_{side}_{iman}", 30, 1)

        femm.mi_selectlabel(current_x_label, current_y_label)
        femm.mi_setblockprop('Coil', 0, 1, f"circuit_{side}_{iman}", 0, 0,
                             500 * up_down(side) * up_down(iman % 2))
        femm.mi_clearselected()

        femm.mi_drawline(
            -halfWidth + leftCurrentGap + bodyWidth + (2 * currentWidth) +
            (iman * (bodyWidth + innerStatorGap)),
            (halfHeight - barHeight) * up_down(side),
            -halfWidth + leftCurrentGap + bodyWidth + (2 * currentWidth) +
            (iman * (bodyWidth + innerStatorGap)),
            (halfHeight - barHeight - currentHeight) * up_down(side),
        )
Ejemplo n.º 5
0
# A more interesting material to add is the iron with a nonlinear
# BH curve.  First, we create a material in the same way as if we 
# were creating a linear material, except the values used for 
# permeability are merely placeholders.

femm.mi_addmaterial('Iron', 2100, 2100, 0, 0, 0, 0, 0, 1, 0, 0, 0);

# A set of points defining the BH curve is then specified.
bdata = [ 0.,0.3,0.8,1.12,1.32,1.46,1.54,1.62,1.74,1.87,1.99,2.046,2.08]; 
hdata = [ 0, 40, 80, 160, 318, 796, 1590, 3380, 7960, 15900, 31800, 55100, 79600];
for n in range(0,len(bdata)):
	femm.mi_addbhpoint('Iron', bdata[n],hdata[n]);

# Add a "circuit property" so that we can calculate the properties of the
# coil as seen from the terminals.
femm.mi_addcircprop('icoil', 20, 1);

# Apply the materials to the appropriate block labels
femm.mi_selectlabel(5,0);
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.
Ejemplo n.º 6
0
def create_FEMM_circuit(label, is_eddies, lam, I, is_mmf, j_t0, materials):
    """Set in FEMM circuits property
    
    Parameters
    ----------
    label :
        label of the surface
    sym :
        integer for symmetry
    is_eddies :
        1 to calculate eddy currents
    lam : LamSlotWind
        Lamination to set the winding
    I : ndarray
        Lamination currents waveforms
    is_mmf :
        1 to compute the lamination magnetomotive
        force / lamination magnetic field
    j_t0 :
        time step for winding current calculation@type integer
    materials :
        list of materials already created in FEMM
    
    Returns
    -------
    (str, list)
        the property of the surface having label as surf.label and
        materials
    """

    is_defcirc = 1  # 1 to define circuits (necessary for eddy current loss
    kJ = 1
    # estimation in AC mode, not necessary for magnetostatics)
    Zs = lam.slot.Zs
    rho = lam.mat_type.elec.rho  # Resistivity at 20°C
    wind_mat = lam.winding.comp_connection_mat(Zs)
    # number of parallel circuits  per phase (maximum 2p)
    Npcpp = lam.winding.Npcpp
    Ntcoil = lam.winding.Ntcoil  # number of turns per coil
    Swire = lam.winding.conductor.comp_surface()
    Sact = lam.winding.conductor.comp_active_surface()
    if "Rotor" in label:  # winding on the rotor
        Jlabel = "Jr"
        Clabel = "Circr"
    else:
        Jlabel = "Js"
        Clabel = "Circs"

    st = label.split("_")
    Nr = int(st[1][1:])  # zone radial coordinate
    Nt = int(st[2][1:])  # zone tangential coordinate
    pos = int(st[3][1:])  # Zone slot number coordinate
    A = wind_mat[Nr, Nt, pos, :]

    for zz in range(len(A)):  # search  for the phase of the winding
        if A[zz] != 0:
            q = zz
    # circuit definition
    if is_defcirc:
        if I.size == 0 or LA.norm(I) == 0:
            femm.mi_addcircprop(Clabel + str(q), 0, 1)  # series connected
        else:
            femm.mi_addcircprop(Clabel + str(q), is_mmf * I[j_t0][q] / Npcpp,
                                1)  # series connected

    # definition of armature field current sources and  circuits
    s = sign(wind_mat[Nr, Nt, pos, q])  # same as the sign of Cwind1
    if s == 1:
        cname = Jlabel + str(q) + "+"
    else:
        cname = Jlabel + str(q) + "-"

    if LA.norm(I) == 0:
        Jcus = 0
    else:
        # equivalent stator current density [A/mm2]
        Jcus = kJ * 1e-6 * Ntcoil * (I[j_t0, q] / Npcpp) * is_mmf / Sact

    if cname not in materials:
        # adding new current source material if necessary
        femm.mi_addmaterial(
            cname,
            1,
            1,
            0,
            s * Jcus,
            is_eddies * 1e-6 / rho,
            0,
            0,
            1,
            0,
            0,
            0,
            1,
            sqrt(4 * Swire / pi),
        )
        materials.append(cname)

    return cname, materials
Ejemplo n.º 7
0
    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
AWG_coil = 22
od_wire = OD_list[AWG_list.index(AWG_coil)]  # find the AWG

N_layers = 6  # Number of stacked layers of wire
id_coil = 1 * inches  # inner coil diameter
Lc = 0.77 * inches  # Length of the Coil
N_turns = round(Lc / od_wire)  # Define lengthwise turns
current = -6  # Define the amount of current in the coil
femm.mi_addcircprop('icoil', current, 1)  # Add it to the FEMM model

od_coil = id_coil + 2 * N_layers * od_wire  # outer coil diameter

coil_group_number = 5  # Define coil number different as magnet
# Call this function to draw a box with rounded corners
# I find this introduces less errors
coil_center_x = id_coil / 2 + (od_coil - id_coil) / 4
coil_center_y = 0
drawroundedcorner_box(femm, coil_group_number, (od_coil - id_coil) / 2, Lc,
                      coil_center_x, coil_center_y, od_wire, 0)
# With segments now drawn, label it
femm.mi_addblocklabel(coil_center_x,
                      coil_center_y)  # Create a label within the coil segments
femm.mi_selectlabel(coil_center_x, coil_center_y)  # Select that label
femm.mi_setblockprop('22 AWG', 0, 1, 'icoil', 0, 0,
automesh = 1
meshsize = 30
minangle = 1
# Set up problem type. This sets up problem as an axisymmetric problem with units of micrometers
femm.mi_probdef(0, 'micrometers', 'axi', 10**(-8), 0, minangle, 0)

# Add materials to our workspace
femm.mi_addmaterial('magnet', 1.05, 1.05, 922850, 0, 0.667, 0, 0, 1, 0, 0, 0)
femm.mi_addmaterial('air', 1, 1, 0)
femm.mi_addmaterial('36awgcopper', 1, 1, 0,
                    i / ((wire_thickness / 2)**(2) * 3.14), 58, 0, 0, 1, 3, 0,
                    0, 1, 127)
#change J applied current

#define circuit with current i in series
femm.mi_addcircprop('spiral', i, 1)

#draw and label magnet wall
femm.mi_drawrectangle(0, wall_distance, wall_radius,
                      (wall_distance + wall_thickness))
femm.mi_addblocklabel(wall_radius / 2, (wall_distance + wall_thickness / 2))
femm.mi_selectlabel(wall_radius / 2, (wall_distance + wall_thickness / 2))
femm.mi_setblockprop('magnet', automesh, meshsize, 0, 270, 0, 0)
femm.mi_clearselected()

#draw and label spiral cross section
while (r < outer_radius):
    if (r == inner_radius):
        pass
    else:
        r = r + wire_spacing
Ejemplo n.º 9
0
    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

air_width = 2 * Params.D4 + Params.D1 + Params.coil_gap * 2 + 2 * Params.air_margin
air_height = 2 * Params.air_margin + Params.D7 + Params.core_gap[-1] + Params.D2
air_rectangle = Rectangle(
    0 - Params.D4 - Params.coil_gap - Params.air_margin,
    0 - Params.core_gap[-1] - Params.D7 - Params.air_margin, air_width,
    air_height)
air_rectangle.assign_material(
    'Air', 0, 0,
    Point(Params.D1 / 2,
Ejemplo n.º 10
0
    femm.mi_clearselected()
    femm.mi_addblocklabel(0.02, d)
    femm.mi_selectlabel(0.02, d)
    femm.mi_setblockprop('Pure Iron', 1, 0, '<None>', 0, 0, 0)

    # Secondary Coil Copper Labels
    femm.mi_clearselected()
    femm.mi_addblocklabel(0.075, 0.21)
    femm.mi_addblocklabel(0.075, -0.21)
    femm.mi_selectlabel(0.075, 0.21)
    femm.mi_selectlabel(0.075, -0.21)
    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
Ejemplo n.º 11
0
def makeCircuit(name, current=0, series=1):
    femm.mi_addcircprop(name, current, series)