Beispiel #1
0
def extract_magnetic_field_map(range_a, range_o, delta_abscissa,
                               delta_ordinate):
    # todo: calculate the norm of b instead of transversal fetching
    # extract the transverse component of the magnetic flux of the solution loaded in femm (last '.ans' file created)
    # return the data as a 2D numpy array

    na = int((range_a[1] - range_a[0]) /
             delta_abscissa) + 1  # number of point on the abscissa axis
    no = int((range_o[1] - range_o[0]) /
             delta_ordinate) + 1  # number of point on the ordinate axis

    abscissa_axis = numpy.linspace(range_a[0], range_a[1],
                                   na)  # abscissa coordinates of data
    ordinate_axis = numpy.linspace(range_o[0], range_o[1], no)

    # coordinates_list = []
    b_list = []

    for j in abscissa_axis:
        for q in ordinate_axis:
            # coordinates_list.append((j, q))
            b_list.append(
                femm.mo_getb(j, q)
                [1])  # fetch the data in the femm solution for each data point

    b_map = numpy.asarray(b_list).reshape(na, no)
    return b_map
    def calcul_pertes_fer(self):
        """Calcul des pertes fer de l'inductance"""

        FREQUENCE = 50

        # Coefficients des pertes fer :
        # Pertes volumique = ALPHA*B**1.5*FREQUENCE**1.5+
        #                    BETA*B**2*FREQUENCE+
        #                    GAMMA*B**2*FREQUENCE**2
        ALPHA = 1.1119e-4
        BETA = 1.688e-4
        GAMMA = 4.361e-4

        # Mesure du Bx, By au milieu de la dent centrale
        b_x, b_y = femm.mo_getb(0, self.hauteur / 4)

        b_moy = np.sqrt(b_x**2 + b_y**2)

        pertes_fer_masse = (ALPHA * b_moy**1.5 * FREQUENCE**1.5 +
                            BETA * b_moy**2 * FREQUENCE +
                            GAMMA * b_moy**2 * FREQUENCE**2)

        pertes_fer = pertes_fer_masse * self.calcul_masse_fer()

        return pertes_fer
    def getFluxRiemanSum(self):
        riemanSum = 0
        interval = self.magnetLength / 200

        for i in range(200):
            x = self.testPoint.x + interval * i
            pointFlux = femm.mo_getb(x, self.testPoint.y)[1]
            riemanSum += .001 * (interval * pointFlux)
        return abs(riemanSum)
    def getFlux(self):
        flux = []
        offsets = []

        for i in range(200):
            offset = i * self.numPoles * self.unbufferedMagnetLength / 200
            b = femm.mo_getb(offset, self.testPoint.y)
            flux.append(b[1])
            offsets.append(offset)

        return max(flux)
Beispiel #5
0
    def pertes_fer(self):
        """ Calcul des pertes fer de l'inductance """

        FREQUENCE = 50  # (en Hz)

        # Mesure du Bx, By au milieu de la dent centrale
        b_x, b_y = femm.mo_getb(0, self.hauteur / 4)
        b_moy = np.sqrt(b_x**2 + b_y**2)
        # TODO : faire la moyenne de Bx et By sur tout le volume
        # plutôt que juste dans la dent ?

        return self._interp_pertes_fer(b_moy)
