femagtools 1.8.1__py3-none-any.whl → 1.8.3__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/__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
|