Example #1
0
def comp_force(self, output):
    """Compute the air-gap surface force based on Maxwell Tensor (MT).

    Parameters
    ----------
    self : ForceMT
        A ForceMT object

    output : Output
        an Output object (to update)
    """

    mu_0 = 4 * pi * 1e-7

    # Load magnetic flux
    Brphiz = output.mag.B.get_rphiz_along("time", "angle")
    Br = Brphiz["radial"]
    Bt = Brphiz["tangential"]
    Bz = Brphiz["axial"]

    # Compute AGSF with MT formula
    Prad = (Br * Br - Bt * Bt - Bz * Bz) / (2 * mu_0)
    Ptan = Br * Bt / mu_0
    Pz = Br * Bz / mu_0

    # Store the results
    components = {}
    if not np_all((Prad == 0)):
        Prad_data = DataTime(
            name="Airgap radial surface force",
            unit="N/m2",
            symbol="P_r",
            axes=list(output.mag.B.components.values())[0].axes,
            values=Prad,
        )
        components["radial"] = Prad_data
    if not np_all((Ptan == 0)):
        Ptan_data = DataTime(
            name="Airgap tangential surface force",
            unit="N/m2",
            symbol="P_t",
            axes=list(output.mag.B.components.values())[0].axes,
            values=Ptan,
        )
        components["tangential"] = Ptan_data
    if not np_all((Pz == 0)):
        Pz_data = DataTime(
            name="Airgap axial surface force",
            unit="N/m2",
            symbol="P_z",
            axes=list(output.mag.B.components.values())[0].axes,
            values=Pz,
        )
        components["axial"] = Pz_data
    output.force.P = VectorField(name="Magnetic airgap surface force",
                                 symbol="P",
                                 components=components)
def build_solution_vector(field, axis_list, name="", symbol="", unit="", is_real=True):
    """Build a SolutionVector object

    Parameters
    ----------
    field : ndarray
        a vector vield
    axis_list : list
        a list of SciDataTool axis

    Returns
    -------
    solution: SolutionVector
        a SolutionVector object
    """

    components = {}

    x_data = DataTime(
        name=name,
        unit=unit,
        symbol=symbol + "x",
        axes=axis_list,
        values=field[..., 0],
        is_real=is_real,
    )
    components["comp_x"] = x_data

    y_data = DataTime(
        name=name,
        unit=unit,
        symbol=symbol + "y",
        axes=axis_list,
        values=field[..., 1],
        is_real=is_real,
    )
    components["comp_y"] = y_data

    if field.shape[-1] == 3 and not np_all((field[..., 2] == 0)):
        z_data = DataTime(
            name=name,
            unit=unit,
            symbol=symbol + "z",
            axes=axis_list,
            values=field[..., 2],
            is_real=is_real,
        )
        components["comp_z"] = z_data

    vectorfield = VectorField(name=name, symbol=symbol, components=components)

    solution = SolutionVector(field=vectorfield, label=symbol)

    return solution
