femagtools 1.3.0__py3-none-any.whl → 1.3.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/airgap.py +11 -37
- femagtools/amela.py +148 -13
- femagtools/bch.py +19 -3
- femagtools/dxfsl/area.py +68 -15
- femagtools/dxfsl/converter.py +15 -6
- femagtools/dxfsl/fslrenderer.py +13 -8
- femagtools/dxfsl/functions.py +1 -1
- femagtools/dxfsl/geom.py +415 -62
- femagtools/dxfsl/machine.py +97 -5
- femagtools/dxfsl/shape.py +46 -2
- femagtools/ecloss.py +393 -0
- femagtools/femag.py +25 -1
- femagtools/fsl.py +3 -2
- femagtools/hxy.py +126 -0
- femagtools/isa7.py +37 -24
- femagtools/machine/__init__.py +14 -13
- femagtools/machine/effloss.py +153 -32
- femagtools/machine/im.py +137 -56
- femagtools/machine/pm.py +584 -202
- femagtools/machine/sm.py +218 -64
- femagtools/machine/utils.py +12 -8
- femagtools/mcv.py +6 -8
- femagtools/model.py +11 -1
- femagtools/parstudy.py +1 -1
- femagtools/plot.py +159 -35
- femagtools/templates/afm_rotor.mako +102 -0
- femagtools/templates/afm_stator.mako +141 -0
- femagtools/templates/airgapinduc.mako +3 -3
- femagtools/templates/basic_modpar.mako +23 -2
- femagtools/templates/cogg_calc.mako +28 -5
- femagtools/templates/cu_losses.mako +1 -1
- femagtools/templates/fieldcalc.mako +39 -0
- femagtools/templates/gen_winding.mako +52 -47
- femagtools/templates/mesh-airgap.mako +43 -0
- femagtools/templates/stator3Linear.mako +5 -4
- femagtools/templates/therm-dynamic.mako +12 -6
- femagtools/templates/therm-static.mako +12 -0
- femagtools/templates/torq_calc.mako +2 -4
- femagtools/utils.py +45 -0
- femagtools/windings.py +2 -1
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/METADATA +1 -1
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/RECORD +47 -41
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/WHEEL +1 -1
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/LICENSE +0 -0
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/entry_points.txt +0 -0
- {femagtools-1.3.0.dist-info → femagtools-1.3.2.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py
CHANGED
@@ -276,6 +276,32 @@ def lw_polyline(entity, lf, xoff=0.0, yoff=0.0, rotation=0.0):
|
|
276
276
|
xoff=xoff, yoff=yoff,
|
277
277
|
rotation=rotation)
|
278
278
|
|
279
|
+
def ellipse(entity, lf, xoff=0.0, yoff=0.0, rotation=0.0):
|
280
|
+
w = np.linalg.norm(entity.major_axis) * 2
|
281
|
+
h = entity.ratio * w
|
282
|
+
theta = np.arctan2(entity.major_axis[1], entity.major_axis[0])
|
283
|
+
start_angle = entity.start_param
|
284
|
+
end_angle = entity.end_param
|
285
|
+
if end_angle < start_angle:
|
286
|
+
end_angle += 2*np.pi
|
287
|
+
alfa = np.linspace(start_angle, end_angle, 20)
|
288
|
+
x = 0.5 * w * np.cos(alfa)
|
289
|
+
y = 0.5 * h * np.sin(alfa)
|
290
|
+
R = np.array([
|
291
|
+
[np.cos(theta), -np.sin(theta)],
|
292
|
+
[np.sin(theta), np.cos(theta)]
|
293
|
+
])
|
294
|
+
x, y = np.dot(R, [x, y])
|
295
|
+
x += entity.center[0]
|
296
|
+
y += entity.center[1]
|
297
|
+
points = np.array((x,y)).T
|
298
|
+
p1 = points[0]
|
299
|
+
for p2 in points[1:]:
|
300
|
+
yield Line(Element(start=p1, end=p2), lf,
|
301
|
+
xoff=xoff, yoff=yoff,
|
302
|
+
rotation=rotation)
|
303
|
+
p1 = p2
|
304
|
+
|
279
305
|
|
280
306
|
def spline(entity, lf, min_dist=0.001, xoff=0.0, yoff=0.0, rotation=0.0):
|
281
307
|
if False:
|
@@ -493,22 +519,26 @@ def dxfshapes(dxffile, mindist=0.01, layers=[]):
|
|
493
519
|
for l in insert_block(dwg, e, lf, rf, block, min_dist=mindist):
|
494
520
|
yield l
|
495
521
|
elif e.dxftype == 'ELLIPSE':
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
522
|
+
for l in ellipse(e, lf):
|
523
|
+
yield l
|
524
|
+
#w = np.linalg.norm(e.major_axis) * 2
|
525
|
+
#h = e.ratio * w
|
526
|
+
#rtheta = np.arctan2(e.major_axis[1], e.major_axis[0])
|
527
|
+
#angle = rtheta*180/np.pi
|
528
|
+
#start_angle = e.start_param*180/np.pi + angle
|
529
|
+
#end_angle = e.end_param*180/np.pi + angle
|
530
|
+
#if end_angle < start_angle:
|
531
|
+
# end_angle += 360
|
532
|
+
#arc = Arc(Element(center=e.center,
|
533
|
+
# radius=w/2,
|
534
|
+
# start_angle=start_angle,
|
535
|
+
# end_angle=end_angle,
|
536
|
+
# width=w,
|
537
|
+
# height=h,
|
538
|
+
# rtheta=rtheta,
|
539
|
+
# start_param=e.start_param,
|
540
|
+
# end_param=e.end_param))
|
541
|
+
#yield arc
|
512
542
|
|
513
543
|
elif e.dxftype == 'POINT':
|
514
544
|
logger.debug("Id %d4: type %s ignored", id, e.dxftype)
|
@@ -817,6 +847,46 @@ class Geometry(object):
|
|
817
847
|
for n, r in zip(self.g.nodes(), rotnodes)}
|
818
848
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
819
849
|
|
850
|
+
def check_geom(self, what):
|
851
|
+
logger.debug("check geometry of %s", what)
|
852
|
+
parts = int(round(np.pi * 2 / self.alfa, 1))
|
853
|
+
logger.debug(" --parts......: %s", parts)
|
854
|
+
logger.debug(" --ist alpha..: %s", self.alfa)
|
855
|
+
real_alfa = np.pi * 2 / parts
|
856
|
+
logger.debug(" --soll alpha.: %s", real_alfa)
|
857
|
+
if not np.isclose(self.alfa, real_alfa):
|
858
|
+
logger.debug(" --BAD angle ==> get corrected machine")
|
859
|
+
return self.correct_geom(real_alfa)
|
860
|
+
return None
|
861
|
+
|
862
|
+
def correct_geom(self, correct_alpha):
|
863
|
+
elements = []
|
864
|
+
for e in self.g.edges(data=True):
|
865
|
+
o = e[2]['object'].correct(self.alfa, correct_alpha, ndec)
|
866
|
+
elements.append(o)
|
867
|
+
geom = Geometry(elements, self.rtol, self.atol)
|
868
|
+
geom.center = self.center
|
869
|
+
geom.alfa = correct_alpha
|
870
|
+
geom.min_radius = self.min_radius
|
871
|
+
geom.max_radius = self.max_radius
|
872
|
+
geom.is_inner = self.is_inner
|
873
|
+
geom.kind = self.kind
|
874
|
+
geom.sym_part = self.sym_part
|
875
|
+
return geom
|
876
|
+
|
877
|
+
def log_geom(self):
|
878
|
+
logger.info("Kind............: %s", self.kind)
|
879
|
+
logger.info("Center..........: %s", self.center)
|
880
|
+
logger.info("Alpha...........: %s", self.alfa)
|
881
|
+
logger.info("Is Inner........: %s", self.is_inner)
|
882
|
+
logger.info("Is Outer........: %s", self.is_outer)
|
883
|
+
logger.info("Min Radius......: %s", self.min_radius)
|
884
|
+
logger.info("Max Radius......: %s", self.max_radius)
|
885
|
+
logger.info("Mirror Corners..: %s", self.mirror_corners)
|
886
|
+
logger.info("Start Corners...: %s", self.start_corners)
|
887
|
+
logger.info("End Corners.....: %s", self.end_corners)
|
888
|
+
logger.info("Edges...........: %s", self.num_edges)
|
889
|
+
|
820
890
|
def scale(self, factor):
|
821
891
|
"""scales all objects"""
|
822
892
|
for e in self.g.edges(data=True):
|
@@ -951,15 +1021,31 @@ class Geometry(object):
|
|
951
1021
|
for e in edges:
|
952
1022
|
self.remove_edge(e)
|
953
1023
|
|
954
|
-
def add_line(self, n1, n2):
|
955
|
-
line = Line(Element(start=n1, end=n2))
|
1024
|
+
def add_line(self, n1, n2, color=None):
|
1025
|
+
line = Line(Element(start=n1, end=n2), color=color)
|
956
1026
|
add_or_join(self,
|
957
|
-
|
958
|
-
|
1027
|
+
n1,
|
1028
|
+
n2,
|
959
1029
|
line,
|
960
1030
|
self.rtol,
|
961
1031
|
self.atol)
|
962
1032
|
|
1033
|
+
def add_arc(self, n1, n2, center, radius, color=None):
|
1034
|
+
angle_n1 = alpha_line(center, n1)
|
1035
|
+
angle_n2 = alpha_line(center, n2)
|
1036
|
+
arc = Arc(Element(center=center,
|
1037
|
+
radius=radius,
|
1038
|
+
start_angle=angle_n1*180/np.pi,
|
1039
|
+
end_angle=angle_n2*180/np.pi),
|
1040
|
+
color=color)
|
1041
|
+
add_or_join(self,
|
1042
|
+
n1,
|
1043
|
+
n2,
|
1044
|
+
arc,
|
1045
|
+
self.rtol,
|
1046
|
+
self.atol)
|
1047
|
+
|
1048
|
+
|
963
1049
|
def elements(self, type):
|
964
1050
|
"""return lists of objects"""
|
965
1051
|
return [e[2]['object'] for e in self.g.edges(data=True)
|
@@ -1077,6 +1163,36 @@ class Geometry(object):
|
|
1077
1163
|
logger.debug("end of dist_end_min_corner: %s", d)
|
1078
1164
|
return d
|
1079
1165
|
|
1166
|
+
def get_start_airgap_corner(self):
|
1167
|
+
if self.is_inner:
|
1168
|
+
p = (self.max_radius, 0.0)
|
1169
|
+
cp = self.start_corners[-1]
|
1170
|
+
else:
|
1171
|
+
p = (self.min_radius, 0.0)
|
1172
|
+
cp = self.start_corners[0]
|
1173
|
+
if points_are_close(p, cp, atol=0.5):
|
1174
|
+
return cp, True
|
1175
|
+
return p, False
|
1176
|
+
|
1177
|
+
def get_end_airgap_corner(self):
|
1178
|
+
if self.is_inner:
|
1179
|
+
p = point(self.center, self.max_radius, self.alfa, ndec)
|
1180
|
+
cp = self.end_corners[-1]
|
1181
|
+
else:
|
1182
|
+
p = point(self.center, self.min_radius, self.alfa, ndec)
|
1183
|
+
cp = self.end_corners[0]
|
1184
|
+
if points_are_close(p, cp, atol=0.5):
|
1185
|
+
return cp, True
|
1186
|
+
return p, False
|
1187
|
+
|
1188
|
+
def get_start_airgap_corner_point(self):
|
1189
|
+
p, b = self.get_start_airgap_corner()
|
1190
|
+
return Point(p)
|
1191
|
+
|
1192
|
+
def get_end_airgap_corner_point(self):
|
1193
|
+
p, b = self.get_end_airgap_corner()
|
1194
|
+
return Point(p)
|
1195
|
+
|
1080
1196
|
def area_size(self):
|
1081
1197
|
pts = [p for p in self.start_corners]
|
1082
1198
|
end_pts = [p for p in reversed(self.end_corners)]
|
@@ -1357,7 +1473,7 @@ class Geometry(object):
|
|
1357
1473
|
|
1358
1474
|
for n_angle, n_c, n_info_next in nbrs[1:]:
|
1359
1475
|
n_info_next['angle'] = n_angle
|
1360
|
-
if np.isclose(f_angle, n_angle):
|
1476
|
+
if np.isclose(f_angle, n_angle, 0.01, 0.01):
|
1361
1477
|
logger.debug(" SAME DIRECTION")
|
1362
1478
|
# ACHTUNG
|
1363
1479
|
if self.is_lefthand_edge(alpha, f_info_next, n_info_next):
|
@@ -1401,7 +1517,7 @@ class Geometry(object):
|
|
1401
1517
|
'alpha_n1': alpha_n1,
|
1402
1518
|
'alpha_n2': e.get_alpha(n2),
|
1403
1519
|
'alpha_start': normalise_angle(alpha_n1 + np.pi),
|
1404
|
-
'tracked': e_dict
|
1520
|
+
'tracked': e_dict.get(x, False),
|
1405
1521
|
'reverse': False}
|
1406
1522
|
return info
|
1407
1523
|
|
@@ -1427,9 +1543,9 @@ class Geometry(object):
|
|
1427
1543
|
logger.debug(' node2 = %s', info['n2'])
|
1428
1544
|
logger.debug(' x = %s', info['x'])
|
1429
1545
|
logger.debug(' lock = (%s, %s, %s)',
|
1430
|
-
info['data']
|
1431
|
-
info['data']
|
1432
|
-
info['data']
|
1546
|
+
info['data'].get(0, False),
|
1547
|
+
info['data'].get(1, False),
|
1548
|
+
info['data'].get(2, False))
|
1433
1549
|
|
1434
1550
|
def set_edge_tracked(self, info):
|
1435
1551
|
x = info['x']
|
@@ -1540,6 +1656,16 @@ class Geometry(object):
|
|
1540
1656
|
result['ok'] = True
|
1541
1657
|
return result
|
1542
1658
|
|
1659
|
+
def set_edge_attributes(self):
|
1660
|
+
if nxversion == 1:
|
1661
|
+
nx.set_edge_attributes(self.g, 0, True)
|
1662
|
+
nx.set_edge_attributes(self.g, 1, False)
|
1663
|
+
nx.set_edge_attributes(self.g, 2, False)
|
1664
|
+
else:
|
1665
|
+
nx.set_edge_attributes(self.g, True, 0)
|
1666
|
+
nx.set_edge_attributes(self.g, False, 1)
|
1667
|
+
nx.set_edge_attributes(self.g, False, 2)
|
1668
|
+
|
1543
1669
|
def create_list_of_areas(self, crunch=False):
|
1544
1670
|
""" return list of areas for each node and their neighbors
|
1545
1671
|
"""
|
@@ -1554,15 +1680,7 @@ class Geometry(object):
|
|
1554
1680
|
area_list.append(a)
|
1555
1681
|
|
1556
1682
|
logger.debug("create new area list")
|
1557
|
-
|
1558
|
-
if nxversion == 1:
|
1559
|
-
nx.set_edge_attributes(self.g, 0, True)
|
1560
|
-
nx.set_edge_attributes(self.g, 1, False)
|
1561
|
-
nx.set_edge_attributes(self.g, 2, False)
|
1562
|
-
else:
|
1563
|
-
nx.set_edge_attributes(self.g, True, 0)
|
1564
|
-
nx.set_edge_attributes(self.g, False, 1)
|
1565
|
-
nx.set_edge_attributes(self.g, False, 2)
|
1683
|
+
self.set_edge_attributes()
|
1566
1684
|
|
1567
1685
|
crunched = 0
|
1568
1686
|
for n in self.g.nodes():
|
@@ -2081,11 +2199,20 @@ class Geometry(object):
|
|
2081
2199
|
return self.alfa
|
2082
2200
|
|
2083
2201
|
def __str__(self):
|
2202
|
+
real_alfa = 0
|
2203
|
+
if self.sym_part > 0:
|
2204
|
+
if self.is_mirrored():
|
2205
|
+
real_alfa = np.pi / self.sym_part
|
2206
|
+
else:
|
2207
|
+
real_alfa = 2*np.pi / self.sym_part
|
2084
2208
|
return "name...........: {}\n".format(self._name) + \
|
2085
2209
|
"kind...........: {}\n".format(self.kind) + \
|
2086
2210
|
"sym_part.......: {}\n".format(self.sym_part) + \
|
2087
2211
|
"sym_counterpart: {}\n".format(self.sym_counterpart) + \
|
2088
2212
|
"alpha..........: {}\n".format(self.alfa) + \
|
2213
|
+
"alpha real.....: {}\n".format(real_alfa) + \
|
2214
|
+
"circle.........: {}\n".format(self.alfa * self.sym_part) + \
|
2215
|
+
"mirrored.......: {}\n".format(self.is_mirrored()) + \
|
2089
2216
|
"radius.........: {} -- {}\n".format(self.min_radius,
|
2090
2217
|
self.max_radius)
|
2091
2218
|
|
@@ -2550,7 +2677,7 @@ class Geometry(object):
|
|
2550
2677
|
dist_max = max(dist_max, g[1])
|
2551
2678
|
return airgaps
|
2552
2679
|
|
2553
|
-
def detect_airgaps(self, center, startangle, endangle, atol):
|
2680
|
+
def detect_airgaps(self, center, startangle, endangle, atol=0.1, with_end=False):
|
2554
2681
|
""" Die Funktion sucht Luftspalt-Kandidaten und liefert eine Liste
|
2555
2682
|
von Möglichkeiten mit jeweils einem minimalen und einem maximalen
|
2556
2683
|
Radius als Begrenzung des Luftspalts.
|
@@ -2570,6 +2697,8 @@ class Geometry(object):
|
|
2570
2697
|
min_radius = self.min_radius + 1.0
|
2571
2698
|
cur_radius = gaplist[0][1]
|
2572
2699
|
max_radius = self.max_radius - 1.0
|
2700
|
+
if with_end:
|
2701
|
+
max_radius = self.max_radius + 1.0
|
2573
2702
|
|
2574
2703
|
for g in gaplist:
|
2575
2704
|
if greater(g[0], cur_radius) and \
|
@@ -2930,29 +3059,59 @@ class Geometry(object):
|
|
2930
3059
|
shaft.type = 6 # iron shaft (Zahn)
|
2931
3060
|
return
|
2932
3061
|
|
3062
|
+
def mark_connecting_edges(self, windings):
|
3063
|
+
logger.debug("begin of mark_connecting_edges")
|
3064
|
+
for a in windings:
|
3065
|
+
logger.debug("- id of winding: %s", a.identifier())
|
3066
|
+
for w in windings:
|
3067
|
+
if a.id != w.id:
|
3068
|
+
elist = [e for e in a.list_of_equal_edges(w)]
|
3069
|
+
logger.debug(" --> %s equal egdes", len(elist))
|
3070
|
+
for e in elist:
|
3071
|
+
e.init_attributes('lightblue', 'no_fsl')
|
3072
|
+
|
2933
3073
|
def search_subregions(self):
|
2934
3074
|
if self.is_stator():
|
2935
|
-
|
3075
|
+
self.search_stator_subregions()
|
3076
|
+
elif self.is_rotor():
|
3077
|
+
self.search_rotor_subregions()
|
3078
|
+
else:
|
3079
|
+
logger.warning("no stator or rotor assigned")
|
3080
|
+
self.search_unknown_subregions()
|
3081
|
+
self.looking_for_corners()
|
2936
3082
|
|
2937
|
-
|
2938
|
-
|
3083
|
+
def collect_windings(self):
|
3084
|
+
found = True
|
3085
|
+
while found:
|
3086
|
+
windings = [a for a in self.list_of_areas()
|
3087
|
+
if a.type == 2]
|
3088
|
+
bad_windings = [a for a in self.list_of_areas()
|
3089
|
+
if a.type == 12]
|
3090
|
+
if not bad_windings:
|
3091
|
+
return windings
|
2939
3092
|
|
2940
|
-
|
2941
|
-
|
3093
|
+
found = False
|
3094
|
+
for a in bad_windings:
|
3095
|
+
if a.is_touching_areas(windings):
|
3096
|
+
a.type = 2
|
3097
|
+
found = True
|
3098
|
+
|
3099
|
+
return [a for a in self.list_of_areas() if a.type == 2]
|
2942
3100
|
|
2943
3101
|
def search_stator_subregions(self, place=''):
|
2944
|
-
|
3102
|
+
logger.debug("Begin of search_stator_subregions")
|
3103
|
+
|
2945
3104
|
if place == 'in':
|
2946
|
-
is_inner = True
|
3105
|
+
self.is_inner = True
|
2947
3106
|
elif place == 'out':
|
2948
|
-
is_inner = False
|
3107
|
+
self.is_inner = False
|
2949
3108
|
|
2950
3109
|
if self.alfa == 0.0:
|
2951
3110
|
self.alfa = np.pi * 2.0
|
2952
3111
|
|
2953
3112
|
stator_size = self.area_size()
|
2954
3113
|
for area in self.list_of_areas():
|
2955
|
-
area.mark_stator_subregions(is_inner,
|
3114
|
+
area.mark_stator_subregions(self.is_inner,
|
2956
3115
|
stator_size,
|
2957
3116
|
self.is_mirrored(),
|
2958
3117
|
self.alfa,
|
@@ -2960,8 +3119,8 @@ class Geometry(object):
|
|
2960
3119
|
self.min_radius,
|
2961
3120
|
self.max_radius)
|
2962
3121
|
|
2963
|
-
windings =
|
2964
|
-
|
3122
|
+
windings = self.collect_windings()
|
3123
|
+
[a.set_type(0) for a in self.list_of_areas() if a.type == 12]
|
2965
3124
|
windings_found = len(windings)
|
2966
3125
|
logger.info("%d windings found", windings_found)
|
2967
3126
|
|
@@ -2970,18 +3129,23 @@ class Geometry(object):
|
|
2970
3129
|
windings_surface.sort(reverse=True)
|
2971
3130
|
max_size = windings_surface[0][0]
|
2972
3131
|
for sz, w in windings_surface:
|
3132
|
+
logger.debug("winding size = %s", sz)
|
2973
3133
|
if sz / max_size < 0.95:
|
2974
3134
|
w.set_type(0)
|
2975
|
-
|
3135
|
+
if sz / max_size < 0.2:
|
3136
|
+
windings_found -= 1
|
2976
3137
|
windings = [a for a in self.list_of_areas()
|
2977
3138
|
if a.is_winding()]
|
2978
3139
|
if windings_found > 2 and len(windings) == 1:
|
3140
|
+
logger.info("no windings remaining")
|
2979
3141
|
# no windings
|
2980
3142
|
[w.set_type(0) for w in windings]
|
2981
3143
|
[a.set_type(1) for a in self.list_of_areas() if a.is_iron()]
|
2982
3144
|
windings = []
|
2983
3145
|
elif len(windings) < windings_found:
|
2984
3146
|
logger.info("%d windings remaining", len(windings))
|
3147
|
+
if len(windings) > 2:
|
3148
|
+
self.mark_connecting_edges(windings)
|
2985
3149
|
|
2986
3150
|
wdg_min_angle = 99999
|
2987
3151
|
wdg_max_angle = 0
|
@@ -3088,19 +3252,19 @@ class Geometry(object):
|
|
3088
3252
|
self.check_shaft_area(shaft_areas[0])
|
3089
3253
|
|
3090
3254
|
def search_rotor_subregions(self, place=''):
|
3091
|
-
logger.debug("
|
3092
|
-
|
3255
|
+
logger.debug("Begin of search_rotor_subregions")
|
3256
|
+
|
3093
3257
|
if place == 'in':
|
3094
|
-
is_inner = True
|
3258
|
+
self.is_inner = True
|
3095
3259
|
elif place == 'out':
|
3096
|
-
is_inner = False
|
3260
|
+
self.is_inner = False
|
3097
3261
|
|
3098
3262
|
if self.alfa == 0.0:
|
3099
3263
|
self.alfa = np.pi * 2.0
|
3100
3264
|
|
3101
3265
|
types = {}
|
3102
3266
|
for area in self.list_of_areas():
|
3103
|
-
t = area.mark_rotor_subregions(is_inner,
|
3267
|
+
t = area.mark_rotor_subregions(self.is_inner,
|
3104
3268
|
self.is_mirrored(),
|
3105
3269
|
self.alfa,
|
3106
3270
|
self.center,
|
@@ -3230,7 +3394,21 @@ class Geometry(object):
|
|
3230
3394
|
if a.surface < max_surface * 0.20: # too small
|
3231
3395
|
a.set_type(0) # air
|
3232
3396
|
|
3233
|
-
logger.debug("
|
3397
|
+
logger.debug("end of search_unknown_subregions")
|
3398
|
+
|
3399
|
+
def looking_for_corners(self):
|
3400
|
+
if self.is_inner:
|
3401
|
+
logger.debug("looking_for_corners: inner")
|
3402
|
+
start_cp = self.start_corners[-1]
|
3403
|
+
end_cp = self.end_corners[-1]
|
3404
|
+
else:
|
3405
|
+
logger.debug("looking_for_corners: outer")
|
3406
|
+
start_cp = self.start_corners[0]
|
3407
|
+
end_cp = self.end_corners[0]
|
3408
|
+
logger.debug("looking_for_corners: start=%s, end=%s",
|
3409
|
+
start_cp, end_cp)
|
3410
|
+
for area in self.list_of_areas():
|
3411
|
+
area.mark_airgap_corners(start_cp, end_cp)
|
3234
3412
|
return
|
3235
3413
|
|
3236
3414
|
def num_areas_of_type(self, type):
|
@@ -3483,19 +3661,16 @@ class Geometry(object):
|
|
3483
3661
|
c += self.remove_appendix(n2, nbrs[0], incr_text + '.')
|
3484
3662
|
return c
|
3485
3663
|
|
3486
|
-
def split_and_get_intersect_points(self,
|
3664
|
+
def split_and_get_intersect_points(self, el, aktion=True):
|
3487
3665
|
logger.debug("begin of split_and_get_intersect_points")
|
3488
3666
|
rtol = 1e-03
|
3489
3667
|
atol = 1e-03
|
3490
|
-
line = Line(
|
3491
|
-
Element(start=center,
|
3492
|
-
end=point(center, outer_radius+1, angle)))
|
3493
3668
|
points = []
|
3494
3669
|
for e in self.elements(Shape):
|
3495
|
-
pts = e.
|
3496
|
-
|
3497
|
-
|
3498
|
-
|
3670
|
+
pts = e.intersect_shape(el,
|
3671
|
+
rtol=rtol,
|
3672
|
+
atol=atol,
|
3673
|
+
include_end=True)
|
3499
3674
|
if pts:
|
3500
3675
|
pts_inside = []
|
3501
3676
|
pts_real = []
|
@@ -3510,7 +3685,7 @@ class Geometry(object):
|
|
3510
3685
|
pts_real.append(p)
|
3511
3686
|
pts_inside.append(p)
|
3512
3687
|
|
3513
|
-
if pts_inside:
|
3688
|
+
if pts_inside and aktion:
|
3514
3689
|
self.remove_edge(e)
|
3515
3690
|
elements = e.split(pts_inside, rtol, atol)
|
3516
3691
|
for e in elements:
|
@@ -3533,6 +3708,31 @@ class Geometry(object):
|
|
3533
3708
|
return True
|
3534
3709
|
return False
|
3535
3710
|
|
3711
|
+
def inside_area_list(self, p):
|
3712
|
+
for area in self.list_of_areas():
|
3713
|
+
if area.is_point_inside(p):
|
3714
|
+
yield area
|
3715
|
+
|
3716
|
+
def critical_touch_point(self, points):
|
3717
|
+
logger.debug("looking for critical touch-point")
|
3718
|
+
winding_touched = False
|
3719
|
+
for p in points[1:]:
|
3720
|
+
d = distance(self.center, p)
|
3721
|
+
logger.debug("-- p = %s, dist = %s", p, d)
|
3722
|
+
for a in self.inside_area_list(p):
|
3723
|
+
logger.debug("-- Area type = %s", a.type)
|
3724
|
+
logger.debug(" min=%s, max= %s", a.min_dist, a.max_dist)
|
3725
|
+
logger.debug(" close to start = %s", a.close_to_startangle)
|
3726
|
+
logger.debug(" close to end = %s", a.close_to_endangle)
|
3727
|
+
if a.is_winding():
|
3728
|
+
winding_touched = True
|
3729
|
+
else:
|
3730
|
+
if winding_touched and greater(a.max_dist, d, atol=0.001):
|
3731
|
+
if not (a.close_to_startangle and a.close_to_endangle):
|
3732
|
+
logger.debug("-- return %s", p)
|
3733
|
+
return p
|
3734
|
+
return None
|
3735
|
+
|
3536
3736
|
def create_lines_outside_windings(self, points):
|
3537
3737
|
if not points:
|
3538
3738
|
return False
|
@@ -3562,6 +3762,159 @@ class Geometry(object):
|
|
3562
3762
|
return True
|
3563
3763
|
return False
|
3564
3764
|
|
3765
|
+
def get_inner_airgap_line(self):
|
3766
|
+
logger.debug("begin of get_inner_airgap_line")
|
3767
|
+
|
3768
|
+
if not self.is_inner:
|
3769
|
+
logger.debug("end of get_inner_airgap_line: not inner")
|
3770
|
+
return []
|
3771
|
+
for a in self.area_list:
|
3772
|
+
logger.debug("%s", a)
|
3773
|
+
area = [a for a in self.area_list if a.close_to_ag_endcorner]
|
3774
|
+
if len(area) != 1:
|
3775
|
+
logger.debug("end of get_inner_airgap_line: %s areas found", len(area))
|
3776
|
+
return []
|
3777
|
+
|
3778
|
+
end_corner = self.end_corners[-1]
|
3779
|
+
logger.debug("END CORNER %s", end_corner)
|
3780
|
+
nodes = [n for n in area[0].list_of_nodes()]
|
3781
|
+
if not nodes:
|
3782
|
+
logger.debug("end of get_inner_airgap_line: no nodes found")
|
3783
|
+
return []
|
3784
|
+
n1 = nodes[0]
|
3785
|
+
if points_are_close(end_corner, n1):
|
3786
|
+
n2 = nodes[-1]
|
3787
|
+
else:
|
3788
|
+
n2 = n1
|
3789
|
+
for n1 in nodes[1:]:
|
3790
|
+
if points_are_close(end_corner, n1):
|
3791
|
+
break
|
3792
|
+
n2 = n1
|
3793
|
+
|
3794
|
+
if not points_are_close(end_corner, n1):
|
3795
|
+
logger.debug("end of get_inner_airgap_line: not close to endcorner")
|
3796
|
+
return []
|
3797
|
+
|
3798
|
+
start_corner = self.start_corners[-1]
|
3799
|
+
|
3800
|
+
logger.debug("EDGE FOUND: %s - %s", n1, n2)
|
3801
|
+
nodes = [n1, n2]
|
3802
|
+
info = self.get_edge_info(n1, n2)
|
3803
|
+
while not points_are_close(start_corner, n2):
|
3804
|
+
info = self.next_edge_lefthand_side(info)
|
3805
|
+
if not info:
|
3806
|
+
return []
|
3807
|
+
n2 = info['n2']
|
3808
|
+
nodes.append(n2)
|
3809
|
+
|
3810
|
+
logger.debug("end of get_inner_airgap_line #%s", len(nodes))
|
3811
|
+
return nodes
|
3812
|
+
|
3813
|
+
def create_corner_areas(self):
|
3814
|
+
self.set_edge_attributes()
|
3815
|
+
self.create_inner_corner_areas()
|
3816
|
+
|
3817
|
+
def create_and_append_area(self, n1, n2):
|
3818
|
+
rslt = self.get_new_area(n1, n2, False)
|
3819
|
+
logger.debug("create_and_append_area: %s", rslt)
|
3820
|
+
if rslt.get('ok', False):
|
3821
|
+
area = rslt['area']
|
3822
|
+
a = Area(area, self.center, 0.0)
|
3823
|
+
a.type = 0 # air
|
3824
|
+
self.area_list.append(a)
|
3825
|
+
return True
|
3826
|
+
logger.error("No area for air near airgap!!")
|
3827
|
+
return False
|
3828
|
+
|
3829
|
+
def create_inner_corner_areas(self):
|
3830
|
+
start_cp, start_exists = self.get_start_airgap_corner()
|
3831
|
+
end_cp, end_exists = self.get_end_airgap_corner()
|
3832
|
+
if start_exists and end_exists:
|
3833
|
+
return
|
3834
|
+
logger.info("*** Corner correction ***")
|
3835
|
+
airgap_line = self.get_inner_airgap_line()
|
3836
|
+
if not airgap_line:
|
3837
|
+
logger.debug("no airgapline found")
|
3838
|
+
return
|
3839
|
+
|
3840
|
+
logger.debug("airgapline found !!")
|
3841
|
+
airgap_nodes = [n for n in airgap_line[1:]]
|
3842
|
+
del airgap_nodes[-1]
|
3843
|
+
if not airgap_nodes:
|
3844
|
+
return # strange
|
3845
|
+
|
3846
|
+
if not start_exists:
|
3847
|
+
cp = self.start_corners[-1]
|
3848
|
+
logger.debug("Start Corner: %s -- %s", cp, start_cp)
|
3849
|
+
start_line = Line(Element(start=cp, end=start_cp), color='red')
|
3850
|
+
start_cp = start_line.node2(ndec)
|
3851
|
+
i = 0
|
3852
|
+
for n in airgap_nodes:
|
3853
|
+
i += 1
|
3854
|
+
if not self.search_intersection(i, self.max_radius,
|
3855
|
+
n, start_cp,
|
3856
|
+
airgap_nodes):
|
3857
|
+
d = distance(self.center, n)
|
3858
|
+
if np.isclose(d, self.max_radius):
|
3859
|
+
self.add_arc(start_cp, n, self.center, self.max_radius, color='red')
|
3860
|
+
else:
|
3861
|
+
self.add_line(start_cp, n, color='red')
|
3862
|
+
self.add_edge(cp, start_cp, start_line)
|
3863
|
+
self.create_and_append_area(start_cp, n)
|
3864
|
+
self.start_corners = self.get_corner_nodes(self.center,
|
3865
|
+
0.0)
|
3866
|
+
break
|
3867
|
+
|
3868
|
+
if not end_exists:
|
3869
|
+
cp = self.end_corners[-1]
|
3870
|
+
logger.debug("End Corner: %s -- %s", cp, end_cp)
|
3871
|
+
end_line = Line(Element(start=cp, end=end_cp), color='red')
|
3872
|
+
end_cp = end_line.node2(ndec)
|
3873
|
+
airgap_nodes.reverse()
|
3874
|
+
i = 0
|
3875
|
+
for n in airgap_nodes:
|
3876
|
+
i += 1
|
3877
|
+
if not self.search_intersection(i, self.max_radius,
|
3878
|
+
n, end_cp,
|
3879
|
+
airgap_nodes):
|
3880
|
+
d = distance(self.center, n)
|
3881
|
+
if np.isclose(d, self.max_radius):
|
3882
|
+
self.add_arc(n, end_cp, self.center, self.max_radius, color='red')
|
3883
|
+
else:
|
3884
|
+
self.add_line(end_cp, n, color='red')
|
3885
|
+
self.add_edge(cp, end_cp, end_line)
|
3886
|
+
self.create_and_append_area(n, end_cp)
|
3887
|
+
self.end_corners = self.get_corner_nodes(self.center,
|
3888
|
+
self.alfa)
|
3889
|
+
break
|
3890
|
+
|
3891
|
+
def search_intersection(self, start_i, r, n1, n2, airgap_nodes):
|
3892
|
+
logger.debug("begin of search_intersection")
|
3893
|
+
|
3894
|
+
ag_line = Line(Element(start=n1, end=n2))
|
3895
|
+
for i in range(start_i, len(airgap_nodes)):
|
3896
|
+
n = airgap_nodes[i]
|
3897
|
+
alfa = alpha_line(self.center, n)
|
3898
|
+
dist_n = distance(self.center, n)
|
3899
|
+
p = point(self.center, r, alfa)
|
3900
|
+
line = Line(Element(start=self.center, end=p))
|
3901
|
+
pts = line.intersect_line(ag_line, include_end=True)
|
3902
|
+
if not pts:
|
3903
|
+
# no intersection
|
3904
|
+
return # ok
|
3905
|
+
if len(pts) != 1:
|
3906
|
+
logger.error("-- no intersection found ?!? %s", pts)
|
3907
|
+
logger.debug("end of search_intersection: bad")
|
3908
|
+
return True # fatal
|
3909
|
+
dist_p = distance(self.center, pts[0])
|
3910
|
+
logger.debug("-- check point %s[%s] -- %s[%s]", n, dist_n, pts[0], dist_p)
|
3911
|
+
if not less(dist_n, dist_p):
|
3912
|
+
logger.debug("end of search_intersection: found")
|
3913
|
+
return True # intersection
|
3914
|
+
logger.debug("-- dist %s <= %s", dist_n, dist_p)
|
3915
|
+
logger.debug("end of search_intersection: ok")
|
3916
|
+
return False # ok
|
3917
|
+
|
3565
3918
|
def print_nodes(self):
|
3566
3919
|
print("=== List of Nodes ({}) ===".format(self.number_of_nodes()))
|
3567
3920
|
for n in self.g.nodes():
|