femagtools 1.8.6__py3-none-any.whl → 1.8.8__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/ecloss.py CHANGED
@@ -5,7 +5,6 @@ __author__ = 'Max Hullmann, Dapu Zhang, Ivan Solc'
5
5
 
6
6
  import logging
7
7
  import warnings
8
- from .amela import Amela
9
8
  import numpy as np
10
9
  from numpy import sinh, sin, cosh, cos, pi
11
10
  from scipy.interpolate import RBFInterpolator
@@ -22,6 +21,7 @@ class FrequencyDomain:
22
21
  self.phase = s['phase']
23
22
  self.order = s['order']
24
23
 
24
+
25
25
  def fd(s):
26
26
  f = FrequencyDomain(s)
27
27
  return f
@@ -53,10 +53,10 @@ def fft(s, fs):
53
53
  freq = np.array([i*fs/l for i in range(ll)])
54
54
 
55
55
  return fd(dict(cmplx_amp=mag,
56
- amp=amp,
57
- freq=freq,
58
- phase=np.angle(mag[0:ll]),
59
- order=freq/freq[idx_max]))
56
+ amp=amp,
57
+ freq=freq,
58
+ phase=np.angle(mag[0:ll]),
59
+ order=freq/freq[idx_max]))
60
60
 
61
61
  def dfac(x):
62
62
  return 6/(x)**3*(sinh(x)-sin(x))/ \
@@ -76,7 +76,7 @@ def nptns(x, x1, nx):
76
76
 
77
77
  def ngrid(wm, hm, elxy):
78
78
  '''calculate number of grid points for the interpolation'''
79
- be = np.sqrt(wm*hm/elxy['excp'].shape[0])
79
+ be = np.sqrt(wm*hm/elxy['ecp'].shape[0])
80
80
  nx = np.around(wm/be) + 1
81
81
  ny = np.around(hm/be) + 1
82
82
 
@@ -91,13 +91,15 @@ def ngrid(wm, hm, elxy):
91
91
 
92
92
  def binterp(x, y, xq, yq, b):
93
93
  '''interpolate flux density with Rbf interpolator'''
94
- f = RBFInterpolator(np.array([[i, j] for i, j in zip(x, y)]), b)
95
- inp = f(np.array([[i, j] for i, j in zip(xq, yq)]))
94
+ f = RBFInterpolator(np.vstack((x, y)).T, b)
95
+ inp = f(np.vstack((xq, yq)).T)
96
96
  return inp.reshape(len(np.unique(yq)), len(np.unique(xq)), -1)
97
97
 
98
98
  def binterp_ialh2(x, y, xq, yq, b):
99
99
  '''interpolate flux density with Rbf interpolator'''
100
- f = RBFInterpolator(np.array([[i, j] for i, j in zip(x, y)]), b, kernel='thin_plate_spline')
100
+ yy = np.vstack((x, y)).T
101
+ logger.debug("shape y %s b %s", yy.shape, np.shape(b))
102
+ f = RBFInterpolator(yy, b, kernel='thin_plate_spline')
101
103
  inp = f(np.array([[i, j] for i, j in zip(xq, yq)]))
102
104
  return inp.reshape(len(np.unique(xq)), -1)
103
105
 
@@ -113,7 +115,7 @@ def Segmentation(wm, hm, lm, elxy, nsegx, nsegy, nsegz):
113
115
  x,y coordinates of each element's centerpoint in local reference frame, for entire magnet - xx, yy
114
116
  '''
115
117
  # Default nx,ny,nz without considering the segmentation
116
- be = np.sqrt(wm*hm/elxy['excp'].shape[0]) #square elements
118
+ be = np.sqrt(wm*hm/np.shape(elxy['ecp'])[1]) #square elements
117
119
  nx_new = int(np.around(wm/be))
118
120
  ny_new = int(np.around(hm/be))
119
121
  nz_new = int(np.around(lm/be))
@@ -126,8 +128,8 @@ def Segmentation(wm, hm, lm, elxy, nsegx, nsegy, nsegz):
126
128
 
127
129
  wms = wm/nsegx
128
130
  hms = hm/nsegy
129
- x0 = 0 # offset for excpl
130
- y0 = 0 # offset for eycpl
131
+ x0 = 0 # offset for ecpl
132
+ y0 = 0 # offset for ecpl
131
133
 
132
134
  segxcpl = np.linspace(wms/2/nx_new, wms - wms/nx_new/2, nx_new) + x0 # x center points of wanted elements distribution, local ref frame, 1st segment
133
135
  segycpl = np.linspace(hms/2/ny_new, hms - hms/ny_new/2, ny_new) + y0 # y center points of wanted elements distribution, local ref frame, 1st segment
@@ -149,21 +151,33 @@ def Segmentation(wm, hm, lm, elxy, nsegx, nsegy, nsegz):
149
151
 
150
152
  return nx_new, ny_new, nz_new, xx, yy
151
153
 
152
- class MagnLoss(Amela):
154
+ class MagnLoss:
153
155
  '''Calculate Magnet Losses with IALH Methode