Example #3
0
def comp_force_nodal(self, output, axes_dict):
    """Run the nodal forces calculation based on a tensor.

    from publications:


    Parameters
    ----------
    self : ForceTensor
        A ForceTensor object

    output : Output
        an Output object (to update)

    """

    dim = 2
    Time = axes_dict["Time"]
    Nt_tot = Time.get_length()  # Number of time step

    meshsolution_mag = output.mag.meshsolution  # Comes from FEMM simulation

    # Select the target group (stator, rotor ...)
    meshsolution_group = meshsolution_mag.get_group(self.group)

    # TODO before: Check if is_same_mesh is True
    mesh = meshsolution_group.get_mesh()

    # New meshsolution object for output, that could be different from the one inputed
    meshsolution = MeshSolution(mesh=[mesh.copy()],
                                is_same_mesh=True,
                                dimension=dim)

    # Load magnetic flux B and H and mu objects
    B_sol = meshsolution_group.get_solution(label="B")
    H_sol = meshsolution_group.get_solution(label="H")
    mu_sol = meshsolution_group.get_solution(label="\mu")

    # Import time vector from Time Data object
    if self.is_periodicity_t is not None:
        is_periodicity_t = self.is_periodicity_t

    is_periodicity_t, is_antiper_t = Time.get_periodicity()
    time = Time.get_values(
        is_oneperiod=is_periodicity_t,
        is_antiperiod=is_antiper_t and is_periodicity_t,
    )

    # Load magnetic flux B and H of size (Nt_tot, nb_elem, dim) and mu (Nt_tot, nb_elem)
    resultB = B_sol.field.get_xyz_along(
        "indice",
        "time=axis_data",
        axis_data={"time": time},
    )
    indice = resultB["indice"]  # Store elements indices

    Bx = resultB["comp_x"]
    By = resultB["comp_y"]
    B = np.stack((Bx, By), axis=2)

    resultH = H_sol.field.get_xyz_along(
        "indice",
        "time=axis_data",
        axis_data={"time": time},
    )
    Hx = resultH["comp_x"]
    Hy = resultH["comp_y"]
    H = np.stack((Hx, Hy), axis=2)

    resultmu = mu_sol.field.get_along(
        "indice",
        "time=axis_data",
        axis_data={"time": time},
    )
    mu = resultmu["\\mu"]

    # Move time axis at the end for clarity purpose
    B = np.moveaxis(B, 0, -1)
    H = np.moveaxis(H, 0, -1)
    mu = np.moveaxis(mu, 0, -1)

    # Loop on elements and nodes for nodal forces
    f, connect = self.element_loop(mesh, B, H, mu, indice, dim, Nt_tot)

    indices_nodes = np.sort(np.unique(connect))
    Indices_Point = Data1D(name="indice",
                           values=indices_nodes,
                           is_components=True)

    # Time axis goes back to first axis
    f = np.moveaxis(f, -1, 0)

    components = {}

    fx_data = DataTime(
        name="Nodal force (x)",
        unit="N",
        symbol="Fx",
        axes=[Time, Indices_Point],
        values=f[..., 0],
    )
    components["comp_x"] = fx_data

    fy_data = DataTime(
        name="Nodal force (y)",
        unit="N",
        symbol="Fy",
        axes=[Time, Indices_Point],
        values=f[..., 1],
    )
    components["comp_y"] = fy_data

    vec_force = VectorField(name="Nodal forces",
                            symbol="F",
                            components=components)
    solforce = SolutionVector(field=vec_force, type_cell="node", label="F")
    meshsolution.solution.append(solforce)

    out_dict = dict()
    out_dict["meshsolution"] = meshsolution

    return out_dict
Example #4
0
def build_meshsolution(self):
    """Get the mesh and solution data from an Elmer VTU results file

    Parameters
    ----------
    self : ElmerResultsVTU
        a ElmerResultsVTU object

    Returns
    -------
    success: bool
        Information if meshsolution could be created

    """
    # create meshsolution
    meshsol = MeshSolution(label=self.label)

    # get the mesh
    save_path, fn = split(self.file_path)
    file_name, file_ext = splitext(fn)
    if file_ext != ".vtu":
        raise ElmerResultsVTUError(
            "ElmerResultsVTU: Results file must be of type VTU.")

    meshvtk = MeshVTK(path=save_path, name=file_name, format="vtu")
    # TODO maybe convert to MeshMat before
    meshsol.mesh = [meshvtk]

    # get the solution data on the mesh
    meshsolvtu = read(self.file_path)
    pt_data = meshsolvtu.point_data  # point_data is of type dict

    # setup axes
    indices = arange(meshsolvtu.points.shape[0])
    Indices = Data1D(name="indice", values=indices, is_components=True)

    # store only data from store dict if available
    comp_ext = ["x", "y", "z"]

    sol_list = []  # list of solutions

    for key, value in pt_data.items():
        # check if value should be stored
        if key in self.store_dict.keys():
            siz = value.shape[1]
            # only regard max. 3 components
            if siz > 3:
                logger.warning(
                    f'ElmerResultsVTU.build_meshsolution(): size of data "{key}" > 3'
                    + " - " + "Data will be truncated.")
                siz = 3

            components = []
            comp_name = []

            # loop though components
            for i in range(siz):
                # setup name, symbol and component name extension
                if siz == 1:
                    ext = ""
                else:
                    ext = comp_ext[i]

                # setup data object
                data = DataTime(
                    name=self.store_dict[key]["name"] + " " + ext,
                    unit=self.store_dict[key]["unit"],
                    symbol=self.store_dict[key]["symbol"] + ext,
                    axes=[Indices],
                    values=value[:, i],
                    normalizations={
                        "ref": Norm_ref(ref=self.store_dict[key]["norm"])
                    },
                )
                components.append(data)
                comp_name.append("comp_" + ext)

            # setup solution depending on number of field components
            if siz == 1:
                field = components[0]
                sol_list.append(
                    SolutionData(
                        field=field,
                        type_cell="point",
                        label=self.store_dict[key]["symbol"],
                    ))
            else:
                comps = {}
                for i in range(siz):
                    comps[comp_name[i]] = components[i]
                field = VectorField(
                    name=self.store_dict[key]["name"],
                    symbol=self.store_dict[key]["symbol"],
                    components=comps,
                )
                sol_list.append(
                    SolutionVector(
                        field=field,
                        type_cell="point",
                        label=self.store_dict[key]["symbol"],
                    ))

    meshsol.solution = sol_list

    return meshsol
