Example #1
0
    def test_Magnetic_FEMM_sym(self):
        """Test compute the Flux in FEMM, with and without symmetry
        and with MANATEE MMF analytical model
		"""

        out = Output(simu=simu)
        out.post.legend_name = "No symmetry"
        simu.run()

        out2 = Output(simu=simu_sym)
        out2.post.legend_name = "1/2 symmetry"
        out2.post.line_color = "r--"
        simu_sym.run()

        out3 = Output(simu=simu_load)
        out3.post.legend_name = "MANATEE MMF"
        out3.post.line_color = "g--"
        simu_load.run()

        # Plot the result by comparing the two simulation (sym / no sym)
        plt.close("all")
        out.plot_B_space(out_list=[out2])

        fig = plt.gcf()
        fig.savefig(join(save_path, "test_EM_SCIM_NL_006_sym.png"))

        # Plot the result by comparing the two simulation (no sym / MANATEE)
        plt.close("all")
        out.plot_B_space(j_t0=0, is_deg=False, out_list=[out3])

        fig = plt.gcf()
        fig.savefig(join(save_path, "test_EM_SCIM_NL_006_MMF.png"))
Example #2
0
    def test_Magnetic_FEMM(self):
        """Test compute the Flux in FEMM and import the mesh.
        """

        out = Output(simu=simu)
        out.post.legend_name = "Slotless lamination"
        simu.run()

        # out.plot_mesh_field(meshsolution=out.mag.meshsolution, title="Permeability")
        out.plot_mesh_field(
            mesh=out.mag.meshsolution.mesh[0],
            title="Permeability",
            field=out.mag.meshsolution.solution[0].mu,
        )
        fig = plt.gcf()
        fig.savefig(join(save_path, "test_CEFC_002_save_mag"))
Example #3
0
    def test_Magnetic_FEMM(self):
        """Test compute the Flux in FEMM without slots and without sliding band.
        """

        out = Output(simu=simu)
        out.post.legend_name = "Slotless lamination"
        simu.run()
    def test_Magnetic_FEMM(self):
        """Test compute the Flux in FEMM and import the mesh.
        """

        out = Output(simu=simu)
        out.post.legend_name = "Slotless lamination"
        simu.run()

        out.plot_mesh_field(
            mesh=out.mag.meshsolution[0].mesh,
            field=out.mag.meshsolution[0].solution.get_field("mu"),
            title="Permeability",
        )

        element_dict = ElementDict()
        element_dict.convert_element(
            out.mag.meshsolution[0].mesh.element)  # It works !
 def test_InCurrent_Error_test(self, test_dict):
     """Check that the input current raises the correct errors
     """
     output = Output(simu=test_dict["test_obj"])
     with self.assertRaises(InputError,
                            msg="Expect: " + test_dict["exp"]) as context:
         output.simu.input.gen_input()
     self.assertEqual(test_dict["exp"], str(context.exception))
Example #6
0
    def test_Magnetic_FEMM_sym(self):
        """Test compute the Flux in FEMM, with and without symmetry
        """

        out = Output(simu=simu)
        out.post.legend_name = "No symmetry"
        simu.run()

        out2 = Output(simu=simu_sym)
        out2.post.legend_name = "1/2 symmetry"
        out2.post.line_color = "r--"
        simu_sym.run()

        # Plot the result by comparing the two simulation
        plt.close("all")
        out.plot_B_space(out_list=[out2])

        fig = plt.gcf()
        fig.savefig(join(save_path, "test_EM_IPMSM_FL_002_sym.png"))

        # Plot the surface magnetic forces
        plt.close("all")
        out.plot_force_space(j_t0=0, is_deg=False, out_list=[])

        fig = plt.gcf()
        fig.savefig(join(save_path, "test_EM_IPMSM_FL_002_force.png"))
    def test_Magnetic_FEMM_sym(self):
        """Test compute the Flux in FEMM, with and without symmetry
        and with MANATEE semi-analytical subdomain model
		"""

        out = Output(simu=simu)
        out.post.legend_name = "Symmetry"
        simu.run()

        out3 = Output(simu=simu_load)
        out3.post.legend_name = "MANATEE SDM"
        out3.post.line_color = "r--"
        simu_load.run()

        plt.close("all")
        out.plot_B_space(out_list=[out3])

        fig = plt.gcf()
        fig.savefig(join(save_path, "test_EM_SPMSM_NL_001_SDM.png"))
Example #8
0
def update(indiv):
    """Update the individual output after the mutation"""

    indiv.output = Output(simu=indiv.output.simu.as_dict())

    for k in range(len(indiv.keys)):
        exec("indiv." + indiv.design_var[indiv.keys[k]].name + "=indiv[k]")

    indiv.is_simu_valid = False
    indiv.cstr_viol = 0

    # Delete the fitness
    del indiv.fitness.values
Example #9
0
    def test_FEMM_sym(self):
        """Figure 9: Check that the FEMM can handle symmetry
        From pyleecan/Tests/Validation/Simulation/test_EM_SCIM_NL_006.py
        """
        simu = Simu1(name="ICEM_2020", machine=SCIM_006)
        simu.machine.name = "fig_09_FEMM_sym"

        # Definition of the enforced output of the electrical module
        Nr = ImportMatrixVal(value=ones(1) * 1500)
        Is = ImportMatrixVal(value=array([[20, -10, -10]]))
        Ir = ImportMatrixVal(value=zeros((1, 28)))
        time = ImportGenVectLin(start=0, stop=0, num=1, endpoint=False)
        angle = ImportGenVectLin(start=0,
                                 stop=2 * pi,
                                 num=4096,
                                 endpoint=False)
        simu.input = InCurrent(
            Is=Is,
            Ir=Ir,  # zero current for the rotor
            Nr=Nr,
            angle_rotor=None,  # Will be computed
            time=time,
            angle=angle,
            angle_rotor_initial=0.2244,
        )

        # Definition of the magnetic simulation
        # 2 sym + antiperiodicity = 1/4 Lamination
        simu.mag = MagFEMM(
            is_stator_linear_BH=2,
            is_rotor_linear_BH=2,
            is_symmetry_a=True,
            sym_a=2,
            is_antiper_a=True,
        )
        # Stop after magnetic computation
        simu.struct = None
        # Run simulation
        out = Output(simu=simu)
        simu.run()

        # FEMM files (mesh and results) are available in Results folder
        copyfile(
            join(out.path_res, "Femm", "fig_09_FEMM_sym_model.ans"),
            join(save_path, "fig_09_FEMM_sym_model.ans"),
        )
        copyfile(
            join(out.path_res, "Femm", "fig_09_FEMM_sym_model.fem"),
            join(save_path, "fig_09_FEMM_sym_model.fem"),
        )
    def test_InCurrent_Ok(self):
        """Check that the input current can return a correct output
        """
        test_obj = Simulation(machine=M3)
        output = Output(simu=test_obj)
        time = ImportGenVectLin(0, 1, 16)
        angle = ImportGenVectLin(0, 2 * pi, 20)
        Is = ImportGenMatrixSin(is_transpose=True)
        Is.init_vector(f=[2, 2, 2],
                       A=[2, 2, 2],
                       Phi=[pi / 2, 0, -pi / 2],
                       N=16,
                       Tf=1)
        S = sqrt(2)
        Is_exp = transpose(
            array([
                [2, S, 0, -S, -2, -S, 0, S, 2, S, 0, -S, -2, -S, 0, S],
                [0, S, 2, S, 0, -S, -2, -S, 0, S, 2, S, 0, -S, -2, -S],
                [-2, -S, 0, S, 2, S, 0, -S, -2, -S, 0, S, 2, S, 0, -S],
            ]))

        Ir = ImportGenMatrixSin(is_transpose=True)
        Ir.init_vector(f=[2, 2], A=[2, 2], Phi=[0, -pi / 2], N=16, Tf=1)
        Ir_exp = transpose(
            array([
                [0, S, 2, S, 0, -S, -2, -S, 0, S, 2, S, 0, -S, -2, -S],
                [-2, -S, 0, S, 2, S, 0, -S, -2, -S, 0, S, 2, S, 0, -S],
            ]))

        angle_rotor = ImportGenVectLin(0, 2 * pi, 16)
        Nr = ImportMatrixVal(value=ones(16) * 10)
        test_obj.input = InCurrent(time=time,
                                   angle=angle,
                                   Is=Is,
                                   Ir=Ir,
                                   angle_rotor=angle_rotor,
                                   Nr=Nr)

        test_obj.input.gen_input()
        assert_array_almost_equal(output.elec.time, linspace(0, 1, 16))
        assert_array_almost_equal(output.elec.angle, linspace(0, 2 * pi, 20))
        assert_array_almost_equal(output.elec.Is, Is_exp)
        assert_array_almost_equal(output.elec.Ir, Ir_exp)
        assert_array_almost_equal(output.elec.angle_rotor,
                                  linspace(0, 2 * pi, 16))
        assert_array_almost_equal(output.elec.Nr, ones(16) * 10)
