pyfemtet 0.3.4__py3-none-any.whl → 0.3.6__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.
Potentially problematic release.
This version of pyfemtet might be problematic. Click here for more details.
- pyfemtet/__init__.py +1 -1
- pyfemtet/dispatch_extensions.py +18 -3
- pyfemtet/opt/base.py +13 -7
- pyfemtet/opt/interface.py +8 -3
- pyfemtet/opt/monitor.py +80 -7
- {pyfemtet-0.3.4.dist-info → pyfemtet-0.3.6.dist-info}/METADATA +1 -1
- {pyfemtet-0.3.4.dist-info → pyfemtet-0.3.6.dist-info}/RECORD +9 -9
- {pyfemtet-0.3.4.dist-info → pyfemtet-0.3.6.dist-info}/LICENSE +0 -0
- {pyfemtet-0.3.4.dist-info → pyfemtet-0.3.6.dist-info}/WHEEL +0 -0
pyfemtet/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.3.
|
|
1
|
+
__version__ = "0.3.6"
|
pyfemtet/dispatch_extensions.py
CHANGED
|
@@ -144,11 +144,12 @@ def _get_subprocess_log_prefix():
|
|
|
144
144
|
return f'({current_process().name}) '
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
def launch_and_dispatch_femtet(timeout=DISPATCH_TIMEOUT) -> Tuple[IFemtet, int]:
|
|
147
|
+
def launch_and_dispatch_femtet(timeout=DISPATCH_TIMEOUT, strict_pid_specify=True) -> Tuple[IFemtet, int]:
|
|
148
148
|
"""Launch Femtet by new process and connect to it.
|
|
149
149
|
|
|
150
150
|
Args:
|
|
151
151
|
timeout (int or float, optional): Seconds to wait for connection. Defaults to DISPATCH_TIMEOUT.
|
|
152
|
+
strict_pid_specify (bool): If True, try to connect the launched femtet process strictly. If False, launch new process but try to connect any connectable femtet.
|
|
152
153
|
|
|
153
154
|
Raises:
|
|
154
155
|
FemtetNotFoundException: Launched Femtet is not found for some reason (i.e. failed to launch Femtet).
|
|
@@ -157,12 +158,26 @@ def launch_and_dispatch_femtet(timeout=DISPATCH_TIMEOUT) -> Tuple[IFemtet, int]:
|
|
|
157
158
|
Returns:
|
|
158
159
|
Tuple[IFemtet, int]:
|
|
159
160
|
"""
|
|
161
|
+
# launch femtet
|
|
160
162
|
util.execute_femtet()
|
|
161
163
|
pid = util.get_last_executed_femtet_process_id()
|
|
162
164
|
logger.debug(f'Target pid is {pid}.')
|
|
163
|
-
for
|
|
165
|
+
for _ in tqdm(range(5), 'wait for launch femtet...'):
|
|
164
166
|
sleep(1)
|
|
165
|
-
|
|
167
|
+
|
|
168
|
+
# dispatch femtet
|
|
169
|
+
if strict_pid_specify:
|
|
170
|
+
Femtet, pid = dispatch_specific_femtet(pid, timeout)
|
|
171
|
+
else:
|
|
172
|
+
# worker process なら排他処理する
|
|
173
|
+
try:
|
|
174
|
+
with Lock('simply-dispatch-femtet'):
|
|
175
|
+
Femtet, pid = dispatch_femtet()
|
|
176
|
+
except RuntimeError as e:
|
|
177
|
+
if "distributed.lock.Lock" in str(e):
|
|
178
|
+
Femtet, pid = dispatch_femtet()
|
|
179
|
+
else:
|
|
180
|
+
raise e
|
|
166
181
|
return Femtet, pid
|
|
167
182
|
|
|
168
183
|
|
pyfemtet/opt/base.py
CHANGED
|
@@ -709,7 +709,7 @@ class AbstractOptimizer(ABC):
|
|
|
709
709
|
subprocess_idx,
|
|
710
710
|
worker_status_list,
|
|
711
711
|
wait_setup,
|
|
712
|
-
skip_set_fem,
|
|
712
|
+
skip_set_fem=False,
|
|
713
713
|
) -> None:
|
|
714
714
|
|
|
715
715
|
# 自分の worker_status の取得
|
|
@@ -784,6 +784,7 @@ class OptunaOptimizer(AbstractOptimizer):
|
|
|
784
784
|
|
|
785
785
|
# 中断の確認 (FAIL loop に陥る対策)
|
|
786
786
|
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
787
|
+
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
787
788
|
trial.study.stop() # 現在実行中の trial を最後にする
|
|
788
789
|
return None # set TrialState FAIL
|
|
789
790
|
|
|
@@ -825,6 +826,7 @@ class OptunaOptimizer(AbstractOptimizer):
|
|
|
825
826
|
|
|
826
827
|
# 中断の確認 (解析中に interrupt されている場合対策)
|
|
827
828
|
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
829
|
+
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
828
830
|
trial.study.stop() # 現在実行中の trial を最後にする
|
|
829
831
|
return None # set TrialState FAIL
|
|
830
832
|
|
|
@@ -842,6 +844,7 @@ class OptunaOptimizer(AbstractOptimizer):
|
|
|
842
844
|
|
|
843
845
|
# 中断の確認 (解析中に interrupt されている場合対策)
|
|
844
846
|
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
847
|
+
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
845
848
|
trial.study.stop() # 現在実行中の trial を最後にする
|
|
846
849
|
return None # set TrialState FAIL
|
|
847
850
|
|
|
@@ -1293,7 +1296,7 @@ class FEMOpt:
|
|
|
1293
1296
|
if not self.opt.is_cluster:
|
|
1294
1297
|
subprocess_indices = subprocess_indices[1:]
|
|
1295
1298
|
worker_addresses = list(self.client.nthreads().keys())
|
|
1296
|
-
assert
|
|
1299
|
+
assert max(subprocess_indices) <= len(worker_addresses)-1, f'コア数{len(worker_addresses)}は不足しています。'
|
|
1297
1300
|
worker_addresses = worker_addresses[:len(range(n_parallel))] # TODO: ノードごとに適度に振り分ける
|
|
1298
1301
|
if not self.opt.is_cluster:
|
|
1299
1302
|
worker_addresses[0] = 'Main'
|
|
@@ -1310,7 +1313,7 @@ class FEMOpt:
|
|
|
1310
1313
|
|
|
1311
1314
|
# actor の設定
|
|
1312
1315
|
self.status = OptimizationStatus(self.client)
|
|
1313
|
-
self.worker_status_list = [OptimizationStatus(self.client, name) for name in worker_addresses]
|
|
1316
|
+
self.worker_status_list = [OptimizationStatus(self.client, name) for name in worker_addresses] # tqdm 検討
|
|
1314
1317
|
self.status.set(OptimizationStatus.SETTING_UP)
|
|
1315
1318
|
self.history = History(self.history_path, self.client)
|
|
1316
1319
|
self.history.init(
|
|
@@ -1332,7 +1335,10 @@ class FEMOpt:
|
|
|
1332
1335
|
# launch monitor
|
|
1333
1336
|
self.monitor_process_future = self.client.submit(
|
|
1334
1337
|
start_monitor_server_forever,
|
|
1335
|
-
self.history,
|
|
1338
|
+
self.history,
|
|
1339
|
+
self.status,
|
|
1340
|
+
worker_addresses,
|
|
1341
|
+
self.worker_status_list,
|
|
1336
1342
|
**self.monitor_server_kwargs, # kwargs
|
|
1337
1343
|
workers=self.monitor_process_worker_name, # if invalid arg,
|
|
1338
1344
|
allow_other_workers=False
|
|
@@ -1446,7 +1452,7 @@ class FEMOpt:
|
|
|
1446
1452
|
sleep(3)
|
|
1447
1453
|
|
|
1448
1454
|
|
|
1449
|
-
def start_monitor_server_forever(history, status, host='localhost', port=8080):
|
|
1450
|
-
monitor = Monitor(history, status)
|
|
1451
|
-
monitor.start_server(host, port)
|
|
1455
|
+
def start_monitor_server_forever(history, status, worker_addresses, worker_status_list, host='localhost', port=8080):
|
|
1456
|
+
monitor = Monitor(history, status, worker_addresses, worker_status_list)
|
|
1457
|
+
monitor.start_server(worker_addresses, worker_status_list, host, port)
|
|
1452
1458
|
return 'Exit monitor server process gracefully'
|
pyfemtet/opt/interface.py
CHANGED
|
@@ -9,7 +9,7 @@ import pandas as pd
|
|
|
9
9
|
import psutil
|
|
10
10
|
from pywintypes import com_error
|
|
11
11
|
from pythoncom import CoInitialize, CoUninitialize
|
|
12
|
-
from win32com.client import constants
|
|
12
|
+
from win32com.client import constants, Dispatch
|
|
13
13
|
from dask.distributed import get_worker
|
|
14
14
|
from femtetutils import util
|
|
15
15
|
|
|
@@ -119,6 +119,7 @@ class FemtetInterface(FEMInterface):
|
|
|
119
119
|
femprj_path=None,
|
|
120
120
|
model_name=None,
|
|
121
121
|
connect_method='auto',
|
|
122
|
+
strict_pid_specify=False,
|
|
122
123
|
**kwargs
|
|
123
124
|
):
|
|
124
125
|
"""Initializes the FemtetInterface.
|
|
@@ -144,12 +145,13 @@ class FemtetInterface(FEMInterface):
|
|
|
144
145
|
self.model_name = model_name
|
|
145
146
|
self.connect_method = connect_method
|
|
146
147
|
|
|
147
|
-
#
|
|
148
|
+
# その他のメンバーの宣言や初期化
|
|
148
149
|
self.Femtet = None
|
|
149
150
|
self.quit_when_destruct = False
|
|
150
151
|
self.connected_method = 'unconnected'
|
|
151
152
|
self.parameters = None
|
|
152
153
|
self.max_api_retry = 3
|
|
154
|
+
self.strict_pid_specify = strict_pid_specify
|
|
153
155
|
|
|
154
156
|
# dask サブプロセスのときは femprj を更新し connect_method を new にする
|
|
155
157
|
try:
|
|
@@ -198,9 +200,12 @@ class FemtetInterface(FEMInterface):
|
|
|
198
200
|
|
|
199
201
|
def _connect_new_femtet(self):
|
|
200
202
|
logger.info('└ Try to launch and connect new Femtet process.')
|
|
201
|
-
|
|
203
|
+
|
|
204
|
+
self.Femtet, _ = launch_and_dispatch_femtet(strict_pid_specify=self.strict_pid_specify)
|
|
205
|
+
|
|
202
206
|
self.connected_method = 'new'
|
|
203
207
|
|
|
208
|
+
|
|
204
209
|
def _connect_existing_femtet(self, pid: int or None = None):
|
|
205
210
|
logger.info('└ Try to connect existing Femtet process.')
|
|
206
211
|
# 既存の Femtet を探して Dispatch する。
|
pyfemtet/opt/monitor.py
CHANGED
|
@@ -76,7 +76,7 @@ def update_scatter_matrix(history, data):
|
|
|
76
76
|
return fig
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def
|
|
79
|
+
def create_home_layout():
|
|
80
80
|
# components の設定
|
|
81
81
|
# https://dash-bootstrap-components.opensource.faculty.ai/docs/components/accordion/
|
|
82
82
|
dummy = html.Div('', id='dummy')
|
|
@@ -131,17 +131,57 @@ OptimizerBase.set_monitor_host() を実行してください。
|
|
|
131
131
|
return layout
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
def create_worker_monitor_layout(
|
|
135
|
+
worker_addresses,
|
|
136
|
+
worker_status_int_list
|
|
137
|
+
):
|
|
138
|
+
from .base import OptimizationStatus
|
|
139
|
+
|
|
140
|
+
interval = dcc.Interval(
|
|
141
|
+
id='worker-status-update-interval',
|
|
142
|
+
interval=1*1000, # in milliseconds
|
|
143
|
+
n_intervals=0,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
rows = [interval]
|
|
147
|
+
for i, (worker_address, status_int) in enumerate(zip(worker_addresses, worker_status_int_list)):
|
|
148
|
+
status_msg = OptimizationStatus.const_to_str(status_int)
|
|
149
|
+
a = dbc.Alert(
|
|
150
|
+
children=[
|
|
151
|
+
f'({worker_address}) ',
|
|
152
|
+
html.P(
|
|
153
|
+
status_msg,
|
|
154
|
+
id=f'worker-status-msg-{i}'
|
|
155
|
+
),
|
|
156
|
+
],
|
|
157
|
+
id=f'worker-status-color-{i}',
|
|
158
|
+
color="primary",
|
|
159
|
+
)
|
|
160
|
+
rows.append(dbc.Row([dbc.Col(a)]))
|
|
161
|
+
|
|
162
|
+
layout = dbc.Container(
|
|
163
|
+
rows,
|
|
164
|
+
fluid=True
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
return layout
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
134
171
|
class Monitor(object):
|
|
135
172
|
|
|
136
|
-
def __init__(self, history, status):
|
|
173
|
+
def __init__(self, history, status, worker_addresses, worker_status_list):
|
|
137
174
|
|
|
138
175
|
from .base import OptimizationStatus
|
|
139
176
|
|
|
140
177
|
# 引数の処理
|
|
141
178
|
self.history = history
|
|
142
179
|
self.status = status
|
|
180
|
+
|
|
181
|
+
# メインスレッドで更新してもらうメンバー
|
|
143
182
|
self.current_status_int = self.status.get()
|
|
144
183
|
self.current_status = self.status.get_text()
|
|
184
|
+
self.current_worker_status_list = [s.get() for s in worker_status_list]
|
|
145
185
|
self.df = self.history.actor_data.copy()
|
|
146
186
|
|
|
147
187
|
# ログファイルの保存場所
|
|
@@ -153,7 +193,8 @@ class Monitor(object):
|
|
|
153
193
|
self.app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
|
154
194
|
|
|
155
195
|
# ページの components と layout の設定
|
|
156
|
-
self.home =
|
|
196
|
+
self.home = create_home_layout()
|
|
197
|
+
self.worker_monitor = create_worker_monitor_layout(worker_addresses, self.current_worker_status_list)
|
|
157
198
|
|
|
158
199
|
# setup sidebar
|
|
159
200
|
# https://dash-bootstrap-components.opensource.faculty.ai/examples/simple-sidebar/
|
|
@@ -186,7 +227,7 @@ class Monitor(object):
|
|
|
186
227
|
dbc.Nav(
|
|
187
228
|
[
|
|
188
229
|
dbc.NavLink("Home", href="/", active="exact"),
|
|
189
|
-
|
|
230
|
+
dbc.NavLink("Workers", href="/page-1", active="exact"),
|
|
190
231
|
],
|
|
191
232
|
vertical=True,
|
|
192
233
|
pills=True,
|
|
@@ -202,8 +243,8 @@ class Monitor(object):
|
|
|
202
243
|
def render_page_content(pathname):
|
|
203
244
|
if pathname == "/": # p0
|
|
204
245
|
return self.home
|
|
205
|
-
|
|
206
|
-
|
|
246
|
+
elif pathname == "/page-1":
|
|
247
|
+
return self.worker_monitor
|
|
207
248
|
# elif pathname == "/page-2":
|
|
208
249
|
# return html.P("Oh cool, this is page 2!")
|
|
209
250
|
# If the user tries to reach a different page, return a 404 message
|
|
@@ -297,10 +338,41 @@ class Monitor(object):
|
|
|
297
338
|
|
|
298
339
|
return max_intervals, button_disable, button_disable, toggle_text, graph, status_children, status_color
|
|
299
340
|
|
|
341
|
+
# worker_monitor のための callback
|
|
342
|
+
@self.app.callback(
|
|
343
|
+
[Output(f'worker-status-msg-{i}', 'children') for i in range(len(worker_addresses))],
|
|
344
|
+
[Output(f'worker-status-color-{i}', 'color') for i in range(len(worker_addresses))],
|
|
345
|
+
[Input('worker-status-update-interval', 'n_intervals'),]
|
|
346
|
+
)
|
|
347
|
+
def update_worker_state(_):
|
|
348
|
+
msgs = [OptimizationStatus.const_to_str(i) for i in self.current_worker_status_list]
|
|
349
|
+
|
|
350
|
+
colors = []
|
|
351
|
+
for status_int in self.current_worker_status_list:
|
|
352
|
+
if status_int == OptimizationStatus.INTERRUPTING:
|
|
353
|
+
colors.append('warning')
|
|
354
|
+
elif status_int == OptimizationStatus.TERMINATED:
|
|
355
|
+
colors.append('dark')
|
|
356
|
+
elif status_int == OptimizationStatus.TERMINATE_ALL:
|
|
357
|
+
colors.append('dark')
|
|
358
|
+
else:
|
|
359
|
+
colors.append('primary')
|
|
360
|
+
|
|
361
|
+
ret = msgs
|
|
362
|
+
ret.extend(colors)
|
|
363
|
+
|
|
364
|
+
return tuple(ret)
|
|
365
|
+
|
|
300
366
|
def _run_server_forever(self, app, host, port):
|
|
301
367
|
app.run(debug=False, host=host, port=port)
|
|
302
368
|
|
|
303
|
-
def start_server(
|
|
369
|
+
def start_server(
|
|
370
|
+
self,
|
|
371
|
+
worker_addresses,
|
|
372
|
+
worker_status_list, # [actor]
|
|
373
|
+
host='localhost',
|
|
374
|
+
port=8080,
|
|
375
|
+
):
|
|
304
376
|
|
|
305
377
|
from .base import OptimizationStatus
|
|
306
378
|
|
|
@@ -339,6 +411,7 @@ class Monitor(object):
|
|
|
339
411
|
self.current_status_int = self.status.get()
|
|
340
412
|
self.current_status = self.status.get_text()
|
|
341
413
|
self.df = self.history.actor_data.copy()
|
|
414
|
+
self.current_worker_status_list = [s.get() for s in worker_status_list]
|
|
342
415
|
|
|
343
416
|
# terminate_all 指令があれば monitor server をホストするプロセスごと終了する
|
|
344
417
|
if self.status.get() == OptimizationStatus.TERMINATE_ALL:
|
|
@@ -8,17 +8,17 @@ pyfemtet/FemtetPJTSample/her_ex40_parametric.py,sha256=w_b48NAvq4zqEYYSk1VxhAstF
|
|
|
8
8
|
pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py,sha256=ci4IDYIYDlSBr4pxlrWvLKw53oq7KF_Ht_AE8Q6D8YM,2370
|
|
9
9
|
pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj,sha256=TYXKt5ZFbsXsEsnmLGX5m-lSBZe8PHT7EFj0IqkrCwM,175152
|
|
10
10
|
pyfemtet/FemtetPJTSample/wat_ex14_parametric.py,sha256=jH8FFtJwm5azqC2mKrs53taA5W0ohftZBCSLfhfCUY4,2258
|
|
11
|
-
pyfemtet/__init__.py,sha256=
|
|
11
|
+
pyfemtet/__init__.py,sha256=eauHvAzEXc0aJ5xQZmFSxwn1EEN1n8i04B7G0Sk7rzI,21
|
|
12
12
|
pyfemtet/_old/_SW_Femtet.py,sha256=555NBjpiEw89uAVWGDgDz_veIGtRv3tIJlVrL3Fz8zk,6044
|
|
13
13
|
pyfemtet/core.py,sha256=PLVvdS3aTUcRKYkGOmkKWRg1r0zkOqPgBhlKRJZ988I,881
|
|
14
|
-
pyfemtet/dispatch_extensions.py,sha256=
|
|
14
|
+
pyfemtet/dispatch_extensions.py,sha256=mJ317UODzh_OafQ-WhkdSjrWpzC_T7rgHqPovH_uL7c,16677
|
|
15
15
|
pyfemtet/logger.py,sha256=JYD0FvzijMS2NvZN7VT7vZA5hqtHEkvS93AHlIMDePw,2507
|
|
16
16
|
pyfemtet/opt/_FemtetWithNX/update_model.py,sha256=t0AB7mKY7rmrI_9stP1-5qhzmugEQ19DnZ4CCrCdTSw,2856
|
|
17
17
|
pyfemtet/opt/__init__.py,sha256=Ax2fKgx9BnTFhUlQH5RVvAxIxGDe8EI_AD38a_8AE14,88
|
|
18
|
-
pyfemtet/opt/base.py,sha256=
|
|
19
|
-
pyfemtet/opt/interface.py,sha256=
|
|
20
|
-
pyfemtet/opt/monitor.py,sha256=
|
|
21
|
-
pyfemtet-0.3.
|
|
22
|
-
pyfemtet-0.3.
|
|
23
|
-
pyfemtet-0.3.
|
|
24
|
-
pyfemtet-0.3.
|
|
18
|
+
pyfemtet/opt/base.py,sha256=G9tDY2SLkh0EgnN2oVCBHWeJwI2PS-2_jStvh0LzRD4,52908
|
|
19
|
+
pyfemtet/opt/interface.py,sha256=90lrE23CKmDPRMNI-qfT9a56mVuvr3Ac_Ju0cZtOnwg,27853
|
|
20
|
+
pyfemtet/opt/monitor.py,sha256=LzspwrrCfrwLcXZ3dT9zziQxD39Q8BJt7sGY5Hm2Hro,16876
|
|
21
|
+
pyfemtet-0.3.6.dist-info/LICENSE,sha256=sVQBhyoglGJUu65-BP3iR6ujORI6YgEU2Qm-V4fGlOA,1485
|
|
22
|
+
pyfemtet-0.3.6.dist-info/METADATA,sha256=KZU7TtzS4TdBbJBOeZXdpf4pQsxneiyTLh1TrUpUyEY,1749
|
|
23
|
+
pyfemtet-0.3.6.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
24
|
+
pyfemtet-0.3.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|