Beispiel #6
0
def solve_FEMM(self, output, sym, FEMM_dict):

    # Loading parameters for readibilitys
    angle = output.mag.angle

    L1 = output.simu.machine.stator.comp_length()
    Nt_tot = output.mag.Nt_tot  # Number of time step
    Na_tot = output.mag.Na_tot  # Number of angular step
    save_path = self.get_path_save(output)

    if (hasattr(output.simu.machine.stator, "winding")
            and output.simu.machine.stator.winding is not None):
        qs = output.simu.machine.stator.winding.qs  # Winding phase number
        Npcpp = output.simu.machine.stator.winding.Npcpp
        Phi_wind_stator = zeros((Nt_tot, qs))
    else:
        Phi_wind_stator = None

    # Create the mesh
    femm.mi_createmesh()

    # Initialize results matrix
    Br = zeros((Nt_tot, Na_tot))
    Bt = zeros((Nt_tot, Na_tot))
    Tem = zeros((Nt_tot, 1))

    lam_int = output.simu.machine.get_lamination(True)
    lam_ext = output.simu.machine.get_lamination(False)
    Rgap_mec_int = lam_int.comp_radius_mec()
    Rgap_mec_ext = lam_ext.comp_radius_mec()

    if self.is_get_mesh or self.is_save_FEA:
        meshFEMM = [Mesh() for ii in range(Nt_tot)]
        solutionFEMM = [Solution() for ii in range(Nt_tot)]
    else:
        meshFEMM = [Mesh()]
        solutionFEMM = [Solution()]

    # Compute the data for each time step
    for ii in range(Nt_tot):
        # Update rotor position and currents
        update_FEMM_simulation(
            output=output,
            materials=FEMM_dict["materials"],
            circuits=FEMM_dict["circuits"],
            is_mmfs=self.is_mmfs,
            is_mmfr=self.is_mmfr,
            j_t0=ii,
            is_sliding_band=self.is_sliding_band,
        )
        # try "previous solution" for speed up of FEMM calculation
        if self.is_sliding_band:
            try:
                base = basename(self.get_path_save_fem(output))
                ans_file = splitext(base)[0] + ".ans"
                femm.mi_setprevious(ans_file, 0)
            except:
                pass

        # Run the computation
        femm.mi_analyze()
        femm.mi_loadsolution()

        # Get the flux result
        if self.is_sliding_band:
            for jj in range(Na_tot):
                Br[ii, jj], Bt[ii,
                               jj] = femm.mo_getgapb("bc_ag2",
                                                     angle[jj] * 180 / pi)
        else:
            Rag = (Rgap_mec_ext + Rgap_mec_int) / 2
            for jj in range(Na_tot):
                B = femm.mo_getb(Rag * np.cos(angle[jj]),
                                 Rag * np.sin(angle[jj]))
                Br[ii,
                   jj] = B[0] * np.cos(angle[jj]) + B[1] * np.sin(angle[jj])
                Bt[ii,
                   jj] = -B[0] * np.sin(angle[jj]) + B[1] * np.cos(angle[jj])

        # Compute the torque
        Tem[ii] = comp_FEMM_torque(FEMM_dict, sym=sym)

        if (hasattr(output.simu.machine.stator, "winding")
                and output.simu.machine.stator.winding is not None):
            # Phi_wind computation
            Phi_wind_stator[ii, :] = comp_FEMM_Phi_wind(
                qs,
                Npcpp,
                is_stator=True,
                Lfemm=FEMM_dict["Lfemm"],
                L1=L1,
                sym=sym)

        # Load mesh data & solution
        if self.is_get_mesh or self.is_save_FEA:
            meshFEMM[ii], solutionFEMM[ii] = self.get_meshsolution(
                self.is_get_mesh, self.is_save_FEA, save_path, ii)

    # Shift to take into account stator position
    roll_id = int(self.angle_stator * Na_tot / (2 * pi))
    Br = roll(Br, roll_id, axis=1)
    Bt = roll(Bt, roll_id, axis=1)

    # Store the results
    output.mag.Br = Br
    output.mag.Bt = Bt
    output.mag.Tem = Tem
    output.mag.Tem_av = mean(Tem)
    if output.mag.Tem_av != 0:
        output.mag.Tem_rip = abs(
            (np_max(Tem) - np_min(Tem)) / output.mag.Tem_av)
    output.mag.Phi_wind_stator = Phi_wind_stator
    output.mag.FEMM_dict = FEMM_dict

    if self.is_get_mesh:
        cond = (not self.is_sliding_band) or (Nt_tot == 1)
        output.mag.meshsolution = MeshSolution(
            name="FEMM_magnetic_mesh",
            mesh=meshFEMM,
            solution=solutionFEMM,
            is_same_mesh=cond,
        )

    if self.is_save_FEA:
        save_path_fea = join(save_path, "MeshSolutionFEMM.json")
        output.mag.meshsolution.save(save_path_fea)

    if (hasattr(output.simu.machine.stator, "winding")
            and output.simu.machine.stator.winding is not None):
        # Electromotive forces computation (update output)
        self.comp_emf()
    else:
        output.mag.emf = None