Example #11
0
    def create_indiv(create, output, design_var):
        """Create individual using DEAP tools
        
        Parameters
        ----------
        creator : function
            function to create the individual
        output : pyleecan.Classes.Output
            output of the individual
        design_var : dict
            Design variables  
            
        Returns:
        --------
        indiv : list
            individual 
        """

        # Extract design variables
        keys = list(design_var.keys())
        var = []

        keys.sort()
        for key in keys:
            tmp = design_var[key].function(design_var[key].space)
            exec(design_var[key].name + "=tmp")
            var.append(tmp)

        ind = create(var)

        # Store the keys
        ind.keys = keys

        # Store the design variables
        ind.design_var = design_var

        # Store the simulation validity
        ind.is_simu_valid = False

        # Store the number of constraints violations
        ind.cstr_viol = 0

        # Output with the design variables set
        ind.output = Output(simu=output.simu.as_dict())

        return ind
Example #12
0
    def test_Magnetic_Phi0(self):
        """Test compute the Torque in FEMM as a function of Phi0
        and compare the results with Syr-e r29
		"""

        Tem_FEMM = zeros(Phi0.shape)
        for ii, I in enumerate(Is_list):
            simu.input.Is = ImportMatrixVal(value=I)
            out = Output(simu=simu)
            simu.run()
            print("test_EM_SynRM_FL_001: " + str(ii + 1) + "/16")
            Tem_FEMM[ii] = out.mag.Tem_av

        fig, ax = plt.subplots()
        ax.set_title("Torque as a function of Phi0")
        ax.set_xlabel("Phi0 [rad]")
        ax.set_ylabel("Torque [N.m]")
        ax.plot(Phi0, Tem_FEMM, "r", label="FEMM")
        ax.plot(Phi0, Tem, "b--", label="Syr-e")

        fig.savefig(join(save_path, "test_EM_SynRM_FL_001.png"))
Example #13
0
    def test_InCurrentDQ_Ok(self):
        """Check that the input current can return a correct output
        """
        test_obj = Simulation(machine=M1)
        output = Output(simu=test_obj)
        time = ImportGenVectLin(0, 1, 7)
        angle = ImportGenVectLin(0, 2 * pi, 20)
        Is = ImportMatrixVal(value=transpose(
            array([
                [2, 2, 2, 2, 2, 2, 2],
                [0, 0, 0, 0, 0, 0, 0],
            ])))

        Is_exp = transpose(
            array([
                [2, 1, -1, -2, -1, 1, 2],
                [-1, 1, 2, 1, -1, -2, -1],
                [-1, -2, -1, 1, 2, 1, -1],
            ]))

        zp = M1.stator.get_pole_pair_number()
        angle_rotor_initial = M1.comp_initial_angle()
        angle_rotor_exp = linspace(0, 2 * pi / zp, 7) + angle_rotor_initial

        Nr = ImportMatrixVal(value=ones(7) * 60 / zp)
        test_obj.input = InCurrentDQ(time=time,
                                     angle=angle,
                                     Is=Is,
                                     Ir=None,
                                     angle_rotor=None,
                                     Nr=Nr,
                                     angle_rotor_initial=angle_rotor_initial,
                                     rot_dir=1)

        test_obj.input.gen_input()
        assert_array_almost_equal(output.elec.time, linspace(0, 1, 7))
        assert_array_almost_equal(output.elec.angle, linspace(0, 2 * pi, 20))
        assert_array_almost_equal(output.elec.Is, Is_exp)
        assert_array_almost_equal(output.elec.angle_rotor, angle_rotor_exp)
        assert_array_almost_equal(output.elec.Nr, ones(7) * 60 / zp)
