femagtools 1.7.9__py3-none-any.whl → 1.8.1__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.
Files changed (43) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/amela.py +2 -2
  3. femagtools/dxfsl/area.py +130 -26
  4. femagtools/dxfsl/conv.py +2 -14
  5. femagtools/dxfsl/converter.py +69 -12
  6. femagtools/dxfsl/fslrenderer.py +15 -13
  7. femagtools/dxfsl/geom.py +153 -82
  8. femagtools/dxfsl/journal.py +2 -2
  9. femagtools/dxfsl/machine.py +19 -15
  10. femagtools/dxfsl/shape.py +3 -0
  11. femagtools/ecloss.py +386 -2
  12. femagtools/femag.py +82 -9
  13. femagtools/fsl.py +52 -56
  14. femagtools/machine/pm.py +1 -1
  15. femagtools/machine/sm.py +16 -8
  16. femagtools/mcv.py +128 -124
  17. femagtools/me.py +13 -13
  18. femagtools/model.py +8 -2
  19. femagtools/plot/fieldlines.py +1 -1
  20. femagtools/plot/mcv.py +18 -0
  21. femagtools/plot/wdg.py +2 -2
  22. femagtools/svgfsl/converter.py +1 -1
  23. femagtools/templates/afm_rotor.mako +4 -0
  24. femagtools/templates/gen_hairpin_winding.mako +36 -45
  25. femagtools/templates/magnetIron.mako +1 -1
  26. femagtools/templates/magnetIron2.mako +1 -1
  27. femagtools/templates/magnetIron3.mako +1 -1
  28. femagtools/templates/magnetIron4.mako +1 -1
  29. femagtools/templates/magnetIron5.mako +1 -1
  30. femagtools/templates/magnetIronV.mako +1 -1
  31. femagtools/templates/magnetSector.mako +1 -1
  32. femagtools/templates/mesh-airgap.mako +12 -6
  33. femagtools/templates/prepare_thermal.mako +199 -61
  34. femagtools/windings.py +25 -20
  35. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/METADATA +20 -20
  36. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/RECORD +42 -43
  37. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/WHEEL +1 -1
  38. tests/test_mcv.py +106 -1
  39. tests/test_windings.py +5 -0
  40. tests/test_mcvwriter.py +0 -96
  41. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/LICENSE +0 -0
  42. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/entry_points.txt +0 -0
  43. {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/top_level.txt +0 -0
femagtools/fsl.py CHANGED
@@ -95,12 +95,12 @@ class Builder:
95
95
  if templ in ('statorFsl', 'dxf'):
96
96
  self.fsl_stator = True
97
97
 
98
- if templ != 'dxffile':
98
+ if templ not in ('dxffile', 'svgfile'):
99
99
  return
100
100
 
101
101
  from femagtools.dxfsl.converter import convert
102
102
  logger.info("Conv stator from %s",
103
- model.stator['dxffile']['name'])
103
+ model.stator[templ]['name'])
104
104
  params = {}
105
105
  params['split'] = model.stator[templ].get('split', False)
106
106
  params['show_plots'] = model.stator[templ].get('plot', False)
@@ -109,7 +109,7 @@ class Builder:
109
109
  params['nodedist'] = model.stator.get('nodedist', 1)
110
110
  pos = 'in' if model.external_rotor else 'out'
111
111
  params['part'] = ('stator', pos)
112
- conv = convert(model.stator['dxffile']['name'], **params)
112
+ conv = convert(model.stator[templ]['name'], **params)
113
113
 
114
114
  model.stator['num_slots'] = conv.get('tot_num_slot')
115
115
  model.set_value('poles', conv.get('num_poles'))
@@ -157,10 +157,18 @@ class Builder:
157
157
  + model.stator['dxf']['fsl'])
158
158
  if templ == 'statorFsl':
159
159
  # obsolete
160
+ th_props = [' ']
161
+ try:
162
+ th_props = [f'stator_density = {model.stator["density"]}',
163
+ f'stator_thcond = {model.stator["thcond"]}',
164
+ f'stator_thcap = {model.stator["thcap"]}',
165
+ ]
166
+ except:
167
+ pass
160
168
  if 'parameter' in model.stator['statorFsl']:
161
169
  return self.render_template(
162
170
  model.stator['statorFsl']['content_template'],
163
- model.stator['statorFsl']['parameter'])
171
+ model.stator['statorFsl']['parameter']) + th_props
164
172
  elif model.stator['statorFsl'].get('content'):
