femagtools 1.8.6__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/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.8.6'
5
+ __version__ = '1.8.7'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2023-2024 Gamma Technology'
femagtools/bch.py CHANGED
@@ -1057,10 +1057,11 @@ class Reader:
1057
1057
  e.g. : idList[-450, -350, -250, -150, -50, 0]
1058
1058
  idList[-500, -400, -300, -200, -100, 0, 0]
1059
1059
  '''
1060
- diff = np.floor(np.abs(np.diff(idList)))
1061
- if idList[-1] == 0 and len(idList) > 2 and \
1062
- diff[-1] == 0:
1060
+ if list(idList).count(0) > 1: # femag writes duplicate id==0 values
1063
1061
  idList = idList[:-1]
1062
+ diff = np.floor(np.abs(np.diff(idList)))
1063
+ if n := np.trim_zeros(np.diff(diff)).size:
1064
+ idList = idList[:-n]
1064
1065
  return idList
1065
1066
 
1066
1067
  def __read_psidq(self, content):
@@ -1085,8 +1086,7 @@ class Reader:
1085
1086
  ncols = ncols-1
1086
1087
 
1087
1088
  id = np.reshape(m[0], (-1, ncols)).T[0]
1088
- if id[0] >= 0:
1089
- id = self.__removeTrailingZero(id)
1089
+ id = self.__removeTrailingZero(id)
1090
1090
  nrows = len(id)
1091
1091
  if nrows > 1 and id[nrows-1] < id[nrows-2]:
1092
1092
  nrows = nrows-1
@@ -1121,8 +1121,7 @@ class Reader:
1121
1121
  ncols = ncols-1
1122
1122
 
1123
1123
  id = np.reshape(m[0], (-1, ncols)).T[0]
1124
- if id[0] >= 0:
1125
- id = self.__removeTrailingZero(id)
1124
+ id = self.__removeTrailingZero(id)
1126
1125
  nrows = len(id)
1127
1126
  if nrows > 1 and id[nrows-1] < id[nrows-2]:
1128
1127
  nrows = nrows-1
@@ -1610,6 +1609,11 @@ class Reader:
1610
1609
  losses['staza'] = floatnan(rec[0])
1611
1610
  losses['stajo'] = floatnan(rec[1])
1612
1611
  losses['total'] += losses['staza']+losses['stajo']
1612
+
1613
+ elif content[i+1].split() == ['Iron', '----']:
1614
+ losses['rotfe'] = sum([floatnan(x) for x in rec])
1615
+ losses['total'] += losses['rotfe']
1616
+
1613
1617
  else:
1614
1618
  losses['rotfe'] = floatnan(rec[1])
1615
1619
  losses['total'] += losses['rotfe']
femagtools/femag.py CHANGED
@@ -61,43 +61,6 @@ def handle_process_output(filedes, outfile, log):
61
61
  pass
62
62
 
63
63
 
64
- def get_shortCircuit_parameters(bch, nload):
65
- try:
66
- if nload < 0:
67
- nload = 0
68
- if nload > 2:
69
- nload = 2
70
- if nload > 0:
71
- dqld = bch.dqPar['ld']
72
- dqlq = bch.dqPar['lq']
73
- dqpsim = bch.dqPar['psim']
74
- if len(dqld) <= nload or len(dqlq) <= nload or len(dqpsim) <= nload:
75
- ld = dqld[-1]/bch.armatureLength
76
- lq = dqlq[-1]/bch.armatureLength
77
- psim = dqpsim[-1]/bch.armatureLength
78
- else:
79
- ld = dqld[nload-1]/bch.armatureLength
80
- lq = dqlq[nload-1]/bch.armatureLength
81
- psim = dqpsim[nload-1]/bch.armatureLength
82
- else:
83
- ld = bch.machine['ld']/bch.armatureLength
84
- lq = bch.machine['lq']/bch.armatureLength
85
- psim = bch.machine['psim']/bch.armatureLength
86
- return dict(
87
- r1=bch.machine['r1'],
88
- ld=ld,
89
- lq=lq,
90
- psim=psim,
91
- num_pol_pair=bch.machine['p'],
92
- fc_radius=bch.machine['fc_radius'],
93
- lfe=bch.armatureLength/1e3,
94
- pocfilename=bch.machine['pocfile'],
95
- num_par_wdgs=bch.machine.get('num_par_wdgs', 0),
96
- calculationMode='shortcircuit')
97
- except (KeyError, AttributeError, IndexError):
98
- raise FemagError("missing pm/Rel-Sim results")
99
-
100
-
101
64
  def set_magnet_properties(model, simulation, magnets):
102
65
  """set temperature adapted magnet properties"""
103
66
  if not hasattr(model, 'magnet'):
@@ -449,7 +412,7 @@ class BaseFemag(object):
449
412
 
450
413
  return list(pathlib.Path(self.workdir).glob('*.PROT'))[0].stem
451
414
 
452
- def readResult(self, simulation, bch=None):
415
+ def readResult(self, machine, simulation, bch=None):
453
416
  if simulation:
454
417
  if simulation['calculationMode'] == "fieldcalc":
455
418
  nc = self.read_nc()
@@ -495,38 +458,11 @@ class BaseFemag(object):
495
458
  if simulation['calculationMode'] == 'pm_sym_fast' or \
496
459
  simulation['calculationMode'] == 'torq_calc':
497
460
  if simulation.get('shortCircuit', False):
498
- logger.info("short circuit simulation")
499
- simulation.update(
500
- get_shortCircuit_parameters(bch,
501
- simulation.get('initial', 2)))
502
-
503
- builder = femagtools.fsl.Builder(self.templatedirs)
461
+ from .shortcircuit import shortcircuit
504
462
  set_magnet_properties(self.model, simulation, self.magnets)
505
- fslcmds = (builder.open_model(self.model) +
506
- builder.create_shortcircuit(simulation))
507
- fslfile = 'shortcicuit.fsl'
508
- with open(os.path.join(self.workdir, fslfile), 'w') as f:
509
- f.write('\n'.join(fslcmds))
510
- self.run(fslfile) #, options?
511
- bchfile = self.get_bch_file(self.modelname)
512
- if bchfile:
513
- bchsc = femagtools.bch.Reader()
514
- logger.info("Read BCH {}".format(bchfile))
515
- with io.open(bchfile, encoding='latin1',
516
- errors='ignore') as f:
517
- bchsc.read(f)
518
- bch.scData = bchsc.scData
519
- for w in bch.flux:
520
- try:
521
- bch.flux[w] += bchsc.flux[w]
522
- bch.flux_fft[w] += bchsc.flux_fft[w]
523
- except (KeyError, IndexError):
524
- logging.debug(
525
- "No additional flux data in sc simulation")
526
- break
527
-
528
- bch.torque += bchsc.torque
529
- bch.demag += bchsc.demag
463
+ bch.scData = shortcircuit(self, machine, bch, simulation)
464
+ #bch.torque += bchsc.torque
465
+ #bch.demag += bchsc.demag
530
466
 
531
467
  if 'airgap_induc' in simulation:
532
468
  try:
@@ -699,8 +635,9 @@ class Femag(BaseFemag):
699
635
  setattr(self, "dy2", machine['stator']['dy2'])
700
636
  except:
701
637
  pass
638
+
702
639
  if simulation:
703
- return self.readResult(simulation)
640
+ return self.readResult(machine, simulation)
704
641
 
705
642
  return {'status': 'ok', 'message': self.modelname,
706
643
  'model': self.model.props()}
@@ -801,6 +738,7 @@ class ZmqFemag(BaseFemag):
801
738
  def subscribe(self, notify):
802
739
  """attaches a notify function"""
803
740
  logger.info("Subscribe on '%s' port %d", self.femaghost, self.port+1)
741
+ femagtools.zmq.SubscriberTask.clear()
804
742
  if self.subscriber is None:
805
743
  # progress/xyplot at a configured timestep published
806
744
  header = [b'progress', b'xyplot', b'license']
femagtools/fsl.py CHANGED
@@ -227,7 +227,7 @@ class Builder:
227
227
  # obsolete
228
228
  th_props = [' ']
229
229
  try:
230
- logger.info(model.magnet)
230
+ logger.debug(model.magnet)
231
231
  th_props = [f'rotor_density = {model["magnet"]["density"]}',
232
232
  f'rotor_thcond = {model["magnet"]["thcond"]}',
233
233
  f'rotor_thcap = {model["magnet"]["thcap"]}'
@@ -750,8 +750,11 @@ class Builder:
750
750
  sim['eccentricity'])
751
751
 
752
752
  if sim.get('calculationMode') == 'pm_sym_f_cur':
753
- if 'nload_ex_cur' in sim.keys(): # convert obsolete key
754
- sim['noload_ex_cur'] = sim.pop('nload_ex_cur')
753
+ if sim.get('nload_ex_cur', ''): # convert obsolete key
754
+ if isinstance(sim, dict):
755
+ sim['noload_ex_cur'] = sim.pop('nload_ex_cur')
756
+ else:
757
+ sim.noload_ex_cur = sim.get('nload_ex_cur')
755
758
  felosses = custom_fefunc + self.create_fe_losses(sim)
756
759
  fslcalc = (displ_stator_rotor
757
760
  + self.__render(sim, sim.get('calculationMode'))
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]
@@ -687,9 +687,9 @@ def _draw_vertical_slots(ax,
687
687
  beta0 = np.linspace(n*taus + taus/2+alpha[0], (n+1)*taus, 5)
688
688
  beta1 = np.linspace(n*taus + taus/2+alpha[1], (n+1)*taus, 5)
689
689
  xr = np.concatenate((
690
- r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))
690
+ r[0]*np.cos(beta0), r[1]*np.cos(beta1[::-1])))+xoff
691
691
  yr = np.concatenate((
692
- r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))
692
+ r[0]*np.sin(beta0), r[1]*np.sin(beta1[::-1])))+yoff
693
693
  ax.fill(xr, yr, color=color[0])
694
694
 
695
695
 
@@ -707,7 +707,10 @@ def vertical_plot(machine, ax):
707
707
  model_type = machine['afmtype'][0:4]
708
708
  dy1 = machine['outer_diam']*1e3
709
709
  dy2 = machine['inner_diam']*1e3
710
- rel_magn_width = max(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']
711
714
  Q = machine['stator']['num_slots']
712
715
  slot_width = machine['stator']['afm_stator']['slot_width']*1e3
713
716
  poles = machine['poles']
@@ -856,7 +859,10 @@ def horizontal_plot(machine, ax):
856
859
  model_type = machine['afmtype'][0:4]
857
860
  dy1 = machine['outer_diam']*1e3
858
861
  dy2 = machine['inner_diam']*1e3
859
- rel_magn_width = max(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']
860
866
  magn_height = machine['magnet']['afm_rotor']['magn_height']*1e3
861
867
  magn_yoke_height = machine['magnet']['afm_rotor']['yoke_height']*1e3
862
868
 
@@ -988,8 +994,11 @@ class AFPM:
988
994
 
989
995
  machine['pole_width'] = np.pi * machine['inner_diam']/machine['poles']
990
996
  machine['lfe'] = machine['outer_diam'] - machine['inner_diam']
991
- machine['magnet']['afm_rotor']['rel_magn_width'] = max(
992
- machine['magnet']['afm_rotor']['rel_magn_width'])
997
+ try:
998
+ machine['magnet']['afm_rotor']['rel_magn_width'] = max(
999
+ machine['magnet']['afm_rotor']['rel_magn_width'])
1000
+ except TypeError:
1001
+ pass
993
1002
 
994
1003
  simulation['skew_displ'] = (simulation.get('skew_angle', 0)/180 * np.pi
995
1004
  * machine['inner_diam'])
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/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):