femagtools 1.8.12__py3-none-any.whl → 1.8.13__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/bch.py +21 -12
- femagtools/ecloss.py +12 -4
- femagtools/femag.py +1 -2
- femagtools/fsl.py +27 -3
- femagtools/job.py +6 -3
- femagtools/machine/__init__.py +35 -3
- femagtools/machine/effloss.py +37 -13
- femagtools/machine/im.py +9 -6
- femagtools/machine/sizing.py +4 -3
- femagtools/machine/sm.py +64 -69
- femagtools/parstudy.py +20 -14
- femagtools/plot/bch.py +1 -1
- femagtools/shortcircuit.py +15 -9
- femagtools/templates/ec-rotorbar.mako +2 -1
- femagtools/templates/gen_hairpin_winding.mako +8 -6
- femagtools/templates/ld_lq_fast.mako +1 -1
- femagtools/templates/mesh-airgap.mako +1 -0
- femagtools/templates/noloadflux-rot.mako +32 -4
- femagtools/templates/rotor_winding_ks2.mako +44 -0
- femagtools/templates/rotor_winding_ks2_ecSimulation.mako +44 -0
- femagtools/templates/statorRing.mako +1 -1
- femagtools/ts.py +38 -7
- femagtools/zmq.py +4 -1
- {femagtools-1.8.12.dist-info → femagtools-1.8.13.dist-info}/METADATA +3 -31
- {femagtools-1.8.12.dist-info → femagtools-1.8.13.dist-info}/RECORD +32 -31
- {femagtools-1.8.12.dist-info → femagtools-1.8.13.dist-info}/WHEEL +1 -1
- tests/test_bchreader.py +5 -5
- tests/test_femag.py +1 -1
- tests/test_fsl.py +3 -3
- femagtools-1.8.12.dist-info/LICENSE +0 -26
- {femagtools-1.8.12.dist-info → femagtools-1.8.13.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.12.dist-info → femagtools-1.8.13.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/bch.py
CHANGED
@@ -7,6 +7,7 @@ import numpy as np
|
|
7
7
|
import re
|
8
8
|
import logging
|
9
9
|
import logging.config
|
10
|
+
from .utils import fft
|
10
11
|
|
11
12
|
logger = logging.getLogger('femagtools.bch')
|
12
13
|
|
@@ -1375,10 +1376,14 @@ class Reader:
|
|
1375
1376
|
try:
|
1376
1377
|
w1 = np.pi*self.dqPar['speed']*self.dqPar['npoles']
|
1377
1378
|
r1 = self.machine.get('r1', 0.0)
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1379
|
+
pos = self.flux['1'][0]['displ']
|
1380
|
+
emfft = [fft(pos, f['voltage_dpsi']) for f in self.flux['1']]
|
1381
|
+
gamma = [emfft[0]['alfa0'] - e['alfa0'] for e in emfft[1:]]
|
1382
|
+
emf = np.array([e['a']/np.sqrt(2) for e in emfft[1:]])
|
1383
|
+
uq, ud = r1*iq + np.cos(gamma)*emf, r1*id + np.sin(gamma)*emf
|
1384
|
+
self.dqPar['u1'] = np.sqrt(uq**2 + ud**2).tolist()
|
1385
|
+
self.dqPar['gamma'] = (-np.arctan2(ud, uq)*180/np.pi).tolist()
|
1386
|
+
|
1382
1387
|
self.dqPar['psim0'] = lfe*self.dqPar['psim0']
|
1383
1388
|
self.dqPar['phi'] = [self.dqPar['beta'][0] +
|
1384
1389
|
self.dqPar['gamma'][0]]
|
@@ -1386,16 +1391,20 @@ class Reader:
|
|
1386
1391
|
for phi in self.dqPar['phi']]
|
1387
1392
|
self.dqPar['i1'].insert(0, 0)
|
1388
1393
|
self.dqPar['u1'].insert(0, self.dqPar.get('up0', 0))
|
1394
|
+
|
1389
1395
|
except KeyError:
|
1390
1396
|
pass
|
1391
1397
|
|
1392
|
-
# if next section is absent
|
1393
1398
|
try:
|
1394
|
-
self.dqPar['psid'] =
|
1395
|
-
self.dqPar['psiq'] =
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
+
self.dqPar['psid'] = np.cos(gamma)*emf/w1
|
1400
|
+
self.dqPar['psiq'] = -np.sin(gamma)*emf/w1
|
1401
|
+
except UnboundLocalError:
|
1402
|
+
try:
|
1403
|
+
self.dqPar['psid'] = [self.dqPar['psim'][0]]
|
1404
|
+
self.dqPar['psiq'] = [self.dqPar['lq'][0] *
|
1405
|
+
self.dqPar['i1'][-1]]
|
1406
|
+
except KeyError:
|
1407
|
+
pass
|
1399
1408
|
return # end of first section
|
1400
1409
|
|
1401
1410
|
# second DQ-Parameter section
|
@@ -1612,8 +1621,8 @@ class Reader:
|
|
1612
1621
|
|
1613
1622
|
elif content[i+1].split() == ['Iron', '----']:
|
1614
1623
|
losses['rotfe'] = sum([floatnan(x) for x in rec])
|
1615
|
-
losses['total'] += losses['rotfe']
|
1616
|
-
|
1624
|
+
losses['total'] += losses['rotfe']
|
1625
|
+
|
1617
1626
|
else:
|
1618
1627
|
losses['rotfe'] = floatnan(rec[1])
|
1619
1628
|
losses['total'] += losses['rotfe']
|
femagtools/ecloss.py
CHANGED
@@ -263,10 +263,11 @@ class MagnLoss:
|
|
263
263
|
for i in range((npos-1)//2 + 1) if i > 0])
|
264
264
|
npos_nonzero = np.argwhere(tmp_period > 0.1*np.amax(bxy_amp)).squeeze()
|
265
265
|
period = tmp_period[npos_nonzero]
|
266
|
-
|
267
266
|
if np.sum(np.around([period[0]%i for i in period])) == 0:
|
268
|
-
|
269
|
-
|
267
|
+
try:
|
268
|
+
npos = min(int(np.ceil(np.amax(period))+1), bxy.shape[2])
|
269
|
+
except:
|
270
|
+
pass
|
270
271
|
try:
|
271
272
|
self.tgrid = 60/self.speed*(self.theta[npos-1] - self.theta[0])/360
|
272
273
|
except AttributeError:
|
@@ -765,7 +766,12 @@ class MagnLoss:
|
|
765
766
|
i["wm"]*1e3, i["hm"]*1e3, i["lm"]*1e3,
|
766
767
|
(nsegx, nsegy, nsegz))
|
767
768
|
|
768
|
-
(nt, bx_fft, by_fft) = self.periodicity_id(i['bl'])
|
769
|
+
(nt, bx_fft, by_fft) = self.periodicity_id(i['bl'])
|
770
|
+
if self.tgrid == 0:
|
771
|
+
logger.warning(f"Time series couldn't be identified. Cannot calculate losses \
|
772
|
+
for loadcase {i['loadcase']}, superelement {i['spel_key']}")
|
773
|
+
all_load_cases.append(0)
|
774
|
+
continue
|
769
775
|
(nx, ny, nz, excpl_new, eycpl_new) = Segmentation(
|
770
776
|
i['wm'], i['hm'], i['lm'], i['elcp'],
|
771
777
|
nsegx, nsegy, nsegz)
|
@@ -778,6 +784,8 @@ class MagnLoss:
|
|
778
784
|
nx, ny, nsegx, nsegy, nt, i['elcp'], i['bl'], excpl_new, eycpl_new)
|
779
785
|
loss = self.loss_ialh2(sx_abs, sy_abs, sx_phase, sy_phase, freq_range,
|
780
786
|
nx, ny, wm, hm, lm, nsegx, nsegy, nsegz, delta_eff) * self.numpoles
|
787
|
+
if np.isnan(loss):
|
788
|
+
loss = 0
|
781
789
|
ialh_loss += loss
|
782
790
|
logger.info('Loadcase %d, Superelement %s, Total losses = %.3f W',
|
783
791
|
i["loadcase"], i["spel_key"], loss)
|
femagtools/femag.py
CHANGED
@@ -475,9 +475,8 @@ class BaseFemag(object):
|
|
475
475
|
if simulation.get('magnet_loss', False):
|
476
476
|
logger.info('Evaluating magnet losses...')
|
477
477
|
ops = range(len(bch.torque))
|
478
|
-
ncf = pathlib.Path(self.workdir) / self.modelname
|
479
478
|
m = femagtools.ecloss.MagnLoss(
|
480
|
-
nc=
|
479
|
+
nc=self.read_nc(), ibeta=ops)
|
481
480
|
try:
|
482
481
|
# change from ialh to ialh2: since v1.8.1
|
483
482
|
magn_losses = m.calc_losses_ialh2()
|
femagtools/fsl.py
CHANGED
@@ -287,12 +287,20 @@ class Builder:
|
|
287
287
|
if 'dxf' in rotmodel:
|
288
288
|
return mcv + ['ndt(agndst)'] + rotmodel['dxf']['fsl']
|
289
289
|
templ = 'rot_hsm'
|
290
|
+
if templ == 'rotorKs2':
|
291
|
+
if 'dxf' in rotmodel:
|
292
|
+
return mcv + ['ndt(agndst)'] + rotmodel['dxf']['fsl']
|
293
|
+
templ = 'rotorKs2'
|
290
294
|
rotmodel.update(model.rotor[templ])
|
291
295
|
return mcv + culosses + self.render_rotor(rotmodel, templ)
|
292
296
|
|
293
297
|
def create_rotor_winding(self, model):
|
298
|
+
if 'ecSimulation' in model.stator:
|
299
|
+
return self.render_rotor(model.rotor, 'rotor_winding_ks2_ecSimulation')
|
294
300
|
if hasattr(model, 'rotor') and model.rotortype() == 'EESM':
|
295
301
|
return self.render_rotor(model.rotor, 'rotor_winding')
|
302
|
+
if hasattr(model, 'rotor') and model.rotortype() == 'rotorKs2':
|
303
|
+
return self.render_rotor(model.rotor, 'rotor_winding_ks2')
|
296
304
|
return []
|
297
305
|
|
298
306
|
def prepare_magnet(self, model):
|
@@ -506,8 +514,11 @@ class Builder:
|
|
506
514
|
params['nodedist'] = fmt.get('nodedist', 1)
|
507
515
|
params['full_model'] = fmt.get('full_model', False)
|
508
516
|
params['EESM'] = fmt.get('type', 'PMSM') == 'EESM'
|
517
|
+
params['rotorKs2'] = fmt.get('type', 'PMSM') == 'rotorKs2'
|
509
518
|
if params['EESM']:
|
510
519
|
model.rotor['EESM'] = {}
|
520
|
+
if params['rotorKs2']:
|
521
|
+
model.rotor['rotorKs2'] = {}
|
511
522
|
conv = convert(fname, **params)
|
512
523
|
|
513
524
|
model.set_value('poles', conv.get('num_poles'))
|
@@ -550,6 +561,8 @@ class Builder:
|
|
550
561
|
if not (hasattr(model, 'magnet') or hasattr(model, 'rotor')):
|
551
562
|
if params['EESM']:
|
552
563
|
setattr(model, 'rotor', {})
|
564
|
+
elif params['rotorKs2']:
|
565
|
+
setattr(model, 'rotor', {})
|
553
566
|
else:
|
554
567
|
setattr(model, 'magnet', {})
|
555
568
|
|
@@ -659,14 +672,20 @@ class Builder:
|
|
659
672
|
self.mesh_airgap(model) +
|
660
673
|
self.create_connect_models(model) +
|
661
674
|
self.create_rotor_winding(model))
|
662
|
-
if 'statorRing' in model.stator:
|
675
|
+
if 'statorRing' in model.stator and 'ecSimulation' not in model.stator:
|
676
|
+
return (self.create_new_model(model) +
|
677
|
+
self.create_cu_losses(windings, condMat, ignore_material) +
|
678
|
+
self.create_fe_losses(model) +
|
679
|
+
rotor +
|
680
|
+
self.create_stator_model(model) +
|
681
|
+
self.create_rotor_winding(model))
|
682
|
+
if 'ecSimulation' in model.stator:
|
663
683
|
return (self.create_new_model(model) +
|
664
684
|
self.create_cu_losses(windings, condMat, ignore_material) +
|
665
685
|
self.create_fe_losses(model) +
|
666
686
|
rotor +
|
667
687
|
self.create_stator_model(model) +
|
668
688
|
self.create_rotor_winding(model))
|
669
|
-
|
670
689
|
return (self.create_new_model(model) +
|
671
690
|
self.create_cu_losses(windings, condMat, ignore_material) +
|
672
691
|
self.create_fe_losses(model) +
|
@@ -770,6 +789,12 @@ class Builder:
|
|
770
789
|
else:
|
771
790
|
plots = []
|
772
791
|
|
792
|
+
if sim.get('calculationMode') in ('cogg_calc',
|
793
|
+
'ld_lq_fast',
|
794
|
+
'pm_sym_loss',
|
795
|
+
'torq_calc',
|
796
|
+
'psd_psq_fast'):
|
797
|
+
return felosses + fslcalc + self.__render(sim, 'plots')
|
773
798
|
return felosses + fslcalc + plots
|
774
799
|
|
775
800
|
def create_shortcircuit(self, model):
|
@@ -858,7 +883,6 @@ class Builder:
|
|
858
883
|
self.fsl_stator = True
|
859
884
|
if magnet:
|
860
885
|
self.fsl_rotor = True
|
861
|
-
|
862
886
|
return template.render_unicode(model=model).split('\n')
|
863
887
|
|
864
888
|
def render_template(self, content_template, parameters):
|
femagtools/job.py
CHANGED
@@ -76,12 +76,14 @@ class Task(object):
|
|
76
76
|
def set_stateofproblem(self, stateofproblem):
|
77
77
|
self.stateofproblem = stateofproblem
|
78
78
|
|
79
|
-
def add_file(self, fname, content=None):
|
79
|
+
def add_file(self, fname, content=None, append=False):
|
80
80
|
"""adds a file required by this task
|
81
81
|
|
82
82
|
Args:
|
83
83
|
fname: file name
|
84
|
-
content: list of str written to file if not None
|
84
|
+
content: list of str written to file if not None
|
85
|
+
append: append file mode if true
|
86
|
+
"""
|
85
87
|
base = os.path.basename(fname)
|
86
88
|
self.transfer_files.append(fname)
|
87
89
|
if os.path.splitext(base)[-1] == '.fsl':
|
@@ -94,7 +96,8 @@ class Task(object):
|
|
94
96
|
return
|
95
97
|
|
96
98
|
# this file has to be created
|
97
|
-
|
99
|
+
fmode = 'a' if append else 'w'
|
100
|
+
with open(os.path.join(self.directory, base), fmode) as f:
|
98
101
|
f.writelines('\n'.join(content))
|
99
102
|
|
100
103
|
def get_results(self):
|
femagtools/machine/__init__.py
CHANGED
@@ -38,7 +38,6 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
38
38
|
opts['rotor_mass'] = rlfe*eecpars['rotor_mass']
|
39
39
|
except KeyError:
|
40
40
|
pass
|
41
|
-
|
42
41
|
if 'ldq' in eecpars or 'psidq' in eecpars: # this is a PM (or EESM)
|
43
42
|
try:
|
44
43
|
dqpars = eecpars['ldq']
|
@@ -65,8 +64,8 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
65
64
|
logger.warning(
|
66
65
|
"single temperature DQ parameters: unable to fit temperature %s", temp)
|
67
66
|
|
68
|
-
psid = rwdg*rlfe*dqp['psid']
|
69
|
-
psiq = rwdg*rlfe*dqp['psiq']
|
67
|
+
psid = rwdg*rlfe*np.array(dqp['psid'])
|
68
|
+
psiq = rwdg*rlfe*np.array(dqp['psiq'])
|
70
69
|
losses = __scale_losses(dqp['losses'], rlfe)
|
71
70
|
losses['ef'] = dqpars[-1]['losses'].get('ef', [2.0, 2.0])
|
72
71
|
losses['hf'] = dqpars[-1]['losses'].get('hf', [1.0, 1.0])
|
@@ -114,9 +113,42 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
114
113
|
pars['psi'] = [psi*rwdg*rlfe for psi in pars['psi']]
|
115
114
|
pars['tcu1'] = temp[0]
|
116
115
|
pars['tcu2'] = temp[1]
|
116
|
+
|
117
117
|
pars.update(opts)
|
118
118
|
return InductionMachine(pars)
|
119
|
+
|
120
|
+
|
121
|
+
def create_from_eecpars_im(temp, eecpars, lfe=1, wdg=1):
|
122
|
+
rlfe = lfe
|
123
|
+
rwdg = wdg
|
124
|
+
|
125
|
+
eecpars_new=eecpars['opResults']
|
126
|
+
opts = {k: eecpars_new[k] for k in ('zeta1', 'gam', 'kh', 'kpfe',
|
127
|
+
'kfric_b', 'kpmag') if k in eecpars_new}
|
128
|
+
|
129
|
+
pars = copy.deepcopy(eecpars_new)
|
130
|
+
|
131
|
+
pars['r1'] = rlfe*rwdg**2*pars.get('r1', 0)
|
132
|
+
pars['lsigma1'] = rlfe*pars['lsigma1']
|
133
|
+
pars['lsigma2'] = rlfe*pars['lsigma2']
|
134
|
+
pars['psiref'] = rwdg*rlfe*pars['psiref']
|
135
|
+
pars['u1ref'] = rwdg*rlfe*pars['u1ref']
|
136
|
+
pars['r2'] = rlfe*pars['r2']
|
137
|
+
pars['fec'] = rlfe*pars['fec']
|
138
|
+
pars['fee'] = rlfe*pars['fee']
|
139
|
+
pars['im'] = [im/rwdg for im in pars['im']]
|
140
|
+
pars['psi'] = [psi*rwdg*rlfe for psi in pars['psi']]
|
141
|
+
pars['tcu1'] = temp[0]
|
142
|
+
pars['tcu2'] = temp[1]
|
143
|
+
pars['nmax'] = eecpars['op']['nmax']
|
144
|
+
pars['umax'] = eecpars['op']['umax']
|
145
|
+
#pars['u1'] = eecpars['genDesign']['u1']
|
146
|
+
pars['Tmax'] = eecpars['op']['Tmax']
|
147
|
+
pars['p'] = eecpars['genDesign']['p']
|
148
|
+
pars['m'] = eecpars['genDesign']['m']
|
119
149
|
|
150
|
+
pars.update(opts)
|
151
|
+
return InductionMachine(pars)
|
120
152
|
|
121
153
|
def create(bch, r1, ls, lfe=1, wdg=1):
|
122
154
|
"""create PmRelMachine from BCH
|
femagtools/machine/effloss.py
CHANGED
@@ -10,7 +10,7 @@ from . import create_from_eecpars
|
|
10
10
|
logger = logging.getLogger("femagtools.effloss")
|
11
11
|
|
12
12
|
|
13
|
-
def iqd_tmech_umax(m, u1, with_mtpa, progress, speed_torque, iq, id, iex):
|
13
|
+
def iqd_tmech_umax(m, u1, with_mtpa, with_tmech, progress, speed_torque, iq, id, iex):
|
14
14
|
"""calculate iq, id for each load (n, T) from speed_torque at voltage u1
|
15
15
|
|
16
16
|
Args:
|
@@ -25,9 +25,14 @@ def iqd_tmech_umax(m, u1, with_mtpa, progress, speed_torque, iq, id, iex):
|
|
25
25
|
num_iv = round(nsamples/7)
|
26
26
|
try:
|
27
27
|
for i, nT in enumerate(speed_torque):
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
if with_tmech:
|
29
|
+
iqde = m.iqd_tmech_umax(
|
30
|
+
nT[1], 2*np.pi*nT[0]*m.p,
|
31
|
+
u1, with_mtpa=with_mtpa)[:-1]
|
32
|
+
else:
|
33
|
+
iqde = m.iqd_torque_umax(
|
34
|
+
nT[1], 2*np.pi*nT[0]*m.p,
|
35
|
+
u1, with_mtpa=with_mtpa)[:-1]
|
31
36
|
iq[i] = iqde[0]
|
32
37
|
id[i] = iqde[1]
|
33
38
|
if len(iqde) > 2:
|
@@ -39,7 +44,8 @@ def iqd_tmech_umax(m, u1, with_mtpa, progress, speed_torque, iq, id, iex):
|
|
39
44
|
finally:
|
40
45
|
progress.close()
|
41
46
|
|
42
|
-
def iqd_tmech_umax_multi(num_proc, ntmesh, m, u1, with_mtpa,
|
47
|
+
def iqd_tmech_umax_multi(num_proc, ntmesh, m, u1, with_mtpa, with_tmech,
|
48
|
+
publish=0):
|
43
49
|
"""calculate iqd for sm and pm using multiproc
|
44
50
|
"""
|
45
51
|
progress_readers = []
|
@@ -59,7 +65,7 @@ def iqd_tmech_umax_multi(num_proc, ntmesh, m, u1, with_mtpa, publish=0):
|
|
59
65
|
iex.append(multiprocessing.Array('d', chunksize))
|
60
66
|
iexk = iex[k]
|
61
67
|
p = multiprocessing.Process(target=iqd_tmech_umax,
|
62
|
-
args=(m, u1, with_mtpa,
|
68
|
+
args=(m, u1, with_mtpa, with_tmech,
|
63
69
|
prog_writer,
|
64
70
|
ntmesh.T[i:i+chunksize],
|
65
71
|
iq[k], id[k], iexk))
|
@@ -254,14 +260,26 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
254
260
|
rb['n'], rb['T'], npoints)
|
255
261
|
else:
|
256
262
|
nt = []
|
257
|
-
|
263
|
+
if isinstance(m, (SynchronousMachineLdq, SynchronousMachinePsidq)):
|
264
|
+
iq, id, iex = m.iqd_torque(T[-1])
|
265
|
+
else:
|
266
|
+
iq, id = m.iqd_torque(T[-1])
|
267
|
+
|
258
268
|
i1max = betai1(iq, id)[1]
|
259
269
|
logger.info("%s %s", n, T)
|
260
270
|
for nx in n:
|
261
271
|
w1 = 2*np.pi*nx*m.p
|
262
|
-
|
263
|
-
|
264
|
-
|
272
|
+
if isinstance(m, (SynchronousMachineLdq, SynchronousMachinePsidq)):
|
273
|
+
if with_tmech:
|
274
|
+
iq, id, iex, tq = m.iqd_tmech_umax(
|
275
|
+
T[-1], w1, u1)
|
276
|
+
else:
|
277
|
+
iq, id, iex, tq = m.iqd_torque_umax(
|
278
|
+
T[-1], w1, u1)
|
279
|
+
else:
|
280
|
+
iq, id, tq = m.iqd_imax_umax(i1max, w1, u1, T[-1],
|
281
|
+
with_tmech=with_tmech,
|
282
|
+
with_mtpa=with_mtpa)
|
265
283
|
if np.isclose(tq, T[-1]):
|
266
284
|
tq = T[-1]
|
267
285
|
for Tx in T:
|
@@ -276,7 +294,8 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
276
294
|
if isinstance(m, (PmRelMachine, SynchronousMachine)):
|
277
295
|
if num_proc > 1:
|
278
296
|
iqd = iqd_tmech_umax_multi(num_proc, ntmesh, m, u1, with_mtpa,
|
279
|
-
publish=progress)
|
297
|
+
with_tmech, publish=progress)
|
298
|
+
|
280
299
|
else:
|
281
300
|
class ProgressLogger:
|
282
301
|
def __init__(self, nsamples, publish):
|
@@ -353,8 +372,13 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
353
372
|
plfe2 = m.kpfe*m.iqd_plfe2(*iqd, f1)
|
354
373
|
plmag = np.zeros_like(plfe2)
|
355
374
|
plcu1 = m.iqd_plcu1(iqd[0], iqd[1], 2*np.pi*f1)
|
356
|
-
|
357
|
-
|
375
|
+
try:
|
376
|
+
plcu1_dc = m.iqd_plcu1(iqd[0], iqd[1],
|
377
|
+
np.array([0.0 for i in f1])).tolist()
|
378
|
+
plcu1_ac = [i-j for i, j in zip(plcu1.tolist(), plcu1_dc)]
|
379
|
+
except:
|
380
|
+
plcu1_dc, plcu1_ac = [], []
|
381
|
+
|
358
382
|
plcu2 = m.iqd_plcu2(*iqd)
|
359
383
|
tfric = m.tfric
|
360
384
|
logger.info("Iex %f %f",
|
femagtools/machine/im.py
CHANGED
@@ -119,6 +119,7 @@ class InductionMachine(Component):
|
|
119
119
|
if 'u1type' in parameters:
|
120
120
|
self.u1ref = self.u1type
|
121
121
|
if hasattr(self, 'f1ref'):
|
122
|
+
#self.wref = 2*np.pi*self.f1ref[0]
|
122
123
|
self.wref = 2*np.pi*self.f1ref
|
123
124
|
if hasattr(self, 'u1ref'):
|
124
125
|
self.psiref = self.u1ref/self.wref
|
@@ -603,7 +604,6 @@ class InductionMachine(Component):
|
|
603
604
|
r['eta'] += (pmech[i:]/(p1[i:])).tolist()
|
604
605
|
else:
|
605
606
|
r['eta'] += (p1[i:]/pmech[i:]).tolist()
|
606
|
-
|
607
607
|
return r
|
608
608
|
|
609
609
|
|
@@ -660,7 +660,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
660
660
|
num_steps)]
|
661
661
|
else:
|
662
662
|
i1tab = np.linspace(i1min, i1max, num_steps).tolist()
|
663
|
-
|
663
|
+
|
664
664
|
m = copy.deepcopy(machine)
|
665
665
|
Q2 = m['rotor']['num_slots']
|
666
666
|
noloadsim = dict(
|
@@ -668,7 +668,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
668
668
|
curvec=i1tab,
|
669
669
|
num_par_wdgs=machine[wdgk].get('num_par_wdgs', 1),
|
670
670
|
Q2=Q2)
|
671
|
-
|
671
|
+
|
672
672
|
da1 = m['bore_diam']
|
673
673
|
ag = m['airgap']
|
674
674
|
# do not create airgap nodechains automatically
|
@@ -722,7 +722,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
722
722
|
rotorbar['rotor'][k]['num_slots_gen'] = 1
|
723
723
|
rotorbar['rotor'][k]['zeroangle'] = 90-180/Q2
|
724
724
|
break
|
725
|
-
|
725
|
+
|
726
726
|
loadsim = dict( # not used
|
727
727
|
calculationMode="asyn_motor",
|
728
728
|
bar_len=bar_len,
|
@@ -740,7 +740,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
740
740
|
task = job.add_task(_eval_noloadrot(pmod), extra_result_files)
|
741
741
|
logger.debug("Task %s noload workdir %s result files %s",
|
742
742
|
task.id, task.directory, task.extra_result_files)
|
743
|
-
# create model
|
743
|
+
# create model
|
744
744
|
for mc in parstudy.femag.copy_magnetizing_curves(
|
745
745
|
model,
|
746
746
|
dir=task.directory):
|
@@ -754,6 +754,8 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
754
754
|
|
755
755
|
# ec simulation
|
756
756
|
barmodel = femagtools.model.MachineModel(rotorbar)
|
757
|
+
barmodel_new = barmodel
|
758
|
+
barmodel_new['stator']['ecSimulation']=1
|
757
759
|
extra_result_files = ['bar.dat']
|
758
760
|
r = (da1-ag)/2
|
759
761
|
task = job.add_task(_eval_ecsim())
|
@@ -767,7 +769,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
767
769
|
task.add_file(mc)
|
768
770
|
task.add_file(
|
769
771
|
'femag.fsl',
|
770
|
-
builder.create_model(
|
772
|
+
builder.create_model(barmodel_new,
|
771
773
|
condMat=parstudy.femag.condMat) +
|
772
774
|
builder.create_analysis(ecsim) +
|
773
775
|
['save_model("close")'])
|
@@ -796,6 +798,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
796
798
|
logger.info("Elapsed time %d s Status %s",
|
797
799
|
(tend-tstart), status)
|
798
800
|
if any([x != 'C' for x in status]):
|
801
|
+
logger.error("AC simulation failed with statuses: %s", status)
|
799
802
|
raise ValueError("AC simulation failed")
|
800
803
|
# collect results
|
801
804
|
results = [t.get_results() for t in job.tasks]
|
femagtools/machine/sizing.py
CHANGED
@@ -381,7 +381,7 @@ def get_stator_dimensions(par, slots=[]):
|
|
381
381
|
Da2 = Da1-2*airgap
|
382
382
|
r = dict(
|
383
383
|
lfe=round(lfe, 3),
|
384
|
-
Dy1=round(Dy1, 3),
|
384
|
+
Dy1=round(Dy1, 3),
|
385
385
|
Da1=round(Da1, 4),
|
386
386
|
Da2=round(Da2, 4),
|
387
387
|
ans=round(ans, 6),
|
@@ -574,6 +574,8 @@ def get_im_rotor_dimensions(A, Da2, psi1, lfe, par, rtype='rotorKs2'):
|
|
574
574
|
Q2 = r['num_slots']
|
575
575
|
r1 = wr/2-slotwidth
|
576
576
|
r2 = (Da2/2-hr-hs1)*np.tan(alfar)
|
577
|
+
logger.info("Dy2 %f Da2 %f hys %f hr %f",
|
578
|
+
r['Dy2']*1e3, Da2*1e3, hyr*1e3, hr*1e3)
|
577
579
|
if rtype == 'statorRotor3':
|
578
580
|
r['statorRotor3'] = dict(
|
579
581
|
slot_width=slotwidth,
|
@@ -985,13 +987,12 @@ def eesm(pnom: float, speed: float, p: int, **kwargs) -> dict:
|
|
985
987
|
r['name'] = f"EESM-{r['poles']}"
|
986
988
|
return r
|
987
989
|
|
988
|
-
|
989
990
|
if __name__ == "__main__":
|
990
991
|
# sizing example with SPM
|
991
992
|
pnom = 10e3 # shaft power in W
|
992
993
|
speed = 4400/60 # speed in 1/s
|
993
994
|
p = 4 # number of pole pairs
|
994
|
-
udc = 600 # DC voltage in V
|
995
|
+
udc = 600 # DC voltage in V
|
995
996
|
|
996
997
|
r = spm(pnom, speed, p, udc=udc)
|
997
998
|
|