femagtools 1.6.8__py3-none-any.whl → 1.7.1__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 +2 -2
- femagtools/bch.py +1 -1
- femagtools/dxfsl/area.py +343 -406
- femagtools/dxfsl/areabuilder.py +139 -12
- femagtools/dxfsl/conv.py +27 -9
- femagtools/dxfsl/converter.py +406 -127
- femagtools/dxfsl/corner.py +3 -0
- femagtools/dxfsl/femparser.py +1 -1
- femagtools/dxfsl/fslrenderer.py +290 -246
- femagtools/dxfsl/functions.py +4 -2
- femagtools/dxfsl/geom.py +1204 -893
- femagtools/dxfsl/journal.py +58 -22
- femagtools/dxfsl/machine.py +254 -75
- femagtools/dxfsl/plotrenderer.py +38 -3
- femagtools/dxfsl/shape.py +380 -103
- femagtools/dxfsl/symmetry.py +679 -110
- femagtools/femag.py +27 -2
- femagtools/forcedens.py +65 -40
- femagtools/fsl.py +71 -28
- femagtools/losscoeffs.py +46 -0
- femagtools/machine/effloss.py +8 -1
- femagtools/machine/im.py +3 -1
- femagtools/machine/pm.py +11 -7
- femagtools/machine/sizing.py +15 -12
- femagtools/machine/sm.py +114 -33
- femagtools/machine/utils.py +38 -34
- femagtools/model.py +12 -2
- femagtools/moo/population.py +1 -1
- femagtools/parstudy.py +17 -1
- femagtools/plot/__init__.py +1 -1
- femagtools/plot/char.py +24 -7
- femagtools/plot/forcedens.py +56 -29
- femagtools/plot/mcv.py +4 -1
- femagtools/plot/phasor.py +6 -1
- femagtools/poc.py +17 -10
- femagtools/templates/cogg_calc.mako +7 -1
- femagtools/templates/displ_stator_rotor.mako +33 -0
- femagtools/templates/fieldcalc.mako +10 -16
- femagtools/templates/pm_sym_f_cur.mako +1 -1
- femagtools/tks.py +3 -9
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/LICENSE +1 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/METADATA +7 -4
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/RECORD +51 -50
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/WHEEL +1 -1
- tests/engines/__init__.py +0 -20
- tests/geom/__init__.py +0 -20
- tests/moo/__init__.py +0 -20
- tests/test_model.py +8 -1
- tests/test_sizing.py +2 -2
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/entry_points.txt +0 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/area.py
CHANGED
@@ -15,8 +15,8 @@ from .functions import less_equal, less, greater_equal, greater
|
|
15
15
|
from .functions import distance, alpha_angle, alpha_line, min_angle, max_angle
|
16
16
|
from .functions import point, line_m, line_n, intersect_point, points_are_close
|
17
17
|
from .functions import middle_angle, part_of_circle, is_same_angle
|
18
|
-
from .functions import area_size
|
19
|
-
from .shape import Element, Shape, Line, Arc, Circle, is_Circle
|
18
|
+
from .functions import area_size, normalise_angle, positive_angle
|
19
|
+
from .shape import Element, Shape, Line, Arc, Circle, is_Circle, is_Line, is_Arc
|
20
20
|
|
21
21
|
logger = logging.getLogger('femagtools.area')
|
22
22
|
|
@@ -27,11 +27,26 @@ logger = logging.getLogger('femagtools.area')
|
|
27
27
|
|
28
28
|
area_number = 0
|
29
29
|
|
30
|
+
TYPE_AIR = 0
|
31
|
+
TYPE_IRON = 1
|
32
|
+
TYPE_WINDINGS = 2
|
33
|
+
TYPE_MAGNET_AIRGAP = 3
|
34
|
+
TYPE_MAGNET_RECT = 4
|
35
|
+
TYPE_YOKE = 5
|
36
|
+
TYPE_TOOTH = 6
|
37
|
+
TYPE_MAGNET_OR_AIR = 8
|
38
|
+
TYPE_AIR_OR_IRON = 9
|
39
|
+
TYPE_MAGNET_OR_IRON = 9
|
40
|
+
TYPE_SHAFT = 10
|
41
|
+
TYPE_MAGNET_RECT_NEAR_AIRGAP = 11
|
42
|
+
TYPE_WINDINGS_OR_AIR = 12
|
43
|
+
TYPE_MAGNET_UNDEFINED = 99
|
44
|
+
TYPE_GROUP = 20
|
30
45
|
|
31
46
|
class Area(object):
|
32
47
|
def __init__(self, area, center, sym_tolerance):
|
33
48
|
self.area = area
|
34
|
-
self.type =
|
49
|
+
self.type = -1 # material
|
35
50
|
self.phi = 0.0
|
36
51
|
self.min_angle = 0.0
|
37
52
|
self.max_angle = 0.0
|
@@ -43,9 +58,13 @@ class Area(object):
|
|
43
58
|
self.close_to_startangle = False
|
44
59
|
self.close_to_endangle = False
|
45
60
|
self.mag_rectangle = False
|
61
|
+
self.mag_width = 0.0
|
46
62
|
self.min_dist = 99999.0
|
47
63
|
self.max_dist = 0.0
|
48
|
-
self.
|
64
|
+
self.min_x = None
|
65
|
+
self.max_x = None
|
66
|
+
self.min_y = None
|
67
|
+
self.max_y = None
|
49
68
|
self.height = 0.0
|
50
69
|
self.alpha = 0.0
|
51
70
|
self.count = 1
|
@@ -62,7 +81,9 @@ class Area(object):
|
|
62
81
|
global area_number
|
63
82
|
area_number += 1
|
64
83
|
self.id = area_number
|
84
|
+
self.is_child = False
|
65
85
|
self.areas_inside = {}
|
86
|
+
self.areas_of_group = []
|
66
87
|
|
67
88
|
def identifier(self):
|
68
89
|
return "{}-{}".format(self.id, self.type)
|
@@ -180,88 +201,94 @@ class Area(object):
|
|
180
201
|
last_point = next_nodes[-1]
|
181
202
|
|
182
203
|
def legend(self):
|
183
|
-
if self.type ==
|
204
|
+
if self.type == TYPE_IRON:
|
184
205
|
return 'Iron'
|
185
|
-
if self.type ==
|
206
|
+
if self.type == TYPE_WINDINGS:
|
186
207
|
return 'Windings'
|
187
|
-
if self.type ==
|
208
|
+
if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
|
188
209
|
return 'Magnet'
|
189
|
-
if self.type ==
|
210
|
+
if self.type == TYPE_YOKE:
|
190
211
|
return 'Yoke'
|
191
|
-
if self.type ==
|
212
|
+
if self.type == TYPE_TOOTH:
|
192
213
|
return 'Tooth'
|
193
|
-
if self.type ==
|
214
|
+
if self.type == TYPE_SHAFT:
|
194
215
|
return 'Shaft'
|
195
216
|
return ''
|
196
217
|
|
197
218
|
def name(self):
|
198
|
-
if self.type ==
|
219
|
+
if self.type == TYPE_IRON:
|
199
220
|
return 'Iron'
|
200
|
-
if self.type ==
|
221
|
+
if self.type == TYPE_WINDINGS:
|
201
222
|
return 'Wndg'
|
202
|
-
if self.type ==
|
223
|
+
if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
|
203
224
|
return 'Mag'
|
204
|
-
if self.type ==
|
225
|
+
if self.type == TYPE_YOKE:
|
205
226
|
return 'StJo'
|
206
|
-
if self.type ==
|
227
|
+
if self.type == TYPE_TOOTH:
|
207
228
|
return 'StZa'
|
208
|
-
if self.type ==
|
229
|
+
if self.type == TYPE_SHAFT:
|
209
230
|
return 'Shft'
|
210
231
|
return ''
|
211
232
|
|
212
233
|
def color(self):
|
213
|
-
if self.type ==
|
234
|
+
if self.type == TYPE_IRON:
|
214
235
|
return 'cyan'
|
215
|
-
if self.type ==
|
236
|
+
if self.type == TYPE_WINDINGS:
|
216
237
|
return 'green'
|
217
|
-
if self.type ==
|
238
|
+
if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
|
218
239
|
return 'red'
|
219
|
-
if self.type ==
|
240
|
+
if self.type == TYPE_YOKE:
|
220
241
|
return 'cyan'
|
221
|
-
if self.type ==
|
242
|
+
if self.type == TYPE_TOOTH:
|
222
243
|
return 'skyblue'
|
223
|
-
if self.type ==
|
244
|
+
if self.type == TYPE_SHAFT:
|
224
245
|
return 'lightgrey'
|
225
246
|
return 'white'
|
226
247
|
|
227
248
|
def color_alpha(self):
|
228
|
-
if self.type ==
|
249
|
+
if self.type == TYPE_IRON:
|
229
250
|
return 0.3
|
230
|
-
if self.type ==
|
251
|
+
if self.type == TYPE_WINDINGS:
|
231
252
|
return 1.0
|
232
|
-
if self.type ==
|
253
|
+
if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
|
233
254
|
return 1.0
|
234
|
-
if self.type ==
|
255
|
+
if self.type == TYPE_YOKE:
|
235
256
|
return 0.5
|
236
|
-
if self.type ==
|
257
|
+
if self.type == TYPE_TOOTH:
|
237
258
|
return 1.0
|
238
|
-
if self.type ==
|
259
|
+
if self.type == TYPE_SHAFT:
|
239
260
|
return 0.8
|
240
261
|
return 1.0
|
241
262
|
|
242
263
|
def is_iron(self):
|
243
|
-
return
|
264
|
+
return \
|
265
|
+
self.type == TYPE_IRON or \
|
266
|
+
self.type == TYPE_YOKE or \
|
267
|
+
self.type == TYPE_TOOTH
|
244
268
|
|
245
269
|
def is_stator_iron_yoke(self):
|
246
|
-
return self.type ==
|
270
|
+
return self.type == TYPE_YOKE
|
247
271
|
|
248
272
|
def is_stator_iron_tooth(self):
|
249
|
-
return self.type ==
|
273
|
+
return self.type == TYPE_TOOTH
|
250
274
|
|
251
275
|
def is_rotor_iron(self):
|
252
|
-
return self.type ==
|
276
|
+
return self.type == TYPE_IRON
|
253
277
|
|
254
278
|
def is_winding(self):
|
255
|
-
return self.type ==
|
279
|
+
return self.type == TYPE_WINDINGS
|
256
280
|
|
257
281
|
def is_magnet(self):
|
258
|
-
return self.type ==
|
282
|
+
return self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT
|
259
283
|
|
260
284
|
def is_shaft(self):
|
261
|
-
return self.type ==
|
285
|
+
return self.type == TYPE_SHAFT
|
262
286
|
|
263
287
|
def is_air(self):
|
264
|
-
return self.type ==
|
288
|
+
return self.type == TYPE_AIR
|
289
|
+
|
290
|
+
def is_type(self, type):
|
291
|
+
return self.type == type
|
265
292
|
|
266
293
|
def set_type(self, t):
|
267
294
|
self.type = t
|
@@ -270,7 +297,7 @@ class Area(object):
|
|
270
297
|
if not self.area:
|
271
298
|
return
|
272
299
|
|
273
|
-
self.
|
300
|
+
self.min_x, self.max_x, self.min_y, self.max_y = self.minmax()
|
274
301
|
s = self.area[0]
|
275
302
|
mm_angle = s.minmax_angle_from_center(center)
|
276
303
|
self.min_angle = mm_angle[0]
|
@@ -289,8 +316,10 @@ class Area(object):
|
|
289
316
|
self.alpha = round(alpha_angle(self.min_angle, self.max_angle), 3)
|
290
317
|
|
291
318
|
def center_is_inside(self, center):
|
292
|
-
if self.
|
293
|
-
self.
|
319
|
+
if less(self.min_x, center[0], rtol=1e-03, atol=1e-04) and \
|
320
|
+
greater(self.max_x, center[0], rtol=1e-03, atol=1e-04) and \
|
321
|
+
less(self.min_y, center[1], rtol=1e-03, atol=1e-04) and \
|
322
|
+
greater(self.max_y, center[1], rtol=1e-03, atol=1e-04):
|
294
323
|
return True
|
295
324
|
return False
|
296
325
|
|
@@ -329,9 +358,8 @@ class Area(object):
|
|
329
358
|
return False
|
330
359
|
|
331
360
|
line = Line(Element(start=p1, end=p2))
|
332
|
-
plist = self.
|
361
|
+
plist = self.get_intersect_points(line)
|
333
362
|
points = len(plist)
|
334
|
-
plist.sort()
|
335
363
|
|
336
364
|
aux_lines = [e for e in self.area if e.has_attribute('auxline')]
|
337
365
|
if aux_lines:
|
@@ -358,6 +386,15 @@ class Area(object):
|
|
358
386
|
def is_touching_both_sides(self):
|
359
387
|
return (self.close_to_startangle and self.close_to_endangle)
|
360
388
|
|
389
|
+
def is_in_touch_with_area(self, geom, a):
|
390
|
+
n1 = self.area[0].n1
|
391
|
+
n2 = a.area[0].n2
|
392
|
+
try:
|
393
|
+
return nx.has_path(geom.g, n1, n2)
|
394
|
+
except nx.NetworkXError:
|
395
|
+
logger.warning("has_path() failed")
|
396
|
+
return False
|
397
|
+
|
361
398
|
def has_connection(self, geom, a, ndec):
|
362
399
|
assert(self.area)
|
363
400
|
assert(a.area)
|
@@ -395,12 +432,14 @@ class Area(object):
|
|
395
432
|
d = distance(p1, p2)
|
396
433
|
gap_list.append((d, (p1, p2), dist_id, a.get_id()))
|
397
434
|
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
if
|
403
|
-
|
435
|
+
if rightangle is not None:
|
436
|
+
d, p1, p2 = a.get_nearest_point(center, radius, rightangle)
|
437
|
+
if p1:
|
438
|
+
gap_list.append((d, (p1, p2), dist_id, a.get_id()))
|
439
|
+
if leftangle is not None:
|
440
|
+
d, p1, p2 = a.get_nearest_point(center, radius, leftangle)
|
441
|
+
if p1:
|
442
|
+
gap_list.append((d, (p1, p2), dist_id, a.get_id()))
|
404
443
|
if not gap_list:
|
405
444
|
return []
|
406
445
|
gap_list.sort()
|
@@ -635,11 +674,21 @@ class Area(object):
|
|
635
674
|
return True
|
636
675
|
return False
|
637
676
|
|
638
|
-
def
|
677
|
+
def get_intersect_points(self, line, rtol=1.e-4, atol=1e-3):
|
639
678
|
points = []
|
640
679
|
for e in self.area:
|
641
|
-
points += e.intersect_line(line, include_end=True)
|
642
|
-
|
680
|
+
points += e.intersect_line(line, rtol=rtol, atol=atol, include_end=True)
|
681
|
+
if not points:
|
682
|
+
return []
|
683
|
+
points = [(x, y) for x, y in points]
|
684
|
+
points.sort()
|
685
|
+
p1 = points[0]
|
686
|
+
pts = [p1]
|
687
|
+
for p2 in points[1:]:
|
688
|
+
if not points_are_close(p1, p2, rtol=rtol, atol=atol):
|
689
|
+
pts.append(p2)
|
690
|
+
p1 = p2
|
691
|
+
return pts
|
643
692
|
|
644
693
|
def is_point_inside(self, pt):
|
645
694
|
for e in self.area:
|
@@ -647,14 +696,49 @@ class Area(object):
|
|
647
696
|
return True
|
648
697
|
return False
|
649
698
|
|
699
|
+
def the_area_is_inside_area(self, a):
|
700
|
+
p = a.area[0].n1
|
701
|
+
return self.the_point_is_inside_area(p)
|
702
|
+
|
703
|
+
def the_point_is_inside_area(self, p):
|
704
|
+
x, y = p
|
705
|
+
if less_equal(x, self.min_x) or greater_equal(x, self.max_x):
|
706
|
+
return False
|
707
|
+
if less_equal(y, self.min_y) or greater_equal(y, self.max_y):
|
708
|
+
return False
|
709
|
+
|
710
|
+
p1 = (self.min_x - 5, y)
|
711
|
+
p2 = (self.max_x + 5, y)
|
712
|
+
line = Line(Element(start=p1, end=p2))
|
713
|
+
pts = self.get_intersect_points(line)
|
714
|
+
if len(pts) % 2 != 0:
|
715
|
+
return False
|
716
|
+
|
717
|
+
c = 0
|
718
|
+
for ax, ay in pts:
|
719
|
+
if not less(ax, x):
|
720
|
+
if c % 2 != 1:
|
721
|
+
return False
|
722
|
+
break
|
723
|
+
c += 1
|
724
|
+
|
725
|
+
if not c < len(pts):
|
726
|
+
return False
|
727
|
+
|
728
|
+
ax, ay = pts[c]
|
729
|
+
if not less(x, ax):
|
730
|
+
return False
|
731
|
+
return True
|
732
|
+
|
650
733
|
def get_best_point_inside(self, geom):
|
651
|
-
|
652
|
-
|
653
|
-
px2 = mm[1]+5
|
734
|
+
px1 = self.min_x - 5
|
735
|
+
px2 = self.max_x + 5
|
654
736
|
|
655
|
-
y_dist =
|
737
|
+
y_dist = self.max_y - self.min_y
|
656
738
|
step = y_dist / 6
|
657
|
-
y_list = np.arange(
|
739
|
+
y_list = np.arange(self.min_y + step * 0.3,
|
740
|
+
self.max_y - step * 0.3,
|
741
|
+
step)
|
658
742
|
|
659
743
|
lines = []
|
660
744
|
for y in y_list:
|
@@ -745,10 +829,9 @@ class Area(object):
|
|
745
829
|
|
746
830
|
def get_point_inside(self, geom):
|
747
831
|
"""return point inside area"""
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
p2 = (mm[1]+5, y)
|
832
|
+
y = (self.min_y + self.max_y) / 2
|
833
|
+
p1 = (self.min_x - 5, y)
|
834
|
+
p2 = (self.max_x + 5, y)
|
752
835
|
line = Line(Element(start=p1, end=p2))
|
753
836
|
|
754
837
|
points = []
|
@@ -820,6 +903,32 @@ class Area(object):
|
|
820
903
|
renderer.fill(x, y, color, alpha)
|
821
904
|
return True
|
822
905
|
|
906
|
+
def magnet_arrow_length(self):
|
907
|
+
if self.is_type(TYPE_MAGNET_AIRGAP):
|
908
|
+
return (self.max_dist - self.min_dist) * 0.9
|
909
|
+
if self.is_type(TYPE_MAGNET_RECT):
|
910
|
+
return self.mag_width
|
911
|
+
return 0.0
|
912
|
+
|
913
|
+
def render_magnet_phi(self, renderer, length):
|
914
|
+
if not self.is_magnet():
|
915
|
+
return
|
916
|
+
p1 = None
|
917
|
+
p2 = None
|
918
|
+
if self.is_type(TYPE_MAGNET_AIRGAP):
|
919
|
+
mid = middle_angle(self.min_angle, self.max_angle)
|
920
|
+
d = self.min_dist + (self.max_dist - self.min_dist) * 0.3
|
921
|
+
p1 = point((0.0, 0.0), d, mid)
|
922
|
+
if self.is_type(TYPE_MAGNET_RECT):
|
923
|
+
x = self.min_x + (self.max_x - self.min_x) / 2
|
924
|
+
y = self.min_y + (self.max_y - self.min_y) / 2
|
925
|
+
p1 = (x, y)
|
926
|
+
if p1 is None:
|
927
|
+
return
|
928
|
+
p2 = point(p1, length, self.phi)
|
929
|
+
renderer.arrow(p1, p2, linewidth=1.2)
|
930
|
+
return
|
931
|
+
|
823
932
|
def render_legend(self, renderer):
|
824
933
|
return renderer.new_legend_handle(self.color(),
|
825
934
|
self.color_alpha(),
|
@@ -867,25 +976,16 @@ class Area(object):
|
|
867
976
|
return False
|
868
977
|
return True
|
869
978
|
|
870
|
-
def has_round_edges(self):
|
871
|
-
arcs = 0
|
872
|
-
for e in self.area:
|
873
|
-
# if isinstance(e, Line):
|
874
|
-
# if not np.isclose(angle, alpha_line(center, e.p1)):
|
875
|
-
# return False
|
876
|
-
# if not np.isclose(angle, alpha_line(center, e.p2)):
|
877
|
-
# return False
|
878
|
-
if isinstance(e, Arc):
|
879
|
-
arcs += 1
|
880
|
-
|
881
|
-
return arcs > 0
|
882
|
-
|
883
979
|
def is_shaft_area(self, center):
|
884
980
|
logger.debug("Begin of check shaft")
|
885
981
|
|
886
|
-
if not self.is_touching_both_sides():
|
887
|
-
|
888
|
-
|
982
|
+
#if not self.is_touching_both_sides():
|
983
|
+
# logger.debug("End of check shaft: don't touch both sides")
|
984
|
+
# return False
|
985
|
+
|
986
|
+
if np.isclose(0.0, self.min_dist, rtol=1e-6, atol=1e-4):
|
987
|
+
logger.debug("End of check shaft: ok (node in center)")
|
988
|
+
return True
|
889
989
|
|
890
990
|
for n in self.list_of_nodes():
|
891
991
|
a = alpha_line(center, n)
|
@@ -900,247 +1000,143 @@ class Area(object):
|
|
900
1000
|
continue
|
901
1001
|
logger.debug("End of check shaft: no")
|
902
1002
|
return False
|
1003
|
+
|
903
1004
|
logger.debug("End of check shaft: ok")
|
904
1005
|
return True
|
905
1006
|
|
906
|
-
def
|
907
|
-
lines = [
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
line_count = 1
|
913
|
-
m_first = 0.0
|
914
|
-
m_prev = 999.999999
|
915
|
-
c_prev = -99
|
916
|
-
m_all = []
|
917
|
-
for c, m, l in lines:
|
918
|
-
if c_prev >= 0:
|
919
|
-
if np.isclose(m_prev, m, atol=0.001):
|
920
|
-
if c_prev+1 != c:
|
921
|
-
# Gleiche Steigung, aber keine Verlängerung
|
922
|
-
line_count += 1
|
923
|
-
m_all.append(m_prev)
|
924
|
-
else:
|
925
|
-
line_count += 1
|
926
|
-
m_all.append(m_prev)
|
927
|
-
else:
|
928
|
-
m_first = m
|
1007
|
+
def get_magnet_line_angles(self):
|
1008
|
+
lines = [e for e in self.area if is_Line(e)]
|
1009
|
+
if len(lines) < 4:
|
1010
|
+
logger.debug("get_magnet_line_angles: only %s lines", len(lines))
|
1011
|
+
return []
|
929
1012
|
|
930
|
-
|
931
|
-
|
1013
|
+
angles = []
|
1014
|
+
prev_angle = lines[0].get_positive_angle()
|
1015
|
+
logger.debug("first angle = %s", prev_angle)
|
1016
|
+
prev_length = lines[0].length()
|
932
1017
|
|
933
|
-
|
1018
|
+
for line in lines[1:]:
|
1019
|
+
this_angle = line.get_positive_angle()
|
1020
|
+
logger.debug("next angle = %s", this_angle)
|
1021
|
+
this_length = line.length()
|
934
1022
|
|
935
|
-
|
936
|
-
|
1023
|
+
if np.isclose(prev_angle, this_angle, rtol=1e-04, atol=1e-02):
|
1024
|
+
# same direction
|
1025
|
+
prev_length += this_length
|
1026
|
+
else:
|
1027
|
+
angles.append((prev_length, prev_angle))
|
1028
|
+
prev_angle = this_angle
|
1029
|
+
prev_length = this_length
|
937
1030
|
|
938
|
-
if
|
939
|
-
logger.debug("
|
940
|
-
|
941
|
-
return False
|
942
|
-
if not np.isclose(m_all[1], m_all[3], atol=0.001):
|
943
|
-
return False
|
944
|
-
return True
|
1031
|
+
if not angles:
|
1032
|
+
logger.debug("get_magnet_line_angles: only one angle")
|
1033
|
+
return []
|
945
1034
|
|
946
|
-
|
1035
|
+
this_length, this_angle = angles[0]
|
1036
|
+
if not np.isclose(prev_angle, this_angle, rtol=1e-04, atol=1e-02):
|
1037
|
+
angles.append((prev_length, prev_angle))
|
1038
|
+
else:
|
1039
|
+
prev_length += this_length
|
1040
|
+
angles[0] = (prev_length, prev_angle)
|
947
1041
|
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
# m = Steigung
|
954
|
-
# l = Länge
|
955
|
-
# L = class Line
|
956
|
-
if len(lines_ceml) < 4:
|
957
|
-
return False
|
1042
|
+
l, first_angle = angles[0]
|
1043
|
+
l, last_angle = angles[-1]
|
1044
|
+
if np.isclose(first_angle, last_angle, rtol=1e-04, atol=1e-02):
|
1045
|
+
del angles[-1]
|
1046
|
+
return angles
|
958
1047
|
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
c_prev = lines_ceml[0][0]
|
963
|
-
a_prev = 999
|
964
|
-
p = None
|
965
|
-
|
966
|
-
e0 = lines_ceml[0][1]
|
967
|
-
e0_p1 = e0.p1
|
968
|
-
e0_p2 = e0.p2
|
969
|
-
L_prev = isinstance(e0, Line)
|
970
|
-
l_prev = lines_ceml[0][3]
|
971
|
-
m_prev = lines_ceml[0][2]
|
972
|
-
|
973
|
-
e1 = lines_ceml[1][1]
|
974
|
-
e1_p1 = e1.p1
|
975
|
-
e1_p2 = e1.p2
|
976
|
-
|
977
|
-
if (points_are_close(e0_p2, e1_p1, atol=1e-02) or
|
978
|
-
points_are_close(e0_p2, e1_p2, atol=1e-02)):
|
979
|
-
a_prev = alpha_line(e0_p1, e0_p2)
|
980
|
-
p = e0_p2
|
981
|
-
elif (points_are_close(e0_p1, e1_p1, atol=1e-02) or
|
982
|
-
points_are_close(e0_p1, e1_p2, atol=1e-02)):
|
983
|
-
a_prev = alpha_line(e0_p2, e0_p1)
|
984
|
-
p = e0_p1
|
985
|
-
else:
|
986
|
-
logger.error(
|
987
|
-
"ERROR: is_mag_rectangle(): points are not close together")
|
988
|
-
logger.error(" e0 p1={}, p2={}".format(e0_p1, e0_p2))
|
989
|
-
logger.error(" e1 p1={}, p2={}".format(e1_p1, e1_p2))
|
990
|
-
return False
|
1048
|
+
def get_magnet_phi(self, angles):
|
1049
|
+
if not angles:
|
1050
|
+
return 0.0
|
991
1051
|
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
logger.error(
|
998
|
-
"ERROR: is_mag_rectangle(): points are not close together")
|
999
|
-
logger.error(" p={}, p1={}, p2={}".format(p, e.p1, e.p2))
|
1000
|
-
return None, None, False
|
1001
|
-
|
1002
|
-
lines_clamL = []
|
1003
|
-
for c, e, m, l in lines_ceml[1:]:
|
1004
|
-
p, a_curr, L_curr = alpha_current(p, e)
|
1005
|
-
if not p:
|
1006
|
-
return False
|
1052
|
+
angles.sort(reverse=True)
|
1053
|
+
# calculate orientation (no rectangle check)
|
1054
|
+
l, alpha = angles[0]
|
1055
|
+
phi = normalise_angle(alpha + np.pi/2)
|
1056
|
+
logger.debug("alpha = %s, phi = %s", alpha, phi)
|
1007
1057
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
if c_prev+1 != c:
|
1012
|
-
logger.debug(" - ok, but not an extension")
|
1013
|
-
# ..., but not an extension
|
1014
|
-
lines_clamL.append([c_prev, l_prev, a_prev, m])
|
1015
|
-
l_prev = e.length()
|
1016
|
-
else:
|
1017
|
-
# ... and an extension
|
1018
|
-
l_prev += e.length()
|
1019
|
-
logger.debug(" - ok, it's an extension")
|
1020
|
-
else:
|
1021
|
-
# it's a different angle
|
1022
|
-
logger.debug(" - diff, angle {} and {} not equal "
|
1023
|
-
.format(a_prev, a_curr))
|
1024
|
-
lines_clamL.append([c_prev, l_prev, a_prev, m_prev, L_prev])
|
1025
|
-
l_prev = e.length()
|
1026
|
-
|
1027
|
-
a_prev = a_curr
|
1028
|
-
L_prev = L_curr
|
1029
|
-
m_prev = m
|
1030
|
-
c_prev = c
|
1031
|
-
|
1032
|
-
lines_clamL.append([c_prev, l_prev, a_prev, m_prev, L_prev])
|
1033
|
-
if np.isclose(lines_clamL[0][2], lines_clamL[-1][2], atol=0.001):
|
1034
|
-
# Gleicher Winkel am Anfang und am Ende
|
1035
|
-
lines_clamL[0][1] += lines_clamL[-1][1] # length
|
1036
|
-
del lines_clamL[-1]
|
1037
|
-
logger.debug(" > last entry deleted")
|
1038
|
-
|
1039
|
-
if len(lines_clamL) < 4:
|
1040
|
-
logger.debug("=== END OF is_mag_rectangle(): NO RECTANGLE #1")
|
1041
|
-
return False
|
1058
|
+
mid = middle_angle(self.min_angle, self.max_angle)
|
1059
|
+
angle = alpha_angle(mid, phi)
|
1060
|
+
logger.debug("phi=%s, mid=%s, angle=%s", phi, mid, angle)
|
1042
1061
|
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
if not np.isclose(lines_lmcL[0][1], lines_lmcL[1][1], atol=0.05):
|
1047
|
-
# Die Steigungen der zwei längsten Linien müssen gleich sein
|
1048
|
-
logger.debug("--- m %s <> %s ---",
|
1049
|
-
lines_lmcL[0][1],
|
1050
|
-
lines_lmcL[1][1])
|
1051
|
-
logger.debug("--- l %s, %s, %s ---",
|
1052
|
-
lines_lmcL[0][0],
|
1053
|
-
lines_lmcL[1][0],
|
1054
|
-
lines_lmcL[2][0])
|
1055
|
-
logger.debug("=== END OF is_mag_rectangle(): NO RECTANGLE #2")
|
1056
|
-
return False
|
1062
|
+
if greater(angle, np.pi * 0.5, rtol=1e-5) and \
|
1063
|
+
less(angle, np.pi * 1.5, rtol=1e-5):
|
1064
|
+
phi = normalise_angle(phi + np.pi)
|
1057
1065
|
|
1058
|
-
|
1059
|
-
|
1060
|
-
return False
|
1066
|
+
logger.debug("phi of magnet %s is %s", self.identifier(), phi)
|
1067
|
+
return phi
|
1061
1068
|
|
1062
|
-
|
1063
|
-
|
1069
|
+
def get_magnet_orientation(self):
|
1070
|
+
logger.debug("get magnet orientation for %s", self.identifier())
|
1071
|
+
if self.is_type(TYPE_MAGNET_RECT):
|
1072
|
+
angles = self.get_magnet_line_angles()
|
1073
|
+
return self.get_magnet_phi(angles)
|
1064
1074
|
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
if alpha < np.pi:
|
1070
|
-
return False
|
1075
|
+
if self.is_type(TYPE_MAGNET_AIRGAP):
|
1076
|
+
if self.close_to_endangle:
|
1077
|
+
if self.close_to_startangle:
|
1078
|
+
return middle_angle(self.min_angle, self.max_angle)
|
1071
1079
|
else:
|
1072
|
-
|
1073
|
-
|
1074
|
-
angle_prev = angle_curr
|
1075
|
-
return True # end of all_lines_with_same_direction()
|
1080
|
+
return self.max_angle
|
1081
|
+
return middle_angle(self.min_angle, self.max_angle)
|
1076
1082
|
|
1077
|
-
|
1078
|
-
lines_cmL.sort()
|
1083
|
+
return 0.0
|
1079
1084
|
|
1080
|
-
|
1081
|
-
|
1082
|
-
logger.debug("=== END OF is_mag_rectangle(): not 2 lines #1")
|
1083
|
-
return False
|
1084
|
-
ok = excursion_to_same_direction(lines_clamL)
|
1085
|
-
logger.debug("=== END OF is_mag_rectangle(): OK = {} #1"
|
1086
|
-
.format(ok))
|
1087
|
-
return ok
|
1088
|
-
if np.isclose(lines_cmL[1][1], lines_cmL[3][1], atol=0.001):
|
1089
|
-
if not (lines_cmL[1][2] and lines_cmL[3][2]):
|
1090
|
-
logger.debug("=== END OF is_mag_rectangle(): not 2 lines #2")
|
1091
|
-
return False
|
1085
|
+
def is_magnet_rectangle(self):
|
1086
|
+
angles = self.get_magnet_line_angles()
|
1092
1087
|
|
1093
|
-
|
1094
|
-
logger.debug("
|
1095
|
-
|
1096
|
-
return ok
|
1088
|
+
if len(angles) != 4:
|
1089
|
+
logger.debug("is_magnet_rectangle: %s angles, not 4", len(angles))
|
1090
|
+
return False
|
1097
1091
|
|
1098
|
-
|
1099
|
-
|
1092
|
+
for l, a in angles:
|
1093
|
+
logger.debug("+ magnet_rectangle: alpha=%s, length=%s", a, l)
|
1100
1094
|
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
lines.sort()
|
1106
|
-
|
1107
|
-
m_prev = 999.999999
|
1108
|
-
a_prev = 0.0
|
1109
|
-
l_total = 0.0
|
1110
|
-
line_length = []
|
1111
|
-
for m, l, a in lines:
|
1112
|
-
if np.isclose(m_prev, m):
|
1113
|
-
l_total += l
|
1114
|
-
else:
|
1115
|
-
if l_total > 0.0:
|
1116
|
-
line_length.append((l_total, m_prev, a_prev))
|
1117
|
-
l_total = l
|
1118
|
-
m_prev = m
|
1119
|
-
a_prev = a
|
1120
|
-
|
1121
|
-
if l_total > 0.0:
|
1122
|
-
line_length.append((l_total, m_prev, a_prev))
|
1123
|
-
line_length.sort(reverse=True)
|
1124
|
-
|
1125
|
-
alpha = line_length[0][2]
|
1126
|
-
if alpha < 0.0:
|
1127
|
-
alpha += np.pi
|
1128
|
-
alpha = alpha + np.pi/2
|
1129
|
-
if alpha > np.pi:
|
1130
|
-
alpha = alpha - np.pi
|
1131
|
-
return alpha
|
1132
|
-
|
1133
|
-
def get_mag_orientation(self):
|
1134
|
-
if self.mag_rectangle:
|
1135
|
-
return self.get_mag_orient_rectangle()
|
1095
|
+
length_0, angle_0 = angles[0]
|
1096
|
+
length_1, angle_1 = angles[1]
|
1097
|
+
length_2, angle_2 = angles[2]
|
1098
|
+
length_3, angle_3 = angles[3]
|
1136
1099
|
|
1137
|
-
if
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1100
|
+
if not np.isclose(angle_0, angle_2, rtol=1e-03, atol=0.05):
|
1101
|
+
logger.debug("is_magnet_rectangle: angles %s and %s not equal",
|
1102
|
+
angle_0, angle_2)
|
1103
|
+
return False
|
1104
|
+
|
1105
|
+
if not np.isclose(angle_1, angle_3, rtol=1e-03, atol=0.05):
|
1106
|
+
logger.debug("is_magnet_rectangle: angles %s and %s not equal",
|
1107
|
+
angle_1, angle_3)
|
1108
|
+
return False
|
1109
|
+
|
1110
|
+
if angle_0 > angle_1:
|
1111
|
+
a0 = angle_0
|
1112
|
+
a1 = angle_1 + np.pi/2
|
1142
1113
|
else:
|
1143
|
-
|
1114
|
+
a0 = angle_1
|
1115
|
+
a1 = angle_0 + np.pi/2
|
1116
|
+
if not np.isclose(a0, a1, rtol=1e-03, atol=0.05):
|
1117
|
+
logger.debug("is_magnet_rectangle: not a rectange (%s neq %s)", a0, a1)
|
1118
|
+
return False
|
1119
|
+
|
1120
|
+
turn_left = False
|
1121
|
+
turn_right = False
|
1122
|
+
for n1, n2, e in self.list_of_elements():
|
1123
|
+
if is_Arc(e):
|
1124
|
+
if e.get_node_number(n1) == 1:
|
1125
|
+
turn_left = True
|
1126
|
+
else:
|
1127
|
+
turn_right = True
|
1128
|
+
|
1129
|
+
if turn_left and turn_right:
|
1130
|
+
logger.debug("is_magnet_rectangle: arcs with different directions")
|
1131
|
+
return False
|
1132
|
+
|
1133
|
+
self.phi = self.get_magnet_phi(angles)
|
1134
|
+
angles.sort()
|
1135
|
+
l, alpha = angles[0]
|
1136
|
+
self.mag_width = l
|
1137
|
+
logger.debug("Area %s is a rectangle with phi %s",
|
1138
|
+
self.identifier(), self.phi)
|
1139
|
+
return True
|
1144
1140
|
|
1145
1141
|
def around_windings(self, areas, geom):
|
1146
1142
|
for a in areas:
|
@@ -1164,6 +1160,10 @@ class Area(object):
|
|
1164
1160
|
return True
|
1165
1161
|
return False
|
1166
1162
|
|
1163
|
+
def is_close_to_border(self, angle, border_angle):
|
1164
|
+
return np.isclose(angle, border_angle,
|
1165
|
+
rtol=1e-03, atol=1e-03)
|
1166
|
+
|
1167
1167
|
def mark_stator_subregions(self,
|
1168
1168
|
is_inner,
|
1169
1169
|
stator_size,
|
@@ -1175,7 +1175,7 @@ class Area(object):
|
|
1175
1175
|
alpha = round(alpha, 6)
|
1176
1176
|
|
1177
1177
|
if self.is_circle():
|
1178
|
-
self.type =
|
1178
|
+
self.type = TYPE_AIR # air
|
1179
1179
|
return self.type
|
1180
1180
|
|
1181
1181
|
ag_delta = (r_out - r_in) / 500.0
|
@@ -1216,24 +1216,24 @@ class Area(object):
|
|
1216
1216
|
|
1217
1217
|
if self.has_iron_separator():
|
1218
1218
|
logger.debug("***** iron (has iron separator)\n")
|
1219
|
-
self.type =
|
1219
|
+
self.type = TYPE_IRON # iron
|
1220
1220
|
return self.type
|
1221
1221
|
|
1222
1222
|
if is_inner:
|
1223
1223
|
# looking for shaft
|
1224
1224
|
if close_to_opposition and not self.close_to_ag:
|
1225
1225
|
if self.is_shaft_area(center):
|
1226
|
-
self.type =
|
1226
|
+
self.type = TYPE_SHAFT # shaft
|
1227
1227
|
logger.debug("***** shaft (close to opposition)\n")
|
1228
1228
|
return self.type
|
1229
1229
|
|
1230
1230
|
if close_to_opposition:
|
1231
|
-
self.type =
|
1231
|
+
self.type = TYPE_YOKE # iron yoke (Joch)
|
1232
1232
|
logger.debug("***** iron yoke #1\n")
|
1233
1233
|
return self.type
|
1234
1234
|
|
1235
1235
|
if self.close_to_startangle and self.close_to_endangle:
|
1236
|
-
self.type =
|
1236
|
+
self.type = TYPE_YOKE # iron yoke (Joch)
|
1237
1237
|
logger.debug("***** iron yoke #2\n")
|
1238
1238
|
return self.type
|
1239
1239
|
|
@@ -1250,21 +1250,21 @@ class Area(object):
|
|
1250
1250
|
|
1251
1251
|
if self.alpha / air_alpha > 2:
|
1252
1252
|
logger.debug("***** windings near airgap\n")
|
1253
|
-
self.type =
|
1253
|
+
self.type = TYPE_WINDINGS # windings
|
1254
1254
|
else:
|
1255
|
-
self.type =
|
1255
|
+
self.type = TYPE_AIR_OR_IRON # air or iron near windings and near airgap?
|
1256
1256
|
logger.debug("***** air or iron ??\n")
|
1257
1257
|
return self.type
|
1258
1258
|
|
1259
1259
|
if self.close_to_startangle:
|
1260
1260
|
if self.is_half_circle(center, self.min_angle):
|
1261
|
-
self.type =
|
1261
|
+
self.type = TYPE_AIR # air
|
1262
1262
|
logger.debug("***** air (part of a circle)\n")
|
1263
1263
|
return self.type
|
1264
1264
|
|
1265
1265
|
if self.close_to_endangle:
|
1266
1266
|
if self.is_half_circle(center, self.max_angle):
|
1267
|
-
self.type =
|
1267
|
+
self.type = TYPE_AIR # air
|
1268
1268
|
logger.debug("***** air (part of a circle)\n")
|
1269
1269
|
return self.type
|
1270
1270
|
|
@@ -1282,32 +1282,32 @@ class Area(object):
|
|
1282
1282
|
if self.min_angle > 0.001:
|
1283
1283
|
if self.max_angle < alpha - 0.001:
|
1284
1284
|
if bad_winding_position():
|
1285
|
-
self.type =
|
1285
|
+
self.type = TYPE_WINDINGS_OR_AIR # windings or air
|
1286
1286
|
logger.debug("***** windings or air #1\n")
|
1287
1287
|
else:
|
1288
|
-
self.type =
|
1288
|
+
self.type = TYPE_WINDINGS # windings
|
1289
1289
|
logger.debug("***** windings #1\n")
|
1290
1290
|
return self.type
|
1291
1291
|
if mirrored:
|
1292
1292
|
if bad_winding_position():
|
1293
|
-
self.type =
|
1293
|
+
self.type = TYPE_WINDINGS_OR_AIR # windings or air
|
1294
1294
|
logger.debug("***** windings or air #2\n")
|
1295
1295
|
else:
|
1296
|
-
self.type =
|
1296
|
+
self.type = TYPE_WINDINGS # windings
|
1297
1297
|
logger.debug("***** windings #2\n")
|
1298
1298
|
return self.type
|
1299
1299
|
|
1300
|
-
self.type =
|
1300
|
+
self.type = TYPE_AIR # air
|
1301
1301
|
logger.debug("***** air #3")
|
1302
1302
|
|
1303
1303
|
if self.close_to_startangle or self.close_to_endangle:
|
1304
1304
|
f = self.surface / stator_size
|
1305
1305
|
if f < 0.02: # area_size less then 2 percent of stator size
|
1306
1306
|
# Luftloch
|
1307
|
-
self.type =
|
1307
|
+
self.type = TYPE_AIR # air
|
1308
1308
|
logger.debug("***** small area => air\n")
|
1309
1309
|
else:
|
1310
|
-
self.type =
|
1310
|
+
self.type = TYPE_AIR_OR_IRON # air or iron near windings and near airgap?
|
1311
1311
|
logger.debug("***** air or iron close to border\n")
|
1312
1312
|
return self.type
|
1313
1313
|
|
@@ -1315,32 +1315,34 @@ class Area(object):
|
|
1315
1315
|
return 0
|
1316
1316
|
|
1317
1317
|
def mark_rotor_subregions(self, is_inner, mirrored, alpha,
|
1318
|
-
center, r_in, r_out
|
1318
|
+
center, r_in, r_out,
|
1319
|
+
startangle,
|
1320
|
+
endangle):
|
1319
1321
|
logger.debug("mark_rotor_subregions")
|
1320
1322
|
|
1321
1323
|
alpha = round(alpha, 6)
|
1322
1324
|
|
1323
1325
|
if self.is_circle():
|
1324
|
-
self.type =
|
1326
|
+
self.type = TYPE_AIR # air
|
1325
1327
|
logger.debug(">>> air is a circle")
|
1326
1328
|
return self.type
|
1327
1329
|
|
1328
1330
|
if is_inner:
|
1329
|
-
self.close_to_ag = np.isclose(r_out, self.max_dist, atol=0.005)
|
1331
|
+
self.close_to_ag = np.isclose(r_out, self.max_dist, rtol=1e-9, atol=0.005)
|
1330
1332
|
close_to_opposition = greater_equal(r_in * 1.05, self.min_dist)
|
1331
1333
|
airgap_radius = r_out
|
1332
1334
|
opposite_radius = r_in
|
1333
1335
|
airgap_toleranz = -(self.max_dist - self.min_dist) / 50.0 # 2%
|
1334
1336
|
else:
|
1335
|
-
self.close_to_ag = np.isclose(r_in, self.min_dist, atol=0.005)
|
1337
|
+
self.close_to_ag = np.isclose(r_in, self.min_dist, rtol=1e-9, atol=0.005)
|
1336
1338
|
close_to_opposition = greater_equal(self.max_dist * 1.05, r_out)
|
1337
1339
|
airgap_radius = r_in
|
1338
1340
|
opposite_radius = r_out
|
1339
1341
|
airgap_toleranz = (self.max_dist - self.min_dist) / 50.0 # 2%
|
1340
1342
|
|
1341
|
-
self.close_to_startangle = np.isclose(self.min_angle,
|
1343
|
+
self.close_to_startangle = np.isclose(self.min_angle, startangle,
|
1342
1344
|
1e-04, 1e-04)
|
1343
|
-
self.close_to_endangle = np.isclose(self.max_angle,
|
1345
|
+
self.close_to_endangle = np.isclose(self.max_angle, endangle,
|
1344
1346
|
1e-04, 1e-04)
|
1345
1347
|
|
1346
1348
|
logger.debug("\n***** mark_rotor_subregions [{}] *****"
|
@@ -1359,28 +1361,29 @@ class Area(object):
|
|
1359
1361
|
|
1360
1362
|
if self.has_iron_separator():
|
1361
1363
|
logger.debug("***** iron (has iron separator)\n")
|
1362
|
-
self.type =
|
1364
|
+
self.type = TYPE_IRON # iron
|
1363
1365
|
return self.type
|
1364
1366
|
|
1365
1367
|
if is_inner:
|
1366
1368
|
# looking for shaft
|
1367
1369
|
if close_to_opposition and not self.close_to_ag:
|
1370
|
+
logger.debug("-- check for shaft")
|
1368
1371
|
if self.is_shaft_area(center):
|
1369
|
-
self.type =
|
1372
|
+
self.type = TYPE_SHAFT # shaft
|
1370
1373
|
logger.debug("***** shaft (close to opposition)\n")
|
1371
1374
|
return self.type
|
1372
1375
|
|
1373
1376
|
if close_to_opposition:
|
1374
|
-
self.type =
|
1377
|
+
self.type = TYPE_IRON # iron
|
1375
1378
|
logger.debug("***** iron (close to opposition)\n")
|
1376
1379
|
return self.type
|
1377
1380
|
|
1378
1381
|
if self.close_to_startangle and self.close_to_endangle:
|
1379
|
-
self.type =
|
1382
|
+
self.type = TYPE_IRON # iron
|
1380
1383
|
logger.debug("***** iron (close to both sides)\n")
|
1381
1384
|
return self.type
|
1382
1385
|
|
1383
|
-
self.mag_rectangle = self.
|
1386
|
+
self.mag_rectangle = self.is_magnet_rectangle()
|
1384
1387
|
|
1385
1388
|
if self.close_to_ag:
|
1386
1389
|
mm = self.minmax_angle_dist_from_center(center,
|
@@ -1389,47 +1392,50 @@ class Area(object):
|
|
1389
1392
|
air_alpha = round(alpha_angle(mm[0], mm[1]), 3)
|
1390
1393
|
logger.debug(" - air_alpha : {}".format(air_alpha))
|
1391
1394
|
|
1395
|
+
if self.mag_rectangle:
|
1396
|
+
self.type = TYPE_MAGNET_RECT_NEAR_AIRGAP # magnet near airgap
|
1397
|
+
logger.debug("***** magnet (airgap, embedded, phi={})\n".
|
1398
|
+
format(self.phi))
|
1399
|
+
return self.type
|
1400
|
+
|
1392
1401
|
if air_alpha / alpha < 0.2:
|
1393
|
-
self.
|
1394
|
-
self.type = 8 # air or magnet ?
|
1402
|
+
self.type = TYPE_MAGNET_OR_AIR # air or magnet ?
|
1395
1403
|
logger.debug("***** air #1 (close to airgap)\n")
|
1396
1404
|
return self.type
|
1397
1405
|
|
1398
1406
|
if air_alpha / alpha > 0.6:
|
1399
|
-
self.
|
1400
|
-
self.type = 3 # magnet
|
1407
|
+
self.type = TYPE_MAGNET_AIRGAP # magnet (no rectangle)
|
1401
1408
|
logger.debug("***** magnet (close to airgap)\n")
|
1402
1409
|
else:
|
1403
|
-
self.
|
1404
|
-
self.type = 9 # iron or magnet ?
|
1410
|
+
self.type = TYPE_MAGNET_OR_IRON # iron or magnet ?
|
1405
1411
|
logger.debug("***** iron or magnet(close to airgap)\n")
|
1406
1412
|
return self.type
|
1407
1413
|
|
1408
1414
|
if self.mag_rectangle:
|
1409
|
-
|
1410
|
-
self.type =
|
1415
|
+
# phi is already calculated and set
|
1416
|
+
self.type = TYPE_MAGNET_RECT # magnet embedded
|
1411
1417
|
logger.debug("***** magnet (embedded, phi={})\n".format(
|
1412
1418
|
self.phi))
|
1413
1419
|
return self.type
|
1414
1420
|
|
1415
1421
|
if not (self.close_to_startangle or self.close_to_endangle):
|
1416
|
-
self.type =
|
1422
|
+
self.type = TYPE_AIR # air
|
1417
1423
|
logger.debug("***** air (somewhere)\n")
|
1418
1424
|
return self.type
|
1419
1425
|
|
1420
1426
|
if self.close_to_startangle:
|
1421
1427
|
if self.is_half_circle(center, self.min_angle):
|
1422
|
-
self.type =
|
1428
|
+
self.type = TYPE_AIR # air
|
1423
1429
|
logger.debug("***** air (part of a circle)\n")
|
1424
1430
|
return self.type
|
1425
1431
|
|
1426
1432
|
if self.close_to_endangle:
|
1427
1433
|
if self.is_half_circle(center, self.max_angle):
|
1428
|
-
self.type =
|
1434
|
+
self.type = TYPE_AIR # air
|
1429
1435
|
logger.debug("***** air (part of a circle)\n")
|
1430
1436
|
return self.type
|
1431
1437
|
|
1432
|
-
self.type =
|
1438
|
+
self.type = TYPE_AIR # air
|
1433
1439
|
logger.debug("***** air (remains)\n")
|
1434
1440
|
return self.type
|
1435
1441
|
|
@@ -1438,33 +1444,32 @@ class Area(object):
|
|
1438
1444
|
logger.debug("mark_unknown_subregions")
|
1439
1445
|
|
1440
1446
|
if self.is_circle():
|
1441
|
-
self.type =
|
1447
|
+
self.type = TYPE_AIR # air
|
1442
1448
|
logger.debug(">>> air is a circle")
|
1443
1449
|
return self.type
|
1444
1450
|
|
1445
1451
|
self.close_to_startangle = np.isclose(self.min_angle, 0.0)
|
1446
1452
|
self.close_to_endangle = np.isclose(self.max_angle, alpha)
|
1447
1453
|
|
1448
|
-
if self.
|
1449
|
-
self.type =
|
1454
|
+
if self.is_magnet_rectangle():
|
1455
|
+
self.type = TYPE_MAGNET_RECT # magnet embedded
|
1450
1456
|
logger.debug(">>> magnet embedded")
|
1451
|
-
self.phi = self.get_mag_orient_rectangle()
|
1452
1457
|
return self.type
|
1453
1458
|
|
1454
1459
|
close_to_max_radius = np.isclose(r_out, self.max_dist)
|
1455
1460
|
close_to_min_radius = np.isclose(r_in, self.min_dist)
|
1456
1461
|
|
1457
1462
|
if close_to_max_radius and close_to_min_radius:
|
1458
|
-
self.type =
|
1463
|
+
self.type = TYPE_IRON # iron
|
1459
1464
|
logger.debug(">>> iron close to min- and max-radius")
|
1460
1465
|
return self.type
|
1461
1466
|
|
1462
1467
|
if self.close_to_startangle and self.close_to_endangle:
|
1463
|
-
self.type =
|
1468
|
+
self.type = TYPE_IRON # iron
|
1464
1469
|
logger.debug(">>> iron close to start- and end-angle")
|
1465
1470
|
return self.type
|
1466
1471
|
|
1467
|
-
self.type =
|
1472
|
+
self.type = TYPE_AIR # air
|
1468
1473
|
logger.debug(">>> air remains")
|
1469
1474
|
return self.type
|
1470
1475
|
|
@@ -1551,74 +1556,6 @@ class Area(object):
|
|
1551
1556
|
for i in a.nested_areas_inside():
|
1552
1557
|
yield i
|
1553
1558
|
|
1554
|
-
def crunch_area(self, geom):
|
1555
|
-
n1_prev = None
|
1556
|
-
e_prev = None
|
1557
|
-
logger.debug("crunch area %s", self.identifier())
|
1558
|
-
|
1559
|
-
if self.is_circle():
|
1560
|
-
return 0
|
1561
|
-
|
1562
|
-
c = 0
|
1563
|
-
for n1, n2, e in self.list_of_elements():
|
1564
|
-
if e_prev is not None:
|
1565
|
-
if len([nbr for nbr in geom.g.neighbors(n1)]) == 2:
|
1566
|
-
e_new = e_prev.concatenate(n1_prev, n2, e)
|
1567
|
-
if e_new is not None:
|
1568
|
-
e_prev_dict = geom.g.get_edge_data(n1_prev, n1)
|
1569
|
-
e_dict = geom.g.get_edge_data(n1, n2)
|
1570
|
-
|
1571
|
-
logger.debug("--> remove from %s to %s [%s, %s, %s]",
|
1572
|
-
n1_prev,
|
1573
|
-
n1,
|
1574
|
-
e_prev_dict[0],
|
1575
|
-
e_prev_dict[1],
|
1576
|
-
e_prev_dict[2])
|
1577
|
-
logger.debug(" remove %s", e_prev)
|
1578
|
-
geom.remove_edge(e_prev)
|
1579
|
-
|
1580
|
-
logger.debug("--> remove from %s to %s [%s, %s, %s]",
|
1581
|
-
n1,
|
1582
|
-
n2,
|
1583
|
-
e_dict[0],
|
1584
|
-
e_dict[1],
|
1585
|
-
e_dict[2])
|
1586
|
-
logger.debug(" remove %s", e)
|
1587
|
-
if e.get_node_number(n1) == 1:
|
1588
|
-
flag1 = e_dict[1]
|
1589
|
-
flag2 = e_dict[2]
|
1590
|
-
else:
|
1591
|
-
flag1 = e_dict[2]
|
1592
|
-
flag2 = e_dict[1]
|
1593
|
-
geom.remove_edge(e)
|
1594
|
-
|
1595
|
-
logger.debug("--> add from %s to %s",
|
1596
|
-
n1_prev,
|
1597
|
-
n2)
|
1598
|
-
logger.debug(" add %s", e_new)
|
1599
|
-
geom.add_edge(n1_prev, n2, e_new)
|
1600
|
-
|
1601
|
-
e_new_dict = geom.g.get_edge_data(n1_prev, n2)
|
1602
|
-
e_new_dict[0] = True
|
1603
|
-
if e_new.get_node_number(n1_prev) == 1:
|
1604
|
-
e_new_dict[1] = flag1
|
1605
|
-
e_new_dict[2] = flag2
|
1606
|
-
else:
|
1607
|
-
e_new_dict[1] = flag2
|
1608
|
-
e_new_dict[2] = flag1
|
1609
|
-
|
1610
|
-
logger.debug(" new dict: [%s, %s, %s]",
|
1611
|
-
e_new_dict[0],
|
1612
|
-
e_new_dict[1],
|
1613
|
-
e_new_dict[2])
|
1614
|
-
e_prev = e_new
|
1615
|
-
c += 1
|
1616
|
-
continue
|
1617
|
-
|
1618
|
-
n1_prev = n1
|
1619
|
-
e_prev = e
|
1620
|
-
return c
|
1621
|
-
|
1622
1559
|
def __str__(self):
|
1623
1560
|
return "Area {}\n".format(self.id) + \
|
1624
1561
|
"distance...............: from {} to {}\n".\
|