femagtools 1.8.17__py3-none-any.whl → 1.8.19__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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.8.17'
5
+ __version__ = '1.8.19'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2023-2025 Gamma Technology'
femagtools/airgap.py CHANGED
@@ -24,7 +24,11 @@ def fft(pos: list, b: list, pmod=0) -> dict:
24
24
  Bamp = r['a']
25
25
  alfa0 = r['alfa0']
26
26
  T0 = r['T0']
27
- npoles = 2*round(360/T0)
27
+ try:
28
+ npoles = 2*round(360/T0)
29
+ except ZeroDivisionError:
30
+ npoles=0
31
+ pass
28
32
  logger.info("flux density: %s poles B amp %f ",
29
33
  npoles, r['a'])
30
34
  return dict(Bamp=Bamp, npoles=npoles,
femagtools/bch.py CHANGED
@@ -271,7 +271,7 @@ class Reader:
271
271
  return self.flux[0]['displ'][1]-self.flux[0]['displ'][0]
272
272
  return None
273
273
 
274
- def read(self, content):
274
+ def read(self, content, **kwargs):
275
275
  """read bch file
276
276
 
277
277
  Args:
@@ -297,7 +297,10 @@ class Reader:
297
297
  if k == title2[:len(k)]:
298
298
  title = title2[:len(k)]
299
299
  if title in self.dispatch:
300
- self.dispatch[title](self, s)
300
+ if title == 'Airgap Induction Br':
301
+ self.dispatch[title](self, s, kwargs.get('ignore_airgap_induction_with_c_step_section', True))
302
+ else:
303
+ self.dispatch[title](self, s)
301
304
 
302
305
  if len(self.weights) > 0:
303
306
  w = list(zip(*self.weights))
@@ -887,7 +890,7 @@ class Reader:
887
890
  self.flux_fft[self.wdg] = []
888
891
  self.flux_fft[self.wdg].append(flux_fft)
889
892
 
890
- def __read_airgapInduction(self, content):
893
+ def __read_airgapInduction(self, content, ignore_c_step_section=True):
891
894
  "read and append airgapInduction section"
892
895
  import scipy.integrate as si
893
896
  import math
@@ -918,7 +921,9 @@ class Reader:
918
921
  i1beta = True
919
922
  continue
920
923
  if line.startswith("C_STEP"):
921
- return # ignore this section
924
+ if ignore_c_step_section:
925
+ return # ignore this section
926
+ continue
922
927
  try:
923
928
  rec = self.__findNums(line)
924
929
  if len(rec) == 10:
@@ -966,6 +971,10 @@ class Reader:
966
971
  self.airgapInduction['iq'] = iq
967
972
  self.airgapInduction['id'] = id
968
973
  nrows = len(self.airgapInduction['id'])
974
+ if not ignore_c_step_section:
975
+ # min 1 required (section with C_STEP)
976
+ nrows = max(1, nrows)
977
+ ncols = max(1, ncols)
969
978
 
970
979
  try:
971
980
  self.airgapInduction['an'] = [np.reshape(an[j][:nrows*ncols],
@@ -999,6 +1008,14 @@ class Reader:
999
1008
  [1:])
1000
1009
  self.airgapInduction['Bm'] = zip(*zip(*self.airgapInduction['Bm'])
1001
1010
  [1:])
1011
+ elif not ignore_c_step_section:
1012
+ # section with C_STEP and a single data linex
1013
+ self.airgapInduction['an'] = [self.airgapInduction['an'][i][0:]
1014
+ for i in range(4)]
1015
+ self.airgapInduction['bn'] = [self.airgapInduction['bn'][i][0:]
1016
+ for i in range(4)]
1017
+ self.airgapInduction['Ba'] = self.airgapInduction['Ba'][0:]
1018
+ self.airgapInduction['Bm'] = self.airgapInduction['Bm'][0:]
1002
1019
  except ValueError:
1003
1020
  print(self.airgapInduction['i1'])
1004
1021
 
@@ -1858,12 +1875,12 @@ class Reader:
1858
1875
  return self.__str__()
1859
1876
 
1860
1877
 
1861
- def read(filename):
1878
+ def read(filename, **kwargs):
1862
1879
  """Read BCH/BATCH results from file *filename*."""
1863
1880
  import io
1864
1881
  bchresults = Reader()
1865
1882
  with io.open(filename, encoding='latin1', errors='ignore') as f:
1866
- bchresults.read(f.readlines())
1883
+ bchresults.read(f.readlines(), **kwargs)
1867
1884
  return bchresults
1868
1885
 
1869
1886
 
femagtools/dxfsl/area.py CHANGED
@@ -475,6 +475,19 @@ class Area(object):
475
475
 
476
476
  self.alpha = round(alpha_angle(self.min_angle, self.max_angle), 3)
477
477
 
478
+ def set_close_to_start_end_angles(self, startangle, endangle):
479
+ logger.debug("set_close_to_start_end_angles(%s, %s)",startangle, endangle)
480
+ logger.debug(">> %s: min/max = %s/%s", self.identifier(), self.min_angle, self.max_angle)
481
+ if np.isclose(startangle, endangle): # full
482
+ self.close_to_startangle = True
483
+ self.close_to_endangle = True
484
+ return
485
+
486
+ self.close_to_startangle = np.isclose(self.min_angle, startangle,
487
+ 1e-04, 1e-04)
488
+ self.close_to_endangle = np.isclose(self.max_angle, endangle,
489
+ 1e-04, 1e-04)
490
+
478
491
  def center_is_inside(self, center):
479
492
  if less(self.min_x, center[0], rtol=1e-03, atol=1e-04) and \
480
493
  greater(self.max_x, center[0], rtol=1e-03, atol=1e-04) and \
@@ -552,12 +565,17 @@ class Area(object):
552
565
  return (self.close_to_startangle and self.close_to_endangle)
553
566
 
554
567
  def is_in_touch_with_area(self, geom, a):
568
+ if self.is_one_circle_element():
569
+ return False
570
+ if a.is_one_circle_element():
571
+ return False
572
+
555
573
  n1 = self.area[0].n1
556
574
  n2 = a.area[0].n2
557
575
  try:
558
576
  return nx.has_path(geom.g, n1, n2)
559
- except nx.NetworkXError:
560
- logger.warning("has_path() failed")
577
+ except nx.NetworkXError as e:
578
+ logger.warning("has_path() failed: %s", e)
561
579
  return False
562
580
 
563
581
  def has_connection(self, geom, a, ndec):
@@ -1189,6 +1207,11 @@ class Area(object):
1189
1207
  continue
1190
1208
  return r
1191
1209
 
1210
+ def is_one_circle_element(self):
1211
+ if len(self.area) == 1:
1212
+ return is_Circle(self.area[0])
1213
+ return False
1214
+
1192
1215
  def is_circle(self):
1193
1216
  e = self.area[0]
1194
1217
  if len(self.area) == 1:
@@ -1436,11 +1459,7 @@ class Area(object):
1436
1459
  opposite_radius = max_radius
1437
1460
 
1438
1461
  airgap_toleranz = (self.max_dist - self.min_dist) / 50.0 # 2%
1439
-
1440
- self.close_to_startangle = np.isclose(self.min_angle, startangle,
1441
- 1e-04, 1e-04)
1442
- self.close_to_endangle = np.isclose(self.max_angle, endangle,
1443
- 1e-04, 1e-04)
1462
+ self.set_close_to_start_end_angles(startangle, endangle)
1444
1463
  self.surface = self.area_size()
1445
1464
 
1446
1465
  def mark_stator_subregions(self,
@@ -1471,10 +1490,7 @@ class Area(object):
1471
1490
  opposite_radius = r_out
1472
1491
  airgap_toleranz = (self.max_dist - self.min_dist) / 50.0 # 2%
1473
1492
 
1474
- self.close_to_startangle = np.isclose(self.min_angle, 0.0,
1475
- 1e-04, 1e-04)
1476
- self.close_to_endangle = np.isclose(self.max_angle, alpha,
1477
- 1e-04, 1e-04)
1493
+ self.set_close_to_start_end_angles(0.0, alpha)
1478
1494
  self.surface = self.area_size()
1479
1495
 
1480
1496
  logger.debug("\n***** mark_stator_subregions [{}] *****"
@@ -1580,7 +1596,10 @@ class Area(object):
1580
1596
  logger.debug("***** air #3")
1581
1597
 
1582
1598
  if self.close_to_startangle or self.close_to_endangle:
1583
- f = self.surface / stator_size
1599
+ if stator_size > 0.0:
1600
+ f = self.surface / stator_size
1601
+ else:
1602
+ f = 0.0
1584
1603
  if f < 0.02: # area_size less then 2 percent of stator size
1585
1604
  # Luftloch
1586
1605
  self.type = TYPE_AIR # air
@@ -1624,10 +1643,7 @@ class Area(object):
1624
1643
  opposite_radius = r_out
1625
1644
  airgap_toleranz = (self.max_dist - self.min_dist) / 50.0 # 2%
1626
1645
 
1627
- self.close_to_startangle = np.isclose(self.min_angle, startangle,
1628
- 1e-04, 1e-04)
1629
- self.close_to_endangle = np.isclose(self.max_angle, endangle,
1630
- 1e-04, 1e-04)
1646
+ self.set_close_to_start_end_angles(startangle, endangle)
1631
1647
 
1632
1648
  logger.debug("\n***** mark_EESM_rotor_subregions [{}] *****"
1633
1649
  .format(self.id))
@@ -1697,10 +1713,7 @@ class Area(object):
1697
1713
  opposite_radius = r_out
1698
1714
  airgap_toleranz = (self.max_dist - self.min_dist) / 50.0 # 2%
1699
1715
 
1700
- self.close_to_startangle = np.isclose(self.min_angle, startangle,
1701
- 1e-04, 1e-04)
1702
- self.close_to_endangle = np.isclose(self.max_angle, endangle,
1703
- 1e-04, 1e-04)
1716
+ self.set_close_to_start_end_angles(startangle, endangle)
1704
1717
 
1705
1718
  logger.debug("\n***** mark_PMSM_rotor_subregions [{}] *****"
1706
1719
  .format(self.id))
@@ -1805,8 +1818,7 @@ class Area(object):
1805
1818
  logger.debug(">>> air is a circle")
1806
1819
  return self.type
1807
1820
 
1808
- self.close_to_startangle = np.isclose(self.min_angle, 0.0)
1809
- self.close_to_endangle = np.isclose(self.max_angle, alpha)
1821
+ self.set_close_to_start_end_angles(0.0, alpha)
1810
1822
 
1811
1823
  if self.is_magnet_rectangle():
1812
1824
  self.type = TYPE_MAGNET_RECT # magnet embedded
@@ -1848,7 +1860,7 @@ class Area(object):
1848
1860
  return 0.0
1849
1861
  return np.pi * e.radius**2
1850
1862
 
1851
- nodes = [n for n in self.list_of_nodes()]
1863
+ nodes = [n for n in self.virtual_nodes(parts=4)]
1852
1864
  return area_size(nodes)
1853
1865
 
1854
1866
  def set_surface(self, mirrored):
@@ -16,7 +16,7 @@ from femagtools.dxfsl.area import Area, TYPE_AIR
16
16
  from femagtools.dxfsl.functions import points_are_close, nodes_are_equal, distance
17
17
  from femagtools.dxfsl.functions import normalise_angle, positive_angle, point
18
18
  from femagtools.dxfsl.functions import alpha_line, alpha_points, alpha_angle
19
- from femagtools.dxfsl.functions import less, is_same_angle
19
+ from femagtools.dxfsl.functions import less, less_equal, greater, is_same_angle
20
20
  from femagtools.dxfsl.functions import Timer
21
21
  from femagtools.dxfsl.journal import getJournal
22
22
  import io
@@ -135,7 +135,7 @@ class EdgeInfo(object):
135
135
  self.angle = positive_angle(alpha_angle(start_angle, self.n1_angle_ingoing()))
136
136
  logger.debug("set_direction_angle: angle is %s", self.angle)
137
137
 
138
- if is_same_angle(0.0, self.angle, atol=0.008): # 1/2 degree
138
+ if is_same_angle(0.0, self.angle, atol=0.015): # 1/2 degree
139
139
  # reverse direction
140
140
  logger.debug("set_direction_angle: reverse direction( nearly 180 degrees)")
141
141
 
@@ -218,7 +218,7 @@ class EdgeInfo(object):
218
218
  myself_angle = self.angle
219
219
  other_angle = nbr_edge.angle
220
220
 
221
- if is_same_angle(0.0, myself_angle):
221
+ if is_same_angle(0.0, myself_angle, atol=0.015):
222
222
  # 360 or 0 degrees => turn 180 degrees
223
223
  logger.debug("-- ATTENTION: myself %s turns nearly 180 degrees", self.classname())
224
224
  logger.debug(" the angle is %s", myself_angle)
@@ -261,7 +261,7 @@ class EdgeInfo(object):
261
261
  logger.debug("#4: end of myself_direction_lefthand: ==> %s", left)
262
262
  return left
263
263
 
264
- if is_same_angle(0.0, other_angle, atol=0.008): # 1/2 degree
264
+ if is_same_angle(0.0, other_angle, atol=0.015): # 1/2 degree
265
265
  # 360 or 0 degrees => turn 180 degrees
266
266
  logger.debug("-- ATTENTION: other %s turns nearly 180 degrees", nbr_edge.classname())
267
267
  logger.debug(" the angle is %s", other_angle)
@@ -288,7 +288,7 @@ class EdgeInfo(object):
288
288
 
289
289
  logger.debug("-- angles: myself = %s, other = %s",
290
290
  myself_angle, other_angle)
291
- if not is_same_angle(myself_angle, other_angle, atol=0.008): # 1/2 degree
291
+ if not is_same_angle(myself_angle, other_angle, atol=0.015): # 1/2 degree
292
292
  logger.debug("-- angles are different")
293
293
  left = myself_angle > other_angle
294
294
  log_lefthand(left, self, nbr_edge)
@@ -730,31 +730,12 @@ class AreaBuilder(object):
730
730
  logger.debug("end of create_inner_corner_auxiliary_areas")
731
731
  return created
732
732
 
733
- def get_airgap_line(self, start_node, end_node, area):
733
+ def get_airgap_line(self, n1, n2, end_node):
734
734
  logger.debug("get_airgap_line")
735
735
 
736
736
  self.set_edge_attributes()
737
737
 
738
- nodes = [n for n in area.list_of_nodes()]
739
- if not nodes:
740
- logger.debug("end of get_airgap_line: no nodes found")
741
- return [], []
742
-
743
- n1 = nodes[0]
744
- if points_are_close(start_node, n1):
745
- n2 = nodes[-1]
746
- else:
747
- n2 = n1
748
- for n1 in nodes[1:]:
749
- if points_are_close(start_node, n1):
750
- break
751
- n2 = n1
752
-
753
- if not points_are_close(start_node, n1):
754
- logger.debug("end of get_airgap_line: not close to start-node")
755
- return [], []
756
-
757
- logger.debug("START EDGE FOUND: %s - %s", n1, n2)
738
+ logger.debug("START EDGE IS: %s - %s", n1, n2)
758
739
  nodes = [n1, n2]
759
740
  info = self.get_edge_info(n1, n2)
760
741
  elements = [info.element]
@@ -768,28 +749,37 @@ class AreaBuilder(object):
768
749
  nodes.append(n2)
769
750
  elements.append(info.element)
770
751
 
771
- logger.debug("end of get_airgap_line #%s", len(nodes))
752
+ logger.debug("end of get_airgap_line: %s nodes", len(nodes))
772
753
  return nodes, elements
773
754
 
755
+ def get_upper_border_line(self):
756
+ start_node = self.geom.end_corners[-1]
757
+ end_node = self.geom.start_corners[-1]
758
+ next_node = self.get_right_neighbor(start_node)
759
+ logger.debug("UPPER NODES start=%s, next=%s, end=%s", start_node, next_node, end_node)
760
+ return self.get_airgap_line(start_node, next_node, end_node)
761
+
762
+ def get_lower_border_line(self):
763
+ start_node = self.geom.start_corners[0]
764
+ end_node = self.geom.end_corners[0]
765
+ next_node = self.get_left_neighbor(start_node)
766
+ logger.debug("LOWER NODES start=%s, next=%s, end=%s", start_node, next_node, end_node)
767
+ return self.get_airgap_line(start_node, next_node, end_node)
768
+
774
769
  def get_inner_airgap_line(self):
775
- logger.debug("begin of get_inner_airgap_line")
770
+ logger.debug("get_inner_airgap_line()")
776
771
  assert(self.geom.is_inner)
777
772
  assert(self.geom.area_list)
773
+ return self.get_upper_border_line()
778
774
 
779
- area = [a for a in self.geom.area_list if a.close_to_ag_endcorner]
780
- if len(area) != 1:
781
- logger.debug("end of get_inner_airgap_line: %s areas found", len(area))
782
- return [], []
783
-
784
- start_node = self.geom.end_corners[-1]
785
- logger.debug("START NODE %s", start_node)
786
- end_node = self.geom.start_corners[-1]
787
- logger.debug("END NODE %s", end_node)
788
-
789
- return self.get_airgap_line(start_node, end_node, area[0])
775
+ def get_inner_opposite_airgap_line(self):
776
+ logger.debug("get_inner_opposite_airgap_line()")
777
+ assert(self.geom.is_inner)
778
+ assert(self.geom.area_list)
779
+ return self.get_lower_border_line()
790
780
 
791
- def close_outer_winding_areas(self):
792
- logger.debug("close_outer_winding_areas")
781
+ def close_outer_winding_areas(self, color='red'):
782
+ logger.debug("begin close_outer_winding_areas")
793
783
 
794
784
  airgap_line, airgap_el = self.get_outer_airgap_line()
795
785
  logger.debug("Outer Airgap with %s Nodes", len(airgap_line))
@@ -797,6 +787,15 @@ class AreaBuilder(object):
797
787
  if len(airgap_line) < 5:
798
788
  return False
799
789
 
790
+ distlist = [distance(self.geom.center, n) for n in airgap_line]
791
+ min_dist = min(distlist)
792
+ max_dist = max(distlist)
793
+ geom_height = self.geom.max_radius - self.geom.min_radius
794
+ line_height = max_dist - min_dist
795
+ if line_height < geom_height * 0.2:
796
+ return 0
797
+
798
+ logger.debug("NODES: %s TO %s", airgap_line[0], airgap_line[-1])
800
799
  n1 = None
801
800
  dist_n1 = 0.0
802
801
 
@@ -805,22 +804,29 @@ class AreaBuilder(object):
805
804
  dist_prev = distance(self.geom.center, n_prev)
806
805
  alpha_prev = alpha_line(self.geom.center, n_prev)
807
806
  alpha_start = alpha_prev
808
-
809
807
  lines_created = 0
808
+ dist_ag = self.geom.min_radius
809
+ logger.debug("MIN RADIUS DIST: %s",dist_ag)
810
810
  for n in airgap_line[1:]:
811
811
  dist = distance(self.geom.center, n)
812
812
  alpha = alpha_line(self.geom.center, n)
813
+ logger.debug("Node %s, dist=%s, alpha=%s", n, dist, alpha)
813
814
  if not n1:
814
- if dist > dist_prev and alpha < alpha_prev:
815
- n1 = n_prev
816
- dist_n1 = dist_prev
815
+ logger.debug("Previous, dist=%s, alpha=%s", dist_prev, alpha_prev)
816
+ if greater(dist_prev, dist_ag, rtol=1e-3, atol=1e-3):
817
+ if greater(dist, dist_prev, rtol=1e-3, atol=1e-3) and \
818
+ less(alpha, alpha_prev, rtol=1e-4, atol=1e-5):
819
+ n1 = n_prev
820
+ dist_n1 = dist_prev
821
+ logger.debug("NODE1: %s (%s)", n1, dist_n1)
817
822
  else:
818
- if np.isclose(dist_n1, dist, rtol=1e-3, atol=1e-3):
823
+ if less_equal(dist, dist_n1, rtol=1e-3, atol=1e-2):
824
+ logger.debug("NODE2: %s (%s)", n, dist)
819
825
  line = Line(Element(start=n1, end=n))
820
826
  if e_prev.intersect_line(line):
821
827
  logger.debug("___LINE NOT POSSIBLE___")
822
828
  else:
823
- self.geom.add_line(n1, n, color='red')
829
+ self.geom.add_line(n1, n, color=color)
824
830
  lines_created += 1
825
831
  n1 = None
826
832
  dist_n1 = 0.0
@@ -830,24 +836,53 @@ class AreaBuilder(object):
830
836
  dist_prev = dist
831
837
  alpha_prev = alpha
832
838
 
839
+ logger.debug("end close_outer_winding_areas: lines=%s", lines_created)
833
840
  return lines_created > 0
834
841
 
842
+ def get_left_neighbor(self, start_node):
843
+ nbrs = self.geom.get_neighbors(start_node)
844
+ start_alpha = normalise_angle(alpha_line(start_node, self.geom.center))
845
+ next_angle = 0.0
846
+ next_node = None
847
+ for n in nbrs:
848
+ alpha = normalise_angle(alpha_line(start_node, n))
849
+ angle = alpha_angle(start_alpha, alpha)
850
+ if angle > next_angle:
851
+ next_angle = angle
852
+ next_node = n
853
+
854
+ logger.debug("Left neighbor is %s", next_node)
855
+ return next_node
856
+
857
+ def get_right_neighbor(self, start_node):
858
+ nbrs = self.geom.get_neighbors(start_node)
859
+ start_alpha = normalise_angle(alpha_line(start_node, self.geom.center))
860
+ next_angle = 99
861
+ next_node = None
862
+ for n in nbrs:
863
+ alpha = normalise_angle(alpha_line(start_node, n))
864
+ angle = alpha_angle(start_alpha, alpha)
865
+ if angle < next_angle:
866
+ next_angle = angle
867
+ next_node = n
868
+
869
+ logger.debug("Right neighbor is %s", next_node)
870
+ return next_node
871
+
835
872
  def get_outer_airgap_line(self):
836
- logger.debug("begin of get_outer_airgap_line")
873
+ logger.debug("get_outer_airgap_line()")
837
874
  assert(self.geom.is_outer)
838
875
  assert(self.geom.area_list)
876
+ return self.get_lower_border_line()
839
877
 
840
- area = [a for a in self.geom.area_list if a.close_to_ag_startcorner]
841
- if len(area) != 1:
842
- logger.debug("end of get_outer_airgap_line: %s areas found", len(area))
843
- return [], []
844
-
845
- start_node = self.geom.start_corners[0]
846
- logger.debug("START NODE %s", start_node)
847
- end_node = self.geom.end_corners[0]
848
- logger.debug("END NODE %s", end_node)
878
+ def get_outer_opposite_airgap_line(self):
879
+ logger.debug("get_outer_opposite_airgap_line()")
880
+ assert(self.geom.is_outer)
881
+ assert(self.geom.area_list)
882
+ return self.get_upper_border_line()
849
883
 
850
- return self.get_airgap_line(start_node, end_node, area[0])
884
+ # same procedure as inner airgap line
885
+ return self.get_inner_airgap_line()
851
886
 
852
887
  def create_one_area_group(self, areas):
853
888
  logger.debug("begin of create_one_area_group")
@@ -915,9 +950,13 @@ class AreaBuilder(object):
915
950
  max_x = 0
916
951
  area = None
917
952
  for a in area_list:
953
+ if a.is_one_circle_element():
954
+ continue
918
955
  if a.max_x > max_x:
919
956
  max_x = a.max_x
920
957
  area = a
958
+ if area is None:
959
+ return False
921
960
 
922
961
  x0, y0 = -9999.0, 0.0
923
962
  for x, y in area.list_of_nodes():
@@ -168,6 +168,10 @@ def symmetry_search(machine,
168
168
  def build_machine_rotor(machine, inner, mindist, plt, EESM=False, single=False):
169
169
  logger.debug("Begin of build_machine_rotor")
170
170
 
171
+ if machine.part == 1:
172
+ logger.error("Full machine rotor without symmetrylines")
173
+ sys.exit(1)
174
+
171
175
  if machine.has_windings():
172
176
  logger.debug("do nothing here with windings in rotor")
173
177
  logger.debug("End of build_machine_rotor")
@@ -258,6 +262,10 @@ def build_machine_stator(machine, inner, mindist, plt, EESM=False, single=False)
258
262
  logger.debug("Begin of build_machine_stator")
259
263
  timer = Timer(start_it=True)
260
264
 
265
+ if machine.part == 1:
266
+ logger.error("Full stator without symmetrylines")
267
+ sys.exit(1)
268
+
261
269
  if not machine.geom.is_stator():
262
270
  logger.debug("Rotor with windings")
263
271
 
@@ -278,6 +286,8 @@ def build_machine_stator(machine, inner, mindist, plt, EESM=False, single=False)
278
286
  machine_temp.create_mirror_lines_outside_windings()
279
287
  else:
280
288
  machine_temp = machine
289
+ if machine_temp.has_windings_in_the_middle():
290
+ machine_temp.create_mirror_lines_outside_windings()
281
291
 
282
292
  if machine_temp.geom.reduce_element_nodes(mindist):
283
293
  machine_temp.rebuild_subregions(EESM, single=single)
@@ -520,13 +530,13 @@ def convert(dxfile,
520
530
  p, basegeom,
521
531
  title="Before finding Machine")
522
532
 
523
- machine_base = basegeom.get_machine()
524
533
  if show_plots:
525
534
  p.render_elements(basegeom, Shape,
526
535
  title=input_file.name,
527
536
  with_hull=False,
528
537
  rows=3, cols=2, num=1, show=debug_mode)
529
538
 
539
+ machine_base = basegeom.get_machine()
530
540
  if not machine_base.is_a_machine():
531
541
  logger.warn("it's Not a Machine")
532
542
  return dict(error='machine not detected')
@@ -256,6 +256,9 @@ class FslRenderer(object):
256
256
  'if mcvkey_yoke == nil then',
257
257
  ' mcvkey_yoke = "dummy"',
258
258
  ' ur = 1000.0',
259
+ ' else if mcvkey_teeth == nil then',
260
+ ' mcvkey_teeth = mcvkey_yoke',
261
+ 'end',
259
262
  'end',
260
263
  'x0_iron_tooth, y0_iron_tooth = 0.0, 0.0',
261
264
  'x0_iron_yoke, y0_iron_yoke = 0.0, 0.0',