Example #14
0
class OutputMulti(FrozenClass):

    # cf Methods.Output.OutputMulti.add_output
    if isinstance(add_output, ImportError):
        add_output = property(fget=lambda x: raise_(
            ImportError("Can't use OutputMulti method add_output: " + str(
                add_output))))
    else:
        add_output = add_output
    # save method is available in all object
    save = save

    def __init__(
        self,
        output_ref=-1,
        outputs=list(),
        is_valid=[],
        design_var=[],
        design_var_names=[],
        init_dict=None,
    ):
        """Constructor of the class. Can be use in two ways :
        - __init__ (arg1 = 1, arg3 = 5) every parameters have name and default values
            for Matrix, None will initialise the property with an empty Matrix
            for pyleecan type, None will call the default constructor
        - __init__ (init_dict = d) d must be a dictionnary wiht every properties as keys

        ndarray or list can be given for Vector and Matrix
        object or dict can be given for pyleecan Object"""

        if output_ref == -1:
            output_ref = Output()
        if init_dict is not None:  # Initialisation by dict
            check_init_dict(
                init_dict,
                [
                    "output_ref", "outputs", "is_valid", "design_var",
                    "design_var_names"
                ],
            )
            # Overwrite default value with init_dict content
            if "output_ref" in list(init_dict.keys()):
                output_ref = init_dict["output_ref"]
            if "outputs" in list(init_dict.keys()):
                outputs = init_dict["outputs"]
            if "is_valid" in list(init_dict.keys()):
                is_valid = init_dict["is_valid"]
            if "design_var" in list(init_dict.keys()):
                design_var = init_dict["design_var"]
            if "design_var_names" in list(init_dict.keys()):
                design_var_names = init_dict["design_var_names"]
        # Initialisation by argument
        self.parent = None
        # output_ref can be None, a Output object or a dict
        if isinstance(output_ref, dict):
            self.output_ref = Output(init_dict=output_ref)
        else:
            self.output_ref = output_ref
        # outputs can be None or a list of Output object
        self.outputs = list()
        if type(outputs) is list:
            for obj in outputs:
                if obj is None:  # Default value
                    self.outputs.append(Output())
                elif isinstance(obj, dict):
                    self.outputs.append(Output(init_dict=obj))
                else:
                    self.outputs.append(obj)
        elif outputs is None:
            self.outputs = list()
        else:
            self.outputs = outputs
        self.is_valid = is_valid
        self.design_var = design_var
        self.design_var_names = design_var_names

        # The class is frozen, for now it's impossible to add new properties
        self._freeze()

    def __str__(self):
        """Convert this objet in a readeable string (for print)"""

        OutputMulti_str = ""
        if self.parent is None:
            OutputMulti_str += "parent = None " + linesep
        else:
            OutputMulti_str += ("parent = " + str(type(self.parent)) +
                                " object" + linesep)
        if self.output_ref is not None:
            tmp = (self.output_ref.__str__().replace(linesep, linesep +
                                                     "\t").rstrip("\t"))
            OutputMulti_str += "output_ref = " + tmp
        else:
            OutputMulti_str += "output_ref = None" + linesep + linesep
        if len(self.outputs) == 0:
            OutputMulti_str += "outputs = []" + linesep
        for ii in range(len(self.outputs)):
            tmp = self.outputs[ii].__str__().replace(linesep,
                                                     linesep + "\t") + linesep
            OutputMulti_str += "outputs[" + str(
                ii) + "] =" + tmp + linesep + linesep
        OutputMulti_str += (
            "is_valid = " + linesep +
            str(self.is_valid).replace(linesep, linesep + "\t") + linesep)
        OutputMulti_str += (
            "design_var = " + linesep +
            str(self.design_var).replace(linesep, linesep + "\t") + linesep)
        OutputMulti_str += ("design_var_names = " + linesep + str(
            self.design_var_names).replace(linesep, linesep + "\t") + linesep)
        return OutputMulti_str

    def __eq__(self, other):
        """Compare two objects (skip parent)"""

        if type(other) != type(self):
            return False
        if other.output_ref != self.output_ref:
            return False
        if other.outputs != self.outputs:
            return False
        if other.is_valid != self.is_valid:
            return False
        if other.design_var != self.design_var:
            return False
        if other.design_var_names != self.design_var_names:
            return False
        return True

    def as_dict(self):
        """Convert this objet in a json seriable dict (can be use in __init__)
        """

        OutputMulti_dict = dict()
        if self.output_ref is None:
            OutputMulti_dict["output_ref"] = None
        else:
            OutputMulti_dict["output_ref"] = self.output_ref.as_dict()
        OutputMulti_dict["outputs"] = list()
        for obj in self.outputs:
            OutputMulti_dict["outputs"].append(obj.as_dict())
        OutputMulti_dict["is_valid"] = self.is_valid
        OutputMulti_dict["design_var"] = self.design_var
        OutputMulti_dict["design_var_names"] = self.design_var_names
        # The class name is added to the dict fordeserialisation purpose
        OutputMulti_dict["__class__"] = "OutputMulti"
        return OutputMulti_dict

    def _set_None(self):
        """Set all the properties to None (except pyleecan object)"""

        if self.output_ref is not None:
            self.output_ref._set_None()
        for obj in self.outputs:
            obj._set_None()
        self.is_valid = None
        self.design_var = None
        self.design_var_names = None

    def _get_output_ref(self):
        """getter of output_ref"""
        return self._output_ref

    def _set_output_ref(self, value):
        """setter of output_ref"""
        check_var("output_ref", value, "Output")
        self._output_ref = value

        if self._output_ref is not None:
            self._output_ref.parent = self

    # Reference output of the multi simulation
    # Type : Output
    output_ref = property(
        fget=_get_output_ref,
        fset=_set_output_ref,
        doc=u"""Reference output of the multi simulation""",
    )

    def _get_outputs(self):
        """getter of outputs"""
        for obj in self._outputs:
            if obj is not None:
                obj.parent = self
        return self._outputs

    def _set_outputs(self, value):
        """setter of outputs"""
        check_var("outputs", value, "[Output]")
        self._outputs = value

        for obj in self._outputs:
            if obj is not None:
                obj.parent = self

    # list of output from the multi-simulation
    # Type : [Output]
    outputs = property(
        fget=_get_outputs,
        fset=_set_outputs,
        doc=u"""list of output from the multi-simulation""",
    )

    def _get_is_valid(self):
        """getter of is_valid"""
        return self._is_valid

    def _set_is_valid(self, value):
        """setter of is_valid"""
        check_var("is_valid", value, "list")
        self._is_valid = value

    # list to indicate if the corresponding output is valid
    # Type : list
    is_valid = property(
        fget=_get_is_valid,
        fset=_set_is_valid,
        doc=u"""list to indicate if the corresponding output is valid""",
    )

    def _get_design_var(self):
        """getter of design_var"""
        return self._design_var

    def _set_design_var(self, value):
        """setter of design_var"""
        check_var("design_var", value, "list")
        self._design_var = value

    # list of design variables corresponding to the output
    # Type : list
    design_var = property(
        fget=_get_design_var,
        fset=_set_design_var,
        doc=u"""list of design variables corresponding to the output""",
    )

    def _get_design_var_names(self):
        """getter of design_var_names"""
        return self._design_var_names

    def _set_design_var_names(self, value):
        """setter of design_var_names"""
        check_var("design_var_names", value, "list")
        self._design_var_names = value

    # list of str containing the design variables names sorted alphabetically
    # Type : list
    design_var_names = property(
        fget=_get_design_var_names,
        fset=_set_design_var_names,
        doc=
        u"""list of str containing the design variables names sorted alphabetically""",
    )
