Skip to content

Commit f4e09e5

Browse files
author
EOMYS ENGINEERING
authored
Merge pull request #142 from EOMYS-Public/Solution
Solution
2 parents f17c054 + a35e52e commit f4e09e5

23 files changed

+43988
-445
lines changed

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
include LICENSE README.md
12
prune Tests
23
prune Tutorials
34
graft pyleecan
5+
prune pyleecan/Results
46
global-exclude *.py[cod]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
55

66
## Presentation
7-
PYLEECAN objective is to provide a **user-friendly, unified, flexible simulation framework for the multiphysic design and optimization of electrical machines and drives** based on fully open-source software.
7+
PYLEECAN objective is to provide a **user-friendly, unified, flexible simulation framework for the multiphysic design and optimization of electrical machines and drives** based on fully open-source software.
88

99
It is meant to be used by researchers, R&D engineers and teachers in electrical engineering, both on standard topologies of electrical machines and on novel topologies (e.g. during a PhD work).
1010
An objective of PYLEECAN is that **every PhD student should start with PYLEECAN instead of implementing his own scripts (e.g. coupling Scilab or Matlab with Femm)**.

Tests/Methods/Mesh/test_interface.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,24 @@
88
import numpy as np
99

1010

11-
@pytest.mark.skip
1211
@pytest.mark.MeshSol
1312
class unittest_interface(TestCase):
14-
"""unittest for elements and nodes getter methods"""
13+
"""unittest for interface method"""
1514

1615
@classmethod
1716
def setUp(self):
1817
self.mesh = MeshMat()
1918
self.mesh.cell["triangle"] = CellMat(nb_pt_per_cell=3)
20-
self.mesh.cell["segment"] = CellMat(nb_pt_per_cell=2)
19+
self.mesh.cell["line"] = CellMat(nb_pt_per_cell=2)
2120
self.mesh.point = PointMat()
2221

2322
self.other_mesh = MeshMat()
2423
self.other_mesh.cell["triangle"] = CellMat(nb_pt_per_cell=3)
25-
self.other_mesh.cell["segment"] = CellMat(nb_pt_per_cell=2)
24+
self.other_mesh.cell["line"] = CellMat(nb_pt_per_cell=2)
2625
self.other_mesh.point = self.mesh.point
2726

2827
def test_MeshMat_flat(self):
29-
"""unittest with ElementDict and PointMat objects"""
28+
"""unittest with a flat interface"""
3029

3130
self.mesh.add_cell([0, 1, 2], "triangle")
3231
self.mesh.add_cell([2, 3, 4], "triangle")
@@ -43,8 +42,8 @@ def test_MeshMat_flat(self):
4342
self.other_mesh.add_cell([4, 6, 2], "triangle")
4443

