femagtools 1.5.7__py3-none-any.whl → 1.6.0__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.
Files changed (38) hide show
  1. femagtools/__init__.py +1 -1
  2. femagtools/bch.py +14 -1
  3. femagtools/dxfsl/area.py +2 -3
  4. femagtools/dxfsl/converter.py +10 -2
  5. femagtools/dxfsl/fslrenderer.py +1 -2
  6. femagtools/dxfsl/functions.py +24 -27
  7. femagtools/dxfsl/geom.py +116 -80
  8. femagtools/dxfsl/machine.py +16 -7
  9. femagtools/dxfsl/plotrenderer.py +2 -2
  10. femagtools/dxfsl/shape.py +68 -17
  11. femagtools/femag.py +21 -3
  12. femagtools/fsl.py +14 -2
  13. femagtools/machine/__init__.py +13 -33
  14. femagtools/machine/afpm.py +22 -21
  15. femagtools/machine/pm.py +22 -21
  16. femagtools/machine/utils.py +112 -58
  17. femagtools/mcv.py +27 -1
  18. femagtools/model.py +4 -2
  19. femagtools/nc.py +7 -0
  20. femagtools/opt.py +1 -1
  21. femagtools/parstudy.py +5 -2
  22. femagtools/plot/__init__.py +1 -0
  23. femagtools/plot/bch.py +2 -0
  24. femagtools/plot/fieldlines.py +37 -0
  25. femagtools/templates/basic_modpar.mako +8 -0
  26. femagtools/templates/bertotti.mako +40 -0
  27. femagtools/templates/modified_steinmetz.mako +39 -0
  28. femagtools/ts.py +1 -1
  29. femagtools/utils.py +7 -1
  30. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/METADATA +1 -1
  31. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/RECORD +38 -35
  32. tests/test_bchreader.py +12 -1
  33. tests/test_femag.py +1 -1
  34. tests/test_fsl.py +1 -1
  35. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/LICENSE +0 -0
  36. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/WHEEL +0 -0
  37. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/entry_points.txt +0 -0
  38. {femagtools-1.5.7.dist-info → femagtools-1.6.0.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/shape.py CHANGED
@@ -9,7 +9,6 @@
9
9
  """
10
10
  from __future__ import print_function
11
11
  import numpy as np
12
- import sys
13
12
  import logging
14
13
  from .functions import less_equal, greater_equal
15
14
  from .functions import distance, line_m, line_n
@@ -18,7 +17,7 @@ from .functions import alpha_line, alpha_angle, alpha_triangle
18
17
  from .functions import normalise_angle, min_angle, max_angle, get_angle_of_arc
19
18
  from .functions import lines_intersect_point, nodes_are_equal
20
19
  from .functions import is_angle_inside, intersect_point
21
- from .functions import middle_angle
20
+ from .functions import middle_angle, middle_point_of_line
22
21
 
23
22
  logger = logging.getLogger('femagtools.geom')
24
23
 
@@ -50,7 +49,10 @@ class Shape(object):
50
49
  if hasattr(s, 'my_attrs'):
51
50
  self.my_attrs = []
52
51
  for a in s.my_attrs:
53
- self.my_attrs.append(a)
52
+ self.my_attrs.append(a)
53
+
54
+ def classname(self):
55
+ return "Shape"
54
56
 
55
57
  def get_my_color(self):
56
58
  if hasattr(self, 'my_color'):
@@ -209,8 +211,8 @@ class Shape(object):
209
211
  d1 = distance(n, self.n1)
210
212
  d2 = distance(n, self.n2)
211
213
  if d1 == d2:
212
- logger.info("distances of %s and %s are equal (%s / %s)",
213
- self.n1, self.n2, d1, d2)
214
+ logger.warning("distances of %s and %s are equal (%s / %s)",
215
+ self.n1, self.n2, d1, d2)
214
216
  raise ValueError('both nodes are equal in element')
215
217
 
216
218
  if d1 < d2:
@@ -307,6 +309,9 @@ class Circle(Shape):
307
309
  self.n1 = None
308
310
  self.n2 = None
309
311
 
312
+ def classname(self):
313
+ return "Circle"
314
+
310
315
  def render(self, renderer, color='blue', with_nodes=False):
311
316
  tmp_color = self.get_my_color()
312
317
  if not tmp_color:
@@ -544,6 +549,19 @@ class Circle(Shape):
544
549
  assert(len(points) == 0)
545
550
  return []
546
551
 
552
+ def cut_into_halves(self):
553
+ """ return two arcs
554
+ """
555
+ a1 = Arc(Element(center=self.center,
556
+ radius=self.radius,
557
+ start_angle=0.0,
558
+ end_angle=180.0))
559
+ a2 = Arc(Element(center=self.center,
560
+ radius=self.radius,
561
+ start_angle=180.0,
562
+ end_angle=0.0))
563
+ return a1, a2
564
+
547
565
  def get_angle_of_arc(self):
548
566
  return np.pi*2.0
549
567
 
@@ -608,6 +626,9 @@ class Arc(Circle):
608
626
  else:
609
627
  self.rtheta = None
610
628
 
629
+ def classname(self):
630
+ return "Arc"
631
+
611
632
  def render(self, renderer, color='blue', with_nodes=False):
612
633
  tmp_color = self.get_my_color()
613
634
  if not tmp_color:
@@ -715,8 +736,9 @@ class Arc(Circle):
715
736
  points.append(e.p2)
716
737
 
717
738
  elif e.is_point_inside(self.p2, rtol, atol):
718
- if not points_are_close(self.p1, e.p1):
739
+ if not points_are_close(self.p1, e.p1, rtol=rtol, atol=atol):
719
740
  logger.error("FATAL ERROR in overlapping_shape() of Arc")
741
+
720
742
  raise ValueError('FATAL ERROR in overlapping_shape() of Arc')
721
743
  points.append(e.p1)
722
744
  points.append(self.p2)
@@ -808,6 +830,20 @@ class Arc(Circle):
808
830
  assert(len(points_inside) == 0)
809
831
  return []
810
832
 
833
+ def cut_into_halves(self):
834
+ """ return two arcs
835
+ """
836
+ midangle = middle_angle(self.startangle, self.endangle)
837
+ a1 = Arc(Element(center=self.center,
838
+ radius=self.radius,
839
+ start_angle=self.startangle*180/np.pi,
840
+ end_angle=midangle*180/np.pi))
841
+ a2 = Arc(Element(center=self.center,
842
+ radius=self.radius,
843
+ start_angle=midangle*180/np.pi,
844
+ end_angle=self.endangle*180/np.pi))
845
+ return a1, a2
846
+
811
847
  def concatenate_arc(self, n1, n2, el):
812
848
  if not points_are_close(self.center, el.center):
813
849
  return None
@@ -833,30 +869,30 @@ class Arc(Circle):
833
869
  def is_point_inside(self, p, rtol=1e-03, atol=1e-03, include_end=False):
834
870
  """ returns true if p is on arc
835
871
  """
836
- logger.debug("is_point_inside: p=%s", p)
872
+ # logger.debug("is_point_inside: p=%s", p)
837
873
  d = distance(p, self.center)
838
874
  if not np.isclose(d, self.radius, rtol=rtol, atol=atol):
839
- logger.debug(" <== RADIUS %s, DISTANCE %s",
840
- self.radius, d)
875
+ # logger.debug(" <== RADIUS %s, DISTANCE %s",
876
+ # self.radius, d)
841
877
  return False
842
878
  if points_are_close(p, self.p1, rtol=rtol, atol=atol):
843
- logger.debug(" <== CLOSE TO P1 %s: rtol=%s, atol=%s",
844
- self.p1, rtol, atol)
879
+ # logger.debug(" <== CLOSE TO P1 %s: rtol=%s, atol=%s",
880
+ # self.p1, rtol, atol)
845
881
  return include_end
846
882
  elif points_are_close(p, self.p2, rtol=rtol, atol=atol):
847
- logger.debug(" <== CLOSE TO P2 %s: rtol=%s, atol=%s",
848
- self.p2, rtol, atol)
883
+ # logger.debug(" <== CLOSE TO P2 %s: rtol=%s, atol=%s",
884
+ # self.p2, rtol, atol)
849
885
  return include_end
850
886
  elif points_are_close(self.p1, self.p2, rtol=rtol, atol=atol):
851
- logger.debug(" <== P1 AND P2 CLOSE TOGETHER")
887
+ # logger.debug(" <== P1 AND P2 CLOSE TOGETHER")
852
888
  return False
853
889
 
854
890
  alpha_p1 = alpha_line(self.center, self.p1)
855
891
  alpha_p2 = alpha_line(self.center, self.p2)
856
892
  alpha_p = alpha_line(self.center, p)
857
893
  alpha_inside = is_angle_inside(alpha_p1, alpha_p2, alpha_p)
858
- logger.debug("is_point_inside: %s (%s, %s ,%s)",
859
- alpha_inside, alpha_p1, alpha_p2, alpha_p)
894
+ # logger.debug("is_point_inside: %s (%s, %s ,%s)",
895
+ # alpha_inside, alpha_p1, alpha_p2, alpha_p)
860
896
  return alpha_inside
861
897
 
862
898
  def is_angle_inside(self, alpha, rtol=1e-03, atol=1e-03,
@@ -889,7 +925,7 @@ class Arc(Circle):
889
925
  self.startangle = np.arctan2(p1[1], p1[0])
890
926
  self.endangle = np.arctan2(p2[1], p2[0])
891
927
  if self.rtheta is not None:
892
- self.rtheta = self.rtheta + alpha
928
+ self.rtheta = self.rtheta + dest_alpha
893
929
  return self
894
930
 
895
931
  def minmax(self):
@@ -1054,6 +1090,9 @@ class Line(Shape):
1054
1090
  self.n1 = None
1055
1091
  self.n2 = None
1056
1092
 
1093
+ def classname(self):
1094
+ return "Line"
1095
+
1057
1096
  def render(self, renderer, color='blue', with_nodes=False):
1058
1097
  tmp_color = self.get_my_color()
1059
1098
  if not tmp_color:
@@ -1186,6 +1225,14 @@ class Line(Shape):
1186
1225
  return split_lines
1187
1226
  return []
1188
1227
 
1228
+ def cut_into_halves(self):
1229
+ """ return two lines
1230
+ """
1231
+ pm = middle_point_of_line(self.p1, self.p2)
1232
+ l1 = Line(Element(start=self.p1, end=pm))
1233
+ l2 = Line(Element(start=pm, end=self.p2))
1234
+ return l1, l2
1235
+
1189
1236
  def concatenate_line(self, n1, n2, el):
1190
1237
  if np.isclose(self.m(999999.0), el.m(999999.0)):
1191
1238
  return Line(Element(start=n1, end=n2))
@@ -1293,6 +1340,9 @@ class Point(Shape):
1293
1340
  def __init__(self, p):
1294
1341
  self.p1 = p
1295
1342
 
1343
+ def classname(self):
1344
+ return "Point"
1345
+
1296
1346
  def render(self, renderer):
1297
1347
  renderer.point(self.p1)
1298
1348
 
@@ -1301,6 +1351,7 @@ class Point(Shape):
1301
1351
  self.p1 = (n[0], n[1])
1302
1352
  return self
1303
1353
 
1354
+
1304
1355
  def is_Circle(e):
1305
1356
  return isinstance(e, Circle) and not isinstance(e, Arc)
1306
1357
 
femagtools/femag.py CHANGED
@@ -90,7 +90,7 @@ def get_shortCircuit_parameters(bch, nload):
90
90
  fc_radius=bch.machine['fc_radius'],
91
91
  lfe=bch.armatureLength/1e3,
92
92
  pocfilename=bch.machine['pocfile'],
93
- num_par_wdgs=bch.machine['num_par_wdgs'],
93
+ num_par_wdgs=bch.machine.get('num_par_wdgs', 0),
94
94
  calculationMode='shortcircuit')
95
95
  except (KeyError, AttributeError, IndexError):
96
96
  raise FemagError("missing pm/Rel-Sim results")
@@ -222,6 +222,12 @@ class BaseFemag(object):
222
222
  pass
223
223
  builder = femagtools.fsl.Builder(self.templatedirs)
224
224
  if simulation:
225
+ if 'num_par_wdgs' not in simulation:
226
+ try:
227
+ num_par_wdgs = self.model.winding['num_par_wdgs']
228
+ simulation['num_par_wdgs'] = num_par_wdgs
229
+ except:
230
+ pass
225
231
  set_magnet_properties(self.model, simulation, self.magnets)
226
232
  return builder.create(self.model, simulation,
227
233
  self.magnets, self.condMat)
@@ -351,6 +357,16 @@ class BaseFemag(object):
351
357
 
352
358
  def readResult(self, simulation, bch=None):
353
359
  if simulation:
360
+ if simulation['calculationMode'] == "fieldcalc":
361
+ nc = self.read_nc()
362
+ pmod = nc.poles_sim
363
+ r = {'airgap': ag.read(
364
+ os.path.join(self.workdir, 'bag.dat'), pmod=pmod)}
365
+ if 'plots' in simulation:
366
+ if 'field_lines' in simulation['plots']:
367
+ r['field_lines'] = os.path.join(
368
+ self.workdir, 'field.svg')
369
+ return r
354
370
  if simulation['calculationMode'] == "pm_sym_loss":
355
371
  return self.read_los(self.modelname)
356
372
 
@@ -365,7 +381,8 @@ class BaseFemag(object):
365
381
 
366
382
  if simulation['calculationMode'] == 'therm-dynamic':
367
383
  temp = [[float(n) for n in l.split()]
368
- for l in (pathlib.Path(self.workdir) / 'temperature.dat').read_text().split('\n') if l]
384
+ for l in (pathlib.Path(self.workdir) /
385
+ 'temperature.dat').read_text().split('\n') if l]
369
386
  ttemp = list(zip(*temp))
370
387
  return {'t': ttemp[0], 'temperature': ttemp[1]}
371
388
 
@@ -383,9 +400,10 @@ class BaseFemag(object):
383
400
  set_magnet_properties(self.model, simulation, self.magnets)
384
401
  fslcmds = (builder.open_model(self.model) +
385
402
  builder.create_shortcircuit(simulation))
403
+ fslfile = 'shortcicuit.fsl'
386
404
  with open(os.path.join(self.workdir, fslfile), 'w') as f:
387
405
  f.write('\n'.join(fslcmds))
388
- self.run(fslfile, options)
406
+ self.run(fslfile) #, options?
389
407
  bchfile = self.get_bch_file(self.modelname)
390
408
  if bchfile:
391
409
  bchsc = femagtools.bch.Reader()
femagtools/fsl.py CHANGED
@@ -484,7 +484,11 @@ class Builder:
484
484
  if not hasattr(model, 'stator'):
485
485
  setattr(model, 'stator', {})
486
486
  model.stator['num_slots'] = conv.get('tot_num_slot')
487
- model.stator['num_slots_gen'] = conv.get('num_sl_gen')
487
+ if model.stator.get('num_slots_gen', 0):
488
+ if model.stator['num_slots'] % model.stator['num_slots_gen'] > 0:
489
+ model.stator['num_slots_gen'] = conv.get('num_sl_gen')
490
+ else:
491
+ model.stator['num_slots_gen'] = conv.get('num_sl_gen')
488
492
  if 'fsl_stator' in conv:
489
493
  self.fsl_stator = True
490
494
  model.stator['dxf'] = dict(fsl=conv['fsl_stator'])
@@ -633,15 +637,23 @@ class Builder:
633
637
 
634
638
  def create_analysis(self, sim):
635
639
  pfefunc = sim.get('loss_funct', '')
640
+ custom_fefunc = ['']
636
641
  if pfefunc:
637
642
  sim['loss_funct'] = 1 # 3?
643
+ if pfefunc == 'bertotti' or 'modified_steinmetz':
644
+ custom_fefunc = self.__render(sim['PVFE_FSL'], pfefunc)
645
+ else:
646
+ custom_fefunc = pfefunc.split('\n')
647
+
638
648
  airgap_induc = (self.create_airgap_induc()
639
649
  if sim.get('airgap_induc', 0) else [])
640
- felosses = pfefunc.split('\n') + self.create_fe_losses(sim)
650
+ felosses = custom_fefunc + self.create_fe_losses(sim)
641
651
  fslcalc = (self.__render(sim, sim.get('calculationMode')) +
642
652
  airgap_induc)
653
+ '''
643
654
  if pfefunc:
644
655
  sim['loss_funct'] = pfefunc
656
+ '''
645
657
 
646
658
  if sim.get('calculationMode') in ('cogg_calc',
647
659
  'ld_lq_fast',
@@ -14,13 +14,14 @@ import logging
14
14
  logger = logging.getLogger(__name__)
15
15
 
16
16
 
17
- def __scale_losses(losses, lfe):
17
+ def __scale_losses(losses, rlfe):
18
18
  if losses:
19
- l = {k: lfe*np.array(losses[k]) for k in (
19
+ l = {k: rlfe*np.array(losses[k]) for k in (
20
20
  'styoke_hyst', 'styoke_eddy',
21
21
  'stteeth_hyst', 'stteeth_eddy',
22
+ 'styoke_excess', 'stteeth_excess', 'rotor_excess',
22
23
  'rotor_hyst', 'rotor_eddy',
23
- 'magnet')}
24
+ 'magnet') if k in losses}
24
25
  l['speed'] = losses['speed']
25
26
  return l
26
27
  return {}
@@ -66,18 +67,15 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
66
67
 
67
68
  psid = rwdg*rlfe*dqp['psid']
68
69
  psiq = rwdg*rlfe*dqp['psiq']
69
- try:
70
- losses = __scale_losses(dqp['losses'], rlfe)
71
- losses['ef'] = dqpars[-1]['losses']['ef']
72
- losses['eh'] = dqpars[-1]['losses']['ef']
73
- except KeyError as e:
74
- logger.warning(e)
75
- losses = {}
70
+ losses = __scale_losses(dqp['losses'], rlfe)
71
+ losses['ef'] = dqpars[-1]['losses']['ef']
72
+ losses['eh'] = dqpars[-1]['losses']['ef']
73
+
76
74
  if 'psidq' in eecpars:
77
75
  machine = PmRelMachinePsidq(
78
76
  eecpars['m'], eecpars['p'],
79
- r1=eecpars['r1']*rlfe*rwdg**2,
80
- ls=eecpars['ls1']*rwdg**2,
77
+ r1=eecpars.get('r1', 0)*rlfe*rwdg**2,
78
+ ls=eecpars.get('ls1', 0)*rwdg**2,
81
79
  psid=psid,
82
80
  psiq=psiq,
83
81
  losses=losses,
@@ -90,8 +88,8 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
90
88
  i1 = np.array(dqp['i1'])/rwdg
91
89
  machine = PmRelMachineLdq(
92
90
  eecpars['m'], eecpars['p'],
93
- r1=eecpars['r1']*rlfe*rwdg**2,
94
- ls=eecpars['ls1']*rwdg**2,
91
+ r1=eecpars.get('r1', 0)*rlfe*rwdg**2,
92
+ ls=eecpars.get('ls1', 0)*rwdg**2,
95
93
  psid=psid,
96
94
  psiq=psiq,
97
95
  losses=losses,
@@ -103,7 +101,7 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
103
101
 
104
102
  # must be an induction machine (TODO: check scaling)
105
103
  pars = copy.deepcopy(eecpars)
106
- pars['r1'] = rlfe*rwdg**2*pars['r1']
104
+ pars['r1'] = rlfe*rwdg**2*pars.get('r1', 0)
107
105
  pars['lsigma1'] = rlfe*pars['lsigma1']
108
106
  pars['lsigma2'] = rlfe*pars['lsigma2']
109
107
  pars['psiref'] = rwdg*rlfe*pars['psiref']
@@ -119,24 +117,6 @@ def create_from_eecpars(temp, eecpars, lfe=1, wdg=1):
119
117
  return InductionMachine(pars)
120
118
 
121
119
 
122
- def __scale_losses(losses, rlfe):
123
- if losses:
124
- l = {k: rlfe*np.array(losses[k]) for k in (
125
- 'styoke_hyst', 'styoke_eddy',
126
- 'stteeth_hyst', 'stteeth_eddy',
127
- 'rotor_hyst', 'rotor_eddy',
128
- 'magnet')}
129
- if 'styoke_exc' in losses:
130
- l.update({k: rlfe*np.array(losses[k])
131
- for k in (
132
- 'styoke_exc',
133
- 'stteeth_exc',
134
- 'rotor_exc')})
135
- l['speed'] = losses['speed']
136
- return l
137
- return {}
138
-
139
-
140
120
  def create(bch, r1, ls, lfe=1, wdg=1):
141
121
  """create PmRelMachine from BCH
142
122
 
@@ -45,7 +45,7 @@ def ld_interpol(i1, beta, v):
45
45
  cur = copy.deepcopy(i1)
46
46
  betad = copy.deepcopy(beta)
47
47
  if np.amin(beta) < -90 and \
48
- np.amax(beta) > -90:
48
+ np.amax(beta) > -90:
49
49
  # motor and generator
50
50
  v[0] = v[1]
51
51
  v[-1] = v[-2]
@@ -53,18 +53,18 @@ def ld_interpol(i1, beta, v):
53
53
  dbeta = np.abs(beta[0][0] - beta[1][0])
54
54
  bp = [[beta[0][0]-dbeta for i in range(len(np.unique(i1)))]] + beta[1:-1] + \
55
55
  [[dbeta for i in range(len(np.unique(i1)))]]
56
- else:
56
+ else:
57
57
  v[-1] = v[-2]
58
58
  dbeta = np.abs(beta[0][0] - beta[1][0])
59
59
  bp = beta[0:-1] + \
60
60
  [[dbeta for i in range(len(np.unique(i1)))]]
61
-
61
+
62
62
  return RectBivariateSpline(np.unique(bp), np.unique(cur), \
63
63
  np.array(v)).ev(*[betad, i1]).tolist()
64
64
 
65
65
  def lq_interpol(i1, beta, v):
66
66
  '''interpolate Lq at beta -90°'''
67
- if -90 not in np.unique(beta):
67
+ if -90 not in np.unique(beta):
68
68
  return v
69
69
  # lq
70
70
  betad = copy.deepcopy(beta)
@@ -75,7 +75,7 @@ def lq_interpol(i1, beta, v):
75
75
  v.pop(inx[0, 0])
76
76
  bp = beta[0:inx[0, 0]] + beta[inx[0, 0]+1:]
77
77
  cp = i1[0:inx[0, 0]] + i1[inx[0, 0]+1:]
78
- else:
78
+ else:
79
79
  v[0] = v[1]
80
80
  dbeta = np.abs(beta[0][0] - beta[1][0])
81
81
  bp = [[-90-dbeta for i in i1[0]]] + beta[1::]
@@ -181,7 +181,7 @@ def parident(workdir, engine, temp, machine,
181
181
  poc=poc.Poc(999),
182
182
  speed=0)
183
183
  logging.info("Noload simulation")
184
- if kwargs.get('use_multiprocessing', True):
184
+ if kwargs.get('use_multiprocessing', True):
185
185
  pstudy = parstudy.List(
186
186
  workdir, condMat=condMat, magnets=magnetMat,
187
187
  magnetizingCurves=magnetizingCurves,
@@ -190,17 +190,17 @@ def parident(workdir, engine, temp, machine,
190
190
  nlresults = pstudy(nlparvardef, machine, nlcalc, engine)
191
191
  if nlresults['status'].count('C') != len(nlresults['status']):
192
192
  raise ValueError('Noload simulation failed %s', nlresults['status'])
193
- else:
193
+ else:
194
194
  nlresults = {"x": [], "f": []}
195
195
  i = 0
196
- for pw, le, sp in zip(pole_width, lfe, linspeed):
196
+ for pw, le, sp in zip(pole_width, lfe, linspeed):
197
197
  nlmachine = {k: machine[k] for k in machine}
198
198
  nlmachine['pole_width'] = pw
199
199
  nlmachine['lfe'] = le
200
200
  nlcalc.update({"speed": sp})
201
201
  nlsubdir = f'{workdir}/{i}'
202
202
  nlworkdir = Path(nlsubdir)
203
- if nlworkdir.exists():
203
+ if nlworkdir.exists():
204
204
  shutil.rmtree(nlworkdir)
205
205
  nlworkdir.mkdir(exist_ok=True)
206
206
  noloadsim = femag.Femag(nlworkdir, condMat=condMat, magnets=magnetMat,
@@ -235,8 +235,8 @@ def parident(workdir, engine, temp, machine,
235
235
  num_move_steps=60,
236
236
  speed=linspeed[i],
237
237
  num_par_wdgs=machine[wdgk].get('num_par_wdgs', 1))
238
-
239
- if kwargs.get('use_multiprocessing', True):
238
+
239
+ if kwargs.get('use_multiprocessing', True):
240
240
  gpstudy = parstudy.Grid(
241
241
  subdir, condMat=condMat, magnets=magnetMat,
242
242
  magnetizingCurves=magnetizingCurves,
@@ -248,7 +248,7 @@ def parident(workdir, engine, temp, machine,
248
248
  domain_beta = np.linspace(beta_min, 0, num_beta_steps).tolist()
249
249
  domain_cur = np.linspace(i1_max/num_cur_steps, i1_max, num_cur_steps).tolist()
250
250
  dir_index = 0
251
- for cur in domain_cur:
251
+ for cur in domain_cur:
252
252
  for be in domain_beta:
253
253
  simulation['angl_i_up'] = be
254
254
  simulation['current'] = cur
@@ -256,7 +256,7 @@ def parident(workdir, engine, temp, machine,
256
256
  subsubdir = subdir + f'/{dir_index}'
257
257
  dir_index = dir_index + 1
258
258
  lworkdir = Path(subsubdir)
259
- if lworkdir.exists():
259
+ if lworkdir.exists():
260
260
  shutil.rmtree(lworkdir)
261
261
  lworkdir.mkdir(exist_ok=True)
262
262
  loadsim = femag.Femag(lworkdir, condMat=condMat, magnets=magnetMat,
@@ -264,7 +264,7 @@ def parident(workdir, engine, temp, machine,
264
264
  cmd=kwargs.get('cmd', None))
265
265
  r = loadsim(mpart, simulation)
266
266
  lresults['f'].append({k: v for k, v in r.items()})
267
-
267
+
268
268
  f = [{k: bch[k]
269
269
  for k in ('linearForce', 'flux', 'losses', 'lossPar')}
270
270
  for bch in lresults['f']]
@@ -288,18 +288,18 @@ def parident(workdir, engine, temp, machine,
288
288
  (-1, num_beta_steps)).T/np.sqrt(2)
289
289
  psiq = np.reshape([r['psiq'] for r in postp],
290
290
  (-1, num_beta_steps)).T/np.sqrt(2)
291
-
291
+
292
292
  ld = np.reshape([r['Ld'] for r in postp],
293
293
  (-1, num_beta_steps)).T.tolist()
294
294
  lq = np.reshape([r['Lq'] for r in postp],
295
295
  (-1, num_beta_steps)).T.tolist()
296
296
  # interpolation ld, lq
297
- curr, angl = [], []
298
- for cr in range(len(beta)):
297
+ curr, angl = [], []
298
+ for cr in range(len(beta)):
299
299
  curr.append(i1)
300
- for al in beta:
300
+ for al in beta:
301
301
  tmp = []
302
- for cr in range(len(i1)):
302
+ for cr in range(len(i1)):
303
303
  tmp.append(al)
304
304
  angl.append(tmp)
305
305
  try:
@@ -307,10 +307,10 @@ def parident(workdir, engine, temp, machine,
307
307
  ld = ld_interpol(xx, yy, ld)
308
308
  xx, yy = copy.deepcopy(curr), copy.deepcopy(angl)
309
309
  lq = lq_interpol(xx, yy, lq)
310
- except:
310
+ except:
311
311
  ld = np.zeros_like(psid).tolist()
312
312
  lq = np.zeros_like(psid).tolist()
313
-
313
+
314
314
  torque = np.reshape([r['torque'] for r in postp],
315
315
  (-1, num_beta_steps)).T
316
316
  losses = {k: np.flip(np.reshape([r['plfe'][k] for r in postp],
@@ -547,6 +547,7 @@ def wdg_resistance(wdg, n, g, aw, outer_diam, inner_diam,
547
547
  def _get_copper_losses(scale_factor, bch):
548
548
  """return copper losses from bch files"""
549
549
  try:
550
+ wdgk = 'winding'
550
551
  cu_losses = sum([b['losses'][0][wdgk] for b in bch])
551
552
  return scale_factor*cu_losses
552
553
  except KeyError:
femagtools/machine/pm.py CHANGED
@@ -638,10 +638,10 @@ class PmRelMachine(object):
638
638
  'rotor_hyst': hf[1],
639
639
  'rotor_eddy': ef[1]}
640
640
  # 'magnet'):
641
- if 'styoke_exc' in pfe:
642
- self.plexp.update({'styoke_exc': cf[0],
643
- 'stteeth_exc':cf[0],
644
- 'rotor_exc': cf[1]})
641
+ if 'styoke_excess' in pfe:
642
+ self.plexp.update({'styoke_excess': cf[0],
643
+ 'stteeth_excess':cf[0],
644
+ 'rotor_excess': cf[1]})
645
645
 
646
646
  def betai1_plcu(self, i1, w1=0):
647
647
  return self.m*self.rstat(w1)*i1**2
@@ -1143,15 +1143,16 @@ class PmRelMachineLdq(PmRelMachine):
1143
1143
  kx = len(beta)-1
1144
1144
  try:
1145
1145
  pfe = kwargs['losses']
1146
- if 'styoke_exc' in pfe:
1146
+ if 'styoke_excess' in pfe and np.any(pfe['styoke_excess']):
1147
1147
  self.bertotti = True
1148
- self.losskeys += ['styoke_exc',
1149
- 'stteeth_exc',
1150
- 'rotor_exc']
1148
+ self.losskeys += ['styoke_excess',
1149
+ 'stteeth_excess',
1150
+ 'rotor_excess']
1151
1151
  self._set_losspar(pfe)
1152
1152
  self._losses = {k: ip.RectBivariateSpline(
1153
1153
  beta, i1, np.array(pfe[k]),
1154
- kx=kx, ky=ky).ev for k in tuple(self.losskeys)}
1154
+ kx=kx, ky=ky).ev for k in self.losskeys
1155
+ if k in pfe}
1155
1156
  except KeyError as e:
1156
1157
  logger.warning("loss map missing: %s", e)
1157
1158
  pass
@@ -1238,12 +1239,12 @@ class PmRelMachineLdq(PmRelMachine):
1238
1239
 
1239
1240
  def betai1_plfe1(self, beta, i1, f1):
1240
1241
  stator_losskeys = ['styoke_eddy', 'styoke_hyst',
1241
- 'stteeth_eddy', 'stteeth_hyst']
1242
+ 'stteeth_eddy', 'stteeth_hyst']
1242
1243
  if self.bertotti:
1243
- stator_losskeys += ['styoke_exc', 'stteeth_exc']
1244
+ stator_losskeys += ['styoke_excess', 'stteeth_excess']
1244
1245
  return np.sum([
1245
- self._losses[k](beta, i1)*(f1/self.fo)**self.plexp[k] for
1246
- k in tuple(stator_losskeys)], axis=0)
1246
+ self._losses[k](beta, i1)*(f1/self.fo)**self.plexp[k]
1247
+ for k in stator_losskeys if k in self._losses], axis=0)
1247
1248
 
1248
1249
  def iqd_plfe1(self, iq, id, f1):
1249
1250
  return self.betai1_plfe1(*betai1(iq, id), f1)
@@ -1251,7 +1252,7 @@ class PmRelMachineLdq(PmRelMachine):
1251
1252
  def betai1_plfe2(self, beta, i1, f1):
1252
1253
  rotor_losskeys = ['rotor_eddy', 'rotor_hyst']
1253
1254
  if self.bertotti:
1254
- rotor_losskeys += ['rotor_exc']
1255
+ rotor_losskeys += ['rotor_excess']
1255
1256
  return np.sum([
1256
1257
  self._losses[k](beta, i1)*(f1/self.fo)**self.plexp[k] for
1257
1258
  k in tuple(rotor_losskeys)], axis=0)
@@ -1295,7 +1296,7 @@ class PmRelMachinePsidq(PmRelMachine):
1295
1296
  self.iqrange = (min(iq), max(iq))
1296
1297
  self.betarange = (-np.pi if min(iq) < 0 else -np.pi/2,
1297
1298
  0 if max(iq) > 0 else -np.pi/2)
1298
- self.i1range = (0, np.sqrt(2)*np.min(id))
1299
+ self.i1range = (0, betai1(np.max(iq), 0)[1])
1299
1300
  self.io = np.max(iq)/2, np.min(id)/2
1300
1301
 
1301
1302
  if np.any(psid.shape < (4, 4)):
@@ -1322,11 +1323,11 @@ class PmRelMachinePsidq(PmRelMachine):
1322
1323
  self._psiq = ip.RectBivariateSpline(iq, id, psiq).ev
1323
1324
  try:
1324
1325
  pfe = kwargs['losses']
1325
- if 'styoke_exc' in pfe:
1326
+ if 'styoke_excess' in pfe and np.any(pfe['styoke_excess']):
1326
1327
  self.bertotti = True
1327
- self.losskeys += ['styoke_exc',
1328
- 'stteeth_exc',
1329
- 'rotor_exc']
1328
+ self.losskeys += ['styoke_excess',
1329
+ 'stteeth_excess',
1330
+ 'rotor_excess']
1330
1331
  self._set_losspar(pfe)
1331
1332
  self._losses = {k: ip.RectBivariateSpline(
1332
1333
  iq, id, np.array(pfe[k])).ev for k in (
@@ -1385,7 +1386,7 @@ class PmRelMachinePsidq(PmRelMachine):
1385
1386
  stator_losskeys = ['styoke_eddy', 'styoke_hyst',
1386
1387
  'stteeth_eddy', 'stteeth_hyst']
1387
1388
  if self.bertotti:
1388
- stator_losskeys += ['styoke_exc', 'stteeth_exc']
1389
+ stator_losskeys += ['styoke_excess', 'stteeth_excess']
1389
1390
  return np.sum([
1390
1391
  self._losses[k](iq, id)*(f1/self.fo)**self.plexp[k] for
1391
1392
  k in tuple(stator_losskeys)], axis=0)
@@ -1396,7 +1397,7 @@ class PmRelMachinePsidq(PmRelMachine):
1396
1397
  def iqd_plfe2(self, iq, id, f1):
1397
1398
  rotor_losskeys = ['rotor_eddy', 'rotor_hyst']
1398
1399
  if self.bertotti:
1399
- rotor_losskeys += ['rotor_exc']
1400
+ rotor_losskeys += ['rotor_excess']
1400
1401
  return np.sum([
1401
1402
  self._losses[k](iq, id)*(f1/self.fo)**self.plexp[k] for
1402
1403
  k in tuple(rotor_losskeys)], axis=0)