pyfemtet 0.4.3__py3-none-any.whl → 0.4.4__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/opt/_femopt.py +48 -16
- pyfemtet/opt/_femopt_core.py +14 -7
- pyfemtet/opt/interface/_femtet.py +31 -17
- pyfemtet/opt/interface/_femtet_parametric.py +72 -0
- pyfemtet/opt/opt/_base.py +12 -3
- pyfemtet/opt/visualization/_monitor.py +2 -2
- pyfemtet-0.4.4.dist-info/METADATA +97 -0
- {pyfemtet-0.4.3.dist-info → pyfemtet-0.4.4.dist-info}/RECORD +12 -11
- pyfemtet-0.4.3.dist-info/METADATA +0 -48
- {pyfemtet-0.4.3.dist-info → pyfemtet-0.4.4.dist-info}/LICENSE +0 -0
- {pyfemtet-0.4.3.dist-info → pyfemtet-0.4.4.dist-info}/WHEEL +0 -0
- {pyfemtet-0.4.3.dist-info → pyfemtet-0.4.4.dist-info}/entry_points.txt +0 -0
pyfemtet/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.4.
|
|
1
|
+
__version__ = "0.4.4"
|
pyfemtet/opt/_femopt.py
CHANGED
|
@@ -81,6 +81,7 @@ class FEMOpt:
|
|
|
81
81
|
self.monitor_process_future = None
|
|
82
82
|
self.monitor_server_kwargs = dict()
|
|
83
83
|
self.monitor_process_worker_name = None
|
|
84
|
+
self._is_error_exit = False
|
|
84
85
|
|
|
85
86
|
# multiprocess 時に pickle できないオブジェクト参照の削除
|
|
86
87
|
def __getstate__(self):
|
|
@@ -328,12 +329,27 @@ class FEMOpt:
|
|
|
328
329
|
subprocess_indices = list(range(n_parallel))
|
|
329
330
|
worker_addresses = list(self.client.nthreads().keys())
|
|
330
331
|
|
|
332
|
+
# worker が足りない場合はエラー
|
|
333
|
+
if n_parallel > len(worker_addresses):
|
|
334
|
+
raise RuntimeError(f'n_parallel({n_parallel}) > n_workers({len(worker_addresses)}). Worker 数が不足しています。')
|
|
335
|
+
|
|
336
|
+
# worker が多い場合は閉じる
|
|
337
|
+
if n_parallel < len(worker_addresses):
|
|
338
|
+
used_worker_addresses = worker_addresses[:n_parallel] # 前から順番に選ぶ:CPU の早い / メモリの多い順に並べることが望ましい
|
|
339
|
+
unused_worker_addresses = worker_addresses[n_parallel:]
|
|
340
|
+
self.client.retire_workers(unused_worker_addresses, close_workers=True)
|
|
341
|
+
worker_addresses = used_worker_addresses
|
|
342
|
+
|
|
331
343
|
# monitor worker の設定
|
|
332
344
|
logger.info('Launching monitor server. This may take a few seconds.')
|
|
333
|
-
self.monitor_process_worker_name = datetime.datetime.now().strftime("Monitor
|
|
345
|
+
self.monitor_process_worker_name = datetime.datetime.now().strftime("Monitor%Y%m%d%H%M%S")
|
|
334
346
|
current_n_workers = len(self.client.nthreads().keys())
|
|
335
|
-
from
|
|
336
|
-
|
|
347
|
+
from subprocess import Popen
|
|
348
|
+
import sys
|
|
349
|
+
Popen(
|
|
350
|
+
f'{sys.executable} -m dask worker {self.client.scheduler.address} --nthreads 1 --nworkers 1 --name {self.monitor_process_worker_name} --no-nanny',
|
|
351
|
+
shell=True
|
|
352
|
+
)
|
|
337
353
|
|
|
338
354
|
# monitor 用 worker が増えるまで待つ
|
|
339
355
|
self.client.wait_for_workers(n_workers=current_n_workers + 1)
|
|
@@ -357,12 +373,17 @@ class FEMOpt:
|
|
|
357
373
|
# Femtet 特有の処理
|
|
358
374
|
metadata = None
|
|
359
375
|
if isinstance(self.fem, FemtetInterface):
|
|
376
|
+
# 結果 csv に記載する femprj に関する情報
|
|
360
377
|
metadata = json.dumps(
|
|
361
378
|
dict(
|
|
362
379
|
femprj_path=self.fem.original_femprj_path,
|
|
363
380
|
model_name=self.fem.model_name
|
|
364
381
|
)
|
|
365
382
|
)
|
|
383
|
+
# Femtet の parametric 設定を目的関数に用いるかどうか
|
|
384
|
+
if self.fem.use_parametric_as_objective:
|
|
385
|
+
from pyfemtet.opt.interface._femtet_parametric import add_parametric_results_as_objectives
|
|
386
|
+
add_parametric_results_as_objectives(self)
|
|
366
387
|
|
|
367
388
|
# actor の設定
|
|
368
389
|
self.status = OptimizationStatus(self.client)
|
|
@@ -389,7 +410,7 @@ class FEMOpt:
|
|
|
389
410
|
# kwargs
|
|
390
411
|
**self.monitor_server_kwargs,
|
|
391
412
|
# kwargs of submit
|
|
392
|
-
workers=self.monitor_process_worker_name,
|
|
413
|
+
workers=self.monitor_process_worker_name,
|
|
393
414
|
allow_other_workers=False
|
|
394
415
|
)
|
|
395
416
|
|
|
@@ -452,10 +473,13 @@ class FEMOpt:
|
|
|
452
473
|
t_save_history.start()
|
|
453
474
|
|
|
454
475
|
# 終了を待つ
|
|
455
|
-
|
|
476
|
+
local_opt_crashed = False
|
|
477
|
+
opt_crashed_list = self.client.gather(calc_futures)
|
|
456
478
|
if not self.opt.is_cluster: # 既存の fem を使っているならそれも待つ
|
|
457
479
|
if t_main is not None:
|
|
458
480
|
t_main.join()
|
|
481
|
+
local_opt_crashed = self.opt._is_error_exit
|
|
482
|
+
opt_crashed_list.append(local_opt_crashed)
|
|
459
483
|
self.status.set(OptimizationStatus.TERMINATED)
|
|
460
484
|
end = time()
|
|
461
485
|
|
|
@@ -465,6 +489,13 @@ class FEMOpt:
|
|
|
465
489
|
logger.info(f'計算が終了しました. 実行時間は {int(end - start)} 秒でした。ウィンドウを閉じると終了します.')
|
|
466
490
|
logger.info(f'結果は{self.history.path}を確認してください.')
|
|
467
491
|
|
|
492
|
+
# ひとつでも crashed ならばフラグを立てる
|
|
493
|
+
if any(opt_crashed_list):
|
|
494
|
+
self._is_error_exit = True
|
|
495
|
+
|
|
496
|
+
return self.history.local_data
|
|
497
|
+
|
|
498
|
+
|
|
468
499
|
def terminate_all(self):
|
|
469
500
|
"""Try to terminate all launched processes.
|
|
470
501
|
|
|
@@ -476,7 +507,10 @@ class FEMOpt:
|
|
|
476
507
|
sleep(1)
|
|
477
508
|
|
|
478
509
|
# terminate monitor process
|
|
479
|
-
self.
|
|
510
|
+
if self._is_error_exit:
|
|
511
|
+
self.status.set(OptimizationStatus.CRASHED)
|
|
512
|
+
else:
|
|
513
|
+
self.status.set(OptimizationStatus.TERMINATE_ALL)
|
|
480
514
|
logger.info(self.monitor_process_future.result())
|
|
481
515
|
sleep(1)
|
|
482
516
|
|
|
@@ -514,22 +548,20 @@ class FEMOpt:
|
|
|
514
548
|
else:
|
|
515
549
|
logger.warn('Monitor process worker not found.')
|
|
516
550
|
|
|
517
|
-
# close scheduler, other workers(, cluster)
|
|
518
|
-
self.client.close()
|
|
519
|
-
while self.client.scheduler is not None:
|
|
520
|
-
sleep(1)
|
|
521
|
-
logger.info('Terminate client.')
|
|
522
|
-
|
|
523
551
|
# close FEM (if specified to quit when deconstruct)
|
|
524
552
|
del self.fem
|
|
525
553
|
logger.info('Terminate FEM.')
|
|
554
|
+
sleep(1)
|
|
526
555
|
|
|
527
|
-
#
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
logger.info('Terminate all relative processes.')
|
|
556
|
+
# close scheduler, other workers(, cluster)
|
|
557
|
+
self.client.shutdown()
|
|
558
|
+
logger.info('Terminate all relative processes.')
|
|
531
559
|
sleep(3)
|
|
532
560
|
|
|
561
|
+
# if optimization was crashed, raise Exception
|
|
562
|
+
if self._is_error_exit:
|
|
563
|
+
raise RuntimeError('At least 1 of optimization processes have been crashed. See console log.')
|
|
564
|
+
|
|
533
565
|
|
|
534
566
|
def _start_monitor_server(
|
|
535
567
|
history,
|
pyfemtet/opt/_femopt_core.py
CHANGED
|
@@ -7,6 +7,7 @@ import datetime
|
|
|
7
7
|
import inspect
|
|
8
8
|
import ast
|
|
9
9
|
import csv
|
|
10
|
+
import ctypes
|
|
10
11
|
|
|
11
12
|
# 3rd-party
|
|
12
13
|
import numpy as np
|
|
@@ -197,9 +198,12 @@ class Function:
|
|
|
197
198
|
|
|
198
199
|
# serializable でない COM 定数を parallelize するため
|
|
199
200
|
# COM 定数を一度 _Scapegoat 型のオブジェクトにする
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
# ParametricIF で使う dll 関数は _FuncPtr 型であって __globals__ を持たないが、
|
|
202
|
+
# これは絶対に constants を持たないので単に無視すればよい。
|
|
203
|
+
if not isinstance(fun, ctypes._CFuncPtr):
|
|
204
|
+
for varname in fun.__globals__:
|
|
205
|
+
if isinstance(fun.__globals__[varname], Constants):
|
|
206
|
+
fun.__globals__[varname] = _Scapegoat()
|
|
203
207
|
|
|
204
208
|
self.fun = fun
|
|
205
209
|
self.name = name
|
|
@@ -224,10 +228,11 @@ class Function:
|
|
|
224
228
|
def _restore_constants(self):
|
|
225
229
|
"""Helper function for parallelize Femtet."""
|
|
226
230
|
fun = self.fun
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if
|
|
230
|
-
fun.__globals__[varname]
|
|
231
|
+
if not isinstance(fun, ctypes._CFuncPtr):
|
|
232
|
+
for varname in fun.__globals__:
|
|
233
|
+
if isinstance(fun.__globals__[varname], _Scapegoat):
|
|
234
|
+
if not fun.__globals__[varname]._ignore_when_restore_constants:
|
|
235
|
+
fun.__globals__[varname] = constants
|
|
231
236
|
|
|
232
237
|
|
|
233
238
|
class Objective(Function):
|
|
@@ -691,6 +696,7 @@ class OptimizationStatus:
|
|
|
691
696
|
RUNNING = 30
|
|
692
697
|
INTERRUPTING = 40
|
|
693
698
|
TERMINATED = 50
|
|
699
|
+
CRASHED = 55
|
|
694
700
|
TERMINATE_ALL = 60
|
|
695
701
|
|
|
696
702
|
def __init__(self, client, name='entire'):
|
|
@@ -712,6 +718,7 @@ class OptimizationStatus:
|
|
|
712
718
|
if status_const == cls.INTERRUPTING: return 'Interrupting'
|
|
713
719
|
if status_const == cls.TERMINATED: return 'Terminated'
|
|
714
720
|
if status_const == cls.TERMINATE_ALL: return 'Terminate_all'
|
|
721
|
+
if status_const == cls.CRASHED: return 'Crashed'
|
|
715
722
|
|
|
716
723
|
def set(self, status_const):
|
|
717
724
|
"""Set optimization status."""
|
|
@@ -60,6 +60,7 @@ class FemtetInterface(FEMInterface):
|
|
|
60
60
|
strictly_pid_specify=True,
|
|
61
61
|
allow_without_project=False,
|
|
62
62
|
open_result_with_gui=True,
|
|
63
|
+
use_parametric_as_objective=False,
|
|
63
64
|
**kwargs # 継承されたクラスからの引数
|
|
64
65
|
):
|
|
65
66
|
|
|
@@ -85,6 +86,7 @@ class FemtetInterface(FEMInterface):
|
|
|
85
86
|
self.parameters = None
|
|
86
87
|
self.max_api_retry = 3
|
|
87
88
|
self.strictly_pid_specify = strictly_pid_specify
|
|
89
|
+
self.use_parametric_as_objective = use_parametric_as_objective
|
|
88
90
|
|
|
89
91
|
# dask サブプロセスのときは femprj を更新し connect_method を new にする
|
|
90
92
|
try:
|
|
@@ -111,6 +113,7 @@ class FemtetInterface(FEMInterface):
|
|
|
111
113
|
femprj_path=self.femprj_path,
|
|
112
114
|
model_name=self.model_name,
|
|
113
115
|
open_result_with_gui=self.open_result_with_gui,
|
|
116
|
+
use_parametric_as_objective=self.use_parametric_as_objective,
|
|
114
117
|
**kwargs
|
|
115
118
|
)
|
|
116
119
|
|
|
@@ -203,7 +206,7 @@ class FemtetInterface(FEMInterface):
|
|
|
203
206
|
def _call_femtet_api(
|
|
204
207
|
self,
|
|
205
208
|
fun,
|
|
206
|
-
|
|
209
|
+
return_value_if_failed,
|
|
207
210
|
if_error,
|
|
208
211
|
error_message,
|
|
209
212
|
is_Gaudi_method=False,
|
|
@@ -219,7 +222,7 @@ class FemtetInterface(FEMInterface):
|
|
|
219
222
|
----------
|
|
220
223
|
fun : Callable
|
|
221
224
|
Femtet API
|
|
222
|
-
|
|
225
|
+
return_value_if_failed : Any
|
|
223
226
|
API が失敗した時の戻り値
|
|
224
227
|
if_error : Type
|
|
225
228
|
エラーが発生していたときに送出したい Exception
|
|
@@ -278,9 +281,9 @@ class FemtetInterface(FEMInterface):
|
|
|
278
281
|
except com_error:
|
|
279
282
|
# パターン 2 エラーが生じたことは確定なのでエラーが起こるよう returns を作る
|
|
280
283
|
if ret_for_check_idx is None:
|
|
281
|
-
returns =
|
|
284
|
+
returns = return_value_if_failed
|
|
282
285
|
else:
|
|
283
|
-
returns = [
|
|
286
|
+
returns = [return_value_if_failed] * (ret_for_check_idx + 1)
|
|
284
287
|
logger.debug(' ' * print_indent + f'Femtet API result:{returns}')
|
|
285
288
|
|
|
286
289
|
# チェックすべき値の抽出
|
|
@@ -290,7 +293,7 @@ class FemtetInterface(FEMInterface):
|
|
|
290
293
|
ret_for_check = returns[ret_for_check_idx]
|
|
291
294
|
|
|
292
295
|
# エラーのない場合は戻り値を return する
|
|
293
|
-
if ret_for_check !=
|
|
296
|
+
if ret_for_check != return_value_if_failed:
|
|
294
297
|
return returns
|
|
295
298
|
|
|
296
299
|
# エラーがある場合は Femtet の生死をチェックし,
|
|
@@ -324,7 +327,7 @@ class FemtetInterface(FEMInterface):
|
|
|
324
327
|
logger.info(' ' * print_indent + f'Femtet が回復されました。コマンド {fun.__name__} を再試行します。')
|
|
325
328
|
return self._call_femtet_api(
|
|
326
329
|
fun,
|
|
327
|
-
|
|
330
|
+
return_value_if_failed,
|
|
328
331
|
if_error,
|
|
329
332
|
error_message,
|
|
330
333
|
is_Gaudi_method,
|
|
@@ -453,7 +456,7 @@ class FemtetInterface(FEMInterface):
|
|
|
453
456
|
# Femtet の設計変数の更新
|
|
454
457
|
existing_variable_names = self._call_femtet_api(
|
|
455
458
|
fun=self.Femtet.GetVariableNames_py,
|
|
456
|
-
|
|
459
|
+
return_value_if_failed=False, # 意味がない
|
|
457
460
|
if_error=ModelError, # 生きてるのに失敗した場合
|
|
458
461
|
error_message=f'GetVariableNames_py に失敗しました。',
|
|
459
462
|
is_Gaudi_method=True,
|
|
@@ -474,7 +477,7 @@ class FemtetInterface(FEMInterface):
|
|
|
474
477
|
if name in existing_variable_names:
|
|
475
478
|
self._call_femtet_api(
|
|
476
479
|
fun=self.Femtet.UpdateVariable,
|
|
477
|
-
|
|
480
|
+
return_value_if_failed=False,
|
|
478
481
|
if_error=ModelError, # 生きてるのに失敗した場合
|
|
479
482
|
error_message=f'変数の更新に失敗しました:変数{name}, 値{value}',
|
|
480
483
|
is_Gaudi_method=True,
|
|
@@ -493,7 +496,7 @@ class FemtetInterface(FEMInterface):
|
|
|
493
496
|
value = row['value']
|
|
494
497
|
self._call_femtet_api(
|
|
495
498
|
fun=self.Femtet.UpdateVariable,
|
|
496
|
-
|
|
499
|
+
return_value_if_failed=False,
|
|
497
500
|
if_error=ModelError, # 生きてるのに失敗した場合
|
|
498
501
|
error_message=f'変数の更新に失敗しました:変数{name}, 値{value}',
|
|
499
502
|
is_Gaudi_method=True,
|
|
@@ -546,14 +549,25 @@ class FemtetInterface(FEMInterface):
|
|
|
546
549
|
is_Gaudi_method=True,
|
|
547
550
|
)
|
|
548
551
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
self.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
552
|
+
if self.use_parametric_as_objective:
|
|
553
|
+
from pyfemtet.opt.interface._femtet_parametric import solve_via_parametric_dll
|
|
554
|
+
self._call_femtet_api(
|
|
555
|
+
fun=solve_via_parametric_dll,
|
|
556
|
+
return_value_if_failed=False,
|
|
557
|
+
if_error=SolveError,
|
|
558
|
+
error_message='パラメトリック解析を用いたソルブに失敗しました',
|
|
559
|
+
is_Gaudi_method=True,
|
|
560
|
+
args=(self.Femtet,),
|
|
561
|
+
)
|
|
562
|
+
else:
|
|
563
|
+
# # ソルブする
|
|
564
|
+
self._call_femtet_api(
|
|
565
|
+
self.Femtet.Solve,
|
|
566
|
+
False,
|
|
567
|
+
SolveError,
|
|
568
|
+
'ソルブに失敗しました',
|
|
569
|
+
is_Gaudi_method=True,
|
|
570
|
+
)
|
|
557
571
|
|
|
558
572
|
# 次に呼ばれるはずのユーザー定義コスト関数の記述を簡単にするため先に解析結果を開いておく
|
|
559
573
|
self._call_femtet_api(
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from pyfemtet.dispatch_extensions import _get_pid
|
|
2
|
+
|
|
3
|
+
import winreg
|
|
4
|
+
import ctypes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _get_dll(Femtet):
|
|
8
|
+
femtet_major_version = _get_femtet_major_version(Femtet)
|
|
9
|
+
dll_path = _get_parametric_dll_path(femtet_major_version)
|
|
10
|
+
return ctypes.cdll.LoadLibrary(dll_path)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_femtet_major_version(Femtet):
|
|
14
|
+
from pyfemtet.core import _version
|
|
15
|
+
version_int8 = _version(Femtet=Femtet)
|
|
16
|
+
return str(version_int8)[0:4]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _get_parametric_dll_path(femtet_major_version) -> str:
|
|
20
|
+
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\FemtetInfo\InstallVersion\x64')
|
|
21
|
+
_, nValues, _ = winreg.QueryInfoKey(key)
|
|
22
|
+
for i in range(nValues):
|
|
23
|
+
name, data, _ = winreg.EnumValue(key, i)
|
|
24
|
+
if name == str(femtet_major_version):
|
|
25
|
+
winreg.CloseKey(key)
|
|
26
|
+
import os
|
|
27
|
+
dll_path = os.path.join(data, 'Program', 'ParametricIF.dll')
|
|
28
|
+
return dll_path
|
|
29
|
+
# ここまで来ていたら失敗
|
|
30
|
+
winreg.CloseKey(key)
|
|
31
|
+
raise RuntimeError('パラメトリック解析機能へのアクセスに失敗しました')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _get_dll_with_set_femtet(Femtet):
|
|
35
|
+
dll = _get_dll(Femtet)
|
|
36
|
+
pid = _get_pid(Femtet.hWnd)
|
|
37
|
+
dll.SetCurrentFemtet.restype = ctypes.c_bool
|
|
38
|
+
dll.SetCurrentFemtet(pid)
|
|
39
|
+
return dll
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def add_parametric_results_as_objectives(femopt) -> bool:
|
|
43
|
+
# load dll and set target femtet
|
|
44
|
+
dll = _get_dll_with_set_femtet(femopt.fem.Femtet)
|
|
45
|
+
|
|
46
|
+
# get objective names
|
|
47
|
+
dll.GetPrmnResult.restype = ctypes.c_int
|
|
48
|
+
n = dll.GetPrmnResult()
|
|
49
|
+
for i in range(n):
|
|
50
|
+
# objective name
|
|
51
|
+
dll.GetPrmResultName.restype = ctypes.c_char_p
|
|
52
|
+
result = dll.GetPrmResultName(i)
|
|
53
|
+
name = result.decode('mbcs')
|
|
54
|
+
# objective value function
|
|
55
|
+
femopt.add_objective(_parametric_objective, name, args=(i,))
|
|
56
|
+
return True # ここまで来たら成功
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _parametric_objective(Femtet, parametric_result_index):
|
|
60
|
+
# load dll and set target femtet
|
|
61
|
+
dll = _get_dll_with_set_femtet(Femtet)
|
|
62
|
+
dll.GetPrmResult.restype = ctypes.c_double
|
|
63
|
+
return dll.GetPrmResult(parametric_result_index)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def solve_via_parametric_dll(Femtet) -> bool:
|
|
67
|
+
# load dll and set target femtet
|
|
68
|
+
dll = _get_dll_with_set_femtet(Femtet)
|
|
69
|
+
# solve
|
|
70
|
+
dll.PrmCalcExecute.restype = ctypes.c_bool
|
|
71
|
+
succeed = dll.PrmCalcExecute()
|
|
72
|
+
return succeed # 成功した場合はTRUE、失敗した場合はFALSEを返す
|
pyfemtet/opt/opt/_base.py
CHANGED
|
@@ -57,6 +57,7 @@ class AbstractOptimizer(ABC):
|
|
|
57
57
|
self.n_trials = None
|
|
58
58
|
self.is_cluster = False
|
|
59
59
|
self.subprocess_idx = None
|
|
60
|
+
self._is_error_exit = False
|
|
60
61
|
|
|
61
62
|
def f(self, x):
|
|
62
63
|
"""Get x, update fem analysis, return objectives (and constraints)."""
|
|
@@ -141,7 +142,8 @@ class AbstractOptimizer(ABC):
|
|
|
141
142
|
def _finalize(self):
|
|
142
143
|
"""Destruct fem and set worker status."""
|
|
143
144
|
del self.fem
|
|
144
|
-
self.worker_status.
|
|
145
|
+
if not self.worker_status.get() == OptimizationStatus.CRASHED:
|
|
146
|
+
self.worker_status.set(OptimizationStatus.TERMINATED)
|
|
145
147
|
|
|
146
148
|
def _run(
|
|
147
149
|
self,
|
|
@@ -149,7 +151,7 @@ class AbstractOptimizer(ABC):
|
|
|
149
151
|
worker_status_list,
|
|
150
152
|
wait_setup,
|
|
151
153
|
skip_set_fem=False,
|
|
152
|
-
) ->
|
|
154
|
+
) -> bool:
|
|
153
155
|
|
|
154
156
|
# 自分の worker_status の取得
|
|
155
157
|
self.subprocess_idx = subprocess_idx
|
|
@@ -186,10 +188,17 @@ class AbstractOptimizer(ABC):
|
|
|
186
188
|
# run and finalize
|
|
187
189
|
try:
|
|
188
190
|
self.run()
|
|
191
|
+
except Exception as e:
|
|
192
|
+
logger.error("================================")
|
|
193
|
+
logger.error("An unexpected error has occured!")
|
|
194
|
+
logger.error("================================")
|
|
195
|
+
logger.error(e)
|
|
196
|
+
self._is_error_exit = True
|
|
197
|
+
self.worker_status.set(OptimizationStatus.CRASHED)
|
|
189
198
|
finally:
|
|
190
199
|
self._finalize()
|
|
191
200
|
|
|
192
|
-
return
|
|
201
|
+
return self._is_error_exit
|
|
193
202
|
|
|
194
203
|
@abstractmethod
|
|
195
204
|
def run(self) -> None:
|
|
@@ -922,8 +922,8 @@ class ProcessMonitorAppWorkerPage:
|
|
|
922
922
|
colors.append('warning')
|
|
923
923
|
elif status_int == OptimizationStatus.TERMINATED:
|
|
924
924
|
colors.append('dark')
|
|
925
|
-
elif status_int == OptimizationStatus.
|
|
926
|
-
colors.append('
|
|
925
|
+
elif status_int == OptimizationStatus.CRASHED:
|
|
926
|
+
colors.append('danger')
|
|
927
927
|
else:
|
|
928
928
|
colors.append('primary')
|
|
929
929
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyfemtet
|
|
3
|
+
Version: 0.4.4
|
|
4
|
+
Summary: Design parameter optimization using Femtet.
|
|
5
|
+
Home-page: https://github.com/pyfemtet/pyfemtet
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Author: kazuma.naito
|
|
8
|
+
Author-email: kazuma.naito@murata.com
|
|
9
|
+
Requires-Python: >=3.9.3,<3.13
|
|
10
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Dist: botorch (>=0.9.5) ; python_version >= "3.12" and python_version < "3.13"
|
|
16
|
+
Requires-Dist: botorch (>=0.9.5,<0.10.0) ; python_version < "3.12"
|
|
17
|
+
Requires-Dist: colorlog (>=6.8.0,<7.0.0)
|
|
18
|
+
Requires-Dist: dash (>=2.14.2,<3.0.0)
|
|
19
|
+
Requires-Dist: dash-bootstrap-components (>=1.5.0,<2.0.0)
|
|
20
|
+
Requires-Dist: dask (>=2023.12.1,<2024.0.0)
|
|
21
|
+
Requires-Dist: distributed (>=2023.12.1,<2024.0.0)
|
|
22
|
+
Requires-Dist: femtetutils (>=1.0.0,<2.0.0)
|
|
23
|
+
Requires-Dist: numpy (>=1.26.2,<2.0.0)
|
|
24
|
+
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
|
25
|
+
Requires-Dist: optuna (>=3.4.0,<4.0.0)
|
|
26
|
+
Requires-Dist: optuna-integration (>=3.6.0,<4.0.0)
|
|
27
|
+
Requires-Dist: pandas (>=2.1.3,<3.0.0)
|
|
28
|
+
Requires-Dist: plotly (>=5.18.0,<6.0.0)
|
|
29
|
+
Requires-Dist: psutil (>=5.9.6,<6.0.0)
|
|
30
|
+
Requires-Dist: pywin32 (>=306,<307)
|
|
31
|
+
Requires-Dist: scipy (>=1.11.4,<2.0.0)
|
|
32
|
+
Requires-Dist: tqdm (>=4.66.1,<5.0.0)
|
|
33
|
+
Project-URL: Repository, https://github.com/pyfemtet/pyfemtet
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Welcome! PyFemtet is the extension package for Femtet.
|
|
37
|
+
|
|
38
|
+
## Main Features
|
|
39
|
+
|
|
40
|
+
<img src="img/pyfemtet_conceptual_diagram.png" width="450">
|
|
41
|
+
|
|
42
|
+
> [!NOTE]
|
|
43
|
+
> For details, see the documentation of "Related Pages" section.
|
|
44
|
+
|
|
45
|
+
### Design Parameter Optimization
|
|
46
|
+
- Single or multiple objective optimization
|
|
47
|
+
- Progress monitor GUI
|
|
48
|
+
- Parallel computation with controling multiple Femtet processes
|
|
49
|
+
- Result output in easy-to-analyze csv format for Excel and other tools
|
|
50
|
+
|
|
51
|
+
### Dispatch Extensions
|
|
52
|
+
- Create `CFemtet` object with process ID specification
|
|
53
|
+
|
|
54
|
+
## Related Pages
|
|
55
|
+
|
|
56
|
+
- Femtet Website: https://www.muratasoftware.com/
|
|
57
|
+
- Documentation (English): https://pyfemtet.readthedocs.io/en/stable/
|
|
58
|
+
- ドキュメント(日本語): https://pyfemtet.readthedocs.io/jp/stable/
|
|
59
|
+
- Source code: https://github.com/pyfemtet/pyfemtet
|
|
60
|
+
- Bug reports: https://github.com/pyfemtet/pyfemtet/issues
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## Getting Started
|
|
64
|
+
|
|
65
|
+
> [!NOTE]
|
|
66
|
+
> Currently Femtet and `pyfemtet` supports **Windows only**.
|
|
67
|
+
|
|
68
|
+
### 1. Install Femtet
|
|
69
|
+
|
|
70
|
+
- Access [Murata Software Website](https://www.muratasoftware.com/) and get **Femtet trial version** or purchase a lisence.
|
|
71
|
+
- Get installer and launch it.
|
|
72
|
+
- **Run 'EnableMacros'** from the start menu.
|
|
73
|
+
> [!NOTE]
|
|
74
|
+
> This procedure requires administrator privileges.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### 2. Install PyFemtet
|
|
78
|
+
|
|
79
|
+
> [!NOTE]
|
|
80
|
+
> The commands on this section are for `CMD` or `PowerShell` on with `py launcher`.
|
|
81
|
+
> For a virtual environment, replace `py` to `python`.
|
|
82
|
+
> If you do not have Python, please install it first.
|
|
83
|
+
|
|
84
|
+
- Get `pyfemtet` via following command:
|
|
85
|
+
|
|
86
|
+
```py -m pip install pyfemtet```
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
### 3. Setting `win32com` Constants
|
|
90
|
+
|
|
91
|
+
- Run following command to enable COM constants:
|
|
92
|
+
|
|
93
|
+
```py -m win32com.client.makepy FemtetMacro```
|
|
94
|
+
|
|
95
|
+
That's all! Now you can use Femtet's extention features via `pyfemtet`.
|
|
96
|
+
For more information including sample code and FEM projects, see the documentation of "Related Pages" section.
|
|
97
|
+
|
|
@@ -12,13 +12,13 @@ pyfemtet/FemtetPJTSample/her_ex40_parametric.py,sha256=B5PQoh71Q3KN2CyLU1gP_Yh9g
|
|
|
12
12
|
pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py,sha256=UfhJffuXyhzdIWNpOrpV6xLTK1fuVvgyhlyg4Rp-628,2148
|
|
13
13
|
pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj,sha256=pxacKe0NPNUPAcxqo2cATFApsMKiVt2g2e_FOk4fpjA,172895
|
|
14
14
|
pyfemtet/FemtetPJTSample/wat_ex14_parametric.py,sha256=LGbWxCek0Ad2YrDCKykiQkE3aIypM4g8P3mLd_2anEE,2052
|
|
15
|
-
pyfemtet/__init__.py,sha256
|
|
15
|
+
pyfemtet/__init__.py,sha256=xw_dYipbaGm6aV2OPgH234_ODRnMNhDWYLau1HFUaAQ,21
|
|
16
16
|
pyfemtet/core.py,sha256=3lqfBGJ5IuKz2Nqj5pRo7YQqKwx_0ZDL72u95Ur_1p0,1386
|
|
17
17
|
pyfemtet/dispatch_extensions.py,sha256=MhWiUXVt2Cq8vDeajMK4SrajjiAmb4m2fK8gXwHLrWA,16177
|
|
18
18
|
pyfemtet/logger.py,sha256=JYD0FvzijMS2NvZN7VT7vZA5hqtHEkvS93AHlIMDePw,2507
|
|
19
19
|
pyfemtet/opt/__init__.py,sha256=_P8unESvqCRD5pmuo6-5yo7BbrPi7c0aE6UZpqUD-_I,596
|
|
20
|
-
pyfemtet/opt/_femopt.py,sha256=
|
|
21
|
-
pyfemtet/opt/_femopt_core.py,sha256=
|
|
20
|
+
pyfemtet/opt/_femopt.py,sha256=LsgIF71hVY7LeAX-gKbJ__hr5FzLdrIW1xSqRg9gNOE,22287
|
|
21
|
+
pyfemtet/opt/_femopt_core.py,sha256=n_m-GIW82uvKNAn_N1ypBZQ4sOjngfNly7-SEkOXfuU,24774
|
|
22
22
|
pyfemtet/opt/femprj_sample/cad_ex01_NX.femprj,sha256=KC8JlHqHzqgyKriK911QSnQByQpRlw-SX5OSQ_GNe5M,149193
|
|
23
23
|
pyfemtet/opt/femprj_sample/cad_ex01_NX.prt,sha256=3okHLeMdslrRA_wkhppZtxIe-2-ZPMfNqWCdQwUV31o,226626
|
|
24
24
|
pyfemtet/opt/femprj_sample/cad_ex01_NX.py,sha256=qpfbU41qsJSMWnROzTOU1mpmHngGoa0cjnLHqNkt0EY,4519
|
|
@@ -53,19 +53,20 @@ pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.femprj,sha256=dMwQMt6yok_Pb
|
|
|
53
53
|
pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.py,sha256=vnfI4WuCvyjQN1MhnzyB-jcAPtTwz3yNiwtTm2yQZHU,2311
|
|
54
54
|
pyfemtet/opt/interface/__init__.py,sha256=qz5BszPuU3jZIoDnPjkPDAgvgHLlx1sYhuqh5ID798k,480
|
|
55
55
|
pyfemtet/opt/interface/_base.py,sha256=lDjdvKYmBMxSc7SfoWSu91qVijGaQ2Ng-0C7z_f4eFM,2079
|
|
56
|
-
pyfemtet/opt/interface/_femtet.py,sha256=
|
|
56
|
+
pyfemtet/opt/interface/_femtet.py,sha256=oDKFGruKVRudSEt3x2NnvVsuCfb_3hF65ONpCrKrIJo,25565
|
|
57
|
+
pyfemtet/opt/interface/_femtet_parametric.py,sha256=hGW7fKMVdHz0X1fVtGQIovxXtFWNFcEyPn9_tnMrny4,2399
|
|
57
58
|
pyfemtet/opt/interface/_femtet_with_nx/__init__.py,sha256=-6W2g2FDEcKzGHmI5KAKQe-4U5jDpMj0CXuma-GZca0,83
|
|
58
59
|
pyfemtet/opt/interface/_femtet_with_nx/_interface.py,sha256=kTEmfAyLMEZvYTYjGXgYnoyhi-wDzhKK7opyVp7rOcY,3931
|
|
59
60
|
pyfemtet/opt/interface/_femtet_with_nx/update_model.py,sha256=t0AB7mKY7rmrI_9stP1-5qhzmugEQ19DnZ4CCrCdTSw,2856
|
|
60
61
|
pyfemtet/opt/interface/_femtet_with_sldworks.py,sha256=400FidHp7mBAVLyxzLlLtGYNzK_TtK61ycd4vFjHES0,6254
|
|
61
62
|
pyfemtet/opt/opt/__init__.py,sha256=eQh-7PJN2YEUbHZnjinbeIyb0bk1wSh76TaEAa2l8SU,191
|
|
62
|
-
pyfemtet/opt/opt/_base.py,sha256=
|
|
63
|
+
pyfemtet/opt/opt/_base.py,sha256=yEnPWAxFUIRNmUV-nbfCW4N3naDkkzQGME3qsDgEBFQ,7571
|
|
63
64
|
pyfemtet/opt/opt/_optuna.py,sha256=TWtp9auU6GBWtEJVOuo8aWSvLcCHCUNUyOQRnqyln4I,9996
|
|
64
65
|
pyfemtet/opt/visualization/__init__.py,sha256=PUCHoZnuZrHjTd0QQQBgzWkCpKY2noBPTvi-lyvxQyw,193
|
|
65
66
|
pyfemtet/opt/visualization/_graphs.py,sha256=G6HaoGD3GpuwXih1nuTeFQMD0zv4jrhogedP9hxaG1c,5306
|
|
66
|
-
pyfemtet/opt/visualization/_monitor.py,sha256=
|
|
67
|
-
pyfemtet-0.4.
|
|
68
|
-
pyfemtet-0.4.
|
|
69
|
-
pyfemtet-0.4.
|
|
70
|
-
pyfemtet-0.4.
|
|
71
|
-
pyfemtet-0.4.
|
|
67
|
+
pyfemtet/opt/visualization/_monitor.py,sha256=X2KR6fd8qf1U58Qr_o0jn0FTm1w9ARMPhs4eMYgGipI,42100
|
|
68
|
+
pyfemtet-0.4.4.dist-info/LICENSE,sha256=sVQBhyoglGJUu65-BP3iR6ujORI6YgEU2Qm-V4fGlOA,1485
|
|
69
|
+
pyfemtet-0.4.4.dist-info/METADATA,sha256=eWMO2_okpoutM3fryBE_1Qo1t05ThIk7k3biMGP43wc,3332
|
|
70
|
+
pyfemtet-0.4.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
71
|
+
pyfemtet-0.4.4.dist-info/entry_points.txt,sha256=E_NUq8BEuKLM3z6Ou0sh6HyvaKE5O6NBDlmO-wgEGaQ,67
|
|
72
|
+
pyfemtet-0.4.4.dist-info/RECORD,,
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: pyfemtet
|
|
3
|
-
Version: 0.4.3
|
|
4
|
-
Summary: Design parameter optimization using Femtet.
|
|
5
|
-
Home-page: https://github.com/pyfemtet/pyfemtet
|
|
6
|
-
License: BSD-3-Clause
|
|
7
|
-
Author: kazuma.naito
|
|
8
|
-
Author-email: kazuma.naito@murata.com
|
|
9
|
-
Requires-Python: >=3.9.3,<3.13
|
|
10
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
11
|
-
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Requires-Dist: botorch (>=0.9.5,<0.10.0) ; python_version < "3.12"
|
|
16
|
-
Requires-Dist: colorlog (>=6.8.0,<7.0.0)
|
|
17
|
-
Requires-Dist: dash (>=2.14.2,<3.0.0)
|
|
18
|
-
Requires-Dist: dash-bootstrap-components (>=1.5.0,<2.0.0)
|
|
19
|
-
Requires-Dist: dask (>=2023.12.1,<2024.0.0)
|
|
20
|
-
Requires-Dist: distributed (>=2023.12.1,<2024.0.0)
|
|
21
|
-
Requires-Dist: femtetutils (>=1.0.0,<2.0.0)
|
|
22
|
-
Requires-Dist: numpy (>=1.26.2,<2.0.0)
|
|
23
|
-
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
|
24
|
-
Requires-Dist: optuna (>=3.4.0,<4.0.0)
|
|
25
|
-
Requires-Dist: optuna-integration (>=3.6.0,<4.0.0)
|
|
26
|
-
Requires-Dist: pandas (>=2.1.3,<3.0.0)
|
|
27
|
-
Requires-Dist: plotly (>=5.18.0,<6.0.0)
|
|
28
|
-
Requires-Dist: psutil (>=5.9.6,<6.0.0)
|
|
29
|
-
Requires-Dist: pywin32 (>=306,<307)
|
|
30
|
-
Requires-Dist: scipy (>=1.11.4,<2.0.0)
|
|
31
|
-
Requires-Dist: tqdm (>=4.66.1,<5.0.0)
|
|
32
|
-
Project-URL: Repository, https://github.com/pyfemtet/pyfemtet
|
|
33
|
-
Description-Content-Type: text/markdown
|
|
34
|
-
|
|
35
|
-
PyFemtet is the extension package for Femtet with Python.
|
|
36
|
-
|
|
37
|
-
- Femtet Website: https://www.muratasoftware.com/
|
|
38
|
-
- Documentation (English): https://pyfemtet.readthedocs.io/en/stable/
|
|
39
|
-
- ドキュメント(日本語): https://pyfemtet.readthedocs.io/jp/stable/
|
|
40
|
-
- Source code: https://github.com/pyfemtet/pyfemtet
|
|
41
|
-
- Bug reports: https://github.com/pyfemtet/pyfemtet/issues
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
It provides:
|
|
45
|
-
|
|
46
|
-
- single and multi objective parameter optimization
|
|
47
|
-
- tools for connect Femtet and Python by pid
|
|
48
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|