PyFemtet 0.3.5__tar.gz → 0.3.7__tar.gz
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.
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/PKG-INFO +1 -1
- pyfemtet-0.3.7/pyfemtet/__init__.py +1 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/base.py +14 -7
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/interface.py +2 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/monitor.py +80 -7
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyproject.toml +1 -1
- pyfemtet-0.3.5/pyfemtet/__init__.py +0 -1
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/LICENSE +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/README.md +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.femprj +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.prt +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/gau_ex08_parametric.femprj +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/gau_ex08_parametric.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/her_ex40_parametric.femprj +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/her_ex40_parametric.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/wat_ex14_parametric.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/_old/_SW_Femtet.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/core.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/dispatch_extensions.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/logger.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/_FemtetWithNX/update_model.py +0 -0
- {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/__init__.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.7"
|
|
@@ -217,7 +217,7 @@ class Function:
|
|
|
217
217
|
# Femtet 特有の処理
|
|
218
218
|
if isinstance(fem, FemtetInterface):
|
|
219
219
|
args = (fem.Femtet, *args)
|
|
220
|
-
return self.fun(*args, **self.kwargs)
|
|
220
|
+
return float(self.fun(*args, **self.kwargs))
|
|
221
221
|
|
|
222
222
|
def _restore_constants(self):
|
|
223
223
|
"""Helper function for parallelize Femtet."""
|
|
@@ -280,7 +280,7 @@ class Objective(Function):
|
|
|
280
280
|
|
|
281
281
|
ret = symlog(ret)
|
|
282
282
|
|
|
283
|
-
return ret
|
|
283
|
+
return float(ret)
|
|
284
284
|
|
|
285
285
|
|
|
286
286
|
class Constraint(Function):
|
|
@@ -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,8 @@ 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
|
-
|
|
1299
|
+
if len(subprocess_indices)>0:
|
|
1300
|
+
assert max(subprocess_indices) <= len(worker_addresses)-1, f'コア数{len(worker_addresses)}は不足しています。'
|
|
1297
1301
|
worker_addresses = worker_addresses[:len(range(n_parallel))] # TODO: ノードごとに適度に振り分ける
|
|
1298
1302
|
if not self.opt.is_cluster:
|
|
1299
1303
|
worker_addresses[0] = 'Main'
|
|
@@ -1332,7 +1336,10 @@ class FEMOpt:
|
|
|
1332
1336
|
# launch monitor
|
|
1333
1337
|
self.monitor_process_future = self.client.submit(
|
|
1334
1338
|
start_monitor_server_forever,
|
|
1335
|
-
self.history,
|
|
1339
|
+
self.history,
|
|
1340
|
+
self.status,
|
|
1341
|
+
worker_addresses,
|
|
1342
|
+
self.worker_status_list,
|
|
1336
1343
|
**self.monitor_server_kwargs, # kwargs
|
|
1337
1344
|
workers=self.monitor_process_worker_name, # if invalid arg,
|
|
1338
1345
|
allow_other_workers=False
|
|
@@ -1446,7 +1453,7 @@ class FEMOpt:
|
|
|
1446
1453
|
sleep(3)
|
|
1447
1454
|
|
|
1448
1455
|
|
|
1449
|
-
def start_monitor_server_forever(history, status, host='localhost', port=8080):
|
|
1450
|
-
monitor = Monitor(history, status)
|
|
1451
|
-
monitor.start_server(host, port)
|
|
1456
|
+
def start_monitor_server_forever(history, status, worker_addresses, worker_status_list, host='localhost', port=8080):
|
|
1457
|
+
monitor = Monitor(history, status, worker_addresses, worker_status_list)
|
|
1458
|
+
monitor.start_server(worker_addresses, worker_status_list, host, port)
|
|
1452
1459
|
return 'Exit monitor server process gracefully'
|
|
@@ -128,6 +128,7 @@ class FemtetInterface(FEMInterface):
|
|
|
128
128
|
femprj_path (str or None, optional): The path to the .femprj file. Defaults to None.
|
|
129
129
|
model_name (str or None, optional): The name of the analysis model. Defaults to None.
|
|
130
130
|
connect_method (str, optional): The connection method to use. Can be 'new', 'existing', or 'auto'. Defaults to 'auto'.
|
|
131
|
+
strict_pid_specify (bool): If True and connect_method=='new', search launched Femtet process strictly based on its process id. This option requires large overhead time. So It is recommended to set False in large n_parallel.
|
|
131
132
|
|
|
132
133
|
Tip:
|
|
133
134
|
If you search for information about the method to connect python and Femtet, see :func:`connect_femtet`.
|
|
@@ -176,6 +177,7 @@ class FemtetInterface(FEMInterface):
|
|
|
176
177
|
super().__init__(
|
|
177
178
|
femprj_path=self.femprj_path,
|
|
178
179
|
model_name=self.model_name,
|
|
180
|
+
strict_pid_specify=self.strict_pid_specify,
|
|
179
181
|
**kwargs
|
|
180
182
|
)
|
|
181
183
|
|
|
@@ -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:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "pyfemtet"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.7" # ignored by versioning plugin
|
|
4
4
|
description = "Design parameter optimization using Femtet."
|
|
5
5
|
authors = ["kazuma.naito <kazuma.naito@murata.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.5"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|