Example #15
0
    def __init__(
        self,
        output_ref=-1,
        outputs=list(),
        is_valid=[],
        design_var=[],
        design_var_names=[],
        init_dict=None,
    ):
        """Constructor of the class. Can be use in two ways :
        - __init__ (arg1 = 1, arg3 = 5) every parameters have name and default values
            for Matrix, None will initialise the property with an empty Matrix
            for pyleecan type, None will call the default constructor
        - __init__ (init_dict = d) d must be a dictionnary wiht every properties as keys

        ndarray or list can be given for Vector and Matrix
        object or dict can be given for pyleecan Object"""

        if output_ref == -1:
            output_ref = Output()
        if init_dict is not None:  # Initialisation by dict
            check_init_dict(
                init_dict,
                [
                    "output_ref", "outputs", "is_valid", "design_var",
                    "design_var_names"
                ],
            )
            # Overwrite default value with init_dict content
            if "output_ref" in list(init_dict.keys()):
                output_ref = init_dict["output_ref"]
            if "outputs" in list(init_dict.keys()):
                outputs = init_dict["outputs"]
            if "is_valid" in list(init_dict.keys()):
                is_valid = init_dict["is_valid"]
            if "design_var" in list(init_dict.keys()):
                design_var = init_dict["design_var"]
            if "design_var_names" in list(init_dict.keys()):
                design_var_names = init_dict["design_var_names"]
        # Initialisation by argument
        self.parent = None
        # output_ref can be None, a Output object or a dict
        if isinstance(output_ref, dict):
            self.output_ref = Output(init_dict=output_ref)
        else:
            self.output_ref = output_ref
        # outputs can be None or a list of Output object
        self.outputs = list()
        if type(outputs) is list:
            for obj in outputs:
                if obj is None:  # Default value
                    self.outputs.append(Output())
                elif isinstance(obj, dict):
                    self.outputs.append(Output(init_dict=obj))
                else:
                    self.outputs.append(obj)
        elif outputs is None:
            self.outputs = list()
        else:
            self.outputs = outputs
        self.is_valid = is_valid
        self.design_var = design_var
        self.design_var_names = design_var_names

        # The class is frozen, for now it's impossible to add new properties
        self._freeze()
Example #16
0
def test_zdt3():
    # ### Defining reference Output

    # Definition of the enforced output of the electrical module
    Nt = 2
    Nr = ImportMatrixVal(value=np.ones(Nt) * 3000)
    Is = ImportMatrixVal(value=np.array([
        [6.97244193e-06, 2.25353053e02, -2.25353060e02],
        [-2.60215295e02, 1.30107654e02, 1.30107642e02],
        #             [-6.97244208e-06, -2.25353053e02, 2.25353060e02],
        #             [2.60215295e02, -1.30107654e02, -1.30107642e02],
    ]))
    Ir = ImportMatrixVal(value=np.zeros(30))
    time = ImportGenVectLin(start=0, stop=0.015, num=Nt, endpoint=True)
    angle = ImportGenVectLin(start=0, stop=2 * np.pi, num=64,
                             endpoint=False)  # num=1024

    # Definition of the simulation
    simu = Simu1(name="Test_machine", machine=SCIM_001)

    simu.input = InCurrent(
        Is=Is,
        Ir=Ir,  # zero current for the rotor
        Nr=Nr,
        angle_rotor=None,  # Will be computed
        time=time,
        angle=angle,
        angle_rotor_initial=0.5216 + np.pi,
    )

    # Definition of the magnetic simulation
    simu.mag = MagFEMM(
        is_stator_linear_BH=2,
        is_rotor_linear_BH=2,
        is_symmetry_a=True,
        is_antiper_a=False,
    )
    simu.mag.Kmesh_fineness = 0.01
    # simu.mag.Kgeo_fineness=0.02
    simu.mag.sym_a = 4
    simu.struct = None

    output = Output(simu=simu)

    # ### Design variable
    my_vars = {}

    for i in range(30):
        my_vars["var_" + str(i)] = OptiDesignVar(
            name="output.simu.input.Ir.value[" + str(i) + "]",
            type_var="interval",
            space=[0, 1],
            function=lambda space: np.random.uniform(*space),
        )

    # ### Objectives
    objs = {
        "obj1":
        OptiObjFunc(
            description="Maximization of the torque average",
            func=lambda output: output.mag.Tem_av,
        ),
        "obj2":
        OptiObjFunc(
            description="Minimization of the torque ripple",
            func=lambda output: output.mag.Tem_rip,
        ),
    }

    # ### Evaluation
    def evaluate(output):
        x = output.simu.input.Ir.value
        f1 = lambda x: x[0]
        g = lambda x: 1 + (9 / 29) * np.sum(x[1:])
        h = lambda f1, g: 1 - np.sqrt(f1 / g) - (f1 / g) * np.sin(10 * np.pi *
                                                                  f1)
        output.mag.Tem_av = f1(x)
        output.mag.Tem_rip = g(x) * h(f1(x), g(x))

    # ### Defining the problem
    my_prob = OptiProblem(output=output,
                          design_var=my_vars,
                          obj_func=objs,
                          eval_func=evaluate)

    solver = OptiGenAlgNsga2Deap(
        problem=my_prob,
        size_pop=40,
        nb_gen=100,
        p_mutate=0.5,
    )
    res = solver.solve()

    def plot_pareto(self):
        """Plot every fitness values with the pareto front for 2 fitness
        
        Parameters
        ----------
        self : OutputMultiOpti
        """

        # TODO Add a feature to return the design_varibles of each indiv from the Pareto front

        # Get fitness and ngen
        is_valid = np.array(self.is_valid)
        fitness = np.array(self.fitness)
        ngen = np.array(self.ngen)

        # Keep only valid values
        indx = np.where(is_valid)[0]

        fitness = fitness[indx]
        ngen = ngen[indx]

        # Get pareto front
        pareto = list(np.unique(fitness, axis=0))

        # Get dominated values
        to_remove = []
        N = len(pareto)
        for i in range(N):
            for j in range(N):
                if all(pareto[j] <= pareto[i]) and any(pareto[j] < pareto[i]):
                    to_remove.append(pareto[i])
                    break

        # Remove dominated values
        for i in to_remove:
            for l in range(len(pareto)):
                if all(i == pareto[l]):
                    pareto.pop(l)
                    break

        pareto = np.array(pareto)

        fig, axs = plt.subplots(1, 2, figsize=(16, 6))

        # Plot Pareto front
        axs[0].scatter(
            pareto[:, 0],
            pareto[:, 1],
            facecolors="b",
            edgecolors="b",
            s=0.8,
            label="Pareto Front",
        )
        axs[0].autoscale()
        axs[0].legend()
        axs[0].set_title("Pyleecan results")
        axs[0].set_xlabel(r"$f_1(x)$")
        axs[0].set_ylabel(r"$f_2(x)$")
        try:
            img_to_find = img.imread(
                "pyleecan\\Tests\\Validation\\Optimization\\zdt3.jpg",
                format="jpg")
            axs[1].imshow(img_to_find, aspect="auto")
            axs[1].axis("off")
            axs[1].set_title("Pareto front of the problem")
        except TypeError:
            print("Pillow is needed to import jpg files")

        return fig

    fig = plot_pareto(res)
    plt.savefig("pyleecan\\Tests\\Results\\Validation\\test_zdt3.png")
    def test_Magnetic_FEMM(self):
        """Test compute the Flux in FEMM and import the mesh.
        """

        out = Output(simu=simu)
        out.post.legend_name = "Slotless lamination"
        simu.run()

        out.plot_mesh(mesh=out.mag.meshsolution.mesh[0], title="FEA Mesh")

        # out.plot_mesh_field(meshsolution=out.mag.meshsolution, title="Permeability")
        out.plot_mesh_field(
            mesh=out.mag.meshsolution.mesh[0],
            title="Permeability",
            field=out.mag.meshsolution.solution[0].face["mu"],
        )
        fig = plt.gcf()
        fig.savefig(join(save_path, "test_CEFC_002_save_mag"))

        # Test save with MeshSolution object in out
        out.save(save_path=save_path)

        load_path = join(save_path, "Output.json")
        # Test to load the Meshsolution object (inside the output):
        with open(load_path) as json_file:
            json_tmp = json.load(json_file)
            FEMM = Output(init_dict=json_tmp)

        # To test that the "mu" is still a ndarray after saving and loading
        out.plot_mesh_field(
            mesh=FEMM.mag.meshsolution.mesh[0],
            title="Permeability",
            field=FEMM.mag.meshsolution.solution[0].face["mu"],
        )
