femagtools 1.8.3__py3-none-any.whl → 1.8.4__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- femagtools/__init__.py +1 -1
- femagtools/bch.py +10 -6
- femagtools/dxfsl/area.py +4 -1
- femagtools/dxfsl/conv.py +49 -17
- femagtools/dxfsl/converter.py +239 -75
- femagtools/dxfsl/fslrenderer.py +18 -22
- femagtools/dxfsl/functions.py +24 -2
- femagtools/dxfsl/geom.py +100 -23
- femagtools/dxfsl/machine.py +44 -7
- femagtools/dxfsl/shape.py +4 -0
- femagtools/dxfsl/symmetry.py +78 -25
- femagtools/fsl.py +0 -1
- femagtools/machine/afpm.py +2 -2
- femagtools/machine/effloss.py +2 -2
- femagtools/machine/im.py +6 -8
- femagtools/machine/sm.py +2 -2
- femagtools/mcv.py +10 -11
- femagtools/templates/mesh-airgap.mako +6 -0
- femagtools/utils.py +1 -1
- femagtools/windings.py +11 -4
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/METADATA +1 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/RECORD +27 -27
- tests/test_parident.py +2 -1
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/LICENSE +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/WHEEL +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.3.dist-info → femagtools-1.8.4.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py
CHANGED
@@ -2256,45 +2256,120 @@ class Geometry(object):
|
|
2256
2256
|
return center[0]
|
2257
2257
|
return None
|
2258
2258
|
|
2259
|
-
def
|
2259
|
+
def is_same_center(self, center_lst, center, rtol, atol):
|
2260
|
+
for c in center_lst:
|
2261
|
+
if points_are_close(c['center'], center['center'], rtol, atol):
|
2262
|
+
radius = center['radius'][0]
|
2263
|
+
if not radius in c['radius']:
|
2264
|
+
c['radius'].append(radius)
|
2265
|
+
c['count'] = c['count'] + 1
|
2266
|
+
return True
|
2267
|
+
return False
|
2268
|
+
|
2269
|
+
def get_center_with_x(self, center_lst, x):
|
2270
|
+
c_list = [c for c in center_lst
|
2271
|
+
if np.isclose(c['center'][0], x, rtol=self.rtol, atol=self.atol)]
|
2272
|
+
if not c_list:
|
2273
|
+
return None
|
2274
|
+
cy_list = [(c['center'][1], c) for c in c_list]
|
2275
|
+
cy_list.sort()
|
2276
|
+
y, c = cy_list[0]
|
2277
|
+
return c
|
2278
|
+
|
2279
|
+
def get_center_with_y(self, center_lst, y):
|
2280
|
+
c_list = [c for c in center_lst
|
2281
|
+
if np.isclose(c['center'][1], y, rtol=self.rtol, atol=self.atol)]
|
2282
|
+
if not c_list:
|
2283
|
+
return None
|
2284
|
+
cy_list = [(c['center'][0], c) for c in c_list]
|
2285
|
+
cy_list.sort()
|
2286
|
+
[logger.info("y=%s, c=%s", y, c) for y, c in cy_list]
|
2287
|
+
y, c = cy_list[0]
|
2288
|
+
return c
|
2289
|
+
|
2290
|
+
def get_center_arcs(self, mm):
|
2260
2291
|
logger.debug("begin of get_center_arcs")
|
2261
2292
|
center_list = []
|
2293
|
+
x_min, x_max, y_min, y_max = mm
|
2294
|
+
|
2295
|
+
def center_is_inside(c):
|
2296
|
+
tol = 0.1
|
2297
|
+
x, y = c
|
2298
|
+
if x-tol > x_min and \
|
2299
|
+
x+tol < x_max and \
|
2300
|
+
y-tol > y_min and \
|
2301
|
+
y+tol < y_max:
|
2302
|
+
return True
|
2303
|
+
return False
|
2304
|
+
|
2262
2305
|
circles = [e for e in self.elements() if is_Circle(e)]
|
2263
2306
|
logger.debug(" -- %s Circles", len(circles))
|
2264
2307
|
|
2265
2308
|
for e in circles:
|
2266
2309
|
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2267
|
-
|
2268
|
-
|
2310
|
+
entry = {'center': center,
|
2311
|
+
'radius': [round(e.radius, 1)],
|
2312
|
+
'phi': e.get_angle_of_arc(),
|
2313
|
+
'dist': e.length(),
|
2314
|
+
'inside': center_is_inside(center),
|
2315
|
+
'count': 1}
|
2316
|
+
center_list.append(entry)
|
2269
2317
|
|
2270
2318
|
arcs = [e for e in self.elements() if is_Arc(e)]
|
2271
2319
|
logger.debug(" -- %s Arcs", len(arcs))
|
2272
2320
|
|
2273
2321
|
for e in arcs:
|
2274
2322
|
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2323
|
+
entry = {'center': center,
|
2324
|
+
'radius': [round(e.radius, 1)],
|
2325
|
+
'phi': e.get_angle_of_arc(),
|
2326
|
+
'dist': e.length(),
|
2327
|
+
'inside': center_is_inside(center),
|
2328
|
+
'count': 1}
|
2329
|
+
if not self.is_same_center(center_list, entry, self.rtol, self.atol):
|
2330
|
+
center_list.append(entry)
|
2283
2331
|
|
2284
2332
|
center = None
|
2285
|
-
arc_list = [[
|
2333
|
+
arc_list = [[c['count'], len(c['radius']), c['phi'], n, c]
|
2334
|
+
for n, c in enumerate(center_list)]
|
2286
2335
|
arc_list.sort(reverse=True)
|
2287
2336
|
|
2288
|
-
|
2289
|
-
|
2290
|
-
center = c1[2]
|
2291
|
-
if len(arc_list) > 1:
|
2292
|
-
c2 = arc_list[1]
|
2293
|
-
if not c1[0] > c2[0]:
|
2294
|
-
center = None
|
2337
|
+
logger.debug("x min/max = %s/%s", x_min, x_max)
|
2338
|
+
logger.debug("y min/max = %s/%s", y_min, y_max)
|
2295
2339
|
|
2296
|
-
logger.debug("
|
2297
|
-
|
2340
|
+
[logger.debug("Arc %s", arc) for arc in arc_list]
|
2341
|
+
if not arc_list:
|
2342
|
+
logger.debug("end of get_center_arcs: no arcs")
|
2343
|
+
return None
|
2344
|
+
|
2345
|
+
cnt, cr1, p, n, c1 = arc_list[0]
|
2346
|
+
logger.debug("First Entry: %s", c1)
|
2347
|
+
center = c1['center']
|
2348
|
+
if len(arc_list) > 1:
|
2349
|
+
cnt, cr2, p, n, c2 = arc_list[1]
|
2350
|
+
logger.debug("Second Entry: %s", c2)
|
2351
|
+
if not cr1 > cr2:
|
2352
|
+
center = None
|
2353
|
+
|
2354
|
+
if center:
|
2355
|
+
logger.debug("end of get_center_arcs: -> %s", center)
|
2356
|
+
return center
|
2357
|
+
|
2358
|
+
c_entry = self.get_center_with_x(center_list, x_min)
|
2359
|
+
if c_entry:
|
2360
|
+
center = c_entry['center']
|
2361
|
+
if center[1] < y_min:
|
2362
|
+
logger.debug("end of get_center_arcs: x -> %s", center)
|
2363
|
+
return center
|
2364
|
+
c_entry = self.get_center_with_y(center_list, y_min)
|
2365
|
+
if c_entry:
|
2366
|
+
center = c_entry['center']
|
2367
|
+
if center[0] < x_min:
|
2368
|
+
logger.debug("end of get_center_arcs: y -> %s", center)
|
2369
|
+
return center
|
2370
|
+
|
2371
|
+
logger.debug("end of get_center_arcs: no center found")
|
2372
|
+
return None
|
2298
2373
|
|
2299
2374
|
def get_center_dim(self, mm):
|
2300
2375
|
return (round(mm[0], 4), round(mm[2], 4))
|
@@ -2305,7 +2380,9 @@ class Geometry(object):
|
|
2305
2380
|
return None
|
2306
2381
|
|
2307
2382
|
center = None
|
2308
|
-
|
2383
|
+
# Zuerst suchen wir anhand der Circle- und Arc-Segmente nach einem
|
2384
|
+
# möglichen Center-Punkt.
|
2385
|
+
center_arcs = self.get_center_arcs(mm)
|
2309
2386
|
|
2310
2387
|
if center_arcs:
|
2311
2388
|
center = center_arcs
|
@@ -3259,7 +3336,7 @@ class Geometry(object):
|
|
3259
3336
|
max_size, max_w = windings_surface[0]
|
3260
3337
|
for sz, w in windings_surface[1:]:
|
3261
3338
|
logger.debug("winding size = %s", sz)
|
3262
|
-
if sz / max_size < 0.
|
3339
|
+
if sz / max_size < 0.70:
|
3263
3340
|
w.set_type(AREA.TYPE_AIR)
|
3264
3341
|
if sz / max_size < 0.2:
|
3265
3342
|
windings_found -= 1
|
femagtools/dxfsl/machine.py
CHANGED
@@ -135,6 +135,16 @@ class Machine(object):
|
|
135
135
|
self.geom.is_outer = True
|
136
136
|
self.geom.is_inner = False
|
137
137
|
|
138
|
+
def set_attributes(self,
|
139
|
+
kind="",
|
140
|
+
inner=False,
|
141
|
+
outer=False):
|
142
|
+
self.set_kind(kind)
|
143
|
+
if inner:
|
144
|
+
self.set_inner()
|
145
|
+
if outer:
|
146
|
+
self.set_outer()
|
147
|
+
|
138
148
|
def clear_cut_lines(self):
|
139
149
|
self.geom.clear_cut_lines()
|
140
150
|
if self.mirror_geom is not None:
|
@@ -635,9 +645,13 @@ class Machine(object):
|
|
635
645
|
parts = symmetry.find_symmetry() # temp solution
|
636
646
|
logger.debug(">>> Symmetry parts = %s <<<", parts)
|
637
647
|
|
638
|
-
if parts
|
639
|
-
|
640
|
-
|
648
|
+
if parts == 1:
|
649
|
+
# no slices, but ok
|
650
|
+
return False
|
651
|
+
|
652
|
+
found = (parts > 1)
|
653
|
+
|
654
|
+
if not found:
|
641
655
|
found = self.geom.find_symmetry(self.radius,
|
642
656
|
self.startangle,
|
643
657
|
self.endangle,
|
@@ -833,11 +847,11 @@ class Machine(object):
|
|
833
847
|
if dist_start > dist_end:
|
834
848
|
machine.mirror_all_areas(self.startangle)
|
835
849
|
machine.rotate_to(angle)
|
836
|
-
machine.geom.create_list_of_areas(delete=True)
|
837
850
|
machine.startangle -= angle
|
838
851
|
else:
|
839
852
|
machine.mirror_all_areas(self.endangle)
|
840
853
|
machine.endangle += angle
|
854
|
+
machine.geom.create_list_of_areas(delete=True)
|
841
855
|
machine.set_alfa_and_corners()
|
842
856
|
machine.part = machine.part_of_circle()
|
843
857
|
machine.geom.set_subregion_parameters(self.startangle,
|
@@ -907,23 +921,25 @@ class Machine(object):
|
|
907
921
|
first_thirdangle,
|
908
922
|
second_thirdangle)
|
909
923
|
machine_mirror_1.clear_cut_lines()
|
910
|
-
|
911
924
|
machine_mirror_1.repair_hull()
|
912
925
|
machine_mirror_1.set_alfa_and_corners()
|
926
|
+
if machine_mirror_1.geom.number_of_edges() < 2: # very bad
|
927
|
+
logger.debug("end get_third_symmetry_mirror: no remaining elements")
|
928
|
+
return None
|
913
929
|
if not machine_mirror_1.check_symmetry_graph(0.001, 0.05):
|
914
930
|
logger.debug("end get_third_symmetry_mirror: no mirror first third")
|
915
931
|
return None
|
916
932
|
|
917
933
|
if plt:
|
918
934
|
plt.render_elements(machine_mirror_1.geom, Shape,
|
919
|
-
title="Part",
|
935
|
+
title="Part 1",
|
920
936
|
show=True,
|
921
937
|
with_corners=False,
|
922
938
|
with_nodes=False,
|
923
939
|
neighbors=True)
|
924
940
|
|
925
941
|
plt.render_elements(machine_mirror_1.mirror_geom, Shape,
|
926
|
-
title="Counterpart",
|
942
|
+
title="Counterpart 1",
|
927
943
|
show=True,
|
928
944
|
with_corners=False,
|
929
945
|
with_nodes=False,
|
@@ -935,10 +951,28 @@ class Machine(object):
|
|
935
951
|
machine_mirror_2.clear_cut_lines()
|
936
952
|
machine_mirror_2.repair_hull()
|
937
953
|
machine_mirror_2.set_alfa_and_corners()
|
954
|
+
if machine_mirror_2.geom.number_of_edges() < 2: # very bad
|
955
|
+
logger.debug("end get_third_symmetry_mirror: no remaining elements")
|
956
|
+
return None
|
938
957
|
if not machine_mirror_2.check_symmetry_graph(0.001, 0.05):
|
939
958
|
logger.debug("end get_third_symmetry_mirror: no mirror second third")
|
940
959
|
return None
|
941
960
|
|
961
|
+
if plt:
|
962
|
+
plt.render_elements(machine_mirror_2.geom, Shape,
|
963
|
+
title="Part 2",
|
964
|
+
show=True,
|
965
|
+
with_corners=False,
|
966
|
+
with_nodes=False,
|
967
|
+
neighbors=True)
|
968
|
+
|
969
|
+
plt.render_elements(machine_mirror_2.mirror_geom, Shape,
|
970
|
+
title="Counterpart 2",
|
971
|
+
show=True,
|
972
|
+
with_corners=False,
|
973
|
+
with_nodes=False,
|
974
|
+
neighbors=True)
|
975
|
+
|
942
976
|
machine_mirror_1.previous_machine = self
|
943
977
|
logger.debug("end get_third_symmetry_mirror: ok")
|
944
978
|
return machine_mirror_1
|
@@ -992,6 +1026,9 @@ class Machine(object):
|
|
992
1026
|
with_nodes=False,
|
993
1027
|
neighbors=True)
|
994
1028
|
|
1029
|
+
if machine_mirror.geom.number_of_edges() < 2: # very bad
|
1030
|
+
logger.debug("end get_symmetry_mirror: no remaining elements")
|
1031
|
+
return None
|
995
1032
|
if machine_mirror.check_symmetry_graph(0.001, 0.05):
|
996
1033
|
machine_mirror.previous_machine = self
|
997
1034
|
machine_mirror.rotate_to(0.0)
|
femagtools/dxfsl/shape.py
CHANGED
@@ -467,6 +467,10 @@ class Circle(Shape):
|
|
467
467
|
r0 = np.linalg.norm(self.center)
|
468
468
|
return max(abs(r-r0-self.radius), abs(r-r0+self.radius))
|
469
469
|
|
470
|
+
def length(self):
|
471
|
+
"""returns length of this circle"""
|
472
|
+
return self.radius*2*np.pi
|
473
|
+
|
470
474
|
def overlapping_shape(self, e, rtol=1e-03, atol=1e-03):
|
471
475
|
if not (isinstance(e, Arc) or isinstance(e, Circle)):
|
472
476
|
# end overlapping_shape: Circle (not Arc or Circle)
|
femagtools/dxfsl/symmetry.py
CHANGED
@@ -120,7 +120,15 @@ class Symmetry(object):
|
|
120
120
|
areas.sort(reverse=True)
|
121
121
|
return areas
|
122
122
|
|
123
|
+
def get_equal_areas(self, areas):
|
124
|
+
return
|
125
|
+
|
123
126
|
def build_results(self, areas):
|
127
|
+
logger.debug("begin of build_results with %s areas", len(areas))
|
128
|
+
[logger.debug("#%s: alpha=%s, min=%s, max=%s",
|
129
|
+
a.get_id(), alpha, a.min_angle, a.max_angle) for
|
130
|
+
alpha, dist, h, mid, a in areas]
|
131
|
+
|
124
132
|
a0_alpha, a0_min_dist, a0_height, a0_mid_angle, a0 = areas[0]
|
125
133
|
equal_areas = [(a0_mid_angle, a0)]
|
126
134
|
check_rslt = []
|
@@ -164,6 +172,7 @@ class Symmetry(object):
|
|
164
172
|
rslt['area'] = a0
|
165
173
|
rslt['areasize'] = areasize
|
166
174
|
check_rslt.append((areasize, rslt))
|
175
|
+
logger.debug("end of build_results")
|
167
176
|
return check_rslt
|
168
177
|
|
169
178
|
def get_winding_symmetry(self, inside=False):
|
@@ -246,7 +255,6 @@ class Symmetry(object):
|
|
246
255
|
|
247
256
|
check_rslt = self.build_results(areas)
|
248
257
|
logger.debug("%s results available", len(check_rslt))
|
249
|
-
[logger.debug("Result: %s", rslt) for rslt in check_rslt]
|
250
258
|
|
251
259
|
parts, start_delta = self.get_symmetry_parts(check_rslt)
|
252
260
|
if parts < 2:
|
@@ -665,6 +673,9 @@ class Symmetry(object):
|
|
665
673
|
m1 = m2
|
666
674
|
d1 = d2
|
667
675
|
|
676
|
+
if not mid_list:
|
677
|
+
return None
|
678
|
+
|
668
679
|
logger.debug("New Mids: %s", mid_list)
|
669
680
|
delta = positive_angle(mid_list[0] * 2)
|
670
681
|
delta_list = [delta]
|
@@ -712,6 +723,41 @@ class Symmetry(object):
|
|
712
723
|
logger.debug("end check_first_last_difference => %s", n1 + 1)
|
713
724
|
return n1 + 1
|
714
725
|
|
726
|
+
def concatenate_results(self, check_rslt):
|
727
|
+
if len(check_rslt) < 2:
|
728
|
+
return check_rslt
|
729
|
+
# ----------
|
730
|
+
def get_slices(rslt):
|
731
|
+
if rslt['slices'] is None:
|
732
|
+
return 0
|
733
|
+
if rslt.get('startdelta', 0.0) != 0.0:
|
734
|
+
return 0
|
735
|
+
if rslt.get('halfslice', None) is not None:
|
736
|
+
return 0
|
737
|
+
return rslt['slices']
|
738
|
+
# ------
|
739
|
+
new_rslt = []
|
740
|
+
size1, n1, rslt1 = check_rslt[0]
|
741
|
+
slices1 = get_slices(rslt1)
|
742
|
+
for size2, n2, rslt2 in check_rslt[1:]:
|
743
|
+
slices2 = get_slices(rslt2)
|
744
|
+
if slices1 > 0 and \
|
745
|
+
slices1 == slices2 and \
|
746
|
+
np.isclose(size1, size2, rtol=1e-01, atol=1e-01) and \
|
747
|
+
(rslt1.get('delta_corr', 0.0) == 0.0 or \
|
748
|
+
rslt2.get('delta_corr', 0.0) == 0.0):
|
749
|
+
# concatenate
|
750
|
+
rslt1['slices'] = None
|
751
|
+
rslt2['delta_corr'] = 0.0
|
752
|
+
rslt2['areas'] = rslt2['areas'] + rslt1['areas']
|
753
|
+
logger.debug("concatenate results(size %s)", size1)
|
754
|
+
else:
|
755
|
+
new_rslt.append((size1, n1, rslt1))
|
756
|
+
slices1, size1, n1, rslt1 = (slices2, size2, n2, rslt2)
|
757
|
+
|
758
|
+
new_rslt.append((size1, n1, rslt1))
|
759
|
+
return new_rslt
|
760
|
+
|
715
761
|
def get_symmetry_parts(self, check_rslt):
|
716
762
|
max_size = 0
|
717
763
|
max_areas = 0
|
@@ -720,10 +766,11 @@ class Symmetry(object):
|
|
720
766
|
self.delta_angle_corr = None
|
721
767
|
unsure_sym = False
|
722
768
|
|
723
|
-
check_rslt = [(size, n, rslt) for n, (size, rslt) in enumerate(check_rslt)
|
769
|
+
check_rslt = [(size, n, rslt) for n, (size, rslt) in enumerate(check_rslt)
|
770
|
+
if rslt['slices'] is not None]
|
724
771
|
check_rslt.sort(reverse=True)
|
725
|
-
|
726
|
-
|
772
|
+
check_rslt = self.concatenate_results(check_rslt)
|
773
|
+
[logger.debug("Result #%s: %s, %s", n, size, rslt) for size, n, rslt in check_rslt]
|
727
774
|
|
728
775
|
rtol = 1e-3
|
729
776
|
atol = 1e-2
|
@@ -740,40 +787,46 @@ class Symmetry(object):
|
|
740
787
|
for size, n, rslt in check_rslt:
|
741
788
|
areas = rslt['areas']
|
742
789
|
slices = rslt['slices']
|
790
|
+
if slices is None:
|
791
|
+
continue
|
792
|
+
|
743
793
|
size = rslt['areasize']
|
744
794
|
angle_corr = rslt.get('delta_corr', 0.0)
|
745
795
|
|
746
796
|
if rslt.get('halfslice', 0) == 1:
|
747
797
|
halfslice.append(rslt)
|
748
798
|
|
749
|
-
if slices
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
without_angle_corr += areas * size
|
764
|
-
else:
|
765
|
-
with_angle_corr += areas * size
|
799
|
+
if slices > 0:
|
800
|
+
max_size = max(max_size, size)
|
801
|
+
max_areas = max(max_areas, areas)
|
802
|
+
max_slices = max(max_slices, slices)
|
803
|
+
missing_middles += rslt.get('missing_middles', [])
|
804
|
+
area = rslt['area']
|
805
|
+
if not (np.isclose(area.min_dist,
|
806
|
+
self.geom.min_radius,
|
807
|
+
rtol=1e-4, atol=1e-3) and \
|
808
|
+
np.isclose(area.max_dist,
|
809
|
+
self.geom.max_radius,
|
810
|
+
rtol=1e-4, atol=1e-3)):
|
811
|
+
if rslt.get('delta_corr', 0.0) == 0.0:
|
812
|
+
without_angle_corr += areas * size
|
766
813
|
else:
|
767
|
-
|
814
|
+
with_angle_corr += areas * size
|
815
|
+
else:
|
816
|
+
maybe_angle_korr += areas * size
|
817
|
+
|
768
818
|
logger.debug("max size: %s, max areas: %s", max_size, max_areas)
|
819
|
+
logger.debug("Angle-Corrections: %s Yes, %s No, %s Maybe",
|
820
|
+
with_angle_corr,
|
821
|
+
without_angle_corr,
|
822
|
+
maybe_angle_korr)
|
769
823
|
|
770
|
-
logger.debug("Angle-Corrections: %s Yes, %s No",
|
771
|
-
with_angle_corr, without_angle_corr)
|
772
824
|
if np.isclose(with_angle_corr, without_angle_corr):
|
773
825
|
with_angle_corr = (maybe_angle_korr > 0)
|
774
826
|
else:
|
775
827
|
with_angle_corr = (with_angle_corr > without_angle_corr)
|
776
828
|
|
829
|
+
# -------------------------
|
777
830
|
def get_halfslice_counterpart(rslt):
|
778
831
|
if rslt.get('halfslice', 0) != 2:
|
779
832
|
return None
|
@@ -788,7 +841,7 @@ class Symmetry(object):
|
|
788
841
|
np.isclose(alpha1, alpha2, rtol=rtol, atol=atol):
|
789
842
|
return half
|
790
843
|
return None
|
791
|
-
|
844
|
+
# -----------
|
792
845
|
if halfslice:
|
793
846
|
logger.debug("%s halfslice [1] found", len(halfslice))
|
794
847
|
|
femagtools/fsl.py
CHANGED
@@ -556,7 +556,6 @@ class Builder:
|
|
556
556
|
if 'fsl_rotor' in conv:
|
557
557
|
self.fsl_rotor = True
|
558
558
|
th_props = ['']
|
559
|
-
logger.debug(model['magnet'])
|
560
559
|
if hasattr(model, 'magnet'):
|
561
560
|
if model['magnet'].get('thcond', 0):
|
562
561
|
th_props = [f'rotor_density = {model["magnet"]["density"]}',
|
femagtools/machine/afpm.py
CHANGED
@@ -11,7 +11,7 @@ from .. import model
|
|
11
11
|
from .. import utils
|
12
12
|
from .. import windings
|
13
13
|
from .. import femag
|
14
|
-
from scipy.interpolate import
|
14
|
+
from scipy.interpolate import make_interp_spline, RegularGridInterpolator, RectBivariateSpline
|
15
15
|
from scipy.integrate import quad
|
16
16
|
import copy
|
17
17
|
|
@@ -58,7 +58,7 @@ def _integrate(radius, pos, val):
|
|
58
58
|
|
59
59
|
|
60
60
|
def _integrate1d(radius, val):
|
61
|
-
interp =
|
61
|
+
interp = make_interp_spline(radius, val, k=1)
|
62
62
|
def func(x):
|
63
63
|
return interp((x))
|
64
64
|
return quad(func, radius[0], radius[-1])[0]
|
femagtools/machine/effloss.py
CHANGED
@@ -166,9 +166,9 @@ def _generate_mesh(n, T, nb, Tb, npoints):
|
|
166
166
|
nmax = max(n)
|
167
167
|
tmin, tmax = 0, max(T)
|
168
168
|
tnum = npoints[1]
|
169
|
-
tip = ip.
|
169
|
+
tip = ip.make_interp_spline(n, T, k=1)
|
170
170
|
if nb and Tb:
|
171
|
-
tbip = ip.
|
171
|
+
tbip = ip.make_interp_spline(nb, Tb, k=1)
|
172
172
|
else:
|
173
173
|
def tbip(x): return 0
|
174
174
|
|
femagtools/machine/im.py
CHANGED
@@ -35,6 +35,9 @@ def log_interp1d(x, y, kind='cubic'):
|
|
35
35
|
logy = np.log10(yy)
|
36
36
|
lin_interp = ip.interp1d(logx, logy, kind=kind, fill_value="extrapolate")
|
37
37
|
def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz)))
|
38
|
+
# TODO check replace interp1d
|
39
|
+
#lin_interp = ip.make_interp_spline(logx, logy, bc_type='not-a-knot')
|
40
|
+
#def log_interp(zz): return np.power(10.0, lin_interp(np.log10(zz), nu=1))
|
38
41
|
return log_interp
|
39
42
|
|
40
43
|
|
@@ -792,15 +795,10 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
792
795
|
tend = time.time()
|
793
796
|
logger.info("Elapsed time %d s Status %s",
|
794
797
|
(tend-tstart), status)
|
798
|
+
if any([x != 'C' for x in status]):
|
799
|
+
raise ValueError("AC simulation failed")
|
795
800
|
# collect results
|
796
|
-
results = []
|
797
|
-
errors = []
|
798
|
-
for t in job.tasks:
|
799
|
-
if t.status == 'C':
|
800
|
-
results.append(t.get_results())
|
801
|
-
else:
|
802
|
-
logger.warning("Status %s", t.status)
|
803
|
-
results.append({})
|
801
|
+
results = [t.get_results() for t in job.tasks]
|
804
802
|
|
805
803
|
i1_0 = results[0]['i1_0'].tolist()
|
806
804
|
psi1_0 = results[0]['psi1_0'].tolist()
|
femagtools/machine/sm.py
CHANGED
@@ -187,7 +187,7 @@ def parident(workdir, engine, machine,
|
|
187
187
|
|
188
188
|
if simulation['calculationMode'] == 'ld_lq_fast':
|
189
189
|
dqpars = dict(m=3, p=b['machine']['p'],
|
190
|
-
r1=r1,
|
190
|
+
r1=float(r1),
|
191
191
|
r2=machine['rotor'].get('resistance', 1),
|
192
192
|
rotor_mass=rotor_mass, kfric_b=1,
|
193
193
|
ldq=[dict(
|
@@ -434,7 +434,7 @@ class SynchronousMachine(object):
|
|
434
434
|
def iqd_tmech(self, torque, n, disp=False, maxiter=500):
|
435
435
|
"""return currents for shaft torque with minimal losses"""
|
436
436
|
if torque > 0:
|
437
|
-
startvals = self.bounds[0][1], 0, self.bounds[-1][1]
|
437
|
+
startvals = self.bounds[0][1]/2, 0, self.bounds[-1][1]
|
438
438
|
else:
|
439
439
|
startvals = -self.bounds[0][1]/2, 0, self.bounds[-1][1]
|
440
440
|
|
femagtools/mcv.py
CHANGED
@@ -12,7 +12,7 @@ import pathlib
|
|
12
12
|
import struct
|
13
13
|
import math
|
14
14
|
import numpy as np
|
15
|
-
|
15
|
+
from scipy.interpolate import make_interp_spline
|
16
16
|
from six import string_types
|
17
17
|
import femagtools.losscoeffs as lc
|
18
18
|
|
@@ -99,7 +99,7 @@ def norm_pfe(B, pfe):
|
|
99
99
|
b = list(b)
|
100
100
|
b[-1] = Bv[n]
|
101
101
|
n += 1
|
102
|
-
pfunc =
|
102
|
+
pfunc = make_interp_spline(b, pfe[i])
|
103
103
|
m.append([float(pfunc(x))
|
104
104
|
for x in Bv[:n]] + [None]*(len(Bv)-n))
|
105
105
|
return Bv.tolist(), m
|
@@ -168,8 +168,7 @@ def recalc_bsin(curve):
|
|
168
168
|
if bi[0] > 0:
|
169
169
|
bi.insert(0, 0)
|
170
170
|
hi.insert(0, 0)
|
171
|
-
bh =
|
172
|
-
kind='cubic', assume_sorted=True)
|
171
|
+
bh = make_interp_spline(bi, hi)
|
173
172
|
for bx in c['bi'][2:]:
|
174
173
|
bt = bx*np.sin(2*np.pi/4/ndel*x)
|
175
174
|
nue = np.sum(bh(bt)/bt)/ndel
|
@@ -196,8 +195,7 @@ def recalc_hsin(curve):
|
|
196
195
|
if hi[0] > 0:
|
197
196
|
hi.insert(0, 0)
|
198
197
|
bi.insert(0, 0)
|
199
|
-
hb =
|
200
|
-
kind='cubic', assume_sorted=True)
|
198
|
+
hb = make_interp_spline(hi, bi)
|
201
199
|
for hx in c['hi'][2:]:
|
202
200
|
ht = hx*np.sin(2*np.pi/4/ndel*x)
|
203
201
|
bt = hb(ht)*np.sin(2*np.pi/4/ndel*x)
|
@@ -243,11 +241,12 @@ def approx(db2, curve, ctype):
|
|
243
241
|
if ctype in (DEMCRV, MAG_AC_CRV):
|
244
242
|
dhdbn = 0
|
245
243
|
k = len(bi2)-1
|
246
|
-
if
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
244
|
+
if k < len(curve['bi']):
|
245
|
+
if curve['bi'][k] - curve['bi'][k-1] > 0:
|
246
|
+
dhdbn = ((curve['hi'][k] - curve['h'][k-1])
|
247
|
+
/(curve['bi'][k] - curve['bi'][k-1]))
|
248
|
+
a.append(MUE0*dhdbn)
|
249
|
+
b.append(MUE0*curve['hi'][k] - dhdbn*curve['bi'][k])
|
251
250
|
else:
|
252
251
|
a.append(1.0)
|
253
252
|
b.append(MUE0*curve['hi'][-1]-curve['bi'][-1])
|
@@ -44,10 +44,16 @@ if not airgap_created then
|
|
44
44
|
nc_line(r2, 0.0, x2, y2, 0.0)
|
45
45
|
|
46
46
|
if m.tot_num_slot > m.num_sl_gen then
|
47
|
+
if inner_da_end == nil then
|
48
|
+
inner_da_end = inner_da_start
|
49
|
+
end
|
47
50
|
x3, y3 = pr2c(inner_da_end, alfa)
|
48
51
|
x4, y4 = pr2c(r1, alfa)
|
49
52
|
nc_line(x3, y3, x4, y4, 0, 0)
|
50
53
|
|
54
|
+
if outer_da_end == nil then
|
55
|
+
outer_da_end = outer_da_start
|
56
|
+
end
|
51
57
|
x3, y3 = pr2c(outer_da_end, alfa)
|
52
58
|
x4, y4 = pr2c(r2, alfa)
|
53
59
|
nc_line(x3, y3, x4, y4, 0, 0)
|
femagtools/utils.py
CHANGED
@@ -17,7 +17,7 @@ def fft(pos, y, pmod=0):
|
|
17
17
|
else:
|
18
18
|
#negative_periodic = np.abs(y[0] - y[-1])/np.max(y) > 1
|
19
19
|
# count zero crossings
|
20
|
-
ypos = np.asarray(y[:-1]) > 0
|
20
|
+
ypos = np.asarray(y[:-1])-np.mean(y[:-1]) > 0
|
21
21
|
nypos = ~ypos
|
22
22
|
nzc = len(((ypos[:-1] & nypos[1:])
|
23
23
|
| (nypos[:-1] & ypos[1:])).nonzero()[0])
|
femagtools/windings.py
CHANGED
@@ -179,10 +179,10 @@ class Winding(object):
|
|
179
179
|
nue = n
|
180
180
|
else:
|
181
181
|
nue = self.kw_order(n)
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
if q1 == q2: # integral slot winding
|
183
|
+
q = self.Q/2/self.m/self.p
|
184
|
+
nuep = nue/self.p
|
185
|
+
return np.sin(nuep*np.pi/2/self.m)/q/np.sin(nuep*np.pi/2/self.m/q)
|
186
186
|
k = 2 if self.l == 1 else 1
|
187
187
|
a = nue*k*np.pi/self.Q*Yk
|
188
188
|
t = self.Q//Qb
|
@@ -416,6 +416,13 @@ class Winding(object):
|
|
416
416
|
[[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)])
|
417
417
|
# complete if not basic winding:
|
418
418
|
Qb = self.Q//num_basic_windings(self.Q, self.p, self.l)
|
419
|
+
|
420
|
+
if not np.asarray(upper).size or not np.asarray(lower).size:
|
421
|
+
layers = 1
|
422
|
+
if layers == 1 and z[1]:
|
423
|
+
z = ([[d*s for s, d in zip(l, ld)] for l, ld in zip(lower, ldirs)],
|
424
|
+
[[d*s for s, d in zip(u, ud)] for u, ud in zip(upper, udirs)])
|
425
|
+
|
419
426
|
if max([abs(n) for m in z[0] for n in m]) < Qb:
|
420
427
|
return [[k + [-n+Qb//2 if n < 0 else -(n+Qb//2) for n in k]
|
421
428
|
for k in m] for m in z]
|