Esempio n. 1
0
    def set_group(self, groupID):

        #select circle slightly larger than the rotor
        select_oversize = 0.001  #mm
        fe.mi_selectcircle(0, 0, self.OR + select_oversize, 4)
        fe.mi_setgroup(groupID)
        fe.mi_clearselected()
Esempio n. 2
0
def addNodeZ(n, group=-1):
    if group == -1:
        group = femmgroupmode
    femm.mi_addnode(n.real, n.imag)
    femm.mi_selectnode(n.real, n.imag)
    femm.mi_setgroup(group)
    femm.mi_clearselected()
Esempio n. 3
0
def setCirc(r, phi, mat, circuit, turns, group=-1):
    if group == -1:
        group = femmgroupmode
    n = cmath.rect(r, rad(phi))
    femm.mi_selectlabel(n.real, n.imag)
    femm.mi_setblockprop(mat, 1, 0, circuit, 0, group, turns)
    femm.mi_clearselected()
Esempio n. 4
0
def setMagnet(r, phi, mat, magdir, group=-1):
    if group == -1:
        group = femmgroupmode
    n = cmath.rect(r, rad(phi))
    femm.mi_selectlabel(n.real, n.imag)
    femm.mi_setblockprop(mat, 1, 0, '<None>', magdir, group, 0)
    femm.mi_clearselected()
Esempio n. 5
0
def addNode(r, phi, group=-1):
    if group == -1:
        group = femmgroupmode
    n = cmath.rect(r, rad(phi))
    femm.mi_addnode(n.real, n.imag)
    femm.mi_selectnode(n.real, n.imag)
    femm.mi_setgroup(group)
    femm.mi_clearselected()
Esempio n. 6
0
def addBlockLabel(r, phi, group=-1):
    if group == -1:
        group = femmgroupmode
    n = cmath.rect(r, rad(phi))
    femm.mi_addblocklabel(n.real, n.imag)
    femm.mi_selectlabel(n.real, n.imag)
    femm.mi_setgroup(group)
    femm.mi_clearselected()
    return n
Esempio n. 7
0
def addLineZZ(n1, n2, group=-1):
    if group == -1:
        group = femmgroupmode
    femm.mi_addsegment(n1.real, n1.imag, n2.real, n2.imag)
    # select middle of arc for adding group
    n = (n1.real + n2.real) / 2 + ((n1.imag + n2.imag) / 2) * 1j
    femm.mi_selectsegment(n.real, n.imag)
    femm.mi_setgroup(group)
    femm.mi_clearselected()
Esempio n. 8
0
    def deleteCoil(self):
        """Delete the coil

        Provided for debugging, should not be used.
        """
        femm.mi_clearselected()
        femm.mi_selectgroup(2)
        femm.mi_deleteselected()
        femm.mi_deletematerial("Cuivre")
    def conditions_limites(self):
        """Méthode permettant d'attribuer les conditions aux limites"""

        femm.mi_addboundprop('lim', 0, 0, 0, 0, 0, 0, 0, 0, 0)
        femm.mi_selectsegment(0, self.hauteur / 2)
        femm.mi_selectsegment(0, -self.hauteur / 2)
        femm.mi_selectsegment(self.largeur / 2, 0)
        femm.mi_selectsegment(-self.largeur / 2, 0)
        femm.mi_setsegmentprop('lim', 0, 1, 0, 0)
        femm.mi_clearselected()
Esempio n. 10
0
    def deleteProjectile(self):
        """Delete the projectile

        Deletes the projectile (drawn) but doesn't erase its properties.
        """
        femm.mi_clearselected()
        femm.mi_selectgroup(1)
        femm.mi_deleteselected()
        femm.mi_deletematerial("Projectile")
        if self.espace is not None:
            femm.mi_addsegment(0, -self.espace, 0, self.espace)
Esempio n. 11
0
def addLine(r1, phi1, r2, phi2, group=-1):
    if group == -1:
        group = femmgroupmode
    n1 = cmath.rect(r1, rad(phi1))
    n2 = cmath.rect(r2, rad(phi2))
    femm.mi_addsegment(n1.real, n1.imag, n2.real, n2.imag)
    # select middle of arc for adding group
    # todo: better guess at point on line (unpredictable if phi1 != phi2)
    n = cmath.rect((r1 + r2) / 2., rad((phi1 + phi2) / 2.))
    femm.mi_selectsegment(n.real, n.imag)
    femm.mi_setgroup(group)
    femm.mi_clearselected()
Esempio n. 12
0
def addArcZZ(n1, n2, group=-1):
    if group == -1:
        group = femmgroupmode
    r1, phi1 = cmath.polar(n1)
    r2, phi2 = cmath.polar(n2)
    femm.mi_addarc(n1.real, n1.imag, n2.real, n2.imag, deg(abs(phi1 - phi2)),
                   10)
    # select middle of arc for adding group
    # todo: better guess at point on arc (unpredictable if r1 != r2)

    n = cmath.rect((r1 + r2) / 2., (phi1 + phi2) / 2.)
    femm.mi_selectarcsegment(n.real, n.imag)
    femm.mi_setgroup(group)
    femm.mi_clearselected()