Example #5
0
def build_meshsolution(self, Nt_tot, meshFEMM, Time, B, H, mu, groups):
    """Build the MeshSolution objets from FEMM outputs.

    Parameters
    ----------
    self : MagFEMM
        a MagFEMM object
    is_get_mesh : bool
        1 to load the mesh and solution into the simulation
    is_save_FEA : bool
        1 to save the mesh and solution into a .json file
    j_t0 : int
        Targeted time step

    Returns
    -------
    meshsol: MeshSolution
        a MeshSolution object with FEMM outputs at every time step
    """

    sollist = list()
    cond = self.is_sliding_band or Nt_tot == 1
    if cond:
        indices_cell = meshFEMM[0].cell["triangle"].indice
        Direction = Data1D(name="direction",
                           values=["x", "y", "z"],
                           is_components=True)
        Indices_Cell = Data1D(name="indice",
                              values=indices_cell,
                              is_components=True)
        Nodirection = Data1D(name="direction",
                             values=["scalar"],
                             is_components=False)

        # Store the results for B
        components = {}

        Bx_data = DataTime(
            name="Magnetic Flux Density Bx",
            unit="T",
            symbol="Bx",
            axes=[Time, Indices_Cell],
            values=B[:, :, 0],
        )
        components["x"] = Bx_data

        By_data = DataTime(
            name="Magnetic Flux Density By",
            unit="T",
            symbol="By",
            axes=[Time, Indices_Cell],
            values=B[:, :, 1],
        )
        components["y"] = By_data

        if not np.all((B[:, :, 2] == 0)):
            Bz_data = DataTime(
                name="Magnetic Flux Density Bz",
                unit="T",
                symbol="Bz",
                axes=[Time, Indices_Cell],
                values=B[:, :, 2],
            )
            components["z"] = Bz_data

        solB = VectorField(name="Magnetic Flux Density",
                           symbol="B",
                           components=components)

        # Store the results for H
        componentsH = {}

        Hx_data = DataTime(
            name="Magnetic Field Hx",
            unit="A/m",
            symbol="Hx",
            axes=[Time, Indices_Cell],
            values=H[:, :, 0],
        )
        componentsH["x"] = Hx_data

        Hy_data = DataTime(
            name="Magnetic Field Hy",
            unit="A/m",
            symbol="Hy",
            axes=[Time, Indices_Cell],
            values=H[:, :, 1],
        )
        componentsH["y"] = Hy_data

        if not np.all((H[:, :, 2] == 0)):
            Hz_data = DataTime(
                name="Magnetic Field Hz",
                unit="A/m",
                symbol="Hz",
                axes=[Time, Indices_Cell],
                values=H[:, :, 2],
            )
            componentsH["z"] = Hz_data

        solH = VectorField(name="Magnetic Field",
                           symbol="H",
                           components=componentsH)

        solmu = DataTime(
            name="Magnetic Permeability",
            unit="H/m",
            symbol="\mu",
            axes=[Time, Indices_Cell],
            values=mu,
        )

        sollist.append(
            SolutionVector(field=solB, type_cell="triangle",
                           label="B"))  # Face solution
        sollist.append(
            SolutionVector(field=solH, type_cell="triangle", label="H"))
        sollist.append(
            SolutionData(field=solmu, type_cell="triangle", label="\mu"))

    meshsol = MeshSolution(
        label="FEMM_magnetotatic",
        mesh=meshFEMM,
        solution=sollist,
        is_same_mesh=cond,
        dimension=2,
    )

    meshsol.group = groups[0]

    return meshsol
