femagtools 1.8.17__py3-none-any.whl → 1.8.19__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/machine/pm.py CHANGED
@@ -97,7 +97,7 @@ class PmRelMachine(object):
97
97
  self.zeta1 = 0.2
98
98
  self.gam = 0.7
99
99
  self.kh = 2
100
- self.kpfe = 1 # iron loss factor
100
+ self.kpfe = 1 # common iron loss factor
101
101
  self.kpmag = 1 # magnet loss factor
102
102
  self.kfric_b = 1
103
103
  self.rotor_mass = 0
@@ -182,6 +182,8 @@ class PmRelMachine(object):
182
182
  return (0, 0)
183
183
  if np.isscalar(iqd0):
184
184
  i0 = self.io
185
+ if torque<0:
186
+ i0[0] = -i0[0]
185
187
  else:
186
188
  i0 = iqd0
187
189
  if with_mtpa:
@@ -193,10 +195,14 @@ class PmRelMachine(object):
193
195
  if res.success:
194
196
  #raise ValueError(f'Torque {torque}, io {i0}: {res.message}')
195
197
  return res.x
198
+ # should not happen
196
199
  def func(i1):
197
200
  return torque - self.mtpa(i1)[2]
201
+ # with warnings.catch_warnings():
202
+ # warnings.simplefilter("error")
198
203
  i1 = so.fsolve(func, res.x[0])[0]
199
204
  return self.mtpa(i1)[:2]
205
+
200
206
  def func(iq):
201
207
  return torque - self.torque_iqd(iq, 0)
202
208
  return so.fsolve(func, 0)[0]
@@ -220,7 +226,7 @@ class PmRelMachine(object):
220
226
  else:
221
227
  i0 = (iq0, 0)
222
228
  logger.debug("initial guess i0 %f -> %s tx %f torque %f",
223
- self.io[0], i0, tx, torque)
229
+ self.io[0], i0, tx, torque)
224
230
  else:
225
231
  i0 = iqd0
226
232
 
@@ -237,7 +243,7 @@ class PmRelMachine(object):
237
243
  # make new initial guess:
238
244
  tx = self.tmech_iqd(*i0, n)
239
245
  logger.debug("k %d new guess i0 %s tx %f torque %f",
240
- k, i0, tx, torque)
246
+ k, i0, tx, torque)
241
247
  i0=(min(0.9*self.i1range[1]/np.sqrt(2), torque/tx*i0[0]), 0)
242
248
  k += 1