Beispiel #7
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 
vals = femm.mo_getcircuitproperties('icoil');

# [i, v, \[Phi]] = MOGetCircuitProperties["icoil"]

# If we were interested in inductance, it could be obtained by
# dividing flux linkage by current
L = 1000*vals[2]/vals[0];
print('The self-inductance of the coil is %g mH' % L);
Beispiel #8
0
def write_Torque_and_B_data_to_file(str_rotor_position, rotation_operator):
    # call this after mi_analyze
    femm.mi_loadsolution()

    # Physical Amount on the Rotor
    femm.mo_groupselectblock(100)  # rotor iron
    femm.mo_groupselectblock(101)  # rotor bars
    Fx = femm.mo_blockintegral(
        18)  #-- 18 x (or r) part of steady-state weighted stress tensor force
    Fy = femm.mo_blockintegral(
        19)  #--19 y (or z) part of steady-state weighted stress tensor force
    torque = femm.mo_blockintegral(
        22)  #-- 22 = Steady-state weighted stress tensor torque
    femm.mo_clearblock()
    # write results to a data file (write to partial files to avoid compete between parallel instances)
    handle_torque.write("%s %g %g %g\n" % (str_rotor_position, torque, Fx, Fy))

    # Field Amount of 1/4 model (this is valid if we presume the suspension two pole field is weak)
    number_of_elements = femm.mo_numelements()
    stator_Bx_data = []
    stator_By_data = []
    stator_Area_data = []
    rotor_Bx_data = []
    rotor_By_data = []
    rotor_Area_data = []
    # one_list = []
    for id_element in range(1, number_of_elements + 1):
        _, _, _, x, y, area, group = femm.mo_getelement(id_element)
        if y > 0 and x > 0:
            if group == 10:  # stator iron
                # 1. What we need for iron loss evaluation is the B waveform at a fixed point (x,y).
                #    For example, (x,y) is the centeroid of element in stator tooth.
                Bx, By = femm.mo_getb(x, y)
                stator_Bx_data.append(Bx)
                stator_By_data.append(By)
                stator_Area_data.append(area)

            if group == 100:  # rotor iron
                # 2. The element at (x,y) is no longer the same element from last rotor position.
                #    To find the exact element from last rotor position,
                #    we rotate the (x,y) forward as we rotate the model (rotor), get the B value there: (x,y)*rotation_operator, and correct the (Bx,By)/rotation_operator
                complex_new_xy = (x + 1j * y) * rotation_operator
                Bx, By = femm.mo_getb(complex_new_xy.real, complex_new_xy.imag)
                complex_new_BxBy = (Bx + 1j * By) * rotation_operator
                rotor_Bx_data.append(complex_new_BxBy.real)
                rotor_By_data.append(complex_new_BxBy.imag)
                rotor_Area_data.append(area)

            # one_list.append(sqrt(Bx**2 + By**2))
            # one_list.append(area)
    # option 1
    handle_stator_B_data.write(str_rotor_position + ',' + ','.join([
        '%g,%g,%g' % (Bx, By, A)
        for Bx, By, A in zip(stator_Bx_data, stator_By_data, stator_Area_data)
    ]) + '\n')
    handle_rotor_B_data.write(str_rotor_position + ',' + ','.join([
        '%g,%g,%g' % (Bx, By, A)
        for Bx, By, A in zip(rotor_Bx_data, rotor_By_data, rotor_Area_data)
    ]) + '\n')

    # option 2: one_list
    # handle_B_data.write(str_rotor_position + ',' + ','.join(['%g'%(B) for B in B_data ]) + ','.join(['%g'%(A) for A in Area_data ]) + '\n')

    # numpy is slower than open().write!!!
    # tic = time()
    # # savetxt(handle_B_data, c_[one_list])
    # savetxt(handle_B_data, one_list)
    # toc = time()
    # print toc - tic, 's\n\n'

    femm.mo_close()
Beispiel #9
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)
    zee.append(n)
    bee.append(b[1])

plt.plot(zee, bee)
plt.ylabel('Flux Density, Tesla')
plt.xlabel('Distance along the z-axis, mm')
plt.title('Plot of flux density along the axis')
plt.grid()
plt.show()

