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/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.elements()
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(areas):
3622
+ if builder.create_area_groups(mag_areas):
3562
3623
  return # bad
3563
3624
  group_list = builder.area_list
3564
- # for debugging
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.info("%s windings in geom", len(wdg_areas))
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.set_edge_attributes()
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.create_inner_corner_auxiliary_areas(startangle, endangle)
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 create_inner_corner_auxiliary_areas(self):
4407
- start_cp, start_exists = self.get_start_airgap_corner()
4408
- end_cp, end_exists = self.get_end_airgap_corner()
4409
- if start_exists and end_exists:
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
- logger.debug("airgapline found !!")
4418
- airgap_nodes = [n for n in airgap_line[1:]]
4419
- del airgap_nodes[-1]
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
- if not start_exists:
4422
- cp = self.start_corners[-1]
4423
- logger.debug("Start Corner: %s -- %s", cp, start_cp)
4424
- start_line = Line(Element(start=cp, end=start_cp),
4425
- color='red',
4426
- linestyle='dotted')
4427
-
4428
- start_cp = start_line.node2(ndec)
4429
- for n in airgap_nodes:
4430
- ag_line = Line(Element(start=start_cp, end=n))
4431
- points = self.get_intersection_points(airgap_el, ag_line, n)
4432
- if not points: # no intersection
4433
- d = distance(self.center, n)
4434
- if np.isclose(d, self.max_radius):
4435
- self.add_arc(start_cp, n, self.center, self.max_radius,
4436
- color='red',
4437
- linestyle='dotted')
4438
- else:
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()))
@@ -247,16 +247,21 @@ class Machine(object):
247
247
  startangle=self.startangle,
248
248
  endangle=self.endangle)
249
249
 
250
- def full_copy(self, concatenate_matching_el=False):
250
+ def clone(self):
251
251
  clone = self.geom.copy_shape(self.radius,
252
252
  0.0, 2*np.pi,
253
- 0.0, self.radius+9999,
254
- concatenate_matching_el=concatenate_matching_el)
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
- self.geom = clone
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-4
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
- from .area import TYPE_WINDINGS
594
- return self.geom.area_size_of_type(TYPE_WINDINGS)
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.set_edge_attributes()
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)