femagtools 1.8.17__py3-none-any.whl → 1.8.18__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/dxfsl/area.py +35 -23
- femagtools/dxfsl/areabuilder.py +69 -46
- femagtools/dxfsl/converter.py +9 -1
- femagtools/dxfsl/geom.py +233 -56
- femagtools/dxfsl/machine.py +28 -8
- femagtools/dxfsl/symmetry.py +20 -5
- femagtools/femag.py +27 -16
- femagtools/machine/__init__.py +2 -0
- femagtools/machine/effloss.py +10 -4
- femagtools/machine/pm.py +72 -68
- femagtools/machine/sm.py +15 -15
- femagtools/plot/bch.py +3 -1
- femagtools/plot/char.py +5 -16
- femagtools/plot/nc.py +67 -34
- femagtools/shortcircuit.py +10 -3
- femagtools/utils.py +5 -4
- {femagtools-1.8.17.dist-info → femagtools-1.8.18.dist-info}/METADATA +2 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.18.dist-info}/RECORD +25 -25
- tests/test_machine.py +1 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.18.dist-info}/WHEEL +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.18.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.18.dist-info}/licenses/LICENSE +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.18.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py
CHANGED
@@ -35,7 +35,7 @@ from .functions import middle_angle, positive_angle
|
|
35
35
|
from .functions import normalise_angle, is_same_angle
|
36
36
|
from .functions import part_of_circle, gcd
|
37
37
|
from .functions import point_on_arc, points_on_line, nodes_are_equal
|
38
|
-
from .functions import area_size
|
38
|
+
from .functions import area_size, get_angle_of_arc
|
39
39
|
import io
|
40
40
|
import time
|
41
41
|
|
@@ -401,11 +401,11 @@ class Geometry(object):
|
|
401
401
|
for n in self.g.nodes()}
|
402
402
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
403
403
|
|
404
|
-
def
|
404
|
+
def get_rotated_nodes(self, alpha, nodes):
|
405
405
|
T = np.array(((np.cos(alpha), -np.sin(alpha)),
|
406
406
|
(np.sin(alpha), np.cos(alpha))))
|
407
|
-
|
408
|
-
return
|
407
|
+
nodes = [T.dot(np.array((n[0], n[1]))).tolist() for n in nodes]
|
408
|
+
return nodes
|
409
409
|
|
410
410
|
def rotate(self, alpha):
|
411
411
|
"""rotates all objects by angle alpha"""
|
@@ -1142,20 +1142,30 @@ class Geometry(object):
|
|
1142
1142
|
rtol=self.rtol,
|
1143
1143
|
atol=self.atol)
|
1144
1144
|
|
1145
|
-
def get_corner_nodes(self, center, angle):
|
1146
|
-
rtol = 1e-4
|
1147
|
-
atol = 1e-4
|
1148
|
-
|
1145
|
+
def get_corner_nodes(self, center, angle, rtol=1e-4, atol=1e-4):
|
1149
1146
|
center_added, corners = self.get_corner_list(center, angle, rtol, atol)
|
1150
1147
|
if len(corners) < 2:
|
1151
1148
|
return () # not enough corners
|
1152
1149
|
return (corners[0].point(), corners[len(corners)-1].point())
|
1153
1150
|
|
1154
|
-
def set_start_corners(self, center, angle):
|
1155
|
-
self.start_corners = self.get_corner_nodes(center, angle)
|
1151
|
+
def set_start_corners(self, center, angle, rtol=1e-4, atol=1e-4):
|
1152
|
+
self.start_corners = self.get_corner_nodes(center, angle, rtol=rtol, atol=atol)
|
1153
|
+
|
1154
|
+
def set_end_corners(self, center, angle, rtol=1e-4, atol=1e-4):
|
1155
|
+
self.end_corners = self.get_corner_nodes(center, angle, rtol=rtol, atol=atol)
|
1156
1156
|
|
1157
|
-
def
|
1158
|
-
|
1157
|
+
def set_virtual_start_end_corners(self):
|
1158
|
+
assert(not self.start_corners)
|
1159
|
+
assert(not self.end_corners)
|
1160
|
+
|
1161
|
+
dist_list = [(distance(self.center, n), n) for n in self.nodes()]
|
1162
|
+
dist_list.sort()
|
1163
|
+
d1, c1 = dist_list[0]
|
1164
|
+
d2, c2 = dist_list[-1]
|
1165
|
+
corners = (c1, c2)
|
1166
|
+
self.start_corners = corners
|
1167
|
+
self.end_corners = corners
|
1168
|
+
return
|
1159
1169
|
|
1160
1170
|
def get_angle(self, alpha1, alpha2):
|
1161
1171
|
if np.isclose(alpha1, alpha2, 0.001, 0.001):
|
@@ -1904,6 +1914,19 @@ class Geometry(object):
|
|
1904
1914
|
self.area_list = []
|
1905
1915
|
return nodes_deleted > 0
|
1906
1916
|
|
1917
|
+
def delete_needless_elements(self, radius):
|
1918
|
+
self.area_list = []
|
1919
|
+
for e in self.elements():
|
1920
|
+
if greater(distance(self.center, e.p1), radius):
|
1921
|
+
self.remove_edge(e)
|
1922
|
+
elif greater(distance(self.center, e.p2), radius):
|
1923
|
+
self.remove_edge(e)
|
1924
|
+
elif is_Arc(e):
|
1925
|
+
p = e.center_of_connection()
|
1926
|
+
if greater(distance(self.center, p), radius):
|
1927
|
+
self.remove_edge(e)
|
1928
|
+
self.delete_all_appendices()
|
1929
|
+
|
1907
1930
|
def render_areagroups(self, renderer):
|
1908
1931
|
if not self.areagroup_list:
|
1909
1932
|
return
|
@@ -2036,11 +2059,47 @@ class Geometry(object):
|
|
2036
2059
|
return c
|
2037
2060
|
return None
|
2038
2061
|
|
2062
|
+
def check_hull_radius(self, center, radius, hull_points):
|
2063
|
+
logger.debug("check_hull_radius")
|
2064
|
+
min_r = radius
|
2065
|
+
max_r = radius
|
2066
|
+
for p in hull_points:
|
2067
|
+
d = round(distance(center, p), 2)
|
2068
|
+
min_r = min(min_r, d)
|
2069
|
+
max_r = max(max_r, d)
|
2070
|
+
|
2071
|
+
if min_r > radius * 0.8:
|
2072
|
+
# radius is ok, adjust hill line
|
2073
|
+
return True, max_r > radius
|
2074
|
+
|
2075
|
+
return False, False
|
2076
|
+
|
2039
2077
|
def get_machine_part(self, mm):
|
2040
2078
|
logger.debug("*** Begin of get_machine_part() ***")
|
2041
2079
|
|
2042
2080
|
h_points = [h for h in convex_hull(self.virtual_nodes())]
|
2043
|
-
center = self.
|
2081
|
+
center, radius = self.get_center_arcs(mm)
|
2082
|
+
if center and radius:
|
2083
|
+
center_left = round(center[0] - mm[0], 4)
|
2084
|
+
center_right = round(mm[1] - center[0], 4)
|
2085
|
+
center_down = round(center[1] - mm[2], 4)
|
2086
|
+
center_up = round(mm[3] - center[1], 4)
|
2087
|
+
min_r = min(center_left, center_right, center_up, center_down)
|
2088
|
+
max_r = max(center_left, center_right, center_up, center_down)
|
2089
|
+
is_full = min_r > max_r / 2
|
2090
|
+
|
2091
|
+
ok, adjust_hull = self.check_hull_radius(center, radius, h_points)
|
2092
|
+
if is_full and ok:
|
2093
|
+
self.set_center([round(center[0], 8), round(center[1], 8)])
|
2094
|
+
self.area_list = []
|
2095
|
+
machine = Machine(self,
|
2096
|
+
radius=radius,
|
2097
|
+
startangle=0.0,
|
2098
|
+
endangle=0.0)
|
2099
|
+
return machine
|
2100
|
+
|
2101
|
+
center = self.get_center(center, h_points, mm)
|
2102
|
+
|
2044
2103
|
logger.debug(" - Center is %s", center)
|
2045
2104
|
|
2046
2105
|
min_radius = 99999
|
@@ -2259,9 +2318,14 @@ class Geometry(object):
|
|
2259
2318
|
def is_same_center(self, center_lst, center, rtol, atol):
|
2260
2319
|
for c in center_lst:
|
2261
2320
|
if points_are_close(c['center'], center['center'], rtol, atol):
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2321
|
+
new_radius, new_phi = center['radiuslist'][0]
|
2322
|
+
c_radiuslist = [r for r, p in c['radiuslist']]
|
2323
|
+
try:
|
2324
|
+
i = c_radiuslist.index(new_radius)
|
2325
|
+
c_radius, c_phi = c['radiuslist'][i]
|
2326
|
+
c['radiuslist'][i][1] = c_phi + new_phi
|
2327
|
+
except:
|
2328
|
+
c['radiuslist'].append([new_radius, new_phi])
|
2265
2329
|
c['count'] = c['count'] + 1
|
2266
2330
|
return True
|
2267
2331
|
return False
|
@@ -2283,7 +2347,6 @@ class Geometry(object):
|
|
2283
2347
|
return None
|
2284
2348
|
cy_list = [(c['center'][0], c) for c in c_list]
|
2285
2349
|
cy_list.sort()
|
2286
|
-
[logger.info("y=%s, c=%s", y, c) for y, c in cy_list]
|
2287
2350
|
y, c = cy_list[0]
|
2288
2351
|
return c
|
2289
2352
|
|
@@ -2302,14 +2365,23 @@ class Geometry(object):
|
|
2302
2365
|
return True
|
2303
2366
|
return False
|
2304
2367
|
|
2368
|
+
def get_best_radius(radiuslist):
|
2369
|
+
radiuslist.sort(reverse=True)
|
2370
|
+
r1, phi1 = radiuslist[0]
|
2371
|
+
for r2, phi2 in radiuslist[1:]:
|
2372
|
+
if phi2 > phi1:
|
2373
|
+
return r2
|
2374
|
+
break
|
2375
|
+
return r1
|
2376
|
+
|
2305
2377
|
circles = [e for e in self.elements() if is_Circle(e)]
|
2306
2378
|
logger.debug(" -- %s Circles", len(circles))
|
2307
2379
|
|
2308
2380
|
for e in circles:
|
2309
2381
|
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2382
|
+
angle = e.get_angle_of_arc()
|
2310
2383
|
entry = {'center': center,
|
2311
|
-
'
|
2312
|
-
'phi': e.get_angle_of_arc(),
|
2384
|
+
'radiuslist': [[round(e.radius, 1), angle]],
|
2313
2385
|
'dist': e.length(),
|
2314
2386
|
'inside': center_is_inside(center),
|
2315
2387
|
'count': 1}
|
@@ -2320,9 +2392,9 @@ class Geometry(object):
|
|
2320
2392
|
|
2321
2393
|
for e in arcs:
|
2322
2394
|
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2395
|
+
angle = e.get_angle_of_arc()
|
2323
2396
|
entry = {'center': center,
|
2324
|
-
'
|
2325
|
-
'phi': e.get_angle_of_arc(),
|
2397
|
+
'radiuslist': [[round(e.radius, 1), angle]],
|
2326
2398
|
'dist': e.length(),
|
2327
2399
|
'inside': center_is_inside(center),
|
2328
2400
|
'count': 1}
|
@@ -2330,7 +2402,7 @@ class Geometry(object):
|
|
2330
2402
|
center_list.append(entry)
|
2331
2403
|
|
2332
2404
|
center = None
|
2333
|
-
arc_list = [[c['count'], len(c['
|
2405
|
+
arc_list = [[c['count'], len(c['radiuslist']), n, c]
|
2334
2406
|
for n, c in enumerate(center_list)]
|
2335
2407
|
arc_list.sort(reverse=True)
|
2336
2408
|
|
@@ -2340,63 +2412,63 @@ class Geometry(object):
|
|
2340
2412
|
[logger.debug("Arc %s", arc) for arc in arc_list]
|
2341
2413
|
if not arc_list:
|
2342
2414
|
logger.debug("end of get_center_arcs: no arcs")
|
2343
|
-
return None
|
2415
|
+
return None, 0
|
2344
2416
|
|
2345
|
-
cnt, cr1,
|
2417
|
+
cnt, cr1, n, c1 = arc_list[0]
|
2346
2418
|
logger.debug("First Entry: %s", c1)
|
2347
2419
|
center = c1['center']
|
2420
|
+
radius = get_best_radius(c1['radiuslist'])
|
2348
2421
|
if len(arc_list) > 1:
|
2349
|
-
cnt, cr2,
|
2422
|
+
cnt, cr2, n, c2 = arc_list[1]
|
2350
2423
|
logger.debug("Second Entry: %s", c2)
|
2351
2424
|
if not cr1 > cr2:
|
2352
2425
|
center = None
|
2353
2426
|
|
2354
2427
|
if center:
|
2355
|
-
logger.debug("end of get_center_arcs:
|
2356
|
-
return center
|
2428
|
+
logger.debug("end of get_center_arcs: c=%s, r=%s", center, radius)
|
2429
|
+
return center, radius
|
2357
2430
|
|
2358
2431
|
c_entry = self.get_center_with_x(center_list, x_min)
|
2359
2432
|
if c_entry:
|
2360
2433
|
center = c_entry['center']
|
2361
2434
|
if center[1] < y_min:
|
2362
|
-
logger.debug("end of get_center_arcs
|
2363
|
-
return center
|
2435
|
+
logger.debug("end of get_center_arcs (x): c=%s", center)
|
2436
|
+
return center, 0
|
2437
|
+
|
2364
2438
|
c_entry = self.get_center_with_y(center_list, y_min)
|
2365
2439
|
if c_entry:
|
2366
2440
|
center = c_entry['center']
|
2367
2441
|
if center[0] < x_min:
|
2368
|
-
logger.debug("end of get_center_arcs
|
2369
|
-
return center
|
2442
|
+
logger.debug("end of get_center_arcs (y): c=%s", center)
|
2443
|
+
return center, 0
|
2370
2444
|
|
2371
2445
|
logger.debug("end of get_center_arcs: no center found")
|
2372
|
-
return None
|
2446
|
+
return None, 0
|
2373
2447
|
|
2374
2448
|
def get_center_dim(self, mm):
|
2375
2449
|
return (round(mm[0], 4), round(mm[2], 4))
|
2376
2450
|
|
2377
|
-
def get_center(self,
|
2378
|
-
logger.debug("Begin of get_center(%s points)", len(
|
2379
|
-
if len(
|
2451
|
+
def get_center(self, center_arcs, hull_points, mm):
|
2452
|
+
logger.debug("Begin of get_center(%s hull-points)", len(hull_points))
|
2453
|
+
if len(hull_points) < 3:
|
2380
2454
|
return None
|
2381
2455
|
|
2382
2456
|
center = None
|
2383
2457
|
# Zuerst suchen wir anhand der Circle- und Arc-Segmente nach einem
|
2384
2458
|
# möglichen Center-Punkt.
|
2385
|
-
center_arcs = self.get_center_arcs(mm)
|
2386
|
-
|
2387
2459
|
if center_arcs:
|
2388
2460
|
center = center_arcs
|
2389
2461
|
else:
|
2390
2462
|
# Wir finden keine Arc-Objekte, welche uns einen Hinweis auf den
|
2391
2463
|
# Center geben können. Wir versuchen in der Verzweiflung mit
|
2392
2464
|
# center_hull oder x(min) und y(min)
|
2393
|
-
center_hull = self.get_center_hull(
|
2465
|
+
center_hull = self.get_center_hull(_hull_points)
|
2394
2466
|
if center_hull:
|
2395
2467
|
center = center_hull
|
2396
2468
|
else:
|
2397
2469
|
center = self.get_center_dim(mm)
|
2398
2470
|
|
2399
|
-
center_xaxis = self.get_center_xaxis(
|
2471
|
+
center_xaxis = self.get_center_xaxis(hull_points)
|
2400
2472
|
y = center_xaxis[1]
|
2401
2473
|
if y is not None:
|
2402
2474
|
if np.isclose(y, center[1], atol=0.3):
|
@@ -3765,16 +3837,44 @@ class Geometry(object):
|
|
3765
3837
|
a_midangle = a.get_mid_angle(self.center)
|
3766
3838
|
if np.isclose(midangle, a_midangle, atol=1e-2, rtol=1e-2):
|
3767
3839
|
s = a.area_size()
|
3768
|
-
mags.append([s, n, a])
|
3840
|
+
mags.append([s, n, a, a_midangle])
|
3769
3841
|
|
3770
3842
|
if not mags:
|
3771
|
-
|
3843
|
+
logger.debug("possible_magnet_in_the_middle: No Areas for Magnets")
|
3844
|
+
return None
|
3845
|
+
|
3772
3846
|
mags.sort(reverse=True)
|
3773
|
-
|
3774
|
-
a
|
3775
|
-
|
3776
|
-
|
3777
|
-
|
3847
|
+
to_angle = np.pi / 2
|
3848
|
+
for s, n, a, mid in mags:
|
3849
|
+
angle = to_angle - mid
|
3850
|
+
nodelist = a.list_of_nodes()
|
3851
|
+
nodes = self.get_rotated_nodes(angle, nodelist)
|
3852
|
+
p1 = self.center
|
3853
|
+
p2 = point(self.center, self.max_radius + 10, mid)
|
3854
|
+
line = Line(Element(start=p1, end=p2))
|
3855
|
+
nodelist = a.get_intersect_points(line)
|
3856
|
+
mid_nodes = self.get_rotated_nodes(angle, nodelist)
|
3857
|
+
if self.is_possible_magnet(nodes, mid_nodes):
|
3858
|
+
a.set_type(AREA.TYPE_MAGNET_AIRGAP)
|
3859
|
+
a.phi = mid
|
3860
|
+
a.mag_width = (a.max_dist - a.min_dist) * 0.9
|
3861
|
+
return a
|
3862
|
+
|
3863
|
+
logger.debug("possible_magnet_in_the_middle: No Magnets")
|
3864
|
+
return None
|
3865
|
+
|
3866
|
+
def is_possible_magnet(self, all_nodes, mid_nodes):
|
3867
|
+
all_y = [n[1] for n in all_nodes]
|
3868
|
+
all_y.sort()
|
3869
|
+
mid_y = [n[1] for n in mid_nodes]
|
3870
|
+
mid_y.sort()
|
3871
|
+
|
3872
|
+
logger.debug("is_possible_magnet: mid y min/max = %s/%s", mid_y[0], mid_y[-1])
|
3873
|
+
logger.debug("is_possible_magnet: all y min/max = %s/%s", all_y[0], all_y[-1])
|
3874
|
+
|
3875
|
+
if all_y[0] > mid_y[-1]:
|
3876
|
+
return False
|
3877
|
+
return True
|
3778
3878
|
|
3779
3879
|
def force_area_as_magnet(self, area):
|
3780
3880
|
for a in self.list_of_areas():
|
@@ -3804,16 +3904,20 @@ class Geometry(object):
|
|
3804
3904
|
return False
|
3805
3905
|
|
3806
3906
|
def looking_for_corners(self):
|
3807
|
-
|
3808
|
-
|
3809
|
-
|
3810
|
-
|
3811
|
-
|
3812
|
-
|
3813
|
-
|
3814
|
-
|
3815
|
-
|
3816
|
-
|
3907
|
+
try:
|
3908
|
+
if self.is_inner:
|
3909
|
+
logger.debug("looking_for_corners: inner")
|
3910
|
+
start_cp = self.start_corners[-1]
|
3911
|
+
end_cp = self.end_corners[-1]
|
3912
|
+
else:
|
3913
|
+
logger.debug("looking_for_corners: outer")
|
3914
|
+
start_cp = self.start_corners[0]
|
3915
|
+
end_cp = self.end_corners[0]
|
3916
|
+
logger.debug("looking_for_corners: start=%s, end=%s",
|
3917
|
+
start_cp, end_cp)
|
3918
|
+
except IndexError:
|
3919
|
+
return
|
3920
|
+
|
3817
3921
|
for area in self.list_of_areas():
|
3818
3922
|
area.mark_airgap_corners(start_cp, end_cp)
|
3819
3923
|
return
|
@@ -4320,6 +4424,73 @@ class Geometry(object):
|
|
4320
4424
|
builder = AreaBuilder(geom=self)
|
4321
4425
|
return builder.create_inner_corner_auxiliary_areas(startangle, endangle)
|
4322
4426
|
|
4427
|
+
def analyse_airgap_line(self, inner):
|
4428
|
+
if inner: # TODO
|
4429
|
+
return False
|
4430
|
+
|
4431
|
+
areas = self.list_of_areas()
|
4432
|
+
builder = AreaBuilder(geom=self)
|
4433
|
+
ag_nodes, ag_el = builder.get_outer_airgap_line()
|
4434
|
+
if not ag_nodes:
|
4435
|
+
logger.warning("Fatal: No nodes found")
|
4436
|
+
return False
|
4437
|
+
|
4438
|
+
distlist = [distance(self.center, n) for n in ag_nodes]
|
4439
|
+
min_dist = min(distlist)
|
4440
|
+
max_dist = max(distlist)
|
4441
|
+
logger.debug("Airgap min/max from center: %s/%s", min_dist, max_dist)
|
4442
|
+
for a in areas:
|
4443
|
+
logger.debug("%s: min/max from center: %s/%s", a.identifier(), a.min_dist, a.max_dist)
|
4444
|
+
logger.debug("%s: min/max x: %s/%s, y: %s/%s",
|
4445
|
+
a.identifier(),
|
4446
|
+
a.min_x, a.max_x,
|
4447
|
+
a.min_y, a.max_y)
|
4448
|
+
if less_equal(a.min_x, -min_dist) and greater_equal(a.max_x, min_dist) and \
|
4449
|
+
less_equal(a.min_y, -min_dist) and greater_equal(a.max_y, min_dist):
|
4450
|
+
logger.debug("%s: around center", a.identifier())
|
4451
|
+
continue
|
4452
|
+
if np.isclose(a.min_dist, min_dist, rtol=1e-3, atol=1e-2):
|
4453
|
+
continue
|
4454
|
+
if less_equal(a.max_dist, max_dist, rtol=1e-3, atol=1e-2):
|
4455
|
+
return False
|
4456
|
+
|
4457
|
+
return builder.close_outer_winding_areas()
|
4458
|
+
|
4459
|
+
def adjust_outer_hull_for_symmetry(self):
|
4460
|
+
logger.debug("adjust_outer_hull_for_symmetry()")
|
4461
|
+
areas = self.list_of_areas()
|
4462
|
+
builder = AreaBuilder(geom=self)
|
4463
|
+
op_nodes, op_el = builder.get_outer_opposite_airgap_line()
|
4464
|
+
if not op_nodes:
|
4465
|
+
logger.warning("Fatal: No nodes found")
|
4466
|
+
return False
|
4467
|
+
|
4468
|
+
radiuslist = {}
|
4469
|
+
n1 = op_nodes[0]
|
4470
|
+
d1 = distance(self.center, n1)
|
4471
|
+
a1 = alpha_line(self.center, n1)
|
4472
|
+
for n2 in op_nodes[1:]:
|
4473
|
+
d2 = distance(self.center, n2)
|
4474
|
+
a2 = alpha_line(self.center, n2)
|
4475
|
+
if np.isclose(d1, d2, rtol=1e-3, atol=1e-2):
|
4476
|
+
r = round((d1 + d2) / 2, 1)
|
4477
|
+
alpha = get_angle_of_arc(a2, a1)
|
4478
|
+
radius_alpha = radiuslist.get(r, 0.0) + alpha
|
4479
|
+
radiuslist[r] = radius_alpha
|
4480
|
+
|
4481
|
+
n1 = n2
|
4482
|
+
d1 = d2
|
4483
|
+
a1 = a2
|
4484
|
+
|
4485
|
+
rlist = [(radiuslist[r], r) for r in radiuslist]
|
4486
|
+
rlist.sort(reverse=True)
|
4487
|
+
alpha, best_radius = rlist[0]
|
4488
|
+
if np.isclose(best_radius, self.max_radius, rtol=1e-3, atol=1e-2):
|
4489
|
+
return False
|
4490
|
+
logger.debug("Best Outer Radius is %s", best_radius)
|
4491
|
+
self.adjust_outer_hull(best_radius)
|
4492
|
+
return True
|
4493
|
+
|
4323
4494
|
def close_outer_winding_areas(self):
|
4324
4495
|
logger.debug("begin close_outer_winding_areas(%s areas)",
|
4325
4496
|
len(self.area_list))
|
@@ -4641,3 +4812,9 @@ class Geometry(object):
|
|
4641
4812
|
|
4642
4813
|
with io.open(name, 'w', encoding='utf-8') as f:
|
4643
4814
|
f.write('\n'.join(content))
|
4815
|
+
|
4816
|
+
def adjust_outer_hull(self, new_radius):
|
4817
|
+
c = Circle(Element(center=self.center, radius=new_radius))
|
4818
|
+
self.add_element(c, 1e-3, 1e-3)
|
4819
|
+
self.delete_needless_elements(new_radius)
|
4820
|
+
self.max_radius = new_radius
|
femagtools/dxfsl/machine.py
CHANGED
@@ -580,10 +580,8 @@ class Machine(object):
|
|
580
580
|
return self.geom.create_auxiliary_lines(self.startangle, self.endangle)
|
581
581
|
|
582
582
|
def set_alfa_and_corners(self):
|
583
|
-
self.geom.
|
584
|
-
|
585
|
-
self.geom.end_corners = self.geom.get_corner_nodes(self.center,
|
586
|
-
self.endangle)
|
583
|
+
self.geom.set_start_corners(self.center, self.startangle)
|
584
|
+
self.geom.set_end_corners(self.center, self.endangle)
|
587
585
|
self.geom.alfa = alpha_angle(self.startangle, self.endangle)
|
588
586
|
|
589
587
|
if self.mirror_geom is not None:
|
@@ -639,6 +637,22 @@ class Machine(object):
|
|
639
637
|
if self.radius <= 0.0:
|
640
638
|
return False
|
641
639
|
|
640
|
+
if is_outer:
|
641
|
+
self.geom.set_subregion_parameters(self.startangle, self.endangle)
|
642
|
+
if self.part > 1:
|
643
|
+
self.geom.set_start_corners(self.center, self.startangle, rtol=1e-3, atol=1e-2)
|
644
|
+
self.geom.set_end_corners(self.center, self.endangle, rtol=1e-3, atol=1e-2)
|
645
|
+
else:
|
646
|
+
self.geom.set_virtual_start_end_corners()
|
647
|
+
|
648
|
+
self.geom.looking_for_corners()
|
649
|
+
create_areas = self.geom.analyse_airgap_line(is_inner)
|
650
|
+
if self.geom.adjust_outer_hull_for_symmetry():
|
651
|
+
create_areas = True
|
652
|
+
|
653
|
+
if create_areas:
|
654
|
+
self.geom.create_list_of_areas(delete=True)
|
655
|
+
|
642
656
|
symmetry = Symmetry(geom=self.geom,
|
643
657
|
startangle=self.startangle,
|
644
658
|
endangle=self.endangle)
|
@@ -1353,10 +1367,11 @@ class Machine(object):
|
|
1353
1367
|
pts = self.geom.split_and_get_intersect_points(line, aktion=False)
|
1354
1368
|
pts.sort()
|
1355
1369
|
|
1370
|
+
arcs_created = False
|
1356
1371
|
p_critical = self.geom.critical_touch_point(pts)
|
1357
1372
|
if p_critical:
|
1358
1373
|
d_critical = distance(self.center, p_critical)
|
1359
|
-
logger.
|
1374
|
+
logger.debug("Critical Point: %s, len=%s", p_critical, d_critical)
|
1360
1375
|
sep_radius = self.get_iron_separator(radius_list)
|
1361
1376
|
logger.debug("Iron Separator found: %s", sep_radius)
|
1362
1377
|
if sep_radius > 0.0 and sep_radius < d_critical:
|
@@ -1367,8 +1382,15 @@ class Machine(object):
|
|
1367
1382
|
if r[1] < d_critical:
|
1368
1383
|
if self.create_arc(r[1]):
|
1369
1384
|
radius = r[1]
|
1385
|
+
arcs_created = True
|
1370
1386
|
break
|
1371
1387
|
|
1388
|
+
if arcs_created:
|
1389
|
+
self.geom.create_list_of_areas(delete=True)
|
1390
|
+
self.geom.search_subregions(self.startangle,
|
1391
|
+
self.endangle,
|
1392
|
+
False)
|
1393
|
+
|
1372
1394
|
# install line
|
1373
1395
|
line = Line(
|
1374
1396
|
Element(start=self.center,
|
@@ -1376,11 +1398,9 @@ class Machine(object):
|
|
1376
1398
|
|
1377
1399
|
pts = self.geom.split_and_get_intersect_points(line)
|
1378
1400
|
pts.sort()
|
1379
|
-
|
1380
1401
|
if self.geom.create_lines_outside_windings(pts):
|
1381
|
-
self.geom.area_list = []
|
1382
1402
|
logger.debug("create subregions again")
|
1383
|
-
self.geom.create_list_of_areas()
|
1403
|
+
self.geom.create_list_of_areas(delete=True)
|
1384
1404
|
self.geom.search_subregions(self.startangle,
|
1385
1405
|
self.endangle,
|
1386
1406
|
False)
|
femagtools/dxfsl/symmetry.py
CHANGED
@@ -48,6 +48,7 @@ class Symmetry(object):
|
|
48
48
|
self.atol = atol
|
49
49
|
self.full = False
|
50
50
|
self.ag_radius = 0.0
|
51
|
+
self.height = geom.max_radius - geom.min_radius
|
51
52
|
if np.isclose(self.startangle, self.endangle):
|
52
53
|
self.alpha = 2.0*np.pi
|
53
54
|
self.full = True
|
@@ -120,9 +121,6 @@ class Symmetry(object):
|
|
120
121
|
areas.sort(reverse=True)
|
121
122
|
return areas
|
122
123
|
|
123
|
-
def get_equal_areas(self, areas):
|
124
|
-
return
|
125
|
-
|
126
124
|
def build_results(self, areas):
|
127
125
|
logger.debug("begin of build_results with %s areas", len(areas))
|
128
126
|
[logger.debug("#%s: alpha=%s, min=%s, max=%s",
|
@@ -286,13 +284,22 @@ class Symmetry(object):
|
|
286
284
|
logger.debug("Geometry: Alpha=%s, Center=%s", self.alpha, self.geom.center)
|
287
285
|
mid_angle, a = area_list[0]
|
288
286
|
result['height'] = a.height
|
287
|
+
result['min_dist'] = a.min_dist
|
288
|
+
result['max_dist'] = a.max_dist
|
289
289
|
result['alpha'] = a.get_alpha(self.geom.center)
|
290
290
|
if self.geom.is_inner:
|
291
291
|
result['airgap'] = np.isclose(a.max_dist, self.ag_radius)
|
292
292
|
else:
|
293
293
|
result['airgap'] = np.isclose(a.min_dist, self.ag_radius)
|
294
|
+
upper_quarter = self.geom.min_radius + self.height * 0.75
|
295
|
+
upper_half = self.geom.min_radius + self.height * 0.5
|
296
|
+
if a.max_dist > upper_quarter:
|
297
|
+
if a.min_dist > upper_half:
|
298
|
+
result['upper_quarter'] = True
|
294
299
|
if len(area_list) == 1: # one area
|
295
|
-
|
300
|
+
rslt = self.check_one_area(mid_angle, a, result, rtol=rtol, atol=atol)
|
301
|
+
logger.debug("end of check_delta")
|
302
|
+
return rslt
|
296
303
|
|
297
304
|
self.delta_check_count += 1
|
298
305
|
area_list.sort()
|
@@ -353,6 +360,7 @@ class Symmetry(object):
|
|
353
360
|
logger.debug("end of check_delta: BAD DELTA %s, (expected %s)",
|
354
361
|
delta_angle, geom_alpha)
|
355
362
|
result['slices'] = 0
|
363
|
+
logger.debug("end of check_delta: very bad")
|
356
364
|
return result # very bad
|
357
365
|
|
358
366
|
deltas = self.create_deltas(delta_list, rtol=rtol, atol=atol)
|
@@ -927,13 +935,20 @@ class Symmetry(object):
|
|
927
935
|
logger.debug("Symmetry-Destroyer destroyed")
|
928
936
|
slices = None
|
929
937
|
|
938
|
+
if rslt.get('upper_quarter', False):
|
939
|
+
if size < max_size / 20:
|
940
|
+
slices = None
|
941
|
+
|
942
|
+
if slices == 1:
|
943
|
+
if rslt.get('upper_quarter', False):
|
944
|
+
slices = None
|
945
|
+
|
930
946
|
if slices == 1:
|
931
947
|
# symmetry killer
|
932
948
|
if areas < max(2, max_areas / 6):
|
933
949
|
if size < max_size * 0.05:
|
934
950
|
slices = None # ignore tiny areas
|
935
951
|
|
936
|
-
|
937
952
|
parts_possible = self.calc_parts(parts_possible, slices)
|
938
953
|
|
939
954
|
if unsure_sym:
|