femagtools 1.8.1__py3-none-any.whl → 1.8.3__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- femagtools/__init__.py +1 -1
- femagtools/dxfsl/area.py +110 -1
- femagtools/dxfsl/areabuilder.py +93 -45
- femagtools/dxfsl/conv.py +5 -0
- femagtools/dxfsl/converter.py +85 -27
- femagtools/dxfsl/fslrenderer.py +5 -4
- femagtools/dxfsl/functions.py +14 -6
- femagtools/dxfsl/geom.py +135 -149
- femagtools/dxfsl/journal.py +1 -1
- femagtools/dxfsl/machine.py +161 -9
- femagtools/dxfsl/shape.py +46 -1
- femagtools/dxfsl/svgparser.py +1 -1
- femagtools/dxfsl/symmetry.py +143 -38
- femagtools/femag.py +64 -61
- femagtools/fsl.py +15 -12
- femagtools/isa7.py +3 -2
- femagtools/machine/__init__.py +5 -4
- femagtools/machine/afpm.py +79 -33
- femagtools/machine/effloss.py +29 -18
- femagtools/machine/sizing.py +192 -13
- femagtools/machine/sm.py +34 -36
- femagtools/machine/utils.py +2 -2
- femagtools/mcv.py +58 -29
- femagtools/model.py +4 -3
- femagtools/multiproc.py +79 -80
- femagtools/parstudy.py +11 -5
- femagtools/plot/nc.py +2 -2
- femagtools/semi_fea.py +108 -0
- femagtools/templates/basic_modpar.mako +0 -3
- femagtools/templates/fe-contr.mako +18 -18
- femagtools/templates/ld_lq_fast.mako +3 -0
- femagtools/templates/mult_cal_fast.mako +3 -0
- femagtools/templates/pm_sym_f_cur.mako +4 -1
- femagtools/templates/pm_sym_fast.mako +3 -0
- femagtools/templates/pm_sym_loss.mako +3 -0
- femagtools/templates/psd_psq_fast.mako +3 -0
- femagtools/templates/torq_calc.mako +3 -0
- femagtools/tks.py +23 -20
- femagtools/zmq.py +213 -0
- {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/METADATA +3 -3
- {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/RECORD +49 -47
- {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/WHEEL +1 -1
- tests/test_afpm.py +15 -6
- tests/test_femag.py +1 -1
- tests/test_fsl.py +4 -4
- tests/test_mcv.py +21 -15
- {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/LICENSE +0 -0
- {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.1.dist-info → femagtools-1.8.3.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,20 @@
|
|
1
|
-
m.hc_min = ${'%12.3f' % model.get('hc_min', 95.0)} -- Limit demagnetisa > 0:[%]Hc,<0:[kA/m]
|
2
|
-
m.con_hdcopy = ${'%12.3f' % model.get('con_hdcopy', 0)} -- Hc-copy:Name:auto:0,intact:1, none:-1
|
3
|
-
m.b_max = ${'%12.3f' % model.get('b_max', 2.4)} -- Max Induction [T] in colorgradation
|
4
|
-
m.b_min = ${'%12.3f' % model.get('move_inside')} -- Move inside: 0 , Move outside: > 0
|
5
|
-
m.calc_fe_loss = ${
|
6
|
-
m.eval_force = ${'%12.3f' % model.get('eval_force', 0)} -- Eval. force density > 0, no <= 0
|
7
|
-
m.allow_draw = ${'%12.3f' % model.get('allow_draw', 1)} -- Draw Graphics :> 0: yes, 0: no
|
8
|
-
m.fline_dens = ${'%12.3f' % model.get('fline_dens', 4)} -- F-Lines: 1: small, 2: medium, 3:thick
|
9
|
-
m.num_flines = ${'%12.3f' % model.get('num_flines', 20)} -- Number of Field-lines: < 100 > 2
|
10
|
-
m.name_bch_log = ${'%12.3f' % model.get('name_bch_log', 0)} -- Name bch-file in Logfile:> 0:yes,0:no
|
11
|
-
m.st_size_move = ${'%12.3f' % model.get('st_size_move', 0)} -- Step size move: r/ph:[degr], x/y:[mm]
|
12
|
-
m.num_nonl_it = ${'%12.3f' % model.get('num_nonl_it', 300)} -- Number of nonlinear Iterations < 99
|
13
|
-
m.perm_mode = ${'%12.3f' % model.get('perm_mode', 0)} -- Permeability mode:>0:restore,0:actual
|
14
|
-
m.error_perm = ${'%12.3f' % model.get('error_perm', 0.005)} -- Rel. Permeability error < 0.1 [%]
|
15
|
-
m.allow_demagn = ${'%12.3f' % model.get('allow_demagn', 0)} -- Allow Demagnetisation:= 1:yes,= 0:no
|
16
|
-
m.maenergy = ${'%12.3f' % model.get('maenergy', 0)} -- Force from magn energy 1 :yes,= 0:no
|
17
|
-
m.el_order_ag = ${'%12.3f' % model.get('el_order_ag', 1)} -- El. order in air gap: lin=1: quadr=2
|
18
|
-
m.export_scrpt = ${'%12.3f' % model.get('export_scrpt', 0)} -- Export parameters in script: yes > 0
|
1
|
+
m.hc_min = ${'%12.3f' % model.get('hc_min', 95.0)} -- Limit demagnetisa > 0:[%]Hc,<0:[kA/m]
|
2
|
+
m.con_hdcopy = ${'%12.3f' % model.get('con_hdcopy', 0)} -- Hc-copy:Name:auto:0,intact:1, none:-1
|
3
|
+
m.b_max = ${'%12.3f' % model.get('b_max', 2.4)} -- Max Induction [T] in colorgradation
|
4
|
+
m.b_min = ${'%12.3f' % model.get('move_inside')} -- Move inside: 0 , Move outside: > 0
|
5
|
+
m.calc_fe_loss = ${model.get('calc_fe_loss', 1)} -- Calc. FE-Loss:0:no, 1:yes, 2:m-output
|
6
|
+
m.eval_force = ${'%12.3f' % model.get('eval_force', 0)} -- Eval. force density > 0, no <= 0
|
7
|
+
m.allow_draw = ${'%12.3f' % model.get('allow_draw', 1)} -- Draw Graphics :> 0: yes, 0: no
|
8
|
+
m.fline_dens = ${'%12.3f' % model.get('fline_dens', 4)} -- F-Lines: 1: small, 2: medium, 3:thick
|
9
|
+
m.num_flines = ${'%12.3f' % model.get('num_flines', 20)} -- Number of Field-lines: < 100 > 2
|
10
|
+
m.name_bch_log = ${'%12.3f' % model.get('name_bch_log', 0)} -- Name bch-file in Logfile:> 0:yes,0:no
|
11
|
+
m.st_size_move = ${'%12.3f' % model.get('st_size_move', 0)} -- Step size move: r/ph:[degr], x/y:[mm]
|
12
|
+
m.num_nonl_it = ${'%12.3f' % model.get('num_nonl_it', 300)} -- Number of nonlinear Iterations < 99
|
13
|
+
m.perm_mode = ${'%12.3f' % model.get('perm_mode', 0)} -- Permeability mode:>0:restore,0:actual
|
14
|
+
m.error_perm = ${'%12.3f' % model.get('error_perm', 0.005)} -- Rel. Permeability error < 0.1 [%]
|
15
|
+
m.allow_demagn = ${'%12.3f' % model.get('allow_demagn', 0)} -- Allow Demagnetisation:= 1:yes,= 0:no
|
16
|
+
m.maenergy = ${'%12.3f' % model.get('maenergy', 0)} -- Force from magn energy 1 :yes,= 0:no
|
17
|
+
m.el_order_ag = ${'%12.3f' % model.get('el_order_ag', 1)} -- El. order in air gap: lin=1: quadr=2
|
18
|
+
m.export_scrpt = ${'%12.3f' % model.get('export_scrpt', 0)} -- Export parameters in script: yes > 0
|
19
19
|
|
20
20
|
pre_models("FE-contr-data")
|
@@ -21,6 +21,9 @@ m.num_cur_steps = ${model['num_cur_steps']}
|
|
21
21
|
m.nu_beta_steps = ${model['num_beta_steps']}
|
22
22
|
m.beta_max = ${model['beta_max']}
|
23
23
|
m.beta_min = ${model['beta_min']}
|
24
|
+
% if model.get('calc_fe_loss', 0):
|
25
|
+
m.calc_fe_loss = ${model['calc_fe_loss']}
|
26
|
+
% endif
|
24
27
|
% if model.get('loss_funct',0):
|
25
28
|
m.loss_funct = ${model.get('loss_funct')}
|
26
29
|
% endif
|
@@ -22,6 +22,9 @@ m.fc_mult_move_type = 1.0 -- Type of move path in air gap
|
|
22
22
|
m.fc_force_points = 0.0 -- number move points in air gap
|
23
23
|
m.loss_funct = ${model.get('loss_funct', 0)} -- loss functon 0: own 1: ext
|
24
24
|
m.loss_fact = ${model.get('loss_fact', 1)} -- loss multiplication factor
|
25
|
+
% if model.get('calc_fe_loss', 0):
|
26
|
+
m.calc_fe_loss = ${model['calc_fe_loss']}
|
27
|
+
% endif
|
25
28
|
|
26
29
|
% if model.get('vtu_movie', 0):
|
27
30
|
m.movie_type = 'vtu'
|
@@ -23,11 +23,14 @@ m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
|
|
23
23
|
% if model.get('vtu_movie', 0):
|
24
24
|
m.movie_type = 'vtu'
|
25
25
|
%endif
|
26
|
+
% if model.get('calc_fe_loss'):
|
27
|
+
m.calc_fe_loss = ${'%d' % model['calc_fe_loss']}
|
28
|
+
% endif
|
26
29
|
% if model.get('loss_funct',0):
|
27
30
|
m.loss_funct = ${model.get('loss_funct')}
|
28
31
|
% endif
|
29
32
|
-- Excitation current
|
30
|
-
m.nloa_ex_cur = ${model.get('
|
33
|
+
m.nloa_ex_cur = ${model.get('noload_ex_cur', 0)} -- No Load Exciting current
|
31
34
|
m.load_ex_cur = ${model.get('load_ex_cur', 0)} -- Load Exciting current
|
32
35
|
m.wdgkeyex = 0 -- automatic winding selection
|
33
36
|
|
@@ -7,6 +7,9 @@ set_sim_data("explicit_mode", ${model.get('explicit_mode',0)})
|
|
7
7
|
% if model.get('wind_temp',0):
|
8
8
|
set_dev_data("cond_temp", ${model.get('wind_temp')}, ${model.get('wind_temp')})
|
9
9
|
% endif
|
10
|
+
% if model.get('calc_fe_loss', 0):
|
11
|
+
m.calc_fe_loss = ${model['calc_fe_loss']}
|
12
|
+
% endif
|
10
13
|
m.move_action = ${model.get('move_action', 0)}
|
11
14
|
% if model.get('lfe',0):
|
12
15
|
m.arm_length = ${model.get('lfe')*1e3}
|
@@ -20,6 +20,9 @@ m.winding_temp = ${model.get('wind_temp')}
|
|
20
20
|
m.current = 1.0
|
21
21
|
m.ntibfilename = model..'.ntib'
|
22
22
|
m.period_frac = ${model.get('period_frac', 1)}
|
23
|
+
% if model.get('calc_fe_loss', 0):
|
24
|
+
m.calc_fe_loss = ${model['calc_fe_loss']}
|
25
|
+
% endif
|
23
26
|
% if model.get('loss_funct',0):
|
24
27
|
m.loss_funct = ${model.get('loss_funct')}
|
25
28
|
% endif
|
@@ -24,6 +24,9 @@ m.delta_iq = ${model['delta_iq']}/m.num_par_wdgs
|
|
24
24
|
% if model.get('load_ex_cur',0):
|
25
25
|
m.load_ex_cur = ${model['load_ex_cur']}
|
26
26
|
%endif
|
27
|
+
% if model.get('calc_fe_loss', 0):
|
28
|
+
m.calc_fe_loss = ${model['calc_fe_loss']}
|
29
|
+
% endif
|
27
30
|
% if model.get('loss_funct',0):
|
28
31
|
m.loss_funct = ${model.get('loss_funct')}
|
29
32
|
% endif
|
femagtools/tks.py
CHANGED
@@ -22,15 +22,15 @@ HBpattern = re.compile(r'H.+\s+B')
|
|
22
22
|
BPpattern = re.compile(r'B.+\s+P')
|
23
23
|
|
24
24
|
_tranlate = {
|
25
|
-
"ch": "Hysteresis Loss Factor",
|
26
|
-
"cw": "Eddy Current Loss Factor",
|
27
|
-
"ce": "Excess Loss Factor",
|
28
|
-
"ch_freq": "Hyteresis Exponent",
|
29
|
-
"cw_freq": "Eddy Current Exponent",
|
30
|
-
"b_coeff": "Induction Loss Exponent",
|
25
|
+
"ch": "Hysteresis Loss Factor",
|
26
|
+
"cw": "Eddy Current Loss Factor",
|
27
|
+
"ce": "Excess Loss Factor",
|
28
|
+
"ch_freq": "Hyteresis Exponent",
|
29
|
+
"cw_freq": "Eddy Current Exponent",
|
30
|
+
"b_coeff": "Induction Loss Exponent",
|
31
31
|
"alpha": "Induction Loss Exponent (Bertotti)",
|
32
|
-
"Bo": "Reference Induction",
|
33
|
-
"fo": "Reference Frequency",
|
32
|
+
"Bo": "Reference Induction",
|
33
|
+
"fo": "Reference Frequency",
|
34
34
|
}
|
35
35
|
|
36
36
|
def readlist(section):
|
@@ -134,15 +134,15 @@ class Reader(object):
|
|
134
134
|
self.losses['cw_freq'] = z[1]
|
135
135
|
self.losses['b_coeff'] = z[2]
|
136
136
|
|
137
|
-
self.steinmetz = {'cw': z[0], 'cw_freq': z[1], 'b_coeff': z[2],
|
137
|
+
self.steinmetz = {'cw': z[0], 'cw_freq': z[1], 'b_coeff': z[2],
|
138
138
|
'Bo': self.Bo, 'fo': self.fo}
|
139
139
|
|
140
140
|
self.losses['Bo'] = self.Bo
|
141
141
|
self.losses['fo'] = self.fo
|
142
142
|
z = lc.fit_bertotti(self.losses['f'],
|
143
143
|
self.losses['B'], pfe)
|
144
|
-
self.bertotti = {'ch': z[0], 'cw': z[1], 'ce': z[2],
|
145
|
-
'
|
144
|
+
self.bertotti = {'ch': z[0], 'cw': z[1], 'ce': z[2],
|
145
|
+
'b_coeff': 2.0, 'Bo': 1, 'fo': 1}
|
146
146
|
logger.info("Bertotti loss coeffs %s", z)
|
147
147
|
|
148
148
|
# must normalize pfe matrix:
|
@@ -171,9 +171,12 @@ class Reader(object):
|
|
171
171
|
'cw_freq': self.cw_freq,
|
172
172
|
'b_coeff': self.b_coeff,
|
173
173
|
'rho': self.rho,
|
174
|
-
'losses': self.losses
|
175
|
-
|
176
|
-
|
174
|
+
'losses': self.losses,
|
175
|
+
'bertotti': self.bertotti,
|
176
|
+
'steinmetz': self.steinmetz,
|
177
|
+
'jordan': self.jordan}
|
178
|
+
|
179
|
+
def tableview(Reader):
|
177
180
|
"""pretty print loss coeff table"""
|
178
181
|
losscoeff = [Reader.jordan, Reader.steinmetz, Reader.bertotti]
|
179
182
|
# Title
|
@@ -181,18 +184,18 @@ def tableview(Reader):
|
|
181
184
|
print('='*strlen)
|
182
185
|
print('| {:^34} '.format(' ') + '| {:^18} | {:^18} | {:^18} |'.format(*["Jordan", "Steinmetz", 'Bertotti']))
|
183
186
|
print('='*strlen)
|
184
|
-
# data
|
185
|
-
for key, item in _tranlate.items():
|
187
|
+
# data
|
188
|
+
for key, item in _tranlate.items():
|
186
189
|
fout = ''
|
187
|
-
for i in losscoeff:
|
188
|
-
if key in i:
|
190
|
+
for i in losscoeff:
|
191
|
+
if key in i:
|
189
192
|
fout += '| ' + f'{i[key]:^18.8e} '
|
190
|
-
else:
|
193
|
+
else:
|
191
194
|
tmp = '-'
|
192
195
|
fout += '| ' + f'{tmp:^18} '
|
193
196
|
print(f'| {item:^34}' + ' ' + fout + '|')
|
194
197
|
print('='*strlen)
|
195
|
-
return
|
198
|
+
return
|
196
199
|
|
197
200
|
def read(filename, filecontent=None):
|
198
201
|
"""read Thyssen File TKS and return mc dict"""
|
femagtools/zmq.py
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
"""zmq functions for FEMAG
|
2
|
+
|
3
|
+
"""
|
4
|
+
import re
|
5
|
+
import pathlib
|
6
|
+
import threading
|
7
|
+
import json
|
8
|
+
import time
|
9
|
+
import logging
|
10
|
+
try:
|
11
|
+
import zmq
|
12
|
+
except ImportError:
|
13
|
+
pass
|
14
|
+
|
15
|
+
numpat = re.compile(r'([+-]?\d+(?:\.\d+)?(?:[eE][+-]\d+)?)\s*')
|
16
|
+
logger = logging.getLogger(__name__)
|
17
|
+
|
18
|
+
class ProtFile:
|
19
|
+
def __init__(self, dirname, num_cur_steps):
|
20
|
+
self.size = 0
|
21
|
+
self.looplen = 0
|
22
|
+
self.cur_steps = [1, num_cur_steps]
|
23
|
+
self.n = 0
|
24
|
+
self.num_loops = 0
|
25
|
+
import platform
|
26
|
+
self.dirname = dirname
|
27
|
+
self.name = 'samples'
|
28
|
+
|
29
|
+
def percent(self):
|
30
|
+
if self.looplen > 0:
|
31
|
+
return min(100 * self.n / self.looplen, 100)
|
32
|
+
return 0
|
33
|
+
|
34
|
+
def update(self):
|
35
|
+
if not self.dirname:
|
36
|
+
return ''
|
37
|
+
p = list(pathlib.Path(self.dirname).glob('*.PROT'))
|
38
|
+
if p:
|
39
|
+
buf = ''
|
40
|
+
if self.size < p[0].stat().st_size:
|
41
|
+
with p[0].open() as fp:
|
42
|
+
fp.seek(self.size)
|
43
|
+
buf = fp.read()
|
44
|
+
return self.append(buf)
|
45
|
+
return ''
|
46
|
+
|
47
|
+
def append(self, buf):
|
48
|
+
self.size += len(buf)
|
49
|
+
for line in [l.strip() for l in buf.split('\n') if l]:
|
50
|
+
if line.startswith('Loop'):
|
51
|
+
self.n = 0
|
52
|
+
try:
|
53
|
+
cur_steps = self.cur_steps[self.num_loops]
|
54
|
+
except IndexError:
|
55
|
+
cur_steps = 1
|
56
|
+
x0, x1, dx, nbeta = [float(f)
|
57
|
+
for f in re.findall(numpat, line)][:4]
|
58
|
+
move_steps = round((x1-x0)/dx+1)
|
59
|
+
beta_steps = int(nbeta)
|
60
|
+
self.looplen = cur_steps*beta_steps*move_steps
|
61
|
+
self.num_loops += 1
|
62
|
+
elif (line.startswith('Cur') or
|
63
|
+
line.startswith('Id')):
|
64
|
+
self.n += 1
|
65
|
+
elif line.startswith('Number movesteps Fe-Losses'):
|
66
|
+
return f'{self.percent():3.1f}%' # 100%
|
67
|
+
elif line.startswith('begin'):
|
68
|
+
self.name = line.split()[1].strip()
|
69
|
+
|
70
|
+
return f'{self.percent():3.1f}%' # {self.n}/{self.looplen}'
|
71
|
+
|
72
|
+
|
73
|
+
class SubscriberTask(threading.Thread):
|
74
|
+
ylabel_index = 1
|
75
|
+
curve_label = '{}.'
|
76
|
+
# used by static notify func
|
77
|
+
percent_list = []
|
78
|
+
notify_timerfunc = None
|
79
|
+
notify_send_loop = True
|
80
|
+
notify = None
|
81
|
+
notify_send_header = set()
|
82
|
+
notify_send_data = dict()
|
83
|
+
|
84
|
+
def __init__(self, **kwargs):
|
85
|
+
threading.Thread.__init__(self)
|
86
|
+
context = zmq.Context.instance()
|
87
|
+
self.subscriber = context.socket(zmq.SUB)
|
88
|
+
self.port = kwargs.get('port', None)
|
89
|
+
self.host = kwargs.get('host')
|
90
|
+
self.notify = kwargs.get('notify', None)
|
91
|
+
SubscriberTask.notify = kwargs.get('notify', None)
|
92
|
+
self.header = kwargs.get('header')
|
93
|
+
self.num_cur_steps = kwargs.get('num_cur_steps', None)
|
94
|
+
SubscriberTask.curve_label = kwargs.get('curve_label', '')
|
95
|
+
SubscriberTask.timestep = kwargs.get('timestep', 1)
|
96
|
+
if not self.host:
|
97
|
+
self.host = 'localhost'
|
98
|
+
if not self.header:
|
99
|
+
self.header = [b'']
|
100
|
+
self.running = True
|
101
|
+
|
102
|
+
# timer function
|
103
|
+
if not SubscriberTask.notify_timerfunc:
|
104
|
+
SubscriberTask.notify_timerfunc = threading.Timer(0.1, SubscriberTask.send_notify)
|
105
|
+
SubscriberTask.notify_send_loop = True
|
106
|
+
SubscriberTask.notify_timerfunc.start()
|
107
|
+
|
108
|
+
if b'xyplot' in self.header:
|
109
|
+
self.ylabel = self.curve_label.format(SubscriberTask.ylabel_index)
|
110
|
+
SubscriberTask.ylabel_index += 1
|
111
|
+
if b'progress' in self.header:
|
112
|
+
self.protfile = ProtFile(None, self.num_cur_steps)
|
113
|
+
self.protId = len(SubscriberTask.percent_list)
|
114
|
+
SubscriberTask.percent_list.append(0) # 0%
|
115
|
+
|
116
|
+
self.subscriber.connect(f'tcp://{self.host}:{self.port}')
|
117
|
+
self.subscriber.setsockopt(zmq.SUBSCRIBE, self.header[0] if len(self.header) == 1 else b'')
|
118
|
+
self.controller = zmq.Context.instance().socket(zmq.PULL)
|
119
|
+
self.controller_url = f'inproc://publisher{self.port}'
|
120
|
+
try:
|
121
|
+
self.controller.bind(self.controller_url)
|
122
|
+
except zmq.error.ZMQError:
|
123
|
+
pass # ignore
|
124
|
+
|
125
|
+
self.poller = zmq.Poller()
|
126
|
+
self.poller.register(self.subscriber, zmq.POLLIN)
|
127
|
+
self.poller.register(self.controller, zmq.POLLIN)
|
128
|
+
self.logger = logger
|
129
|
+
|
130
|
+
def stop(self):
|
131
|
+
socket = zmq.Context.instance().socket(zmq.PUSH)
|
132
|
+
socket.connect(self.controller_url)
|
133
|
+
socket.send(b"quit")
|
134
|
+
socket.close()
|
135
|
+
self.running = False
|
136
|
+
|
137
|
+
def clear():
|
138
|
+
SubscriberTask.ylabel_index = 1
|
139
|
+
SubscriberTask.curve_label = '{}.'
|
140
|
+
SubscriberTask.notify_timerfunc = None
|
141
|
+
SubscriberTask.notify_send_loop = False
|
142
|
+
SubscriberTask.notify = None
|
143
|
+
SubscriberTask.notify_send_header = set()
|
144
|
+
SubscriberTask.notify_send_data = dict()
|
145
|
+
SubscriberTask.percent_list = []
|
146
|
+
|
147
|
+
def send_notify():
|
148
|
+
logger.debug(f"Send loop: {SubscriberTask.notify_send_loop}")
|
149
|
+
while SubscriberTask.notify_send_loop:
|
150
|
+
logger.debug(f"Send data: {SubscriberTask.notify_send_header}")
|
151
|
+
if 'progress_logger' in SubscriberTask.notify_send_header:
|
152
|
+
# collect data from different threads
|
153
|
+
SubscriberTask.notify_send_header.remove('progress_logger')
|
154
|
+
numTot = len(SubscriberTask.percent_list)
|
155
|
+
d = json.loads(SubscriberTask.notify_send_data.get('progress_logger')[1])
|
156
|
+
d['percent'] = sum(SubscriberTask.percent_list) / numTot
|
157
|
+
d['subtitle'] = f"{SubscriberTask.percent_list.count(100)} of {numTot}"
|
158
|
+
SubscriberTask.notify(['progress_logger', json.dumps(d)])
|
159
|
+
if 'xyplot' in SubscriberTask.notify_send_header:
|
160
|
+
SubscriberTask.notify([s.decode('latin1')
|
161
|
+
for s in SubscriberTask.notify_send_data.get('xyplot')])
|
162
|
+
SubscriberTask.notify_send_header.remove('xyplot')
|
163
|
+
|
164
|
+
time.sleep(abs(SubscriberTask.timestep))
|
165
|
+
logger.debug(f"Send Finished loop: {SubscriberTask.notify_send_loop}")
|
166
|
+
|
167
|
+
def run(self):
|
168
|
+
self.logger.debug("subscriber is ready, port: %s", {self.port})
|
169
|
+
while self.running:
|
170
|
+
socks = dict(self.poller.poll())
|
171
|
+
if socks.get(self.subscriber) == zmq.POLLIN:
|
172
|
+
try:
|
173
|
+
response = self.subscriber.recv_multipart()
|
174
|
+
# Sometimes femag send messages with only len = 1. These messages must be ignored
|
175
|
+
if len(response) < 2:
|
176
|
+
continue
|
177
|
+
# header progress
|
178
|
+
if response[0] == b'progress' and b'progress' in self.header:
|
179
|
+
SubscriberTask.notify_send_header.add('progress_logger')
|
180
|
+
response[0] = b'progress_logger'
|
181
|
+
SubscriberTask.notify_send_data['progress_logger'] = response
|
182
|
+
SubscriberTask.percent_list[self.protId] = json.loads(response[1].decode()).get('percent')
|
183
|
+
continue
|
184
|
+
|
185
|
+
# header xyplot (add ylabel)
|
186
|
+
if response[0] == b'xyplot' and b'xyplot' in self.header :
|
187
|
+
d = json.loads(response[1].decode(), strict=False)
|
188
|
+
d['ylabel'] = f"{d.get('ylabel')}_{self.ylabel}" \
|
189
|
+
if d.get('ylabel') else self.ylabel
|
190
|
+
response[1] = json.dumps(d).encode()
|
191
|
+
|
192
|
+
# timestep negative, immediately update
|
193
|
+
if SubscriberTask.timestep < 0:
|
194
|
+
self.notify([s.decode('latin1') for s in response])
|
195
|
+
else:
|
196
|
+
SubscriberTask.notify_send_data['xyplot'] = response
|
197
|
+
SubscriberTask.notify_send_header.add('xyplot')
|
198
|
+
continue
|
199
|
+
|
200
|
+
if response[0] in self.header or b'' in self.header:
|
201
|
+
self.notify([s.decode('latin1') for s in response])
|
202
|
+
|
203
|
+
except Exception:
|
204
|
+
self.logger.error(
|
205
|
+
"error in subscription message processing", exc_info=True)
|
206
|
+
|
207
|
+
if socks.get(self.controller) == zmq.POLLIN:
|
208
|
+
req = self.controller.recv()
|
209
|
+
self.logger.info("subscriber %s", req)
|
210
|
+
break
|
211
|
+
self.subscriber.close()
|
212
|
+
self.controller.close()
|
213
|
+
self.logger.debug("subscriber stopped")
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: femagtools
|
3
|
-
Version: 1.8.
|
3
|
+
Version: 1.8.3
|
4
4
|
Summary: Python API for FEMAG
|
5
5
|
Author-email: Ronald Tanner <tar@semafor.ch>, Dapu Zhang <dzhang@gtisoft.com>, Beat Holm <hob@semafor.ch>, Günther Amsler <amg@semafor.ch>, Nicolas Mauchle <mau@semafor.ch>
|
6
6
|
License: Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel
|
@@ -37,7 +37,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
37
37
|
Requires-Python: >=3.7
|
38
38
|
Description-Content-Type: text/markdown
|
39
39
|
License-File: LICENSE
|
40
|
-
Requires-Dist: numpy
|
40
|
+
Requires-Dist: numpy
|
41
41
|
Requires-Dist: scipy
|
42
42
|
Requires-Dist: mako
|
43
43
|
Requires-Dist: six
|