femagtools 1.8.5__py3-none-any.whl → 1.8.7__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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, \