Esempio n. 13
0
    def affectation_materiaux(self):
        """Méthode permettant d'attribuer la propriété des matériaux"""

        # Affectation de l'air (x,y)
        femm.mi_addmaterial('Air', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
        femm.mi_addblocklabel(0, 0)
        femm.mi_selectlabel(0, 0)
        femm.mi_setblockprop('Air', 0, 1, '<None>', 0, 0, 0)
        femm.mi_clearselected()

        # Affectation du Cuivre (bobine positive) (Attention J en A/mm²)
        femm.mi_addmaterial('Cuivre-', 1, 1, 0,
                            -self.k_b * self.j_max * 1.0e-6, 0, 0, 0, 0, 0, 0,
                            0)
        femm.mi_addblocklabel(self.largeur / 4, 0)
        femm.mi_selectlabel(self.largeur / 4, 0)
        femm.mi_setblockprop('Cuivre-', 0, 1, 'incricuit', 0, 0, 0)
        femm.mi_clearselected()

        # Affectation du Cuivre (bobine négative)
        femm.mi_addmaterial('Cuivre+', 1, 1, 0, self.k_b * self.j_max * 1.0e-6,
                            0, 0, 0, 0, 0, 0, 0)
        femm.mi_addblocklabel(-self.largeur / 4, 0)
        femm.mi_selectlabel(-self.largeur / 4, 0)
        femm.mi_setblockprop('Cuivre+', 0, 1, 'incircuit', 0, 0, 0)
        femm.mi_clearselected()

        # Matériau non linéaire

        # Création d'un matériau linéaire
        femm.mi_addmaterial('Iron', 2100, 2100, 0, 0, 0, 0, 0, 0, 0, 0, 0)

        # Les points de la courbe BH
        bdata = [
            0.1, 0.2, 0.4, 0.7, 1., 1.2, 1.3, 1.4, 1.5, 1.55, 1.6, 1.65, 1.7
        ]
        hdata = [
            26.5, 37.8, 52.4, 71.9, 99.3, 136, 176, 279, 659, 1084, 1718, 2577,
            3670
        ]
        # Affectation des points de la courbe
        for n in range(0, len(bdata)):
            femm.mi_addbhpoint('Iron', bdata[n], hdata[n])

        # Les points de la courbe Pertes fer = f(B)
        pdata = [
            0.0176, 0.0683, 0.240, 0.602, 1.09, 1.51, 1.79, 2.14, 2.56, 2.77,
            2.96, 3.13, 3.29
        ]
        self._interp_pertes_fer = interp1d(bdata,
                                           pdata,
                                           bounds_error=False,
                                           fill_value=(pdata[0], pdata[-1]))

        # Affectation du matériau
        femm.mi_addblocklabel(self.largeur / 2 - self.l_dent / 4, 0)
        femm.mi_selectlabel(self.largeur / 2 - self.l_dent / 4, 0)
        femm.mi_setblockprop('Iron', 0, 1, '<None>', 0, 0, 0)
        femm.mi_clearselected()
Esempio n. 14
0
def draw_conductor(coords, in_conductor, label_name, label_dict):
    '''Draw a square conductor, set a block label in the middle of the
    conductor and add label properties.'''
    femm.mi_drawrectangle(*coords)

    label_coord = (average(
        (coords[0], coords[2])), average((coords[1], coords[3])))
    femm.mi_addblocklabel(*label_coord)
    femm.mi_selectlabel(*label_coord)
    if in_conductor == 1:
        femm.mi_setblockprop('copper', 1, 0, 'phase_prim', 0, 1, 1)
    elif in_conductor == 0:
        femm.mi_setblockprop('copper', 1, 0, 'phase_sec', 0, 1, 1)
    femm.mi_clearselected()
    label_dict[label_name] = label_coord
Esempio n. 15
0
 def build_coil(self, coil_dict):
     """
     load coil_cross sections into femm environment
     :param coil_dict:
     :return:
     """
     for section, section_tuple in coil_dict.items():
         path_point = np.array(section_tuple[0])
         profile = section_tuple[1] + path_point
         # draw line segments between nodes
         for index, point in enumerate(profile):
             last_point = profile[index - 1]
             femm.mi_drawline(last_point[1], last_point[0], point[1],
                              point[0])
         femm.mi_addblocklabel(path_point[1], path_point[0])
         femm.mi_selectlabel(path_point[1], path_point[0])
         femm.mi_setblockprop(str(section))
         femm.mi_clearselected()
Esempio n. 16
0
    def setSpace(self):
        """Define space

        Define the whole space used in FEMM

        Raises:
            Exception -- Coil and projectile must be defined first to compute a safe space size.
        """
        if self.Lp is not None and self.Lb is not None:
            femm.mi_clearselected()
            self.espace = self.__space_factor * max(self.Lb, self.Rbo, self.Lp)
            femm.mi_addblocklabel(2 * self.Rbo, 0)
            femm.mi_selectlabel(2 * self.Rbo, 0)
            femm.mi_setblockprop("Air", 0, self.meshsize, "<None>", 0, 3, 0)
            femm.mi_makeABC(7, self.espace, 0, 0, 0)
            femm.mi_zoomnatural()
        else:
            raise Exception("Define coil and projectile first.")
    def affectation_materiaux(self):
        """Méthode permettant d'attribuer la propriété des matériaux"""

        # Affectation de l'air (x,y)
        femm.mi_addmaterial('Air', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
        femm.mi_addblocklabel(0, 0)
        femm.mi_selectlabel(0, 0)
        femm.mi_setblockprop('Air', 0, 1, '<None>', 0, 0, 0)
        femm.mi_clearselected()

        # Affectation du Cuivre (bobine positive) (Attention J en A/mm²)
        femm.mi_addmaterial('Cuivre+', 1, 1, 0, self.k_b * self.j_max * 1.0e-6,
                            0, 0, 0, 0, 0, 0, 0)
        femm.mi_addblocklabel(self.largeur / 4, 0)
        femm.mi_selectlabel(self.largeur / 4, 0)
        femm.mi_setblockprop('Cuivre+', 0, 1, 'incricuit', 0, 0, 0)
        femm.mi_clearselected()

        # Affectation du Cuivre (bobine négative)
        femm.mi_addmaterial('Cuivre-', 1, 1, 0,
                            -self.k_b * self.j_max * 1.0e-6, 0, 0, 0, 0, 0, 0,
                            0)
        femm.mi_addblocklabel(-self.largeur / 4, 0)
        femm.mi_selectlabel(-self.largeur / 4, 0)
        femm.mi_setblockprop('Cuivre-', 0, 1, 'incircuit', 0, 0, 0)
        femm.mi_clearselected()

        # Matériau non linéaire

        # Création d'un matériau linéaire
        femm.mi_addmaterial('Iron', 2100, 2100, 0, 0, 0, 0, 0, 0, 0, 0, 0)

        # Les points de la courbe BH
        bdata = [
            0., 0.2, 0.4, 0.7, 1, 1.2, 1.3, 1.4, 1.5, 1.55, 1.6, 1.65, 1.7,
            1.8, 1.91, 2, 2.1, 3.2454
        ]

        hdata = [
            0., 31.9, 44.9, 67.3, 106., 164., 235., 435., 1109., 1813., 2802.,
            4054., 5592., 9711., 16044., 31319., 88491., 1000000.
        ]

        # Affectation des points de la courbe
        for n in range(0, len(bdata)):
            femm.mi_addbhpoint('Iron', bdata[n], hdata[n])

        # Affectation du matériau
        femm.mi_addblocklabel(self.largeur / 2 - self.l_dent / 4, 0)
        femm.mi_selectlabel(self.largeur / 2 - self.l_dent / 4, 0)
        femm.mi_setblockprop('Iron', 0, 1, '<None>', 0, 0, 0)
        femm.mi_clearselected()
Esempio n. 18
0
def draw_FEMM(self,
              nodeprop=None,
              maxseg=None,
              propname=None,
              hide=False,
              group=None):
    """Draw the Arc object in FEMM and assign the property

    Parameters
    ----------
    nodeprop :
        Nodal property
         (Default value = None)
    maxseg :
        Meshed with elements that span at most maxsegdeg degrees per element
         (Default value = None)
    propname :
        Boundary property ’propname’
         (Default value = None)
    hide :
        0 = not hidden in post-processor, 1 == hidden in post processor
         (Default value = False)
    group :
        the group the Arc1 object belongs
         (Default value = None)

    Returns
    -------
    None
    """

    # Get BC (if any)
    if self.label in boundary_prop:
        propname = boundary_prop[self.label]

    # Create the nodes
    begin = self.get_begin()
    end = self.get_end()
    X1, Y1 = begin.real, begin.imag
    X2, Y2 = end.real, end.imag
    femm.mi_addnode(X1, Y1)
    femm.mi_selectnode(X1, Y1)
    femm.mi_setnodeprop(nodeprop, group)
    femm.mi_clearselected()
    femm.mi_addnode(X2, Y2)
    femm.mi_selectnode(X2, Y2)
    femm.mi_setnodeprop(nodeprop, group)
    femm.mi_clearselected()

    # Create the arc
    angle = self.get_angle(is_deg=True)
    if angle > 0:
        femm.mi_addarc(X1, Y1, X2, Y2, angle, 2)
    else:
        femm.mi_addarc(X2, Y2, X1, Y1, -angle, 2)
    # Set Arc properties
    Zm = self.get_middle()
    femm.mi_selectarcsegment(Zm.real, Zm.imag)
    femm.mi_setarcsegmentprop(maxseg, propname, hide, group)
    femm.mi_clearselected()
Esempio n. 19
0
    def drawCoil(self):
        """Draw the coil

        Draws the coil in the FEMM instance

        Raises:
            Exception -- The coil is not defined, please call defineCoil before.
        """
        if self.Lb is not None:
            femm.mi_clearselected()
            femm.mi_addmaterial("Cuivre", 1, 1, 0, 0, 1 / self.rho * 10**-6, 0,
                                0, 1, 3 if self.wire_type == "round" else 6, 0,
                                0, 1, self.phi)
            femm.mi_addnode(self.Rbi, -self.Lb / 2)
            femm.mi_addnode(self.Rbo, -self.Lb / 2)
            femm.mi_addnode(self.Rbi, self.Lb / 2)
            femm.mi_addnode(self.Rbo, self.Lb / 2)
            femm.mi_addsegment(self.Rbi, -self.Lb / 2, self.Rbo, -self.Lb / 2)
            femm.mi_addsegment(self.Rbo, -self.Lb / 2, self.Rbo, self.Lb / 2)
            femm.mi_addsegment(self.Rbo, self.Lb / 2, self.Rbi, self.Lb / 2)
            femm.mi_addsegment(self.Rbi, -self.Lb / 2, self.Rbi, self.Lb / 2)
            femm.mi_selectnode(self.Rbi, -self.Lb / 2)
            femm.mi_selectnode(self.Rbo, -self.Lb / 2)
            femm.mi_selectnode(self.Rbi, self.Lb / 2)
            femm.mi_selectnode(self.Rbo, self.Lb / 2)
            femm.mi_selectsegment(self.Rbi, 0)
            femm.mi_selectsegment((self.Rbi + self.Rbo) / 2, -self.Lb / 2)
            femm.mi_selectsegment(self.Rbo, 0)
            femm.mi_selectsegment((self.Rbi + self.Rbo) / 2, self.Lb / 2)
            femm.mi_setgroup(2)
            femm.mi_addblocklabel((self.Rbi + self.Rbo) / 2, 0)
            femm.mi_selectlabel((self.Rbi + self.Rbo) / 2, -self.Lb / 2)
            femm.mi_setblockprop("Cuivre", 0, self.meshsize, "Bobine", 0, 2,
                                 self.n)
            femm.mi_clearselected()
        else:
            raise Exception("No coil defined.")
Esempio n. 20
0
    def drawProjectile(self):
        """Draw projectile

        Draws the projectil in the FEMM instance

        Raises:
            Exception -- Projectile is not defined
        """
        if self.Lp is not None:
            femm.mi_addmaterial("Projectile", self.mu, self.mu, 0, 0, 0, 0, 0,
                                1, 0, 0, 0)
            femm.mi_clearselected()
            femm.mi_addnode(0, -self.Lp / 2)
            femm.mi_addnode(self.Rp, -self.Lp / 2)
            femm.mi_addnode(0, self.Lp / 2)
            femm.mi_addnode(self.Rp, self.Lp / 2)
            femm.mi_addsegment(0, -self.Lp / 2, self.Rp, -self.Lp / 2)
            femm.mi_addsegment(self.Rp, -self.Lp / 2, self.Rp, self.Lp / 2)
            femm.mi_addsegment(self.Rp, self.Lp / 2, 0, self.Lp / 2)
            femm.mi_addsegment(0, self.Lp / 2, 0, -self.Lp / 2)
            femm.mi_selectnode(0, -self.Lp / 2)
            femm.mi_selectnode(self.Rp, -self.Lp / 2)
            femm.mi_selectnode(0, self.Lp / 2)
            femm.mi_selectnode(self.Rp, self.Lp / 2)
            femm.mi_selectsegment(0, 0)
            femm.mi_selectsegment(self.Rp / 2, -self.Lp / 2)
            femm.mi_selectsegment(self.Rp, 0)
            femm.mi_selectsegment(self.Rp / 2, self.Lp / 2)
            femm.mi_setgroup(1)
            femm.mi_addblocklabel(self.Rp / 2, 0)
            femm.mi_selectlabel(self.Rp / 2, 0)
            femm.mi_setblockprop("Projectile", 0, self.meshsize, "<None>", 0,
                                 1, 0)
            femm.mi_clearselected()
        else:
            raise Exception("No projectile defined.")
Esempio n. 21
0
    def set_materials(self, magnet, iron):

        #ensure that the materials are actually added to the analysis
        magnet.add()
        iron.add()

        R1 = self.OR - (self.dm + self.dri)  #inner radius of rotor
        R2 = self.OR - self.dm  #radius to inside of PM

        #assign magnet material
        mag_center = [(R2 + self.OR) / 2, 0]
        mag_orientation = 1  #1 = North facing out, -1 = North facing in

        num_magnets = 2 * self.p
        theta = 360 / num_magnets

        for i in range(num_magnets):
            xy = rotate(*mag_center, theta * i)

            #add 180 degrees if magnet faces in
            mag_dir = theta * i + 180 * (mag_orientation < 0
                                         )  #magnet orientation in deg
            fe.mi_addblocklabel(*xy)
            fe.mi_selectlabel(*xy)
            fe.mi_setblockprop(magnet.name, 1, 0, 0, mag_dir, 0, 0)
            fe.mi_clearselected()

            mag_dir *= -1  #alternate between N and S poles

        #assign steel material
        xy = [(R1 + R2) / 2, 0]

        fe.mi_addblocklabel(*xy)
        fe.mi_selectlabel(*xy)
        fe.mi_setblockprop(iron.name, 1, 0, 0, 0, 1, 0)
        fe.mi_clearselected()

        #add air to center if rotor is hollow
        if self.hollow:
            fe.mi_addblocklabel(0, 0)
            fe.mi_selectlabel(0, 0)
            fe.mi_setblockprop('Air', 1, 0, 0, 0, 0, 0)
            fe.mi_clearselected()
Esempio n. 22
0
def add_block_labels(tg, etiquettes_dict):
    '''Add block labels to pcbs, air, isolation disc, isolation gel/liquid.'''
    # Add block labels
    # ei seteditmode(editmode)
    # From manual: Sets the current editmode to:
    # – "nodes" - nodes
    # – "segments" - line segments
    # – "arcsegments" - arc segments
    # – "blocks" - block labels
    # – "group" - selected group
    femm.mi_seteditmode('blocks')

    # ei addblocklabel(x,y)
    # From manual: Add a new block label at (x,y)

    # labels for the PCBs
    coords = [2, tg.height_dielectric + tg.height_pcb_core / 2.]
    femm.mi_addblocklabel(*coords)
    etiquettes_dict['pcb_prim'] = coords

    coords = [2, -tg.height_pcb_core / 2.]
    femm.mi_addblocklabel(*coords)
    etiquettes_dict['pcb_sec'] = coords

    # label for the surrounding air
    coords = [2, tg.height_dielectric * 2 + tg.height_gel]
    femm.mi_addblocklabel(*coords)
    etiquettes_dict['air'] = coords

    # label for the dilectric gel or liquid surrounding the transformer
    coords = [tg.radius_pcb + 2, tg.height_dielectric + tg.height_gel / 2.]
    femm.mi_addblocklabel(*coords)
    etiquettes_dict['gel'] = coords

    # label for the isolation disc
    coords = [2, tg.height_dielectric / 2.]
    femm.mi_addblocklabel(*coords)
    etiquettes_dict['isolant'] = coords

    # Set material type for all blocks
    # mi_setblockprop("blockname", automesh, meshsize, "incircuit",
    # magdirection, group, turns)
    # From manual: Set the selected block labels to have the properties:
    # – Block property "blockname".
    # – automesh: 0 = mesher defers to mesh size constraint defined in
    # meshsize, 1 = mesher automatically chooses the mesh density.
    # – meshsize: size constraint on the mesh in the block marked by this label
    # – Block is a member of the circuit named "incircuit"
    # – The magnetization is directed along an angle in measured in degrees
    # denoted by the parameter magdirection. Alternatively, magdirection can be
    # a string containing a formula that prescribes the magnetization direction
    # as a function of element position. In this formula theta and R denotes
    # the angle in degrees of a line connecting the center each element with
    # the origin and the length of this line, respectively; x and y denote the
    # x- and y-position of the center of the each element. For axisymmetric
    # problems, r and z should be used in place of x and y.
    # – A member of group number group
    # – The number of turns associated with this label is denoted by turns.

    femm.mi_selectlabel(*etiquettes_dict['pcb_prim'])
    femm.mi_selectlabel(*etiquettes_dict['pcb_sec'])
    femm.mi_setblockprop('fr4', 1, 0, '<None>', 0, 1, 0)
    femm.mi_clearselected()

    femm.mi_selectlabel(*etiquettes_dict['air'])
    femm.mi_setblockprop('air', 1, 0, '<None>', 0, 1, 0)
    femm.mi_clearselected()

    femm.mi_selectlabel(*etiquettes_dict['gel'])
    femm.mi_setblockprop('silgel', 1, 0, 'None')
    femm.mi_clearselected()

    femm.mi_selectlabel(*etiquettes_dict['isolant'])
    femm.mi_setblockprop(tg.material_dielectric, 1, 0, 'None')
    femm.mi_clearselected()
Esempio n. 23
0
def clearGroup(group):
    if group != 0:
        clearGroup(0)
    femm.mi_selectgroup(group)
    femm.mi_deleteselected()
    femm.mi_clearselected()
Esempio n. 24
0
def assign_FEMM_surface(surf, prop, FEMM_dict, rotor, stator):
    """Assign the property given in parameter to surface having the label given
    Parameters
    ----------
    surf : Surface
        the surface to assign
    prop : str
        The property to assign in FEMM
    FEMM_dict : dict
        Dictionnary containing the main parameters of FEMM
    rotor : Lamination
        The rotor of the machine
    stator : Lamination
        The stator of the machine
    Returns
    -------
    None

    """

    mesh_dict = get_mesh_param(surf.label, FEMM_dict)
    label = surf.label
    Clabel = 0  # By default no circuit
    Ntcoil = 0  # By default no circuit
    mag = 0  # By default no magnetization

    # Select the lamination according to the label
    if "Rotor" in label:
        lam = rotor
    else:
        lam = stator

    # point_ref is None => don't assign the surface
    if surf.point_ref is not None:
        # Select the surface
        point_ref = surf.point_ref
        femm.mi_addblocklabel(point_ref.real, point_ref.imag)
        femm.mi_selectlabel(point_ref.real, point_ref.imag)

        # Get circuit or magnetization properties if needed
        if "Wind" in label:  # If the surface is a winding
            if "Rotor" in label:  # Winding on the rotor
                Clabel = "Circr" + prop[2]
            else:  # winding on the stator
                Clabel = "Circs" + prop[2]
            Ntcoil = lam.winding.Ntcoil
            if prop[-1] == "-":  # Adapt Ntcoil sign if needed
                Ntcoil *= -1
        elif "HoleMagnet" in label:  # LamHole
            if "Parallel" in label:
                # calculate pole angle and angle of pole middle
                alpha_p = 360 / lam.hole[0].Zh
                mag_0 = (floor_divide(angle(point_ref, deg=True), alpha_p) +
                         0.5) * alpha_p

                # HoleM50 or HoleM53
                if (type(lam.hole[0]) == HoleM50) or (type(lam.hole[0])
                                                      == HoleM53):
                    if "_T0_" in label:
                        mag = mag_0 + lam.hole[0].comp_alpha() * 180 / pi
                    else:
                        mag = mag_0 - lam.hole[0].comp_alpha() * 180 / pi

                # HoleM51
                if type(lam.hole[0]) == HoleM51:
                    if "_T0_" in label:
                        mag = mag_0 + lam.hole[0].comp_alpha() * 180 / pi
                    elif "_T1_" in label:
                        mag = mag_0
                    else:
                        mag = mag_0 - lam.hole[0].comp_alpha() * 180 / pi

                # HoleM52
                if type(lam.hole[0]) == HoleM52:
                    mag = mag_0

                # modifiy magnetisation of south poles
                if "_S_" in label:
                    mag = mag + 180
            else:
                raise NotImplementedYetError(
                    "Only parallele magnetization are available for HoleMagnet"
                )
        elif "Magnet" in label:  # LamSlotMag
            if "Radial" in label and "_N_" in label:  # Radial magnetization
                mag = "theta"  # North pole magnet
            elif "Radial" in label:
                mag = "theta + 180"  # South pole magnet
            elif "Parallel" in label and "_N_" in label:
                mag = angle(point_ref) * 180 / pi  # North pole magnet
            elif "Parallel" in label:
                mag = angle(point_ref) * 180 / pi + 180  # South pole magnet
            elif "Hallbach" in label:
                Zs = lam.slot.Zs
                mag = str(-(Zs / 2 - 1)) + " * theta + 90 "
        elif "Ventilation" in label:
            prop = "Air"
        elif "Hole" in label:
            prop = "Air"
        # Set the surface property
        femm.mi_setblockprop(
            prop,
            mesh_dict["automesh"],
            mesh_dict["meshsize"],
            Clabel,
            mag,
            mesh_dict["group"],
            Ntcoil,
        )
        femm.mi_clearselected()
Esempio n. 25
0
            (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),
        )

        femm.mi_drawline(
            -halfWidth + leftCurrentGap + bodyWidth + (2 * currentWidth) +
            (iman * (bodyWidth + innerStatorGap)),
            (halfHeight - barHeight - currentHeight) * up_down(side),
            -halfWidth + leftCurrentGap + bodyWidth + currentWidth +
Esempio n. 26
0
def drawroundedcorner_box(femm, group, width, length, x_center, y_center,
                          corner_radius, one_sided):
    x1 = x_center - width / 2
    y1 = y_center - length / 2
    x2 = x1 + width
    y2 = y1 + length

    # mc = .02 * inches

    mc = corner_radius
    # first create nodes at the 4 corners
    # because they will be joined by an arc segment

    c1_x = x1
    c1_y = y1

    c2_x = x2
    c2_y = y1

    c3_x = x2
    c3_y = y2

    c4_x = x1
    c4_y = y2

    # now make blunted edge magnet based on it
    n1x = c1_x
    n1y = c1_y + mc

    n2x = c1_x + mc
    n2y = c1_y

    n3x = c2_x - mc
    n3y = c2_y

    n4x = c2_x
    n4y = c2_y + mc

    n5x = c3_x
    n5y = c3_y - mc

    n6x = c3_x - mc
    n6y = c3_y

    n7x = c4_x + mc
    n7y = c4_y

    n8x = c4_x
    n8y = c4_y - mc

    # If drawing all 4 corners
    if (one_sided == 0):
        femm.mi_addnode(n1x, n1y)
        femm.mi_addnode(n2x, n2y)
        femm.mi_addnode(n3x, n3y)
        femm.mi_addnode(n4x, n4y)
        femm.mi_addnode(n5x, n5y)
        femm.mi_addnode(n6x, n6y)
        femm.mi_addnode(n7x, n7y)
        femm.mi_addnode(n8x, n8y)

        femm.mi_addarc(n1x, n1y, n2x, n2y, 90, 3)
        femm.mi_addsegment(n2x, n2y, n3x, n3y)

        femm.mi_addarc(n3x, n3y, n4x, n4y, 90, 3)
        femm.mi_addsegment(n4x, n4y, n5x, n5y)

        femm.mi_addarc(n5x, n5y, n6x, n6y, 90, 3)
        femm.mi_addsegment(n6x, n6y, n7x, n7y)
        femm.mi_addarc(n7x, n7y, n8x, n8y, 90, 3)
        femm.mi_addsegment(n8x, n8y, n1x, n1y)

        femm.mi_clearselected()
        # femm.mi_drawrectangle(x1, mag_y1, mag_x2, mag_y2)
        # femm.mi_selectrectangle(x1, mag_y1, mag_x2, mag_y2,0)

        femm.mi_selectsegment(c1_x, c1_y)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c1_x + width / 4, c1_y)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c2_x, c2_y)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c3_x, c3_y + length / 2)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c3_x, c3_y)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c3_x - width / 4, c3_y)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c4_x, c4_y)
        femm.mi_setgroup(group)
        femm.mi_selectsegment(c4_x, c4_y - length / 2)
        femm.mi_setgroup(group)

        #femm.mi_clearselected()

    # if drawing only rounded corners on far side
    # because location is on axis.
    if (one_sided == 1):

        femm.mi_addnode(c1_x, c1_y)
        femm.mi_addnode(n3x, n3y)
        femm.mi_addnode(n4x, n4y)
        femm.mi_addnode(n5x, n5y)
        femm.mi_addnode(n6x, n6y)
        femm.mi_addnode(c4_x, c4_y)

        femm.mi_addsegment(c4_x, c4_y, c1_x, c1_y)

        femm.mi_addsegment(c1_x, c1_y, n3x, n3y)

        femm.mi_addarc(n3x, n3y, n4x, n4y, 90, 3)
        femm.mi_addsegment(n4x, n4y, n5x, n5y)

        femm.mi_addarc(n5x, n5y, n6x, n6y, 90, 3)
        femm.mi_addsegment(n6x, n6y, c4_x, c4_y)

        femm.mi_clearselected()
        femm.mi_selectsegment(c1_x, c1_y + length / 2)
        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)