Example #18
0
    def test_ecc_FEMM(self):
        """Figure 19: transfrom_list in FEMM for eccentricities
        """
        simu = Simu1(name="ICEM_2020", machine=SPMSM_015)
        simu.machine.name = "fig_19_Transform_list"

        # Modify stator Rext to get more convincing translation
        SPMSM_015.stator.Rext = SPMSM_015.stator.Rext * 0.9
        gap = SPMSM_015.comp_width_airgap_mec()

        # Definition of the enforced output of the electrical module
        Nr = ImportMatrixVal(value=ones(1) * 3000)
        Is = ImportMatrixVal(value=array([[0, 0, 0]]))
        time = ImportGenVectLin(start=0, stop=0, num=1, endpoint=True)
        angle = ImportGenVectLin(start=0,
                                 stop=2 * 2 * pi / 9,
                                 num=2043,
                                 endpoint=False)
        simu.input = InCurrent(
            Is=Is,
            Ir=None,  # No winding on the rotor
            Nr=Nr,
            angle_rotor=None,
            time=time,
            angle=angle,
            angle_rotor_initial=0,
        )

        # Definition of the magnetic simulation (is_mmfr=False => no flux from the magnets)
        simu.mag = MagFEMM(
            is_stator_linear_BH=0,
            is_rotor_linear_BH=0,
            is_sliding_band=False,  # Ecc => No sliding band
            is_symmetry_a=False,  # No sym
            is_mmfs=False,
            is_get_mesh=True,
            is_save_FEA=True,
            sym_a=1,
        )
        simu.struct = None

        # Set two transformations
        # First rotate 3rd Magnet
        transform_list = [{
            "type": "rotate",
            "value": 0.08,
            "label": "MagnetRotorRadial_S_R0_T0_S3"
        }]
        # Then Translate the rotor
        transform_list.append({
            "type": "translate",
            "value": gap * 0.75,
            "label": "Rotor"
        })
        simu.mag.transform_list = transform_list

        # Run the simulation
        out = Output(simu=simu)
        simu.run()

        # FEMM files (mesh and results) are available in Results folder
        copyfile(
            join(out.path_res, "Femm", "fig_19_Transform_list_model.ans"),
            join(save_path, "fig_19_Transform_list_model.ans"),
        )
        copyfile(
            join(out.path_res, "Femm", "fig_19_Transform_list_model.fem"),
            join(save_path, "fig_19_Transform_list_model.fem"),
        )
        # Plot, check, save
        out.plot_mesh(mesh=out.mag.meshsolution.mesh[0], title="FEMM Mesh")
        fig = plt.gcf()
        fig.savefig(join(save_path, "fig_19_transform_list.png"))
        fig.savefig(join(save_path, "fig_19_transform_list.svg"), format="svg")