154
156
  Parameters
155
157
  ----------
156
- workdir: working directory
157
- modelname: name of the femag model (*.nc)
158
+ nc: (object) nc/isa7
158
159
  ibeta: load cases [0, 1, 2]
160
+ magnet_data: array of pm data (see nc/isa7 get_magnet_data)
159
161
  '''
160
- def __init__(self, workdir, modelname, ibeta, **kwargs):
161
- super().__init__(workdir, magnet_data=dict(name=modelname))
162
- self.pm = self.get_magnet_data_all(ibeta)
163
- self.theta = self.pm[-1][-1]['phi'] # rotor pos
162
+ def __init__(self, **kwargs):
163
+ #super().__init__(workdir, magnet_data=dict(name=modelname))
164
+ if 'nc' in kwargs:
165
+ ibeta = kwargs.get('ibeta', [0])
166
+ nc = kwargs['nc']
167
+ self.pm = [nc.get_magnet_data(ibeta=i) for i in ibeta]
168
+ elif 'magnet_data' in kwargs:
169
+ self.pm = kwargs['magnet_data']
164
170
  self.speed = kwargs.get('speed', self.pm[-1][-1]['speed'])
165
- self.tgrid = 60/self.speed*(self.theta[-1] - self.theta[0])/360
166
- self.lt = len(self.theta)
171
+ logger.info("Speed %f", self.speed)
172
+ try: # move action rotation
173
+ self.theta = self.pm[-1][-1]['phi'] # rotor pos
174
+ self.lt = len(self.theta)
175
+ self.tgrid = 60/self.speed*(self.theta[-1]-self.theta[0])/360
176
+ except: # move action linear
177
+ self.displ = self.pm[-1][-1]['displ'] # rotor pos
178
+ self.lt = len(self.displ)
179
+ self.tgrid = (self.displ[-1]-self.displ[0])/self.speed
180
+
167
181
  self.ls = self.pm[-1][-1]['ls']
168
182
  self.th_loss = []
169
183
  try:
@@ -187,7 +201,6 @@ class MagnLoss(Amela):
187
201
  self.lm = 0
188
202
 
189
203
  self.segz = kwargs.get('segz', [0])
190
- self.is_meter = False
191
204
  # Determine the number of segments in z direction
192
205
  for i in range(len(self.segz)):
193
206
  if self.segz[i] > 0:
@@ -204,78 +217,71 @@ class MagnLoss(Amela):
204
217
 
205
218
  def periodicity_id(self, b):
206
219
  '''identify the periodicity of a given signal'''
207
- bx = b['bxl']
208
- by = b['byl']
209
- idx = bx.shape[1]
220
+ bxy = np.array(b['bxyl'])
221
+ npos = bxy.shape[2]
210
222
  if self.symmetry:
211
- ll = bx.shape[0]
223
+ nels = bxy.shape[1]
212
224
  ff = []
213
225
 
214
- for i in range(idx):
215
- r = idx//(i + 1)
226
+ for i in range(npos):
227
+ r = npos//(i + 1)
216
228
 
217
229
  if r > 1:
218
- f = 0
219
-
220
- for j in range(r-1):
221
- f += np.sum(np.abs(bx[:, 0:(i+1)] - bx[:, (j+1)*(i+1)-1:(j+2)*(i+1)-1]))/((i+1)*ll)
222
- f += np.sum(np.abs(by[:, 0:(i+1)] - by[:, (j+1)*(i+1)-1:(j+2)*(i+1)-1]))/((i+1)*ll)
223
-
224
- ff.append(f/(r-1))
225
-
230
+ ff.append(np.sum([np.sum(
231
+ np.abs(bxy[:, :, :(i+1)]
232
+ - bxy[:, :, (j+1)*(i+1)-1:(j+2)*(i+1)-1]),
233
+ axis=1) / ((i+1)*nels)
234
+ for j in range(r-1)])/(r-1))
226
235
  minf = np.amin(ff)
227
236
  i = np.argmin(ff)
228
- bxymax = np.amax([np.amax(np.abs(bx)), np.amax(np.abs(by))])
237
+ bxymax = np.amax(np.abs(bxy))
238
+ logger.debug("ll %d idx %d minf %f i %d bxymax %d",
239
+ nels, npos, minf, i, bxymax)
229
240
 
230
241
  if minf < bxymax * 1e-4:
231
242
  ishift = i
232
- num_period = (idx - 1) // ishift
243
+ num_period = (npos - 1) // ishift
233
244
 
234
245
  for j in range(num_period - 1):
235
- bx[:, 0:i+1] += bx[:, i+j*ishift:(i+1)+(j+1)*ishift]
236
- by[:, 0:i+1] += by[:, i+j*ishift:(i+1)+(j+1)*ishift]
246
+ bxy[:, :, 0:i+1] += bxy[:, :, i+j*ishift:(i+1)+(j+1)*ishift]
237
247
 
238
- bx[:, 0:i + 1] /= num_period
239
- by[:, 0:i + 1] /= num_period
240
- idx = i + 1
248
+ bxy[:, :, 0:i + 1] /= num_period
249
+ npos = i + 1
241
250
  else:
242
- ff = []
243
-
244
- for i in range(idx - 1, 0, -1):
245
- f1 = np.sum(np.abs(bx[:, 0] - bx[:, i]))/ll + np.sum(np.abs(by[:, 0] - by[:, i]))/ll
246
- ff.append(f1)
247
-
251
+ ff = [np.sum(np.abs(bxy[:, :, 0] - bxy[:, :, i]))/nels
252
+ for i in range(npos - 1, 0, -1)]
248
253
  minf = np.amin(ff)
249
254
  i = np.argmin(ff)
250
- idx = idx - i
255
+ npos = npos - i
251
256
 
252
- bx_fft = fft(b['bxf'][0:idx-1], (idx-1)/self.tgrid)
253
- by_fft = fft(b['byf'][0:idx-1], (idx-1)/self.tgrid)
257
+ bx_fft = fft(b['bxyf'][0], (npos-1)/self.tgrid)
258
+ by_fft = fft(b['bxyf'][1], (npos-1)/self.tgrid)
254
259
 
255
260
  if self.symmetry:
256
261
  bxy_amp = bx_fft.amp + by_fft.amp
257
- tmp_period = np.array([(idx-1)/i for i in range((idx-1)//2 + 1) if i > 0])
258
- idx_nonzero = np.argwhere(tmp_period > 0.1*np.amax(bxy_amp)).squeeze()
259
- period = tmp_period[idx_nonzero]
262
+ tmp_period = np.array([(npos-1)/i
263
+ for i in range((npos-1)//2 + 1) if i > 0])
264
+ npos_nonzero = np.argwhere(tmp_period > 0.1*np.amax(bxy_amp)).squeeze()
265
+ period = tmp_period[npos_nonzero]
260
266
 
261
267
  if np.sum(np.around([period[0]%i for i in period])) == 0:
262
- idx = int(np.ceil(np.amax(period))+1)
263
- if idx > bx.shape[1]:
264
- idx = bx.shape[1]
265
-
266
- self.tgrid = 60/self.speed*(self.theta[idx-1] - self.theta[0])/360
268
+ npos = min(int(np.ceil(np.amax(period))+1), bxy.shape[2])
267
269
 
268
- return [idx, bx_fft, by_fft]
270
+ try:
271
+ self.tgrid = 60/self.speed*(self.theta[npos-1] - self.theta[0])/360
272
+ except AttributeError:
273
+ self.tgrid = (self.displ[npos-1] - self.displ[0])/self.speed
274
+ logger.debug("Tgrid %f npos %d bx %f by %f xfreq %s yfreq %s",
275
+ self.tgrid, npos-1,
276
+ np.max(bx_fft.amp), np.max(by_fft.amp),
277
+ bx_fft.freq, by_fft.freq)
278
+ return [npos, bx_fft, by_fft]
269
279
 
270
280
  def consider_bx(self, wm, hm, bx_fft, by_fft):
271
281
  '''check if a caculation is necessary for the x direction'''
272
282
  fft_freq = bx_fft.freq
273
283
  fft_freq[fft_freq==0] = 0.5e-2
274
284
 
275
- if not self.is_meter:
276
- self.ls *= 1e-3
277
- self.lm *= 1e-3
278
- self.is_meter = True
279
285
  # skin depth
280
286
  delta = self.skin_depth(fft_freq)
281
287
 
@@ -296,9 +302,9 @@ class MagnLoss(Amela):
296
302
  krfy = dfac(wm/delta)
297
303
  py = ampf(by_fft, krfy)*wm**3*hm
298
304
 
299
- if px/py > 0.005:
300
- self.is_x = True
301
- return ' '
305
+ if py > 0:
306
+ if px/py > 0.005:
307
+ self.is_x = True
302
308
 
303
309
  def bpm_fft(self, nx, ny, nt, elxy, bxy):
304
310
  '''interpolate the flux density'''
@@ -355,7 +361,7 @@ class MagnLoss(Amela):
355
361
  c_ef_n0 = 32/pi**5/eta/dfac(xi)*6
356
362
  sum_r = 0.0
357
363
  sum_i = 0.0
358
- n = np.array([i for i in range(100)])
364
+ n = np.linspace(100)
359
365
  lambda_n = (2*n + 1)*pi
360
366
  beta_n = np.sqrt(lambda_n ** 2 + 2j*xi**2)
361
367
  beta_nr = np.real(beta_n)
@@ -398,14 +404,16 @@ class MagnLoss(Amela):
398
404
  if self.is_x and nu[ix] < 2:
399
405
  with warnings.catch_warnings():
400
406
  warnings.simplefilter('ignore')
401
- px_se[iy,ix,c] = self.calc_pvpm(bx_fft[iy,ix,c], max(c/self.tgrid, 1e-6),
402
- mu[iy], hm, wm/self.segx[jj], 0)
407
+ px_se[iy,ix,c] = self.calc_pvpm(
408
+ bx_fft[iy,ix,c], max(c/self.tgrid, 1e-6),
409
+ mu[iy], hm, wm/self.segx[jj], 0)
403
410
 
404
411
  if mu[iy] < 2:
405
412
  with warnings.catch_warnings():
406
413
  warnings.simplefilter('ignore')
407
- py_se[iy,ix,c] = self.calc_pvpm(by_fft[iy,ix,c], max(c/self.tgrid, 1e-6),
408
- nu[ix], wm/self.segx[jj], hm, 0)
414
+ py_se[iy,ix,c] = self.calc_pvpm(
415
+ by_fft[iy,ix,c], max(c/self.tgrid, 1e-6),
416
+ nu[ix], wm/self.segx[jj], hm, 0)
409
417
  py_sum = np.sum(py_se)
410
418
  px_sum = np.sum(px_se)
411
419
  pec[jj,kk] = (py_sum + px_sum)*(self.ls/self.lm)*self.numpoles*self.segx[jj]
@@ -424,12 +432,10 @@ class MagnLoss(Amela):
424
432
  ialh_loss = 0
425
433
  loss_detail = []
426
434
  for i in k:
427
- logger.info(f'magnet width and height: {i["wm"]:.2f}mm {i["hm"]:.2f}mm')
435
+ logger.info('magnet geom / mm: w %.2f h %.2f l %.2f',
436
+ i["wm"]*1e3, i["hm"]*1e3, i["lm"]*1e3)
428
437
  [nt, bx_fft, by_fft] = self.periodicity_id(i['bl'])
429
438
  [nx, ny] = ngrid(i['wm'], i['hm'], i['elcp'])
430
- keyset = ('wm', 'hm')
431
- for j in keyset:
432
- i[j]*=1e-3
433
439
  self.consider_bx(i['wm'], i['hm'], bx_fft, by_fft)
434
440
  bfft = self.bpm_fft(nx, ny, nt, i['elcp'], i['bl'])
435
441
  loss = self.loss(*bfft, i['wm'], i['hm'])
@@ -483,7 +489,7 @@ class MagnLoss(Amela):
483
489
  for m in range (int(ny/2)):
484
490
  symmetry = 4 if (m > 0) & (n > 0) else 2 # symmetry factor 4 due to double symmetry utilization.
485
491
 
486
- for k in range (0,1000,2): # loop is symmetrical on one side
492
+ for k in range (0, 1000, 2): # loop is symmetrical on one side
487
493
  complex_xnmkf = sx_ampl[n,m,f]*2/(np.pi*(k+1))*epsilon_z_x/epsilon_z_y*(m*np.pi*wm/hm)/(2j *epsilon**2 + (n*np.pi)**2 + (m*np.pi*wm/hm)**2 + ry*((k+1)*np.pi*wm/lm)**2)
488
494
  complex_ynmkf = sy_ampl[n,m,f]*2/(np.pi*(k+1)) *n*np.pi/(2j *epsilon**2 + (n*np.pi)**2 + (m*np.pi*wm/hm)**2 + rx*((k+1)*np.pi*wm/lm)**2)
489
495
  real_x_nmkf = np.real(complex_xnmkf)
@@ -599,8 +605,8 @@ class MagnLoss(Amela):
599
605
  break
600
606
 
601
607
  filt = np.ones((nf))
602
- for ii in range(ilim,nf):
603
- filt[ii] = (feclim/freq[ii])
608
+ for ii in range(ilim, nf):
609
+ filt[ii] = feclim/freq[ii]
604
610
  for ii in range(nx): # Derivation in frequency domain
605
611
  for jj in range(ny):
606
612
  complbx[ii,jj,:] = -complbx[ii,jj,:]*freq*filt*np.pi*2j
@@ -608,8 +614,8 @@ class MagnLoss(Amela):
608
614
 
609
615
  for ii in range (nx): # Inverse Fourier-Transformation
610
616
  for jj in range (ny):
611
- sx = np.fft.irfftn(complbx[ii,jj,:], [nt - 1])
612
- sy = np.fft.irfftn(complby[ii,jj,:], [nt - 1])
617
+ sx = np.fft.irfftn(complbx[ii,jj,:], s=[nt - 1], axes=[0])
618
+ sy = np.fft.irfftn(complby[ii,jj,:], s=[nt - 1], axes=[0])
613
619
  sx = np.append(sx, sx[0])
614
620
  sy = np.append(sy, sy[0])
615
621
  sx_pm_3D[ii,jj,:] = sx
@@ -636,25 +642,27 @@ class MagnLoss(Amela):
636
642
  '''
