femagtools 1.8.5__py3-none-any.whl → 1.8.7__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/bch.py +16 -9
- femagtools/dxfsl/area.py +3 -0
- femagtools/dxfsl/conv.py +1 -8
- femagtools/dxfsl/converter.py +62 -144
- femagtools/dxfsl/geom.py +49 -0
- femagtools/femag.py +13 -72
- femagtools/fsl.py +6 -3
- femagtools/isa7.py +47 -3
- femagtools/losscoeffs.py +29 -3
- femagtools/machine/afpm.py +82 -21
- femagtools/mcv.py +162 -7
- femagtools/multiproc.py +2 -1
- femagtools/parstudy.py +3 -1
- femagtools/plot/__init__.py +1 -0
- femagtools/plot/bch.py +172 -36
- femagtools/plot/machine.py +100 -0
- femagtools/plot/nc.py +13 -0
- femagtools/poc.py +10 -0
- femagtools/shortcircuit.py +378 -0
- femagtools/templates/psi-torq-rem-rot.mako +127 -0
- femagtools/utils.py +2 -0
- femagtools/zmq.py +22 -4
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/METADATA +1 -1
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/RECORD +30 -27
- tests/test_nc.py +11 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/LICENSE +0 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/WHEEL +0 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/entry_points.txt +0 -0
- {femagtools-1.8.5.dist-info → femagtools-1.8.7.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/bch.py
CHANGED
@@ -618,8 +618,8 @@ class Reader:
|
|
618
618
|
|
619
619
|
def __read_peak_winding_currents(self, content):
|
620
620
|
self.scData['peakWindingCurrents'] = [float(x)
|
621
|
-
for x in
|
622
|
-
|
621
|
+
for x in self._numPattern.findall(
|
622
|
+
''.join(content))]
|
623
623
|
|
624
624
|
def __read_general_machine_data(self, content):
|
625
625
|
mcfiles = []
|
@@ -1057,10 +1057,11 @@ class Reader:
|
|
1057
1057
|
e.g. : idList[-450, -350, -250, -150, -50, 0]
|
1058
1058
|
idList[-500, -400, -300, -200, -100, 0, 0]
|
1059
1059
|
'''
|
1060
|
-
|
1061
|
-
if idList[-1] == 0 and len(idList) > 2 and \
|
1062
|
-
diff[-1] == 0:
|
1060
|
+
if list(idList).count(0) > 1: # femag writes duplicate id==0 values
|
1063
1061
|
idList = idList[:-1]
|
1062
|
+
diff = np.floor(np.abs(np.diff(idList)))
|
1063
|
+
if n := np.trim_zeros(np.diff(diff)).size:
|
1064
|
+
idList = idList[:-n]
|
1064
1065
|
return idList
|
1065
1066
|
|
1066
1067
|
def __read_psidq(self, content):
|
@@ -1085,8 +1086,7 @@ class Reader:
|
|
1085
1086
|
ncols = ncols-1
|
1086
1087
|
|
1087
1088
|
id = np.reshape(m[0], (-1, ncols)).T[0]
|
1088
|
-
|
1089
|
-
id = self.__removeTrailingZero(id)
|
1089
|
+
id = self.__removeTrailingZero(id)
|
1090
1090
|
nrows = len(id)
|
1091
1091
|
if nrows > 1 and id[nrows-1] < id[nrows-2]:
|
1092
1092
|
nrows = nrows-1
|
@@ -1121,8 +1121,7 @@ class Reader:
|
|
1121
1121
|
ncols = ncols-1
|
1122
1122
|
|
1123
1123
|
id = np.reshape(m[0], (-1, ncols)).T[0]
|
1124
|
-
|
1125
|
-
id = self.__removeTrailingZero(id)
|
1124
|
+
id = self.__removeTrailingZero(id)
|
1126
1125
|
nrows = len(id)
|
1127
1126
|
if nrows > 1 and id[nrows-1] < id[nrows-2]:
|
1128
1127
|
nrows = nrows-1
|
@@ -1610,6 +1609,11 @@ class Reader:
|
|
1610
1609
|
losses['staza'] = floatnan(rec[0])
|
1611
1610
|
losses['stajo'] = floatnan(rec[1])
|
1612
1611
|
losses['total'] += losses['staza']+losses['stajo']
|
1612
|
+
|
1613
|
+
elif content[i+1].split() == ['Iron', '----']:
|
1614
|
+
losses['rotfe'] = sum([floatnan(x) for x in rec])
|
1615
|
+
losses['total'] += losses['rotfe']
|
1616
|
+
|
1613
1617
|
else:
|
1614
1618
|
losses['rotfe'] = floatnan(rec[1])
|
1615
1619
|
losses['total'] += losses['rotfe']
|
@@ -1771,6 +1775,9 @@ class Reader:
|
|
1771
1775
|
def __getattr__(self, k):
|
1772
1776
|
return self.__dict__[k]
|
1773
1777
|
|
1778
|
+
def asdict(self):
|
1779
|
+
return {k[0]: k[1] for k in self.items()}
|
1780
|
+
|
1774
1781
|
def items(self):
|
1775
1782
|
return [(k, self.get(k)) for k in ('version',
|
1776
1783
|
'type',
|
femagtools/dxfsl/area.py
CHANGED
@@ -435,6 +435,9 @@ class Area(object):
|
|
435
435
|
self.type == TYPE_WINDINGS or \
|
436
436
|
self.type == TYPE_FD_WINDINGS
|
437
437
|
|
438
|
+
def is_field_winding(self):
|
439
|
+
return self.type == TYPE_FD_WINDINGS
|
440
|
+
|
438
441
|
def is_magnet(self):
|
439
442
|
return self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT
|
440
443
|
|
femagtools/dxfsl/conv.py
CHANGED
@@ -180,12 +180,6 @@ def main():
|
|
180
180
|
help='create full model (fsl only)',
|
181
181
|
dest='full_model',
|
182
182
|
action="store_true")
|
183
|
-
argparser.add_argument('--no_processing',
|
184
|
-
help=(argparse.SUPPRESS if not super_help else
|
185
|
-
"omit multiprocessing"),
|
186
|
-
dest='no_processing',
|
187
|
-
action="store_true",
|
188
|
-
default=False)
|
189
183
|
|
190
184
|
args = argparser.parse_args()
|
191
185
|
|
@@ -282,8 +276,7 @@ def main():
|
|
282
276
|
write_id=args.write_id,
|
283
277
|
debug_mode=args.debugger,
|
284
278
|
full_model=args.full_model,
|
285
|
-
write_journal=args.journal
|
286
|
-
no_processing=args.no_processing)
|
279
|
+
write_journal=args.journal)
|
287
280
|
keys = ('tot_num_slot', 'num_sl_gen', 'num_poles', 'nodedist',
|
288
281
|
'dy1', 'da1', 'da2', 'dy2', 'agndst', 'name')
|
289
282
|
logger.info("%s", {k: res[k] for k in keys if k in res})
|
femagtools/dxfsl/converter.py
CHANGED
@@ -10,7 +10,7 @@ from femagtools.dxfsl.shape import Shape
|
|
10
10
|
from femagtools.dxfsl.fslrenderer import FslRenderer, agndst
|
11
11
|
from femagtools.dxfsl.plotrenderer import PlotRenderer
|
12
12
|
from femagtools.dxfsl.concat import Concatenation
|
13
|
-
from femagtools.dxfsl.functions import Timer,
|
13
|
+
from femagtools.dxfsl.functions import Timer, middle_angle
|
14
14
|
from femagtools.dxfsl.journal import Journal, getJournal
|
15
15
|
from femagtools.dxfsl.area import TYPE_WINDINGS
|
16
16
|
from femagtools.dxfsl.areabuilder import disable_logging, enable_logging
|
@@ -18,7 +18,6 @@ import logging
|
|
18
18
|
import logging.config
|
19
19
|
import numpy as np
|
20
20
|
import sys
|
21
|
-
import multiprocessing
|
22
21
|
|
23
22
|
logger = logging.getLogger(__name__)
|
24
23
|
|
@@ -43,117 +42,6 @@ def plot_geom(doit, plt, geom, title="Plot", areas=True):
|
|
43
42
|
fill_areas=areas)
|
44
43
|
|
45
44
|
|
46
|
-
class SymSearchProcess(SimpleProcess):
|
47
|
-
def __init__(self,
|
48
|
-
name=None,
|
49
|
-
queue=None,
|
50
|
-
machine=None,
|
51
|
-
plt=None, # plotter
|
52
|
-
kind="",
|
53
|
-
mindist=0.01,
|
54
|
-
symtol=0.0,
|
55
|
-
sympart=0,
|
56
|
-
is_inner=False,
|
57
|
-
is_outer=False,
|
58
|
-
show_plots=True,
|
59
|
-
debug_mode=False,
|
60
|
-
rows=1,
|
61
|
-
cols=1,
|
62
|
-
num=1,
|
63
|
-
no_processing=False):
|
64
|
-
SimpleProcess.__init__(self,
|
65
|
-
name=name,
|
66
|
-
no_processing=no_processing)
|
67
|
-
self.queue = queue
|
68
|
-
self.mach_in = machine
|
69
|
-
self.mach_out = None
|
70
|
-
self.plt = plt
|
71
|
-
self.kind = kind
|
72
|
-
self.mindist = mindist
|
73
|
-
self.symtol = symtol
|
74
|
-
self.sympart = sympart
|
75
|
-
self.is_inner = is_inner
|
76
|
-
self.is_outer = is_outer
|
77
|
-
self.show_plots = show_plots
|
78
|
-
self.debug_mode = debug_mode
|
79
|
-
self.rows = rows
|
80
|
-
self.cols = cols
|
81
|
-
self.num = num
|
82
|
-
pass
|
83
|
-
|
84
|
-
def run(self):
|
85
|
-
if not self.without_processing():
|
86
|
-
logger.info("Process is running")
|
87
|
-
self.plt = None
|
88
|
-
self.show_plots = False
|
89
|
-
else:
|
90
|
-
logger.info("without multiprocessing")
|
91
|
-
|
92
|
-
try:
|
93
|
-
self.mach_out = symmetry_search(
|
94
|
-
self.mach_in,
|
95
|
-
plt=self.plt,
|
96
|
-
kind=self.kind,
|
97
|
-
mindist=self.mindist,
|
98
|
-
symtol=self.symtol,
|
99
|
-
sympart=self.sympart,
|
100
|
-
is_inner=self.is_inner,
|
101
|
-
is_outer=self.is_outer,
|
102
|
-
show_plots=self.show_plots,
|
103
|
-
debug_mode=self.debug_mode,
|
104
|
-
rows=self.rows,
|
105
|
-
cols=self.cols,
|
106
|
-
num=self.num)
|
107
|
-
except Exception as e:
|
108
|
-
logger.warning("Exception in symmetry_search: %s", e)
|
109
|
-
if not self.mach_out:
|
110
|
-
logger.error("NO MACHINE AFTER PROCESS")
|
111
|
-
self.queue.put(self.mach_out)
|
112
|
-
if not self.without_processing():
|
113
|
-
logger.info("Process is finished")
|
114
|
-
|
115
|
-
|
116
|
-
class BuildInnerProcess(SimpleProcess):
|
117
|
-
def __init__(self,
|
118
|
-
name=None,
|
119
|
-
queue=None,
|
120
|
-
machine=None,
|
121
|
-
mindist=0.01,
|
122
|
-
plt=None, # plotter
|
123
|
-
EESM=False,
|
124
|
-
no_processing=False):
|
125
|
-
SimpleProcess.__init__(self,
|
126
|
-
name=name,
|
127
|
-
no_processing=no_processing)
|
128
|
-
self.queue = queue
|
129
|
-
self.mach_in = machine
|
130
|
-
self.mach_out = None
|
131
|
-
self.plt = plt
|
132
|
-
self.mindist = mindist
|
133
|
-
self.EESM = EESM
|
134
|
-
pass
|
135
|
-
|
136
|
-
def run(self):
|
137
|
-
if not self.without_processing():
|
138
|
-
logger.info("Process is running")
|
139
|
-
self.plt = None
|
140
|
-
else:
|
141
|
-
logger.info("without multiprocessing")
|
142
|
-
|
143
|
-
try:
|
144
|
-
self.mach_out = build_inner_machine(
|
145
|
-
self.mach_in,
|
146
|
-
mindist=self.mindist,
|
147
|
-
plt=self.plt,
|
148
|
-
EESM=self.EESM)
|
149
|
-
except Exception as e:
|
150
|
-
logger.warning("Exception in symmetry_search: %s", e)
|
151
|
-
|
152
|
-
self.queue.put(self.mach_out)
|
153
|
-
if not self.without_processing():
|
154
|
-
logger.info("Process is finished")
|
155
|
-
|
156
|
-
|
157
45
|
def symmetry_search(machine,
|
158
46
|
plt=None, # plotter
|
159
47
|
kind="single",
|
@@ -348,6 +236,7 @@ def build_machine_rotor(machine, inner, mindist, plt, EESM=False, single=False):
|
|
348
236
|
title="Final Rotor")
|
349
237
|
|
350
238
|
t = timer.stop("-- rotor created in %0.4f seconds --")
|
239
|
+
journal.put('time_rotor_created', t)
|
351
240
|
|
352
241
|
logger.debug("End of build_machine_rotor")
|
353
242
|
return machine_temp
|
@@ -420,6 +309,7 @@ def build_machine_stator(machine, inner, mindist, plt, EESM=False, single=False)
|
|
420
309
|
title="Final Stator")
|
421
310
|
|
422
311
|
t = timer.stop("-- stator created in %0.4f seconds --")
|
312
|
+
journal.put('time_stator_created', t)
|
423
313
|
|
424
314
|
logger.debug("End of build_machine_stator")
|
425
315
|
return machine_temp
|
@@ -504,8 +394,7 @@ def convert(dxfile,
|
|
504
394
|
write_id=False,
|
505
395
|
full_model=False,
|
506
396
|
debug_mode=False,
|
507
|
-
write_journal=False
|
508
|
-
no_processing=False):
|
397
|
+
write_journal=False):
|
509
398
|
global journal
|
510
399
|
layers = ()
|
511
400
|
conv = {}
|
@@ -724,23 +613,19 @@ def convert(dxfile,
|
|
724
613
|
machine_outer.set_outer()
|
725
614
|
|
726
615
|
start_timer.stop("-- first part in %0.4f seconds --", info=True)
|
616
|
+
|
727
617
|
process_timer = Timer(start_it=True)
|
728
618
|
# inner part
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
rows=3, # rows
|
740
|
-
cols=2, # columns
|
741
|
-
num=3, # start num
|
742
|
-
no_processing=no_processing)
|
743
|
-
inner_proc.start_task()
|
619
|
+
machine_inner = symmetry_search(machine=machine_inner,
|
620
|
+
plt=p, # plot
|
621
|
+
kind=inner_name,
|
622
|
+
is_inner=True,
|
623
|
+
mindist=mindist,
|
624
|
+
symtol=symtol,
|
625
|
+
show_plots=show_plots,
|
626
|
+
rows=3, # rows
|
627
|
+
cols=2, # columns
|
628
|
+
num=3) # start num
|
744
629
|
|
745
630
|
# outer part
|
746
631
|
machine_outer = symmetry_search(machine_outer,
|
@@ -754,29 +639,20 @@ def convert(dxfile,
|
|
754
639
|
cols=2, # columns
|
755
640
|
num=4) # start num
|
756
641
|
|
757
|
-
machine_inner = inner_queue.get()
|
758
|
-
inner_proc.wait()
|
759
642
|
process_timer.stop("-- symmetry search in %0.4f seconds --", info=True)
|
760
643
|
|
761
644
|
machine_inner.sync_with_counterpart(machine_outer)
|
762
645
|
|
763
646
|
final_timer = Timer(start_it=True)
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
mindist=mindist,
|
769
|
-
plt=p,
|
770
|
-
EESM=EESM,
|
771
|
-
no_processing=no_processing)
|
772
|
-
inner_proc.start_task()
|
647
|
+
machine_inner = build_inner_machine(machine_inner,
|
648
|
+
mindist=mindist,
|
649
|
+
plt=p,
|
650
|
+
EESM=EESM)
|
773
651
|
|
774
652
|
machine_outer = build_outer_machine(machine_outer,
|
775
653
|
mindist,
|
776
654
|
p,
|
777
655
|
EESM=EESM)
|
778
|
-
machine_inner = inner_queue.get()
|
779
|
-
inner_proc.wait()
|
780
656
|
final_timer.stop("-- final part in %0.4f seconds --", info=True)
|
781
657
|
|
782
658
|
machine_inner.sync_with_counterpart(machine_outer)
|
@@ -958,7 +834,7 @@ def convert(dxfile,
|
|
958
834
|
r_out = 0.0
|
959
835
|
r_in = 0.0
|
960
836
|
if machine.cut_is_possible(r_in, r_out):
|
961
|
-
logger.
|
837
|
+
logger.debug("make a cut")
|
962
838
|
machine = machine.cut(r_in, r_out)
|
963
839
|
|
964
840
|
if part:
|
@@ -1080,6 +956,37 @@ def convert(dxfile,
|
|
1080
956
|
return conv
|
1081
957
|
|
1082
958
|
|
959
|
+
def _create_rotor_parameters(machine):
|
960
|
+
rotor = {
|
961
|
+
'min_radius': machine.geom.min_radius,
|
962
|
+
'max_radius': machine.geom.max_radius,
|
963
|
+
'mags': machine.geom.magnets_minmax_list(),
|
964
|
+
'fd_wnds': machine.geom.fd_windings_minmax_list()
|
965
|
+
}
|
966
|
+
shaft_min, shaft_max = machine.geom.shaft_minmax()
|
967
|
+
if shaft_max > 0.0:
|
968
|
+
rotor['shaft_min'] = shaft_min
|
969
|
+
rotor['shaft_max'] = shaft_max
|
970
|
+
if shaft_max > rotor['min_radius']:
|
971
|
+
rotor['min_radius'] = shaft_max
|
972
|
+
return rotor
|
973
|
+
|
974
|
+
|
975
|
+
def _create_stator_parameters(machine):
|
976
|
+
stator = {
|
977
|
+
'min_radius': machine.geom.min_radius,
|
978
|
+
'max_radius': machine.geom.max_radius,
|
979
|
+
'wnds': machine.geom.windings_minmax_list()
|
980
|
+
}
|
981
|
+
shaft_min, shaft_max = machine.geom.shaft_minmax()
|
982
|
+
if shaft_max > 0.0:
|
983
|
+
stator['shaft_min'] = shaft_min
|
984
|
+
stator['shaft_max'] = shaft_max
|
985
|
+
if shaft_max > stator['min_radius']:
|
986
|
+
stator['min_radius'] = shaft_max
|
987
|
+
return stator
|
988
|
+
|
989
|
+
|
1083
990
|
def create_femag_parameters(m_inner, m_outer, nodedist=1):
|
1084
991
|
if not (m_inner and m_outer):
|
1085
992
|
logger.warning("inner %s outer %s", m_inner, m_outer)
|
@@ -1122,6 +1029,13 @@ def create_femag_parameters(m_inner, m_outer, nodedist=1):
|
|
1122
1029
|
params['alfa_slot'] = alfa_slot
|
1123
1030
|
params['alfa_pole'] = alfa_pole
|
1124
1031
|
|
1032
|
+
if m_inner.geom.is_rotor():
|
1033
|
+
params['rotor'] = _create_rotor_parameters(m_inner)
|
1034
|
+
params['stator'] = _create_stator_parameters(m_outer)
|
1035
|
+
else:
|
1036
|
+
params['rotor'] = _create_rotor_parameters(m_outer)
|
1037
|
+
params['stator'] = _create_stator_parameters(m_inner)
|
1038
|
+
|
1125
1039
|
if num_slots == 0 or num_poles == 0:
|
1126
1040
|
if num_slots == 0:
|
1127
1041
|
logger.warning("No slots found")
|
@@ -1149,6 +1063,8 @@ def create_femag_parameters_stator(motor, position):
|
|
1149
1063
|
params['dy1'] = 2*motor.geom.max_radius
|
1150
1064
|
params['da1'] = 2*motor.geom.min_radius
|
1151
1065
|
params['slot_area'] = motor.slot_area()
|
1066
|
+
params['stator'] = _create_stator_parameters(motor)
|
1067
|
+
params['machine'] = motor
|
1152
1068
|
return params
|
1153
1069
|
|
1154
1070
|
|
@@ -1163,4 +1079,6 @@ def create_femag_parameters_rotor(motor, position):
|
|
1163
1079
|
params['dy1'] = 2*motor.geom.max_radius
|
1164
1080
|
params['da1'] = 2*motor.geom.min_radius
|
1165
1081
|
params['slot_area'] = motor.slot_area()
|
1082
|
+
params['rotor'] = _create_rotor_parameters(motor)
|
1083
|
+
params['machine'] = motor
|
1166
1084
|
return params
|
femagtools/dxfsl/geom.py
CHANGED
@@ -4528,6 +4528,55 @@ class Geometry(object):
|
|
4528
4528
|
add_element(e)
|
4529
4529
|
self.area_list += area_list
|
4530
4530
|
|
4531
|
+
def areas_minmax_list(self, area_list):
|
4532
|
+
if not area_list:
|
4533
|
+
return []
|
4534
|
+
|
4535
|
+
dist_list = []
|
4536
|
+
for n, a in enumerate(area_list):
|
4537
|
+
dist_list.append((a.min_dist, a.max_dist, n))
|
4538
|
+
dist_list.sort()
|
4539
|
+
|
4540
|
+
minmax_list = []
|
4541
|
+
d1_this, d2_this, n = dist_list [0]
|
4542
|
+
for d1_next, d2_next, n in dist_list[1:]:
|
4543
|
+
if d1_next > d2_this:
|
4544
|
+
minmax_list.append((d1_this, d2_this))
|
4545
|
+
d1_this = d1_next
|
4546
|
+
d2_this = d2_next
|
4547
|
+
else:
|
4548
|
+
d2_this = max(d2_this, d2_next)
|
4549
|
+
minmax_list.append((d1_this, d2_this))
|
4550
|
+
return minmax_list
|
4551
|
+
|
4552
|
+
def magnets_minmax_list(self):
|
4553
|
+
magnets = [a for a in self.list_of_areas()
|
4554
|
+
if a.is_magnet()]
|
4555
|
+
return self.areas_minmax_list(magnets)
|
4556
|
+
|
4557
|
+
def windings_minmax_list(self):
|
4558
|
+
windings = [a for a in self.list_of_areas()
|
4559
|
+
if a.is_winding()]
|
4560
|
+
return self.areas_minmax_list(windings)
|
4561
|
+
|
4562
|
+
def fd_windings_minmax_list(self):
|
4563
|
+
windings = [a for a in self.list_of_areas()
|
4564
|
+
if a.is_field_winding()]
|
4565
|
+
return self.areas_minmax_list(windings)
|
4566
|
+
|
4567
|
+
def shaft_minmax(self):
|
4568
|
+
shafts = [a for a in self.list_of_areas()
|
4569
|
+
if a.is_shaft()]
|
4570
|
+
if not shafts:
|
4571
|
+
return (0.0, 0.0)
|
4572
|
+
|
4573
|
+
dmin = shafts[0].min_dist
|
4574
|
+
dmax = shafts[0].max_dist
|
4575
|
+
for s in shafts[1:]:
|
4576
|
+
dmin = min(dmin, s.min_dist)
|
4577
|
+
dmax = max(dmax, s.max_dist)
|
4578
|
+
return (dmin, dmax)
|
4579
|
+
|
4531
4580
|
def check_airgap_connecting_nodes(self, geom, startangle, endangle):
|
4532
4581
|
logger.info("check_airgap_connecting_nodes")
|
4533
4582
|
|
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
|
-
|
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
|
-
|
506
|
-
|
507
|
-
|
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:
|
@@ -699,8 +635,9 @@ class Femag(BaseFemag):
|
|
699
635
|
setattr(self, "dy2", machine['stator']['dy2'])
|
700
636
|
except:
|
701
637
|
pass
|
638
|
+
|
702
639
|
if simulation:
|
703
|
-
return self.readResult(simulation)
|
640
|
+
return self.readResult(machine, simulation)
|
704
641
|
|
705
642
|
return {'status': 'ok', 'message': self.modelname,
|
706
643
|
'model': self.model.props()}
|
@@ -801,9 +738,12 @@ class ZmqFemag(BaseFemag):
|
|
801
738
|
def subscribe(self, notify):
|
802
739
|
"""attaches a notify function"""
|
803
740
|
logger.info("Subscribe on '%s' port %d", self.femaghost, self.port+1)
|
741
|
+
femagtools.zmq.SubscriberTask.clear()
|
804
742
|
if self.subscriber is None:
|
743
|
+
# progress/xyplot at a configured timestep published
|
744
|
+
header = [b'progress', b'xyplot', b'license']
|
805
745
|
self.subscriber = femagtools.zmq.SubscriberTask(
|
806
|
-
port=self.port+1, host=self.femaghost, notify=notify)
|
746
|
+
port=self.port+1, host=self.femaghost, notify=notify, header=header)
|
807
747
|
self.subscriber.start()
|
808
748
|
else:
|
809
749
|
# reattach?
|
@@ -1087,7 +1027,7 @@ class ZmqFemag(BaseFemag):
|
|
1087
1027
|
response = self.send_request(
|
1088
1028
|
['CONTROL', f'getfile = {filename}'], timeout=1000)
|
1089
1029
|
return [response[0].decode('latin1'),
|
1090
|
-
response[1] if len(response) else b'']
|
1030
|
+
response[1] if len(response) > 1 else b'']
|
1091
1031
|
|
1092
1032
|
def exportsvg(self, fslcmds, timeout=10000):
|
1093
1033
|
"""get svg format from fsl commands (if any graphic created)
|
@@ -1156,6 +1096,7 @@ class ZmqFemag(BaseFemag):
|
|
1156
1096
|
logger.info("Interrupt %s", self.femaghost)
|
1157
1097
|
ctrl.send_string('interrupt')
|
1158
1098
|
ctrl.close()
|
1099
|
+
femagtools.zmq.SubscriberTask.clear()
|
1159
1100
|
|
1160
1101
|
def copy_winding_file(self, name, wdg):
|
1161
1102
|
wdg.write(name, self.workdir)
|
femagtools/fsl.py
CHANGED
@@ -227,7 +227,7 @@ class Builder:
|
|
227
227
|
# obsolete
|
228
228
|
th_props = [' ']
|
229
229
|
try:
|
230
|
-
logger.
|
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,8 +750,11 @@ class Builder:
|
|
750
750
|
sim['eccentricity'])
|
751
751
|
|
752
752
|
if sim.get('calculationMode') == 'pm_sym_f_cur':
|
753
|
-
if 'nload_ex_cur'
|
754
|
-
sim
|
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'))
|