Example #19
0
    def test_Optimization_problem(self):
        """
        Figure19: Machine topology before optimization
        Figure20: Individuals in the fitness space
        Figure21: Pareto Front in the fitness space
        Figure22: Topology to maximize first torque harmonic
        Figure22: Topology to minimize second torque harmonic  

        WARNING: The computation takes 6 hours on a single 3GHz CPU core.
        The algorithm uses randomization at different steps so 
        the results won't be exactly the same as the one in the publication
        """
        # ------------------ #
        # DEFAULT SIMULATION #
        # ------------------ #

        # First, we need to define a default simulation.
        # This simulation will the base of every simulation during the optimization process

        # Load the machine
        SPMSM_001 = load("pyleecan/Tests/Validation/Machine/SPMSM_001.json")

        # Definition of the enforced output of the electrical module
        Na = 1024  # Angular steps
        Nt = 32  # Time step
        Is = ImportMatrixVal(value=np.array([
            [1.73191211247099e-15, 24.4948974278318, -24.4948974278318],
            [-0.925435413499285, 24.9445002597334, -24.0190648462341],
            [-1.84987984757817, 25.3673918959653, -23.5175120483872],
            [-2.77234338398183, 25.7631194935712, -22.9907761095894],
            [-3.69183822565029, 26.1312592975275, -22.4394210718773],
            [-4.60737975447626, 26.4714170945114, -21.8640373400352],
            [-5.51798758565886, 26.7832286350338, -21.2652410493749],
            [-6.42268661752422, 27.0663600234871, -20.6436734059628],
            [-7.32050807568877, 27.3205080756888, -20.0000000000000],
            [-8.21049055044714, 27.5454006435389, -19.3349100930918],
            [-9.09168102627374, 27.7407969064430, -18.6491158801692],
            [-9.96313590233562, 27.9064876291883, -17.9433517268527],
            [-10.8239220029239, 28.0422953859991, -17.2183733830752],
            [-11.6731175767218, 28.1480747505277, -16.4749571738058],
            [-12.5098132838389, 28.2237124515809, -15.7138991677421],
            [-13.3331131695549, 28.2691274944141, -14.9360143248592],
            [-14.1421356237309, 28.2842712474619, -14.1421356237310],
            [-14.9360143248592, 28.2691274944141, -13.3331131695549],
            [-15.7138991677420, 28.2237124515809, -12.5098132838389],
            [-16.4749571738058, 28.1480747505277, -11.6731175767219],
            [-17.2183733830752, 28.0422953859991, -10.8239220029240],
            [-17.9433517268527, 27.9064876291883, -9.96313590233564],
            [-18.6491158801692, 27.7407969064430, -9.09168102627375],
            [-19.3349100930918, 27.5454006435389, -8.21049055044716],
            [-20, 27.3205080756888, -7.32050807568879],
            [-20.6436734059628, 27.0663600234871, -6.42268661752424],
            [-21.2652410493749, 26.7832286350338, -5.51798758565888],
            [-21.8640373400352, 26.4714170945114, -4.60737975447627],
            [-22.4394210718772, 26.1312592975275, -3.69183822565031],
            [-22.9907761095894, 25.7631194935712, -2.77234338398184],
            [-23.5175120483872, 25.3673918959653, -1.84987984757819],
            [-24.0190648462341, 24.9445002597334, -0.925435413499304],
        ]))
        Nr = ImportMatrixVal(value=np.ones(Nt) * 400)
        Ir = ImportMatrixVal(value=np.zeros((Nt, 28)))
        time = ImportGenVectLin(start=0,
                                stop=1 / (400 / 60) / 24,
                                num=Nt,
                                endpoint=False)
        angle = ImportGenVectLin(start=0,
                                 stop=2 * np.pi,
                                 num=Na,
                                 endpoint=False)

        SPMSM_001.name = (
            "Default SPMSM machine"  # Rename the machine to have the good plot title
        )

        # Definition of the simulation
        simu = Simu1(name="Default simulation", machine=SPMSM_001)

        simu.input = InCurrent(
            Is=Is,
            Ir=Ir,  # zero current for the rotor
            Nr=Nr,
            angle_rotor=None,  # Will be computed
            time=time,
            angle=angle,
            angle_rotor_initial=0.39,
        )

        # Definition of the magnetic simulation
        simu.mag = MagFEMM(
            is_stator_linear_BH=2,
            is_rotor_linear_BH=2,
            is_symmetry_a=True,
            is_antiper_a=False,
        )

        simu.mag.sym_a = 4
        simu.struct = None

        # Default Output
        output = Output(simu=simu)

        # Modify magnet width and the slot opening height
        output.simu.machine.stator.slot.H0 = 0.001
        output.simu.machine.rotor.slot.magnet[0].Wmag *= 0.98

        # FIG21 Display default machine
        output.simu.machine.plot()
        fig = plt.gcf()
        fig.savefig(
            join(save_path, "fig_21_Machine_topology_before_optimization.png"))
        fig.savefig(
            join(save_path, "fig_21_Machine_topology_before_optimization.svg"),
            format="svg",
        )

        # -------------------- #
        # OPTIMIZATION PROBLEM #
        # -------------------- #

        # Objective functions

        def harm1(output):
            """Return the average torque opposite (opposite to be maximized)"""
            N = output.simu.input.time.num
            x = output.mag.Tem[:, 0]
            sp = np.fft.rfft(x)
            sp = 2 / N * np.abs(sp)
            return -sp[0] / 2

        def harm2(output):
            """Return the first torque harmonic """
            N = output.simu.input.time.num
            x = output.mag.Tem[:, 0]
            sp = np.fft.rfft(x)
            sp = 2 / N * np.abs(sp)
            return sp[1]

        objs = {
            "Opposite average torque (Nm)":
            OptiObjFunc(description="Maximization of the average torque",
                        func=harm1),
            "First torque harmonic (Nm)":
            OptiObjFunc(
                description="Minimization of the first torque harmonic",
                func=harm2),
        }

        # Design variables
        my_vars = {
            "design var 1":
            OptiDesignVar(
                name="output.simu.machine.stator.slot.W0",
                type_var="interval",
                space=[
                    0.2 * output.simu.machine.stator.slot.W2,
                    output.simu.machine.stator.slot.W2,
                ],
                function=lambda space: random.uniform(*space),
            ),
            "design var 2":
            OptiDesignVar(
                name="output.simu.machine.rotor.slot.magnet[0].Wmag",
                type_var="interval",
                space=[
                    0.5 * output.simu.machine.rotor.slot.W0,
                    0.99 * output.simu.machine.rotor.slot.W0,
                ],  # May generate error in FEMM
                function=lambda space: random.uniform(*space),
            ),
        }

        # Problem creation
        my_prob = OptiProblem(output=output, design_var=my_vars, obj_func=objs)

        # Solve problem with NSGA-II
        solver = OptiGenAlgNsga2Deap(problem=my_prob,
                                     size_pop=12,
                                     nb_gen=40,
                                     p_mutate=0.5)
        res = solver.solve()

        # ------------- #
        # PLOTS RESULTS #
        # ------------- #

        res.plot_generation()
        fig = plt.gcf()
        fig.savefig(join(save_path, "fig_20_Individuals_in_fitness_space.png"))
        fig.savefig(join(save_path, "fig_20_Individuals_in_fitness_space.svg"),
                    format="svg")

        res.plot_pareto()
        fig = plt.gcf()
        fig.savefig(join(save_path, "Pareto_front_in_fitness_space.png"))
        fig.savefig(join(save_path, "Pareto_front_in_fitness_space.svg"),
                    format="svg")

        # Extraction of best topologies for every objective
        pareto = res.get_pareto()  # Extraction of the pareto front

        out1 = [pareto[0]["output"], pareto[0]["fitness"]]  # First objective
        out2 = [pareto[0]["output"], pareto[0]["fitness"]]  # Second objective

        for pm in pareto:
            if pm["fitness"][0] < out1[1][0]:
                out1 = [pm["output"], pm["fitness"]]
            if pm["fitness"][1] < out2[1][1]:
                out2 = [pm["output"], pm["fitness"]]

        # Rename machine to modify the title
        name1 = "Machine that maximizes the average torque ({:.3f} Nm)".format(
            abs(out1[1][0]))
        out1[0].simu.machine.name = name1
        name2 = "Machine that minimizes the first torque harmonic ({:.4f}Nm)".format(
            abs(out1[1][1]))
        out2[0].simu.machine.name = name2

        # plot the machine
        out1[0].simu.machine.plot()
        fig = plt.gcf()
        fig.savefig(
            join(save_path, "fig_21_Topology_to_maximize_average_torque.png"),
            format="png",
        )
        fig.savefig(
            join(save_path, "fig_21_Topology_to_maximize_average_torque.svg"),
            format="svg",
        )

        out2[0].simu.machine.plot()
        fig = plt.gcf()
        fig.savefig(
            join(save_path,
                 "fig_21_Topology_to_minimize_first_torque_harmonic.png"),
            format="png",
        )
        fig.savefig(
            join(save_path,
                 "fig_21_Topology_to_minimize_first_torque_harmonic.svg"),
            format="svg",
        )
