femagtools 1.7.5__py3-none-any.whl → 1.7.7__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 +11 -1
  3. femagtools/dxfsl/area.py +108 -7
  4. femagtools/dxfsl/conv.py +15 -0
  5. femagtools/dxfsl/converter.py +44 -20
  6. femagtools/dxfsl/fslrenderer.py +93 -42
  7. femagtools/dxfsl/functions.py +8 -0
  8. femagtools/dxfsl/geom.py +126 -18
  9. femagtools/dxfsl/machine.py +30 -9
  10. femagtools/femag.py +3 -3
  11. femagtools/fsl.py +73 -48
  12. femagtools/isa7.py +2 -2
  13. femagtools/machine/effloss.py +2 -0
  14. femagtools/machine/pm.py +198 -42
  15. femagtools/machine/sm.py +294 -253
  16. femagtools/machine/utils.py +5 -14
  17. femagtools/model.py +32 -2
  18. femagtools/moo/algorithm.py +6 -0
  19. femagtools/nc.py +2 -0
  20. femagtools/opt.py +2 -1
  21. femagtools/plot/bch.py +19 -5
  22. femagtools/plot/char.py +4 -4
  23. femagtools/plot/nc.py +21 -4
  24. femagtools/plot/wdg.py +38 -26
  25. femagtools/templates/gen_hairpin_winding.mako +209 -0
  26. femagtools/templates/gen_winding.mako +8 -9
  27. femagtools/templates/magnetIron.mako +32 -6
  28. femagtools/templates/mesh-airgap.mako +9 -0
  29. femagtools/templates/rotor_winding.mako +10 -6
  30. femagtools/templates/statorRotor3.mako +8 -5
  31. femagtools/windings.py +31 -18
  32. {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/METADATA +1 -1
  33. {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/RECORD +38 -37
  34. {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/WHEEL +1 -1
  35. tests/test_windings.py +1 -1
  36. {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/LICENSE +0 -0
  37. {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/entry_points.txt +0 -0
  38. {femagtools-1.7.5.dist-info → femagtools-1.7.7.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
  def K(d):
16
16
  """space phasor transformation matrix
17
- (Inverse Park Transformation) T-1 * dq
17
+ (Inverse Park Transformation) T-1 * dq --> abc
18
18
  arguments:
19
19
  d: rotation angle
20
20
 
@@ -28,7 +28,7 @@ def K(d):
28
28
 
29
29
  def T(d):
30
30
  """space phasor transformation matrix
31
- (Park Transformation) T * abc
31
+ (Park Transformation) T * abc --> dq
32
32
  arguments:
33
33
  d: rotation angle
34
34
 
@@ -390,21 +390,12 @@ def dqparident(workdir, engine, temp, machine,
390
390
  fcu = 0.42
391
391
 
392
392
  try: # calc basic dimensions if not fsl or dxf model
393
+ from ..model import MachineModel
393
394
  wdg = create_wdg(machine)
394
395
  Q1 = wdg.Q
395
- slotmodel = [k for k in machine['stator'] if isinstance(
396
- machine['stator'][k], dict)][-1]
397
- if slotmodel == 'stator1':
398
- hs = machine['stator']['stator1']['slot_rf1'] - \
399
- machine['stator']['stator1']['tip_rh1']
400
- else:
401
- da1 = machine['bore_diam']
402
- dy1 = machine['outer_diam']
403
- hs = machine['stator'][slotmodel].get(
404
- 'slot_height', 0.6*(dy1-da1)/2)
405
-
396
+ model = MachineModel(machine)
406
397
  Jmax = 30e6 # max current density in A/m2
407
- Acu = fcu*np.pi*(da1+hs)*hs/Q1/2 # approx. copper area of one slot
398
+ Acu = fcu*model.slot_area() # approx. copper area of one slot
408
399
  i1_max = round(g*Acu/wdg.l/N*Jmax/10)*10
409
400
  except KeyError:
410
401
  if kwargs.get('i1_max', 0) == 0:
femagtools/model.py CHANGED
@@ -15,6 +15,12 @@ MODELNAME_CHARS = string.printable[:63] + "-_äöüéè"
15
15
  # maximum name length
16
16
  MAX_MODEL_NAME_LEN = 255
17
17
 
18
+ default_th_properties = {
19
+ "spmaweight": 8.96,
20
+ "tempcoef": 3.9e-3,
21
+ "thcond": 30,
22
+ "thcap": 480
23
+ }
18
24
 
19
25
  def movesteps(nodes):
20
26
  """returns list of move steps
@@ -191,6 +197,28 @@ class MachineModel(Model):
191
197
  except (KeyError, AttributeError):
192
198
  pass
193
199
 
200
+ def slot_height(self):
201
+ if 'statorRotor3' in self.stator:
202
+ return self.stator['statorRotor3']['slot_height']
203
+ if 'stator1' in self.stator:
204
+ return self.stator['stator1']['slot_rf1'] - self.stator['stator1']['tip_rh1']
205
+ if 'stator4' in self.stator:
206
+ return self.stator['stator4']['slot_height']
207
+ da1 = self.bore_diam
208
+ if self.external_rotor:
209
+ yh = da1-self.inner_diam
210
+ else:
211
+ yh = da1+self.outer_diam
212
+ return 0.6*yh/2
213
+
214
+ def slot_area(self):
215
+ if 'slot_area' in self.stator:
216
+ return self.stator['slot_area']
217
+ da1 = self.bore_diam
218
+ Q1 = self.stator['num_slots']
219
+ hs = self.slot_height()
220
+ return np.pi*hs*(da1+hs)/Q1/2
221
+
194
222
  def set_num_slots_gen(self):
195
223
  if 'num_slots_gen' not in self.stator:
196
224
  try:
@@ -392,6 +420,8 @@ class MachineModel(Model):
392
420
  for k in self.rotor:
393
421
  # anything that is a dict must represent the type
394
422
  if isinstance(self.rotor[k], dict):
423
+ if k == 'rot_hsm':
424
+ return 'EESM'
395
425
  return k
396
426
  raise AttributeError("Missing rotor model in {}".format(self.magnet))
397
427
 
@@ -429,11 +459,11 @@ class MachineModel(Model):
429
459
  def props(self):
430
460
  """returns dict of this model"""
431
461
  keys = ('name', 'poles', 'outer_diam', 'airgap',
432
- 'bore_diam', 'external_rotor', 'agndst')
462
+ 'bore_diam', 'inner_diam', 'external_rotor', 'agndst')
433
463
  model = {k: getattr(self, k) for k in keys if hasattr(self, k)}
434
464
  if hasattr(self, 'stator'):
435
465
  model['stator'] = {k: self.stator[k]
436
- for k in ('num_slots', 'num_slots_gen')
466
+ for k in ('num_slots', 'num_slots_gen', 'slot_area')
437
467
  if k in self.stator}
438
468
  return model
439
469
 
@@ -71,6 +71,9 @@ class Nsga2:
71
71
  rnd*alpha))**(1.0/(self.eta_c+1.0))
72
72
 
73
73
  c1 = 0.5*((y1+y2)-betaq*(y2-y1))
74
+ if isinstance(c1, complex):
75
+ logger.warning(f"c1 {c1} is complex")
76
+ c1 = abs(c1)
74
77
 
75
78
  beta = 1.0 + (2.0*(yu-y2)/(y2-y1))
76
79
  alpha = 2.0 - beta**(-(self.eta_c+1.0))
@@ -81,6 +84,9 @@ class Nsga2:
81
84
  rnd*alpha))**(1.0/(self.eta_c+1.0))
82
85
 
83
86
  c2 = 0.5*((y1+y2)+betaq*(y2-y1))
87
+ if isinstance(c2, complex):
88
+ logger.warning(f"c2 {c2} is complex")
89
+ c2 = abs(c2)
84
90
 
85
91
  if c1<yl : c1=yl
86
92
  if c2<yl : c2=yl
femagtools/nc.py CHANGED
@@ -191,6 +191,8 @@ class Reader(object):
191
191
  self.speed = float(grp.variables['speed'].getValue().data)
192
192
  self.FC_RADIUS = float(grp.variables['fc_radius'].getValue().data)
193
193
  self.pole_pairs = int(grp.variables['pole_pairs'].getValue().data)
194
+ self.layers = int(grp.variables['num_layers'].getValue().data)
195
+ self.coil_span = int(grp.variables['coil_span'].getValue().data)
194
196
  self.delta_node_angle = float( # rad
195
197
  grp.variables['delta_node_angle'].getValue().data)
196
198
  self.poles_sim = int(grp.variables['poles_sim'].getValue().data)
femagtools/opt.py CHANGED
@@ -77,7 +77,8 @@ class Optimizer(object):
77
77
  set_magnet_properties(self.model, self.fea, self.femag.magnets)
78
78
  task.add_file('femag.fsl',
79
79
  self.builder.create(self.model, self.fea,
80
- self.femag.magnets))
80
+ self.femag.magnets,
81
+ self.femag.condMat))
81
82
  if 'poc' in self.fea:
82
83
  task.add_file(self.fea['pocfilename'],
83
84
  self.fea['poc'].content())
femagtools/plot/bch.py CHANGED
@@ -508,19 +508,33 @@ def transientsc(bch, title=''):
508
508
  row = 1
509
509
  plt.subplot(rows, cols, row)
510
510
  ax = plt.gca()
511
- ax.set_title('Currents / A')
512
511
  ax.grid(True)
513
- for i in ('ia', 'ib', 'ic'):
514
- ax.plot(bch.scData['time'], bch.scData[i], label=i)
512
+ istat = np.array([bch.scData[i]
513
+ for i in ('ia', 'ib', 'ic')])
514
+ if np.max(istat) > 4000:
515
+ istat *= 1e-3
516
+ ax.set_title('Currents / kA')
517
+ else:
518
+ ax.set_title('Currents / A')
519
+
520
+ for i, iph in zip(('ia', 'ib', 'ic'), istat):
521
+ ax.plot(bch.scData['time'], iph, label=i)
515
522
  ax.set_xlabel('Time / s')
516
523
  ax.legend()
517
524
 
518
525
  row = 2
519
526
  plt.subplot(rows, cols, row)
520
527
  ax = plt.gca()
521
- ax.set_title('Torque / Nm')
528
+ scale = 1
529
+ torque = np.array(bch.scData['torque'])
530
+ if np.max(torque) > 4000:
531
+ torque *= 1e-3
532
+ ax.set_title('Torque / kNm')
533
+ else:
534
+ ax.set_title('Torque / Nm')
535
+
522
536
  ax.grid(True)
523
- ax.plot(bch.scData['time'], bch.scData['torque'])
537
+ ax.plot(bch.scData['time'], torque)
524
538
  ax.set_xlabel('Time / s')
525
539
 
526
540
  fig.tight_layout(h_pad=2)
femagtools/plot/char.py CHANGED
@@ -326,15 +326,15 @@ def _plot_contour(speed, torque, z, ax, title='', levels=[],
326
326
  contf = ax.tricontourf(x, y, z,
327
327
  levels=levels, cmap=cmap)
328
328
 
329
+ #ax.plot(x, y, "k.", ms=3)
330
+ if clabel:
331
+ ax.clabel(cont, inline=True, colors='k', fontsize=8, inline_spacing=0)
332
+
329
333
  clippath = Path(_get_nT_boundary(x, y))
330
334
  patch = PathPatch(clippath, facecolor='none')
331
335
  ax.add_patch(patch)
332
336
  for c in cont.collections:
333
337
  c.set_clip_path(patch)
334
- #ax.plot(x, y, "k.", ms=3)
335
- if clabel:
336
- ax.clabel(cont, inline=True, colors='k', fontsize=8, inline_spacing=0)
337
-
338
338
  for c in contf.collections:
339
339
  c.set_clip_path(patch)
340
340
 
femagtools/plot/nc.py CHANGED
@@ -30,10 +30,27 @@ def spel(isa, superelements=[], with_axis=False, ax=0):
30
30
  spels = isa.superelements
31
31
  for se in spels:
32
32
  ax.add_patch(Polygon([n.xy
33
- for nc in se.nodechains
34
- for n in nc.nodes],
35
- color=isa.color[se.color], lw=0))
36
-
33
+ for nc in se.nodechains
34
+ for n in nc.nodes],
35
+ color=isa.color[se.color], lw=0))
36
+ try:
37
+ # draw wire direction
38
+ if se.subregion:
39
+ if se.subregion.curdir != 0:
40
+ wkey = se.subregion.winding.key
41
+ if se.subregion.curdir < 0:
42
+ label = str(se.subregion.curdir*wkey)
43
+ else:
44
+ label = '+'+str(se.subregion.curdir*wkey)
45
+
46
+ xy = np.array([n.xy
47
+ for nc in se.nodechains
48
+ for n in nc.nodes])
49
+ cx, cy = np.mean(np.unique(xy[:, 0])), np.mean(np.unique(xy[:, -1]))
50
+ ax.text(cx, cy, label, rotation=np.arctan2(cy, cx)/np.pi*180-90,
51
+ horizontalalignment='center', verticalalignment='center')
52
+ except:
53
+ pass
37
54
  ax.autoscale(enable=True)
38
55
  if not with_axis:
39
56
  ax.axis('off')
femagtools/plot/wdg.py CHANGED
@@ -48,19 +48,28 @@ def mmf_fft(f, title='', mmfmin=1e-2, ax=0):
48
48
  pass
49
49
 
50
50
 
51
- def zoneplan(wdg, ax=0):
51
+ def zoneplan(wdg, write_title=True, max_slots=0, ax=0):
52
52
  """plot zone plan of winding wdg"""
53
53
  from matplotlib.patches import Rectangle
54
54
  upper, lower = wdg.zoneplan()
55
55
  Qb = len([n for l in upper for n in l])
56
+ if max_slots:
57
+ Qb = max_slots
56
58
  from femagtools.windings import coil_color
57
- rh = 0.5
59
+ h = 0.5
60
+ w = 1
61
+ dx = -1.5, -1.5
62
+ dt = 0.5, 0.5
63
+ yl = 0, 0.
64
+ ymax = h
58
65
  if lower:
59
- yl = rh
60
- ymax = 2*rh + 0.2
61
- else:
62
- yl = 0
63
- ymax = rh + 0.2
66
+ if wdg.q < 1:
67
+ dx = -1, -1.5
68
+ dt = 0.2, 0.2
69
+ w = 0.5
70
+ else:
71
+ yl = h, 0
72
+ ymax = 2*h
64
73
  if ax == 0:
65
74
  ax = plt.gca()
66
75
  ax.axis('off')
@@ -70,28 +79,31 @@ def zoneplan(wdg, ax=0):
70
79
 
71
80
  for i, p in enumerate(upper):
72
81
  for x in p:
73
- ax.add_patch(Rectangle((abs(x)-1.5, yl), 1, rh,
74
- facecolor=coil_color[i],
75
- edgecolor='white', fill=True))
76
- s = f'+{i+1}' if x > 0 else f'-{i+1}'
77
- ax.text(abs(x)-1, yl+rh/2, s, color='black',
78
- ha="center", va="center")
82
+ if abs(x) < Qb+1:
83
+ ax.add_patch(Rectangle((abs(x)+dx[0], yl[0]), w, h,
84
+ facecolor=coil_color[i],
85
+ edgecolor='white', fill=True))
86
+ s = f'+{i+1}' if x > 0 else f'-{i+1}'
87
+ ax.text(abs(x)+dx[0]+dt[0], yl[0]+h/2, s, color='black',
88
+ ha="center", va="center")
79
89
  for i, p in enumerate(lower):
80
90
  for x in p:
81
- ax.add_patch(Rectangle((abs(x)-1.5, yl-rh), 1, rh,
82
- facecolor=coil_color[i],
83
- edgecolor='white', fill=True))
84
- s = f'+{i+1}' if x > 0 else f'-{i+1}'
85
- ax.text(abs(x)-1, yl-rh/2, s, color='black',
86
- ha="center", va="center")
87
-
88
- yu = yl+rh
91
+ if abs(x) < Qb+1:
92
+ ax.add_patch(Rectangle((abs(x)+dx[1], yl[1]), w, h,
93
+ facecolor=coil_color[i],
94
+ edgecolor='white', fill=True))
95
+ s = f'+{i+1}' if x > 0 else f'-{i+1}'
96
+ ax.text(abs(x)+dx[1]+dt[1], yl[1]+h/2, s, color='black',
97
+ ha="center", va="center")
98
+
99
+ yu = yl[0]+h
89
100
  step = 1 if Qb < 25 else 2
90
- if lower:
91
- yl -= rh
101
+ yl = min(yl)
92
102
  margin = 0.05
93
- ax.text(-0.5, yu+margin, f'Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}',
94
- ha='left', va='bottom', size=15)
103
+ if write_title:
104
+ ax.text(-0.5, yu+margin,
105
+ f'Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}, yd={wdg.yd}',
106
+ ha='left', va='bottom', size=15)
95
107
  for i in range(0, Qb, step):
96
108
  ax.text(i, yl-margin, f'{i+1}', ha="center", va="top")
97
109
 
@@ -99,7 +111,7 @@ def zoneplan(wdg, ax=0):
99
111
  def winding_factors(wdg, n=8, ax=0):
100
112
  """plot winding factors"""
101
113
  ax = plt.gca()
102
- ax.set_title(f'Winding factors Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}')
114
+ ax.set_title(f'Winding factors Q={wdg.Q}, p={wdg.p}, q={round(wdg.q,4)}, yd={wdg.yd}')
103
115
  ax.grid(True)
104
116
  order, kwp, kwd, kw = np.array(
105
117
  [(n, k1, k2, k3)
@@ -0,0 +1,209 @@
1
+ -- hairpin winding template
2
+
3
+ rcoil, phi_coil = c2pd(m.xcoil_1, m.ycoil_1)
4
+
5
+ slot_div_angle = 360/m.tot_num_slot
6
+
7
+ -- delete existing mesh in the slot
8
+ for i = 1, m.num_sl_gen do
9
+ xc, yc = pd2c(rcoil, phi_coil+(i-1)*slot_div_angle)
10
+ delete_mesh_se(xc, yc)
11
+ end
12
+ -- wire params
13
+ wire_height = ${model['wire']["wire_height"]*1e3}
14
+ wire_width = ${model['wire']["wire_width"]*1e3}
15
+ wire_corner_r = ${model['wire']["corner_radius"]*1e3}
16
+ wire_gap = ${model['wire']["wire_separation"]*1e3}
17
+ TH1 = ${model['wire']["wire_th1"]*1e3} -- distance to the bore radius
18
+ nwires = ${model['wire']["num_layers"]}
19
+
20
+ fml = require "fml"
21
+
22
+ function line_xy(pnt1, pnt2, nnodes)
23
+ -- create line
24
+ nc_line(pnt1.x, pnt1.y, pnt2.x, pnt2.y, nnodes)
25
+ end
26
+
27
+ function circle_xy(pnt1, pnt2, cx, cy, nnodes)
28
+ -- create circle
29
+ nc_circle_m(pnt1.x, pnt1.y, pnt2.x, pnt2.y, cx, cy, nnodes)
30
+ end
31
+
32
+ function draw_rectangle_wire(dx, dy, dphi, wire_height, wire_width, r0, agndst)
33
+
34
+ local x = {}
35
+ local y = {}
36
+ local x1 = {}
37
+ local y1 = {}
38
+ local hl = {}
39
+ local hi = {}
40
+ local hj = {}
41
+ local hk = {}
42
+ local xcp, ycp
43
+ local tmpx, tmpy, tmpr, tmpp
44
+
45
+ h1 = fml.Point:Create(dx, 0)
46
+ h2 = fml.Point:Create(dx, -wire_width/2+dy)
47
+ he = fml.Point:Create(dx+wire_height, 0)
48
+
49
+ hl[1] = fml.Line:Create(h1, 90)
50
+ hl[2] = fml.Line:Parallel(hl[1], wire_height)
51
+ hl[3] = fml.Line:Create(h2, 0)
52
+ hl[4] = fml.Line:Parallel(hl[3], -wire_width)
53
+
54
+ hi[1] = fml.Point:Intersection(hl[1], hl[3])
55
+ hi[2] = fml.Point:Intersection(hl[1], hl[4])
56
+ hi[3] = fml.Point:Intersection(hl[2], hl[4])
57
+ hi[4] = fml.Point:Intersection(hl[2], hl[3])
58
+ -- with corner
59
+ if r0 > 0 then
60
+ s1 = {1, 1, 2, 2}
61
+ s2 = {3, 4, 4, 3}
62
+ s3 = {1, 4, 3, 2}
63
+ ctr = 1
64
+
65
+ for i =1, 4 do
66
+ hj[ctr], hj[ctr+1], hj[ctr+2] = fml.Point:Rounding(hl[s1[i]], hl[s2[i]], r0, s3[i])
67
+ ctr = ctr + 3
68
+ end
69
+
70
+ for j = 1, #hj do
71
+ tmpr, tmpp = c2pd(hj[j].x, hj[j].y)
72
+ tmpx, tmpy = pd2c(tmpr, tmpp+dphi)
73
+ hk[j] = fml.Point:Create(tmpx, tmpy)
74
+ end
75
+
76
+ dst = agndst/2
77
+ ah1 = fml.Point:Create((hk[12].x+hk[8].x)/2 , (hk[12].y+hk[8].y)/2)
78
+ ah2 = fml.Point:Create((hk[6].x+hk[2].x)/2 , (hk[6].y+hk[2].y)/2)
79
+
80
+ line_xy(hk[12], ah1, 0)
81
+ line_xy(ah1, hk[8], 0)
82
+ line_xy(hk[9], hk[5], 0)
83
+ line_xy( hk[6], ah2, 0)
84
+
85
+ line_xy(ah2, hk[2], 0)
86
+ line_xy(hk[3], hk[11], 0)
87
+
88
+ circle_xy(hk[8], hk[9], hk[7].x, hk[7].y, 6)
89
+ circle_xy(hk[5], hk[6], hk[4].x, hk[4].y, 6)
90
+ circle_xy(hk[2], hk[3], hk[1].x, hk[1].y, 6)
91
+ circle_xy(hk[11], hk[12], hk[10].x, hk[10].y, 6)
92
+ xcp = (hk[12].x + hk[6].x)/2
93
+ ycp = (hk[12].y + hk[6].y)/2
94
+
95
+ else
96
+ xcp = 0
97
+ ycp = 0
98
+
99
+ for i = 1, 4 do
100
+ x[i], y[i] = hi[i].x, hi[i].y
101
+ tmpr, tmpp = c2pd(x[i], y[i])
102
+ tmpx, tmpy = pd2c(tmpr, tmpp+dphi)
103
+ x1[i], y1[i] = tmpx, tmpy
104
+ xcp = xcp + tmpx/4
105
+ ycp = ycp + tmpy/4
106
+ end
107
+
108
+ nc_line(x1[1], y1[1], x1[2], y1[2], 0)
109
+ nc_line_cont(x1[3], y1[3], 0)
110
+ nc_line_cont(x1[4], y1[4], 0)
111
+ nc_line_cont(x1[1], y1[1], 0)
112
+
113
+ end
114
+
115
+ return xcp, ycp, ah1, ah2
116
+ end
117
+
118
+ -- hairpin winding
119
+ wire_xy = {}
120
+ x0, y0 = da1/2+TH1, 0
121
+ auh1 = {}
122
+ auh2 = {}
123
+
124
+ for j = 1, m.num_sl_gen do
125
+ wire_xy[j] = {}
126
+ for k = 1, nwires do
127
+ wire_xy[j][k] = 0.0
128
+ end
129
+ end
130
+
131
+ ndt(agndst)
132
+ for j = 1, m.num_sl_gen do
133
+ for i = 1, nwires do
134
+ dx, dy = x0+(wire_gap+wire_height)*(i-1), y0
135
+ xcp, ycp, ah1, ah2 = draw_rectangle_wire(dx, dy, 360/m.tot_num_slot/2*(2*j-1), wire_height, wire_width, wire_corner_r, agndst)
136
+ wire_xy[j][nwires - (i-1)] = fml.Point:Create(xcp, ycp) -- large radius to smaller radius
137
+ create_mesh_se(xcp, ycp)
138
+ end
139
+
140
+ end
141
+ create_mesh()
142
+
143
+ -- create winding
144
+
145
+ widfile = io.open("wid.fsl", 'r')
146
+
147
+ nrows = 1
148
+ winding = {}
149
+
150
+ for i in widfile:lines() do
151
+ winding[nrows] = {}
152
+ ncols = 1
153
+ for j in string.gmatch(i, "[+-]?%d+") do
154
+ winding[nrows][ncols] = tonumber(j)
155
+ ncols = ncols + 1
156
+ end
157
+ nrows = nrows + 1
158
+ end
159
+
160
+ --[[
161
+
162
+ winding table
163
+
164
+ 1 slot_go pos_in_slot slot_ret pos_in_slot
165
+
166
+ ]]--
167
+ dir = 'wi'
168
+ cols = {"green", "yellow", "cyan"}
169
+ wk = 1
170
+ for i = 1, #winding do
171
+ idx = winding[i][2]
172
+ idxp = winding[i][3]
173
+ idy = winding[i][4]
174
+ idyp = winding[i][5]
175
+
176
+ if i == 1 then
177
+ if idx <= m.num_sl_gen then
178
+ wkey = def_new_wdg(wire_xy[idx][idxp].x, wire_xy[idx][idxp].y, cols[winding[i][1]], "Phase"..winding[i][1], 1, 0, 0, dir)
179
+ end
180
+
181
+ if math.abs(idy) <= m.num_sl_gen then
182
+ add_to_wdg (wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, "wsamekey", "wo", "wser")
183
+ end
184
+ else
185
+ if winding[i][1] == winding[i-1][1] and winding[i][1] == wk then
186
+ if idx <= m.num_sl_gen then
187
+ add_to_wdg (wire_xy[idx][idxp].x, wire_xy[idx][idxp].y, "wsamekey", dir, "wser")
188
+ end
189
+ if math.abs(idy) <= m.num_sl_gen then
190
+ add_to_wdg (wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, "wsamekey", "wo", "wser")
191
+ end
192
+ else
193
+ if idx <= m.num_sl_gen then
194
+ wkey = def_new_wdg(wire_xy[idx][idxp].x, wire_xy[idx][idxp].y, cols[winding[i][1]], "Phase"..winding[i][1], 1, 0, 0, dir)
195
+ wk = wk + 1
196
+ end
197
+ if math.abs(idy) <= m.num_sl_gen then
198
+ if wk == winding[i][1] then
199
+ add_to_wdg (wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, "wsamekey", "wo", "wser")
200
+ else
201
+ wkey = def_new_wdg(wire_xy[math.abs(idy)][idyp].x, wire_xy[math.abs(idy)][idyp].y, cols[winding[i][1]], "Phase"..winding[i][1], 1, 0, 0, "wo")
202
+ wk = wk + 1
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ m.num_par_wdgs = ${model.get('num_par_wdgs', 1)}
@@ -99,20 +99,19 @@ if m.slot_height ~= nil then
99
99
  elseif m.middle_line == 2 then
100
100
  dr = 1
101
101
  end
102
- lamCu = 400
103
- capCu = 385
104
- da = 1.0785
105
- dCu = 1.0
106
- lam = lamCu*(dCu/(da-dCu)+(da-dCu)/da)
107
- cap = capCu*da^2/(dCu^2*math.pi/4)
102
+
103
+ density = ${model.windings['spmaweight']*1e3}
104
+ lam = ${model.windings['thcond']}
105
+ cap = ${model.windings['thcap']}
106
+
108
107
  for i=1,m.num_sl_gen do
109
108
  a = (2*i-1)*math.pi/m.tot_num_sl + m.zeroangl/180*math.pi
110
109
  xwl,ywl = pr2c(rw+dr,a+dw)
111
- def_mat_therm(xwl,ywl,'yellow',8920,lam,cap,1)
110
+ def_mat_therm(xwl,ywl,'yellow',density,lam,cap,1)
112
111
  if m.middle_line > 0 then
113
112
  xwr,ywr = pr2c(rw-dr,a-dw)
114
- def_mat_therm(xwr,ywr,'yellow',8920,lam,cap,1)
113
+ def_mat_therm(xwr,ywr,'yellow',density,lam,cap,1)
115
114
  end
116
115
  end
117
116
  end
118
- %endif
117
+ %endif
@@ -44,16 +44,25 @@ beta = math.pi/m.num_poles
44
44
  xrb,yrb = pr2c(m.yoke_rad+0.1, beta) -- rotor lamination
45
45
  thcond = ${model['thcond']}
46
46
  thcap = ${model['thcap']}
47
- def_mat_therm(xrb,yrb,'blue',7700,thcond,thcap,1)
48
- def_mat_therm(m.yoke_rad/2,0.1,'blue',7700,thcond,thcap,1) -- Shaft
47
+ density = ${model.get('density')*1e3}
48
+ def_mat_therm(xrb,yrb,'blue',density,thcond,thcap,1)
49
49
 
50
+ %if model.get('thcond_shaft', 0) and model.get('thcap_shaft', 0):
51
+ if m.shaft_rad < m.yoke_rad then
52
+ thcond = ${model['thcond_shaft']}
53
+ thcap = ${model['thcap_shaft']}
54
+ density = ${model['spmaweight_shaft']*1e3}
55
+ def_mat_therm(m.yoke_rad/2,0.1,'blue',density,thcond,thcap,1) -- Shaft
56
+ end
57
+ %endif
50
58
  rm = m.magn_rad*math.cos(beta)
51
- thcond = 8
52
- thcap = 440
59
+ density = ${model['spmaweight_magnet']*1e3}
60
+ thcond = ${model.get('thcond_magnet', 8)}
61
+ thcap = ${model.get('thcap_magnet', 440)}
53
62
  for i = 1,m.npols_gen do -- Magnete
54
63
  alfa = (2*i-1) * beta
55
64
  xmx,ymx = pr2c(rm,alfa)
56
- def_mat_therm(xmx,ymx,darkgreen-i%2,7500,thcond,thcap,1)
65
+ def_mat_therm(xmx,ymx,darkgreen-i%2,density,thcond,thcap,1)
57
66
  end
58
67
 
59
68
  if m.air_triangle > 0 then
@@ -67,4 +76,21 @@ if m.air_triangle > 0 then
67
76
  def_mat_therm(xsx,ysx,skyblue,1.12,0.026,1007,1)
68
77
  end
69
78
  end
70
- %endif
79
+
80
+
81
+ -- add air layer (inside) for heat transfer
82
+ h = 3.8
83
+ beta = 360*m.npols_gen/m.num_poles
84
+
85
+
86
+ x0, y0 = pd2c(m.shaft_rad, m.zeroangl)
87
+ x1, y1 = pd2c(m.shaft_rad-h, m.zeroangl)
88
+ x2, y2 = pd2c(m.shaft_rad-h, beta+m.zeroangl)
89
+ x3, y3 = pd2c(m.shaft_rad, beta+m.zeroangl)
90
+ nc_line(x0, y0, x1, y1, 0)
91
+ nc_circle(x1, y1, x2, y2, 0)
92
+ nc_line(x2, y2, x3, y3, 0)
93
+ x0, y0 = pd2c(m.shaft_rad-h/2, beta/2+m.zeroangl)
94
+ create_mesh_se(x0, y0)
95
+
96
+ %endif
@@ -14,13 +14,22 @@ if not airgap_created then
14
14
  end
15
15
  % if hasattr(model, 'bore_diam'):
16
16
  r1 = m.fc_radius - ag/6
17
+ if(m.npols_gen == m.num_poles) then
18
+ alfa = alfa / 2
19
+ end
17
20
  x1, y1 = pr2c(r1, alfa)
18
21
  n = math.floor(m.fc_radius*alfa/agndst + 1.5)
19
22
  nc_circle_m(r1, 0, x1, y1, 0.0, 0.0, n)
23
+ if(m.npols_gen == m.num_poles) then
24
+ nc_circle_m(x1, y1, r1, 0, 0.0, 0.0, n)
25
+ end
20
26
 
21
27
  r2 = m.fc_radius + ag/6
22
28
  x2, y2 = pr2c(r2, alfa)
23
29
  nc_circle_m(r2, 0, x2, y2, 0.0, 0.0, n)
30
+ if(m.npols_gen == m.num_poles) then
31
+ nc_circle_m(x2, y2, r2, 0, 0.0, 0.0, n)
32
+ end
24
33
 
25
34
  if inner_da_start == nil then
26
35
  inner_da_start = da2/2
@@ -1,12 +1,16 @@
1
- -- Winding (ROT_HSM only!)
1
+ -- Winding (ROT_HSM or dxf)
2
2
  m.num_wires = ${model['num_wires']}
3
3
 
4
- a = m.rotor_diam/2 - ag - m.pole_height - m.core_height/2
5
- b = ((m.core_width1 + m.core_width2)/4 + m.pole_width/2)/2
6
- r = math.sqrt(a^2 + b^2)
7
- alpha = math.atan2(b, a)
8
-
9
4
  phi = math.pi/m.num_poles
5
+ if m.xcoil_r == nil then -- ROT_HSM
6
+ a = m.rotor_diam/2 - ag - m.pole_height - m.core_height/2
7
+ b = ((m.core_width1 + m.core_width2)/4 + m.pole_width/2)/2
8
+ r = math.sqrt(a^2 + b^2)
9
+ alpha = math.atan2(b, a)
10
+ else
11
+ r,beta = c2pr(m.xcoil_r, m.ycoil_r)
12
+ alpha = phi - beta
13
+ end
10
14
  dir = {'wi', 'wo'}
11
15
  xcoil, ycoil = pr2c(r, phi - alpha)
12
16
  def_new_wdg(xcoil, ycoil, yellow, "Exc", m.num_wires, 10.0, dir[1])