Example #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)
Example #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()
Example #3
0
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)
Example #5
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)
Example #6
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()
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')
Example #8
0
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()
Example #9
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
Example #10
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.
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 
Example #11
0
    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)
Example #12
0
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))
Example #14
0
    def saveas(self, fname):

        fe.mi_saveas(fname)
        self.fname = fname
Example #15
0
    def save(self):

        fe.mi_saveas(self.fname)
Example #16
0
        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
Example #17
0
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()
Example #19
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
Example #20
0
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)
Example #21
0
    def sauvegarde_simulation(self):
        """Sauvegarde de la simulation (à faire avant de simuler)"""

        femm.mi_saveas('transfo.fem')