Example #20
0
class OptiProblem(FrozenClass):
    """Multi-objectives optimization problem with some constraints"""

    VERSION = 1

    # cf Methods.Optimization.OptiProblem.eval_pb
    if isinstance(eval_pb, ImportError):
        eval_pb = property(fget=lambda x: raise_(
            ImportError("Can't use OptiProblem method eval_pb: " + str(eval_pb)
                        )))
    else:
        eval_pb = eval_pb
    # save method is available in all object
    save = save

    def __init__(
            self,
            output=-1,
            design_var=dict(),
            obj_func=dict(),
            eval_func=None,
            constraint=dict(),
            init_dict=None,
    ):
        """Constructor of the class. Can be use in two ways :
        - __init__ (arg1 = 1, arg3 = 5) every parameters have name and default values
            for Matrix, None will initialise the property with an empty Matrix
            for pyleecan type, None will call the default constructor
        - __init__ (init_dict = d) d must be a dictionnary wiht every properties as keys

        ndarray or list can be given for Vector and Matrix
        object or dict can be given for pyleecan Object"""

        if output == -1:
            output = Output()
        if init_dict is not None:  # Initialisation by dict
            check_init_dict(
                init_dict,
                [
                    "output", "design_var", "obj_func", "eval_func",
                    "constraint"
                ],
            )
            # Overwrite default value with init_dict content
            if "output" in list(init_dict.keys()):
                output = init_dict["output"]
            if "design_var" in list(init_dict.keys()):
                design_var = init_dict["design_var"]
            if "obj_func" in list(init_dict.keys()):
                obj_func = init_dict["obj_func"]
            if "eval_func" in list(init_dict.keys()):
                eval_func = init_dict["eval_func"]
            if "constraint" in list(init_dict.keys()):
                constraint = init_dict["constraint"]
        # Initialisation by argument
        self.parent = None
        # output can be None, a Output object or a dict
        if isinstance(output, dict):
            self.output = Output(init_dict=output)
        else:
            self.output = output
        # design_var can be None or a dict of OptiDesignVar object
        self.design_var = dict()
        if type(design_var) is dict:
            for key, obj in design_var.items():
                if isinstance(obj, dict):
                    self.design_var[key] = OptiDesignVar(init_dict=obj)
                else:
                    self.design_var[key] = obj
        elif design_var is None:
            self.design_var = dict()
        else:
            self.design_var = design_var  # Should raise an error
        # obj_func can be None or a dict of OptiObjFunc object
        self.obj_func = dict()
        if type(obj_func) is dict:
            for key, obj in obj_func.items():
                if isinstance(obj, dict):
                    self.obj_func[key] = OptiObjFunc(init_dict=obj)
                else:
                    self.obj_func[key] = obj
        elif obj_func is None:
            self.obj_func = dict()
        else:
            self.obj_func = obj_func  # Should raise an error
        self.eval_func = eval_func
        # constraint can be None or a dict of OptiConstraint object
        self.constraint = dict()
        if type(constraint) is dict:
            for key, obj in constraint.items():
                if isinstance(obj, dict):
                    self.constraint[key] = OptiConstraint(init_dict=obj)
                else:
                    self.constraint[key] = obj
        elif constraint is None:
            self.constraint = dict()
        else:
            self.constraint = constraint  # Should raise an error

        # The class is frozen, for now it's impossible to add new properties
        self._freeze()

    def __str__(self):
        """Convert this objet in a readeable string (for print)"""

        OptiProblem_str = ""
        if self.parent is None:
            OptiProblem_str += "parent = None " + linesep
        else:
            OptiProblem_str += ("parent = " + str(type(self.parent)) +
                                " object" + linesep)
        if self.output is not None:
            tmp = self.output.__str__().replace(linesep,
                                                linesep + "\t").rstrip("\t")
            OptiProblem_str += "output = " + tmp
        else:
            OptiProblem_str += "output = None" + linesep + linesep
        if len(self.design_var) == 0:
            OptiProblem_str += "design_var = dict()" + linesep
        for key, obj in self.design_var.items():
            tmp = (self.design_var[key].__str__().replace(
                linesep, linesep + "\t") + linesep)
            OptiProblem_str += "design_var[" + key + "] =" + tmp + linesep + linesep
        if len(self.obj_func) == 0:
            OptiProblem_str += "obj_func = dict()" + linesep
        for key, obj in self.obj_func.items():
            tmp = (
                self.obj_func[key].__str__().replace(linesep, linesep + "\t") +
                linesep)
            OptiProblem_str += "obj_func[" + key + "] =" + tmp + linesep + linesep
        if self._eval_func[1] is None:
            OptiProblem_str += "eval_func = " + str(self._eval_func[1])
        else:
            OptiProblem_str += ("eval_func = " + linesep +
                                str(self._eval_func[1]) + linesep + linesep)
        if len(self.constraint) == 0:
            OptiProblem_str += "constraint = dict()" + linesep
        for key, obj in self.constraint.items():
            tmp = (self.constraint[key].__str__().replace(
                linesep, linesep + "\t") + linesep)
            OptiProblem_str += "constraint[" + key + "] =" + tmp + linesep + linesep
        return OptiProblem_str

    def __eq__(self, other):
        """Compare two objects (skip parent)"""

        if type(other) != type(self):
            return False
        if other.output != self.output:
            return False
        if other.design_var != self.design_var:
            return False
        if other.obj_func != self.obj_func:
            return False
        if other.eval_func != self.eval_func:
            return False
        if other.constraint != self.constraint:
            return False
        return True

    def as_dict(self):
        """Convert this objet in a json seriable dict (can be use in __init__)
        """

        OptiProblem_dict = dict()
        if self.output is None:
            OptiProblem_dict["output"] = None
        else:
            OptiProblem_dict["output"] = self.output.as_dict()
        OptiProblem_dict["design_var"] = dict()
        for key, obj in self.design_var.items():
            OptiProblem_dict["design_var"][key] = obj.as_dict()
        OptiProblem_dict["obj_func"] = dict()
        for key, obj in self.obj_func.items():
            OptiProblem_dict["obj_func"][key] = obj.as_dict()
        if self.eval_func is None:
            OptiProblem_dict["eval_func"] = None
        else:
            OptiProblem_dict["eval_func"] = [
                dumps(self._eval_func[0]).decode("ISO-8859-2"),
                self._eval_func[1],
            ]
        OptiProblem_dict["constraint"] = dict()
        for key, obj in self.constraint.items():
            OptiProblem_dict["constraint"][key] = obj.as_dict()
        # The class name is added to the dict fordeserialisation purpose
        OptiProblem_dict["__class__"] = "OptiProblem"
        return OptiProblem_dict

    def _set_None(self):
        """Set all the properties to None (except pyleecan object)"""

        if self.output is not None:
            self.output._set_None()
        for key, obj in self.design_var.items():
            obj._set_None()
        for key, obj in self.obj_func.items():
            obj._set_None()
        self.eval_func = None
        for key, obj in self.constraint.items():
            obj._set_None()

    def _get_output(self):
        """getter of output"""
        return self._output

    def _set_output(self, value):
        """setter of output"""
        check_var("output", value, "Output")
        self._output = value

        if self._output is not None:
            self._output.parent = self

    # Default output to define the default simulation.
    # Type : Output
    output = property(
        fget=_get_output,
        fset=_set_output,
        doc=u"""Default output to define the default simulation. """,
    )

    def _get_design_var(self):
        """getter of design_var"""
        for key, obj in self._design_var.items():
            if obj is not None:
                obj.parent = self
        return self._design_var

    def _set_design_var(self, value):
        """setter of design_var"""
        check_var("design_var", value, "{OptiDesignVar}")
        self._design_var = value

    # Dict of design variables
    # Type : {OptiDesignVar}
    design_var = property(fget=_get_design_var,
                          fset=_set_design_var,
                          doc=u"""Dict of design variables""")

    def _get_obj_func(self):
        """getter of obj_func"""
        for key, obj in self._obj_func.items():
            if obj is not None:
                obj.parent = self
        return self._obj_func

    def _set_obj_func(self, value):
        """setter of obj_func"""
        check_var("obj_func", value, "{OptiObjFunc}")
        self._obj_func = value

    # Dict of objective functions
    # Type : {OptiObjFunc}
    obj_func = property(fget=_get_obj_func,
                        fset=_set_obj_func,
                        doc=u"""Dict of objective functions""")

    def _get_eval_func(self):
        """getter of eval_func"""
        return self._eval_func[0]

    def _set_eval_func(self, value):
        """setter of eval_func"""
        try:
            check_var("eval_func", value, "list")
        except CheckTypeError:
            check_var("eval_func", value, "function")
        if isinstance(value, list):  # Load function from saved dict
            self._eval_func = [loads(value[0].encode("ISO-8859-2")), value[1]]
        elif value is None:
            self._eval_func = [None, None]
        elif callable(value):
            self._eval_func = [value, getsource(value)]
        else:
            raise TypeError(
                "Expected function or list from a saved file, got: " +
                str(type(value)))

    # Function to evaluate before computing obj function and constraints
    # Type : function
    eval_func = property(
        fget=_get_eval_func,
        fset=_set_eval_func,
        doc=
        u"""Function to evaluate before computing obj function and constraints""",
    )

    def _get_constraint(self):
        """getter of constraint"""
        for key, obj in self._constraint.items():
            if obj is not None:
                obj.parent = self
        return self._constraint

    def _set_constraint(self, value):
        """setter of constraint"""
        check_var("constraint", value, "{OptiConstraint}")
        self._constraint = value

    # Dict containing the constraints
    # Type : {OptiConstraint}
    constraint = property(
        fget=_get_constraint,
        fset=_set_constraint,
        doc=u"""Dict containing the constraints """,
    )
