femagtools 1.8.3__py3-none-any.whl → 1.8.4__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/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]
|