Example #6
0
def get_meshsolution(self, output):
    """Build the MeshSolution objects from the FEA outputs.

    Parameters
    ----------
    self : MagElmer
        a MagElmer object
    output: Output
        An Output object

    Returns
    -------
    meshsol: MeshSolution
        a MeshSolution object with Elmer outputs at every time step
    """
    project_name = self.get_path_save_fea(output)
    elmermesh_folder = project_name
    meshsol = MeshSolution(label="Elmer MagnetoDynamics")
    if not self.is_get_mesh or not self.is_save_FEA:
        self.get_logger().info(
            "MagElmer: MeshSolution is not stored by request.")
        return False

    meshvtk = MeshVTK(path=elmermesh_folder, name="step_t0002", format="vtu")
    meshsol.mesh = [meshvtk]

    result_filename = join(elmermesh_folder, "step_t0002.vtu")
    meshsolvtu = read(result_filename)
    #pt_data = meshsolvtu.point_data
    cell_data = meshsolvtu.cell_data

    #indices = arange(meshsolvtu.points.shape[0])
    indices = arange(meshsolvtu.cells[0].data.shape[0] +
                     meshsolvtu.cells[1].data.shape[0])

    Indices = Data1D(name="indice", values=indices, is_components=True)
    # store_dict = {
    #     "magnetic vector potential": {
    #         "name": "Magnetic Vector Potential A",
    #         "unit": "Wb",
    #         "symbol": "A",
    #         "norm": 1,
    #     },
    #     "magnetic flux density": {
    #         "name": "Magnetic Flux Density B",
    #         "unit": "T",
    #         "symbol": "B",
    #         "norm": 1,
    #     },
    #     "magnetic field strength": {
    #         "name": "Magnetic Field H",
    #         "unit": "A/m",
    #         "symbol": "H",
    #         "norm": 1,
    #     },
    #     "current density": {
    #         "name": "Current Density J",
    #         "unit": "A/mm2",
    #         "symbol": "J",
    #         "norm": 1,
    #     }
    # }
    store_dict = {
        "magnetic flux density e": {
            "name": "Magnetic Flux Density B",
            "unit": "T",
            "symbol": "B",
            "norm": 1,
        },
        "magnetic vector potential e": {
            "name": "Magnetic Vector Potential A",
            "unit": "Wb",
            "symbol": "A",
            "norm": 1,
        },
        "magnetic field strength e": {
            "name": "Magnetic Field H",
            "unit": "A/m",
            "symbol": "H",
            "norm": 1,
        },
        "current density e": {
            "name": "Current Density J",
            "unit": "A/mm2",
            "symbol": "J",
            "norm": 1,
        },
    }
    comp_ext = ["x", "y", "z"]
    sol_list = []
    #for key, value in pt_data.items():
    for key, value in cell_data.items():
        if key in store_dict.keys():
            #siz = value.shape[1]
            siz = value[0].shape[1]
            if siz > 3:
                print("Some Message")
                siz = 3
            components = []
            comp_name = []
            values = np_append(value[0], value[1], axis=0)
            for i in range(siz):
                if siz == 1:
                    ext = ""
                else:
                    ext = comp_ext[i]

                data = DataTime(
                    name=store_dict[key]["name"] + ext,
                    unit=store_dict[key]["unit"],
                    symbol=store_dict[key]["symbol"] + ext,
                    axes=[Indices],
                    #values=value[:, i],
                    values=values[:, i],
                    normalizations={"ref": store_dict[key]["norm"]},
                )

                components.append(data)
                comp_name.append("comp_" + ext)

            if siz == 1:
                field = components[0]
                sol_list.append(
                    SolutionData(
                        field=field,
                        #type_cell="point",
                        type_cell="triangle",
                        label=store_dict[key]["symbol"],
                    ))
            else:
                comps = {}
                for i in range(siz):
                    comps[comp_name[i]] = components[i]
                field = VectorField(name=store_dict[key]["name"],
                                    symbol=store_dict[key]["symbol"],
                                    components=comps)
                sol_list.append(
                    SolutionVector(
                        field=field,
                        #type_cell="point",
                        type_cell="triangle",
                        label=store_dict[key]["symbol"],
                    ))

    meshsol.solution = sol_list
    output.mag.meshsolution = meshsol

    return True