637
643
  nx_tot = int(nx*nsegx)
638
644
  ny_tot = int(ny*nsegy)
639
-
640
- Bxl_ac = np.zeros((np.asarray(bxy['bxl']).shape))
645
+ bxyl = np.asarray(bxy['bxyl'])
646
+ Bxl_ac = np.zeros((bxyl[0].shape))
641
647
  Byl_ac = np.zeros_like(Bxl_ac)
642
648
 
643
649
  # Remove the DC component of the original bxl, byl
644
650
  for ii in range(Bxl_ac.shape[0]):
645
- Bxl_ac[ii,:] = bxy['bxl'][ii,:] - np.mean(bxy['bxl'][ii,:])
651
+ Bxl_ac[ii,:] = bxyl[0, ii, :] - np.mean(bxyl[0,ii,:])
646
652
  for ii in range(Byl_ac.shape[0]):
647
- Byl_ac[ii,:] = bxy['byl'][ii,:] - np.mean(bxy['byl'][ii,:])
648
-
653
+ Byl_ac[ii,:] = bxyl[1,ii,:] - np.mean(bxyl[1,ii,:])
649
654
  xx_ = excpl_new.ravel()
650
655
  yy_ = eycpl_new.ravel()
651
656
  bx_3d_ac = np.zeros((nx_tot,ny_tot,nt))
