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.
Files changed (25) hide show
  1. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/PKG-INFO +1 -1
  2. pyfemtet-0.3.7/pyfemtet/__init__.py +1 -0
  3. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/base.py +14 -7
  4. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/interface.py +2 -0
  5. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/monitor.py +80 -7
  6. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyproject.toml +1 -1
  7. pyfemtet-0.3.5/pyfemtet/__init__.py +0 -1
  8. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/LICENSE +0 -0
  9. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/README.md +0 -0
  10. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.femprj +0 -0
  11. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.prt +0 -0
  12. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.py +0 -0
  13. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/gau_ex08_parametric.femprj +0 -0
  14. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/gau_ex08_parametric.py +0 -0
  15. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/her_ex40_parametric.femprj +0 -0
  16. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/her_ex40_parametric.py +0 -0
  17. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py +0 -0
  18. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj +0 -0
  19. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/FemtetPJTSample/wat_ex14_parametric.py +0 -0
  20. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/_old/_SW_Femtet.py +0 -0
  21. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/core.py +0 -0
  22. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/dispatch_extensions.py +0 -0
  23. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/logger.py +0 -0
  24. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/_FemtetWithNX/update_model.py +0 -0
  25. {pyfemtet-0.3.5 → pyfemtet-0.3.7}/pyfemtet/opt/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyfemtet
3
- Version: 0.3.5
3
+ Version: 0.3.7
4
4
  Summary: Design parameter optimization using Femtet.
5
5
  Home-page: https://github.com/pyfemtet/pyfemtet
6
6
  License: BSD-3-Clause
@@ -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
- assert max(subprocess_indices) <= len(worker_addresses)-1, f'コア数{len(worker_addresses)}は不足しています。'
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, self.status, # args
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 setup_home():
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 = setup_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
- # dbc.NavLink("ペアプロット", href="/page-1", active="exact"),
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
- # elif pathname == "/page-1":
206
- # return self.multi_pairplot_layout
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(self, host='localhost', port=8080):
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.5" # ignored by versioning plugin
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