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.
@@ -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.start_corners = self.geom.get_corner_nodes(self.center,
584
- self.startangle)
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.info("Critical Point: %s, len=%s", p_critical, d_critical)
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)
@@ -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
- return self.check_one_area(mid_angle, a, result, rtol=rtol, atol=atol)
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
- hcj = magnetMat.get('HcJ', 0)
99
- if hcj:
100
- model.hc_min = -hcj * (1+tempcoefhc*(magn_temp-20))
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 list(pathlib.Path(self.workdir).glob('*.PROT'))[0].stem
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
- ecp = [e.center for e in se.elements]
1363
- geometry = se.get_rect_geom()
1364
-
1365
- #= np.moveaxis(bxy, 1, 0)
1366
- pd = dict(name='pm_data_se' + str(se.key),
1367
- hm=geometry['h'],
1368
- wm=geometry['w'],
1369
- lm=self.arm_length,
1370
- alpha=geometry['alpha'],
1371
- ls=self.arm_length,
1372
- sigma=cond,
1373
- mur=mur,
1374
- loadcase=ibeta,
1375
- numpoles=poles,
1376
- elcp=transform_coord(geometry, ecp),
1377
- area=se.area(),
1378
- spel_key=se.key)
1379
- if ibeta != None:
1380
- pd.update({'bl': self.get_magnet_flux_density(se, icur, ibeta)})
1381
- pd.update(pos)
1382
-
1383
- pm_data.append(pd)
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:
@@ -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:
@@ -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
- w1type, tmax = m.w1_imax_umax(betai1(iq, id)[1], u1)
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)