femagtools 1.8.6__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/__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):