165
173
  return (['agndst = {}'.format(model.get('agndst', 1e-3)*1e3),
166
174
  'ndt(agndst)'] +
@@ -214,16 +222,24 @@ class Builder:
214
222
  .format(model.magnet.get('mcvkey_yoke', 'dummy')),
215
223
  "mcvkey_shaft = '{}'"
216
224
  .format(model.magnet.get('mcvkey_shaft', 'dummy'))]
217
-
218
225
  if 'magnetFsl' in model.magnet:
219
226
  self.fsl_rotor = True
220
227
  # obsolete
228
+ th_props = [' ']
229
+ try:
230
+ logger.info(model.magnet)
231
+ th_props = [f'rotor_density = {model["magnet"]["density"]}',
232
+ f'rotor_thcond = {model["magnet"]["thcond"]}',
233
+ f'rotor_thcap = {model["magnet"]["thcap"]}'
234
+ ]
235
+ except:
236
+ pass
221
237
  if 'parameter' in model.magnet['magnetFsl']:
222
238
  return mcv + self.render_template(
223
239
  model.magnet['magnetFsl']['content_template'],
224
- model.magnet['magnetFsl']['parameter'])
240
+ model.magnet['magnetFsl']['parameter']) + th_props
225
241
  elif model.magnet['magnetFsl'].get('content'):
226
- return mcv + model.magnet['magnetFsl']['content'].split('\n')
242
+ return mcv + model.magnet['magnetFsl']['content'].split('\n')
227
243
  if isinstance(model.magnet['magnetFsl']
228
244
  ['content_template'], str):
229
245
  with open(model.magnet['magnetFsl']
@@ -231,9 +247,8 @@ class Builder:
231
247
  templ = [l.strip() for l in f.readlines()]
232
248
  else:
233
249
  templ = model.magnet['magnetFsl']['content_template']
234
-
235
250
  return mcv + self.render_template(
236
- '\n'.join(templ),
251
+ '\n'.join(templ),
237
252
  model.magnet['magnetFsl'])
238
253
 
239
254
  templ = model.magnettype()
@@ -311,7 +326,7 @@ class Builder:
311
326
  if templ == 'dxf':
312
327
  # reuse dxfsl model
313
328
  self.fsl_rotor = True
314
- if templ != 'dxffile':
329
+ if templ not in ('dxffile', 'svgfile'):
315
330
  return
316
331
 
317
332
  from femagtools.dxfsl.converter import convert
@@ -367,7 +382,9 @@ class Builder:
367
382
  'beta = 360*m.npols_gen/m.num_poles',
368
383
  'x3,y3 = pd2c(dy1/2,beta+m.zeroangl)',
369
384
  'x4,y4 = pd2c(dy2/2,beta+m.zeroangl)',
370
- 'def_bcond_tp(x1,y1,x2,y2,x3,y3,x4,y4, 4)',
385
+ 'if m.b_min == 0 then',
386
+ ' def_bcond_tp(x1,y1,x2,y2,x3,y3,x4,y4, 4)',
387
+ 'end',
371
388
  'state_of_problem("mag_static")']
372
389
  return fslcmds
373
390
  return []
@@ -433,12 +450,12 @@ class Builder:
433
450
  return []
434
451
 
435
452
  def create_gen_winding(self, model):
436
- try:
453
+ try:
437
454
  model.winding['wire'].update(
438
455
  {"num_layers": model.winding["num_layers"]})
439
456
  genwdg = self.__render(model.winding,
440
457
  'gen_' + model.winding['wire'].get('name'))
441
- except:
458
+ except:
442
459
  genwdg = self.__render(model, 'gen_winding')
443
460
 
444
461
  k = list({'leak_dist_wind',
@@ -467,30 +484,31 @@ class Builder:
467
484
  'file_leak:close()'])
468
485
  return genwdg
469
486
 
470
- def prepare_model_with_dxf(self, model):
487
+ def prepare_model_with_dxf_or_svg(self, model):
471
488
  from femagtools.dxfsl.converter import convert
472
- dxfname = model.dxffile.get('name', None)
473
- if not dxfname:
474
- logger.error('Name of dxf-file expected')
489
+ fmt = model.dxffile if hasattr(model, 'dxffile') else model.svgfile
490
+ fname = fmt.get('name', None)
491
+ if not fname:
492
+ logger.error('Name of dxf or svg file expected')
475
493
  return []
476
494
 