Example #7
0
def solve_FEMM(self, femm, output, sym):

    # Get time and angular axes
    Angle_comp, Time_comp = self.get_axes(output)
    _, Time_comp_Tem = self.get_axes(output, is_remove_apert=True)

    # Check if the angular axis is anti-periodic
    _, is_antiper_a = Angle_comp.get_periodicity()

    # Import angular vector from Data object
    angle = Angle_comp.get_values(
        is_oneperiod=self.is_periodicity_a,
        is_antiperiod=is_antiper_a and self.is_periodicity_a,
    )

    # Number of angular steps
    Na_comp = angle.size

    # Check if the angular axis is anti-periodic
    _, is_antiper_t = Time_comp.get_periodicity()

    # Number of time steps
    Nt_comp = Time_comp.get_length(
        is_oneperiod=True,
        is_antiperiod=is_antiper_t and self.is_periodicity_t,
    )

    # Loading parameters for readibility
    L1 = output.simu.machine.stator.comp_length()
    save_path = self.get_path_save(output)
    FEMM_dict = output.mag.FEMM_dict

    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_comp, qs))
    else:
        Phi_wind_stator = None

    # Create the mesh
    femm.mi_createmesh()

    # Initialize results matrix
    Br = zeros((Nt_comp, Na_comp))
    Bt = zeros((Nt_comp, Na_comp))
    Tem = zeros((Nt_comp))

    Rag = output.simu.machine.comp_Rgap_mec()

    # Compute the data for each time step
    for ii in range(Nt_comp):
        self.get_logger().debug("Solving step " + str(ii + 1) + " / " +
                                str(Nt_comp))
        # Update rotor position and currents
        update_FEMM_simulation(
            femm=femm,
            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_comp):
                Br[ii, jj], Bt[ii,
                               jj] = femm.mo_getgapb("bc_ag2",
                                                     angle[jj] * 180 / pi)
        else:
            for jj in range(Na_comp):
                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, 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(
                femm,
                qs,
                Npcpp,
                is_stator=True,
                Lfemm=FEMM_dict["Lfemm"],
                L1=L1,
                sym=sym,
            )

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

            if ii == 0:
                meshFEMM = [tmpmeshFEMM]
                groups = [tmpgroups]
                B_elem = np.zeros(
                    [Nt_comp, meshFEMM[ii].cell["triangle"].nb_cell, 3])
                H_elem = np.zeros(
                    [Nt_comp, meshFEMM[ii].cell["triangle"].nb_cell, 3])
                mu_elem = np.zeros(
                    [Nt_comp, meshFEMM[ii].cell["triangle"].nb_cell])

            B_elem[ii, :, 0:2] = tmpB
            H_elem[ii, :, 0:2] = tmpH
            mu_elem[ii, :] = tmpmu

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

    # Store the results
    sym_dict = dict()  # Define the periodicity
    if self.is_periodicity_t:
        sym_dict.update(Time_comp.symmetries)
    if self.is_periodicity_a:
        sym_dict.update(Angle_comp.symmetries)

    sym_dict_Tem = dict()
    if self.is_periodicity_t:
        sym_dict_Tem.update(Time_comp_Tem.symmetries)

    Br_data = DataTime(
        name="Airgap radial flux density",
        unit="T",
        symbol="B_r",
        axes=[Time_comp, Angle_comp],
        symmetries=sym_dict,
        values=Br,
    )
    Bt_data = DataTime(
        name="Airgap tangential flux density",
        unit="T",
        symbol="B_t",
        axes=[Time_comp, Angle_comp],
        symmetries=sym_dict,
        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_comp_Tem],
        symmetries=sym_dict_Tem,
        values=Tem,
    )
    output.mag.Tem_av = mean(Tem)
    self.get_logger().debug("Average Torque: " + str(output.mag.Tem_av) +
                            " N.m")
    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

    if (hasattr(output.simu.machine.stator, "winding")
            and output.simu.machine.stator.winding is not None):
        Phase = Data1D(
            name="phase",
            unit="",
            values=gen_name(qs, is_add_phase=True),
            is_components=True,
        )
        output.mag.Phi_wind_stator = DataTime(
            name="Stator Winding Flux",
            unit="Wb",
            symbol="Phi_{wind}",
            axes=[Time_comp, Phase],
            symmetries=sym_dict,
            values=Phi_wind_stator,
        )

    output.mag.FEMM_dict = FEMM_dict

    if self.is_get_mesh:
        output.mag.meshsolution = self.build_meshsolution(
            Nt_comp, meshFEMM, Time_comp, B_elem, H_elem, mu_elem, 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

    if self.is_close_femm:
        femm.closefemm()
Example #8
0
def comp_AGSF_transfer(self, output, rnoise=None):
    """Method to compute Air-Gap Surface Force transfer from middle air-gap
    radius to stator bore radius.

    From publication:
        PILE, Raphaël, LE BESNERAIS, Jean, PARENT, Guillaume, et al. Analytical
        study of air-gap surface force–application to electrical machines. Open
        Physics, 2020, vol. 18, no 1, p. 658-673.
        https://www.degruyter.com/view/journals/phys/18/1/article-p658.xml

    Parameters
    ----------
    self: Force
        a Force object
    output : Output
        an Output object

    """

    Rag = output.force.Rag
    Rsbo = output.simu.machine.stator.Rint

    AGSF = output.force.AGSF

    arg_list = ["freqs", "wavenumber"]
    result_freq = AGSF.get_rphiz_along(*arg_list)
    Prad_wr = result_freq["radial"]
    Ptan_wr = result_freq["tangential"]
    wavenumber = result_freq["wavenumber"]
    freqs = result_freq["freqs"]
    Nf = len(freqs)

    Ratio = Rag / Rsbo

    # Transfer coefficients Eq. (46)
    Sn = (Ratio**
          2) * (power(Ratio, wavenumber) + power(Ratio, -wavenumber)) / 2
    Cn = (Ratio**
          2) * (power(Ratio, wavenumber) - power(Ratio, -wavenumber)) / 2

    # Noise filtering (useful with magnetic FEA)
    if rnoise is not None:
        Inoise = where(abs(wavenumber) > rnoise)[0]
        Sn[Inoise] = 1
        Cn[Inoise] = 0

    XSn = repeat(Sn[..., newaxis], Nf, axis=1).transpose()
    XCn = repeat(Cn[..., newaxis], Nf, axis=1).transpose()

    # Transfer law Eq. (45)
    Prad_wr_TR = multiply(XSn, Prad_wr) + 1j * multiply(XCn, Ptan_wr)
    Ptan_wr_TR = multiply(XSn, Ptan_wr) - 1j * multiply(XCn, Prad_wr)

    Datafreqs = Data1D(name="freqs", values=freqs)
    Datawavenumbers = Data1D(name="wavenumber", values=wavenumber)

    axes_list = [Datafreqs, Datawavenumbers]

    AGSF_TR = VectorField(
        name="Air gap Surface Force",
        symbol="AGSF",
    )

    AGSF_TR.components["radial"] = DataFreq(
        name="Radial AGSF",
        unit="N/m²",
        symbol="AGSF_r",
        axes=axes_list,
        values=Prad_wr_TR,
    )

    AGSF_TR.components["tangential"] = DataFreq(
        name="Tangential AGSF",
        unit="N/m²",
        symbol="AGSF_t",
        axes=axes_list,
        values=Ptan_wr_TR,
    )

    # Replace original AGSF
    output.force.AGSF = AGSF_TR
    output.force.Rag = Rsbo
Example #9
0
def comp_force(self, output, axes_dict):
    """Compute the air-gap surface force based on Maxwell Tensor (MT).

    Parameters
    ----------
    self : ForceMT
        A ForceMT object
    output : Output
        an Output object (to update)
    axes_dict: {Data}
        Dict of axes used for force calculation
    """

    # Get time and angular axes
    Angle = axes_dict["Angle"]
    Time = axes_dict["Time"]

    # Import angular vector from Angle Data object
    _, is_antiper_a = Angle.get_periodicity()
    angle = Angle.get_values(
        is_oneperiod=self.is_periodicity_a,
        is_antiperiod=is_antiper_a and self.is_periodicity_a,
    )

    # Import time vector from Time Data object
    _, is_antiper_t = Time.get_periodicity()
    time = Time.get_values(
        is_oneperiod=self.is_periodicity_t,
        is_antiperiod=is_antiper_t and self.is_periodicity_t,
    )

    # Load magnetic flux
    Brphiz = output.mag.B.get_rphiz_along(
        "time=axis_data",
        "angle=axis_data",
        axis_data={
            "time": time,
            "angle": angle
        },
    )
    Br = Brphiz["radial"]
    Bt = Brphiz["tangential"]
    Bz = Brphiz["axial"]

    # Magnetic void permeability
    mu_0 = 4 * pi * 1e-7

    # Compute AGSF with MT formula
    Prad = (Br * Br - Bt * Bt - Bz * Bz) / (2 * mu_0)
    Ptan = Br * Bt / mu_0
    Pz = Br * Bz / mu_0

    # Store Maxwell Stress tensor P in VectorField
    # Build axes list
    axes_list = list()
    for axe in output.mag.B.get_axes():
        if axe.name == Angle.name:
            axes_list.append(Angle)
        elif axe.name == Time.name:
            axes_list.append(Time)
        else:
            axes_list.append(axe)

    # Build components list
    components = {}
    if not np_all((Prad == 0)):
        Prad_data = DataTime(
            name="Airgap radial surface force",
            unit="N/m2",
            symbol="P_r",
            axes=axes_list,
            values=Prad,
        )
        components["radial"] = Prad_data
    if not np_all((Ptan == 0)):
        Ptan_data = DataTime(
            name="Airgap tangential surface force",
            unit="N/m2",
            symbol="P_t",
            axes=axes_list,
            values=Ptan,
        )
        components["tangential"] = Ptan_data
    if not np_all((Pz == 0)):
        Pz_data = DataTime(
            name="Airgap axial surface force",
            unit="N/m2",
            symbol="P_z",
            axes=axes_list,
            values=Pz,
        )
        components["axial"] = Pz_data

    # Store components in VectorField
    output.force.P = VectorField(name="Magnetic airgap surface force",
                                 symbol="P",
                                 components=components)
Example #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
Example #11
0
def get_meshsolution(self, output):
    """Get and set the mesh data and solution data.

    Parameters
    ----------
    self : StructElmer
        a StructElmer object
    save_path: str
        Full path to folder in which the results are saved

    Returns
    -------
    success: bool
        Information if meshsolution could be created

    """
    # logger
    logger = self.get_logger()

    # create meshsolution
    meshsol = MeshSolution(label="Elmer Structural")

    # if meshsoltion is not requested set empty MeshSolution
    if not self.is_get_mesh or not self.is_save_FEA:
        logger.info("StructElmer: MeshSolution is not stored by request.")
        output.struct.meshsolution = meshsol
        return False

    # get the mesh
    fea_path = self.get_path_save_fea(output)
    meshvtk = MeshVTK(path=join(fea_path, "Results"), name="case_t0001", format="vtu")
    # TODO maybe convert to MeshMat before
    meshsol.mesh = [meshvtk]

    # get the solution data on the mesh
    filename = join(fea_path, "Results", "case_t0001.vtu")
    meshsolvtu = read(filename)
    pt_data = meshsolvtu.point_data  # point_data is of type dict

    # setup axes
    indices = arange(meshsolvtu.points.shape[0])
    Indices = Data1D(name="indice", values=indices, is_components=True)

    # store only certain data
    store_dict = {
        "displacement": {
            "name": "Displacement",
            "unit": "mm",
            "symbol": "disp",
            "norm": 1e-3,
        },
        "vonmises": {
            "name": "Von Mises Stress",
            "unit": "MPa",
            "symbol": "vonmises",
            "norm": 1e6,
        },
    }
    comp_ext = ["x", "y", "z"]

    sol_list = []  # list of solutions

    for key, value in pt_data.items():
        # check if value should be stored
        if key in store_dict.keys():
            siz = value.shape[1]
            # only regard max. 3 components
            if siz > 3:
                logger.warning(
                    f'StructElmer get_meshsolution: size of data "{key}" > 3'
                    + " - "
                    + "Data will be truncated."
                )
                siz = 3

            components = []
            comp_name = []

            # loop though components
            for i in range(siz):
                # setup name, symbol and component name extension
                if siz == 1:
                    ext = ""
                else:
                    ext = comp_ext[i]

                # setup data object
                data = DataTime(
                    name=store_dict[key]["name"] + " " + ext,
                    unit=store_dict[key]["unit"],
                    symbol=store_dict[key]["symbol"] + ext,
                    axes=[Indices],
                    values=value[:, i],
                    normalizations={"ref": store_dict[key]["norm"]},
                )
                components.append(data)
                comp_name.append("comp_" + ext)

            # setup solution depending on number of field components
            if siz == 1:
                field = components[0]
                sol_list.append(
                    SolutionData(
                        field=field,
                        type_cell="point",
                        label=store_dict[key]["symbol"],
                    )
                )
            else:
                comps = {}
                for i in range(siz):
                    comps[comp_name[i]] = components[i]
                field = VectorField(
                    name=store_dict[key]["name"],
                    symbol=store_dict[key]["symbol"],
                    components=comps,
                )
                sol_list.append(
                    SolutionVector(
                        field=field,
                        type_cell="point",
                        label=store_dict[key]["symbol"],
                    )
                )

    meshsol.solution = sol_list

    output.struct.meshsolution = meshsol

    return True
Example #12
0
def store_output(self, output, out_dict, axes_dict):
    """Store the standard outputs of Magnetics that are temporarily in out_dict as arrays into OutMag as Data object

    Parameters
    ----------
    self : Magnetic
        a Magnetic object
    output : Output
        an Output object (to update)
    out_dict : dict
        Dict containing all magnetic quantities that have been calculated in comp_flux_airgap
    axes_dict: {Data}
        Dict of axes used for magnetic calculation

    """

    # Get time axis
    Time = axes_dict["Time"]

    # Store airgap flux as VectorField object
    # Axes for each airgap flux component
    axis_list = [Time, axes_dict["Angle"]]
    # Create VectorField with empty components
    output.mag.B = VectorField(
        name="Airgap flux density",
        symbol="B",
    )
    # Radial flux component
    if "Br" in out_dict:
        output.mag.B.components["radial"] = DataTime(
            name="Airgap radial flux density",
            unit="T",
            symbol="B_r",
            axes=axis_list,
            values=out_dict.pop("Br"),
        )
    # Tangential flux component
    if "Bt" in out_dict:
        output.mag.B.components["tangential"] = DataTime(
            name="Airgap tangential flux density",
            unit="T",
            symbol="B_t",
            axes=axis_list,
            values=out_dict.pop("Bt"),
        )
    # Axial flux component
    if "Bz" in out_dict:
        output.mag.B.components["axial"] = DataTime(
            name="Airgap axial flux density",
            unit="T",
            symbol="B_z",
            axes=axis_list,
            values=out_dict.pop("Bz"),
        )

    # Store electromagnetic torque over time, and global values: average, peak to peak and ripple
    if "Tem" in out_dict:

        Tem = out_dict.pop("Tem")

        output.mag.Tem = DataTime(
            name="Electromagnetic torque",
            unit="Nm",
            symbol="T_{em}",
            axes=[axes_dict["Time_Tem"]],
            values=Tem,
        )

        # Calculate average torque in Nm
        output.mag.Tem_av = mean(Tem)
        self.get_logger().debug("Average Torque: " + str(output.mag.Tem_av) +
                                " N.m")

        # Calculate peak to peak torque in absolute value Nm
        output.mag.Tem_rip_pp = abs(np_max(Tem) - np_min(Tem))  # [N.m]

        # Calculate torque ripple in percentage
        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

    # Store stator winding flux and calculate electromotive force
    if "Phi_wind_stator" in out_dict:

        # Store stator winding flux
        qs = self.parent.machine.stator.winding.qs

        Phase = Data1D(
            name="phase",
            unit="",
            values=gen_name(qs),
            is_components=True,
        )

        output.mag.Phi_wind_stator = DataTime(
            name="Stator Winding Flux",
            unit="Wb",
            symbol="Phi_{wind}",
            axes=[Time, Phase],
            values=out_dict.pop("Phi_wind_stator"),
        )

        # Electromotive force computation
        output.mag.comp_emf()