femagtools 1.8.5__py3-none-any.whl → 1.8.7__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/isa7.py CHANGED
@@ -1418,6 +1418,13 @@ class Element(BaseEntity):
1418
1418
  """return True if the element has lamination properties"""
1419
1419
  return self.reluc != (1.0, 1.0) and self.mag == (0.0, 0.0)
1420
1420
 
1421
+ def remanence(self, temperature=20):
1422
+ """return remanence Brx, Bry at element
1423
+ Arguments:
1424
+ temperature: (float) temperature in °C"""
1425
+ br_temp_corr = 1. + self.br_temp_coef*(temperature - 20.)
1426
+ return self.mag[0]*br_temp_corr, self.mag[1]*br_temp_corr
1427
+
1421
1428
  def demagnetization(self, temperature=20):
1422
1429
  """return demagnetization Hx, Hy of this element"""
1423
1430
  return self.demag_b(self.flux_density(cosys='polar'), temperature)
@@ -1429,9 +1436,9 @@ class Element(BaseEntity):
1429
1436
  # assume polar coordinates of b
1430
1437
  pos = np.arctan2(self.center[1], self.center[0])
1431
1438
  #pos = 0 # cartesian
1432
- br_temp_corr = 1. + self.br_temp_coef*(temperature - 20.)
1433
- magn = np.sqrt(self.mag[0]**2 + self.mag[1]**2)*br_temp_corr
1434
- alfa = np.arctan2(self.mag[1], self.mag[0]) - pos
1439
+ mag = self.remanence(temperature)
1440
+ magn = np.sqrt(mag[0]**2 + mag[1]**2)
1441
+ alfa = np.arctan2(mag[1], mag[0]) - pos
1435
1442
  b1, b2 = b
1436
1443
  bpol = b1 * np.cos(alfa) + b2 * np.sin(alfa)
1437
1444
  reluc = abs(self.reluc[0]) / (4*np.pi*1e-7 * 1000)
@@ -1505,6 +1512,43 @@ class SuperElement(BaseEntity):
1505
1512
  """return area of this superelement"""
1506
1513
  return sum([e.area for e in self.elements])
1507
1514
 
1515
+ def get_rect_geom(self):
1516
+ """return rectangle parameters of superelement:
1517
+ x0, y0: center coordinates
1518
+ w, h: width and height
1519
+ alpha: angle of main axis"""
1520
+ bxy = np.array([n.xy for b in self.nodechains
1521
+ for n in b.nodes[:-1]])
1522
+ # center
1523
+ cxy = np.mean(bxy, axis=0)
1524
+ # corner points: calculate angles
1525
+ b = np.vstack((bxy[-1], bxy, bxy[0]))
1526
+ a = np.arctan2(b[1:, 1]-b[:-1, 1],
1527
+ b[1:, 0]- b[:-1, 0])
1528
+ peaks = np.where(np.abs(np.diff(a)) > 1)[0]
1529
+ c = bxy[peaks]
1530
+ # width and height
1531
+ dxy = np.linalg.norm(np.vstack(
1532
+ (bxy[:-1, :] - bxy[1:, :],
1533
+ bxy[-1, :] - bxy[0, :])), axis=1)
1534
+ dc = (np.sum(dxy[peaks[0]:peaks[1]]),
1535
+ np.sum(dxy[peaks[1]:peaks[2]]),
1536
+ np.sum(dxy[peaks[2]:peaks[3]]),
1537
+ np.sum(np.hstack(
1538
+ (dxy[peaks[3]:], dxy[:peaks[0]]))))
1539
+ w = np.mean(np.sort(dc)[-2:])
1540
+ area = self.area()
1541
+ h = area/w
1542
+ # angle of main axis
1543
+ i = np.argmax(dc)
1544
+ c = np.vstack((c, c[0]))
1545
+ alpha = np.arctan2(c[i+1, 1]-c[i, 1], c[i+1, 0]-c[i, 0])
1546
+ if alpha < 0:
1547
+ alpha += np.pi
1548
+ return {'w': w, 'h': h, 'x0': cxy[0], 'y0': cxy[1],
1549
+ 'area': area, 'alpha': alpha}
1550
+
1551
+
1508
1552
  class SubRegion(BaseEntity):