477
- if dxfname.split('.')[-1] not in ('dxf', 'svg'): # add svg support
478
- dxfname += '.dxf'
479
- if not os.path.isfile(dxfname):
480
- logger.error('File "%s" not found', dxfname)
481
- raise ValueError(f'File {dxfname} not found')
495
+ if fname.split('.')[-1] not in ('dxf', 'svg'): # add svg support
496
+ fname += fmt[:3]
497
+ if not os.path.isfile(fname):
498
+ logger.error('File "%s" not found', fname)
499
+ raise ValueError(f'File {fname} not found')
482
500
 
483
501
  params = {}
484
- params['split'] = model.dxffile.get('split', False)
485
- params['show_plots'] = model.dxffile.get('plot', False)
502
+ params['split'] = fmt.get('split', False)
503
+ params['show_plots'] = fmt.get('plot', False)
486
504
  params['write_fsl'] = True
487
- params['airgap'] = model.dxffile.get('airgap', 0.0)
488
- params['nodedist'] = model.dxffile.get('nodedist', 1)
489
- params['full_model'] = model.dxffile.get('full_model', False)
490
- params['EESM'] = model.dxffile.get('type', 'PMSM') == 'EESM'
505
+ params['airgap'] = fmt.get('airgap', 0.0)
506
+ params['nodedist'] = fmt.get('nodedist', 1)
507
+ params['full_model'] = fmt.get('full_model', False)
508
+ params['EESM'] = fmt.get('type', 'PMSM') == 'EESM'
491
509
  if params['EESM']:
492
510
  model.rotor['EESM'] = {}
493
- conv = convert(dxfname, **params)
511
+ conv = convert(fname, **params)
494
512
 
495
513
  model.set_value('poles', conv.get('num_poles'))
496
514
  model.set_value('outer_diam', conv.get('dy1') * 1e-3)
@@ -524,7 +542,7 @@ class Builder:
524
542
  self.fsl_stator = True
525
543
  th_props = [' ']
526
544
  if model.stator.get('thcond', 0):