femm.closefemm()  # close the instance of femm
Beispiel #10
0
def solve_FEMM(self, output, sym, FEMM_dict):

    # Loading parameters for readibility
    angle = output.mag.angle
    L1 = output.simu.machine.stator.comp_length()
    Nt_tot = output.mag.Nt_tot  # Number of time step
    Na_tot = output.mag.Na_tot  # Number of angular step
    save_path = self.get_path_save(output)

    if (hasattr(output.simu.machine.stator, "winding")
            and output.simu.machine.stator.winding is not None):
        qs = output.simu.machine.stator.winding.qs  # Winding phase number
        Npcpp = output.simu.machine.stator.winding.Npcpp
        Phi_wind_stator = zeros((Nt_tot, qs))
    else:
        Phi_wind_stator = None

    # Create the mesh
    femm.mi_createmesh()

    # Initialize results matrix
    Br = zeros((Nt_tot, Na_tot))
    Bt = zeros((Nt_tot, Na_tot))
    Tem = zeros((Nt_tot))

    Rag = output.simu.machine.comp_Rgap_mec()

    # Compute the data for each time step
    for ii in range(Nt_tot):
        # Update rotor position and currents
        update_FEMM_simulation(
            output=output,
            materials=FEMM_dict["materials"],
            circuits=FEMM_dict["circuits"],
            is_mmfs=self.is_mmfs,
            is_mmfr=self.is_mmfr,
            j_t0=ii,
            is_sliding_band=self.is_sliding_band,
        )
        # try "previous solution" for speed up of FEMM calculation
        if self.is_sliding_band:
            try:
                base = basename(self.get_path_save_fem(output))
                ans_file = splitext(base)[0] + ".ans"
                femm.mi_setprevious(ans_file, 0)
            except:
                pass

        # Run the computation
        femm.mi_analyze()
        femm.mi_loadsolution()

        # Get the flux result
        if self.is_sliding_band:
            for jj in range(Na_tot):
                Br[ii, jj], Bt[ii,
                               jj] = femm.mo_getgapb("bc_ag2",
                                                     angle[jj] * 180 / pi)
        else:
            for jj in range(Na_tot):
                B = femm.mo_getb(Rag * np.cos(angle[jj]),
                                 Rag * np.sin(angle[jj]))
                Br[ii,
                   jj] = B[0] * np.cos(angle[jj]) + B[1] * np.sin(angle[jj])
                Bt[ii,
                   jj] = -B[0] * np.sin(angle[jj]) + B[1] * np.cos(angle[jj])

        # Compute the torque
        Tem[ii] = comp_FEMM_torque(FEMM_dict, sym=sym)

        if (hasattr(output.simu.machine.stator, "winding")
                and output.simu.machine.stator.winding is not None):
            # Phi_wind computation
            Phi_wind_stator[ii, :] = comp_FEMM_Phi_wind(
                qs,
                Npcpp,
                is_stator=True,
                Lfemm=FEMM_dict["Lfemm"],
                L1=L1,
                sym=sym)

        # Load mesh data & solution
        if (self.is_sliding_band or Nt_tot == 1) and (self.is_get_mesh
                                                      or self.is_save_FEA):
            tmpmeshFEMM, tmpB, tmpH, tmpmu, tmpgroups = self.get_meshsolution(
                save_path, ii)

            if ii == 0:
                meshFEMM = [tmpmeshFEMM]
                groups = [tmpgroups]
                B = np.zeros(
                    [Nt_tot, meshFEMM[ii].cell["triangle"].nb_cell, 3])
                H = np.zeros(
                    [Nt_tot, meshFEMM[ii].cell["triangle"].nb_cell, 3])
                mu = np.zeros([Nt_tot, meshFEMM[ii].cell["triangle"].nb_cell])

            B[ii, :, 0:2] = tmpB
            H[ii, :, 0:2] = tmpH
            mu[ii, :] = tmpmu

    # Shift to take into account stator position
    roll_id = int(self.angle_stator * Na_tot / (2 * pi))
    Br = roll(Br, roll_id, axis=1)
    Bt = roll(Bt, roll_id, axis=1)

    # Store the results
    Time = DataLinspace(
        name="time",
        unit="s",
        symmetries={},
        initial=output.mag.time[0],
        final=output.mag.time[-1],
        number=Nt_tot,
        include_endpoint=True,
    )
    Angle = DataLinspace(
        name="angle",
        unit="rad",
        symmetries={},
        initial=angle[0],
        final=angle[-1],
        number=Na_tot,
        include_endpoint=True,
    )
    Br_data = DataTime(
        name="Airgap radial flux density",
        unit="T",
        symbol="B_r",
        axes=[Time, Angle],
        values=Br,
    )
    Bt_data = DataTime(
        name="Airgap tangential flux density",
        unit="T",
        symbol="B_t",
        axes=[Time, Angle],
        values=Bt,
    )
    output.mag.B = VectorField(
        name="Airgap flux density",
        symbol="B",
        components={
            "radial": Br_data,
            "tangential": Bt_data
        },
    )

    output.mag.Tem = DataTime(
        name="Electromagnetic torque",
        unit="Nm",
        symbol="T_{em}",
        axes=[Time],
        values=Tem,
    )
    output.mag.Tem_av = mean(Tem)
    output.mag.Tem_rip_pp = abs(np_max(Tem) - np_min(Tem))  # [N.m]
    if output.mag.Tem_av != 0:
        output.mag.Tem_rip_norm = output.mag.Tem_rip_pp / output.mag.Tem_av  # []
    else:
        output.mag.Tem_rip_norm = None
    output.mag.Phi_wind_stator = Phi_wind_stator
    output.mag.FEMM_dict = FEMM_dict

    if self.is_get_mesh:
        output.mag.meshsolution = self.build_meshsolution(
            Nt_tot, meshFEMM, Time, B, H, mu, groups)

    if self.is_save_FEA:
        save_path_fea = join(save_path, "MeshSolutionFEMM.h5")
        output.mag.meshsolution.save(save_path_fea)

    if (hasattr(output.simu.machine.stator, "winding")
            and output.simu.machine.stator.winding is not None):
        # Electromotive forces computation (update output)
        self.comp_emf()
    else:
        output.mag.emf = None
