femagtools 1.7.8__py3-none-any.whl → 1.7.9__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/dxfsl/area.py +38 -9
  3. femagtools/dxfsl/converter.py +2 -1
  4. femagtools/dxfsl/fslrenderer.py +8 -1
  5. femagtools/dxfsl/geom.py +19 -8
  6. femagtools/dxfsl/svgparser.py +31 -4
  7. femagtools/femag.py +14 -0
  8. femagtools/fsl.py +74 -28
  9. femagtools/isa7.py +41 -0
  10. femagtools/job.py +2 -2
  11. femagtools/machine/afpm.py +5 -1
  12. femagtools/machine/utils.py +4 -3
  13. femagtools/model.py +7 -0
  14. femagtools/moo/population.py +9 -7
  15. femagtools/nc.py +12 -0
  16. femagtools/plot/__init__.py +1 -1
  17. femagtools/plot/nc.py +22 -5
  18. femagtools/plot/wdg.py +38 -5
  19. femagtools/svgfsl/converter.py +6 -0
  20. femagtools/templates/gen_winding.mako +7 -0
  21. femagtools/templates/magnetIron.mako +30 -46
  22. femagtools/templates/magnetIron2.mako +39 -0
  23. femagtools/templates/magnetIron3.mako +39 -0
  24. femagtools/templates/magnetIron4.mako +39 -0
  25. femagtools/templates/magnetIron5.mako +39 -0
  26. femagtools/templates/magnetIronV.mako +34 -54
  27. femagtools/templates/magnetSector.mako +32 -47
  28. femagtools/templates/prepare_thermal.mako +219 -0
  29. femagtools/templates/statorRotor3.mako +3 -22
  30. femagtools/windings.py +67 -39
  31. {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/METADATA +3 -1
  32. {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/RECORD +38 -37
  33. {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/WHEEL +1 -1
  34. tests/test_fsl.py +1 -1
  35. tests/test_windings.py +13 -2
  36. {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/LICENSE +0 -0
  37. {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/entry_points.txt +0 -0
  38. {femagtools-1.7.8.dist-info → femagtools-1.7.9.dist-info}/top_level.txt +0 -0
femagtools/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  """
4
4
  __title__ = 'femagtools'
5
- __version__ = '1.7.8'
5
+ __version__ = '1.7.9'
6
6
  __author__ = 'Ronald Tanner'
7
7
  __license__ = 'BSD'
8
8
  __copyright__ = 'Copyright 2023-2024 Gamma Technology'
femagtools/dxfsl/area.py CHANGED
@@ -171,6 +171,38 @@ class Area(object):
171
171
  if e1.n1 == e2.n1 and e1.n2 == e2.n2:
172
172
  yield e1
173
173
 
174
+ def reduce_nodes(self, mindist=0.01):
175
+ """reduces number of nodes (lines only)
176
+ https://rdp.readthedocs.io/en/latest
177
+ """
178
+ import rdp
179
+ def reduce_nodes_(lines, mindist):
180
+ nodes = [le.get_nodes()[0] for le in lines]
181
+ r = rdp.rdp(nodes,
182
+ epsilon=mindist)
183
+ if len(r) < len(nodes):
184
+ return [Line(Element(start=n1, end=n2))
185
+ for n1, n2 in zip(r, r[1:])]
186
+ return lines
187
+
188
+ lines = []
189
+ reduced = []
190
+ for e in self.area:
191
+ if isinstance(e, Line):
192
+ lines.append(e)
193
+ else:
194
+ reduced.append(e)
195
+ reduced += reduce_nodes_(lines, mindist)
196
+ lines = []
197
+ if lines:
198
+ reduced += reduce_nodes_(lines, mindist)
199
+
200
+ if len(self.area) > len(reduced):
201
+ logger.info("reduced areas %d -> %d",
202
+ len(self.area), len(reduced))
203
+ return reduced
204
+ return []
205
+
174
206
  def virtual_nodes(self, render=False, parts=64):
175
207
  if len(self.area) < 2:
176
208
  return
@@ -337,15 +369,9 @@ class Area(object):
337
369
  return False
338
370
 
339
371
  def minmax_dist_from_center(self, center):
340
- rmin = 1e20
341
- rmax = 0
342
- for n in self.list_of_nodes():
343
- r = np.linalg.norm(np.array(n)-center)
344
- if r < rmin:
345
- rmin = r
346
- if r > rmax:
347
- rmax = r
348
- return rmin, rmax
372
+ nodes = np.array([n for e in self.area for n in e.get_nodes()])
373
+ return (np.min(np.linalg.norm(nodes-center, axis=1)),
374
+ np.max(np.linalg.norm(nodes-center, axis=1)))
349
375
 
350
376
  def minmax_angle_dist_from_center(self, center, dist):
351
377
  circ = Circle(Element(center=center, radius=dist))
@@ -959,11 +985,14 @@ class Area(object):
959
985
  self.legend())
960
986
 
961
987
  def remove_edges(self, g, ndec):
988
+ r = 0
962
989
  for e in self.area:
963
990
  try:
964
991
  g.remove_edge(e.node1(ndec), e.node2(ndec))
992
+ r+=1
965
993
  except Exception:
966
994
  continue
995
+ return r
967
996
 
968
997
  def is_circle(self):
969
998
  e = self.area[0]
@@ -533,6 +533,7 @@ def convert(dxfile,
533
533
  EESM=EESM)
534
534
 
535
535
  if machine_outer.geom.is_stator() or machine_outer.has_windings():
536
+ machine_outer.geom.reduce_winding_nodes()
536
537
  machine_outer = build_machine_stator(machine_outer,
537
538
  False,
538
539
  mindist,
@@ -718,7 +719,7 @@ def convert(dxfile,
718
719
  p,
719
720
  EESM=EESM,
720
721
  single=True)
721
-
722
+ machine.geom.reduce_winding_nodes()
722
723
  params = create_femag_parameters_stator(machine,
723
724
  part[1])
724
725
  else:
@@ -162,6 +162,8 @@ class FslRenderer(object):
162
162
  geom.split_all_lines_longer_than(split_len)
163
163
  self.content = []
164
164
 
165
+ MAXDST=4.0
166
+ NUMLEVELS=10
165
167
  ndt_list = [(0.00, 1.1),
166
168
  (0.05, 1.5),
167
169
  (0.10, 1.7),
@@ -173,6 +175,9 @@ class FslRenderer(object):
173
175
  (0.70, 4.5),
174
176
  (0.85, 5.5),
175
177
  (1.10, 5.5)]
178
+ ndt_list = [(1.1*nl/NUMLEVELS, nl/NUMLEVELS*(MAXDST-1.1)+1.1)
179
+ for nl in range(NUMLEVELS+1)]
180
+
176
181
  dist = geom.max_radius - geom.min_radius
177
182
  el_sorted = self.sorted_elements(geom, inner)
178
183
 
@@ -182,7 +187,7 @@ class FslRenderer(object):
182
187
  if ndt_list[n][0] < d_percent:
183
188
  self.agndst = ndt_list[n][1] * self.agndst
184
189
  self.content.append('\nndt({}*agndst)\n'.
185
- format(ndt_list[n][1]))
190
+ format(round(ndt_list[n][1], 1)))
186
191
  while ndt_list[n][0] < d_percent:
187
192
  n += 1
188
193
  e.render(self)
@@ -233,6 +238,8 @@ class FslRenderer(object):
233
238
  'r, phi = c2pr(x0, y0)',
234
239
  'x1, y1 = pr2c(r1, phi)',
235
240
  'x2, y2 = pr2c(r1, {}*math.pi/parts)'.format(slice),
241
+ f'-- end max corner {geom.end_corners[-1]}',
242
+ f'-- center {geom.center}',
236
243
  f'r = {geom.dist_end_max_corner()}',
237
244
  'x3, y3 = pr2c(r, {}*math.pi/parts)'.format(slice),
238
245
  'nc_line(x0, y0, x1, y1, 0)',
femagtools/dxfsl/geom.py CHANGED
@@ -91,11 +91,12 @@ def create_geometry(new_elements, split=False):
91
91
 
92
92
 
93
93
  def intersect_and_split(inp_elements, rtol, atol):
94
- logger.info("Load input elements ... ")
94
+ logger.info("Load input elements ... %s", len(inp_elements))
95
95
  out_elements = []
96
96
  for e in inp_elements:
97
97
  out_size = len(out_elements)
98
98
  intersect_and_split_element(e, out_elements, 0, out_size, rtol, atol)
99
+ logger.debug(" done", e)
99
100
  return out_elements
100
101
 
101
102
 
@@ -650,9 +651,9 @@ class Geometry(object):
650
651
  return True
651
652
  return False
652
653
 
653
- def get_edge(self, eg):
654
+ def get_edge(self, obj):
654
655
  return [[e[0], e[1], e[2]['object']] for e in self.g.edges(data=True)
655
- if e[2]['object'] is eg]
656
+ if e[2]['object'] is obj]
656
657
 
657
658
  def get_edge_element(self, n1, n2):
658
659
  e_dict = self.g.get_edge_data(n1, n2)
@@ -679,9 +680,9 @@ class Geometry(object):
679
680
  assert(len(e) == 1)
680
681
  self._remove_edge(e[0][0], e[0][1])
681
682
 
682
- def remove_edges(self, edges):
683
- for e in edges:
684
- self.remove_edge(e)
683
+ def remove_edges(self, objs):
684
+ for o in objs:
685
+ self.remove_edge(o)
685
686
 
686
687
  def _remove_node(self, n):
687
688
  for nbr in self.g.neighbors(n):
@@ -867,8 +868,8 @@ class Geometry(object):
867
868
  logger.debug("begin of dist_end_max_corner")
868
869
  logger.debug("end corners: %s", self.end_corners)
869
870
 
870
- if self.is_mirrored():
871
- return self.dist_start_max_corner()
871
+ #if self.is_mirrored():
872
+ # return self.dist_start_max_corner()
872
873
  d = distance(self.center, self.end_corners[-1])
873
874
  logger.debug("end of dist_end_max_corner: %s", d)
874
875
  return d
@@ -1843,6 +1844,16 @@ class Geometry(object):
1843
1844
  return [h for (k, h) in legend.items()]
1844
1845
  return []
1845
1846
 
1847
+ def reduce_winding_nodes(self, mindist=0.01):
1848
+ for area in self.list_of_areas():
1849
+ if area.is_winding():
1850
+ reduced_shapes = area.reduce_nodes(mindist)
1851
+ if reduced_shapes:
1852
+ area.remove_edges(self.g, ndec)
1853
+ area.area = reduced_shapes
1854
+ for r in reduced_shapes:
1855
+ self.add_element(r, rtol=self.rtol, atol=self.atol)
1856
+
1846
1857
  def render_areagroups(self, renderer):
1847
1858
  if not self.areagroup_list:
1848
1859
  return
@@ -37,10 +37,17 @@ def get_angles(sweep, center, p1, p2):
37
37
  def get_shapes(path):
38
38
  """return list of node elements (A, L)"""
39
39
  state = ''
40
+ prevstate = ''
40
41
  p = []
41
- for s in [s for s in re.split('([AML])|,|\\s+',path) if s]:
42
+ for s in [s for s in re.split('([AMLHV])|,|\\s+', path) if s]:
42
43
  if state == '':
43
- state = s[0]
44
+ s = s.upper()
45
+ if s in ('A','M','L','H','V'):
46
+ state = s
47
+ prevstate = s
48
+ else: # wild guess
49
+ p.append(float(s))
50
+ state = prevstate
44
51
  elif state == 'M':
45
52
  p.append(float(s))
46
53
  if len(p) == 2:
@@ -52,7 +59,7 @@ def get_shapes(path):
52
59
  if len(p) == 2:
53
60
  p2 = np.array(p)
54
61
  logger.debug("Line %s -> %s",
55
- p1, p2)
62
+ p1, p2)
56
63
  yield Line(Element(start=p1, end=p2))
57
64
  p1 = p2.copy()
58
65
  p = []
@@ -66,7 +73,7 @@ def get_shapes(path):
66
73
  center = get_center(r, p1, p2, sweep)
67
74
  start, end = get_angles(sweep, center, p1, p2)
68
75
  logger.debug("Arc center %s r %f %f -> %f",
69
- center, r, start, end)
76
+ center, r, start, end)
70
77
  yield Arc(Element(center=center,
71
78
  radius=r,
72
79
  start_angle=start*180/np.pi,
@@ -74,14 +81,34 @@ def get_shapes(path):
74
81
  p1 = p2.copy()
75
82
  p = []
76
83
  state = ''
84
+ elif state == 'H':
85
+ logger.debug("h %s", s)
86
+ p2 = np.array((float(s), 0))
87
+ yield Line(Element(start=p1, end=p2))
88
+ p1 = p2.copy()
89
+ p = []
90
+ state = ''
91
+ elif state == 'V':
92
+ logger.debug("V %s", s)
93
+ p2 = np.array((0, float(s)))
94
+ yield Line(Element(start=p1, end=p2))
95
+ p1 = p2.copy()
96
+ p = []
97
+ state = ''
77
98
  else:
78
99
  raise ValueError(f"unsupported path {state}")
79
100
 
80
101
 
81
102
  def svgshapes(svgfile):
82
103
  svg = ET.parse(svgfile)
104
+ bcolor = re.compile('fill:([^;]+)')
105
+ sr = 0
83
106
  for p in svg.findall(".//{http://www.w3.org/2000/svg}path"):
107
+ m = bcolor.search(p.get('style'))
108
+ if m:
109
+ logger.info("subregion %d: %s", sr, m.groups()[0])
84
110
  yield from get_shapes(p.get('d'))
111
+ sr += 1
85
112
  for p in svg.findall(".//{http://www.w3.org/2000/svg}line"):
86
113
  yield Line(Element(start=[float(p.get('x1')), float(p.get('y1'))],
87
114
  end=[float(p.get('x2')), float(p.get('y2'))]))
femagtools/femag.py CHANGED
@@ -401,6 +401,10 @@ class BaseFemag(object):
401
401
  ttemp = list(zip(*temp))
402
402
  return {'t': ttemp[0], 'temperature': ttemp[1]}
403
403
 
404
+ if simulation['calculationMode'] == 'hsn':
405
+ model = self.read_nc()
406
+ return model.get_minmax_temp()
407
+
404
408
  if not bch:
405
409
  bch = self.read_bch(self.modelname)
406
410
  if simulation['calculationMode'] == 'pm_sym_fast' or \
@@ -468,6 +472,11 @@ class BaseFemag(object):
468
472
  bch.magnet_loss_th = m.th_loss
469
473
  except:
470
474
  pass
475
+ try:
476
+ if hasattr(self, 'dy2'):
477
+ setattr(bch, 'dy2', self.dy2)
478
+ except:
479
+ pass
471
480
  return bch
472
481
 
473
482
 
@@ -599,6 +608,11 @@ class Femag(BaseFemag):
599
608
  stateofproblem = 'mag_static'
600
609
 
601
610
  self.run(fslfile, options, fsl_args, stateofproblem=stateofproblem)
611
+
612
+ try:
613
+ setattr(self, "dy2", machine['stator']['dy2'])
614
+ except:
615
+ pass
602
616
  if simulation:
603
617
  return self.readResult(simulation)
604
618
 
femagtools/fsl.py CHANGED
@@ -356,25 +356,18 @@ class Builder:
356
356
  if 'thcond' in model.stator:
357
357
  fslcmds += [
358
358
  '-- thermal properties in airgap',
359
- 'if m.zeroangl ~= nil then',
360
- ' ag_cond = 0.063',
361
- ' thcap = 1007',
362
- ' beta = math.pi*m.npols_gen/m.num_poles + m.zeroangl/180*math.pi',
363
- ' xai, yai = pr2c((da1+da2)/4, beta)',
364
- ' def_mat_therm(xai,yai,"cyan",1.19,ag_cond,thcap,1)',
365
- ' xai, yai = pr2c((da1+da2)/4-ag/4, beta)',
366
- ' def_mat_therm(xai,yai,"cyan",1.19,ag_cond,thcap,1)',
367
- ' xai, yai = pr2c((da1+da2)/4+ag/4, beta)',
368
- ' def_mat_therm(xai,yai,"cyan",1.19,ag_cond,thcap,1)',
369
- '',
370
- ' state_of_problem("therm_static") -- thermic boundary conditions',
371
- ' x1,y1 = pd2c(dy2/2,m.zeroangl)',
372
- ' x2,y2 = pd2c(dy1/2,m.zeroangl)',
373
- ' beta = 360*m.npols_gen/m.num_poles',
374
- ' x3,y3 = pd2c(dy1/2,beta+m.zeroangl)',
375
- ' x4,y4 = pd2c(dy2/2,beta+m.zeroangl)',
376
- ' def_bcond_tp(x1,y1,x2,y2,x3,y3,x4,y4, 4)',
359
+ 'if m.zeroangl == nil then',
360
+ ' m.zeroangl = 0.0',
377
361
  'end',
362
+ 'beta = math.pi*m.npols_gen/m.num_poles + m.zeroangl/180*math.pi',
363
+ '',
364
+ 'state_of_problem("therm_static") -- thermic boundary conditions',
365
+ 'x1,y1 = pd2c(dy2/2,m.zeroangl)',
366
+ 'x2,y2 = pd2c(dy1/2,m.zeroangl)',
367
+ 'beta = 360*m.npols_gen/m.num_poles',
368
+ 'x3,y3 = pd2c(dy1/2,beta+m.zeroangl)',
369
+ 'x4,y4 = pd2c(dy2/2,beta+m.zeroangl)',
370
+ 'def_bcond_tp(x1,y1,x2,y2,x3,y3,x4,y4, 4)',
378
371
  'state_of_problem("mag_static")']
379
372
  return fslcmds
380
373
  return []
@@ -440,14 +433,14 @@ class Builder:
440
433
  return []
441
434
 
442
435
  def create_gen_winding(self, model):
443
- try:
444
- if model.winding['wire']['name'] == 'hairpin_winding':
445
- model.winding['wire'].update(
446
- {"num_layers": model.winding["num_layers"]})
447
- genwdg = self.__render(model.winding,
448
- 'gen_' + model.winding['wire'].get('name'))
449
- except KeyError: # not hairpin_winding
436
+ try:
437
+ model.winding['wire'].update(
438
+ {"num_layers": model.winding["num_layers"]})
439
+ genwdg = self.__render(model.winding,
440
+ 'gen_' + model.winding['wire'].get('name'))
441
+ except:
450
442
  genwdg = self.__render(model, 'gen_winding')
443
+
451
444
  k = list({'leak_dist_wind',
452
445
  'leak_evol_wind',
453
446
  'leak_tooth_wind'}.intersection(model.winding))
@@ -510,6 +503,9 @@ class Builder:
510
503
  setattr(model, 'stator', {})
511
504
  model.stator['num_slots'] = conv.get('tot_num_slot')
512
505
  model.stator['slot_area'] = conv.get('slot_area')
506
+ model.stator['dy1'] = conv.get('dy1')*1e-3
507
+ model.stator['dy2'] = conv.get('dy2')*1e-3
508
+
513
509
  if model.get('num_agnodes', 0) == 0:
514
510
  model.set_value('agndst', conv['agndst']*1e-3)
515
511
  logger.info("num poles %d num slots %d outer diameter %.4f m agndst %.4f mm",
@@ -526,19 +522,39 @@ class Builder:
526
522
 
527
523
  if 'fsl_stator' in conv:
528
524
  self.fsl_stator = True
529
- model.stator['dxf'] = dict(fsl=conv['fsl_stator'])
525
+ th_props = [' ']
526
+ if model.stator.get('thcond', 0):
527
+ th_props = [f'stator_density = {1e3*model.stator["density"]}',
528
+ f'stator_thcond = {model.stator["thcond"]}',
529
+ f'stator_thcap = {model.stator["thcap"]}',
530
+ ]
531
+ model.stator['dxf'] = dict(fsl=conv['fsl_stator'] + th_props)
530
532
  if not (hasattr(model, 'magnet') or hasattr(model, 'rotor')):
531
533
  if params['EESM']:
532
534
  setattr(model, 'rotor', {})
533
535
  else:
534
536
  setattr(model, 'magnet', {})
537
+
535
538
  if 'fsl_rotor' in conv:
536
539
  self.fsl_rotor = True
540
+ th_props = ['']
537
541
  if hasattr(model, 'magnet'):
538
- model.magnet['dxf'] = dict(fsl=conv['fsl_rotor'])
542
+ if model['magnet'].get('thcond', 0):
543
+ logger.info(model['magnet'])
544
+ th_props = [f'rotor_density = {1e3*model["magnet"]["density"]}',
545
+ f'rotor_thcond = {model["magnet"]["thcond"]}',
546
+ f'rotor_thcap = {model["magnet"]["thcap"]}'
547
+ ]
548
+ model.magnet['dxf'] = dict(fsl=conv['fsl_rotor'] + th_props)
539
549
  if hasattr(model, 'rotor'):
540
550
  model.rotor['dxf'] = dict(fsl=conv['fsl_rotor'])
541
551
 
552
+ def create_thermal_properties(self, model):
553
+ if model.stator.get('thcond') and model.stator.get('thcap') and \
554
+ model.stator.get('density'):
555
+ return self.__render(model, 'prepare_thermal')
556
+ return ['']
557
+
542
558
  def create_model(self, model, magnets=[], condMat=[], ignore_material=False):
543
559
  magnetMat = {}
544
560
  material = ''
@@ -594,6 +610,35 @@ class Builder:
594
610
  self.create_magnet_model(model))
595
611
  if magnetMat:
596
612
  rotor += self.create_magnet(model, magnetMat)
613
+
614
+ if model['magnet'].get('thcond_magnet', 0):
615
+ th_props = [f'magn_density = {1e3*model["magnet"]["spmaweight_magnet"]}',
616
+ f'magn_thcond = {model["magnet"]["thcond_magnet"]}',
617
+ f'magn_thcap = {model["magnet"]["thcap_magnet"]}'
618
+ ]
619
+ rotor += th_props
620
+ if model.is_dxffile() or 'dxf' in model['magnet']:
621
+ rotor += ['if x0_shaft == 0.0 then',
622
+ '-- add air layer (inside) for heat transfer',
623
+ ' h = dy2/2/3',
624
+ ' if h > 5 then',
625
+ ' h = 3.8',
626
+ ' end ',
627
+ ' if m.zeroangl == nil then ',
628
+ ' m.zeroangl = 0.0',
629
+ ' end',
630
+ ' beta = 360*m.npols_gen/m.num_poles',
631
+ ' x0, y0 = pd2c(dy2/2, m.zeroangl)',
632
+ ' x1, y1 = pd2c(dy2/2-h, m.zeroangl)',
633
+ ' x2, y2 = pd2c(dy2/2-h, beta+m.zeroangl)',
634
+ ' x3, y3 = pd2c(dy2/2, beta+m.zeroangl)',
635
+ ' nc_line(x0, y0, x1, y1, 0)',
636
+ ' nc_circle(x1, y1, x2, y2, 0)',
637
+ ' nc_line(x2, y2, x3, y3, 0)',
638
+ ' x0, y0 = pd2c(dy2/2-h/2, beta/2+m.zeroangl)',
639
+ ' create_mesh_se(x0, y0)',
640
+ 'end'
641
+ ]
597
642
  else:
598
643
  rotor = self.create_rotor_model(
599
644
  model, condMat, ignore_material)
@@ -635,7 +680,8 @@ class Builder:
635
680
  rotor +
636
681
  self.mesh_airgap(model) +
637
682
  self.create_connect_models(model) +
638
- self.create_rotor_winding(model))
683
+ self.create_rotor_winding(model)) + \
684
+ self.create_thermal_properties(model)
639
685
 
640
686
  return (self.open_model(model) +
641
687
  self.create_fe_losses(model) +
femagtools/isa7.py CHANGED
@@ -544,6 +544,10 @@ class Isa7(object):
544
544
  16: [0.8274509803921568, 0.8274509803921568, 0.8274509803921568]} # LIGHGREY
545
545
 
546
546
  def __init__(self, reader):
547
+ try:
548
+ self.state_of_problem = reader.state_of_problem
549
+ except:
550
+ pass
547
551
  self.points = [Point(x, y)
548
552
  for x, y in zip(reader.POINT_ISA_POINT_REC_PT_CO_X,
549
553
  reader.POINT_ISA_POINT_REC_PT_CO_Y)]
@@ -1139,6 +1143,43 @@ class Isa7(object):
1139
1143
  sreg[sr.name] = [0,0,0]
1140
1144
  return sreg
1141
1145
 
1146
+ def get_minmax_temp(self):
1147
+ def node_subregion(subregion_name):
1148
+ node_temperature = []
1149
+ for i in self.subregions:
1150
+ if i.name.lower() == subregion_name:
1151
+ for j in i.elements():
1152
+ for k in j.vertices:
1153
+ node_temperature.append(k.vpot[-1])
1154
+ ndtemp = np.unique(node_temperature)
1155
+ return [np.amax(ndtemp), np.amin(ndtemp), np.mean(ndtemp)]
1156
+
1157
+ zero_temp = [0.0, 0.0, 0.0]
1158
+ component_temperature = dict(styoke=zero_temp, stteeth=zero_temp,
1159
+ magnet=zero_temp, winding=zero_temp)
1160
+ for i in self.subregions:
1161
+ if i.name:
1162
+ sreg_name = i.name.lower()
1163
+ if sreg_name in ('stza', 'stth', 'stteeth'):
1164
+ component_temperature['stteeth'] = node_subregion(sreg_name)
1165
+ elif sreg_name in ('styk', 'styoke', 'stjo'):
1166
+ component_temperature['styoke'] = node_subregion(sreg_name)
1167
+ elif sreg_name == 'iron':
1168
+ component_temperature['iron'] = node_subregion(sreg_name)
1169
+ elif sreg_name == 'pmag':
1170
+ component_temperature['magnet'] = node_subregion(sreg_name)
1171
+ else:
1172
+ pass
1173
+
1174
+ wdg_temps = []
1175
+ for j in self.wdg_elements():
1176
+ for k in j.vertices:
1177
+ wdg_temps.append(k.vpot[-1])
1178
+ wdg_temp = np.unique(wdg_temps)
1179
+ component_temperature['winding'] = [np.amax(wdg_temp),
1180
+ np.amin(wdg_temp),
1181
+ np.mean(wdg_temp)]
1182
+ return component_temperature
1142
1183
 
1143
1184
  def flux_dens(self, x, y, icur, ibeta):
1144
1185
  el = self.get_element(x, y)
femagtools/job.py CHANGED
@@ -112,7 +112,7 @@ class Task(object):
112
112
  if bchfile_list:
113
113
  result = femagtools.bch.Reader()
114
114
  with open(bchfile_list[-1]) as f:
115
- logger.info("Reading %s",
115
+ logger.debug("Reading %s",
116
116
  bchfile_list[-1])
117
117
  result.read(f)
118
118
  if bagdat.exists():
@@ -127,7 +127,7 @@ class Task(object):
127
127
  asm_list = sorted(basedir.glob(
128
128
  '*_[0-9][0-9][0-9].ASM'))
129
129
  if asm_list:
130
- logger.info("Reading %s",
130
+ logger.debug("Reading %s",
131
131
  asm_list[-1])
132
132
  result = femagtools.asm.read(asm_list[-1])
133
133
  if bagdat.exists():
@@ -645,6 +645,9 @@ class AFPM:
645
645
  parameters={
646
646
  'phi_voltage_winding': current_angles})
647
647
  logger.info("Current angles: %s", current_angles)
648
+ elif (simulation['calculationMode'] == 'cogg_calc' and
649
+ 'poc' not in simulation):
650
+ simulation['poc'] = poc.Poc(machine['pole_width'])
648
651
 
649
652
  lresults = self.parstudy(
650
653
  parvardef,
@@ -652,5 +655,6 @@ class AFPM:
652
655
  simulation, engine) # Note: imcomplete machine prevents rebuild
653
656
 
654
657
  results = process(lfe, pole_width, machine, lresults['f'])
655
- results.update(_psidq_ldq(results, nlresults))
658
+ if nlresults:
659
+ results.update(_psidq_ldq(results, nlresults))
656
660
  return results
@@ -411,6 +411,7 @@ def dqparident(workdir, engine, temp, machine,
411
411
  elif ('wire_width' in machine[wdgk]) and ('wire_height' in machine[wdgk]):
412
412
  aw = machine[wdgk]['wire_width']*machine[wdgk]['wire_height']
413
413
  else: # wire diameter from slot area
414
+ da1 = machine['bore_diam']
414
415
  aw = 0.75 * fcu * np.pi*da1*hs/Q1/wdg.l/N
415
416
  r1 = wdg_resistance(wdg, N, g, aw, da1, hs, lfe)
416
417
  except (NameError, KeyError):
@@ -489,6 +490,8 @@ def dqparident(workdir, engine, temp, machine,
489
490
  machine['poles'] = 2*results['f'][0]['machine']['p']
490
491
  da1 = 2*results['f'][0]['machine']['fc_radius']
491
492
  wdg = create_wdg(machine)
493
+ if 'bore_diam' in machine:
494
+ da1 = machine['bore_diam']
492
495
  ls1 = 0
493
496
  try:
494
497
  leakages = [float(x)
@@ -569,14 +572,12 @@ def dqparident(workdir, engine, temp, machine,
569
572
  if r1:
570
573
  dqpars['r1'] = r1
571
574
  else:
572
- from .. import nc
573
- model = nc.read(str(pathlib.Path(workdir) / machine['name']))
575
+ model = parvar.femag.read_nc()
574
576
  try:
575
577
  nlayers = wdg.l
576
578
  except UnboundLocalError:
577
579
  wdg = create_wdg(machine)
578
580
  nlayers = wdg.l
579
- da1 = machine['outer_diam']
580
581
  Q1 = wdg.Q
581
582
  istat = 0 if model.get_areas()[0]['slots'] else 1
582
583
  asl = model.get_areas()[istat]['slots']
femagtools/model.py CHANGED
@@ -386,6 +386,13 @@ class MachineModel(Model):
386
386
  if mcv:
387
387
  logger.debug('shaft mcv %s', mcv)
388
388
  rotor['mcvkey_shaft'] = magcurves.fix_name(mcv)
389
+ mshaft = magcurves.find_by_name(mcv)
390
+ thkeys_shaft = ['thcond', 'thcap', 'rho']
391
+ if mshaft and set(thkeys_shaft).issubset(mshaft.keys()):
392
+ for k in thkeys_shaft:
393
+ rotor[k+'_shaft'] = mshaft[k]
394
+ rotor['spmaweight_shaft'] = rotor['rho_shaft']
395
+
389
396
  self.stator['mcvkey_shaft_name'] = mcv
390
397
  names.append((mcv, 1.0))
391
398
  else:
@@ -198,21 +198,23 @@ class Population:
198
198
  self.update_pareto_information()
199
199
  retval = [[] for s in range(max(self.pareto_rank)+1)]
200
200
  for i, j in enumerate(self.individuals):
201
- retval[self.pareto_rank[i]].append(i)
201
+ retval[self.pareto_rank[i]].append(j)
202
202
  return retval
203
203
 
204
204
  def compute_ideal(self):
205
- return [min(x)
205
+ return [np.min(np.array(x)[np.isfinite(x)])
206
206
  for x in zip(*[i.cur_f
207
- for i in self.individuals if i.rank == 0])]
207
+ for i in self.individuals
208
+ if i.rank == 0])]
208
209
 
209
210
  def compute_nadir(self):
210
- return [max(x)
211
+ return [np.max(np.array(x)[np.isfinite(x)])
211
212
  for x in zip(*[i.cur_f
212
- for i in self.individuals if i.rank == 0])]
213
+ for i in self.individuals
214
+ if i.rank == 0])]
213
215
 
214
216
  def compute_worst(self):
215
- return [max(x)
217
+ return [np.max(np.array(x)[np.isfinite(x)])
216
218
  for x in zip(*[i.cur_f
217
219
  for i in self.individuals])]
218
220
 
@@ -252,7 +254,7 @@ class Population:
252
254
  raise ValueError(
253
255
  'Invalid components of the objective function selected for plot')
254
256
 
255
- p_dim = self.problem.f_dimension
257
+ p_dim = self.problem.f_dim
256
258
 
257
259
  if p_dim == 1:
258
260
  raise ValueError(