243
249
  raise ValueError(
@@ -247,45 +253,18 @@ class PmRelMachine(object):
247
253
  iq = so.fsolve(tqiq, (i0[0],))[0]
248
254
  return iq, 0, self.tmech_iqd(iq, 0, n)
249
255
 
250
- def iqd_tmech0(self, torque, n, iqd0=0, with_mtpa=True):
251
- """return minimum d-q-current for shaft torque"""
252
- if np.abs(torque) < 1e-2:
253
- return (0, 0)
254
- if np.isscalar(iqd0):
255
- i0 = self.io
256
- else:
257
- i0 = iqd0
258
-
259
- if with_mtpa:
260
- res = so.minimize(
261
- lambda iqd: la.norm(iqd), i0, method='SLSQP',
262
- constraints=({'type': 'eq',
263
- 'fun': lambda iqd:
264
- self.tmech_iqd(*iqd, n) - torque}))
265
- if res.success:
266
- return res.x
267
-
268
- #logger.warning("n: %s, torque %s: %s %s",
269
- # 60*n, torque, res.message, i0)
270
- # try a different approach:
271
- #raise ValueError(
272
- # f'Torque {torque:.1f} speed {60*n:.1f} {res.message}')
273
- def func(i1):
274
- return torque - self.mtpa_tmech(i1, n)[2]
275
- i1 = so.fsolve(func, res.x[0])[0]
276
- return self.mtpa_tmech(i1, n)[:2]
277
-
278
- def tqiq(iq):
279
- return torque - self.tmech_iqd(float(iq), 0, n)
280
- iq = so.fsolve(tqiq, (i0[0],))[0]
281
- return iq, 0, self.tmech_iqd(iq, 0, n)
282
-
283
256
  def tloss_iqd(self, iq, id, n):
284
257
  """return loss torque of d-q current, iron loss correction factor
285
258
  and friction windage losses"""
286
259
  if n > 1e-3:
287
260
  f1 = self.p*n
288
- plfe = self.kpfe * (self.iqd_plfe1(iq, id, f1) + self.iqd_plfe2(iq, id, f1))
261
+ plfe1 = self.kpfe * self.iqd_plfe1(iq, id, f1)
262
+ plfe2 = self.kpfe * self.iqd_plfe2(iq, id, f1)
263
+ if hasattr(self, 'kpfe_s'):
264
+ plfe1 = self.kpfe_s * self.iqd_plfe1(iq, id, f1)
265
+ if hasattr(self, 'kpfe_r'):
266
+ plfe2 = self.kpfe_r * self.iqd_plfe2(iq, id, f1)
267
+ plfe = plfe1 + plfe2
289
268
  pmag = self.kpmag * self.iqd_plmag(iq, id, f1)
290
269
  return (plfe + pmag + self.pfric(n))/(2*np.pi*n)
291
270
  return 0
@@ -350,12 +329,12 @@ class PmRelMachine(object):
350
329
  sign = -1 if i1max > 0 else 1
351
330
  res = so.minimize(
352
331
  lambda n: sign*self.tmech_iqd(iq, id, n),
353
- n0,
354
- constraints={
355
- 'type': 'eq',
356
- 'fun': lambda n:
357
- np.sqrt(2)*u1max - np.linalg.norm(
358
- self.uqd(2*np.pi*n*self.p, iq, id))})
332
+ n0,
333
+ constraints={
334
+ 'type': 'eq',
335
+ 'fun': lambda n:
336
+ np.sqrt(2)*u1max - np.linalg.norm(
337
+ self.uqd(2*np.pi*n*self.p, iq, id))})
359
338
  return 2*np.pi*res.x[0]*self.p, self.tmech_iqd(iq, id, res.x[0])
360
339
 