Esempio n. 27
0
    def computeMuImpact(self,
                        mus=[5, 10, 50, 100, 500, 1000, 5000],
                        error=0.1):
        """Compute the impact of Mu

        The model is NOT LINEAR in mu. It is hard to guess what would be the effect
        of an increased suceptibility and it may highly modify the response of the coil.
        However, for some configuration the error is low (typically a long coil and a small projectile).

        This function provides some help to know if we can consider the model linear in Mu.
        Simply provide a range of possible susceptibilities for your projectile, and an
        acceptable relative error.

        We do not check the whole linearity, but simply in two points selected empirically.
        Therefore some care should be taken regarding the output of this helper method.

        Keyword Arguments:
            mus {list} -- [description] (default: {[5, 10, 50, 100, 500, 1000, 5000]})
            error {number} -- [description] (default: {0.1})
        """
        _mu = self.mu
        res = []
        test_res = []
        print("Coil " + self._seed + " mus")
        for mu in mus:
            self.mu = mu
            self.deleteProjectile()
            self.drawProjectile()
            femm.mi_clearselected()
            femm.mi_selectgroup(1)

            femm.mi_analyze()
            femm.mi_loadsolution()
            femm.mo_groupselectblock(1)
            res.append(femm.mo_getcircuitproperties("Bobine")[2] / self._i0)

            femm.mi_movetranslate2(0, self.Lb / 4, 4)
            femm.mi_analyze()
            femm.mi_loadsolution()
            femm.mo_groupselectblock(1)
            test_res.append(
                femm.mo_getcircuitproperties("Bobine")[2] / self._i0)
        self.mu = _mu
        success = True
        errors = []
        for i in range(0, len(test_res)):
            errors.append(
                numpy.abs((res[i] / res[0]) / (test_res[i] / test_res[0]) - 1))
            if errors[-1] > error:
                success = False
                # break
        if success:
            return {
                'valid': True,
                'mus': mus,
                'mu_Lz_0': res,
                'mu_Lz_1': test_res,
                'errors': errors
            }
        else:
            return {
                'valid': False,
                'mus': mus,
                'mu_Lz_0': res,
                'mu_Lz_1': test_res,
                'errors': errors
            }