527
- th_props = [f'stator_density = {1e3*model.stator["density"]}',
545
+ th_props = [f'stator_density = {model.stator["density"]}',
528
546
  f'stator_thcond = {model.stator["thcond"]}',
529
547
  f'stator_thcap = {model.stator["thcap"]}',
530
548
  ]
@@ -538,10 +556,10 @@ class Builder:
538
556
  if 'fsl_rotor' in conv:
539
557
  self.fsl_rotor = True
540
558
  th_props = ['']
559
+ logger.info(model['magnet'])
541
560
  if hasattr(model, 'magnet'):
542
561
  if model['magnet'].get('thcond', 0):
543
- logger.info(model['magnet'])
544
- th_props = [f'rotor_density = {1e3*model["magnet"]["density"]}',
562
+ th_props = [f'rotor_density = {model["magnet"]["density"]}',
545
563
  f'rotor_thcond = {model["magnet"]["thcond"]}',
546
564
  f'rotor_thcap = {model["magnet"]["thcap"]}'
547
565
  ]
@@ -575,8 +593,8 @@ class Builder:
575
593
  magnetMat['magntemp'] = 20
576
594
  if model.is_complete():
577
595
  logger.info("create new model '%s'", model.name)
578
- if model.is_dxffile():
579
- self.prepare_model_with_dxf(model)
596
+ if model.is_dxffile() or model.is_svgfile():
597
+ self.prepare_model_with_dxf_or_svg(model)
580
598
  else:
581
599
  self.prepare_stator(model)
582
600
  if hasattr(model, 'magnet'):
@@ -617,28 +635,6 @@ class Builder:
617
635
  f'magn_thcap = {model["magnet"]["thcap_magnet"]}'
618
636
  ]
619
637
  rotor += th_props
620
- if model.is_dxffile() or 'dxf' in model['magnet']:
621
- rotor += ['if x0_shaft == 0.0 then',
622
- '-- add air layer (inside) for heat transfer',
623
- ' h = dy2/2/3',
624
- ' if h > 5 then',
625
- ' h = 3.8',
626
- ' end ',
627
- ' if m.zeroangl == nil then ',
628
- ' m.zeroangl = 0.0',
629
- ' end',
630
- ' beta = 360*m.npols_gen/m.num_poles',
631
- ' x0, y0 = pd2c(dy2/2, m.zeroangl)',
632
- ' x1, y1 = pd2c(dy2/2-h, m.zeroangl)',
633
- ' x2, y2 = pd2c(dy2/2-h, beta+m.zeroangl)',
634
- ' x3, y3 = pd2c(dy2/2, beta+m.zeroangl)',
635
- ' nc_line(x0, y0, x1, y1, 0)',
636
- ' nc_circle(x1, y1, x2, y2, 0)',
637
- ' nc_line(x2, y2, x3, y3, 0)',
638
- ' x0, y0 = pd2c(dy2/2-h/2, beta/2+m.zeroangl)',
639
- ' create_mesh_se(x0, y0)',
640
- 'end'
641
- ]
642
638
  else:
643
639
  rotor = self.create_rotor_model(
644
640
  model, condMat, ignore_material)
femagtools/machine/pm.py CHANGED
@@ -148,7 +148,7 @@ class PmRelMachine(object):
148
148
  kr = self.zeta1[0]*freq**3 + self.zeta1[1]*freq**2 + \
149
149
  self.zeta1[2]*freq + self.zeta1[3]
150
150
  kr[kr<1] = 1.
151
- return self.r1*(1 - self.kth1*(self.tcu1 - 20))*kr # ref 20°C
151
+ return self.r1*(1 + self.kth1*(self.tcu1 - 20))*kr # ref 20°C
152
152
  if self.skin_resistance is not None:
153
153
  return self.skin_resistance(self.r1, w, self.tcu1, kth=self.kth1)
154
154
 
femagtools/machine/sm.py CHANGED
@@ -339,6 +339,20 @@ class SynchronousMachine(object):
339
339
 
340
340
  def rstat(self, w):
341
341
  """stator resistance"""
342
+ if isinstance(self.zeta1, list):
343
+ # polyfit from ac loss calculation
344
+ freq = w/2/np.pi
345
+ kr = self.zeta1[0]*freq**3 + self.zeta1[1]*freq**2 + \
346
+ self.zeta1[2]*freq + self.zeta1[3]
347
+ if isinstance(kr, list):
348
+ kr = np.array(kr)
349
+ kr[kr<1.0] = 1.0
350
+ elif isinstance(kr, np.ndarray):
351
+ kr[kr<1.0] = 1.0
352
+ else:
353
+ if kr < 1.0:
354
+ kr = 1.0
355
+ return self.r1*(1 + self.kth1*(self.tcu1 - 20))*kr # ref 20°C
342
356
  sr = self.skin_resistance[0]
343
357
  if sr is not None:
344
358
  return sr(self.r1, w, self.tcu1, kth=self.kth1)
@@ -792,10 +806,7 @@ class SynchronousMachinePsidq(SynchronousMachine):
792
806
  if 'styoke_excess' in eecpars[idname][0]['losses'] and \
793
807
  np.any(np.array(eecpars[idname][0]['losses']['styoke_excess'])):
794
808
  self.bertotti = True
795
- keys.update({{
796
- 'styoke_excess': 1.5,
797
- 'stteeth_excess':1.5,
798
- 'rotor_excess': 1.5}})
809
+ keys += ['styoke_excess', 'stteeth_excess','rotor_excess']
799
810
  if islinear:
800
811
  pfe = {k: np.array([l['losses'][k]
801
812
  for l in eecpars[idname]])
@@ -912,10 +923,7 @@ class SynchronousMachineLdq(SynchronousMachine):
912
923
  if 'styoke_excess' in eecpars[idname][0]['losses'] and \
913
924
  np.any(np.array(eecpars[idname][0]['losses']['styoke_excess'])):
914
925
  self.bertotti = True
915
- keys.update({{
916
- 'styoke_excess': 1.5,
917
- 'stteeth_excess':1.5,
918
- 'rotor_excess': 1.5}})
926
+ keys += ['styoke_excess', 'stteeth_excess','rotor_excess']
919
927
 
920
928
  if islinear:
921
929
  pfe = {k: np.array([l['losses'][k]
femagtools/mcv.py CHANGED
@@ -103,6 +103,54 @@ def norm_pfe(B, pfe):
103
103
  for x in Bv[:n]] + [None]*(len(Bv)-n))
104
104
  return Bv.tolist(), m
105
105
 
106
+ def extrapol(crv, jsat=0, bmax=3):
107
+ """extends BH curve into saturation range"""
108
+ curve = copy.deepcopy(crv)
109
+ dh = curve['hi'][-1]-curve['hi'][-2]
110
+ db = curve['bi'][-1]-curve['bi'][-2]
111
+ mue_d = db/dh
112
+ mue = curve['bi'][-1]/curve['hi'][-1]
113
+ db = 3e-2*curve['bi'][-1]
114
+ b2 = 1.5
115
+
116
+ curve['muer'] = [b/MUE0/h if h>0 else float('nan')
117
+ for b, h in zip(curve['bi'],
118
+ curve['hi'])]
119
+
120
+ # extend bh-curve into saturation
121
+ while mue_d > 1.01*MUE0 and mue > 1.5*MUE0:
122
+ mue_d = MUE0 + (mue_d-MUE0)/np.sqrt(b2)
123
+ curve['bi'].append(curve['bi'][-1]+db)
124
+ curve['hi'].append(curve['hi'][-1]+db/mue_d)
125
+ curve['muer'].append(curve['bi'][-1]/MUE0/curve['hi'][-1])
126
+ b2 += 2
127
+ mue = curve['bi'][-1]/curve['hi'][-1]
128
+
129
+ # Fröhlich-Kennelly coefficients
130
+ if jsat:
131
+ hx = curve['hi'][-1]
132
+ bx = curve['bi'][-1]
133
+ fkb = 1./jsat
134
+ fka = (hx/(bx - MUE0*hx) - hx/jsat)
135
+ else:
136
+ Js1 = curve['bi'][-1] - MUE0*curve['hi'][-1]
137
+ Js0 = curve['bi'][-2] - MUE0*curve['hi'][-2]
138
+ fkb = ((curve['hi'][-1]/Js1 - curve['hi'][-2]/Js0)
139
+ /(curve['hi'][-1] - curve['hi'][-2]))
140
+ fka = curve['hi'][-1]/Js1 - fkb*curve['hi'][-1]
141
+ logger.debug("B values %d Fröhlich-Kennelly coeffs: a %f b %f",
142
+ len(curve['bi']), fka, fkb)
143
+ bstep = 0.15
144
+ bx = np.arange(curve['bi'][-1] + bstep, bmax, bstep)
145
+ # Fröhlich-Kennelly approximation
146
+ b = fkb * bx - MUE0*fka - 1
147
+ a = fkb * bx
148
+ c = MUE0*fka
149
+ nuer = (b + np.sqrt(b*b + 4*a*c))/2/a
150
+ curve['bi'] += bx.tolist()
151
+ curve['hi'] += (nuer*bx/MUE0).tolist()
152
+ return curve
153
+
106
154
 
107
155
  def recalc_bsin(curve):
108
156
  """recalculates B-H curve (static problems) into effective
@@ -159,7 +207,7 @@ def recalc_hsin(curve):
159
207
  return ncurve
160
208
 
161
209
 
162
- def approx(db2, curve):
210
+ def approx(db2, curve, ctype):
163
211
  """return nuer, bi2, a, b approx for curve"""
164
212
  nuek0 = (curve['hi'][1] - curve['hi'][0]) / \
165
213
  (curve['bi'][1]-curve['bi'][0])
@@ -191,12 +239,22 @@ def approx(db2, curve):
191
239
  nuer.append(MUE0*nuek1)
192
240
  bi2.append(bk12)
193
241
 
194
- a.append(1.0)
195
- b.append(MUE0*curve['hi'][-1]-curve['bi'][-1])
242
+ if ctype in (DEMCRV, MAG_AC_CRV):
243
+ dhdbn = 0
244
+ k = len(bi2)-1
245
+ if curve['bi'][k] - curve['bi'][k-1] > 0:
246
+ dhdbn = ((curve['hi'][k] - curve['h'][k-1],KK)
247
+ /(curve['bi'][k] - curve['bi'][k-1]))
248
+ a.append(MUE0*dhdbn)
249
+ b.append(MUE0*curve['hi'][k] - dhdbn*curve['bi'][k])
250
+ else:
251
+ a.append(1.0)
252
+ b.append(MUE0*curve['hi'][-1]-curve['bi'][-1])
196
253
  return dict(nuer=nuer, a=a, b=b, bi2=bi2)
197
254
 
198
255
 
199
256
  def fe_sat_mag(curve):
257
+ """returns maximum polarization of all BH curves"""
200
258
  fesat = 0
201
259
  for c in curve:
202
260
  js2 = c['bi'][-1] - MUE0*c['hi'][-1]
@@ -219,7 +277,7 @@ def findNotNone(l):
219
277
 
220
278
 
221
279
  class Mcv(object):
222
- def __init__(self):
280
+ def __init__(self, data={}):
223
281
  # default values from file: mcv.par
224
282
  self.ACT_VERSION_MC_CURVE = 0
225
283
  self.ORIENTED_VERSION_MC_CURVE = 1
@@ -248,7 +306,6 @@ class Mcv(object):
248
306
  self.mc1_induction_factor = self.MC1_INDUCTION_FACTOR
249
307
  self.mc1_induction_beta_factor = self.MC1_INDUCTION_BETA_FACTOR
250
308
  self.mc1_fe_spez_weigth = self.MC1_FE_SPEZ_WEIGTH
251
- self.mc1_fe_sat_magnetization = self.MC1_FE_SAT_MAGNETIZATION
252
309
 
253
310
  self.mc1_title = ''
254
311
  self.version_mc_curve = self.ACT_VERSION_MC_CURVE
@@ -274,26 +331,18 @@ class Mcv(object):
274
331
 
275
332
  self.mc1_energy = [[0]*self.MCURVES_MAX]*self.MC1_NIMAX
276
333
 
277
- def rtrimValueList(self, vlist):
278
- """cut list at first 0"""
279
- le = len(vlist)
280
- for i in range(le-1, -1, -1):
281
- if vlist[i] != 0.:
282
- break
283
- return list(vlist[:i+1])
284
-
285
- def __getitem__(self, key):
286
- if key == 'ctype': # for compatibility purposes
287
- return self.mc1_type
288
- return getattr(self, key)
289
-
290
-
291
- class Writer(Mcv):
292
- def __init__(self, data=None):
293
- Mcv.__init__(self)
294
334
  if data:
295
335
  self.setData(data)
296
336
 
337
+ self.mc1_curves = len(self.curve)
338
+ if self.mc1_type == MAGCRV and self.mc1_curves > 1:
339
+ self.mc1_type = ORIENT_CRV
340
+ if self.mc1_type in (ORIENT_CRV, ORIENT_PM_CRV):
341
+ self.version_mc_curve = self.ORIENTED_VERSION_MC_CURVE
342
+ elif self.mc1_type == DEMCRV_BR:
343
+ self.version_mc_curve = self.PARAMETER_PM_CURVE
344
+
345
+
297
346
  def __setattr__(self, key, val):
298
347
  try:
299
348
  self.__dict__[key] = val
@@ -317,6 +366,24 @@ class Writer(Mcv):
317
366
  pass
318
367
  return
319
368
 
369
+ def rtrimValueList(self, vlist):
370
+ """cut list at first 0"""
371
+ le = len(vlist)
372
+ for i in range(le-1, -1, -1):
373
+ if vlist[i] != 0.:
374
+ break
375
+ return list(vlist[:i+1])
376
+
377
+ def __getitem__(self, key):
378
+ if key == 'ctype': # for compatibility purposes
379
+ return self.mc1_type
380
+ return getattr(self, key)
381
+
382
+
383
+ class Writer(Mcv):
384
+ def __init__(self, data=None):
385
+ Mcv.__init__(self, data)
386
+
320
387
  def getBlockLength(self, d):
321
388
  if isinstance(d, string_types) or isinstance(d, bytes):
322
389
  try:
@@ -374,11 +441,6 @@ class Writer(Mcv):
374
441
 
375
442
  def _prepare(self, fillfac, recsin):
376
443
  """prepare output format (internal use only)"""
377
- if self.mc1_type in (ORIENT_CRV, ORIENT_PM_CRV):
378
- self.version_mc_curve = self.ORIENTED_VERSION_MC_CURVE
379
- elif self.mc1_type == DEMCRV_BR:
380
- self.version_mc_curve = self.PARAMETER_PM_CURVE
381
-
382
444
  curve = copy.deepcopy(self.curve)
383
445
  if fillfac:
384
446
  alpha = fillfac/self.mc1_fillfac
@@ -392,17 +454,17 @@ class Writer(Mcv):
392
454
  if fillfac or recsin:
393
455
  if hasattr(self, 'mc1_fe_sat_magnetization'):
394
456
  self.mc1_fe_sat_magnetization = fe_sat_mag(curve)
395
- logger.info("%s Type: %d Num Curves %d",
457
+ logger.info("%s Type: %d (%s) Num Curves %d",
396
458
  self.name, self.version_mc_curve,
459
+ types[self.mc1_type],
397
460
  len(self.curve))
398
- self.mc1_curves = len(self.curve)
399
461
  self.mc1_ni = [min(len(c['hi']),
400
462
  len(c['bi']))
401
463
  for c in self.curve if 'hi' in c]
402
464
  self.mc1_db2 = [(c['bi'][-1]**2 - c['bi'][0]**2)/n
403
465
  for c, n in zip(curve, self.mc1_mi)]
404
466
  for db2, c in zip(self.mc1_db2, curve):
405
- c.update(approx(db2, c))
467
+ c.update(approx(db2, c, self.mc1_type))
406
468
  if not hasattr(self, 'mc1_fe_sat_magnetization'):
407
469
  self.mc1_fe_sat_magnetization = fe_sat_mag(curve)
408
470
  self.mc1_mi = [len(c['a'])
@@ -513,6 +575,7 @@ class Writer(Mcv):
513
575
  self.mc1_cw_factor = cw
514
576
  self.mc1_cw_freq_factor = beta
515
577
  self.mc1_induction_factor = gamma
578
+
516
579
  except AttributeError:
517
580
  pass
518
581
  self.writeBlock([float(self.mc1_base_frequency),
@@ -528,10 +591,10 @@ class Writer(Mcv):
528
591
  if not hasattr(self, 'losses') or not self.losses:
529
592
  # new variables: ce factor for bertotti losses
530
593
  # b_beta_coeff for modified steinmetz
531
- try:
532
- self.writeBlock([float(self.mc1_ce_factor),
594
+ try:
595
+ self.writeBlock([float(self.mc1_ce_factor),
533
596
  float(self.mc1_induction_beta_factor)])
534
- except:
597
+ except:
535
598
  pass
536
599
  return
537
600
 
@@ -599,7 +662,7 @@ class Writer(Mcv):
599
662
  logger.info('Losses n freq %d n ind %d', nfreq, nind)
600
663
  except Exception as e:
601
664
  logger.error("Exception %s", e, exc_info=True)
602
-
665
+
603
666
  def writeMcv(self, filename, fillfac=None, recsin=''):
604
667
  # windows needs this strip to remove '\r'
605
668
  filename = filename.strip()
@@ -612,7 +675,7 @@ class Writer(Mcv):
612
675
  else:
613
676
  binary = False
614
677
  self.fp = open(filename, "wb")
615
- logger.info("Write File %s, binary format %d", filename, binary)
678
+ logger.info("Write File %s, binary format", filename)
616
679
 
617
680
  self.writeBinaryFile(fillfac, recsin)
618
681
  self.fp.close()
@@ -737,8 +800,9 @@ class Reader(Mcv):
737
800
  if self.version_mc_curve == self.ORIENTED_VERSION_MC_CURVE or \
738
801
  self.version_mc_curve == self.PARAMETER_PM_CURVE:
739
802
  self.mc1_curves = int(line[4])
740
- logger.debug("MC file %s Version %s Curves %d",
741
- filename, self.version_mc_curve, self.mc1_curves)
803
+ logger.info("Read file %s %s Type: %d (%s) Num Curves %d",
804
+ filename, self.name, self.version_mc_curve,
805
+ types[self.mc1_type], self.mc1_curves)
742
806
  if self.mc1_type == DEMCRV_BR:
743
807
  self.mc1_angle[self.mc1_curves-1] = self.mc1_remz
744
808
 
@@ -873,7 +937,7 @@ class Reader(Mcv):
873
937
 
874
938
  self.ce = 0
875
939
  self.b_beta_coeff = 0
876
- try:
940
+ try:
877
941
  if not self.losses['f'][0]:
878
942
  self.fp.seek(-16, 1)
879
943
  res = self.readBlock([float]*2)
@@ -882,30 +946,33 @@ class Reader(Mcv):
882
946
  pass
883
947
 
884
948
  def get_results(self):
949
+ self.desc = self.mc1_title
950
+ self.fillfac = self.mc1_fillfac
951
+ #self.cversion = self.version_mc_curve
885
952
  result = {
886
- 'name': self.name,
887
- 'desc': self.mc1_title,
888
- 'cversion': self.version_mc_curve,
889
- 'ctype': self.mc1_type,
890
- 'recalc': self.mc1_recalc,
891
- 'remz': self.mc1_remz,
892
- 'bsat': self.mc1_bsat,
893
- 'bref': self.mc1_bref,
894
- 'fillfac': self.mc1_fillfac,
895
- 'fo': self.fo,
896
- 'Bo': self.Bo,
897
- 'ch': self.ch,
898
- 'ch_freq': self.ch_freq,
899
- 'cw': self.cw,
900
- 'ce': self.ce,
901
- 'b_beta_coeff': self.b_beta_coeff,
902
- 'cw_freq': self.cw_freq,
903
- 'b_coeff': self.b_coeff,
904
- 'rho': self.rho,
905
- 'fe_sat_mag': self.fe_sat_mag,
906
- 'curve': [{k: c[k] for k in ('hi', 'bi')}
907
- for c in self.curve]
908
- }
953
+ k: getattr(self, k) for k in (
954
+ 'name',
955
+ 'desc',
956
+ 'cversion',
957
+ 'ctype',
958
+ 'recalc',
959
+ 'remz',
960
+ 'bsat',
961
+ 'bref',
962
+ 'fillfac',
963
+ 'fo',
964
+ 'Bo',
965
+ 'ch',
966
+ 'ch_freq',
967
+ 'cw',
968
+ 'ce',
969
+ 'b_beta_coeff',
970
+ 'cw_freq',
971
+ 'b_coeff',
972
+ 'rho',
973
+ 'fe_sat_mag') if hasattr(self, k)}
974
+ result['curve'] = [{k: c[k] for k in ('hi', 'bi')}
975
+ for c in self.curve]
909
976
  try:
910
977
  if self.losses:
911
978
  result['losses'] = self.losses
@@ -1003,69 +1070,6 @@ class MagnetizingCurve(object):
1003
1070
  pass
1004
1071
  return None
1005
1072
 
1006
- def recalc(self):
1007
- for m in self.mcv:
1008
- curve = self.mcv[m]['curve'][0]
1009
- mi = MC1_MIMAX-2
1010
- dh = curve['hi'][-1]-curve['hi'][-2]
1011
- db = curve['bi'][-1]-curve['bi'][-2]
1012
- dmue_d = db/dh
1013
- dmue = curve['bi'][-1]/curve['hi'][-1]
1014
- db = 3e-2*curve['bi'][-1]
1015
- n3 = 1.5
1016
-
1017
- curve['muer'] = [b/MUE0/h
1018
- for b, h in zip(curve['bi'],
1019
- curve['hi'])]
1020
-
1021
- # extend bh-curve into saturation
1022
- while dmue_d > 1.01*MUE0 and dmue > 1.5*MUE0:
1023
- dmue_d = MUE0 + (dmue_d-MUE0)/np.sqrt(n3)
1024
- curve['bi'].append(curve['bi'][-1]+db)
1025
- curve['hi'].append(curve['hi'][-1]+db/dmue_d)
1026
- curve['muer'].append(curve['bi'][-1]/MUE0/curve['hi'][-1])
1027
- n3 += 0.2
1028
- dmue = curve['bi'][-1]/curve['hi'][-1]
1029
-
1030
- self.mcv[m]['db2'] = (curve['bi'][-1]**2 -
1031
- curve['bi'][0]**2)/(mi-1)
1032
- nuek0 = (curve['hi'][1] - curve['hi'][0]) / \
1033
- (curve['bi'][1]-curve['bi'][0])
1034
- for j1 in range(len(curve['bi'])):
1035
- bk02 = curve['bi'][j1]**2
1036
- if bk02 > 0:
1037
- break
1038
- curve['nuer'] = [MUE0*nuek0]
1039
- curve['bi2'] = [bk02]
1040
- curve['a'] = []
1041
- curve['b'] = []
1042
-
1043
- bk1 = 0.0
1044
- while bk1 <= curve['bi'][-1]:
1045
- bk12 = bk02 + self.mcv[m]['db2']
1046
- bk1 = np.sqrt(bk12)
1047
- j = 2
1048
- while j < len(curve['bi']) and bk1 <= curve['bi'][j]:
1049
- j += 1
1050
- j -= 1
1051
- bdel = curve['bi'][j] - curve['bi'][j1]
1052
- c1 = (curve['hi'][j] - curve['hi'][j1])/bdel
1053
- c2 = curve['hi'][j1] - c1*curve['bi'][j1]
1054
-
1055
- nuek1 = c1 + c2/bk1
1056
-
1057
- curve['a'].append(MUE0*(bk12*nuek0 -
1058
- bk02*nuek1)/self.mcv[m]['db2'])
1059
- curve['b'].append(MUE0*(nuek1 - nuek0)/self.mcv[m]['db2'])
1060
- nuek0 = nuek1
1061
- bk02 = bk12
1062
-
1063
- curve['nuer'].append(MUE0*nuek1)
1064
- curve['bi2'].append(bk12)
1065
-
1066
- curve['a'].append(1.0)
1067
- curve['b'].append(MUE0*curve['hi'][-1]-curve['bi'][-1])
1068
-
1069
1073
  def fix_name(self, name, fillfac=1.0):
1070
1074
  """return os compatible mcv name including fillfac"""
1071
1075
  if not self.find_by_name(name):