1509
1553
  def __init__(self, key, sr_type, color, name, nturns, curdir, wb_key,
1510
1554
  superelements, nodechains):
femagtools/losscoeffs.py CHANGED
@@ -20,6 +20,11 @@ def pfe_jordan(f, B, ch, fh, cw, fw, fb, fo, Bo):
20
20
  def pfe_steinmetz(f, B, cw, fw, fb, fo, Bo):
21
21
  return cw*(f/fo)**fw * (B/Bo)**fb
22
22
 
23
+ def pfe_modified_steinmetz(f, B, ch, cw, alpha, beta, fo, Bo):
24
+ return ch*(f/fo)*(B/Bo)**(alpha + B*beta) + cw*(f/fo)**2*(B/Bo)**2
25
+
26
+ def wbert(f, b, ch, cw, cx):
27
+ return (ch + cw*f)*b**2 + cx*f**0.5*b**1.5
23
28
 
24
29
  def fitsteinmetz(f, B, losses, Bo, fo, alpha0=1.0):
25
30
  """fit coeffs of
@@ -56,6 +61,30 @@ def fitsteinmetz(f, B, losses, Bo, fo, alpha0=1.0):
56
61
  fbx, y, (1.0, 1.0, 2.0))
57
62
  return fitp
58
63
 
64
+ def fit_modified_steinmetz(f, B, losses, Bo, fo):
65
+ """fit coeffs of modifeld steinmetz
66
+ losses(f,B)=ch*(f/fo)*(B/Bo)**(alpha + B*beta) + cw*(f/fo)**2*(B/Bo)**2
67
+ returns (ch, cw, alpha, beta)
68
+ """
69
+ pfe = losses
70
+ z = []
71
+ for i, fx in enumerate(f):
72
+ if fx:
73
+ if isinstance(B[0], float):
74
+ z += [(fx, bx, y)
75
+ for bx, y in zip(B, pfe[i])
76
+ if y]
77
+ else:
78
+ z += [(fx, bx, y)
79
+ for bx, y in zip(B[i], pfe[i])
80
+ if y]
81
+
82
+ fbx = np.array(z).T[0:2]
83
+ y = np.array(z).T[2]
84
+ fitp, cov = so.curve_fit(lambda x, ch, cw, alpha, beta: pfe_modified_steinmetz(
85
+ x[0], x[1], ch, cw, alpha, beta, fo, Bo),
86
+ fbx, y, (1.0, 1.0, 1.0, 1.0))
87
+ return fitp
59
88
 
60
89
  def fitjordan(f, B, losses, Bo, fo):
61
90
  """fit coeffs of
@@ -115,9 +144,6 @@ def fit_bertotti(f, B, losses):
115
144
  if j > 2:
116
145
  v.append(np.array((f[i0:j+i0], bb, y)).T.tolist())
117
146
 
118
- def wbert(f, b, ch, cw, cx):
119
- return (ch + cw*f)*b**2 + cx*f**0.5*b**1.5
120
-
121
147
  z = np.array([b for a in v for b in a]).T
122
148
  fbx = z[0:2]
123
149
  y = z[2]
@@ -15,6 +15,7 @@ from scipy.interpolate import make_interp_spline, RegularGridInterpolator, RectB
15
15
  from scipy.integrate import quad
16
16
  import copy
17
17
  from matplotlib.colors import to_rgb
18
+ from multiprocessing import Pool
18
19
 
19
20
  logger = logging.getLogger(__name__)
20
21
 
@@ -54,7 +55,8 @@ def _integrate(radius, pos, val):
54
55
  interp = RegularGridInterpolator((radius, pos), val)
55
56
  def func(x, y):
56
57
  return interp((x, y))