652
657
  by_3d_ac = np.zeros_like(bx_3d_ac)
653
658
 
659
+ ecpl = elxy['ecpl']
654
660
  # Interpolation to the new resolution -> [nx*nsegx, ny*nsegy, nt]
655
- by_3d_ac = binterp_ialh2(elxy['excpl'], elxy['eycpl'], xx_, yy_, Byl_ac[:, 0:nt])
661
+ by_3d_ac = binterp_ialh2(ecpl[0], ecpl[1],
662
+ xx_, yy_, Byl_ac[:, 0:nt])
656
663
  if self.is_x:
657
- bx_3d_ac = binterp_ialh2(elxy['excpl'], elxy['eycpl'], xx_, yy_, Bxl_ac[:, 0:nt])
664
+ bx_3d_ac = binterp_ialh2(ecpl[0], ecpl[1],
665
+ xx_, yy_, Bxl_ac[:, 0:nt])
658
666
  bx_3d_ac = bx_3d_ac.reshape(nx_tot,ny_tot,nt)
659
667
  by_3d_ac = by_3d_ac.reshape(nx_tot,ny_tot,nt)
660
668
 
@@ -725,8 +733,10 @@ class MagnLoss(Amela):
725
733
  for ii in range(nsegx):
726
734
  for jj in range(nsegy): # nsegy is always = 1