Esempio n. 28
0
def draw_FEMM(self, nodeprop=None, maxseg=None, propname=None, hide=False, group=None):
    """Draw the Arc object in FEMM and assign the property

    Parameters
    ----------
    nodeprop :
        Nodal property
         (Default value = None)
    maxseg :
        Meshed with elements that span at most maxsegdeg degrees per element
         (Default value = None)
    propname :
        Boundary property ’propname’
         (Default value = None)
    hide :
        0 = not hidden in post-processor, 1 == hidden in post processor
         (Default value = False)
    group :
        the group the Arc1 object belongs
         (Default value = None)

    Returns
    -------
    None
    """

    # Get BC (if any)
    for bound_label in boundary_prop:
        if bound_label in self.label:
            propname = boundary_prop[bound_label]

    # split if arc angle > 180
    angle = self.get_angle(is_deg=True)

    # Create the nodes
    begin = self.get_begin()
    mid = self.get_middle()
    end = self.get_end()
    X1, Y1 = begin.real, begin.imag
    X2, Y2 = mid.real, mid.imag
    X3, Y3 = end.real, end.imag
    femm.mi_addnode(X1, Y1)
    femm.mi_selectnode(X1, Y1)
    femm.mi_setnodeprop(nodeprop, group)
    femm.mi_clearselected()
    femm.mi_addnode(X3, Y3)
    femm.mi_selectnode(X3, Y3)
    femm.mi_setnodeprop(nodeprop, group)
    femm.mi_clearselected()
    if abs(angle) > 180:
        femm.mi_addnode(X2, Y2)
        femm.mi_selectnode(X2, Y2)
        femm.mi_setnodeprop(nodeprop, group)
        femm.mi_clearselected()

    # invert the nodes
    if angle < 0:
        angle = -angle
        X1, Y1, X3, Y3 = X3, Y3, X1, Y1

    if angle > 180:
        femm.mi_addarc(X1, Y1, X2, Y2, angle / 2, 2)
        femm.mi_addarc(X2, Y2, X3, Y3, angle / 2, 2)
    else:
        femm.mi_addarc(X1, Y1, X3, Y3, angle, 2)

    # Set Arc properties
    if angle > 180:
        cent = self.get_center()
        mid1 = cent + (mid - cent) * exp(1j * angle / 4)
        mid2 = cent + (mid - cent) * exp(-1j * angle / 4)
        femm.mi_selectarcsegment(mid1.real, mid1.imag)
        femm.mi_selectarcsegment(mid2.real, mid1.imag)
    else:
        femm.mi_selectarcsegment(X2, Y2)

    femm.mi_setarcsegmentprop(maxseg, propname, hide, group)
    femm.mi_clearselected()
