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 +1 -1
- femagtools/airgap.py +5 -1
- femagtools/bch.py +23 -6
- femagtools/dxfsl/area.py +35 -23
- femagtools/dxfsl/areabuilder.py +97 -58
- femagtools/dxfsl/converter.py +11 -1
- femagtools/dxfsl/fslrenderer.py +3 -0
- femagtools/dxfsl/geom.py +265 -63
- femagtools/dxfsl/machine.py +128 -9
- femagtools/dxfsl/symmetry.py +20 -5
- femagtools/femag.py +27 -16
- femagtools/isa7.py +25 -22
- femagtools/machine/__init__.py +3 -1
- femagtools/machine/effloss.py +18 -4
- femagtools/machine/pm.py +88 -74
- femagtools/machine/sm.py +32 -21
- femagtools/mcv.py +4 -1
- femagtools/plot/bch.py +3 -1
- femagtools/plot/char.py +5 -16
- femagtools/plot/nc.py +67 -34
- femagtools/shortcircuit.py +18 -10
- femagtools/templates/psi-torq-rem.mako +4 -4
- femagtools/templates/statorKS1.mako +43 -0
- femagtools/utils.py +5 -4
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/METADATA +2 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/RECORD +31 -30
- tests/test_machine.py +1 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/WHEEL +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/licenses/LICENSE +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
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):
|
femagtools/dxfsl/areabuilder.py
CHANGED
@@ -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.
|
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.
|
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.
|
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,
|
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
|
-
|
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
|
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("
|
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
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
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
|
-
|
815
|
-
|
816
|
-
|
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
|
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=
|
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("
|
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
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
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
|
-
|
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():
|
femagtools/dxfsl/converter.py
CHANGED
@@ -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')
|
femagtools/dxfsl/fslrenderer.py
CHANGED
@@ -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',
|