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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.8.13'
5
+ __version__ = '1.8.14'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2023-2025 Gamma Technology'
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: # femag writes duplicate id==0 values
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
- if n := np.trim_zeros(np.diff(diff)).size:
1065
- idList = idList[:-n]
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
- for part in ('stator', 'rotor', 'commutator', 'magnet'):
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
- return self.__render(submod, 'FE-losses')
458
- return []
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
- 'gen_' + model.winding['wire'].get('name'))
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 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:
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:
@@ -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):
@@ -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
- 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)
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(barmodel_new,
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("Elapsed time %d s Status %s",
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
- # def inoload(x, iml, ims, mexp):
825
- # """return noload current"""
826
- # return iml*x/psiref + ims*(x/psiref)**mexp
827
- # fitp, cov = so.curve_fit(inoload, psihtab, i10tab, (1, 1, 1))
828
- # iml, ims, mexp = fitp
829
- # logger.info("iml, ims, mexp %g, %g, %g",
830
- # iml, ims, mexp)
831
- # i1tab.insert(0, 0)
832
- # psi1_0.insert(0, 0)
833
- # i1_0.insert(0, 0)
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
@@ -92,7 +92,8 @@ class PmRelMachine(object):
92
92
  self.io = (1, -1)
93
93
  self.fo = 50.0
94
94
  self.tcu1 = 20
95
- self.tmag = 20
95
+ # for information purpose only
96
+ self.tmag = kwargs.get('tmag', 20)
96
97
  self.zeta1 = 0.2
97
98
  self.gam = 0.7
98
99
  self.kh = 2