Esempio n. 29
0
def draw_FEMM(
    self,
    nodeprop=None,
    propname=None,
    elementsize=None,
    automesh=None,
    hide=False,
    group=None,
):
    """<   Draw the segment in FEMM and assign the property

    Parameters
    ----------
    nodeprop :
        Nodal property
         (Default value = None)
    propname :
        Boundary property ’propname’
         (Default value = None)
    elementsize :
        Local element size along segment no greater than elementsize
         (Default value = None)
    automesh :
        0 = mesher defers to the element constraint defined by
        elementsize, 1 = mesher automatically chooses mesh size along
        the selected segments
        (Default value = None)
    hide :
        0 = not hidden in post-processor, 1 == hidden in post processorc
         (Default value = False)
    group :
        group the segment belongs
         (Default value = None)

    Returns
    -------

    
    """

    # Get BC (if any)
    if self.label in boundary_prop:
        propname = boundary_prop[self.label]

    # Add the nodes
    X1, Y1 = self.begin.real, self.begin.imag
    X2, Y2 = self.end.real, self.end.imag
    femm.mi_addnode(X1, Y1)
    femm.mi_selectnode(X1, Y1)
    femm.mi_setnodeprop(nodeprop, group)
    femm.mi_clearselected()
    femm.mi_addnode(X2, Y2)
    femm.mi_selectnode(X2, Y2)
    femm.mi_setnodeprop(nodeprop, group)
    femm.mi_clearselected()
    # add the segment
    femm.mi_addsegment(X1, Y1, X2, Y2)
    # Set property
    femm.mi_selectsegment((X1 + X2) / 2, (Y1 + Y2) / 2)
    femm.mi_setsegmentprop(propname, elementsize, automesh, hide, group)
    femm.mi_clearselected()
Esempio n. 30
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