4544
new_seg_mesh = self.mesh.interface(self.other_mesh)
46-
solution = np.array([[0, 2], [2, 4]])
47-
resultat = new_seg_mesh.cell["segment"].connectivity
45+
solution = np.array([[0, 2], [4, 2]])
46+
resultat = new_seg_mesh.cell["line"].connectivity
4847
testA = np.sum(abs(resultat - solution))
4948
msg = (
5049
"Wrong projection: returned "
@@ -56,7 +55,7 @@ def test_MeshMat_flat(self):
5655
self.assertAlmostEqual(testA, 0, msg=msg, delta=DELTA)
5756

5857
def test_CellMat_PointMat_corner_ext(self):
59-
"""unittest with CellMat and PointMat objects, extract interface from the external mesh point of view"""
58+
"""unittest with an external corner interface"""
6059
self.mesh.add_cell([0, 1, 2], "triangle")
6160
self.mesh.add_cell([1, 2, 3], "triangle")
6261
self.mesh.add_cell([1, 5, 4], "triangle")
@@ -67,22 +66,24 @@ def test_CellMat_PointMat_corner_ext(self):
6766
self.mesh.point.add_point([4, 0])
6867
self.mesh.point.add_point([3.5, 1])
6968
self.mesh.point.add_point([3, -1])
69+
self.mesh.point.add_point([10, 10])
7070

7171
self.other_mesh.add_cell([0, 1, 5], "triangle")
72+
self.other_mesh.add_cell([0, 5, 6], "triangle")
7273

7374
# Method test 1
7475
new_seg_mesh = self.mesh.interface(self.other_mesh)
7576

7677
# Check result
7778
solution = np.array([[0, 1], [1, 5]])
78-
result = new_seg_mesh.cell["segment"].connectivity
79+
result = new_seg_mesh.cell["line"].connectivity
7980
testA = np.sum(abs(result - solution))
8081
msg = "Wrong result: returned " + str(result) + ", expected: " + str(solution)
8182
DELTA = 1e-10
8283
self.assertAlmostEqual(testA, 0, msg=msg, delta=DELTA)
8384

8485
def test_CellMat_PointMat_corner_int(self):
85-
"""unittest with CellMat and PointMat objects, extract interface from the internal mesh point of view"""
86+
"""unittest with an internal corner interface"""
8687
self.mesh.add_cell([0, 1, 2], "triangle")
8788
self.mesh.add_cell([1, 2, 3], "triangle")
8889
self.mesh.add_cell([1, 5, 4], "triangle")
@@ -93,39 +94,38 @@ def test_CellMat_PointMat_corner_int(self):
9394
self.mesh.point.add_point([4, 0])
9495
self.mesh.point.add_point([3.5, 1])
9596
self.mesh.point.add_point([3, -1])
97+
self.mesh.point.add_point([10, 10])
9698

9799
self.other_mesh.add_cell([0, 1, 5], "triangle")
100+
self.other_mesh.add_cell([0, 5, 6], "triangle")
98101

99102
# Method test 1
100103
new_seg_mesh = self.other_mesh.interface(self.mesh)
101104

102105
# Check result
103106
solution = np.array([[0, 1], [1, 5]])
104-
result = new_seg_mesh.cell["segment"].connectivity
107+
result = new_seg_mesh.cell["line"].connectivity
105108
testA = np.sum(abs(result - solution))
106109
msg = "Wrong result: returned " + str(result) + ", expected: " + str(solution)
107110
DELTA = 1e-10
108111
self.assertAlmostEqual(testA, 0, msg=msg, delta=DELTA)
109112

110113
def test_CellMat_PointMat_self(self):
111-
"""unittest with CellMat and PointMat objects, extract interface on itself"""
114+
"""unittest with interface of a mesh on itself"""
112115
self.mesh.add_cell([0, 1, 2], "triangle")
113116
self.mesh.add_cell([0, 2, 3], "triangle")
114-
self.mesh.add_cell([0, 3, 4], "triangle")
115-
self.mesh.add_cell([0, 4, 1], "triangle")
116117

117118
self.mesh.point.add_point([0, 0])
118119
self.mesh.point.add_point([0, 1])
119120
self.mesh.point.add_point([1, 0])
120121
self.mesh.point.add_point([-1, 0])
121-
self.mesh.point.add_point([0, -1])
122122

123123
# Method test 1
124124
new_seg_mesh = self.mesh.interface(self.mesh)
125125

126126
# Check result
127-
solution = np.array([])
128-
result = new_seg_mesh.cell["segment"].connectivity
127+
solution = np.array([[0, 1], [0, 2], [0, 3], [1, 2], [2, 3]])
128+
result = new_seg_mesh.cell["line"].connectivity
129129
testA = np.sum(abs(result - solution))
130130
msg = "Wrong result: returned " + str(result) + ", expected: " + str(solution)
131131
DELTA = 1e-10

Tests/Methods/Output/__init__.py

Whitespace-only changes.

Tests/Methods/Output/test_plot_mesh_field.py

Lines changed: 0 additions & 43 deletions
This file was deleted.

Tests/Plot/test_ICEM_2020.py

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ def test_Optimization_problem():
525525
# This simulation will the base of every simulation during the optimization process
526526

527527
# Load the machine
528-
SPMSM_001 = load("pyleecan/Tests/Validation/Machine/SPMSM_001.json")
528+
SPMSM_001 = load(join(DATA_DIR, "Machine", "SPMSM_001.json"))
529529

530530
# Definition of the enforced output of the electrical module
531531
Na = 1024 # Angular steps
@@ -612,41 +612,32 @@ def test_Optimization_problem():
612612
fig.savefig(
613613
join(save_path, "fig_21_Machine_topology_before_optimization.svg"), format="svg"
614614
)
615-
615+
plt.close("all")
616616
# -------------------- #
617617
# OPTIMIZATION PROBLEM #
618618
# -------------------- #
619619

620620
# Objective functions
621-
622-
def harm1(output):
621+
def tem_av(output):
623622
"""Return the average torque opposite (opposite to be maximized)"""
624-
N = output.simu.input.time.num
625-
x = output.mag.Tem.values[:, 0]
626-
sp = np.fft.rfft(x)
627-
sp = 2 / N * np.abs(sp)
628-
return -sp[0] / 2
629-
630-
def harm2(output):
631-
"""Return the first torque harmonic """
632-
N = output.simu.input.time.num
633-
x = output.mag.Tem.values[:, 0]
634-
sp = np.fft.rfft(x)
635-
sp = 2 / N * np.abs(sp)
636-
return sp[1]
637-
638-
objs = [
623+
return -abs(output.mag.Tem_av)
624+
625+
def Tem_rip_pp(output):
626+
"""Return the torque ripple """
627+
return abs(output.mag.Tem_rip_pp)
628+
629+
my_objs = [
639630
DataKeeper(
640631
name="Maximization of the average torque",
641632
symbol="Tem_av",
642633
unit="N.m",
643-
keeper=harm1,
634+
keeper=tem_av,
644635
),
645636
DataKeeper(
646-
name="Minimization of the first torque harmonic",
647-
symbol="Tem_h1",
637+
name="Minimization of the torque ripple",
638+
symbol="Tem_rip_pp",
648639
unit="N.m",
649-
keeper=harm2,
640+
keeper=Tem_rip_pp,
650641
),
651642
]
652643

@@ -679,7 +670,7 @@ def harm2(output):
679670
]
680671

681672
# Problem creation
682-
my_prob = OptiProblem(output=output, design_var=my_vars, obj_func=objs)
673+
my_prob = OptiProblem(output=output, design_var=my_vars, obj_func=my_objs)
683674

684675
# Solve problem with NSGA-II
685676
solver = OptiGenAlgNsga2Deap(problem=my_prob, size_pop=12, nb_gen=40, p_mutate=0.5)
@@ -689,14 +680,14 @@ def harm2(output):
689680
# PLOTS RESULTS #
690681
# ------------- #
691682

692-
res.plot_generation(x_symbol="Tem_av", y_symbol="Tem_h1")
683+
res.plot_generation(x_symbol="Tem_av", y_symbol="Tem_rip_pp")
693684
fig = plt.gcf()
694685
fig.savefig(join(save_path, "fig_20_Individuals_in_fitness_space.png"))
695686
fig.savefig(
696687
join(save_path, "fig_20_Individuals_in_fitness_space.svg"), format="svg"
697688
)
698689

699-
res.plot_pareto(x_symbol="Tem_av", y_symbol="Tem_h1")
690+
res.plot_pareto(x_symbol="Tem_av", y_symbol="Tem_rip_pp")
700691
fig = plt.gcf()
701692
fig.savefig(join(save_path, "Pareto_front_in_fitness_space.png"))
702693
fig.savefig(join(save_path, "Pareto_front_in_fitness_space.svg"), format="svg")
@@ -709,12 +700,15 @@ def harm2(output):
709700
idx_1 = pareto_index[0] # First objective
710701
idx_2 = pareto_index[0] # Second objective
711702

703+
Tem_av = res["Tem_av"].result
704+
Tem_rip_pp = res["Tem_rip_pp"].result
705+
712706
for i in pareto_index:
713707
# First objective
714-
if res["Tem_av"][i] < res["Tem_av"][idx_1]:
708+
if Tem_av[i] < Tem_av[idx_1]:
715709
idx_1 = i
716710
# Second objective
717-
if res["Tem_h1"][i] < res["Tem_h1"][idx_2]:
711+
if Tem_rip_pp[i] < Tem_rip_pp[idx_2]:
718712
idx_2 = i
719713

720714
# Get corresponding simulations
@@ -723,11 +717,11 @@ def harm2(output):
723717

724718
# Rename machine to modify the title
725719
name1 = "Machine that maximizes the average torque ({:.3f} Nm)".format(
726-
abs(res["Tem_av"][idx_1])
720+
abs(Tem_av[idx_1])
727721
)
728722
simu1.machine.name = name1
729-
name2 = "Machine that minimizes the first torque harmonic ({:.4f}Nm)".format(
730-
abs(res["Tem_h1"][idx_2])
723+
name2 = "Machine that minimizes the torque ripple ({:.4f}Nm)".format(
724+
abs(Tem_rip_pp[idx_2])
731725
)
732726
simu2.machine.name = name2
733727

@@ -744,10 +738,8 @@ def harm2(output):
744738
simu2.machine.plot()
745739
fig = plt.gcf()
746740
fig.savefig(
747-
join(save_path, "fig_21_Topology_to_minimize_first_torque_harmonic.png"),
748-
format="png",
741+
join(save_path, "fig_21_Topology_to_minimize_torque_ripple.png"), format="png",
749742
)
750743
fig.savefig(
751-
join(save_path, "fig_21_Topology_to_minimize_first_torque_harmonic.svg"),
752-
format="svg",
744+
join(save_path, "fig_21_Topology_to_minimize_torque_ripple.svg"), format="svg",
753745
)

Tests/Plot/test_plots.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from unittest import TestCase
33
from os.path import join
44
import matplotlib.pyplot as plt
5-
from Tests import save_validation_path as save_path
5+
from Tests import save_plot_path as save_path
66
import pytest
77

88
from pyleecan.Classes.Simu1 import Simu1

Tests/Tutorials/test_tutorial.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from Tests import TEST_DIR
55
from os.path import join, abspath, isfile
66

7-
TUTO_DIR = join(join(TEST_DIR, ".."), "Tutorials")
7+
TUTO_DIR = abspath(join(TEST_DIR, "..", "Tutorials"))
88

99

1010
@pytest.mark.tutorial
@@ -17,7 +17,7 @@ def test_short_tutorial(tuto_name):
1717

1818
# Execute it
1919
ep = ExecutePreprocessor(timeout=-1, kernel_name="python3")
20-
ep.preprocess(nb, {"metadata": {"path": TUTO_DIR}})
20+
ep.preprocess(nb, {"metadata": {"path": abspath(join(TEST_DIR, ".."))}})
2121

2222

2323
@pytest.mark.tutorial
@@ -31,4 +31,4 @@ def test_long_tutorial(tuto_name):
3131

3232
# Execute it
3333
ep = ExecutePreprocessor(timeout=-1, kernel_name="python3")
34-
ep.preprocess(nb, {"metadata": {"path": TUTO_DIR}})
34+
ep.preprocess(nb, {"metadata": {"path": abspath(join(TEST_DIR, ".."))}})

Tests/Validation/Simulation/test_EM_SPMSM_FL_002.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ def test_Magnetic_FEMM_sym():
8686
)
8787

8888
out.mag.meshsolution.plot_mesh(
89-
group_names=["stator", "/", "airgap", "stator_windings"]
89+
group_names="stator",
90+
save_path=join(save_path, "EM_SPMSM_FL_002_mesh_stator.png"),
91+
)
92+
93+
out.mag.meshsolution.plot_mesh(
94+
group_names=["stator", "/", "airgap", "stator_windings"],
95+
save_path=join(save_path, "EM_SPMSM_FL_002_mesh_stator_interface.png"),
9096
)
9197

9298
out.mag.meshsolution.plot_contour(

0 commit comments

Comments
 (0)