femagtools 1.8.13__py3-none-any.whl → 1.8.14__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 +30 -5
- femagtools/femag.py +2 -0
- femagtools/fsl.py +31 -37
- femagtools/isa7.py +16 -0
- femagtools/job.py +9 -0
- femagtools/machine/__init__.py +7 -38
- femagtools/machine/effloss.py +6 -7
- femagtools/machine/im.py +57 -26
- femagtools/machine/pm.py +2 -1
- femagtools/machine/sizing.py +92 -7
- femagtools/machine/sm.py +5 -1
- femagtools/machine/utils.py +37 -14
- femagtools/multiproc.py +6 -0
- femagtools/parstudy.py +1 -1
- femagtools/templates/FE-losses.mako +0 -3
- femagtools/templates/ec-rotorbar.mako +1 -2
- femagtools/templates/ld_lq_fast.mako +1 -1
- femagtools/templates/mesh-airgap.mako +0 -1
- femagtools/templates/noloadflux-rot.mako +5 -32
- femagtools/templates/statorRing.mako +1 -1
- femagtools/utils.py +5 -1
- {femagtools-1.8.13.dist-info → femagtools-1.8.14.dist-info}/METADATA +31 -2
- {femagtools-1.8.13.dist-info → femagtools-1.8.14.dist-info}/RECORD +30 -31
- {femagtools-1.8.13.dist-info → femagtools-1.8.14.dist-info}/WHEEL +1 -1
- femagtools-1.8.14.dist-info/licenses/LICENSE +26 -0
- tests/test_femag.py +1 -1
- tests/test_fsl.py +5 -5
- femagtools/templates/rotor_winding_ks2.mako +0 -44
- femagtools/templates/rotor_winding_ks2_ecSimulation.mako +0 -44
- {femagtools-1.8.13.dist-info → femagtools-1.8.14.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.13.dist-info → femagtools-1.8.14.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/bch.py
CHANGED
@@ -115,6 +115,22 @@ def losses_mapping_external_rotor(losses):
|
|
115
115
|
pass
|
116
116
|
return d
|
117
117
|
|
118
|
+
def _convert(obj):
|
119
|
+
"""make dict jsonizable"""
|
120
|
+
if isinstance(obj, dict):
|
121
|
+
return {k: _convert(v) for k, v in obj.items()}
|
122
|
+
elif isinstance(obj, (np.float32, np.float64)):
|
123
|
+
return float(obj)
|
124
|
+
elif isinstance(obj, list):
|
125
|
+
return [_convert(k) for k in obj]
|
126
|
+
elif isinstance(obj, tuple):
|
127
|
+
return tuple(_convert(k) for k in obj)
|
128
|
+
elif isinstance(obj, np.ndarray):
|
129
|
+
return obj.tolist()
|
130
|
+
elif isinstance(obj, (np.int32, np.int64)):
|
131
|
+
return int(obj)
|
132
|
+
else:
|
133
|
+
return obj
|
118
134
|
|
119
135
|
def _readSections(f):
|
120
136
|
"""return list of bch sections
|
@@ -1058,11 +1074,14 @@ class Reader:
|
|
1058
1074
|
e.g. : idList[-450, -350, -250, -150, -50, 0]
|
1059
1075
|
idList[-500, -400, -300, -200, -100, 0, 0]
|
1060
1076
|
'''
|
1061
|
-
if list(idList).count(0) > 1:
|
1077
|
+
if list(idList).count(0) > 1: # femag may write duplicate id==0 values
|
1062
1078
|
idList = idList[:-1]
|
1063
1079
|
diff = np.floor(np.abs(np.diff(idList)))
|
1064
|
-
|
1065
|
-
|
1080
|
+
maxdiff = np.max(diff)
|
1081
|
+
# also remove samples that are close
|
1082
|
+
if n := np.trim_zeros(np.diff(
|
1083
|
+
np.round(diff/maxdiff, 2))).size:
|
1084
|
+
return idList[:-n]
|
1066
1085
|
return idList
|
1067
1086
|
|
1068
1087
|
def __read_psidq(self, content):
|
@@ -1396,8 +1415,8 @@ class Reader:
|
|
1396
1415
|
pass
|
1397
1416
|
|
1398
1417
|
try:
|
1399
|
-
self.dqPar['psid'] = np.cos(gamma)*emf/w1
|
1400
|
-
self.dqPar['psiq'] = -np.sin(gamma)*emf/w1
|
1418
|
+
self.dqPar['psid'] = list(np.cos(gamma)*emf/w1)
|
1419
|
+
self.dqPar['psiq'] = list(-np.sin(gamma)*emf/w1)
|
1401
1420
|
except UnboundLocalError:
|
1402
1421
|
try:
|
1403
1422
|
self.dqPar['psid'] = [self.dqPar['psim'][0]]
|
@@ -1405,6 +1424,8 @@ class Reader:
|
|
1405
1424
|
self.dqPar['i1'][-1]]
|
1406
1425
|
except KeyError:
|
1407
1426
|
pass
|
1427
|
+
|
1428
|
+
self.dqPar = _convert(self.dqPar)
|
1408
1429
|
return # end of first section
|
1409
1430
|
|
1410
1431
|
# second DQ-Parameter section
|
@@ -1476,6 +1497,7 @@ class Reader:
|
|
1476
1497
|
self.dqPar['u1'].insert(0, self.dqPar.get('up0', 0))
|
1477
1498
|
except:
|
1478
1499
|
pass
|
1500
|
+
self.dqPar = _convert(self.dqPar)
|
1479
1501
|
|
1480
1502
|
def __read_weights(self, content):
|
1481
1503
|
# Stator-Iron - Conductors - Magnets
|
@@ -1845,6 +1867,9 @@ def read(filename):
|
|
1845
1867
|
|
1846
1868
|
if __name__ == "__main__":
|
1847
1869
|
import json
|
1870
|
+
logging.basicConfig(level=logging.INFO,
|
1871
|
+
format='%(asctime)s %(message)s')
|
1872
|
+
|
1848
1873
|
if len(sys.argv) == 2:
|
1849
1874
|
filename = sys.argv[1]
|
1850
1875
|
else:
|
femagtools/femag.py
CHANGED
@@ -485,6 +485,8 @@ class BaseFemag(object):
|
|
485
485
|
|
486
486
|
if len(ops) != len(bch.losses):
|
487
487
|
magn_losses.insert(0, magn_losses[0])
|
488
|
+
|
489
|
+
magn_losses = [float(i) for i in magn_losses]
|
488
490
|
try:
|
489
491
|
for i in range(len(bch.losses)):
|
490
492
|
bch.losses[i].update({"magnetH": magn_losses[i]})
|
femagtools/fsl.py
CHANGED
@@ -287,20 +287,12 @@ 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'
|
294
290
|
rotmodel.update(model.rotor[templ])
|
295
291
|
return mcv + culosses + self.render_rotor(rotmodel, templ)
|
296
292
|
|
297
293
|
def create_rotor_winding(self, model):
|
298
|
-
if 'ecSimulation' in model.stator:
|
299
|
-
return self.render_rotor(model.rotor, 'rotor_winding_ks2_ecSimulation')
|
300
294
|
if hasattr(model, 'rotor') and model.rotortype() == 'EESM':
|
301
295
|
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')
|
304
296
|
return []
|
305
297
|
|
306
298
|
def prepare_magnet(self, model):
|
@@ -444,25 +436,38 @@ class Builder:
|
|
444
436
|
return self.__render(windings, 'cu_losses')
|
445
437
|
|
446
438
|
def create_fe_losses(self, model):
|
447
|
-
|
439
|
+
fe_losses = []
|
440
|
+
fe_losses_items = (
|
441
|
+
'ffactor', 'cw', 'ch', 'hyscoef',
|
442
|
+
'edycof', 'indcof', 'fillfact',
|
443
|
+
'fillfac', 'basfreq', 'basind',
|
444
|
+
'ffactor')
|
445
|
+
|
446
|
+
part = 'stator'
|
447
|
+
if model.get(part, 0):
|
448
|
+
submod = model.get(part)
|
449
|
+
if any([submod.get(k, 0) for k in fe_losses_items]):
|
450
|
+
if submod.get('fillfac', 0):
|
451
|
+
submod['fillfact'] = submod['fillfac']
|
452
|
+
fe_losses += self.__render(submod, 'FE-losses')
|
453
|
+
fe_losses.append('pre_models("FE-Losses-1")')
|
454
|
+
|
455
|
+
for part in ('rotor', 'commutator', 'magnet'):
|
448
456
|
if model.get(part, 0):
|
449
457
|
submod = model.get(part)
|
450
|
-
if any(submod.get(k, 0) for k in
|
451
|
-
'ffactor', 'cw', 'ch', 'hyscoef',
|
452
|
-
'edycof', 'indcof', 'fillfact',
|
453
|
-
'fillfac','basfreq', 'basind',
|
454
|
-
'ffactor')):
|
458
|
+
if any([submod.get(k, 0) for k in fe_losses_items]):
|
455
459
|
if submod.get('fillfac', 0):
|
456
460
|
submod['fillfact'] = submod['fillfac']
|
457
|
-
|
458
|
-
|
461
|
+
fe_losses += self.__render(submod, 'FE-losses')
|
462
|
+
fe_losses.append('pre_models("FE-Losses-2")')
|
463
|
+
return fe_losses
|
459
464
|
|
460
465
|
def create_gen_winding(self, model):
|
461
466
|
try:
|
462
467
|
model.winding['wire'].update(
|
463
468
|
{"num_layers": model.winding["num_layers"]})
|
464
469
|
genwdg = self.__render(model.winding,
|
465
|
-
|
470
|
+
'gen_' + model.winding['wire'].get('name'))
|
466
471
|
except:
|
467
472
|
genwdg = self.__render(model, 'gen_winding')
|
468
473
|
|
@@ -514,11 +519,8 @@ class Builder:
|
|
514
519
|
params['nodedist'] = fmt.get('nodedist', 1)
|
515
520
|
params['full_model'] = fmt.get('full_model', False)
|
516
521
|
params['EESM'] = fmt.get('type', 'PMSM') == 'EESM'
|
517
|
-
params['rotorKs2'] = fmt.get('type', 'PMSM') == 'rotorKs2'
|
518
522
|
if params['EESM']:
|
519
523
|
model.rotor['EESM'] = {}
|
520
|
-
if params['rotorKs2']:
|
521
|
-
model.rotor['rotorKs2'] = {}
|
522
524
|
conv = convert(fname, **params)
|
523
525
|
|
524
526
|
model.set_value('poles', conv.get('num_poles'))
|
@@ -561,8 +563,6 @@ class Builder:
|
|
561
563
|
if not (hasattr(model, 'magnet') or hasattr(model, 'rotor')):
|
562
564
|
if params['EESM']:
|
563
565
|
setattr(model, 'rotor', {})
|
564
|
-
elif params['rotorKs2']:
|
565
|
-
setattr(model, 'rotor', {})
|
566
566
|
else:
|
567
567
|
setattr(model, 'magnet', {})
|
568
568
|
|
@@ -672,20 +672,14 @@ class Builder:
|
|
672
672
|
self.mesh_airgap(model) +
|
673
673
|
self.create_connect_models(model) +
|
674
674
|
self.create_rotor_winding(model))
|
675
|
-
if 'statorRing' 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:
|
675
|
+
if 'statorRing' in model.stator:
|
683
676
|
return (self.create_new_model(model) +
|
684
677
|
self.create_cu_losses(windings, condMat, ignore_material) +
|
685
678
|
self.create_fe_losses(model) +
|
686
679
|
rotor +
|
687
680
|
self.create_stator_model(model) +
|
688
681
|
self.create_rotor_winding(model))
|
682
|
+
|
689
683
|
return (self.create_new_model(model) +
|
690
684
|
self.create_cu_losses(windings, condMat, ignore_material) +
|
691
685
|
self.create_fe_losses(model) +
|
@@ -696,7 +690,6 @@ class Builder:
|
|
696
690
|
self.create_connect_models(model) +
|
697
691
|
self.create_rotor_winding(model)) + \
|
698
692
|
self.create_thermal_properties(model)
|
699
|
-
|
700
693
|
return (self.open_model(model) +
|
701
694
|
self.create_fe_losses(model) +
|
702
695
|
self.create_magnet(model, magnetMat))
|
@@ -757,6 +750,11 @@ class Builder:
|
|
757
750
|
if sim.get('airgap_induc', 0) else [])
|
758
751
|
displ_stator_rotor = self.create_displ_stator_rotor(
|
759
752
|
sim.get('eccentricity', {}))
|
753
|
+
# sliding band
|
754
|
+
sliding_band = []
|
755
|
+
if sim.get("sliding", 0):
|
756
|
+
sliding_band = [f'save_model("cont")',
|
757
|
+
f'enable_sliding()']
|
760
758
|
revert_displ = []
|
761
759
|
if displ_stator_rotor:
|
762
760
|
sim['eval_force'] = 1
|
@@ -776,6 +774,7 @@ class Builder:
|
|
776
774
|
sim.noload_ex_cur = sim.get('nload_ex_cur')
|
777
775
|
felosses = custom_fefunc + self.create_fe_losses(sim)
|
778
776
|
fslcalc = (displ_stator_rotor
|
777
|
+
+ sliding_band
|
779
778
|
+ self.__render(sim, sim.get('calculationMode'))
|
780
779
|
+ airgap_induc + revert_displ
|
781
780
|
+ ['save_model("cont")'])
|
@@ -789,12 +788,6 @@ class Builder:
|
|
789
788
|
else:
|
790
789
|
plots = []
|
791
790
|
|
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')
|
798
791
|
return felosses + fslcalc + plots
|
799
792
|
|
800
793
|
def create_shortcircuit(self, model):
|
@@ -883,6 +876,7 @@ class Builder:
|
|
883
876
|
self.fsl_stator = True
|
884
877
|
if magnet:
|
885
878
|
self.fsl_rotor = True
|
879
|
+
|
886
880
|
return template.render_unicode(model=model).split('\n')
|
887
881
|
|
888
882
|
def render_template(self, content_template, parameters):
|
femagtools/isa7.py
CHANGED
@@ -1035,16 +1035,28 @@ class Isa7(object):
|
|
1035
1035
|
def get_mass(self):
|
1036
1036
|
""" return mass (in kg) of material conductors, iron, magnets
|
1037
1037
|
"""
|
1038
|
+
masse_rotor_yoke = 0
|
1039
|
+
section_rotor_yoke = 0
|
1038
1040
|
try:
|
1039
1041
|
return self.mass
|
1040
1042
|
except AttributeError:
|
1041
1043
|
self.mass = [{'iron': 0, 'conductors': 0, 'magnets': 0},
|
1042
1044
|
{'iron': 0, 'conductors': 0, 'magnets': 0}]
|
1043
1045
|
scf = self.scale_factor()
|
1046
|
+
for se in self.subregions:
|
1047
|
+
if se.name == 'Bar':
|
1048
|
+
r = 1 # as rotor bar is inside
|
1049
|
+
spw = self.CU_SPEZ_WEIGHT*1e3
|
1050
|
+
l = 1 #self.PS_LENGTH_CU[r]*1e-2
|
1051
|
+
slf = 1 #self.PS_FILFACTOR_CU[r]
|
1052
|
+
self.mass[r]['conductors'] += scf*se.area()*self.arm_length*spw*l*slf
|
1044
1053
|
for se in self.superelements:
|
1054
|
+
winding_detected=0
|
1055
|
+
lamination_detected=0
|
1045
1056
|
r = 0 if se.outside else 1
|
1046
1057
|
if se.subregion:
|
1047
1058
|
if se.subregion.winding:
|
1059
|
+
winding_detected=1
|
1048
1060
|
spw = self.CU_SPEZ_WEIGHT*1e3
|
1049
1061
|
l = self.PS_LENGTH_CU[r]*1e-2
|
1050
1062
|
slf = self.PS_FILFACTOR_CU[r]
|
@@ -1052,6 +1064,7 @@ class Isa7(object):
|
|
1052
1064
|
continue
|
1053
1065
|
|
1054
1066
|
if se.mcvtype or se.elements[0].is_lamination():
|
1067
|
+
lamination_detected=1
|
1055
1068
|
try:
|
1056
1069
|
spw = self.iron_loss_coefficients[se.mcvtype-1][
|
1057
1070
|
'spec_weight']*1e3 # kg/m³
|
@@ -1062,6 +1075,9 @@ class Isa7(object):
|
|
1062
1075
|
fillfact = 1
|
1063
1076
|
#logger.warning('missing iron losscoeffs using defaults')
|
1064
1077
|
m = scf*self.arm_length*se.area()*spw*fillfact
|
1078
|
+
if r == 1:
|
1079
|
+
masse_rotor_yoke += m
|
1080
|
+
section_rotor_yoke += se.area()
|
1065
1081
|
self.mass[r]['iron'] += m
|
1066
1082
|
else:
|
1067
1083
|
try:
|
femagtools/job.py
CHANGED
@@ -146,6 +146,15 @@ class Task(object):
|
|
146
146
|
result = dict(error=msg)
|
147
147
|
return result
|
148
148
|
|
149
|
+
def read_nc(self):
|
150
|
+
"read most recent NC file and return result"
|
151
|
+
basedir = pathlib.Path(self.directory)
|
152
|
+
ncfiles = sorted(basedir.glob('*.nc'))
|
153
|
+
if not ncfiles:
|
154
|
+
return None
|
155
|
+
import femagtools.nc
|
156
|
+
return femagtools.nc.read(ncfiles[-1])
|
157
|
+
|
149
158
|
def readErrorMessage(self, html=True):
|
150
159
|
errstr = ""
|
151
160
|
if html:
|
femagtools/machine/__init__.py
CHANGED
@@ -38,6 +38,7 @@ 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
|
+
|
41
42
|
if 'ldq' in eecpars or 'psidq' in eecpars: # this is a PM (or EESM)
|
42
43
|
try:
|
43
44
|
dqpars = eecpars['ldq']
|
@@ -81,7 +82,7 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
81
82
|
losses=losses,
|
82
83
|
id=np.array(dqp['id'])/rwdg,
|
83
84
|
iq=np.array(dqp['iq'])/rwdg,
|
84
|
-
tcu1=temp[0],
|
85
|
+
tcu1=temp[0], tmag=temp[1],
|
85
86
|
**opts)
|
86
87
|
else:
|
87
88
|
beta = dqp['beta']
|
@@ -95,7 +96,7 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
95
96
|
losses=losses,
|
96
97
|
beta=beta,
|
97
98
|
i1=i1,
|
98
|
-
tcu1=temp[0],
|
99
|
+
tcu1=temp[0], tmag=temp[1],
|
99
100
|
**opts)
|
100
101
|
return machine
|
101
102
|
|
@@ -113,40 +114,6 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
|
|
113
114
|
pars['psi'] = [psi*rwdg*rlfe for psi in pars['psi']]
|
114
115
|
pars['tcu1'] = temp[0]
|
115
116
|
pars['tcu2'] = temp[1]
|
116
|
-
|
117
|
-
pars.update(opts)
|
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']
|
149
|
-
|
150
117
|
pars.update(opts)
|
151
118
|
return InductionMachine(pars)
|
152
119
|
|
@@ -179,7 +146,8 @@ def create(bch, r1, ls, lfe=1, wdg=1):
|
|
179
146
|
if 'ex_current' in bch.machine:
|
180
147
|
raise ValueError("not yet implemented for EESM")
|
181
148
|
machine = PmRelMachinePsidq(m, p, psid, psiq, r1*rlfe*rwdg**2,
|
182
|
-
id, iq, ls*rwdg**2, losses=losses
|
149
|
+
id, iq, ls*rwdg**2, losses=losses,
|
150
|
+
tmag=bch.magnet.get('Tmag', 20))
|
183
151
|
try:
|
184
152
|
machine.rotor_mass = rlfe*np.sum(bch.weights[1])
|
185
153
|
except (IndexError, AttributeError):
|
@@ -204,7 +172,8 @@ def create(bch, r1, ls, lfe=1, wdg=1):
|
|
204
172
|
machine = PmRelMachineLdq(m, p, psid=psid, psiq=psiq,
|
205
173
|
r1=r1*rlfe*rwdg**2,
|
206
174
|
i1=i1, beta=beta, ls=ls*rwdg**2,
|
207
|
-
losses=losses
|
175
|
+
losses=losses,
|
176
|
+
tmag=bch.magnet.get('Tmag', 20))
|
208
177
|
try:
|
209
178
|
machine.rotor_mass = rlfe*np.sum(bch.weights[1])
|
210
179
|
except (IndexError, AttributeError):
|
femagtools/machine/effloss.py
CHANGED
@@ -262,6 +262,9 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
262
262
|
nt = []
|
263
263
|
if isinstance(m, (SynchronousMachineLdq, SynchronousMachinePsidq)):
|
264
264
|
iq, id, iex = m.iqd_torque(T[-1])
|
265
|
+
i1max = betai1(iq, id)[1]
|
266
|
+
w1type, tmax = m.w1_imax_umax(i1max, u1)
|
267
|
+
pmax = tmax*w1type/m.p
|
265
268
|
else:
|
266
269
|
iq, id = m.iqd_torque(T[-1])
|
267
270
|
|
@@ -270,12 +273,9 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
270
273
|
for nx in n:
|
271
274
|
w1 = 2*np.pi*nx*m.p
|
272
275
|
if isinstance(m, (SynchronousMachineLdq, SynchronousMachinePsidq)):
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
else:
|
277
|
-
iq, id, iex, tq = m.iqd_torque_umax(
|
278
|
-
T[-1], w1, u1)
|
276
|
+
tq = T[-1]
|
277
|
+
if tq*w1/m.p > pmax:
|
278
|
+
tq = pmax/w1*m.p
|
279
279
|
else:
|
280
280
|
iq, id, tq = m.iqd_imax_umax(i1max, w1, u1, T[-1],
|
281
281
|
with_tmech=with_tmech,
|
@@ -289,7 +289,6 @@ def efficiency_losses_map(eecpars, u1, T, temp, n, npoints=(60, 40),
|
|
289
289
|
raise ValueError("Speed, Torque Mesh is empty")
|
290
290
|
nsamples = len(n)
|
291
291
|
ntmesh = np.array(nt).T
|
292
|
-
|
293
292
|
logger.info("total speed,torque samples %s", ntmesh.shape)
|
294
293
|
if isinstance(m, (PmRelMachine, SynchronousMachine)):
|
295
294
|
if num_proc > 1:
|
femagtools/machine/im.py
CHANGED
@@ -119,7 +119,6 @@ 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]
|
123
122
|
self.wref = 2*np.pi*self.f1ref
|
124
123
|
if hasattr(self, 'u1ref'):
|
125
124
|
self.psiref = self.u1ref/self.wref
|
@@ -522,9 +521,10 @@ class InductionMachine(Component):
|
|
522
521
|
wmrange = sorted([0, wmType, wmPullout, wmMax])
|
523
522
|
elif wmMax < wmType:
|
524
523
|
wmrange = sorted([0, wmMax])
|
524
|
+
elif wmType<0 or wmPullout<0 or wmMax<0:
|
525
|
+
wmrange = sorted([1, abs(min(wmMax,wmType, wmPullout)), abs(max(wmMax,wmType, wmPullout))])
|
525
526
|
else:
|
526
527
|
wmrange = sorted([0, wmType, wmMax])
|
527
|
-
|
528
528
|
logger.info("Speed range %s", wmrange)
|
529
529
|
wmlin = []
|
530
530
|
dw = 0
|
@@ -604,6 +604,7 @@ class InductionMachine(Component):
|
|
604
604
|
r['eta'] += (pmech[i:]/(p1[i:])).tolist()
|
605
605
|
else:
|
606
606
|
r['eta'] += (p1[i:]/pmech[i:]).tolist()
|
607
|
+
|
607
608
|
return r
|
608
609
|
|
609
610
|
|
@@ -660,7 +661,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
660
661
|
num_steps)]
|
661
662
|
else:
|
662
663
|
i1tab = np.linspace(i1min, i1max, num_steps).tolist()
|
663
|
-
|
664
|
+
|
664
665
|
m = copy.deepcopy(machine)
|
665
666
|
Q2 = m['rotor']['num_slots']
|
666
667
|
noloadsim = dict(
|
@@ -668,7 +669,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
668
669
|
curvec=i1tab,
|
669
670
|
num_par_wdgs=machine[wdgk].get('num_par_wdgs', 1),
|
670
671
|
Q2=Q2)
|
671
|
-
|
672
|
+
|
672
673
|
da1 = m['bore_diam']
|
673
674
|
ag = m['airgap']
|
674
675
|
# do not create airgap nodechains automatically
|
@@ -679,11 +680,11 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
679
680
|
m[wdgk].pop('resistance')
|
680
681
|
except KeyError:
|
681
682
|
pass
|
682
|
-
|
683
|
+
|
683
684
|
parstudy = femagtools.parstudy.ParameterStudy(
|
684
685
|
workdir, condMat=condMat,
|
685
686
|
magnetizingCurves=magnetizingCurves, cmd=cmd)
|
686
|
-
|
687
|
+
|
687
688
|
builder = femagtools.fsl.Builder(kwargs.get('templatedirs', []))
|
688
689
|
model = femagtools.model.MachineModel(m)
|
689
690
|
# modelfiles = parstudy.setup_model(builder, model)
|
@@ -722,7 +723,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
722
723
|
rotorbar['rotor'][k]['num_slots_gen'] = 1
|
723
724
|
rotorbar['rotor'][k]['zeroangle'] = 90-180/Q2
|
724
725
|
break
|
725
|
-
|
726
|
+
|
726
727
|
loadsim = dict( # not used
|
727
728
|
calculationMode="asyn_motor",
|
728
729
|
bar_len=bar_len,
|
@@ -740,7 +741,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
740
741
|
task = job.add_task(_eval_noloadrot(pmod), extra_result_files)
|
741
742
|
logger.debug("Task %s noload workdir %s result files %s",
|
742
743
|
task.id, task.directory, task.extra_result_files)
|
743
|
-
# create model
|
744
|
+
# create model
|
744
745
|
for mc in parstudy.femag.copy_magnetizing_curves(
|
745
746
|
model,
|
746
747
|
dir=task.directory):
|
@@ -754,11 +755,10 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
754
755
|
|
755
756
|
# ec simulation
|
756
757
|
barmodel = femagtools.model.MachineModel(rotorbar)
|
757
|
-
barmodel_new = barmodel
|
758
|
-
barmodel_new['stator']['ecSimulation']=1
|
759
758
|
extra_result_files = ['bar.dat']
|
760
759
|
r = (da1-ag)/2
|
761
|
-
task = job.add_task(_eval_ecsim())
|
760
|
+
#task = job.add_task(_eval_ecsim())
|
761
|
+
task = job.add_task(_eval_ecsim(), extra_result_files)
|
762
762
|
logger.debug("Task %s rotobar workdir %s result files %s",
|
763
763
|
task.id, task.directory, task.extra_result_files)
|
764
764
|
task.set_stateofproblem('mag_dynamic')
|
@@ -769,7 +769,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
769
769
|
task.add_file(mc)
|
770
770
|
task.add_file(
|
771
771
|
'femag.fsl',
|
772
|
-
builder.create_model(
|
772
|
+
builder.create_model(barmodel,
|
773
773
|
condMat=parstudy.femag.condMat) +
|
774
774
|
builder.create_analysis(ecsim) +
|
775
775
|
['save_model("close")'])
|
@@ -795,10 +795,9 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
795
795
|
logger.info('Started %s', status)
|
796
796
|
status = engine.join()
|
797
797
|
tend = time.time()
|
798
|
-
logger.info("
|
798
|
+
logger.info("Elapssed time %d s Status %s",
|
799
799
|
(tend-tstart), status)
|
800
800
|
if any([x != 'C' for x in status]):
|
801
|
-
logger.error("AC simulation failed with statuses: %s", status)
|
802
801
|
raise ValueError("AC simulation failed")
|
803
802
|
# collect results
|
804
803
|
results = [t.get_results() for t in job.tasks]
|
@@ -821,16 +820,17 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
821
820
|
u1ref = u1ph
|
822
821
|
psiref = u1ref/w1
|
823
822
|
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
823
|
+
# def inoload(x, iml, ims, mexp):
|
824
|
+
# """return noload current"""
|
825
|
+
# return iml*x/psiref + ims*(x/psiref)**mexp
|
826
|
+
# fitp, cov = so.curve_fit(inoload, psihtab, i10tab, (1, 1, 1))
|
827
|
+
# iml, ims, mexp = fitp
|
828
|
+
# logger.info("iml, ims, mexp %g, %g, %g",
|
829
|
+
# iml, ims, mexp)
|
830
|
+
# i1tab.insert(0, 0)
|
831
|
+
# psi1_0.insert(0, 0)
|
832
|
+
# i1_0.insert(0, 0)
|
833
|
+
|
834
834
|
logger.info("psi1_0 %s", np.mean(psi1_0, axis=1))
|
835
835
|
logger.info("psih %s", psih)
|
836
836
|
logger.debug("psi1_0-psih %s", np.mean(psi1_0, axis=1)-psih)
|
@@ -851,7 +851,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
851
851
|
hs = machine['stator'][slotmodel].get('slot_height',
|
852
852
|
0.33*(machine['outer_diam']-da1))
|
853
853
|
n = machine[wdgk]['num_wires']
|
854
|
-
if 'dia_wire' in machine[wdgk]:
|
854
|
+
if 'dia_wire' in machine[wdgk] and machine[wdgk].get('dia_wire', 1e-3) !=0:
|
855
855
|
aw = np.pi*machine[wdgk].get('dia_wire', 1e-3)**2/4
|
856
856
|
else: # wire diameter from slot area
|
857
857
|
aw = 0.75 * \
|
@@ -878,6 +878,7 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
878
878
|
# kind='quadratic')(imref))
|
879
879
|
psihref = float(log_interp1d(i1tab, psih)(imref))
|
880
880
|
psi1ref = float(psi1(imref))
|
881
|
+
|
881
882
|
|
882
883
|
lh = psihref/imref
|
883
884
|
L1 = psi1ref/imref
|
@@ -908,8 +909,37 @@ def parident(workdir, engine, f1, u1, wdgcon,
|
|
908
909
|
# r2 = results[1]['r2']
|
909
910
|
# ls2 = results[1]['ls2']
|
910
911
|
pfe = results[2]['pfe1'][0]
|
912
|
+
|
913
|
+
end_ring_section = machine['rotor']['Aring']
|
914
|
+
bore_diam = machine['bore_diam']
|
915
|
+
for key, value in machine['rotor'].items():
|
916
|
+
if isinstance(value, dict) and 'slot_height' in value:
|
917
|
+
slot_height_rotor = value['slot_height']
|
918
|
+
break
|
919
|
+
if slot_height_rotor is not None:
|
920
|
+
rayon = (bore_diam / 2) - slot_height_rotor/2
|
921
|
+
end_ring_length = 2 * np.pi * rayon
|
922
|
+
else:
|
923
|
+
end_ring_length = 0
|
924
|
+
|
925
|
+
end_ring_volume = end_ring_section*end_ring_length
|
926
|
+
|
927
|
+
for material_info in condMat:
|
928
|
+
if material_info.get('name') == machine.get('rotor', {}).get('material'):
|
929
|
+
spmaweight_rotor = material_info.get('spmaweight')
|
930
|
+
break
|
931
|
+
else:
|
932
|
+
spmaweight_rotor = 0
|
933
|
+
end_ring_mass = end_ring_volume * spmaweight_rotor*1e3
|
934
|
+
|
911
935
|
rotor_mass = sum([results[2].get('conweight', 0),
|
912
936
|
results[2].get('lamweight', 0)])
|
937
|
+
logger.info('Conductor mass in rotor = %s',results[2].get('conweight', 0))
|
938
|
+
logger.info('Lamination mass in rotor = %s',results[2].get('lamweight', 0))
|
939
|
+
logger.info('Rotor mass without end-ring = %s',rotor_mass)
|
940
|
+
rotor_mass += 2*end_ring_mass
|
941
|
+
logger.info('One end-ring mass = %s',end_ring_mass)
|
942
|
+
logger.info('Total rotor mass = %s',rotor_mass)
|
913
943
|
|
914
944
|
n = machine[wdgk]['num_wires']
|
915
945
|
g = loadsim['num_par_wdgs']
|
@@ -977,12 +1007,13 @@ class _eval_noloadrot():
|
|
977
1007
|
i0 = np.linalg.norm(
|
978
1008
|
femagtools.machine.T(0).dot(ire.T),
|
979
1009
|
axis=0)/np.sqrt(2)
|
1010
|
+
|
980
1011
|
|
981
1012
|
psi0 = np.array([np.linalg.norm(
|
982
1013
|
femagtools.machine.T(0).dot(psire[:, k, :].T),
|
983
1014
|
axis=0)/np.sqrt(2)
|
984
1015
|
for k in range(ncurs)])
|
985
|
-
|
1016
|
+
|
986
1017
|
# matrix (i x j x k) of curr, rotor pos, angle
|
987
1018
|
Bamp = [[femagtools.airgap.fft(bags[:, 0], b, self.pmod)['Bamp']
|
988
1019
|
for b in bags.T[1:]]
|
femagtools/machine/pm.py
CHANGED