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.
- femagtools/__init__.py +1 -1
- femagtools/amela.py +2 -2
- femagtools/dxfsl/area.py +130 -26
- femagtools/dxfsl/conv.py +2 -14
- femagtools/dxfsl/converter.py +69 -12
- femagtools/dxfsl/fslrenderer.py +15 -13
- femagtools/dxfsl/geom.py +153 -82
- femagtools/dxfsl/journal.py +2 -2
- femagtools/dxfsl/machine.py +19 -15
- femagtools/dxfsl/shape.py +3 -0
- femagtools/ecloss.py +386 -2
- femagtools/femag.py +82 -9
- femagtools/fsl.py +52 -56
- femagtools/machine/pm.py +1 -1
- femagtools/machine/sm.py +16 -8
- femagtools/mcv.py +128 -124
- femagtools/me.py +13 -13
- femagtools/model.py +8 -2
- femagtools/plot/fieldlines.py +1 -1
- femagtools/plot/mcv.py +18 -0
- femagtools/plot/wdg.py +2 -2
- femagtools/svgfsl/converter.py +1 -1
- femagtools/templates/afm_rotor.mako +4 -0
- femagtools/templates/gen_hairpin_winding.mako +36 -45
- femagtools/templates/magnetIron.mako +1 -1
- femagtools/templates/magnetIron2.mako +1 -1
- femagtools/templates/magnetIron3.mako +1 -1
- femagtools/templates/magnetIron4.mako +1 -1
- femagtools/templates/magnetIron5.mako +1 -1
- femagtools/templates/magnetIronV.mako +1 -1
- femagtools/templates/magnetSector.mako +1 -1
- femagtools/templates/mesh-airgap.mako +12 -6
- femagtools/templates/prepare_thermal.mako +199 -61
- femagtools/windings.py +25 -20
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/METADATA +20 -20
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/RECORD +42 -43
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/WHEEL +1 -1
- tests/test_mcv.py +106 -1
- tests/test_windings.py +5 -0
- tests/test_mcvwriter.py +0 -96
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/LICENSE +0 -0
- {femagtools-1.7.9.dist-info → femagtools-1.8.1.dist-info}/entry_points.txt +0 -0
- {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
|
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[
|
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[
|
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
|
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
|
-
'
|
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
|
487
|
+
def prepare_model_with_dxf_or_svg(self, model):
|
471
488
|
from femagtools.dxfsl.converter import convert
|
472
|
-
|
473
|
-
|
474
|
-
|
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
|
478
|
-
|
479
|
-
if not os.path.isfile(
|
480
|
-
logger.error('File "%s" not found',
|
481
|
-
raise ValueError(f'File {
|
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'] =
|
485
|
-
params['show_plots'] =
|
502
|
+
params['split'] = fmt.get('split', False)
|
503
|
+
params['show_plots'] = fmt.get('plot', False)
|
486
504
|
params['write_fsl'] = True
|
487
|
-
params['airgap'] =
|
488
|
-
params['nodedist'] =
|
489
|
-
params['full_model'] =
|
490
|
-
params['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(
|
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 = {
|
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
|
-
|
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.
|
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
|
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
|
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
|
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
|
-
|
195
|
-
|
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
|
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.
|
741
|
-
|
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
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
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):
|