femagtools 1.8.1__py3-none-any.whl → 1.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- femagtools/__init__.py +1 -1
- femagtools/dxfsl/area.py +45 -1
- femagtools/dxfsl/areabuilder.py +93 -45
- femagtools/dxfsl/converter.py +51 -26
- femagtools/dxfsl/fslrenderer.py +5 -4
- femagtools/dxfsl/geom.py +123 -137
- femagtools/dxfsl/machine.py +161 -9
- femagtools/dxfsl/shape.py +46 -1
- femagtools/dxfsl/svgparser.py +1 -1
- femagtools/dxfsl/symmetry.py +115 -30
- femagtools/fsl.py +10 -10
- femagtools/machine/__init__.py +5 -4
- femagtools/machine/afpm.py +41 -15
- femagtools/machine/sizing.py +189 -11
- femagtools/machine/utils.py +2 -2
- femagtools/mcv.py +2 -3
- femagtools/model.py +4 -3
- femagtools/parstudy.py +1 -1
- femagtools/plot/nc.py +2 -2
- {femagtools-1.8.1.dist-info → femagtools-1.8.2.dist-info}/METADATA +1 -1
- {femagtools-1.8.1.dist-info → femagtools-1.8.2.dist-info}/RECORD +26 -26
- tests/test_mcv.py +1 -1
- {femagtools-1.8.1.dist-info → femagtools-1.8.2.dist-info}/LICENSE +0 -0
- {femagtools-1.8.1.dist-info → femagtools-1.8.2.dist-info}/WHEEL +0 -0
- {femagtools-1.8.1.dist-info → femagtools-1.8.2.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.1.dist-info → femagtools-1.8.2.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py
CHANGED
@@ -235,6 +235,9 @@ def single_path(edges):
|
|
235
235
|
|
236
236
|
nodes_filecount = 0
|
237
237
|
|
238
|
+
TYPE_UNDEFINED = 0
|
239
|
+
TYPE_ROTOR = 1
|
240
|
+
TYPE_STATOR = 2
|
238
241
|
|
239
242
|
class Geometry(object):
|
240
243
|
"""collection of connected shapes"""
|
@@ -252,6 +255,7 @@ class Geometry(object):
|
|
252
255
|
delete=False,
|
253
256
|
adjust=False,
|
254
257
|
main=False,
|
258
|
+
type=TYPE_UNDEFINED,
|
255
259
|
debug=False):
|
256
260
|
self._name = ''
|
257
261
|
self.kind = ''
|
@@ -260,6 +264,7 @@ class Geometry(object):
|
|
260
264
|
self.end_corners = []
|
261
265
|
self.sym_part = 0
|
262
266
|
self.sym_counterpart = 0
|
267
|
+
self.sym_type = type
|
263
268
|
self.sym_slices = 0
|
264
269
|
self.sym_slice_angle = 0.0
|
265
270
|
self.alfa = 0.0
|
@@ -440,10 +445,12 @@ class Geometry(object):
|
|
440
445
|
is_inner=self.is_inner,
|
441
446
|
is_outer=self.is_outer,
|
442
447
|
rtol=self.rtol,
|
443
|
-
atol=self.atol
|
448
|
+
atol=self.atol,
|
449
|
+
type=self.sym_type)
|
444
450
|
geom.alfa = correct_alpha
|
445
451
|
geom.kind = self.kind
|
446
452
|
geom.sym_part = self.sym_part
|
453
|
+
geom.sym_type = self.sym_type
|
447
454
|
return geom
|
448
455
|
|
449
456
|
def log_geom(self):
|
@@ -861,6 +868,12 @@ class Geometry(object):
|
|
861
868
|
def start_max_corner(self, i):
|
862
869
|
return self.start_corners[-1][i]
|
863
870
|
|
871
|
+
def get_start_airgap_node(self):
|
872
|
+
if self.is_inner:
|
873
|
+
return self.start_corners[-1]
|
874
|
+
else:
|
875
|
+
return self.start_corners[0]
|
876
|
+
|
864
877
|
def dist_start_max_corner(self):
|
865
878
|
logger.debug("begin of dist_start_max_corner")
|
866
879
|
logger.debug("start corners: %s", self.start_corners)
|
@@ -868,16 +881,21 @@ class Geometry(object):
|
|
868
881
|
logger.debug("end of dist_start_max_corner: %s", d)
|
869
882
|
return d
|
870
883
|
|
871
|
-
def dist_end_max_corner(self):
|
884
|
+
def dist_end_max_corner(self, mirrored=True):
|
872
885
|
logger.debug("begin of dist_end_max_corner")
|
873
886
|
logger.debug("end corners: %s", self.end_corners)
|
874
887
|
|
875
|
-
if self.is_mirrored():
|
888
|
+
if self.is_mirrored() and mirrored:
|
876
889
|
return self.dist_start_max_corner()
|
877
890
|
d = distance(self.center, self.end_corners[-1])
|
878
891
|
logger.debug("end of dist_end_max_corner: %s", d)
|
879
892
|
return d
|
880
893
|
|
894
|
+
def max_corners_match(self):
|
895
|
+
d1 = self.dist_start_max_corner()
|
896
|
+
d2 = self.dist_end_max_corner(mirrored=False)
|
897
|
+
return np.isclose(d1, d2, rtol=1e-3, atol=1e-3)
|
898
|
+
|
881
899
|
def dist_start_min_corner(self):
|
882
900
|
logger.debug("begin of dist_start_min_corner")
|
883
901
|
logger.debug("start corners: %s", self.start_corners)
|
@@ -885,16 +903,24 @@ class Geometry(object):
|
|
885
903
|
logger.debug("end of dist_start_min_corner: %s", d)
|
886
904
|
return d
|
887
905
|
|
888
|
-
def dist_end_min_corner(self):
|
906
|
+
def dist_end_min_corner(self, mirrored=True):
|
889
907
|
logger.debug("begin of dist_end_min_corner")
|
890
908
|
logger.debug("end corners: %s", self.end_corners)
|
891
909
|
|
892
|
-
if self.is_mirrored():
|
910
|
+
if self.is_mirrored() and mirrored:
|
893
911
|
return self.dist_start_min_corner()
|
894
912
|
d = distance(self.center, self.end_corners[0])
|
895
913
|
logger.debug("end of dist_end_min_corner: %s", d)
|
896
914
|
return d
|
897
915
|
|
916
|
+
def min_corners_match(self):
|
917
|
+
d1 = self.dist_start_min_corner()
|
918
|
+
d2 = self.dist_end_min_corner(mirrored=False)
|
919
|
+
return np.isclose(d1, d2, rtol=1e-3, atol=1e-3)
|
920
|
+
|
921
|
+
def min_max_corners_match(self):
|
922
|
+
return self.min_corners_match() and self.max_corners_match()
|
923
|
+
|
898
924
|
def get_start_airgap_corner(self):
|
899
925
|
if self.is_inner:
|
900
926
|
p = (self.max_radius, 0.0)
|
@@ -1146,9 +1172,12 @@ class Geometry(object):
|
|
1146
1172
|
nx.set_edge_attributes(self.g, False, 1)
|
1147
1173
|
nx.set_edge_attributes(self.g, False, 2)
|
1148
1174
|
|
1149
|
-
def create_list_of_areas(self, main=False):
|
1175
|
+
def create_list_of_areas(self, main=False, delete=False):
|
1150
1176
|
""" return list of areas for each node and their neighbors
|
1151
1177
|
"""
|
1178
|
+
if delete: # clear list of areas
|
1179
|
+
self.area_list = []
|
1180
|
+
|
1152
1181
|
if len(self.area_list) > 0:
|
1153
1182
|
logger.debug("area list already available")
|
1154
1183
|
# list already available
|
@@ -1553,7 +1582,8 @@ class Geometry(object):
|
|
1553
1582
|
concatenate=concatenate,
|
1554
1583
|
connect=connect,
|
1555
1584
|
delete=delete_appendices,
|
1556
|
-
split=split
|
1585
|
+
split=split,
|
1586
|
+
type=self.sym_type)
|
1557
1587
|
geom.with_center_node = self.with_center_node
|
1558
1588
|
|
1559
1589
|
logger.debug('end copy_shape')
|
@@ -1614,7 +1644,8 @@ class Geometry(object):
|
|
1614
1644
|
split=split,
|
1615
1645
|
concatenate=concatenate,
|
1616
1646
|
connect=connect,
|
1617
|
-
adjust=adjust
|
1647
|
+
adjust=adjust,
|
1648
|
+
type=self.sym_type)
|
1618
1649
|
|
1619
1650
|
def is_new_angle(self, alpha_list, alpha):
|
1620
1651
|
for a in alpha_list:
|
@@ -1704,6 +1735,13 @@ class Geometry(object):
|
|
1704
1735
|
def symmetry_endangle(self):
|
1705
1736
|
return self.sym_area.sym_endangle
|
1706
1737
|
|
1738
|
+
def rotate_symmetry_parameters(self):
|
1739
|
+
self.sym_startangle += self.sym_slice_angle
|
1740
|
+
self.sym_endangle += self.sym_slice_angle
|
1741
|
+
if self.sym_area:
|
1742
|
+
self.sym_area.sym_startangle = self.sym_startangle
|
1743
|
+
self.sym_area.sym_endangle = self.sym_endangle
|
1744
|
+
|
1707
1745
|
def get_symmetry_copies(self):
|
1708
1746
|
if self.sym_counterpart == 0:
|
1709
1747
|
return int(self.sym_part)
|
@@ -2958,12 +2996,22 @@ class Geometry(object):
|
|
2958
2996
|
self.sym_counterpart = 1
|
2959
2997
|
self.sym_part = 2
|
2960
2998
|
|
2999
|
+
def force_to_be_rotor(self):
|
3000
|
+
self.sym_type = TYPE_ROTOR
|
3001
|
+
|
3002
|
+
def force_to_be_stator(self):
|
3003
|
+
self.sym_type = TYPE_STATOR
|
3004
|
+
|
2961
3005
|
def is_rotor(self):
|
3006
|
+
if self.sym_type != TYPE_UNDEFINED:
|
3007
|
+
return self.sym_type == TYPE_ROTOR
|
2962
3008
|
if self.sym_counterpart:
|
2963
3009
|
return self.sym_part < self.sym_counterpart
|
2964
3010
|
return False
|
2965
3011
|
|
2966
3012
|
def is_stator(self):
|
3013
|
+
if self.sym_type != TYPE_UNDEFINED:
|
3014
|
+
return self.sym_type == TYPE_STATOR
|
2967
3015
|
if self.sym_counterpart:
|
2968
3016
|
return self.sym_part > self.sym_counterpart
|
2969
3017
|
return False
|
@@ -3096,6 +3144,16 @@ class Geometry(object):
|
|
3096
3144
|
for e in elist:
|
3097
3145
|
e.init_attributes('lightblue', 'no_fsl')
|
3098
3146
|
|
3147
|
+
def set_subregion_parameters(self,
|
3148
|
+
startangle,
|
3149
|
+
endangle):
|
3150
|
+
for a in self.list_of_areas():
|
3151
|
+
a.set_subregion_parameters(self.is_inner,
|
3152
|
+
self.min_radius,
|
3153
|
+
self.max_radius,
|
3154
|
+
startangle,
|
3155
|
+
endangle)
|
3156
|
+
|
3099
3157
|
def search_subregions(self, startangle, endangle, EESM, single=False):
|
3100
3158
|
if self.is_stator():
|
3101
3159
|
self.search_stator_subregions(startangle,
|
@@ -3555,22 +3613,33 @@ class Geometry(object):
|
|
3555
3613
|
return
|
3556
3614
|
elements = []
|
3557
3615
|
for a in areas:
|
3558
|
-
elements += a.
|
3559
|
-
geom = Geometry(elements, center=self.center)
|
3616
|
+
elements += a.copy_of_elements()
|
3617
|
+
geom = Geometry(elements, center=self.center, type=self.sym_type)
|
3618
|
+
geom.create_list_of_areas()
|
3619
|
+
mag_areas = geom.list_of_areas()
|
3620
|
+
|
3560
3621
|
builder = AreaBuilder(geom=geom)
|
3561
|
-
if builder.create_area_groups(
|
3622
|
+
if builder.create_area_groups(mag_areas):
|
3562
3623
|
return # bad
|
3563
3624
|
group_list = builder.area_list
|
3564
|
-
|
3565
|
-
# self.areagroup_list = group_list
|
3625
|
+
|
3566
3626
|
for group in group_list:
|
3567
3627
|
if not group.is_magnet_rectangle():
|
3568
3628
|
logger.debug("Warning: group is not a rectangle")
|
3569
3629
|
group.set_type(AREA.TYPE_MAGNET_RECT)
|
3570
3630
|
phi = group.get_magnet_orientation()
|
3571
3631
|
for a in group.areas_of_group:
|
3572
|
-
logger.debug("Replace phi %s by %s", a.phi, phi)
|
3573
3632
|
a.phi = phi
|
3633
|
+
p = a.get_best_point_inside(geom)
|
3634
|
+
phi_set = False
|
3635
|
+
for area in areas:
|
3636
|
+
if area.the_point_is_inside_area(p):
|
3637
|
+
logger.debug("Replace phi %s by %s", area.phi, phi)
|
3638
|
+
area.phi = phi
|
3639
|
+
phi_set = True
|
3640
|
+
break
|
3641
|
+
if not phi_set:
|
3642
|
+
logger.warning("___MAGNET PHI NOT SET. AREA NOT FOUND IN GEOMETRY___")
|
3574
3643
|
|
3575
3644
|
def search_unknown_subregions(self):
|
3576
3645
|
logger.debug("begin of search_unknown_subregions")
|
@@ -3614,7 +3683,7 @@ class Geometry(object):
|
|
3614
3683
|
def windings_in_the_middle(self, midangle):
|
3615
3684
|
wdg_areas = [a for a in self.list_of_areas()
|
3616
3685
|
if a.is_winding()]
|
3617
|
-
logger.
|
3686
|
+
logger.debug("%s windings in geom", len(wdg_areas))
|
3618
3687
|
for a in wdg_areas:
|
3619
3688
|
if greater(a.max_angle, midangle) and \
|
3620
3689
|
less(a.min_angle, midangle):
|
@@ -3652,6 +3721,10 @@ class Geometry(object):
|
|
3652
3721
|
AREA.TYPE_YOKE,
|
3653
3722
|
AREA.TYPE_TOOTH,))
|
3654
3723
|
|
3724
|
+
def num_of_magnets(self):
|
3725
|
+
return self.num_areas_of_type((AREA.TYPE_MAGNET_AIRGAP,
|
3726
|
+
AREA.TYPE_MAGNET_RECT,))
|
3727
|
+
|
3655
3728
|
def area_close_to_endangle(self, type):
|
3656
3729
|
return len([area for area in self.list_of_areas()
|
3657
3730
|
if area.is_type(type) and area.close_to_endangle])
|
@@ -4147,61 +4220,18 @@ class Geometry(object):
|
|
4147
4220
|
return True
|
4148
4221
|
return False
|
4149
4222
|
|
4150
|
-
def get_inner_airgap_line(self):
|
4151
|
-
logger.debug("begin of get_inner_airgap_line")
|
4152
|
-
|
4153
|
-
if not self.is_inner:
|
4154
|
-
logger.debug("end of get_inner_airgap_line: not inner")
|
4155
|
-
return [], []
|
4156
|
-
for a in self.area_list:
|
4157
|
-
logger.debug("%s", a)
|
4158
|
-
area = [a for a in self.area_list if a.close_to_ag_endcorner]
|
4159
|
-
if len(area) != 1:
|
4160
|
-
logger.debug("end of get_inner_airgap_line: %s areas found", len(area))
|
4161
|
-
return [], []
|
4162
|
-
|
4163
|
-
end_corner = self.end_corners[-1]
|
4164
|
-
logger.debug("END CORNER %s", end_corner)
|
4165
|
-
nodes = [n for n in area[0].list_of_nodes()]
|
4166
|
-
if not nodes:
|
4167
|
-
logger.debug("end of get_inner_airgap_line: no nodes found")
|
4168
|
-
return [], []
|
4169
|
-
n1 = nodes[0]
|
4170
|
-
if points_are_close(end_corner, n1):
|
4171
|
-
n2 = nodes[-1]
|
4172
|
-
else:
|
4173
|
-
n2 = n1
|
4174
|
-
for n1 in nodes[1:]:
|
4175
|
-
if points_are_close(end_corner, n1):
|
4176
|
-
break
|
4177
|
-
n2 = n1
|
4178
|
-
|
4179
|
-
if not points_are_close(end_corner, n1):
|
4180
|
-
logger.debug("end of get_inner_airgap_line: not close to endcorner")
|
4181
|
-
return [], []
|
4182
|
-
|
4183
|
-
start_corner = self.start_corners[-1]
|
4184
|
-
|
4185
|
-
logger.debug("EDGE FOUND: %s - %s", n1, n2)
|
4186
|
-
nodes = [n1, n2]
|
4187
|
-
info = self.get_edge_info(n1, n2)
|
4188
|
-
elements = [info.get('element', None)]
|
4189
|
-
while not points_are_close(start_corner, n2):
|
4190
|
-
info = self.next_edge_lefthand_side(info)
|
4191
|
-
if not info:
|
4192
|
-
return []
|
4193
|
-
n2 = info['n2']
|
4194
|
-
nodes.append(n2)
|
4195
|
-
elements.append(info.get('element', None))
|
4196
|
-
|
4197
|
-
logger.debug("end of get_inner_airgap_line #%s", len(nodes))
|
4198
|
-
return nodes, elements
|
4199
|
-
|
4200
4223
|
def create_inner_corner_areas(self, startangle, endangle):
|
4201
|
-
self
|
4224
|
+
builder = AreaBuilder(geom=self)
|
4225
|
+
return builder.create_inner_corner_auxiliary_areas(startangle, endangle)
|
4226
|
+
|
4227
|
+
def close_outer_winding_areas(self):
|
4228
|
+
logger.debug("begin close_outer_winding_areas(%s areas)",
|
4229
|
+
len(self.area_list))
|
4202
4230
|
|
4203
4231
|
builder = AreaBuilder(geom=self)
|
4204
|
-
builder.
|
4232
|
+
rslt = builder.close_outer_winding_areas()
|
4233
|
+
logger.debug("end close_outer_winding_areas (%s)", rslt)
|
4234
|
+
return rslt
|
4205
4235
|
|
4206
4236
|
def repair_border_line(self, nodes):
|
4207
4237
|
logger.debug("begin repair_border_line")
|
@@ -4403,78 +4433,34 @@ class Geometry(object):
|
|
4403
4433
|
points += pts
|
4404
4434
|
return points
|
4405
4435
|
|
4406
|
-
def
|
4407
|
-
|
4408
|
-
|
4409
|
-
|
4410
|
-
return
|
4411
|
-
logger.debug("*** Corner Auxiliary Areas ***")
|
4412
|
-
airgap_line, airgap_el = self.get_inner_airgap_line()
|
4413
|
-
if not airgap_el:
|
4414
|
-
logger.debug("no airgapline found")
|
4415
|
-
return
|
4436
|
+
def mirror_all_areas(self, mirrorangle):
|
4437
|
+
axis_p = point(self.center, self.max_radius, mirrorangle)
|
4438
|
+
axis_m = line_m(self.center, axis_p)
|
4439
|
+
axis_n = line_n(self.center, axis_m)
|
4416
4440
|
|
4417
|
-
|
4418
|
-
|
4419
|
-
|
4441
|
+
def add_element(e):
|
4442
|
+
n = self.find_nodes(e.start(), e.end())
|
4443
|
+
if not self.has_edge(n[0], n[1]):
|
4444
|
+
self.add_edge(n[0], n[1], e)
|
4420
4445
|
|
4421
|
-
|
4422
|
-
|
4423
|
-
|
4424
|
-
|
4425
|
-
|
4426
|
-
|
4427
|
-
|
4428
|
-
|
4429
|
-
|
4430
|
-
|
4431
|
-
|
4432
|
-
|
4433
|
-
|
4434
|
-
|
4435
|
-
|
4436
|
-
|
4437
|
-
|
4438
|
-
|
4439
|
-
self.add_line(start_cp, n,
|
4440
|
-
color='red',
|
4441
|
-
linestyle='dotted')
|
4442
|
-
self.add_element(start_line,
|
4443
|
-
rtol=self.rtol,
|
4444
|
-
atol=self.atol)
|
4445
|
-
self.create_and_append_area(start_cp, n)
|
4446
|
-
self.start_corners = self.get_corner_nodes(self.center,
|
4447
|
-
0.0)
|
4448
|
-
break
|
4449
|
-
|
4450
|
-
if not end_exists:
|
4451
|
-
cp = self.end_corners[-1]
|
4452
|
-
logger.debug("End Corner: %s -- %s", cp, end_cp)
|
4453
|
-
end_line = Line(Element(start=cp, end=end_cp),
|
4454
|
-
color='red',
|
4455
|
-
linestyle='dotted')
|
4456
|
-
end_cp = end_line.node2(ndec)
|
4457
|
-
airgap_nodes.reverse()
|
4458
|
-
for n in airgap_nodes:
|
4459
|
-
ag_line = Line(Element(start=end_cp, end=n))
|
4460
|
-
points = self.get_intersection_points(airgap_el, ag_line, n)
|
4461
|
-
if not points: # no intersection
|
4462
|
-
d = distance(self.center, n)
|
4463
|
-
if np.isclose(d, self.max_radius):
|
4464
|
-
self.add_arc(n, end_cp, self.center, self.max_radius,
|
4465
|
-
color='red',
|
4466
|
-
linestyle='dotted')
|
4467
|
-
else:
|
4468
|
-
self.add_line(end_cp, n,
|
4469
|
-
color='red',
|
4470
|
-
linestyle='dotted')
|
4471
|
-
self.add_element(end_line,
|
4472
|
-
rtol=self.rtol,
|
4473
|
-
atol=self.atol)
|
4474
|
-
self.create_and_append_area(n, end_cp)
|
4475
|
-
self.end_corners = self.get_corner_nodes(self.center,
|
4476
|
-
self.alfa)
|
4477
|
-
break
|
4446
|
+
area_list = []
|
4447
|
+
for a in self.area_list:
|
4448
|
+
area = a.mirror_area(self.center, axis_m, axis_n)
|
4449
|
+
area_list.append(area)
|
4450
|
+
for e in area.elements():
|
4451
|
+
add_element(e)
|
4452
|
+
self.area_list += area_list
|
4453
|
+
|
4454
|
+
def check_airgap_connecting_nodes(self, geom, startangle, endangle):
|
4455
|
+
logger.info("check_airgap_connecting_nodes")
|
4456
|
+
|
4457
|
+
start_node_in = self.get_start_airgap_node()
|
4458
|
+
start_node_out = geom.get_start_airgap_node()
|
4459
|
+
angle_in = alpha_line(self.center, start_node_in)
|
4460
|
+
angle_out = alpha_line(self.center, start_node_out)
|
4461
|
+
if np.isclose(angle_in, angle_out):
|
4462
|
+
return
|
4463
|
+
logger.warning("WARNING: airgap connecting nodes do not aline")
|
4478
4464
|
|
4479
4465
|
def print_nodes(self):
|
4480
4466
|
print("=== List of Nodes ({}) ===".format(self.number_of_nodes()))
|
femagtools/dxfsl/machine.py
CHANGED
@@ -247,16 +247,21 @@ class Machine(object):
|
|
247
247
|
startangle=self.startangle,
|
248
248
|
endangle=self.endangle)
|
249
249
|
|
250
|
-
def
|
250
|
+
def clone(self):
|
251
251
|
clone = self.geom.copy_shape(self.radius,
|
252
252
|
0.0, 2*np.pi,
|
253
|
-
0.0,
|
254
|
-
|
253
|
+
0.0,
|
254
|
+
self.radius+9999,
|
255
|
+
concatenate=False,
|
256
|
+
connect=False)
|
255
257
|
clone.kind = self.geom.kind
|
256
258
|
clone.sym_part = self.geom.sym_part
|
257
259
|
clone.sym_counterpart = self.geom.sym_counterpart
|
258
260
|
clone.alfa = self.geom.alfa
|
259
|
-
|
261
|
+
return Machine(clone,
|
262
|
+
radius = self.radius,
|
263
|
+
startangle=self.startangle,
|
264
|
+
endangle=self.endangle)
|
260
265
|
|
261
266
|
def copy_mirror(self, startangle, midangle, endangle):
|
262
267
|
logger.debug("begin of copy_mirror")
|
@@ -532,7 +537,7 @@ class Machine(object):
|
|
532
537
|
logger.debug('begin repair_hull_geom (%s, %s)', startangle, endangle)
|
533
538
|
|
534
539
|
rtol = 1e-3
|
535
|
-
atol = 1e-
|
540
|
+
atol = 1e-3
|
536
541
|
c_corner = Corner(self.center, self.center)
|
537
542
|
start_c_added, start_corners = geom.get_corner_list(self.center, startangle,
|
538
543
|
rtol=rtol, atol=atol)
|
@@ -590,8 +595,34 @@ class Machine(object):
|
|
590
595
|
return w
|
591
596
|
|
592
597
|
def slot_area(self):
|
593
|
-
|
594
|
-
|
598
|
+
return self.geom.area_size_of_type(AREA.TYPE_WINDINGS)
|
599
|
+
|
600
|
+
def get_winding_symmetry(self, inside=False):
|
601
|
+
logger.debug("begin of get_winding_symmetry")
|
602
|
+
symmetry = Symmetry(geom=self.geom,
|
603
|
+
startangle=self.startangle,
|
604
|
+
endangle=self.endangle)
|
605
|
+
parts = symmetry.get_winding_symmetry(inside=inside)
|
606
|
+
logger.debug("end of get_winding_symmetry (parts=%s)", parts)
|
607
|
+
return parts
|
608
|
+
|
609
|
+
def get_magnet_symmetry(self):
|
610
|
+
logger.debug("begin of get_magnet_symmetry")
|
611
|
+
symmetry = Symmetry(geom=self.geom,
|
612
|
+
startangle=self.startangle,
|
613
|
+
endangle=self.endangle)
|
614
|
+
parts = symmetry.get_magnet_symmetry()
|
615
|
+
logger.debug("end of get_magnet_symmetry (parts=%s)", parts)
|
616
|
+
return parts
|
617
|
+
|
618
|
+
def get_symmetry(self):
|
619
|
+
logger.debug("begin of get_symmetry")
|
620
|
+
symmetry = Symmetry(geom=self.geom,
|
621
|
+
startangle=self.startangle,
|
622
|
+
endangle=self.endangle)
|
623
|
+
parts = symmetry.find_symmetry()
|
624
|
+
logger.debug("end of get_symmetry (parts=%s)", parts)
|
625
|
+
return parts
|
595
626
|
|
596
627
|
def find_symmetry(self, sym_tolerance, is_inner, is_outer, plt):
|
597
628
|
logger.debug("begin of find_symmetry")
|
@@ -761,6 +792,97 @@ class Machine(object):
|
|
761
792
|
self.geom.symmetry_endangle()))
|
762
793
|
return machine_slice
|
763
794
|
|
795
|
+
def get_forced_winding_slice(self):
|
796
|
+
logger.debug("get_forced_winding_slice()")
|
797
|
+
if not self.geom.is_outer:
|
798
|
+
return None
|
799
|
+
|
800
|
+
areas = len(self.geom.area_list)
|
801
|
+
winding_areas = self.geom.num_of_windings()
|
802
|
+
iron_areas = self.geom.num_of_irons()
|
803
|
+
air_areas = self.geom.num_areas_of_type((AREA.TYPE_AIR,))
|
804
|
+
|
805
|
+
if not (winding_areas + iron_areas + air_areas == areas):
|
806
|
+
logger.warning("Warning: strange areas in stator")
|
807
|
+
|
808
|
+
if winding_areas == 0:
|
809
|
+
return self.get_possible_windings()
|
810
|
+
|
811
|
+
if winding_areas < 2:
|
812
|
+
return None # nothing to do
|
813
|
+
parts = self.get_winding_symmetry()
|
814
|
+
if parts < 2:
|
815
|
+
return None # nothing to do
|
816
|
+
return self.get_symmetry_slice()
|
817
|
+
|
818
|
+
def get_possible_windings(self, EESM=False, single=False):
|
819
|
+
if not self.geom.is_outer:
|
820
|
+
return None
|
821
|
+
|
822
|
+
machine = self.clone()
|
823
|
+
machine.repair_hull()
|
824
|
+
machine.set_alfa_and_corners()
|
825
|
+
machine.geom.set_subregion_parameters(self.startangle,
|
826
|
+
self.endangle)
|
827
|
+
machine.geom.looking_for_corners()
|
828
|
+
dist_start = machine.geom.dist_start_min_corner()
|
829
|
+
dist_end = machine.geom.dist_end_min_corner()
|
830
|
+
|
831
|
+
if not np.isclose(dist_start, dist_end, rtol=1e-3, atol=1e-3):
|
832
|
+
angle = machine.geom.alfa
|
833
|
+
if dist_start > dist_end:
|
834
|
+
machine.mirror_all_areas(self.startangle)
|
835
|
+
machine.rotate_to(angle)
|
836
|
+
machine.geom.create_list_of_areas(delete=True)
|
837
|
+
machine.startangle -= angle
|
838
|
+
else:
|
839
|
+
machine.mirror_all_areas(self.endangle)
|
840
|
+
machine.endangle += angle
|
841
|
+
machine.set_alfa_and_corners()
|
842
|
+
machine.part = machine.part_of_circle()
|
843
|
+
machine.geom.set_subregion_parameters(self.startangle,
|
844
|
+
self.endangle)
|
845
|
+
machine.geom.looking_for_corners()
|
846
|
+
|
847
|
+
if machine.geom.close_outer_winding_areas():
|
848
|
+
machine.geom.create_list_of_areas(delete=True)
|
849
|
+
machine.geom.set_subregion_parameters(self.startangle,
|
850
|
+
self.endangle)
|
851
|
+
machine.geom.looking_for_corners()
|
852
|
+
parts = machine.get_winding_symmetry(inside=True)
|
853
|
+
|
854
|
+
if parts == 1:
|
855
|
+
return machine
|
856
|
+
if parts > 1:
|
857
|
+
return machine.get_symmetry_slice()
|
858
|
+
|
859
|
+
return machine
|
860
|
+
|
861
|
+
def get_forced_magnet_slice(self):
|
862
|
+
logger.debug("get_forced_magnet_slice()")
|
863
|
+
areas = len(self.geom.area_list)
|
864
|
+
magnet_areas = self.geom.num_of_magnets()
|
865
|
+
iron_areas = self.geom.num_of_irons()
|
866
|
+
air_areas = self.geom.num_areas_of_type((AREA.TYPE_AIR,))
|
867
|
+
|
868
|
+
if magnet_areas < 2:
|
869
|
+
return None # nothing to do
|
870
|
+
parts = self.get_magnet_symmetry()
|
871
|
+
|
872
|
+
if parts < 2:
|
873
|
+
return None # nothing to do
|
874
|
+
slice = self.get_symmetry_slice()
|
875
|
+
match = slice.geom.min_max_corners_match()
|
876
|
+
while parts > 1 and not match:
|
877
|
+
parts = parts - 1
|
878
|
+
self.geom.rotate_symmetry_parameters()
|
879
|
+
slice = self.get_symmetry_slice()
|
880
|
+
match = slice.geom.min_max_corners_match()
|
881
|
+
if match:
|
882
|
+
slice.geom.set_rotor()
|
883
|
+
return slice
|
884
|
+
return None
|
885
|
+
|
764
886
|
def get_forced_symmetry(self, part):
|
765
887
|
logger.debug("begin get_forced_symmetry")
|
766
888
|
if not self.is_full():
|
@@ -1041,6 +1163,13 @@ class Machine(object):
|
|
1041
1163
|
|
1042
1164
|
def sync_with_counterpart(self, cp_machine):
|
1043
1165
|
logger.debug("sync_with_counterpart")
|
1166
|
+
|
1167
|
+
def not_tiny_areas(geom):
|
1168
|
+
sz_list = [a.area_size() for a in geom.list_of_areas()]
|
1169
|
+
max_sz = max(sz_list)
|
1170
|
+
large_sz_list = [sz for sz in sz_list if sz > max_sz * 0.005]
|
1171
|
+
return len(large_sz_list)
|
1172
|
+
|
1044
1173
|
self.geom.sym_counterpart = cp_machine.get_symmetry_part()
|
1045
1174
|
self.geom.sym_part = self.get_symmetry_part()
|
1046
1175
|
logger.debug("part/sym-part: self=%s/%s, cp=%s/%s",
|
@@ -1049,6 +1178,14 @@ class Machine(object):
|
|
1049
1178
|
cp_machine.geom.sym_counterpart = self.get_symmetry_part()
|
1050
1179
|
cp_machine.geom.sym_part = cp_machine.get_symmetry_part()
|
1051
1180
|
|
1181
|
+
if not_tiny_areas(self.geom) == 1:
|
1182
|
+
if not_tiny_areas(cp_machine.geom) > 1:
|
1183
|
+
self.geom.force_to_be_stator()
|
1184
|
+
cp_machine.geom.force_to_be_rotor()
|
1185
|
+
elif not_tiny_areas(cp_machine.geom) == 1:
|
1186
|
+
self.geom.force_to_be_rotor()
|
1187
|
+
cp_machine.geom.force_to_be_stator()
|
1188
|
+
|
1052
1189
|
def search_subregions(self, EESM, single=False):
|
1053
1190
|
logger.debug("Search subregions")
|
1054
1191
|
self.geom.search_subregions(self.startangle,
|
@@ -1073,8 +1210,7 @@ class Machine(object):
|
|
1073
1210
|
|
1074
1211
|
def rebuild_subregions(self, EESM, single=False):
|
1075
1212
|
logger.debug("Rebuild subregions")
|
1076
|
-
self.geom.
|
1077
|
-
self.geom.area_list = []
|
1213
|
+
self.geom.create_list_of_areas(delete=True)
|
1078
1214
|
self.geom.search_subregions(self.startangle,
|
1079
1215
|
self.endangle,
|
1080
1216
|
EESM,
|
@@ -1142,6 +1278,11 @@ class Machine(object):
|
|
1142
1278
|
self.endangle)
|
1143
1279
|
return self.geom.windings_in_the_middle(midangle)
|
1144
1280
|
|
1281
|
+
def has_magnets_in_the_middle(self):
|
1282
|
+
midangle = middle_angle(self.startangle,
|
1283
|
+
self.endangle)
|
1284
|
+
return self.geom.magnets_in_the_middle(midangle)
|
1285
|
+
|
1145
1286
|
def create_mirror_lines_outside_windings(self):
|
1146
1287
|
logger.debug("create_mirror_lines_outside_windings")
|
1147
1288
|
|
@@ -1272,3 +1413,14 @@ class Machine(object):
|
|
1272
1413
|
self.clear_cut_lines()
|
1273
1414
|
self.repair_hull()
|
1274
1415
|
self.set_alfa_and_corners()
|
1416
|
+
|
1417
|
+
def mirror_all_areas(self, mirror_angle):
|
1418
|
+
self.geom.mirror_all_areas(mirror_angle)
|
1419
|
+
|
1420
|
+
def check_airgap_connecting_nodes(self, m_outer):
|
1421
|
+
logger.info("check_airgap_connecting_nodes")
|
1422
|
+
assert(self.geom.is_inner)
|
1423
|
+
assert(m_outer.geom.is_outer)
|
1424
|
+
self.geom.check_airgap_connecting_nodes(m_outer.geom,
|
1425
|
+
self.startangle,
|
1426
|
+
self.endangle)
|