Example #21
0
def solve(self):
    """Method to perform NSGA-II using DEAP tools
    
    Parameters
    ----------
    self : OptiGenAlgNsga2Deap
        Solver to perform NSGA-II

    Returns
    -------
    multi_output : OutputMultiOpti
        class containing the results
    """

    if self.problem == None:
        raise MissingProblem(
            "The problem has not been defined, please add a problem to OptiGenAlgNsga2Deap"
        )

    # Create the toolbox
    self.create_toolbox()

    # Add the design variable names
    self.multi_output.design_var_names = list(self.problem.design_var.keys())
    self.multi_output.design_var_names.sort()

    # Add the fitness names
    self.multi_output.fitness_names = list(self.problem.obj_func.keys())
    self.multi_output.fitness_names.sort()

    # Add the reference output to multi_output
    self.multi_output.output_ref = self.problem.output

    # Create the first population
    pop = self.toolbox.population(self.size_pop)

    # Start of the evaluation of the generation
    time_start_gen = datetime.now().strftime("%H:%M:%S")

    # Evaluate the population
    nb_error = 0
    for i in range(0, self.size_pop):
        nb_error += evaluate(self, pop[i])
        print(
            "\r{}  gen {:>5}: {:>5.2f}%, {:>4} errors.".format(
                time_start_gen, 0, (i + 1) * 100 / self.size_pop, nb_error),
            end="",
        )

    # Check the constraints violation
    nb_infeasible = 0
    if len(self.problem.constraint) > 0:
        for indiv in pop:
            nb_infeasible += check_cstr(self, indiv)
    print("\r{}  gen {:>5}: 100%, {:>4} errors,{:>4} infeasible.".format(
        time_start_gen, 0, nb_error, nb_infeasible - nb_error))

    # Add pop to OutputMultiOpt
    for indiv in pop:
        # Check that at every fitness values is different from inf
        is_valid = indiv.fitness.valid and indiv.is_simu_valid and indiv.cstr_viol == 0

        # Add the indiv to the multi_output
        self.multi_output.add_evaluation(indiv.output, is_valid, list(indiv),
                                         indiv.fitness.values, 0)

    if self.selector == None:
        pop = selNSGA2(pop, self.size_pop)
    else:
        parents = self.selector(pop, self.size_pop)

    ############################
    # LOOP FOR EACH GENERATION #
    ############################
    for ngen in range(1, self.nb_gen):
        time_start_gen = datetime.now().strftime("%H:%M:%S")
        # Extracting parents using
        parents = tournamentDCD(pop, self.size_pop)

        # Copy new indivuals
        children = []

        for indiv in parents:
            child = self.toolbox.individual()
            for i in range(len(indiv)):
                child[i] = deepcopy(indiv[i])
            child.output = Output(init_dict=indiv.output.as_dict())
            child.fitness = deepcopy(indiv.fitness)
            children.append(child)

        for indiv1, indiv2 in zip(children[::2], children[::-2]):
            # Crossover
            is_cross = False
            if random.random() < self.p_cross:
                is_cross = True
                if self.crossover == None:
                    cxOnePoint(indiv1, indiv2)

            # Mutation
            is_mutation = self.mutate(indiv1)
            if is_cross or is_mutation:
                update(indiv1)

            is_mutation = self.mutate(indiv2)
            if is_cross or is_mutation:
                update(indiv2)

        # Evaluate the children
        to_eval = []
        for indiv in children:
            if indiv.fitness.valid == False:
                to_eval.append(indiv)

        nb_error = 0
        for i in range(len(to_eval)):
            nb_error += evaluate(self, to_eval[i])
            print(
                "\r{}  gen {:>5}: {:>5.2f}%, {:>4} errors.".format(
                    time_start_gen, ngen, (i + 1) * 100 / len(to_eval),
                    nb_error),
                end="",
            )

        # Check the constraints violation
        nb_infeasible = 0
        if len(self.problem.constraint) > 0:
            for indiv in to_eval:
                nb_infeasible += check_cstr(self, indiv)
        print("\r{}  gen {:>5}: 100%, {:>4} errors,{:>4} infeasible.".format(
            time_start_gen, ngen, nb_error, nb_infeasible - nb_error))
        # Add children to OutputMultiOpti
        for indiv in children:
            # Check that at every fitness values is different from inf
            is_valid = (indiv.fitness.valid and indiv.is_simu_valid
                        and indiv.cstr_viol == 0)

            # Add the indiv to the multi_output
            self.multi_output.add_evaluation(
                indiv.output,
                is_valid,
                list(indiv),
                indiv.fitness.values,
                ngen,
            )

        # Sorting the population according to NSGA2
        if self.selector == None:
            pop = selNSGA2(pop + children, self.size_pop)
        else:
            pop = self.selector(pop, self.size_pop)

    return self.multi_output