727
735
  for kk in range(nsegz):
728
- Plossx, Plossy = self.ialh2(sx_abs[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:], sy_abs[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:],
729
- sx_phase[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:], sy_phase[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:],
736
+ Plossx, Plossy = self.ialh2(sx_abs[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:],
737
+ sy_abs[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:],
738
+ sx_phase[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:],
739
+ sy_phase[2*ii*nx:2*(ii+1)*nx, 2*jj*ny:2*(jj+1)*ny,:],
730
740
  freq_range, wm/nsegx, hm/nsegy, lm/nsegz, delta_eff)
731
741
  pec[ii,jj,kk] = (Plossx + Plossy)
732
742
 
@@ -740,8 +750,8 @@ class MagnLoss(Amela):
740
750
  Returns: all_load_cases: list of losses for all load cases
741
751
  '''
742
752
 
743
- nsegx = max(1,nsegx) # 1 = no segmentation
744
- nsegz = max(1,nsegz) # 1 = no segmentation
753
+ nsegx = max(1, nsegx) # 1 = no segmentation
754
+ nsegz = max(1, nsegz) # 1 = no segmentation
745
755
  nsegy = 1 # y segmentation not supported, nsegy is always = 1
746
756
 
747
757
  delta_eff = 0
@@ -751,22 +761,28 @@ class MagnLoss(Amela):
751
761
  ialh_loss = 0
752
762
  loss_detail = []
753
763
  for i in k: # loop for each superelement in a case
754
- logger.info(f'magnet width and height: {i["wm"]:.2f}mm {i["hm"]:.2f}mm')
755
- logger.info(f'number of magnet segments: x: {nsegx:.0f} y: {nsegy:.0f} z: {nsegz:.0f}')
756
- (nt, bx_fft, by_fft) = self.periodicity_id(i['bl']) # finds the time periodic part of the simulation
757
- (nx, ny, nz, excpl_new, eycpl_new) = Segmentation(i['wm'], i['hm'], i['lm'], i['elcp'], nsegx, nsegy, nsegz)
758
- # conversion from mm to m for wm,hm,lm
759
- wm = i['wm']/1000
760
- hm = i['hm']/1000
761
- lm = i['lm']/1000
764
+ logger.info('magnet geom / mm: w %.2f h %.2f l %.2f segments %s',
765
+ i["wm"]*1e3, i["hm"]*1e3, i["lm"]*1e3,
766
+ (nsegx, nsegy, nsegz))
767
+
768
+ (nt, bx_fft, by_fft) = self.periodicity_id(i['bl']) # finds the time periodic part of the simulation
769
+ (nx, ny, nz, excpl_new, eycpl_new) = Segmentation(
770
+ i['wm'], i['hm'], i['lm'], i['elcp'],
771
+ nsegx, nsegy, nsegz)
772
+
773
+ wm = i['wm']
774
+ hm = i['hm']
775
+ lm = i['lm']
762
776
  self.consider_bx(wm, hm, bx_fft, by_fft)
763
- (sx_abs, sy_abs, sx_phase, sy_phase, freq_range) = self.Process_B_data(nx, ny, nsegx, nsegy, nt, i['elcp'], i['bl'], excpl_new, eycpl_new)
764
- loss = self.loss_ialh2(sx_abs, sy_abs, sx_phase, sy_phase, freq_range, nx, ny, wm, hm, lm, nsegx, nsegy, nsegz, delta_eff) * self.numpoles
777
+ (sx_abs, sy_abs, sx_phase, sy_phase, freq_range) = self.Process_B_data(
778
+ nx, ny, nsegx, nsegy, nt, i['elcp'], i['bl'], excpl_new, eycpl_new)
779
+ loss = self.loss_ialh2(sx_abs, sy_abs, sx_phase, sy_phase, freq_range,
780
+ nx, ny, wm, hm, lm, nsegx, nsegy, nsegz, delta_eff) * self.numpoles
765
781
  ialh_loss += loss
766
- logger.info(f'Loadcase {i["loadcase"]}, Superelement {i["spel_key"]}, Total losses = {loss:.3f} W')
782
+ logger.info('Loadcase %d, Superelement %s, Total losses = %.3f W',
783
+ i["loadcase"], i["spel_key"], loss)
767
784
  loss_detail.append([i['spel_key'], loss/self.numpoles])
768
785
  self.th_loss.append(loss_detail)
769
786
  all_load_cases.append(ialh_loss)
770
787
 
771
788
  return all_load_cases
772
-
femagtools/femag.py CHANGED
@@ -61,43 +61,6 @@ def handle_process_output(filedes, outfile, log):
61
61
  pass
62
62
 
63
63
 
64
- def get_shortCircuit_parameters(bch, nload):
65
- try:
66
- if nload < 0:
67
- nload = 0
68
- if nload > 2:
69
- nload = 2
70
- if nload > 0:
71
- dqld = bch.dqPar['ld']
72
- dqlq = bch.dqPar['lq']
73
- dqpsim = bch.dqPar['psim']
74
- if len(dqld) <= nload or len(dqlq) <= nload or len(dqpsim) <= nload:
75
- ld = dqld[-1]/bch.armatureLength
76
- lq = dqlq[-1]/bch.armatureLength
77
- psim = dqpsim[-1]/bch.armatureLength
78
- else:
79
- ld = dqld[nload-1]/bch.armatureLength
80
- lq = dqlq[nload-1]/bch.armatureLength
81
- psim = dqpsim[nload-1]/bch.armatureLength
82
- else:
83
- ld = bch.machine['ld']/bch.armatureLength
84
- lq = bch.machine['lq']/bch.armatureLength
85
- psim = bch.machine['psim']/bch.armatureLength
86
- return dict(
87
- r1=bch.machine['r1'],
88
- ld=ld,
89
- lq=lq,
90
- psim=psim,
91
- num_pol_pair=bch.machine['p'],
92
- fc_radius=bch.machine['fc_radius'],
93
- lfe=bch.armatureLength/1e3,
94
- pocfilename=bch.machine['pocfile'],
95
- num_par_wdgs=bch.machine.get('num_par_wdgs', 0),
96
- calculationMode='shortcircuit')
97
- except (KeyError, AttributeError, IndexError):
98
- raise FemagError("missing pm/Rel-Sim results")
99
-
100
-
101
64
  def set_magnet_properties(model, simulation, magnets):
102
65
  """set temperature adapted magnet properties"""
103
66
  if not hasattr(model, 'magnet'):
@@ -449,7 +412,7 @@ class BaseFemag(object):
449
412
 
450
413
  return list(pathlib.Path(self.workdir).glob('*.PROT'))[0].stem
451
414
 
452
- def readResult(self, simulation, bch=None):
415
+ def readResult(self, machine, simulation, bch=None):
453
416
  if simulation:
454
417
  if simulation['calculationMode'] == "fieldcalc":
455
418
  nc = self.read_nc()
@@ -495,38 +458,11 @@ class BaseFemag(object):
495
458
  if simulation['calculationMode'] == 'pm_sym_fast' or \
496
459
  simulation['calculationMode'] == 'torq_calc':
497
460
  if simulation.get('shortCircuit', False):
498
- logger.info("short circuit simulation")
499
- simulation.update(
500
- get_shortCircuit_parameters(bch,
501
- simulation.get('initial', 2)))
502
-
503
- builder = femagtools.fsl.Builder(self.templatedirs)
461
+ from .shortcircuit import shortcircuit
504
462
  set_magnet_properties(self.model, simulation, self.magnets)
505
- fslcmds = (builder.open_model(self.model) +
506
- builder.create_shortcircuit(simulation))
507
- fslfile = 'shortcicuit.fsl'
508
- with open(os.path.join(self.workdir, fslfile), 'w') as f:
509
- f.write('\n'.join(fslcmds))
510
- self.run(fslfile) #, options?
511
- bchfile = self.get_bch_file(self.modelname)
512
- if bchfile:
513
- bchsc = femagtools.bch.Reader()
514
- logger.info("Read BCH {}".format(bchfile))
515
- with io.open(bchfile, encoding='latin1',
516
- errors='ignore') as f:
517
- bchsc.read(f)
518
- bch.scData = bchsc.scData
519
- for w in bch.flux:
520
- try:
521
- bch.flux[w] += bchsc.flux[w]
522
- bch.flux_fft[w] += bchsc.flux_fft[w]
523
- except (KeyError, IndexError):
524
- logging.debug(
525
- "No additional flux data in sc simulation")
526
- break
527
-
528
- bch.torque += bchsc.torque
529
- bch.demag += bchsc.demag
463
+ bch.scData = shortcircuit(self, machine, bch, simulation)
464
+ #bch.torque += bchsc.torque
465
+ #bch.demag += bchsc.demag
530
466
 
531
467
  if 'airgap_induc' in simulation:
532
468
  try:
@@ -538,13 +474,15 @@ class BaseFemag(object):
538
474
 
539
475
  if simulation.get('magnet_loss', False):
540
476
  logger.info('Evaluating magnet losses...')
541
- ops = [k for k in range(len(bch.torque))]
542
- m = femagtools.ecloss.MagnLoss(self.workdir, self.modelname, ibeta=ops)
477
+ ops = range(len(bch.torque))
478
+ ncf = pathlib.Path(self.workdir) / self.modelname
479
+ m = femagtools.ecloss.MagnLoss(
480
+ nc=femagtools.nc.read(ncf), ibeta=ops)
543
481
  try:
544
482
  # change from ialh to ialh2: since v1.8.1
545
483
  magn_losses = m.calc_losses_ialh2()
546
484
  except:
547
- magn_losses = [0 for i in range(len(ops))]
485
+ magn_losses = list(range(len(ops)))
548
486
 
549
487
  if len(ops) != len(bch.losses):
550
488
  magn_losses.insert(0, magn_losses[0])
@@ -699,8 +637,9 @@ class Femag(BaseFemag):
699
637
  setattr(self, "dy2", machine['stator']['dy2'])
700
638
  except:
701
639
  pass
640
+
702
641
  if simulation:
703
- return self.readResult(simulation)
642
+ return self.readResult(machine, simulation)
704
643
 
705
644
  return {'status': 'ok', 'message': self.modelname,
706
645
  'model': self.model.props()}
@@ -801,6 +740,7 @@ class ZmqFemag(BaseFemag):
801
740
  def subscribe(self, notify):
802
741
  """attaches a notify function"""
803
742
  logger.info("Subscribe on '%s' port %d", self.femaghost, self.port+1)
743
+ femagtools.zmq.SubscriberTask.clear()
804
744
  if self.subscriber is None:
805
745
  # progress/xyplot at a configured timestep published
806
746
  header = [b'progress', b'xyplot', b'license']
femagtools/fsl.py CHANGED
@@ -227,7 +227,7 @@ class Builder:
227
227
  # obsolete
228
228
  th_props = [' ']
229
229
  try:
230
- logger.info(model.magnet)
230
+ logger.debug(model.magnet)
231
231
  th_props = [f'rotor_density = {model["magnet"]["density"]}',
232
232
  f'rotor_thcond = {model["magnet"]["thcond"]}',
233
233
  f'rotor_thcap = {model["magnet"]["thcap"]}'
@@ -750,12 +750,17 @@ class Builder:
750
750
  sim['eccentricity'])
751
751
 
752
752
  if sim.get('calculationMode') == 'pm_sym_f_cur':
753
- if 'nload_ex_cur' in sim.keys(): # convert obsolete key
754
- sim['noload_ex_cur'] = sim.pop('nload_ex_cur')
753
+ if sim.get('nload_ex_cur', ''): # convert obsolete key
754
+ if isinstance(sim, dict):
755
+ sim['noload_ex_cur'] = sim.pop('nload_ex_cur')
756
+ else:
757
+ sim.noload_ex_cur = sim.get('nload_ex_cur')
755
758
  felosses = custom_fefunc + self.create_fe_losses(sim)
756
759
  fslcalc = (displ_stator_rotor
757
760
  + self.__render(sim, sim.get('calculationMode'))
758
- + airgap_induc + revert_displ)
761
+ + airgap_induc + revert_displ
762
+ + ['save_model("cont")'])
763
+
759
764
  '''
760
765
  if pfefunc:
761
766
  sim['loss_funct'] = pfefunc
@@ -768,8 +773,7 @@ class Builder:
768
773
  'psd_psq_fast'):
769
774
  return felosses + fslcalc
770
775
 
771
- return (felosses + fslcalc +
772
- self.__render(sim, 'plots'))
776
+ return felosses + fslcalc + self.__render(sim, 'plots')
773
777
 
774
778
  def create_shortcircuit(self, model):
775
779
  return self.__render(model, 'shortcircuit')
@@ -832,8 +836,7 @@ class Builder:
832
836
  fslmodel = self.create_model(model, magnets, condMat)
833
837
  logger.info("create simulation '%s'", sim['calculationMode'])
834
838
 
835
- return (fslmodel + self.create_analysis(sim) +
836
- ['save_model("close")'])
839
+ return fslmodel + self.create_analysis(sim)
837
840
 
838
841
  def create_detailed_wire(self, params, templ):
839
842
  return self.__render(params, templ)