pyfemtet 0.7.0__py3-none-any.whl → 0.7.1__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/_util/dask_util.py +10 -0
- pyfemtet/_util/excel_macro_util.py +16 -4
- pyfemtet/opt/_femopt.py +27 -17
- pyfemtet/opt/_femopt_core.py +7 -2
- pyfemtet/opt/interface/_excel_interface.py +280 -91
- pyfemtet/opt/interface/_femtet.py +7 -20
- pyfemtet/opt/optimizer/_base.py +2 -1
- {pyfemtet-0.7.0.dist-info → pyfemtet-0.7.1.dist-info}/METADATA +2 -1
- {pyfemtet-0.7.0.dist-info → pyfemtet-0.7.1.dist-info}/RECORD +13 -12
- {pyfemtet-0.7.0.dist-info → pyfemtet-0.7.1.dist-info}/LICENSE +0 -0
- {pyfemtet-0.7.0.dist-info → pyfemtet-0.7.1.dist-info}/WHEEL +0 -0
- {pyfemtet-0.7.0.dist-info → pyfemtet-0.7.1.dist-info}/entry_points.txt +0 -0
pyfemtet/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.7.
|
|
1
|
+
__version__ = "0.7.1"
|
|
@@ -5,16 +5,27 @@ import asyncio # for timeout
|
|
|
5
5
|
import win32gui
|
|
6
6
|
import win32con
|
|
7
7
|
import win32api
|
|
8
|
+
import win32process
|
|
8
9
|
|
|
9
10
|
from pyfemtet.logger import get_module_logger
|
|
10
11
|
|
|
11
12
|
logger = get_module_logger('util.excel', __name__)
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
def _get_pid(hwnd):
|
|
16
|
+
"""Window handle から process ID を取得します."""
|
|
17
|
+
if hwnd > 0:
|
|
18
|
+
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
|
19
|
+
else:
|
|
20
|
+
pid = 0
|
|
21
|
+
return pid
|
|
22
|
+
|
|
23
|
+
|
|
14
24
|
class _ExcelDialogProcessor:
|
|
15
25
|
|
|
16
26
|
def __init__(self, excel_, timeout, restore_book=True):
|
|
17
27
|
self.excel = excel_
|
|
28
|
+
self.excel_pid = _get_pid(excel_.hWnd)
|
|
18
29
|
self.__excel_window_title = f' - Excel' # {basename} - Excel
|
|
19
30
|
self.__error_dialog_title = 'Microsoft Visual Basic'
|
|
20
31
|
self.__vbe_window_title = f'Microsoft Visual Basic for Applications - ' # Microsoft Visual Basic for Applications - {basename}
|
|
@@ -42,6 +53,7 @@ class _ExcelDialogProcessor:
|
|
|
42
53
|
win32gui.EnumWindows(self.enum_callback_to_close_dialog, found)
|
|
43
54
|
await asyncio.sleep(0.5)
|
|
44
55
|
if any(found):
|
|
56
|
+
await asyncio.sleep(1.)
|
|
45
57
|
break
|
|
46
58
|
|
|
47
59
|
logger.debug('ブックを閉じます。')
|
|
@@ -56,7 +68,7 @@ class _ExcelDialogProcessor:
|
|
|
56
68
|
def enum_callback_to_activate(self, hwnd, _):
|
|
57
69
|
title = win32gui.GetWindowText(hwnd)
|
|
58
70
|
# Excel 本体
|
|
59
|
-
if self.__excel_window_title in title:
|
|
71
|
+
if (self.excel_pid == _get_pid(hwnd)) and (self.__excel_window_title in title):
|
|
60
72
|
# Visible == True の際、エラーが発生した際、
|
|
61
73
|
# 一度 Excel ウィンドウをアクティブ化しないと dialog が出てこない
|
|
62
74
|
# が、これだけではダメかも。
|
|
@@ -65,7 +77,7 @@ class _ExcelDialogProcessor:
|
|
|
65
77
|
def enum_callback_to_close_dialog(self, hwnd, found):
|
|
66
78
|
title = win32gui.GetWindowText(hwnd)
|
|
67
79
|
# エラーダイアログ
|
|
68
|
-
if self.__error_dialog_title == title:
|
|
80
|
+
if (self.excel_pid == _get_pid(hwnd)) and (self.__error_dialog_title == title):
|
|
69
81
|
# 何故かこのコマンド以外受け付けず、
|
|
70
82
|
# このコマンドで問答無用でデバッグモードに入る
|
|
71
83
|
logger.debug('エラーダイアログを見つけました。')
|
|
@@ -77,14 +89,14 @@ class _ExcelDialogProcessor:
|
|
|
77
89
|
def enum_callback_to_close_confirm_dialog(self, hwnd, _):
|
|
78
90
|
title = win32gui.GetWindowText(hwnd)
|
|
79
91
|
# 確認ダイアログ
|
|
80
|
-
if "Microsoft Excel" in title:
|
|
92
|
+
if (self.excel_pid == _get_pid(hwnd)) and ("Microsoft Excel" in title):
|
|
81
93
|
# DisplayAlerts が False の場合は不要
|
|
82
94
|
win32gui.SendMessage(hwnd, win32con.WM_SYSCOMMAND, win32con.SC_CLOSE, 0)
|
|
83
95
|
|
|
84
96
|
def enum_callback_to_close_book(self, hwnd, _):
|
|
85
97
|
title = win32gui.GetWindowText(hwnd)
|
|
86
98
|
# VBE
|
|
87
|
-
if self.__vbe_window_title in title:
|
|
99
|
+
if (self.excel_pid == _get_pid(hwnd)) and (self.__vbe_window_title in title):
|
|
88
100
|
# 何故かこれで book 本体が閉じる
|
|
89
101
|
win32gui.SendMessage(hwnd, win32con.WM_CLOSE, 0, 0)
|
|
90
102
|
|
pyfemtet/opt/_femopt.py
CHANGED
|
@@ -12,7 +12,7 @@ from traceback import print_exception
|
|
|
12
12
|
# 3rd-party
|
|
13
13
|
import numpy as np
|
|
14
14
|
import pandas as pd
|
|
15
|
-
from dask.distributed import LocalCluster, Client
|
|
15
|
+
from dask.distributed import LocalCluster, Client, get_worker, Nanny
|
|
16
16
|
|
|
17
17
|
# pyfemtet relative
|
|
18
18
|
from pyfemtet.opt.interface import FEMInterface, FemtetInterface
|
|
@@ -136,6 +136,7 @@ class FEMOpt:
|
|
|
136
136
|
self.monitor_server_kwargs = dict()
|
|
137
137
|
self.monitor_process_worker_name = None
|
|
138
138
|
self._hv_reference = None
|
|
139
|
+
self._extra_space_dir = None
|
|
139
140
|
|
|
140
141
|
# multiprocess 時に pickle できないオブジェクト参照の削除
|
|
141
142
|
def __getstate__(self):
|
|
@@ -675,10 +676,6 @@ class FEMOpt:
|
|
|
675
676
|
directions,
|
|
676
677
|
)
|
|
677
678
|
|
|
678
|
-
# Femtet の confirm_before_exit のセット
|
|
679
|
-
self.fem.confirm_before_exit = confirm_before_exit
|
|
680
|
-
self.fem.kwargs['confirm_before_exit'] = confirm_before_exit
|
|
681
|
-
|
|
682
679
|
logger.info('Femtet loaded successfully.')
|
|
683
680
|
|
|
684
681
|
# クラスターの設定
|
|
@@ -718,30 +715,43 @@ class FEMOpt:
|
|
|
718
715
|
# これは CLI の --no-nanny オプションも同様らしい。
|
|
719
716
|
|
|
720
717
|
# クラスターの構築
|
|
718
|
+
# noinspection PyTypeChecker
|
|
721
719
|
cluster = LocalCluster(
|
|
722
720
|
processes=True,
|
|
723
721
|
n_workers=n_parallel,
|
|
724
722
|
threads_per_worker=1,
|
|
723
|
+
worker_class=Nanny,
|
|
725
724
|
)
|
|
726
725
|
logger.info('LocalCluster launched successfully.')
|
|
727
726
|
|
|
728
|
-
self.client = Client(
|
|
729
|
-
|
|
727
|
+
self.client = Client(
|
|
728
|
+
cluster,
|
|
729
|
+
direct_to_workers=False,
|
|
730
|
+
)
|
|
730
731
|
logger.info('Client launched successfully.')
|
|
731
732
|
|
|
732
|
-
|
|
733
|
-
subprocess_indices = list(range(n_parallel))[1:]
|
|
734
|
-
worker_addresses = list(self.client.nthreads().keys())
|
|
733
|
+
self.scheduler_address = self.client.scheduler.address
|
|
735
734
|
|
|
736
|
-
#
|
|
737
|
-
|
|
738
|
-
|
|
735
|
+
# worker address を取得
|
|
736
|
+
nannies_dict: dict[Any, Nanny] = self.client.cluster.workers
|
|
737
|
+
nannies = tuple(nannies_dict.values())
|
|
738
|
+
|
|
739
|
+
# ひとつの Nanny を選んで monitor 用にしつつ
|
|
740
|
+
# その space は main process に使わせるために記憶する
|
|
741
|
+
self.monitor_process_worker_name = nannies[0].worker_address
|
|
742
|
+
self._extra_space_dir = nannies[0].worker_dir
|
|
743
|
+
|
|
744
|
+
# 名前と address がごちゃごちゃになっていて可読性が悪いが
|
|
745
|
+
# 選んだ以外の Nanny は計算を割り当てる用にする
|
|
746
|
+
worker_addresses = ['Main']
|
|
747
|
+
worker_addresses.extend([n.worker_address for n in nannies[1:]])
|
|
748
|
+
subprocess_indices = list(range(n_parallel))[1:]
|
|
739
749
|
|
|
740
750
|
with self.client.cluster as _cluster, self.client as _client:
|
|
741
751
|
|
|
742
752
|
# actor の設定
|
|
743
|
-
self.status = OptimizationStatus(_client)
|
|
744
|
-
self.worker_status_list = [OptimizationStatus(_client, name) for name in worker_addresses] # tqdm 検討
|
|
753
|
+
self.status = OptimizationStatus(_client, worker_address=self.monitor_process_worker_name)
|
|
754
|
+
self.worker_status_list = [OptimizationStatus(_client, worker_address=self.monitor_process_worker_name, name=name) for name in worker_addresses] # tqdm 検討
|
|
745
755
|
self.status.set(OptimizationStatus.SETTING_UP)
|
|
746
756
|
self.history = History(
|
|
747
757
|
self.history_path,
|
|
@@ -773,7 +783,6 @@ class FEMOpt:
|
|
|
773
783
|
logger.info('Process monitor initialized successfully.')
|
|
774
784
|
|
|
775
785
|
# fem
|
|
776
|
-
# TODO: n_parallel=1 のときもアップロードしている。これを使うべきか、アップロードしないべき。
|
|
777
786
|
self.fem._setup_before_parallel(_client)
|
|
778
787
|
|
|
779
788
|
# opt
|
|
@@ -794,7 +803,7 @@ class FEMOpt:
|
|
|
794
803
|
subprocess_indices,
|
|
795
804
|
[self.worker_status_list] * len(subprocess_indices),
|
|
796
805
|
[wait_setup] * len(subprocess_indices),
|
|
797
|
-
workers=worker_addresses,
|
|
806
|
+
workers=worker_addresses if self.opt.is_cluster else worker_addresses[1:],
|
|
798
807
|
allow_other_workers=False,
|
|
799
808
|
)
|
|
800
809
|
|
|
@@ -818,6 +827,7 @@ class FEMOpt:
|
|
|
818
827
|
),
|
|
819
828
|
kwargs=dict(
|
|
820
829
|
skip_reconstruct=True,
|
|
830
|
+
space_dir=self._extra_space_dir,
|
|
821
831
|
)
|
|
822
832
|
)
|
|
823
833
|
t_main.start()
|
pyfemtet/opt/_femopt_core.py
CHANGED
|
@@ -980,8 +980,13 @@ class OptimizationStatus:
|
|
|
980
980
|
TERMINATE_ALL = 60
|
|
981
981
|
CRASHED = 70
|
|
982
982
|
|
|
983
|
-
def __init__(self, client, name='entire'):
|
|
984
|
-
self._future = client.submit(
|
|
983
|
+
def __init__(self, client, worker_address, name='entire'):
|
|
984
|
+
self._future = client.submit(
|
|
985
|
+
_OptimizationStatusActor,
|
|
986
|
+
actor=True,
|
|
987
|
+
workers=[worker_address],
|
|
988
|
+
allow_other_workers=False,
|
|
989
|
+
)
|
|
985
990
|
self._actor = self._future.result()
|
|
986
991
|
self.name = name
|
|
987
992
|
self.set(self.INITIALIZING)
|
|
@@ -21,12 +21,11 @@ from pyfemtet.core import SolveError
|
|
|
21
21
|
from pyfemtet.opt.optimizer.parameter import Parameter
|
|
22
22
|
|
|
23
23
|
from pyfemtet.dispatch_extensions import _get_pid, dispatch_specific_femtet
|
|
24
|
-
from pyfemtet.dispatch_extensions._impl import _NestableSpawnProcess
|
|
25
24
|
|
|
26
25
|
from pyfemtet._femtet_config_util.exit import _exit_or_force_terminate
|
|
27
|
-
from pyfemtet._femtet_config_util.autosave import _set_autosave_enabled, _get_autosave_enabled
|
|
28
26
|
|
|
29
27
|
from pyfemtet._util.excel_macro_util import watch_excel_macro_error
|
|
28
|
+
from pyfemtet._util.dask_util import lock_or_no_lock
|
|
30
29
|
|
|
31
30
|
from pyfemtet._warning import show_experimental_warning
|
|
32
31
|
|
|
@@ -80,11 +79,53 @@ class ExcelInterface(FEMInterface):
|
|
|
80
79
|
Excel マクロ関数のタイムアウト時間を秒単位で指定
|
|
81
80
|
します。 None の場合はタイムアウトなしとなります。
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
setup_xlsm_path (str or Path, optional):
|
|
83
|
+
セットアップ時に呼ぶ関数を含む xlsm のパスです。
|
|
84
|
+
指定しない場合は ``input_xlsm_path`` と
|
|
85
|
+
同じと見做します。
|
|
86
|
+
|
|
87
|
+
setup_procedure_name (str, optional):
|
|
88
|
+
セットアップ時に呼ぶマクロ関数名です。
|
|
89
|
+
指定しない場合、セットアップ時に何もしません。
|
|
90
|
+
|
|
91
|
+
setup_procedure_args (list or tuple, optional):
|
|
92
|
+
セットアップ時に呼ぶマクロ関数の引数です。
|
|
93
|
+
|
|
94
|
+
teardown_xlsm_path (str or Path, optional):
|
|
95
|
+
終了時に呼ぶ関数を含む xlsm のパスです。
|
|
96
|
+
指定しない場合は ``input_xlsm_path`` と
|
|
97
|
+
同じと見做します。
|
|
98
|
+
|
|
99
|
+
teardown_procedure_name (str, optional):
|
|
100
|
+
終了時に呼ぶマクロ関数名です。
|
|
101
|
+
指定しない場合、終了時に何もしません。
|
|
102
|
+
|
|
103
|
+
teardown_procedure_args (list or tuple, optional):
|
|
104
|
+
終了時に呼ぶマクロ関数の引数です。
|
|
105
|
+
|
|
106
|
+
visible (bool):
|
|
107
|
+
excel を可視化するかどうかです。
|
|
108
|
+
ただし、 True を指定した場合でもマクロの実行中は
|
|
109
|
+
不可視になります。
|
|
110
|
+
デフォルトは False です。
|
|
111
|
+
|
|
112
|
+
display_alerts (bool):
|
|
113
|
+
excel ダイアログを表示するかどうかです。
|
|
114
|
+
デバッグ目的の場合以外は True にしないでください。
|
|
85
115
|
デフォルトは False です。
|
|
86
116
|
|
|
87
|
-
|
|
117
|
+
terminate_excel_when_quit (bool):
|
|
118
|
+
終了時に Excel を終了するかどうかです。
|
|
119
|
+
指定しない場合、 connect_method が 'new' の場合
|
|
120
|
+
True とふるまい 'auto' の場合 False と振舞います。
|
|
121
|
+
|
|
122
|
+
interactive (bool):
|
|
123
|
+
excel を対話モードにするかどうかです。
|
|
124
|
+
False にすると、 visible == True であっても
|
|
125
|
+
自動化プロセス中にユーザーが誤って
|
|
126
|
+
Excel 本体を操作できないようにします。
|
|
127
|
+
デフォルトは True です。
|
|
128
|
+
|
|
88
129
|
Attributes:
|
|
89
130
|
input_xlsm_path (Path):
|
|
90
131
|
設計変数の定義を含む Excel ファイルのパス。
|
|
@@ -133,12 +174,12 @@ class ExcelInterface(FEMInterface):
|
|
|
133
174
|
|
|
134
175
|
"""
|
|
135
176
|
|
|
136
|
-
input_xlsm_path:
|
|
177
|
+
input_xlsm_path: str # 操作対象の xlsm パス
|
|
137
178
|
input_sheet_name: str # 変数セルを定義しているシート名
|
|
138
|
-
output_xlsm_path:
|
|
179
|
+
output_xlsm_path: str # 操作対象の xlsm パス (指定しない場合、input と同一)
|
|
139
180
|
output_sheet_name: str # 計算結果セルを定義しているシート名 (指定しない場合、input と同一)
|
|
140
181
|
|
|
141
|
-
|
|
182
|
+
related_file_paths: list[str] # 並列時に個別に並列プロセスの space にアップロードする必要のあるパス
|
|
142
183
|
|
|
143
184
|
procedure_name: str # マクロ関数名(or モジュール名.関数名)
|
|
144
185
|
procedure_args: list # マクロ関数の引数
|
|
@@ -148,17 +189,26 @@ class ExcelInterface(FEMInterface):
|
|
|
148
189
|
sh_input: CDispatch # 変数の定義された WorkSheet
|
|
149
190
|
wb_output: CDispatch # システムを構成する Workbook
|
|
150
191
|
sh_output: CDispatch # 計算結果の定義された WorkSheet (sh_input と同じでもよい)
|
|
192
|
+
wb_setup: CDispatch # システムを構成する Workbook
|
|
193
|
+
wb_teardown: CDispatch # システムを構成する Workbook
|
|
151
194
|
|
|
152
|
-
visible: bool
|
|
153
|
-
display_alerts: bool
|
|
195
|
+
visible: bool # excel を可視化するかどうか
|
|
196
|
+
display_alerts: bool # ダイアログを表示するかどうか
|
|
154
197
|
terminate_excel_when_quit: bool # 終了時に Excel を終了するかどうか
|
|
198
|
+
interactive: bool # excel を対話モードにするかどうか
|
|
155
199
|
|
|
156
200
|
_load_problem_from_me: bool = True
|
|
157
201
|
_excel_pid: int
|
|
158
202
|
_excel_hwnd: int
|
|
203
|
+
_with_femtet_autosave_setting: bool = True # Femtet の自動保存機能の自動設定を行うかどうか。Femtet がインストールされていない場合はオフにする。クラス変数なので、インスタンス化前に設定する。
|
|
159
204
|
_femtet_autosave_buffer: bool # Femtet の自動保存機能の一時退避場所。最適化中はオフにする。
|
|
160
|
-
_with_call_femtet: bool # Femtet を Python から起動するかどうか。Excel から起動できる場合は False でよい。
|
|
161
205
|
|
|
206
|
+
setup_xlsm_path: str
|
|
207
|
+
setup_procedure_name: str
|
|
208
|
+
setup_procedure_args: list or tuple
|
|
209
|
+
teardown_xlsm_path: str
|
|
210
|
+
teardown_procedure_name: str
|
|
211
|
+
teardown_procedure_args: list or tuple
|
|
162
212
|
|
|
163
213
|
def __init__(
|
|
164
214
|
self,
|
|
@@ -170,39 +220,67 @@ class ExcelInterface(FEMInterface):
|
|
|
170
220
|
procedure_args: list or tuple = None,
|
|
171
221
|
connect_method: str = 'auto', # or 'new'
|
|
172
222
|
procedure_timeout: float or None = None,
|
|
173
|
-
|
|
223
|
+
setup_xlsm_path: str or Path = None,
|
|
224
|
+
setup_procedure_name: str = None,
|
|
225
|
+
setup_procedure_args: list or tuple = None,
|
|
226
|
+
teardown_xlsm_path: str or Path = None,
|
|
227
|
+
teardown_procedure_name: str = None,
|
|
228
|
+
teardown_procedure_args: list or tuple = None,
|
|
229
|
+
related_file_paths: list[str or Path] = None,
|
|
230
|
+
visible: bool = False,
|
|
231
|
+
display_alerts: bool = False,
|
|
232
|
+
terminate_excel_when_quit: bool = None,
|
|
233
|
+
interactive: bool = True,
|
|
174
234
|
):
|
|
175
235
|
|
|
176
236
|
show_experimental_warning("ExcelInterface")
|
|
177
237
|
|
|
178
238
|
# 初期化
|
|
179
|
-
self.input_xlsm_path =
|
|
239
|
+
self.input_xlsm_path = str(input_xlsm_path) # あとで再取得する
|
|
180
240
|
self.input_sheet_name = input_sheet_name
|
|
181
|
-
self.output_xlsm_path = None
|
|
241
|
+
self.output_xlsm_path = str(input_xlsm_path) if output_xlsm_path is None else str(output_xlsm_path)
|
|
182
242
|
self.output_sheet_name = output_sheet_name or self.input_sheet_name
|
|
183
243
|
self.procedure_name = procedure_name or 'FemtetMacro.FemtetMain'
|
|
184
244
|
self.procedure_args = procedure_args or []
|
|
185
245
|
assert connect_method in ['new', 'auto']
|
|
186
246
|
self.connect_method = connect_method
|
|
187
|
-
self._femtet_autosave_buffer = _get_autosave_enabled()
|
|
188
247
|
self.procedure_timeout = procedure_timeout
|
|
189
|
-
|
|
190
|
-
|
|
248
|
+
if terminate_excel_when_quit is None:
|
|
249
|
+
self.terminate_excel_when_quit = self.connect_method == 'new'
|
|
250
|
+
else:
|
|
251
|
+
self.terminate_excel_when_quit = terminate_excel_when_quit
|
|
252
|
+
|
|
253
|
+
self.setup_xlsm_path = str(input_xlsm_path) if setup_xlsm_path is None else str(setup_xlsm_path) # あとで取得する
|
|
254
|
+
self.setup_procedure_name = setup_procedure_name
|
|
255
|
+
self.setup_procedure_args = setup_procedure_args or []
|
|
256
|
+
|
|
257
|
+
self.teardown_xlsm_path = str(input_xlsm_path) if teardown_xlsm_path is None else str(teardown_xlsm_path) # あとで取得する
|
|
258
|
+
self.teardown_procedure_name = teardown_procedure_name
|
|
259
|
+
self.teardown_procedure_args = teardown_procedure_args or []
|
|
260
|
+
|
|
261
|
+
self.related_file_paths = [str(p) for p in related_file_paths] if related_file_paths is not None else []
|
|
262
|
+
|
|
263
|
+
self.visible = visible
|
|
264
|
+
self.interactive = interactive
|
|
265
|
+
self.display_alerts = display_alerts
|
|
191
266
|
|
|
192
267
|
# dask サブプロセスのときは space 直下の input_xlsm_path を参照する
|
|
193
268
|
try:
|
|
194
269
|
worker = get_worker()
|
|
195
|
-
space = worker.local_directory
|
|
196
|
-
self.input_xlsm_path =
|
|
197
|
-
self.output_xlsm_path =
|
|
270
|
+
space = os.path.abspath(worker.local_directory)
|
|
271
|
+
self.input_xlsm_path = os.path.join(space, os.path.basename(self.input_xlsm_path))
|
|
272
|
+
self.output_xlsm_path = os.path.join(space, os.path.basename(self.output_xlsm_path))
|
|
273
|
+
self.setup_xlsm_path = os.path.join(space, os.path.basename(self.setup_xlsm_path))
|
|
274
|
+
self.teardown_xlsm_path = os.path.join(space, os.path.basename(self.teardown_xlsm_path))
|
|
275
|
+
self.related_file_paths = [os.path.join(space, os.path.basename(p)) for p in self.related_file_paths]
|
|
198
276
|
|
|
199
277
|
# main プロセスの場合は絶対パスを参照する
|
|
200
278
|
except ValueError:
|
|
201
|
-
self.input_xlsm_path =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
279
|
+
self.input_xlsm_path = os.path.abspath(self.input_xlsm_path)
|
|
280
|
+
self.output_xlsm_path = os.path.abspath(self.output_xlsm_path)
|
|
281
|
+
self.setup_xlsm_path = os.path.abspath(self.setup_xlsm_path)
|
|
282
|
+
self.teardown_xlsm_path = os.path.abspath(self.teardown_xlsm_path)
|
|
283
|
+
self.related_file_paths = [os.path.abspath(p) for p in self.related_file_paths]
|
|
206
284
|
|
|
207
285
|
# サブプロセスでの restore のための情報保管
|
|
208
286
|
kwargs = dict(
|
|
@@ -213,26 +291,109 @@ class ExcelInterface(FEMInterface):
|
|
|
213
291
|
procedure_name=self.procedure_name,
|
|
214
292
|
procedure_args=self.procedure_args,
|
|
215
293
|
connect_method='new', # subprocess で connect する際は new を強制する
|
|
294
|
+
terminate_excel_when_quit=True, # なので終了時は破棄する
|
|
216
295
|
procedure_timeout=self.procedure_timeout,
|
|
217
|
-
|
|
296
|
+
setup_xlsm_path=self.setup_xlsm_path,
|
|
297
|
+
setup_procedure_name=self.setup_procedure_name,
|
|
298
|
+
setup_procedure_args=self.setup_procedure_args,
|
|
299
|
+
teardown_xlsm_path=self.teardown_xlsm_path,
|
|
300
|
+
teardown_procedure_name=self.teardown_procedure_name,
|
|
301
|
+
teardown_procedure_args=self.teardown_procedure_args,
|
|
302
|
+
related_file_paths=self.related_file_paths,
|
|
303
|
+
visible=self.visible,
|
|
304
|
+
interactive=self.interactive,
|
|
305
|
+
display_alerts=self.display_alerts,
|
|
218
306
|
)
|
|
219
307
|
FEMInterface.__init__(self, **kwargs)
|
|
220
308
|
|
|
221
309
|
def __del__(self):
|
|
222
|
-
|
|
223
|
-
_set_autosave_enabled(self._femtet_autosave_buffer)
|
|
224
|
-
finally:
|
|
225
|
-
pass
|
|
310
|
+
pass
|
|
226
311
|
|
|
227
312
|
def _setup_before_parallel(self, client) -> None:
|
|
228
313
|
# メインプロセスで、並列プロセスを開始する前に行う前処理
|
|
229
314
|
|
|
230
|
-
|
|
231
|
-
|
|
315
|
+
client.upload_file(self.input_xlsm_path, False)
|
|
316
|
+
|
|
317
|
+
if not is_same_path(self.input_xlsm_path, self.output_xlsm_path):
|
|
318
|
+
client.upload_file(self.output_xlsm_path, False)
|
|
319
|
+
|
|
320
|
+
if not is_same_path(self.input_xlsm_path, self.setup_xlsm_path):
|
|
321
|
+
client.upload_file(self.setup_xlsm_path, False)
|
|
322
|
+
|
|
323
|
+
if not is_same_path(self.input_xlsm_path, self.teardown_xlsm_path):
|
|
324
|
+
client.upload_file(self.setup_xlsm_path, False)
|
|
325
|
+
|
|
326
|
+
for path in self.related_file_paths:
|
|
327
|
+
client.upload_file(path, False)
|
|
232
328
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
329
|
+
def _setup_after_parallel(self, *args, **kwargs):
|
|
330
|
+
"""サブプロセス又はメインプロセスのサブスレッドで、最適化を開始する前の前処理"""
|
|
331
|
+
|
|
332
|
+
# kwargs で space_dir が与えられている場合、そちらを使用する
|
|
333
|
+
# メインプロセスで呼ばれることを想定
|
|
334
|
+
if 'space_dir' in kwargs.keys():
|
|
335
|
+
space = kwargs['space_dir']
|
|
336
|
+
if space is not None:
|
|
337
|
+
self.input_xlsm_path = os.path.join(space, os.path.basename(self.input_xlsm_path))
|
|
338
|
+
self.output_xlsm_path = os.path.join(space, os.path.basename(self.output_xlsm_path))
|
|
339
|
+
self.setup_xlsm_path = os.path.join(space, os.path.basename(self.setup_xlsm_path))
|
|
340
|
+
self.teardown_xlsm_path = os.path.join(space, os.path.basename(self.teardown_xlsm_path))
|
|
341
|
+
self.related_file_paths = [os.path.join(space, os.path.basename(p)) for p in self.related_file_paths]
|
|
342
|
+
|
|
343
|
+
# connect_method が auto でかつ使用中のファイルを開こうとする場合に備えて excel のファイル名を変更
|
|
344
|
+
subprocess_idx = kwargs['opt'].subprocess_idx
|
|
345
|
+
|
|
346
|
+
def proc_path(path, ignore_no_exists):
|
|
347
|
+
exclude_ext, ext = os.path.splitext(path)
|
|
348
|
+
new_path = exclude_ext + f'{subprocess_idx}' + ext
|
|
349
|
+
if os.path.exists(path): # input と output が同じの場合など。input がないのはおかしい
|
|
350
|
+
os.rename(path, new_path)
|
|
351
|
+
elif not ignore_no_exists:
|
|
352
|
+
raise FileNotFoundError(f'{path} が見つかりません。')
|
|
353
|
+
return new_path
|
|
354
|
+
|
|
355
|
+
self.input_xlsm_path = proc_path(self.input_xlsm_path, False)
|
|
356
|
+
self.output_xlsm_path = proc_path(self.output_xlsm_path, True)
|
|
357
|
+
self.setup_xlsm_path = proc_path(self.setup_xlsm_path, True)
|
|
358
|
+
self.teardown_xlsm_path = proc_path(self.teardown_xlsm_path, True)
|
|
359
|
+
|
|
360
|
+
# スレッドが変わっているかもしれないので win32com の初期化
|
|
361
|
+
CoInitialize()
|
|
362
|
+
|
|
363
|
+
# 最適化中は femtet の autosave を無効にする
|
|
364
|
+
if self._with_femtet_autosave_setting:
|
|
365
|
+
from pyfemtet._femtet_config_util.autosave import _set_autosave_enabled, _get_autosave_enabled
|
|
366
|
+
self._femtet_autosave_buffer = _get_autosave_enabled()
|
|
367
|
+
_set_autosave_enabled(False)
|
|
368
|
+
|
|
369
|
+
# excel に繋ぐ
|
|
370
|
+
self.connect_excel(self.connect_method)
|
|
371
|
+
|
|
372
|
+
# load_objective は 1 回目に呼ばれたのが main thread なので
|
|
373
|
+
# subprocess に入った後でもう一度 load objective を行う
|
|
374
|
+
from pyfemtet.opt.optimizer import AbstractOptimizer
|
|
375
|
+
from pyfemtet.opt._femopt_core import Objective
|
|
376
|
+
opt: AbstractOptimizer = kwargs['opt']
|
|
377
|
+
obj: Objective
|
|
378
|
+
for obj_name, obj in opt.objectives.items():
|
|
379
|
+
if isinstance(obj.fun, ScapeGoatObjective):
|
|
380
|
+
opt.objectives[obj_name].fun = self.objective_from_excel
|
|
381
|
+
|
|
382
|
+
# excel の setup 関数を必要なら実行する
|
|
383
|
+
if self.setup_procedure_name is not None:
|
|
384
|
+
with lock_or_no_lock('excel_setup_procedure'):
|
|
385
|
+
try:
|
|
386
|
+
with watch_excel_macro_error(self.excel, timeout=self.procedure_timeout, restore_book=False):
|
|
387
|
+
self.excel.Run(
|
|
388
|
+
f'{self.setup_procedure_name}',
|
|
389
|
+
*self.setup_procedure_args
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
# 再計算
|
|
393
|
+
self.excel.CalculateFull()
|
|
394
|
+
|
|
395
|
+
except com_error as e:
|
|
396
|
+
raise RuntimeError(f'Failed to run macro {self.setup_procedure_args}. The original message is: {e}')
|
|
236
397
|
|
|
237
398
|
def connect_excel(self, connect_method):
|
|
238
399
|
|
|
@@ -253,6 +414,7 @@ class ExcelInterface(FEMInterface):
|
|
|
253
414
|
# 可視性の設定
|
|
254
415
|
self.excel.Visible = self.visible
|
|
255
416
|
self.excel.DisplayAlerts = self.display_alerts
|
|
417
|
+
self.excel.Interactive = self.interactive
|
|
256
418
|
|
|
257
419
|
# 開く
|
|
258
420
|
self.excel.Workbooks.Open(str(self.input_xlsm_path))
|
|
@@ -271,11 +433,10 @@ class ExcelInterface(FEMInterface):
|
|
|
271
433
|
else:
|
|
272
434
|
raise RuntimeError(f'Sheet {self.input_sheet_name} does not exist in the book {self.wb_input.Name}.')
|
|
273
435
|
|
|
274
|
-
|
|
436
|
+
# 開く (output)
|
|
437
|
+
if is_same_path(self.input_xlsm_path, self.output_xlsm_path):
|
|
275
438
|
self.wb_output = self.wb_input
|
|
276
|
-
|
|
277
439
|
else:
|
|
278
|
-
# 開く (output)
|
|
279
440
|
self.excel.Workbooks.Open(str(self.output_xlsm_path))
|
|
280
441
|
for wb in self.excel.Workbooks:
|
|
281
442
|
if wb.Name == os.path.basename(self.output_xlsm_path):
|
|
@@ -292,9 +453,35 @@ class ExcelInterface(FEMInterface):
|
|
|
292
453
|
else:
|
|
293
454
|
raise RuntimeError(f'Sheet {self.output_sheet_name} does not exist in the book {self.wb_output.Name}.')
|
|
294
455
|
|
|
456
|
+
# 開く (setup)
|
|
457
|
+
if is_same_path(self.input_xlsm_path, self.setup_xlsm_path):
|
|
458
|
+
self.wb_setup = self.wb_input
|
|
459
|
+
else:
|
|
460
|
+
self.excel.Workbooks.Open(self.setup_xlsm_path)
|
|
461
|
+
for wb in self.excel.Workbooks:
|
|
462
|
+
if wb.Name == os.path.basename(self.setup_xlsm_path):
|
|
463
|
+
self.wb_setup = wb
|
|
464
|
+
break
|
|
465
|
+
else:
|
|
466
|
+
raise RuntimeError(f'Cannot open {self.setup_xlsm_path}')
|
|
467
|
+
|
|
468
|
+
# 開く (teardown)
|
|
469
|
+
if is_same_path(self.input_xlsm_path, self.teardown_xlsm_path):
|
|
470
|
+
self.wb_teardown = self.wb_input
|
|
471
|
+
else:
|
|
472
|
+
self.excel.Workbooks.Open(self.teardown_xlsm_path)
|
|
473
|
+
for wb in self.excel.Workbooks:
|
|
474
|
+
if wb.Name == os.path.basename(self.teardown_xlsm_path):
|
|
475
|
+
self.wb_teardown = wb
|
|
476
|
+
break
|
|
477
|
+
else:
|
|
478
|
+
raise RuntimeError(f'Cannot open {self.teardown_xlsm_path}')
|
|
479
|
+
|
|
295
480
|
# book に参照設定を追加する
|
|
296
481
|
self.add_femtet_ref_xla(self.wb_input)
|
|
297
482
|
self.add_femtet_ref_xla(self.wb_output)
|
|
483
|
+
self.add_femtet_ref_xla(self.wb_setup)
|
|
484
|
+
self.add_femtet_ref_xla(self.wb_teardown)
|
|
298
485
|
|
|
299
486
|
def add_femtet_ref_xla(self, wb):
|
|
300
487
|
|
|
@@ -345,38 +532,6 @@ class ExcelInterface(FEMInterface):
|
|
|
345
532
|
if ref.Description == 'FemtetMacro': # FemtetMacro
|
|
346
533
|
wb.VBProject.References.Remove(ref)
|
|
347
534
|
|
|
348
|
-
def _setup_after_parallel(self, *args, **kwargs):
|
|
349
|
-
# サブプロセス又はメインプロセスのサブスレッドで、最適化を開始する前の前処理
|
|
350
|
-
|
|
351
|
-
# スレッドが変わっているかもしれないので win32com の初期化
|
|
352
|
-
CoInitialize()
|
|
353
|
-
|
|
354
|
-
# 最適化中は femtet の autosave を無効にする
|
|
355
|
-
_set_autosave_enabled(False)
|
|
356
|
-
|
|
357
|
-
# 必要なら Femtet を起動する
|
|
358
|
-
if self._with_call_femtet:
|
|
359
|
-
util.execute_femtet()
|
|
360
|
-
|
|
361
|
-
# 直後の Excel 起動に間に合わない場合があるため
|
|
362
|
-
# Femtet が Dispatch 可能になるまで捨てプロセスで待つ
|
|
363
|
-
p = _NestableSpawnProcess(target=wait_femtet)
|
|
364
|
-
p.start()
|
|
365
|
-
p.join()
|
|
366
|
-
|
|
367
|
-
# excel に繋ぐ
|
|
368
|
-
self.connect_excel(self.connect_method)
|
|
369
|
-
|
|
370
|
-
# load_objective は 1 回目に呼ばれたのが main thread なので
|
|
371
|
-
# subprocess に入った後でもう一度 load objective を行う
|
|
372
|
-
from pyfemtet.opt.optimizer import AbstractOptimizer
|
|
373
|
-
from pyfemtet.opt._femopt_core import Objective
|
|
374
|
-
opt: AbstractOptimizer = kwargs['opt']
|
|
375
|
-
obj: Objective
|
|
376
|
-
for obj_name, obj in opt.objectives.items():
|
|
377
|
-
if isinstance(obj.fun, ScapeGoatObjective):
|
|
378
|
-
opt.objectives[obj_name].fun = self.objective_from_excel
|
|
379
|
-
|
|
380
535
|
def update(self, parameters: pd.DataFrame) -> None:
|
|
381
536
|
|
|
382
537
|
# params を作成
|
|
@@ -407,48 +562,75 @@ class ExcelInterface(FEMInterface):
|
|
|
407
562
|
|
|
408
563
|
def quit(self):
|
|
409
564
|
if self.terminate_excel_when_quit:
|
|
565
|
+
|
|
566
|
+
already_terminated = not hasattr(self, 'excel')
|
|
567
|
+
if already_terminated:
|
|
568
|
+
return
|
|
569
|
+
|
|
410
570
|
logger.info('Excel の終了処理を開始します。')
|
|
411
571
|
|
|
572
|
+
# 参照設定解除の前に終了処理を必要なら実施する
|
|
573
|
+
# excel の setup 関数を必要なら実行する
|
|
574
|
+
if self.teardown_procedure_name is not None:
|
|
575
|
+
with lock_or_no_lock('excel_setup_procedure'):
|
|
576
|
+
try:
|
|
577
|
+
with watch_excel_macro_error(self.excel, timeout=self.procedure_timeout, restore_book=False):
|
|
578
|
+
self.excel.Run(
|
|
579
|
+
f'{self.teardown_procedure_name}',
|
|
580
|
+
*self.teardown_procedure_args
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
# 再計算
|
|
584
|
+
self.excel.CalculateFull()
|
|
585
|
+
|
|
586
|
+
except com_error as e:
|
|
587
|
+
raise RuntimeError(f'Failed to run macro {self.teardown_procedure_args}. The original message is: {e}')
|
|
588
|
+
|
|
589
|
+
# 参照設定を解除する(不要な処理かも)
|
|
412
590
|
self.remove_femtet_ref_xla(self.wb_input)
|
|
413
591
|
self.remove_femtet_ref_xla(self.wb_output)
|
|
592
|
+
self.remove_femtet_ref_xla(self.wb_setup)
|
|
593
|
+
self.remove_femtet_ref_xla(self.wb_teardown)
|
|
414
594
|
|
|
595
|
+
# シートの COM オブジェクト変数を削除する
|
|
415
596
|
del self.sh_input
|
|
416
597
|
del self.sh_output
|
|
417
598
|
|
|
599
|
+
# workbook を閉じる
|
|
418
600
|
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
419
601
|
self.wb_input.Close(SaveChanges := False)
|
|
420
|
-
|
|
602
|
+
|
|
603
|
+
if not is_same_path(self.input_xlsm_path, self.output_xlsm_path):
|
|
421
604
|
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
422
605
|
self.wb_output.Close(SaveChanges := False)
|
|
423
606
|
|
|
607
|
+
if not is_same_path(self.input_xlsm_path, self.setup_xlsm_path):
|
|
608
|
+
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
609
|
+
self.wb_setup.Close(SaveChanges := False)
|
|
610
|
+
|
|
611
|
+
if not is_same_path(self.input_xlsm_path, self.teardown_xlsm_path):
|
|
612
|
+
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
613
|
+
self.wb_teardown.Close(SaveChanges := False)
|
|
614
|
+
|
|
424
615
|
del self.wb_input
|
|
425
616
|
del self.wb_output
|
|
617
|
+
del self.wb_setup
|
|
618
|
+
del self.wb_teardown
|
|
619
|
+
|
|
426
620
|
|
|
621
|
+
# excel の終了
|
|
427
622
|
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
428
623
|
self.excel.Quit()
|
|
429
624
|
del self.excel
|
|
430
625
|
|
|
431
|
-
|
|
626
|
+
# ここで Excel のプロセスが残らず落ちる
|
|
627
|
+
gc.collect()
|
|
432
628
|
|
|
433
|
-
if self.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
logger.info('
|
|
438
|
-
while self._excel_pid == _get_pid(self._excel_hwnd):
|
|
439
|
-
sleep(1)
|
|
440
|
-
|
|
441
|
-
# TODO: 正確だが時間がかかる。選択できるようにしたほうがいいかもしれない。
|
|
442
|
-
logger.info('終了する Femtet を特定しています。')
|
|
443
|
-
femtet_pid = util.get_last_executed_femtet_process_id()
|
|
444
|
-
from multiprocessing import Process
|
|
445
|
-
p = Process(target=_terminate_femtet, args=(femtet_pid,))
|
|
446
|
-
p.start()
|
|
447
|
-
p.join()
|
|
448
|
-
logger.info('Excel-Femtet を終了しました。')
|
|
449
|
-
|
|
450
|
-
logger.info('自動保存機能の設定を元に戻しています。')
|
|
451
|
-
_set_autosave_enabled(self._femtet_autosave_buffer)
|
|
629
|
+
if self._with_femtet_autosave_setting:
|
|
630
|
+
from pyfemtet._femtet_config_util.autosave import _set_autosave_enabled
|
|
631
|
+
logger.info('自動保存機能の設定を元に戻しています。')
|
|
632
|
+
_set_autosave_enabled(self._femtet_autosave_buffer)
|
|
633
|
+
logger.info('自動保存機能の設定を元に戻しました。')
|
|
452
634
|
|
|
453
635
|
# 直接アクセスしてもよいが、ユーザーに易しい名前にするためだけのプロパティ
|
|
454
636
|
@property
|
|
@@ -583,5 +765,12 @@ class ScapeGoatObjective:
|
|
|
583
765
|
return tuple()
|
|
584
766
|
|
|
585
767
|
|
|
768
|
+
def is_same_path(p1, p2):
|
|
769
|
+
_p1 = os.path.abspath(p1).lower()
|
|
770
|
+
_p2 = os.path.abspath(p2).lower()
|
|
771
|
+
return _p1 == _p2
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
586
775
|
if __name__ == '__main__':
|
|
587
776
|
ExcelInterface(..., ...)
|
|
@@ -86,10 +86,6 @@ class FemtetInterface(FEMInterface):
|
|
|
86
86
|
it will be None and no parametric outputs are used
|
|
87
87
|
as objectives.
|
|
88
88
|
|
|
89
|
-
confirm_before_exit (bool):
|
|
90
|
-
Whether to confirm before (abnormal) termination.
|
|
91
|
-
Default is True.
|
|
92
|
-
|
|
93
89
|
**kwargs: Additional arguments from inherited classes.
|
|
94
90
|
|
|
95
91
|
Warning:
|
|
@@ -115,7 +111,6 @@ class FemtetInterface(FEMInterface):
|
|
|
115
111
|
allow_without_project: bool = False, # main でのみ True を許容したいので super() の引数にしない。
|
|
116
112
|
open_result_with_gui: bool = True,
|
|
117
113
|
parametric_output_indexes_use_as_objective: dict[int, str or float] = None,
|
|
118
|
-
confirm_before_exit: bool = True,
|
|
119
114
|
**kwargs # 継承されたクラスからの引数
|
|
120
115
|
):
|
|
121
116
|
|
|
@@ -145,7 +140,6 @@ class FemtetInterface(FEMInterface):
|
|
|
145
140
|
self.parametric_output_indexes_use_as_objective = parametric_output_indexes_use_as_objective
|
|
146
141
|
self._original_autosave_enabled = _get_autosave_enabled()
|
|
147
142
|
_set_autosave_enabled(False)
|
|
148
|
-
self.confirm_before_exit = confirm_before_exit
|
|
149
143
|
|
|
150
144
|
# dask サブプロセスのときは femprj を更新し connect_method を new にする
|
|
151
145
|
try:
|
|
@@ -183,7 +177,6 @@ class FemtetInterface(FEMInterface):
|
|
|
183
177
|
open_result_with_gui=self.open_result_with_gui,
|
|
184
178
|
parametric_output_indexes_use_as_objective=self.parametric_output_indexes_use_as_objective,
|
|
185
179
|
save_pdt=self.save_pdt,
|
|
186
|
-
confirm_before_exit=self.confirm_before_exit,
|
|
187
180
|
**kwargs
|
|
188
181
|
)
|
|
189
182
|
|
|
@@ -253,11 +246,9 @@ class FemtetInterface(FEMInterface):
|
|
|
253
246
|
cmd = f'{sys.executable} -m win32com.client.makepy FemtetMacro'
|
|
254
247
|
os.system(cmd)
|
|
255
248
|
message = Msg.ERR_NO_MAKEPY
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if self.confirm_before_exit:
|
|
260
|
-
input('Press enter to finish...')
|
|
249
|
+
logger.error('================')
|
|
250
|
+
logger.error(message)
|
|
251
|
+
logger.error('================')
|
|
261
252
|
raise RuntimeError(message)
|
|
262
253
|
|
|
263
254
|
if self.Femtet is None:
|
|
@@ -541,24 +532,20 @@ class FemtetInterface(FEMInterface):
|
|
|
541
532
|
try:
|
|
542
533
|
variable_names = self.Femtet.GetVariableNames_py()
|
|
543
534
|
except AttributeError as e:
|
|
544
|
-
|
|
535
|
+
logger.error('================')
|
|
545
536
|
logger.error(Msg.ERR_CANNOT_ACCESS_API + 'GetVariableNames_py')
|
|
546
537
|
logger.error(Msg.CERTIFY_MACRO_VERSION)
|
|
547
|
-
|
|
548
|
-
if self.confirm_before_exit:
|
|
549
|
-
input(Msg.ENTER_TO_QUIT)
|
|
538
|
+
logger.error('================')
|
|
550
539
|
raise e
|
|
551
540
|
|
|
552
541
|
if variable_names is not None:
|
|
553
542
|
if param_name in variable_names:
|
|
554
543
|
return self.Femtet.GetVariableValue(param_name)
|
|
555
544
|
message = Msg.ERR_NO_SUCH_PARAMETER_IN_FEMTET
|
|
556
|
-
|
|
545
|
+
logger.error('================')
|
|
557
546
|
logger.error(message)
|
|
558
547
|
logger.error(f'`{param_name}` not in {variable_names}')
|
|
559
|
-
|
|
560
|
-
if self.confirm_before_exit:
|
|
561
|
-
input(Msg.ENTER_TO_QUIT)
|
|
548
|
+
logger.error('================')
|
|
562
549
|
raise RuntimeError(message)
|
|
563
550
|
else:
|
|
564
551
|
return None
|
pyfemtet/opt/optimizer/_base.py
CHANGED
|
@@ -302,6 +302,7 @@ class AbstractOptimizer(ABC):
|
|
|
302
302
|
worker_status_list, # 他の worker の status オブジェクト
|
|
303
303
|
wait_setup, # 他の worker の status が ready になるまで待つか
|
|
304
304
|
skip_reconstruct=False, # reconstruct fem を行うかどうか
|
|
305
|
+
space_dir=None, # 特定の space_dir を使うかどうか
|
|
305
306
|
) -> Optional[Exception]:
|
|
306
307
|
|
|
307
308
|
# 自分の worker_status の取得
|
|
@@ -314,7 +315,7 @@ class AbstractOptimizer(ABC):
|
|
|
314
315
|
|
|
315
316
|
# set_fem をはじめ、終了したらそれを示す
|
|
316
317
|
self._reconstruct_fem(skip_reconstruct)
|
|
317
|
-
self.fem._setup_after_parallel(opt=self)
|
|
318
|
+
self.fem._setup_after_parallel(opt=self, space_dir=space_dir)
|
|
318
319
|
self.worker_status.set(OptimizationStatus.WAIT_OTHER_WORKERS)
|
|
319
320
|
|
|
320
321
|
# wait_setup or not
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyfemtet
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Design parameter optimization using Femtet.
|
|
5
5
|
Home-page: https://github.com/pyfemtet/pyfemtet
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -22,6 +22,7 @@ Requires-Dist: dash-bootstrap-components (>=1.5.0,<2.0.0)
|
|
|
22
22
|
Requires-Dist: dask (>=2023.12.1,<2024.0.0)
|
|
23
23
|
Requires-Dist: distributed (>=2023.12.1,<2024.0.0)
|
|
24
24
|
Requires-Dist: femtetutils (>=1.0.0,<2.0.0)
|
|
25
|
+
Requires-Dist: fire (>=0.6.0,<0.7.0)
|
|
25
26
|
Requires-Dist: numpy (>=1.26.2,<2.0.0)
|
|
26
27
|
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
|
27
28
|
Requires-Dist: optuna (>=3.4.0,<5.0.0)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
pyfemtet/__init__.py,sha256=
|
|
1
|
+
pyfemtet/__init__.py,sha256=tUukPDbH9wVBvn9_DYqm0p_Q7TagQGM_2ZX042hSuUs,21
|
|
2
2
|
pyfemtet/_femtet_config_util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
pyfemtet/_femtet_config_util/autosave.py,sha256=dNirA9XGuFehas8_Jkj2BW9GOzMbPyhnt1WHcH_ObSU,2070
|
|
4
4
|
pyfemtet/_femtet_config_util/exit.py,sha256=0BWID-tjOkmZwmgPFkcJMkWW39voccz5ARIBWvZbHaw,1877
|
|
@@ -10,7 +10,8 @@ pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po,sha256=F2bJGHVMtk086pekjVwY
|
|
|
10
10
|
pyfemtet/_message/locales/messages.pot,sha256=8Yjf462pJdEtxBLySKT34zMG5CH5uLB_8VaJQll_QsY,14493
|
|
11
11
|
pyfemtet/_message/messages.py,sha256=F8ENLZKoHq5irn-Ag7rqA3aSDsTmRWDyNHvOLY76ROI,13368
|
|
12
12
|
pyfemtet/_util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
pyfemtet/_util/
|
|
13
|
+
pyfemtet/_util/dask_util.py,sha256=ufgr4m8slvyWP97lWBwolysQpJ1PmAO_-OI8IlEyvU8,233
|
|
14
|
+
pyfemtet/_util/excel_macro_util.py,sha256=cF1Z3yl9FMM0J7dpMRTsle8uYxYcfHhQC0QffnVovdY,7944
|
|
14
15
|
pyfemtet/_warning.py,sha256=TSOj8mOhuyfOUJB24LsW6GNhTA3IzIEevJw_hLKTrq8,2205
|
|
15
16
|
pyfemtet/brep/__init__.py,sha256=V1IQ2s-8eWjXOVlTp2jMav9u-NBiSkmyAX1vmtHDEso,73
|
|
16
17
|
pyfemtet/brep/_impl.py,sha256=Amf_wsUxUosQB3XXhErJ5RGKXBxRnaaPpavb_0Xx6Ek,404
|
|
@@ -20,23 +21,23 @@ pyfemtet/dispatch_extensions/_impl.py,sha256=yH_yeAnQ-Xi9GfjX-FQt9u3yHnrLYIteRb6
|
|
|
20
21
|
pyfemtet/logger/__init__.py,sha256=UOJ9n_U2xwdTrp0Xgg-N6geySxNzKqTBQlXsaH0kW_w,420
|
|
21
22
|
pyfemtet/logger/_impl.py,sha256=rsAd0HpmveOaLS39ucp3U2OcDhQMWjC5fnVGhbJtWVw,6375
|
|
22
23
|
pyfemtet/opt/__init__.py,sha256=wRR8LbEhb5I6MUgmnCgjB6-tqHlOVxDIo7yPkq0QbBs,758
|
|
23
|
-
pyfemtet/opt/_femopt.py,sha256=
|
|
24
|
-
pyfemtet/opt/_femopt_core.py,sha256=
|
|
24
|
+
pyfemtet/opt/_femopt.py,sha256=3mh68QrVeP3EAhy3xEaNyB97uNJYAUZvpaPv6ZRrMN4,37883
|
|
25
|
+
pyfemtet/opt/_femopt_core.py,sha256=7z9xS8oQ8wW7dMoPaLL5PUizdJJIhoIM0EsvTu6LZ2Q,35416
|
|
25
26
|
pyfemtet/opt/_test_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
27
|
pyfemtet/opt/_test_utils/control_femtet.py,sha256=8oAl9y5V2n8Nnsgx_ebcZVzwFt1eI3swkdiKg6pg3-M,1085
|
|
27
28
|
pyfemtet/opt/_test_utils/hyper_sphere.py,sha256=nQhw8EIY0DwvcTqrbKhkxiITLZifr4-nG77E-_6ggmA,700
|
|
28
29
|
pyfemtet/opt/_test_utils/record_history.py,sha256=JCNJLZMCNTpJ6VT7iwEt2DIbwmsuQmgC0ClQSfcatj4,3915
|
|
29
30
|
pyfemtet/opt/interface/__init__.py,sha256=P5Ij-xjB4628qdgacIXLu_WBaWCoBkAk4nEMUCAQzWs,458
|
|
30
31
|
pyfemtet/opt/interface/_base.py,sha256=NVrvHVL7npgZbAQdMziA5TbTBghgi31JwrFH57edBKE,2615
|
|
31
|
-
pyfemtet/opt/interface/_excel_interface.py,sha256=
|
|
32
|
-
pyfemtet/opt/interface/_femtet.py,sha256=
|
|
32
|
+
pyfemtet/opt/interface/_excel_interface.py,sha256=mdPOCeEVrozcDBGIkprb8qSiCUYN2g07gz4KJRZdWSw,32479
|
|
33
|
+
pyfemtet/opt/interface/_femtet.py,sha256=REbi7-DdV0Keq-IgjDCTWHP9gjweayoORz3S04RfmkA,34443
|
|
33
34
|
pyfemtet/opt/interface/_femtet_parametric.py,sha256=0pAEhHflp0wIxWBVMXI8nCC02oAyRKLinH3Y6O8bq3M,2224
|
|
34
35
|
pyfemtet/opt/interface/_femtet_with_nx/__init__.py,sha256=-6W2g2FDEcKzGHmI5KAKQe-4U5jDpMj0CXuma-GZca0,83
|
|
35
36
|
pyfemtet/opt/interface/_femtet_with_nx/_interface.py,sha256=oefISc6c6RPPyhPnWuzCb60tgsrzGiqoIWk1DsiKzTk,5986
|
|
36
37
|
pyfemtet/opt/interface/_femtet_with_nx/update_model.py,sha256=P7VH0i_o-X9OUe6AGaLF1fACPeHNrMjcrOBCA3MMrI4,3092
|
|
37
38
|
pyfemtet/opt/interface/_femtet_with_sldworks.py,sha256=qqo2P4qZN0d89uNQyohKxq-Yhdql5vC0QHg4bpy7Ky8,11011
|
|
38
39
|
pyfemtet/opt/optimizer/__init__.py,sha256=Ia6viowECkG0IFXtFef0tJ4jDKsoDzJLqMJ9xLFH2LQ,543
|
|
39
|
-
pyfemtet/opt/optimizer/_base.py,sha256=
|
|
40
|
+
pyfemtet/opt/optimizer/_base.py,sha256=0cramby4lHPjNt6WoSn8XFhfx54xXMYucjD0O1uYz7w,12591
|
|
40
41
|
pyfemtet/opt/optimizer/_optuna/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
42
|
pyfemtet/opt/optimizer/_optuna/_botorch_patch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
43
|
pyfemtet/opt/optimizer/_optuna/_botorch_patch/enable_nonlinear_constraint.py,sha256=b2-PP2HM46kJS4cJkBWnxnW9AS9JfeVkEjmkoKK_ziE,8949
|
|
@@ -120,8 +121,8 @@ pyfemtet/opt/visualization/result_viewer/.gitignore,sha256=ryvb4aqbbsHireHWlPQfx
|
|
|
120
121
|
pyfemtet/opt/visualization/result_viewer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
121
122
|
pyfemtet/opt/visualization/result_viewer/application.py,sha256=WcHBx_J5eNLKSaprpk9BGifwhO04oN8FiNGYTWorrXA,1691
|
|
122
123
|
pyfemtet/opt/visualization/result_viewer/pages.py,sha256=laEAKHAtdshCAHxgXo-zMNg3RP6lCxfszO3XwLnF1dU,32156
|
|
123
|
-
pyfemtet-0.7.
|
|
124
|
-
pyfemtet-0.7.
|
|
125
|
-
pyfemtet-0.7.
|
|
126
|
-
pyfemtet-0.7.
|
|
127
|
-
pyfemtet-0.7.
|
|
124
|
+
pyfemtet-0.7.1.dist-info/LICENSE,sha256=sVQBhyoglGJUu65-BP3iR6ujORI6YgEU2Qm-V4fGlOA,1485
|
|
125
|
+
pyfemtet-0.7.1.dist-info/METADATA,sha256=NQPiiH6Lfk_1zkuMKNVtOnegaWhJXp_hN6afJMmaWts,3408
|
|
126
|
+
pyfemtet-0.7.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
127
|
+
pyfemtet-0.7.1.dist-info/entry_points.txt,sha256=ZfYqRaoiPtuWqFi2_msccyrVF0LurMn-IHlYamAegZo,104
|
|
128
|
+
pyfemtet-0.7.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|