57
- return [quad(func, radius[0], radius[-1], args=(p,))[0]
58
+ return [quad(func, radius[0], radius[-1],
59
+ args=(p,), limit=200)[0]
58
60
  for p in pos]
59
61
 
60
62
 
@@ -62,7 +64,7 @@ def _integrate1d(radius, val):
62
64
  interp = make_interp_spline(radius, val, k=1)
63
65
  def func(x):
64
66
  return interp((x))
65
- return quad(func, radius[0], radius[-1])[0]
67
+ return quad(func, radius[0], radius[-1], limit=100)[0]
66
68
 
67
69
  def ld_interpol(i1, beta, v):
68
70
  '''interpolate Ld at beta angle 0°, -180°'''
@@ -152,7 +154,17 @@ def parident(workdir, engine, temp, machine,
152
154
  machine[wdgk].get('num_par_wdgs', 1))
153
155
 
154
156
  p = machine['poles']
155
- num_slices = kwargs.get('num_slices', 3)
157
+ if np.isscalar(machine['magnet']['afm_rotor']['rel_magn_width']):
158
+ num_slices = kwargs.get('num_slices', 3)
159
+ rmagw = num_slices*[machine['magnet']['afm_rotor']['rel_magn_width']]
160
+ else:
161
+ rmagw = machine['magnet']['afm_rotor']['rel_magn_width']
162
+ if len(rmagw) == 1:
163
+ num_slices = kwargs.get('num_slices', 3)
164
+ rmagw = num_slices*list(rmagw)
165
+ else:
166
+ num_slices = len(rmagw)
167
+
156
168
  lfe = get_arm_lengths(machine['outer_diam'],
157
169
  machine['inner_diam'],
158
170
  num_slices)
@@ -172,6 +184,8 @@ def parident(workdir, engine, temp, machine,
172
184
  "decision_vars": [
173
185
  {"values": pole_width,
174
186
  "name": "pole_width"},
187
+ {"values": rmagw,
188
+ "name": "magnet.afm_rotor.rel_magn_width"},
175
189
  {"values": lfe,
176
190
  "name": "lfe"},
177
191
  {"values": linspeed, "name": "speed"}
@@ -216,9 +230,11 @@ def parident(workdir, engine, temp, machine,
216
230
  else:
217
231
  nlresults = {"x": [], "f": []}
218
232
  i = 0
219
- for pw, le, sp in zip(pole_width, lfe, linspeed):
233
+
234
+ for pw, le, sp, rmw in zip(pole_width, lfe, linspeed, rmagw):
220
235
  nlmachine = {k: machine[k] for k in machine}
221
236
  nlmachine['pole_width'] = pw
237
+ nlmachine['magnet']['afm_rotor']['rel_magn_width'] = rmw
222
238
  nlmachine['lfe'] = le
223
239
  nlcalc.update({"speed": sp})
224
240
  nlsubdir = f'{workdir}/{i}'
@@ -237,10 +253,11 @@ def parident(workdir, engine, temp, machine,
237
253
  current_angles = nlresults['f'][0]['current_angles']
238
254
  results = []
239
255
  i = 0
240
- for l, pw in zip(lfe, pole_width):
256
+ for l, pw, rmw in zip(lfe, pole_width, rmagw):
241
257
  mpart = {k: machine[k] for k in machine if k != 'afm_rotor'}
242
258
  mpart['pole_width'] = pw
243
259
  mpart['lfe'] = l
260
+ mpart['magnet']['afm_rotor']['rel_magn_width'] = rmw
244
261
  subdir = f"{workdir}/{i}"
245
262
 
246
263
  simulation = dict(
@@ -296,12 +313,23 @@ def parident(workdir, engine, temp, machine,
296
313
  i += 1
297
314
 
298
315
  postp = []
299
- for results in [process(lfe, pole_width, machine, bch)
300
- for bch in zip(*[r['f'] for r in results])]:
301
- torque = np.mean(results.pop('torque'))
302
- results['torque'] = torque
303
- results.update(_psidq_ldq(results, nlresults))
304
- postp.append(results)
316
+ if kwargs.get('use_multiprocessing', True):
317
+ with Pool() as p:
318
+ for r in p.starmap(process,
319
+ [(lfe, pole_width, machine, bch)
320
+ for bch in zip(*[r['f']
321
+ for r in results])]):
322
+ torque = np.mean(r.pop('torque'))
323
+ r['torque'] = torque
324
+ r.update(_psidq_ldq(r, nlresults))
325
+ postp.append(r)
326
+ else:
327
+ for r in [process(lfe, pole_width, machine, bch)
328
+ for bch in zip(*[r['f'] for r in results])]:
329
+ torque = np.mean(r.pop('torque'))
330
+ r['torque'] = torque
331
+ r.update(_psidq_ldq(r, nlresults))
332
+ postp.append(r)
305
333
 
306
334
  r1 = postp[0]['r1']
307
335
  i1 = [r['i1'] for r in postp][::num_beta_steps]
@@ -396,6 +424,7 @@ def process(lfe, pole_width, machine, bch):
396
424
  n = len(rotpos[0])
397
425
  currents = [bch[0]['flux'][k][0]['current_k'][:n]
398
426
  for k in bch[0]['flux']]
427
+
399
428
  if len(pole_width) > 1:
400
429
  # check homogenity:
401
430
  if np.diff([len(d) for d in displ]).any():
@@ -427,6 +456,9 @@ def process(lfe, pole_width, machine, bch):
427
456
  for ux in bch[0]['flux'][k][0]['voltage_dpsi'][:-1]]
428
457
  for k in bch[0]['flux']}
429
458
  emf = [voltage[k][:n] for k in voltage]
459
+ fluxxy = {k: [scale_factor * np.array(flx)
460
+ for flx in bch[0]['flux'][k][0]['flux_k']]
461
+ for k in bch[0]['flux']}
430
462
  flux = [fluxxy[k][:n] for k in fluxxy]
431
463
 
432
464
  pos = (rotpos[0]/np.pi*180)
@@ -485,7 +517,6 @@ def process(lfe, pole_width, machine, bch):
485
517
  except KeyError as exc:
486
518
  #logger.warning("missing key %s", exc)
487
519
  pass
488
-
489
520
  return {
490
521
  'weights': weights.tolist(),
491
522
  'pos': pos.tolist(), 'r1': r1,
@@ -646,13 +677,20 @@ def _draw_vertical_slots(ax,
646
677
  color = _get_colors(color, delta)
647
678
  taus = 2*np.pi/Q
648
679
  for n in range(Q):
649
- beta = np.array([[n*taus+alpha[0], (n+1)*taus-alpha[0]],
650
- [(n+1)*taus-alpha[1], n*taus+alpha[1]]])
651
- ax.fill(np.hstack((r * np.cos(beta[0, 0]),
652
- (r[::-1] * np.cos(beta[0, 1]))))+xoff,
653
- np.hstack((r * np.sin(beta[0, 0]),
654
- (r[::-1] * np.sin(beta[0, 1]))))+yoff,
655
- facecolor=color[0], edgecolor=color[0])
680
+ beta0 = np.linspace(n*taus, n*taus + taus/2-alpha[0], 5)
681
+ beta1 = np.linspace(n*taus, n*taus + taus/2-alpha[1], 5)
682
+ xr = np.concatenate((
683
+ r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))+xoff
684
+ yr = np.concatenate((
685
+ r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))+yoff
686
+ ax.fill(xr, yr, color=color[0])
687
+ beta0 = np.linspace(n*taus + taus/2+alpha[0], (n+1)*taus, 5)
688
+ beta1 = np.linspace(n*taus + taus/2+alpha[1], (n+1)*taus, 5)
689
+ xr = np.concatenate((
690
+ r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))+xoff
691
+ yr = np.concatenate((
692
+ r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))+yoff
693
+ ax.fill(xr, yr, color=color[0])
656
694
 
657
695
 
658
696
  def vertical_plot(machine, ax):
@@ -669,7 +707,10 @@ def vertical_plot(machine, ax):
669
707
  model_type = machine['afmtype'][0:4]
670
708
  dy1 = machine['outer_diam']*1e3
671
709
  dy2 = machine['inner_diam']*1e3
672
- rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
710
+ try:
711
+ rel_magn_width = max(machine['magnet']['afm_rotor']['rel_magn_width'])
712
+ except TypeError:
713
+ rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
673
714
  Q = machine['stator']['num_slots']
674
715
  slot_width = machine['stator']['afm_stator']['slot_width']*1e3
675
716
  poles = machine['poles']
@@ -818,7 +859,10 @@ def horizontal_plot(machine, ax):
818
859
  model_type = machine['afmtype'][0:4]
819
860
  dy1 = machine['outer_diam']*1e3
820
861
  dy2 = machine['inner_diam']*1e3
821
- rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
862
+ try:
863
+ rel_magn_width = max(machine['magnet']['afm_rotor']['rel_magn_width'])
864
+ except TypeError:
865
+ rel_magn_width = machine['magnet']['afm_rotor']['rel_magn_width']
822
866
  magn_height = machine['magnet']['afm_rotor']['magn_height']*1e3
823
867
  magn_yoke_height = machine['magnet']['afm_rotor']['yoke_height']*1e3
824
868
 
@@ -911,6 +955,14 @@ class AFPM:
911
955
  except KeyError:
912
956
  raise ValueError("missing key afmtype")
913
957
 
958
+ if np.isscalar(machine['magnet']['afm_rotor']['rel_magn_width']):
959
+ rmagw = num_slices*[machine['magnet']['afm_rotor']['rel_magn_width']]
960
+ else:
961
+ rmagw = machine['magnet']['afm_rotor']['rel_magn_width']
962
+ if len(rmagw) == 1:
963
+ rmagw = num_slices*list(rmagw)
964
+ elif num_slices != len(rmagw):
965
+ num_slices = len(rmagw)
914
966
  lfe = get_arm_lengths(machine['outer_diam'],
915
967
  machine['inner_diam'],
916
968
  num_slices)
@@ -934,11 +986,20 @@ class AFPM:
934
986
  "name": "pole_width"},
935
987
  {"values": lfe,
936
988
  "name": "lfe"},
989
+ {"values": rmagw,
990
+ "name": "magnet.afm_rotor.rel_magn_width"},
937
991
  {"values": linspeed, "name": "speed"}
938
992
  ]
939
993
  }
994
+
940
995
  machine['pole_width'] = np.pi * machine['inner_diam']/machine['poles']
941
996
  machine['lfe'] = machine['outer_diam'] - machine['inner_diam']
997
+ try:
998
+ machine['magnet']['afm_rotor']['rel_magn_width'] = max(
999
+ machine['magnet']['afm_rotor']['rel_magn_width'])
1000
+ except TypeError:
1001
+ pass
1002
+
942
1003
  simulation['skew_displ'] = (simulation.get('skew_angle', 0)/180 * np.pi
943
1004
  * machine['inner_diam'])
944
1005
  nlresults = {}
femagtools/mcv.py CHANGED
@@ -298,6 +298,8 @@ class Mcv(object):
298
298
  # {'ch': 0, 'cw': 0, 'ch_freq':0, 'cw_freq':0}
299
299
  self.bertotti = {}
300
300
  # {'ch': 0, 'cw': 0, 'ce':0, 'ch_freq':0, 'cw_freq':0}
301
+ self.steinmetz_modified = {}
302
+ # {'ch': 0, 'cw': 0, 'ch_freq': 1, 'b_beta_coeff': 0, 'cw_freq': 2, 'b_coeff': 2}
301
303
  self.MC1_FE_SPEZ_WEIGTH = 7.65
302
304
  self.MC1_FE_SAT_MAGNETIZATION = 2.15
303
305
 
@@ -359,7 +361,7 @@ class Mcv(object):
359
361
  for k in wtrans:
360
362
  if wtrans[k] in data.keys():
361
363
  self.__setattr__(k, data[wtrans[k]])
362
- for k in ('bertotti', 'jordan', 'steinmetz'):
364
+ for k in ('bertotti', 'jordan', 'steinmetz', 'steinmetz_modified'):
363
365
  if k in data:
364
366
  self.__setattr__(k, data[k])
365
367
  self.curve = data['curve']
@@ -374,6 +376,13 @@ class Mcv(object):
374
376
  # assume jordan iron loss parameters
375
377
  for k in self.jordan:
376
378
  self.jordan[k] = getattr(self, transl[k])
379
+ # set loss coeffs when existing
380
+ try:
381
+ for k in ('bertotti', 'jordan', 'steinmetz', 'steinmetz_modified'):
382
+ if k in data:
383
+ self.__setattr__(k, data[k])
384
+ except:
385
+ pass
377
386
  return
378
387
 
379
388
  def rtrimValueList(self, vlist):
@@ -489,14 +498,24 @@ class Writer(Mcv):
489
498
  feloss: (str) iron loss method (bertotti, jordan)
490
499
  """
491
500
  curve = self._prepare(fillfac, recsin)
501
+ write_losses = True
492
502
  try:
493
503
  if feloss.lower() == 'bertotti':
494
504
  for k in self.bertotti:
495
505
  setattr(self, transl[k], self.bertotti[k])
496
- del self.losses
497
- else:
506
+ write_losses = False
507
+ elif feloss.lower() == 'jordan':
498
508
  for k in self.jordan:
499
509
  setattr(self, transl[k], self.jordan[k])
510
+ write_losses = False
511
+ elif feloss.lower() == 'steinmetz':
512
+ for k in self.steinmetz:
513
+ setattr(self, transl[k], self.steinmetz[k])
514
+ write_losses = False
515
+ elif feloss.lower() == 'modified steinmetz':
516
+ for k in self.steinmetz_modified:
517
+ setattr(self, transl[k], self.steinmetz_modified[k])
518
+ write_losses = False
500
519
  except AttributeError as e:
501
520
  logger.warning("%s", e)
502
521
  pass
@@ -578,7 +597,7 @@ class Writer(Mcv):
578
597
  self.writeBlock([self.mc1_angle[K], self.mc1_db2[K]])
579
598
 
580
599
  try:
581
- if not (self.mc1_ch_factor or self.mc1_cw_factor) and self.losses:
600
+ if not (self.mc1_ch_factor or self.mc1_cw_factor) and self.losses and write_losses:
582
601
  # fit loss parameters
583
602
  pfe = self.losses['pfe']
584
603
  f = self.losses['f']
@@ -611,12 +630,24 @@ class Writer(Mcv):
611
630
  float(self.mc1_fe_spez_weigth),
612
631
  float(self.mc1_fe_sat_magnetization)])
613
632
 
633
+ logger.info(f"fo = {float(self.mc1_base_frequency)}")
634
+ logger.info(f"Bo = {float(self.mc1_base_induction)}")
635
+ logger.info(f"ch = {float(self.mc1_ch_factor)}")
636
+ logger.info(f"cw = {float(self.mc1_cw_factor)}")
637
+ logger.info(f"ch_freq = {float(self.mc1_ch_freq_factor)}")
638
+ logger.info(f"cw_freq = {float(self.mc1_cw_freq_factor)}")
639
+ logger.info(f"b_coeff = {float(self.mc1_induction_factor)}")
640
+ logger.info(f"fr_spez_weight = {float(self.mc1_fe_spez_weigth)}")
641
+ logger.info(f"fe_sat_magnetization = {float(self.mc1_fe_sat_magnetization)}")
642
+
614
643
  if not hasattr(self, 'losses') or not self.losses:
615
644
  # new variables: ce factor for bertotti losses
616
645
  # b_beta_coeff for modified steinmetz
617
646
  try:
618
647
  self.writeBlock([float(self.mc1_ce_factor),
619
648
  float(self.mc1_induction_beta_factor)])
649
+ logger.info(f"ce = {float(self.mc1_ce_factor)}")
650
+ logger.info(f"b_beta_coeff = {float(self.mc1_induction_beta_factor)}")
620
651
  except:
621
652
  pass
622
653
  return
@@ -677,13 +708,18 @@ class Writer(Mcv):
677
708
  [0.0]*(M_LOSS_INDUCT - len(pl)))
678
709
  self.writeBlock(float(f))
679
710
  nrec += 1
680
- for m in range(M_LOSS_FREQ - nrec):
681
- self.writeBlock([0.0]*M_LOSS_INDUCT)
682
- self.writeBlock(0.0)
711
+
712
+ if write_losses:
713
+ for m in range(M_LOSS_FREQ - nrec):
714
+ self.writeBlock([0.0]*M_LOSS_INDUCT)
715
+ self.writeBlock(0.0)
683
716
 
684
717
  self.writeBlock([self.losses['cw'], self.losses['cw_freq'],
685
718
  self.losses['b_coeff'], self.losses['fo'],
686
719
  self.losses['Bo']])
720
+ logger.info("losses_cw = %f, losses_cw_freq = %f, losses_b_coeff = %f, losses_fo = %f, losses_Bo = %f",
721
+ self.losses['cw'], self.losses['cw_freq'],
722
+ self.losses['b_coeff'], self.losses['fo'], self.losses['Bo'])
687
723
  self.writeBlock([1])
688
724
  logger.info('Losses n freq %d n ind %d', nfreq, nind)
689
725
  except Exception as e:
@@ -1175,6 +1211,125 @@ class MagnetizingCurve(object):
1175
1211
  losses['fo'] = self.mcv[m]['fo']
1176
1212
 
1177
1213
 
1214
+ class MCVconvert:
1215
+ def __init__(self, bhdata):
1216
+ self.steinmetz = dict(cw=0, cw_freq=0, b_coeff=0)
1217
+ self.jordan = dict(ch=0, ch_freq=0, cw=0, cw_freq=0, b_coeff=0)
1218
+ self.bertotti = dict(ch=0, cw=0, ce=0)
1219
+ self.steinmetz_modified = dict(ch=0, cw=0, ch_freq=1, b_beta_coeff=0, cw_freq=2, b_coeff=2)
1220
+ self.losscalc = None
1221
+
1222
+ B = []
1223
+ f = [50.0, 100.0, 200.0, 400.0, 1000.0, 2000.0]
1224
+ pfe = []
1225
+ jordan = False
1226
+ bertotti = False
1227
+ modified_steinmetz = False
1228
+ flag = False
1229
+
1230
+ if "losses" in bhdata:
1231
+ # test if any nan in data
1232
+ for i in ("B", "f"):
1233
+ if np.any(np.isnan(bhdata["losses"][i])) or \
1234
+ np.any(np.isnan(bhdata["losses"][i])):
1235
+ flag = True
1236
+ for i in bhdata["losses"]['pfe']:
1237
+ if np.any(np.isnan(i)):
1238
+ flag = True
1239
+
1240
+ if 'losses' not in bhdata or flag:
1241
+ # check steinmetz or jordan
1242
+ bhdata.update({"losses": {"pfe": [], "f":[], "B": []}})
1243
+ B = bhdata["curve"][-1]["bi"]
1244
+ if "ch" in bhdata:
1245
+
1246
+ if "ce" in bhdata:
1247
+ if bhdata['ce'] > 1e-15:
1248
+ bertotti = True
1249
+
1250
+ if bhdata["ch"] > 1e-15 and bhdata['ce'] < 1e-15:
1251
+ jordan = True
1252
+
1253
+ else:
1254
+ jordan = True
1255
+
1256
+ #if (conditions for modified steinmetz):
1257
+ # modified_steinmetz = True
1258
+
1259
+ if jordan:
1260
+ self.losscalc = 'jordan'
1261
+ logger.info("calculating based on jordan...")
1262
+ for i in f:
1263
+ pfe.append(lc.pfe_jordan(i, np.array(B), bhdata['ch'], bhdata['ch_freq'], bhdata['cw'],
1264
+ bhdata['cw_freq'], bhdata['b_coeff'], 50, 1.5))
1265
+
1266
+ elif bertotti:
1267
+ self.losscalc = 'bertotti'
1268
+ logger.info("calculating based on bertotti")
1269
+ for i in f:
1270
+ pfe.append(lc.wbert(i, np.array(B), bhdata['ch'], bhdata['cw'], bhdata['ce']))
1271
+
1272
+ elif modified_steinmetz:
1273
+ self.losscalc = 'modified steinmetz'
1274
+ logger.info("calculating based on modified steinmetz...")
1275
+ for i in f:
1276
+ pfe.append(lc.pfe_modified_steinmetz(i, np.array(B), bhdata['ch'], bhdata['cw'], bhdata['b_coeff'], bhdata['b_beta_coeff'], 1, 1))
1277
+
1278
+ else: # steinmetz
1279
+ self.losscalc = 'steinmetz'
1280
+ logger.info("calculating based on steinmetz...")
1281
+ for i in f:
1282
+ pfe.append(lc.pfe_steinmetz(i, np.array(B), bhdata['cw'],
1283
+ bhdata['cw_freq'], bhdata['b_coeff'], 50, 1.5))
1284
+ bhdata['losses']['pfe'] = pfe
1285
+ bhdata['losses']['B'] = B
1286
+ bhdata['losses']['f'] = f
1287
+
1288
+ idx = 0
1289
+ for i, j in enumerate(bhdata['losses']['f']):
1290
+ if j == 0:
1291
+ idx = i
1292
+ break
1293
+ idx = idx - 1
1294
+ z = lc.fitsteinmetz(bhdata['losses']['f'][0:idx],
1295
+ bhdata['losses']['B'],
1296
+ bhdata['losses']['pfe'][0:idx],
1297
+ 1.5,
1298
+ 50)
1299
+
1300
+ for i, j in enumerate(self.steinmetz):
1301
+ self.steinmetz[j] = z[i]
1302
+ self.steinmetz.update({"Bo": 1.5, "fo": 50})
1303
+
1304
+ z = lc.fitjordan(bhdata['losses']['f'][0:idx],
1305
+ bhdata['losses']['B'],
1306
+ bhdata['losses']['pfe'][0:idx],
1307
+ 1.5,
1308
+ 50)
1309
+
1310
+ for i, j in enumerate(self.jordan):
1311
+ self.jordan[j] = z[i]
1312
+ self.jordan.update({"Bo": 1.5, "fo": 50})
1313
+
1314
+ z = lc.fit_bertotti(bhdata['losses']['f'][0:idx],
1315
+ bhdata['losses']['B'],
1316
+ bhdata['losses']['pfe'][0:idx])
1317
+
1318
+ for i, j in enumerate(self.bertotti):
1319
+ self.bertotti[j] = z[i]
1320
+ self.bertotti.update({"Bo": 1, "fo": 1, "alpha": 2.0, "ch_freq": 1.0, "cw_freq": 2.0, "b_coeff": 2.0})
1321
+
1322
+ z = lc.fit_modified_steinmetz(bhdata['losses']['f'][0:idx],
1323
+ bhdata['losses']['B'],
1324
+ bhdata['losses']['pfe'][0:idx], 1, 1)
1325
+
1326
+ for i,j in enumerate(self.steinmetz_modified):
1327
+ self.steinmetz_modified[j] = z[i]
1328
+ self.steinmetz_modified.update({"Bo": 1, "fo": 1})
1329
+
1330
+ bhdata['losses']['pfe'] = np.transpose(bhdata['losses']['pfe']).tolist() #len(B) rows and len(f) columns
1331
+
1332
+
1178
1333
  def read(filename):
1179
1334
  """read MC/MCV file and return mc dict"""
1180
1335
  mcv = Reader()
femagtools/multiproc.py CHANGED
@@ -56,7 +56,8 @@ class ProgressLogger(threading.Thread):
56
56
  ["progress_logger",
57
57
  f"{self.numTot}:{numOf}:{percent}:{' '.join(summary)}"])
58
58
  else:
59
- logger.info('collecting FE losses ...')
59
+ # TODO: log message might be misleading
60
+ logger.debug('collecting FE losses ...')
60
61
  return
61
62
 
62
63
  def stop(self):
femagtools/parstudy.py CHANGED
@@ -6,6 +6,7 @@ import scipy as sc
6
6
  import logging
7
7
  import glob
8
8
  import os
9
+ import re
9
10
  import time
10
11
  import shutil
11
12
  import functools
@@ -172,7 +173,8 @@ class ParameterStudy(object):
172
173
  else:
173
174
  workdir = pathlib.Path(self.femag.workdir)
174
175
  for d in workdir.glob('[0-9]*'):
175
- shutil.rmtree(d)
176
+ if re.search(r'^\d+$', d.name):
177
+ shutil.rmtree(d)
176
178
 
177
179
  extra_result_files = []
178
180
  if simulation.get('airgap_induc', False):
@@ -1,6 +1,7 @@
1
1
  """Creating plots
2
2
 
3
3
  """
4
+ from .machine import machine
4
5
  from .fluxdens import airgap, airgap_fft
5
6
  from .bch import torque, torque_fft, force, force_fft, \
6
7
  fluxdens_surface, winding_current, winding_flux, \