Beispiel #11
0
        b = np.zeros(
            [ns, nn],
            dtype=np.complex64)  # matrix that will hold the flux density info

    # Store element flux densities B and magnetic potential A
    for m in range(nn):
        if g[m] == GroupSummary[
                'magnet']:  # Element is in a rotor magnet, marked with group numbers 11 and higher
            # Store vector potential at the element centroid for elements that are in PMs
            A[index, m] = femm.mo_geta(float(np.real(z[m])),
                                       float(np.imag(z[m])))
        elif g[m] == GroupSummary['stator_iron_core'] \
            or g[m] == GroupSummary['rotor_iron_core'] \
            or g[m] == GroupSummary['coils']: # Element is on the stator or rotor iron or coils
            # Store flux density at the element centroid for these elements
            b_temp = femm.mo_getb(float(np.real(z[m])), float(np.imag(z[m])))
            b[index, m] = b_temp[0] + 1j * b_temp[1]

    # Torque, force, fluxes
    torque = femm.mo_gapintegral('WholeModelSlidingBand', 0)
    forces = femm.mo_gapintegral('WholeModelSlidingBand', 1)
    energy = femm.mo_gapintegral('WholeModelSlidingBand', 2)

    cP_Uac = femm.mo_getcircuitproperties('U-GrpAC')
    cP_Vac = femm.mo_getcircuitproperties('V-GrpAC')
    cP_Wac = femm.mo_getcircuitproperties('W-GrpAC')
    cP_Ubd = femm.mo_getcircuitproperties('U-GrpBD')
    cP_Vbd = femm.mo_getcircuitproperties('V-GrpBD')
    cP_Wbd = femm.mo_getcircuitproperties('W-GrpBD')
    M[index, 0] = torque
    M[index, 1] = forces[0]
Beispiel #12
0
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])

# Or we could, for example, plot the results along a line using
zee = []
bee = []
for n in range(-100, 101):
    b = femm.mo_getb(0, n)
    zee.append(n)
    bee.append(b[1])

plt.plot(zee, bee)
plt.ylabel('Flux Density, Tesla')
plt.xlabel('Distance along the z-axis, mm')