361
340
  return so.fsolve(lambda x: np.linalg.norm(
@@ -453,22 +432,26 @@ class PmRelMachine(object):
453
432
  i1 = self.i1_tmech(torque, 0, n)
454
433
  i0 = iqd(0, i1)
455
434
 
435
+ logger.debug("i0 %s", i0)
456
436
  if np.linalg.norm(self.uqd(w1, *i0))/np.sqrt(2) > u1max:
457
437
  beta, i1 = betai1(*i0)
458
438
  with warnings.catch_warnings():
459
439
  warnings.simplefilter("ignore")
460
- i0 = iqd(so.fsolve(lambda b: u1max - np.linalg.norm(
461
- self.uqd(w1, *iqd(b, i1)))/np.sqrt(2),
462
- beta)[0], i1)
440
+ bx, _, ier, msg = so.fsolve(lambda b: u1max - np.linalg.norm(
441
+ self.uqd(w1, *iqd(b, i1)))/np.sqrt(2), beta,
442
+ full_output=True)
443
+ i0 = iqd(bx[0], i1)
444
+ logger.debug("i0 %s ier %d %s", i0, ier, msg)
463
445
 
464
- res = so.minimize(lambda iqd: np.linalg.norm(iqd), i0, method='SLSQP',
465
- constraints=(
466
- {'type': 'eq',
467
- 'fun': lambda iqd:
468
- self.tmech_iqd(*iqd, n) - torque},
469
- {'type': 'ineq',
470
- 'fun': lambda iqd:
471
- np.sqrt(2)*u1max - la.norm(self.uqd(w1, *iqd))}))
446
+ res = so.minimize(
447
+ lambda iqd: np.linalg.norm(iqd), i0, method='SLSQP',
448
+ constraints=(
449
+ {'type': 'eq',
450
+ 'fun': lambda iqd:
451
+ self.tmech_iqd(*iqd, n) - torque},
452
+ {'type': 'ineq',
453
+ 'fun': lambda iqd:
454
+ np.sqrt(2)*u1max - la.norm(self.uqd(w1, *iqd))}))
472
455
  iq, id = res.x
473
456
  else:
474
457
  iq, id = i0
@@ -587,18 +570,19 @@ class PmRelMachine(object):
587
570
  log((iq, id, tq))
588
571
  return iq, id, tq
589
572
 
590
- def iqd_imax_umax(self, i1max, w1, u1max, torque, with_mtpv=True, with_tmech=True, with_mtpa=True):
573
+ def iqd_imax_umax(self, i1max, w1, u1max, torque, with_mtpv=True,
574
+ with_tmech=True, with_mtpa=True):
591
575
  """return d-q current and shaft torque at stator frequency and max voltage
592
576
  and max current (for motor operation if maxtorque else generator operation)"""
593
577
  if torque > 0:
594
- sign=-1
578
+ sign = -1
595
579
  # -pi/2 --> 0
596
580
  b0, b1 = max(-np.pi/2, self.betarange[0]), 0
597
581
  if max(self.betarange) < b1:
598
582
  raise ValueError(
599
583
  f"invalid betarange for maxtorque>0: {self.betarange}")
600
584
  else:
601
- sign=1
585
+ sign = 1
602
586
  # -pi/2 --> -pi
603
587
  b0, b1 = -np.pi/2, max(-np.pi, self.betarange[0])
604
588
  if min(self.betarange) > b0:
@@ -608,6 +592,7 @@ class PmRelMachine(object):
608
592
  iq, id, _ = self.mtpa(i1max)
609
593
  else:
610
594
  iq, id = iqd(0, i1max)
595
+
611
596
  deps = 1e-6
612
597
  kmax = 100
613
598
 
@@ -622,8 +607,10 @@ class PmRelMachine(object):
622
607
  else:
623
608
  iq, id, tq = self.iqd_torque_umax(torque, w1, u1max)
624
609
  if not with_mtpv:
610
+ logging.debug("not mtpv iq %f id %f tq %f",
611
+ iq, id, tq)
625
612
  return iq, id, tq
626
- beta, i1 = betai1(iq, id)
613
+ #beta, i1 = betai1(iq, id)
627
614
  else:
628
615
  for k in range(kmax):
629
616
  bx = b0 + (b1-b0)/2
@@ -642,9 +629,9 @@ class PmRelMachine(object):
642
629
  if abs(du) > 0.1:
643
630
  logger.debug('oops? iqd_imax_umax one more torque reduction')
644
631
  if with_tmech:
645
- iq, id = self.iqd_tmech_umax(torque, w1, u1max)[:2]
632
+ iq, id, tq = self.iqd_tmech_umax(torque, w1, u1max)
646
633
  else:
647
- iq, id = self.iqd_torque_umax(torque, w1, u1max)[:2]
634
+ iq, id, tq = self.iqd_torque_umax(torque, w1, u1max)
648
635
  if with_mtpv:
649
636
  try:
650
637
  if with_tmech:
@@ -656,9 +643,26 @@ class PmRelMachine(object):
656
643
  iq, id, tq = self.mtpv(w1, u1max, iqd0=(iq, id),
657
644
  maxtorque=torque>0,
658
645
  i1max=i1max)
646
+ logging.debug("mtpv iq %f id %f tq %f",
647
+ iq, id, tq)
659
648
  return iq, id, tq
660
649
  except ValueError as e:
661
- logger.debug(e)
650
+ n = w1/2/np.pi/self.p
651
+ logger.debug(" i1max %f iq %f id %f", i1max, iq, id)
652
+ #
653
+ res = so.minimize(
654
+ lambda iqd: sign*self.tmech_iqd(*iqd, n),
655
+ (iq, id),
656
+ constraints=[{
657
+ 'type': 'eq',
658
+ 'fun': lambda iqd:
659
+ np.sqrt(2)*u1max - np.linalg.norm(
660
+ self.uqd(w1, *iqd))}])
661
+ logger.debug(" n %f i1max %f %f iq %f id %f tq %f",
662
+ 60*n, i1max, np.linalg.norm(res.x)/np.sqrt(2),
663
+ iq, id, sign*res.fun)
664
+ if res['success'] and abs(i1max*np.sqrt(2)) >= np.linalg.norm(res.x):
665
+ return *res.x, sign*res.fun
662
666
 
663
667
  if with_tmech:
664
668
  tq = self.tmech_iqd(iq, id, w1/2/np.pi/self.p)
@@ -723,6 +727,8 @@ class PmRelMachine(object):
723
727
  else:
724
728
  i0 = iqd0
725
729
  n = w1/2/np.pi/self.p
730
+ logger.debug("w1 %f u1 %f iqd0 %s maxtorque %s %f",
731
+ w1, u1, iqd0, maxtorque, i1max)
726
732
  constraints=[{'type': 'eq',
727
733
  'fun': lambda iqd:
728
734
  np.sqrt(2)*u1 - la.norm(
@@ -734,6 +740,7 @@ class PmRelMachine(object):
734
740
  res = so.minimize(lambda iqd: sign*self.tmech_iqd(*iqd, n), i0,
735
741
  method='SLSQP',
736
742
  constraints=constraints)
743
+ logger.debug("iq %f id %f w1 %f success %s", res.x[0], res.x[1], w1, res['success'])
737
744
  if res['success']:
738
745
  return res.x[0], res.x[1], sign*res.fun
739
746
  #logger.warning("w1=%.1f u1=%.1f maxtorque=%s %s: %s", w1, u1, maxtorque, res.x, res.message)
@@ -814,7 +821,7 @@ class PmRelMachine(object):
814
821
  if (abs(i1max) >= i1
815
822
  and round(u1max, 1) >= round(np.linalg.norm(
816
823
  self.uqd(w1max, iq, id)/np.sqrt(2)), 1)):
817
- return [w1type/2/np.pi/self.p, speedmax]
824
+ return [float(w1type/2/np.pi/self.p), float(speedmax)]
818
825
  wl, wu = [w1type, min(4*w1type, w1max)]
819
826
  if with_mtpv:
820
827
  kmax = 6
@@ -835,6 +842,7 @@ class PmRelMachine(object):
835
842
  T, with_mtpa=with_mtpa,
836
843
  with_mtpv=False)[:2]
837
844
  i1 = betai1(iq, id)[1]
845
+ logger.debug("iq %f id %f i1 %f", iq, id, i1)
838
846
  try:
839
847
  if with_tmech:
840
848
  def voltw1(wx):
@@ -851,7 +859,7 @@ class PmRelMachine(object):
851
859
  if ier == 1: #in (1, 4, 5):
852
860
  if abs(w[0]) <= wx:
853
861
  self.check_extrapolation = True
854
- return [w/2/np.pi/self.p
862
+ return [float(w/2/np.pi/self.p)
855
863
  for w in (w1type, w[0], w1max)] # ['MTPA', 'MTPV']
856
864
  if w[0] > wu:
857
865
  wl += (wu-wl)/4
@@ -873,7 +881,7 @@ class PmRelMachine(object):
873
881
  self.check_extrapolation = True
874
882
  w1max = min(w1max, np.floor(self.w1_umax(
875
883
  u1max, *iqd(-np.pi/2, abs(i1max)))))
876
- return [w/2/np.pi/self.p for w in (w1type, w1max)] # ['MTPA']
884
+ return [float(w/2/np.pi/self.p) for w in (w1type, w1max)] # ['MTPA']
877
885
 
878
886
 
879
887
  def operating_point(self, T, n, u1max, with_mtpa=True):
@@ -925,10 +933,10 @@ class PmRelMachine(object):
925
933
  plfe1 = self.iqd_plfe1(iq, id, f1)
926
934
  plfe2 = self.iqd_plfe2(iq, id, f1)
927
935
  plmag = self.iqd_plmag(iq, id, f1)
928
- plfe = plfe1 + plfe2 + plmag
936
+ plfe = plfe1 + plfe2
929
937
  plfric = self.pfric(n)
930
938
  plcu = self.betai1_plcu(i1, 2 * np.pi * f1)
931
- pltotal = plfe + plcu + plfric
939
+ pltotal = plfe + plcu + plfric + plmag
932
940
  p1 = pmech + pltotal
933
941
  if np.abs(pmech) < 1e-12:
934
942
  eta = 0 # power to low for eta calculation
@@ -990,8 +998,8 @@ class PmRelMachine(object):
990
998
  if kwargs.get('i1max', 0):
991
999
  i1max = kwargs['i1max']
992
1000
  w1, Tf = self.w1_imax_umax(i1max, u1max,
993
- with_mtpa=with_mtpa,
994
- with_tmech=with_tmech)
1001
+ with_mtpa=with_mtpa,
1002
+ with_tmech=with_tmech)
995
1003
  if with_mtpa:
996
1004
  iq, id, T = self.mtpa(i1max)
997
1005
  else:
@@ -1026,7 +1034,8 @@ class PmRelMachine(object):
1026
1034
  iq, id = iqd(0, i1max)
1027
1035
 
1028
1036
  if with_tmech:
1029
- w1, Tf = self.w1_imax_umax(i1max, u1max, with_mtpa=with_mtpa,
1037
+ w1, Tf = self.w1_imax_umax(i1max, u1max,
1038
+ with_mtpa=with_mtpa,
1030
1039
  with_tmech=with_tmech)
1031
1040
  else:
1032
1041
  iq, id = self.iqd_torque(T)
@@ -1100,14 +1109,15 @@ class PmRelMachine(object):
1100
1109
  iq, id, tq = self.iqd_imax_umax(
1101
1110
  i1max, w1, u1max,
1102
1111
  tq, with_tmech=with_tmech,
1103
- with_mtpv=with_mtpv,
1104
1112
  with_mtpa=with_mtpa)
1105
1113
  else:
1106
1114
  if with_tmech:
1107
1115
  iq, id, tq = self.mtpv_tmech(w1, u1max,
1116
+ iqd0=(iq, id),
1108
1117
  maxtorque=T > 0)
1109
1118
  else:
1110
1119
  iq, id, tq = self.mtpv(w1, u1max,
1120
+ iqd0=(iq, id),
1111
1121
  maxtorque=T > 0)
1112
1122
  if (T > 0 and tq > 0) or (T < 0 and tq < 0):
1113
1123
  r['id'].append(id)
@@ -1115,8 +1125,8 @@ class PmRelMachine(object):
1115
1125
  r['n'].append(nn)
1116
1126
  r['T'].append(tq)
1117
1127
  else:
1118
- logger.warning("fieldweakening: n %g T %g tq %g i1max %g w1 %g u1 %g",
1119
- nn*60, T, tq, i1max, w1, u1max)
1128
+ logger.debug("fieldweakening: n %g T %g tq %g i1max %g w1 %g u1 %g",
1129
+ nn*60, T, tq, i1max, w1, u1max)
1120
1130
  except ValueError as e:
1121
1131
  nmax = r['n'][-1]
1122
1132
  logger.warning("%s: adjusted nmax %f T %f", e, nmax, r['T'][-1])
@@ -1149,11 +1159,15 @@ class PmRelMachine(object):
1149
1159
  f1 = np.array(r['n'])*self.p
1150
1160
  plfe1 = self.kpfe*self.iqd_plfe1(np.array(r['iq']), np.array(r['id']), f1)
1151
1161
  plfe2 = self.kpfe*self.iqd_plfe2(np.array(r['iq']), np.array(r['id']), f1)
1162
+ if hasattr(self, 'kpfe_s'):
1163
+ plfe1 = self.kpfe_s*self.iqd_plfe1(np.array(r['iq']), np.array(r['id']), f1)
1164
+ if hasattr(self, 'kpfe_r'):
1165
+ plfe2 = self.kpfe_r*self.iqd_plfe2(np.array(r['iq']), np.array(r['id']), f1)
1152
1166
  plmag = self.kpmag*self.iqd_plmag(np.array(r['iq']), np.array(r['id']), f1)
1153
- plfe = plfe1 + plfe2 + plmag
1167
+ plfe = plfe1 + plfe2
1154
1168
  plcu = self.betai1_plcu(np.array(r['i1']), 2*np.pi*f1)
1155
1169
  plfw = self.pfric(2*np.pi*f1)
1156
- pltotal = plfe + plcu + plfw
1170
+ pltotal = plfe + plcu + plfw + plmag
1157
1171
  r['pmech'] = pmech.tolist()
1158
1172
  r['plfe'] = plfe.tolist()
1159
1173
  r['plcu'] = plcu.tolist()
femagtools/machine/sm.py CHANGED
@@ -22,7 +22,7 @@ eecdefaults = {
22
22
  'tcu2': 20,
23
23
  'rotor_mass': 0,
24
24
  'kfric_b': 1,
25
- 'kpfe': 1 # iron loss factor
25
+ 'kpfe': 1 # common iron loss factor
26
26
  }
27
27
 
28
28
  logger = logging.getLogger('sm')
@@ -76,7 +76,13 @@ def parident(workdir, engine, machine,
76
76
  raise ValueError('i1_max missing')
77
77
  i1_max = kwargs['i1_max']
78
78
 
79
- ifnom = machine['rotor']['ifnom']
79
+
80
+ if "magnetFsl" in machine["magnet"]:
81
+ rotorkey = "magnet"
82
+ else:
83
+ rotorkey = "rotor"
84
+
85
+ ifnom = machine[rotorkey]['ifnom']
80
86
  exc_logspace = True
81
87
  ifmin, ifmax = ifnom/4, 1.4*ifnom
82
88
  if exc_logspace:
@@ -126,7 +132,7 @@ def parident(workdir, engine, machine,
126
132
  period_frac=kwargs.get('period_frac', 6),
127
133
  speed=kwargs.get('speed', 50))
128
134
 
129
- if kwargs.get("feloss", 0):
135
+ if kwargs.get("feloss", 0):
130
136
  simulation["feloss"] = kwargs["feloss"]
131
137
  machine["calc_fe_loss"] = loss_models[kwargs["feloss"].lower()]
132
138
  ###self.cleanup() # remove previously created files in workdir
@@ -197,7 +203,7 @@ def parident(workdir, engine, machine,
197
203
  if simulation['calculationMode'] == 'ld_lq_fast':
198
204
  dqpars = dict(m=3, p=b['machine']['p'],
199
205
  r1=float(r1),
200
- r2=machine['rotor'].get('resistance', 1),
206
+ r2=machine[rotorkey].get('resistance', 1),
201
207
  rotor_mass=rotor_mass, kfric_b=1,
202
208
  ldq=[dict(
203
209
  ex_current=b['machine']['ex_current'],
@@ -214,7 +220,7 @@ def parident(workdir, engine, machine,
214
220
  else:
215
221
  dqpars = dict(m=3, p=b['machine']['p'],
216
222
  r1=r1,
217
- r2=machine['rotor'].get('resistance', 1),
223
+ r2=machine[rotorkey].get('resistance', 1),
218
224
  rotor_mass=rotor_mass, kfric_b=1,
219
225
  psidq=[dict(
220
226
  ex_current=b['machine']['ex_current'],
@@ -387,8 +393,13 @@ class SynchronousMachine(object):
387
393
  and friction windage losses"""
388
394
  if n > 1e-3:
389
395
  f1 = self.p*n
390
- plfe = self.kpfe * (self.iqd_plfe1(iq, id, iex, f1)
391
- + self.iqd_plfe2(iq, id, iex, f1))
396
+ plfe1 = self.kpfe * self.iqd_plfe1(iq, id, iex, f1)
397
+ plfe2 = self.kpfe * self.iqd_plfe2(iq, id, iex, f1)
398
+ if hasattr(self, 'kpfe_s'):
399
+ plfe1 = self.kpfe_s * self.iqd_plfe1(iq, id, iex, f1)
400
+ if hasattr(self, 'kpfe_r'):
401
+ plfe2 = self.kpfe_r * self.iqd_plfe2(iq, id, iex, f1)
402
+ plfe = plfe1 + plfe2
392
403
  return (plfe + self.pfric(n))/(2*np.pi*n)
393
404
  return 0
394
405
 
@@ -413,8 +424,8 @@ class SynchronousMachine(object):
413
424
  def uqd(self, w1, iq, id, iex):
414
425
  """return uq, ud of frequency w1 and d-q current"""
415
426
  psid, psiq = self.psi(iq, id, iex)
416
- r1 = self.rstat(w1)
417
- return r1*iq + w1*psid, r1*id - w1*psiq
427
+ # r1 = self.rstat(w1)
428
+ return self.r1*iq + w1*(self.ls*id + psid), self.r1*id - w1*(self.ls*iq + psiq)
418
429
 
419
430
  def plcu1(self, iqde, w1):
420
431
  r1 = self.rstat(w1)
@@ -458,9 +469,9 @@ class SynchronousMachine(object):
458
469
  #options={'disp': disp, 'maxiter': maxiter})
459
470
  if res['success']:
460
471
  return res.x
461
- else:
472
+ else:
462
473
  res = so.minimize(
463
- lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, res.x, method='SLSQP',
474
+ lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, res.x, method='SLSQP',
464
475
  bounds=self.bounds,
465
476
  )
466
477
  if res['success']:
@@ -548,10 +559,10 @@ class SynchronousMachine(object):
548
559
  log(res.x)
549
560
  if res["success"]:
550
561
  return *res.x, self.tmech_iqd(*res.x, n)
551
- else:
562
+ else:
552
563
  # didn't converge, fullfill voltage and torque demand
553
564
  res = so.minimize(
554
- lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, io, method='SLSQP',
565
+ lambda cur: (self.tmech_iqd(*cur, n) - torque)**2, io, method='SLSQP',
555
566
  bounds=self.bounds,
556
567
  constraints=[
557
568
  {'type': 'eq',
@@ -562,8 +573,8 @@ class SynchronousMachine(object):
562
573
  return *res.x, self.tmech_iqd(*res.x, n)
563
574
  else:
564
575
  res = so.minimize(
565
- lambda cur: (self.tmech_iqd(*cur, n) - torque)**2 +
566
- (np.linalg.norm(self.uqd(w1, *cur)) - u1max*np.sqrt(2))**2, io, method='SLSQP',
576
+ lambda cur: (self.tmech_iqd(*cur, n) - torque)**2 +
577
+ (np.linalg.norm(self.uqd(w1, *cur)) - u1max*np.sqrt(2))**2, io, method='SLSQP',
567
578
  bounds=self.bounds,
568
579
  )
569
580
  return *res.x, self.tmech_iqd(*res.x, n)
@@ -680,7 +691,7 @@ class SynchronousMachine(object):
680
691
  Tf = T
681
692
  w1type = self.w1_umax(u1max, iq, id, iex)
682
693
  logger.debug("w1type %f", w1type)
683
- wmType = w1type/self.p
694
+ wmType = float(w1type/self.p)
684
695
  pmax = Tf*wmType
685
696
 
686
697
  def tload(wm):
@@ -723,7 +734,7 @@ class SynchronousMachine(object):
723
734
  iq, id, iex, tqx = self.iqd_torque_umax(
724
735
  tq, w1, u1max)
725
736
  tqx -= self.tfric
726
- else:
737
+ else:
727
738
  tqx = Tf
728
739
 
729
740
  uq, ud = self.uqd(w1, iq, id, iex)
@@ -857,9 +868,9 @@ class SynchronousMachinePsidq(SynchronousMachine):
857
868
  'rotor_hyst', 'rotor_eddy')}
858
869
 
859
870
  def set_max_iex(self, iexc):
860
- self.bounds[-1] = (self.bounds[-1][0], iexc)
871
+ self.bounds[-1] = (self.bounds[-1][0], iexc)
861
872
  self.exc_max = iexc
862
-
873
+
863
874
  def psi(self, iq, id, iex):
864
875
  """return psid, psiq of currents iq, id"""
865
876
  try:
@@ -980,9 +991,9 @@ class SynchronousMachineLdq(SynchronousMachine):
980
991
  'styoke_eddy', 'stteeth_eddy',
981
992
  'rotor_hyst', 'rotor_eddy')}
982
993
  pass
983
-
994
+
984
995
  def set_max_iex(self, iexc):
985
- self.bounds[-1] = (self.bounds[-1][0], iexc)
996
+ self.bounds[-1] = (self.bounds[-1][0], iexc)
986
997
  self.exc_max = iexc
987
998
 
988
999
  def psi(self, iq, id, iex):
femagtools/mcv.py CHANGED
@@ -1173,7 +1173,10 @@ class MagnetizingCurve(object):
1173
1173
  mcv = self.find_by_name(name)
1174
1174
  if not mcv:
1175
1175
  bname = name
1176
- filename = ''.join((name, ext))
1176
+ filename = name if pathlib.Path(name).suffix.upper() == ext \
1177
+ else ''.join((name, ext))
1178
+ if name == 'dummy':
1179
+ return filename
1177
1180
  # check fillfac and readmcv
1178
1181
  if not fillfac or fillfac == 1.0:
1179
1182
  try:
femagtools/plot/bch.py CHANGED
@@ -515,10 +515,12 @@ def cogging(bch, title=''):
515
515
  fig.subplots_adjust(top=0.92)
516
516
 
517
517
 
518
- def demagnetization(demag, ax=0):
518
+ def demagnetization(demag, title='', ax=0):
519
519
  """plot rel. remanence vs. current"""
520
520
  if ax == 0:
521
521
  ax = plt.gca()
522
+ if title:
523
+ ax.set_title(title)
522
524
  scale = 1
523
525
  unit = 'A'
524
526
  if np.max(demag['i1']) > 25e3:
femagtools/plot/char.py CHANGED
@@ -304,23 +304,12 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
304
304
  y, yscale = _normalize10(y, **kwargs)
305
305
 
306
306
  if not levels:
307
+ levels = [0.5, 0.7, 0.8]
307
308
  if max(z) <= 1:
308
- if max(z) > 0.96:
309
- #levels = [0.5, 0.75, 0.8, 0.84,
310
- #0.89, 0.92, 0.94, 0.96, 0.97]
311
- levels = np.linspace(min(z),max(z),9)
312
- levels = np.round(levels, 2)
313
- levels = list(levels)
314
-
315
- else:
316
- #levels = [0.25, 0.5, 0.75, 0.8, 0.84,
317
- #0.88, 0.9, 0.92, 0.94, 0.96]
318
- levels = np.linspace(min(z),max(z),9)
319
- levels = np.round(levels, 2)
320
- levels = list(levels)
321
-
322
- if max(z) > levels[-1]:
323
- levels.append(np.ceil(max(z)*100)/100)
309
+ a = np.array(z)
310
+ zmax = np.ceil(100*np.max(z))/100
311
+ levels += [zmax - x for x in
312
+ [0.07, 0.05, 0.03, 0.02, 0.01, 0]]
324
313
  else:
325
314
  levels = 14
326
315
  #