femagtools 1.8.17__py3-none-any.whl → 1.8.19__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/bch.py +23 -6
- femagtools/dxfsl/area.py +35 -23
- femagtools/dxfsl/areabuilder.py +97 -58
- femagtools/dxfsl/converter.py +11 -1
- femagtools/dxfsl/fslrenderer.py +3 -0
- femagtools/dxfsl/geom.py +265 -63
- femagtools/dxfsl/machine.py +128 -9
- femagtools/dxfsl/symmetry.py +20 -5
- femagtools/femag.py +27 -16
- femagtools/isa7.py +25 -22
- femagtools/machine/__init__.py +3 -1
- femagtools/machine/effloss.py +18 -4
- femagtools/machine/pm.py +88 -74
- femagtools/machine/sm.py +32 -21
- femagtools/mcv.py +4 -1
- femagtools/plot/bch.py +3 -1
- femagtools/plot/char.py +5 -16
- femagtools/plot/nc.py +67 -34
- femagtools/shortcircuit.py +18 -10
- femagtools/templates/psi-torq-rem.mako +4 -4
- femagtools/templates/statorKS1.mako +43 -0
- femagtools/utils.py +5 -4
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/METADATA +2 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/RECORD +31 -30
- tests/test_machine.py +1 -2
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/WHEEL +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/licenses/LICENSE +0 -0
- {femagtools-1.8.17.dist-info → femagtools-1.8.19.dist-info}/top_level.txt +0 -0
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.close_outer_winding_areas()
|
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)
|
@@ -1270,6 +1284,30 @@ class Machine(object):
|
|
1270
1284
|
def search_critical_elements(self, mindist):
|
1271
1285
|
self.geom.search_critical_elements(mindist)
|
1272
1286
|
|
1287
|
+
def create_arc_element(self,
|
1288
|
+
radius,
|
1289
|
+
startangle,
|
1290
|
+
endangle):
|
1291
|
+
arc = Arc(Element(center=self.center,
|
1292
|
+
radius=radius,
|
1293
|
+
start_angle=startangle*180/np.pi,
|
1294
|
+
end_angle=endangle*180/np.pi),
|
1295
|
+
color='darkred',
|
1296
|
+
linestyle='dotted')
|
1297
|
+
|
1298
|
+
node1 = self.geom.find_the_node(arc.p1)
|
1299
|
+
if node1 is None:
|
1300
|
+
self.geom.split_with_point(arc.p1)
|
1301
|
+
node1 = self.geom.find_the_node(arc.p1)
|
1302
|
+
node2 = self.geom.find_the_node(arc.p2)
|
1303
|
+
if node2 is None:
|
1304
|
+
self.geom.split_with_point(arc.p2)
|
1305
|
+
node2 = self.geom.find_the_node(arc.p2)
|
1306
|
+
assert(node1 is not None)
|
1307
|
+
assert(node2 is not None)
|
1308
|
+
logger.debug("ARC Node1=%s, Node2=%s", node1, node2)
|
1309
|
+
self.geom.add_element(arc, rtol=1e-3, atol=1e-3)
|
1310
|
+
|
1273
1311
|
def create_arc(self, radius,
|
1274
1312
|
color='red', linestyle='dotted',
|
1275
1313
|
attr=None):
|
@@ -1330,6 +1368,79 @@ class Machine(object):
|
|
1330
1368
|
self.endangle)
|
1331
1369
|
return self.geom.possible_magnet_in_the_middle(midangle)
|
1332
1370
|
|
1371
|
+
def separate_tooth_and_yoke(self, midangle):
|
1372
|
+
logger.debug("begin separate_tooth_and_yoke")
|
1373
|
+
wdg_list = self.geom.get_areas_of_type((AREA.TYPE_WINDINGS,))
|
1374
|
+
wdg_max_dist = 0.0
|
1375
|
+
wdg = None
|
1376
|
+
for w in wdg_list:
|
1377
|
+
if w.max_dist > wdg_max_dist:
|
1378
|
+
wdg_max_dist = w.max_dist
|
1379
|
+
wdg = w
|
1380
|
+
|
1381
|
+
tooth_list = self.geom.get_areas_of_type((AREA.TYPE_TOOTH,))
|
1382
|
+
tooth_max_dist = 0.0
|
1383
|
+
for tooth in tooth_list:
|
1384
|
+
tooth_max_dist = max(tooth_max_dist, tooth.max_dist)
|
1385
|
+
tooth_height = tooth_max_dist - self.geom.min_radius
|
1386
|
+
wdg_height = wdg_max_dist - self.geom.min_radius
|
1387
|
+
|
1388
|
+
logger.debug("HEIGHT TOOTH=%s, WINDINGS=%s", tooth_height, wdg_height)
|
1389
|
+
|
1390
|
+
if greater_equal(tooth_height, wdg_height * 0.9) and \
|
1391
|
+
less_equal(tooth_height, wdg_height * 1.1):
|
1392
|
+
logger.debug("Tooths are ok")
|
1393
|
+
return False # tooth ok
|
1394
|
+
|
1395
|
+
iron_list = self.geom.get_areas_of_irons()
|
1396
|
+
tooth_list = [iron for iron in iron_list
|
1397
|
+
if iron.close_to_ag and greater(iron.max_dist, wdg_max_dist, rtol=1e-2, atol=1e-2)]
|
1398
|
+
logger.debug("max winding dist = %s", wdg_max_dist)
|
1399
|
+
logger.debug("tooths = %s", len(tooth_list))
|
1400
|
+
wdg_nodes = [(distance(self.center, n), n) for n in wdg.list_of_nodes()]
|
1401
|
+
wdg_nodes.sort(reverse=True)
|
1402
|
+
|
1403
|
+
top_nodes = []
|
1404
|
+
other_nodes = []
|
1405
|
+
for d, n in wdg_nodes:
|
1406
|
+
if np.isclose(d, wdg.max_dist, rtol=1e-2, atol=1e-1):
|
1407
|
+
top_nodes.append((alpha_line(self.center, n), d, n))
|
1408
|
+
else:
|
1409
|
+
other_nodes.append((d, alpha_line(self.center, n), n))
|
1410
|
+
|
1411
|
+
a_right, d_right, n_right = (None, None, None)
|
1412
|
+
a_left, d_left, n_left = (None, None, None)
|
1413
|
+
|
1414
|
+
if not top_nodes:
|
1415
|
+
other_nodes.sort(reverse=True)
|
1416
|
+
for d, a, n in other_nodes:
|
1417
|
+
if a > midangle:
|
1418
|
+
if not a_left:
|
1419
|
+
a_left = a
|
1420
|
+
d_left = d
|
1421
|
+
n_left = n
|
1422
|
+
else:
|
1423
|
+
if not a_right:
|
1424
|
+
a_right = a
|
1425
|
+
d_right = d
|
1426
|
+
n_right = n
|
1427
|
+
if a_left and a_right:
|
1428
|
+
break
|
1429
|
+
if not (a_left and a_right):
|
1430
|
+
logger.debug("end separate_tooth_and_yoke: no arcs possible")
|
1431
|
+
return False # bad luck
|
1432
|
+
else:
|
1433
|
+
top_nodes.sort()
|
1434
|
+
a_right, d_right, n_right = top_nodes[0]
|
1435
|
+
a_left, d_left, n_left = top_nodes[0-1]
|
1436
|
+
node_right = self.geom.find_the_node(n_right)
|
1437
|
+
node_left = self.geom.find_the_node(n_left)
|
1438
|
+
|
1439
|
+
self.create_arc_element(d_right, self.startangle, a_right)
|
1440
|
+
self.create_arc_element(d_left, a_left, self.endangle)
|
1441
|
+
logger.debug("end separate_tooth_and_yoke")
|
1442
|
+
return True
|
1443
|
+
|
1333
1444
|
def create_mirror_lines_outside_windings(self):
|
1334
1445
|
logger.debug("create_mirror_lines_outside_windings")
|
1335
1446
|
|
@@ -1337,6 +1448,9 @@ class Machine(object):
|
|
1337
1448
|
logger.debug("end create_mirror_lines_outside_windings: not done")
|
1338
1449
|
return
|
1339
1450
|
|
1451
|
+
midangle = middle_angle(self.startangle, self.endangle)
|
1452
|
+
self.separate_tooth_and_yoke(midangle)
|
1453
|
+
|
1340
1454
|
radius = self.radius+10
|
1341
1455
|
ag_list = self.geom.detect_airgaps(self.center,
|
1342
1456
|
self.startangle, self.endangle,
|
@@ -1345,7 +1459,6 @@ class Machine(object):
|
|
1345
1459
|
radius_list = [(ag[0], (ag[0] + ag[1]) / 2, ag[1]) for ag in ag_list]
|
1346
1460
|
radius_list.sort(reverse=True)
|
1347
1461
|
|
1348
|
-
midangle = middle_angle(self.startangle, self.endangle)
|
1349
1462
|
line = Line(
|
1350
1463
|
Element(start=self.center,
|
1351
1464
|
end=point(self.center, radius, midangle)))
|
@@ -1353,10 +1466,11 @@ class Machine(object):
|
|
1353
1466
|
pts = self.geom.split_and_get_intersect_points(line, aktion=False)
|
1354
1467
|
pts.sort()
|
1355
1468
|
|
1469
|
+
arcs_created = False
|
1356
1470
|
p_critical = self.geom.critical_touch_point(pts)
|
1357
1471
|
if p_critical:
|
1358
1472
|
d_critical = distance(self.center, p_critical)
|
1359
|
-
logger.
|
1473
|
+
logger.debug("Critical Point: %s, len=%s", p_critical, d_critical)
|
1360
1474
|
sep_radius = self.get_iron_separator(radius_list)
|
1361
1475
|
logger.debug("Iron Separator found: %s", sep_radius)
|
1362
1476
|
if sep_radius > 0.0 and sep_radius < d_critical:
|
@@ -1367,8 +1481,15 @@ class Machine(object):
|
|
1367
1481
|
if r[1] < d_critical:
|
1368
1482
|
if self.create_arc(r[1]):
|
1369
1483
|
radius = r[1]
|
1484
|
+
arcs_created = True
|
1370
1485
|
break
|
1371
1486
|
|
1487
|
+
if arcs_created:
|
1488
|
+
self.geom.create_list_of_areas(delete=True)
|
1489
|
+
self.geom.search_subregions(self.startangle,
|
1490
|
+
self.endangle,
|
1491
|
+
False)
|
1492
|
+
|
1372
1493
|
# install line
|
1373
1494
|
line = Line(
|
1374
1495
|
Element(start=self.center,
|
@@ -1376,11 +1497,9 @@ class Machine(object):
|
|
1376
1497
|
|
1377
1498
|
pts = self.geom.split_and_get_intersect_points(line)
|
1378
1499
|
pts.sort()
|
1379
|
-
|
1380
1500
|
if self.geom.create_lines_outside_windings(pts):
|
1381
|
-
self.geom.area_list = []
|
1382
1501
|
logger.debug("create subregions again")
|
1383
|
-
self.geom.create_list_of_areas()
|
1502
|
+
self.geom.create_list_of_areas(delete=True)
|
1384
1503
|
self.geom.search_subregions(self.startangle,
|
1385
1504
|
self.endangle,
|
1386
1505
|
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:
|
femagtools/femag.py
CHANGED
@@ -79,6 +79,7 @@ def set_magnet_properties(model, simulation, magnets):
|
|
79
79
|
magn_temp = simulation.magn_temp
|
80
80
|
if 'material' not in model.magnet:
|
81
81
|
return
|
82
|
+
|
82
83
|
try:
|
83
84
|
material = model.magnet['material']
|
84
85
|
magnetMat = magnets.find(material)
|
@@ -95,19 +96,24 @@ def set_magnet_properties(model, simulation, magnets):
|
|
95
96
|
tempcoefmuer = (tempcoefbr-tempcoefhc)/(1+tempcoefhc*(magn_temp-20))
|
96
97
|
if 'temcoefmuer' in magnetMat:
|
97
98
|
tempcoefmuer = magnetMat['temcoefmuer']
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
if not hasattr(model, 'hc_min'):
|
100
|
+
for k in 'Hk', 'HcJ':
|
101
|
+
if k in magnetMat:
|
102
|
+
hcmin = magnetMat.get(k)
|
103
|
+
model.hc_min = hcmin * (1+tempcoefhc*(magn_temp-20))
|
104
|
+
break
|
105
|
+
if hasattr(model, 'hc_min'):
|
106
|
+
logger.info("hc_min %f", model.hc_min)
|
101
107
|
model.magnet['temp_prop']['relperm'] = \
|
102
108
|
(1+tempcoefmuer*(magn_temp-20))*relperm
|
103
109
|
if tempcoefbr:
|
104
110
|
model.magnet['temp_prop']['temcoefbr'] = tempcoefbr
|
105
111
|
if tempcoefhc:
|
106
112
|
model.magnet['temp_prop']['temcoefhc'] = tempcoefhc
|
107
|
-
|
108
113
|
except AttributeError:
|
109
114
|
pass
|
110
115
|
|
116
|
+
|
111
117
|
class BaseFemag(object):
|
112
118
|
def __init__(self, workdir, cmd, magnetizingCurves, magnets, condMat,
|
113
119
|
templatedirs=[]):
|
@@ -415,7 +421,8 @@ class BaseFemag(object):
|
|
415
421
|
except FileNotFoundError:
|
416
422
|
pass
|
417
423
|
|
418
|
-
return
|
424
|
+
return sorted(pathlib.Path(self.workdir).glob('*.PROT'),
|
425
|
+
key=lambda x: x.stat().st_mtime, reverse=True)[0].stem
|
419
426
|
|
420
427
|
def readResult(self, machine, simulation, bch=None):
|
421
428
|
if simulation:
|
@@ -460,14 +467,6 @@ class BaseFemag(object):
|
|
460
467
|
|
461
468
|
if not bch:
|
462
469
|
bch = self.read_bch(self.modelname)
|
463
|
-
if simulation['calculationMode'] == 'pm_sym_fast' or \
|
464
|
-
simulation['calculationMode'] == 'torq_calc':
|
465
|
-
if simulation.get('shortCircuit', False):
|
466
|
-
from .shortcircuit import shortcircuit
|
467
|
-
set_magnet_properties(self.model, simulation, self.magnets)
|
468
|
-
bch.scData = shortcircuit(self, machine, bch, simulation)
|
469
|
-
#bch.torque += bchsc.torque
|
470
|
-
#bch.demag += bchsc.demag
|
471
470
|
|
472
471
|
if 'airgap_induc' in simulation:
|
473
472
|
try:
|
@@ -477,6 +476,19 @@ class BaseFemag(object):
|
|
477
476
|
bch.airgap = ag.read(os.path.join(self.workdir, 'bag.dat'),
|
478
477
|
pmod=pmod)
|
479
478
|
|
479
|
+
if simulation['calculationMode'] == 'pm_sym_fast' or \
|
480
|
+
simulation['calculationMode'] == 'torq_calc':
|
481
|
+
if simulation.get('shortCircuit', False):
|
482
|
+
from .shortcircuit import shortcircuit
|
483
|
+
set_magnet_properties(self.model, simulation, self.magnets)
|
484
|
+
bch.scData = shortcircuit(self,
|
485
|
+
{'name': self.model.name,
|
486
|
+
'poles': self.model.poles,
|
487
|
+
'hc_min': self.model.get('hc_min', 0)},
|
488
|
+
bch, simulation)
|
489
|
+
#bch.torque += bchsc.torque
|
490
|
+
#bch.demag += bchsc.demag
|
491
|
+
|
480
492
|
if simulation.get('magnet_loss', False):
|
481
493
|
logger.info('Evaluating magnet losses...')
|
482
494
|
ops = range(len(bch.torque))
|
@@ -490,7 +502,7 @@ class BaseFemag(object):
|
|
490
502
|
|
491
503
|
if len(ops) != len(bch.losses):
|
492
504
|
magn_losses.insert(0, magn_losses[0])
|
493
|
-
|
505
|
+
|
494
506
|
magn_losses = [float(i) for i in magn_losses]
|
495
507
|
try:
|
496
508
|
for i in range(len(bch.losses)):
|
@@ -600,10 +612,9 @@ class Femag(BaseFemag):
|
|
600
612
|
os.remove(f)
|
601
613
|
|
602
614
|
def __call__(self, machine, simulation={},
|
603
|
-
options=['-b'], fsl_args=[]):
|
615
|
+
options=['-b'], fsl_args=[], fslfile='femag.fsl'):
|
604
616
|
"""setup fsl file, run calculation and return
|
605
617
|
BCH, ASM, TS or LOS results if any."""
|
606
|
-
fslfile = 'femag.fsl'
|
607
618
|
with open(os.path.join(self.workdir, fslfile), 'w') as f:
|
608
619
|
f.write('\n'.join(self.create_fsl(machine,
|
609
620
|
simulation)))
|
femagtools/isa7.py
CHANGED
@@ -1359,28 +1359,31 @@ class Isa7(object):
|
|
1359
1359
|
# prep dictionary for the loss calculation
|
1360
1360
|
pm_data = []
|
1361
1361
|
for i, se in enumerate(mag_spels):
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1362
|
+
try:
|
1363
|
+
ecp = [e.center for e in se.elements]
|
1364
|
+
geometry = se.get_rect_geom()
|
1365
|
+
|
1366
|
+
#= np.moveaxis(bxy, 1, 0)
|
1367
|
+
pd = dict(name='pm_data_se' + str(se.key),
|
1368
|
+
hm=geometry['h'],
|
1369
|
+
wm=geometry['w'],
|
1370
|
+
lm=self.arm_length,
|
1371
|
+
alpha=geometry['alpha'],
|
1372
|
+
ls=self.arm_length,
|
1373
|
+
sigma=cond,
|
1374
|
+
mur=mur,
|
1375
|
+
loadcase=ibeta,
|
1376
|
+
numpoles=poles,
|
1377
|
+
elcp=transform_coord(geometry, ecp),
|
1378
|
+
area=se.area(),
|
1379
|
+
spel_key=se.key)
|
1380
|
+
if ibeta != None:
|
1381
|
+
pd.update({'bl': self.get_magnet_flux_density(se, icur, ibeta)})
|
1382
|
+
pd.update(pos)
|
1383
|
+
|
1384
|
+
pm_data.append(pd)
|
1385
|
+
except IndexError as e:
|
1386
|
+
logger.warning("se %d magnet geometry ignored: %s", i, e)
|
1384
1387
|
return pm_data
|
1385
1388
|
|
1386
1389
|
def get_magnet_flux_density(self, se, icur, ibeta) -> list:
|
femagtools/machine/__init__.py
CHANGED
@@ -32,7 +32,7 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
32
32
|
PM, EESM or IM"""
|
33
33
|
rlfe = lfe
|
34
34
|
rwdg = wdg
|
35
|
-
opts = {k: eecpars[k] for k in ('zeta1', 'gam', 'kh', 'kpfe',
|
35
|
+
opts = {k: eecpars[k] for k in ('zeta1', 'gam', 'kh', 'kpfe', 'kpfe_s', 'kpfe_r',
|
36
36
|
'kfric_b', 'kpmag') if k in eecpars}
|
37
37
|
try:
|
38
38
|
opts['rotor_mass'] = rlfe*eecpars['rotor_mass']
|
@@ -51,6 +51,8 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
51
51
|
smpars = copy.deepcopy(eecpars)
|
52
52
|
smpars['tcu1'] = temp[0]
|
53
53
|
smpars['tcu2'] = temp[1]
|
54
|
+
# external inductances
|
55
|
+
opts["ls"] = eecpars.get('ls1', 0)*rwdg**2
|
54
56
|
if 'ldq' in smpars:
|
55
57
|
machine = SynchronousMachineLdq(smpars, lfe=rlfe, wdg=rwdg, **opts)
|
56
58
|
else:
|
femagtools/machine/effloss.py
CHANGED
@@ -252,6 +252,8 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
252
252
|
rb['n'] = None
|
253
253
|
rb['T'] = None
|
254
254
|
if 'n' not in rb:
|
255
|
+
if kwargs.get('i1max', 0):
|
256
|
+
kwargs['i1max'] = -kwargs['i1max']
|
255
257
|
rb = m.characteristics(-T, max(r['n']), u1, nsamples=nsamples,
|
256
258
|
with_mtpv=with_mtpv, with_mtpa=with_mtpa,
|
257
259
|
with_pmconst=with_pmconst, with_tmech=with_tmech,
|
@@ -267,13 +269,17 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
267
269
|
if isinstance(m, (SynchronousMachineLdq, SynchronousMachinePsidq)):
|
268
270
|
iq, id, iex = m.iqd_torque(T[-1])
|
269
271
|
i1max = betai1(iq, id)[1]
|
272
|
+
if kwargs.get("i1max", 0):
|
273
|
+
i1max = kwargs["i1max"]
|
270
274
|
w1type, tmax = m.w1_imax_umax(i1max, u1)
|
271
275
|
pmax = tmax*w1type/m.p
|
272
276
|
else:
|
273
277
|
iq, id = m.iqd_torque(T[-1])
|
274
|
-
|
278
|
+
i1max = betai1(iq, id)[1]
|
279
|
+
if kwargs.get("i1max", 0):
|
280
|
+
i1max = kwargs["i1max"]
|
281
|
+
w1type, tmax = m.w1_imax_umax(i1max, u1)
|
275
282
|
|
276
|
-
i1max = betai1(iq, id)[1]
|
277
283
|
logger.info("%s %s", n, T)
|
278
284
|
for nx in n:
|
279
285
|
w1 = 2*np.pi*nx*m.p
|
@@ -366,6 +372,10 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
366
372
|
if isinstance(m, PmRelMachine):
|
367
373
|
plfe1 = m.kpfe*m.iqd_plfe1(*iqd, f1)
|
368
374
|
plfe2 = m.kpfe*m.iqd_plfe2(iqd[0], iqd[1], f1)
|
375
|
+
if hasattr(m, 'kpfe_s'):
|
376
|
+
plfe1 = m.kpfe_s*m.iqd_plfe1(*iqd, f1)
|
377
|
+
if hasattr(m, 'kpfe_r'):
|
378
|
+
plfe2 = m.kpfe_r*m.iqd_plfe2(iqd[0], iqd[1], f1)
|
369
379
|
plmag = m.kpmag*m.iqd_plmag(iqd[0], iqd[1], f1)
|
370
380
|
plcu1 = m.iqd_plcu1(iqd[0], iqd[1], 2*np.pi*f1)
|
371
381
|
plcu2 = m.iqd_plcu2(*iqd)
|
@@ -379,6 +389,10 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
379
389
|
elif isinstance(m, SynchronousMachine):
|
380
390
|
plfe1 = m.kpfe*m.iqd_plfe1(*iqd, f1)
|
381
391
|
plfe2 = m.kpfe*m.iqd_plfe2(*iqd, f1)
|
392
|
+
if hasattr(m, 'kpfe_s'):
|
393
|
+
plfe1 = m.kpfe_s*m.iqd_plfe1(*iqd, f1)
|
394
|
+
if hasattr(m, 'kpfe_r'):
|
395
|
+
plfe2 = m.kpfe_r*m.iqd_plfe2(*iqd, f1)
|
382
396
|
plmag = np.zeros_like(plfe2)
|
383
397
|
plcu1 = m.iqd_plcu1(iqd[0], iqd[1], f1)
|
384
398
|
try:
|
@@ -431,7 +445,7 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
431
445
|
e = pm / p1
|
432
446
|
else:
|
433
447
|
e = p1 / pm
|
434
|
-
eta.append(e)
|
448
|
+
eta.append(float(e))
|
435
449
|
|
436
450
|
return dict(
|
437
451
|
iq=iqd[0].tolist(),
|
@@ -450,4 +464,4 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
450
464
|
plfric=plfric.tolist(),
|
451
465
|
losses=ploss.tolist(),
|
452
466
|
plcu1_dc=plcu1_dc,
|
453
|
-
plcu1_ac=plcu1_ac)
|
467
|
+
plcu1_ac=plcu1_ac)
|