pyfemtet 0.3.12__py3-none-any.whl → 0.4.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/FemtetPJTSample/NX_ex01/NX_ex01.py +1 -1
- pyfemtet/FemtetPJTSample/Sldworks_ex01/Sldworks_ex01.py +1 -1
- pyfemtet/FemtetPJTSample/gau_ex08_parametric.py +1 -1
- pyfemtet/FemtetPJTSample/her_ex40_parametric.femprj +0 -0
- pyfemtet/FemtetPJTSample/her_ex40_parametric.py +1 -1
- pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py +1 -1
- pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj +0 -0
- pyfemtet/FemtetPJTSample/wat_ex14_parametric.py +1 -1
- pyfemtet/__init__.py +1 -1
- pyfemtet/core.py +14 -0
- pyfemtet/dispatch_extensions.py +5 -0
- pyfemtet/opt/__init__.py +22 -2
- pyfemtet/opt/_femopt.py +544 -0
- pyfemtet/opt/_femopt_core.py +730 -0
- pyfemtet/opt/interface/__init__.py +15 -0
- pyfemtet/opt/interface/_base.py +71 -0
- pyfemtet/opt/{interface.py → interface/_femtet.py} +120 -407
- pyfemtet/opt/interface/_femtet_with_nx/__init__.py +3 -0
- pyfemtet/opt/interface/_femtet_with_nx/_interface.py +128 -0
- pyfemtet/opt/interface/_femtet_with_sldworks.py +174 -0
- pyfemtet/opt/opt/__init__.py +8 -0
- pyfemtet/opt/opt/_base.py +202 -0
- pyfemtet/opt/opt/_optuna.py +240 -0
- pyfemtet/opt/visualization/__init__.py +7 -0
- pyfemtet/opt/visualization/_graphs.py +222 -0
- pyfemtet/opt/visualization/_monitor.py +1149 -0
- {pyfemtet-0.3.12.dist-info → pyfemtet-0.4.1.dist-info}/METADATA +4 -4
- pyfemtet-0.4.1.dist-info/RECORD +38 -0
- {pyfemtet-0.3.12.dist-info → pyfemtet-0.4.1.dist-info}/WHEEL +1 -1
- pyfemtet-0.4.1.dist-info/entry_points.txt +3 -0
- pyfemtet/opt/base.py +0 -1490
- pyfemtet/opt/monitor.py +0 -474
- pyfemtet-0.3.12.dist-info/RECORD +0 -26
- /pyfemtet/opt/{_FemtetWithNX → interface/_femtet_with_nx}/update_model.py +0 -0
- {pyfemtet-0.3.12.dist-info → pyfemtet-0.4.1.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from dask.distributed import get_worker
|
|
7
|
+
|
|
8
|
+
from pyfemtet.core import ModelError
|
|
9
|
+
from pyfemtet.opt.interface import FemtetInterface, logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
here, me = os.path.split(__file__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FemtetWithNXInterface(FemtetInterface):
|
|
16
|
+
"""Femtet with NX interface class.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
prt_path: The path to the prt file.
|
|
20
|
+
|
|
21
|
+
For details of The other arguments, see ``FemtetInterface``.
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
_JOURNAL_PATH = os.path.abspath(os.path.join(here, 'update_model.py'))
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
prt_path,
|
|
30
|
+
femprj_path=None,
|
|
31
|
+
model_name=None,
|
|
32
|
+
connect_method='auto',
|
|
33
|
+
strictly_pid_specify=True,
|
|
34
|
+
):
|
|
35
|
+
|
|
36
|
+
# check NX installation
|
|
37
|
+
self.run_journal_path = os.path.join(os.environ.get('UGII_BASE_DIR'), 'NXBIN', 'run_journal.exe')
|
|
38
|
+
if not os.path.isfile(self.run_journal_path):
|
|
39
|
+
raise FileNotFoundError(
|
|
40
|
+
r'"%UGII_BASE_DIR%\NXBIN\run_journal.exe" が見つかりませんでした。環境変数 UGII_BASE_DIR 又は NX のインストール状態を確認してください。')
|
|
41
|
+
|
|
42
|
+
# 引数の処理
|
|
43
|
+
# dask サブプロセスのときは prt_path を worker space から取るようにする
|
|
44
|
+
try:
|
|
45
|
+
worker = get_worker()
|
|
46
|
+
space = worker.local_directory
|
|
47
|
+
self.prt_path = os.path.join(space, os.path.basename(prt_path))
|
|
48
|
+
except ValueError: # get_worker に失敗した場合
|
|
49
|
+
self.prt_path = os.path.abspath(prt_path)
|
|
50
|
+
|
|
51
|
+
# FemtetInterface の設定 (femprj_path, model_name の更新など)
|
|
52
|
+
# + restore 情報の上書き
|
|
53
|
+
super().__init__(
|
|
54
|
+
femprj_path=femprj_path,
|
|
55
|
+
model_name=model_name,
|
|
56
|
+
connect_method=connect_method,
|
|
57
|
+
strictly_pid_specify=strictly_pid_specify,
|
|
58
|
+
prt_path=self.prt_path,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def check_param_value(self, name):
|
|
62
|
+
"""Override FemtetInterface.check_param_value().
|
|
63
|
+
|
|
64
|
+
Do nothing because the parameter can be registered
|
|
65
|
+
to not only .femprj but also .prt.
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
def _setup_before_parallel(self, client):
|
|
71
|
+
client.upload_file(
|
|
72
|
+
self.kwargs['prt_path'],
|
|
73
|
+
False
|
|
74
|
+
)
|
|
75
|
+
super()._setup_before_parallel(client)
|
|
76
|
+
|
|
77
|
+
def update_model(self, parameters: 'pd.DataFrame') -> None:
|
|
78
|
+
"""Update .x_t"""
|
|
79
|
+
|
|
80
|
+
self.parameters = parameters.copy()
|
|
81
|
+
|
|
82
|
+
# Femtet が参照している x_t パスを取得する
|
|
83
|
+
x_t_path = self.Femtet.Gaudi.LastXTPath
|
|
84
|
+
|
|
85
|
+
# 前のが存在するならば消しておく
|
|
86
|
+
if os.path.isfile(x_t_path):
|
|
87
|
+
os.remove(x_t_path)
|
|
88
|
+
|
|
89
|
+
# 変数の json 文字列を作る
|
|
90
|
+
tmp_dict = {}
|
|
91
|
+
for i, row in parameters.iterrows():
|
|
92
|
+
tmp_dict[row['name']] = row['value']
|
|
93
|
+
str_json = json.dumps(tmp_dict)
|
|
94
|
+
|
|
95
|
+
# NX journal を使ってモデルを編集する
|
|
96
|
+
env = os.environ.copy()
|
|
97
|
+
subprocess.run(
|
|
98
|
+
[self.run_journal_path, self._JOURNAL_PATH, '-args', self.prt_path, str_json, x_t_path],
|
|
99
|
+
env=env,
|
|
100
|
+
shell=True,
|
|
101
|
+
cwd=os.path.dirname(self.prt_path)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# この時点で x_t ファイルがなければ NX がモデル更新に失敗しているはず
|
|
105
|
+
if not os.path.isfile(x_t_path):
|
|
106
|
+
raise ModelError
|
|
107
|
+
|
|
108
|
+
# モデルの再インポート
|
|
109
|
+
self._call_femtet_api(
|
|
110
|
+
self.Femtet.Gaudi.ReExecute,
|
|
111
|
+
False,
|
|
112
|
+
ModelError, # 生きてるのに失敗した場合
|
|
113
|
+
error_message=f'モデル再構築に失敗しました.',
|
|
114
|
+
is_Gaudi_method=True,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# 処理を確定
|
|
118
|
+
self._call_femtet_api(
|
|
119
|
+
self.Femtet.Redraw,
|
|
120
|
+
False, # 戻り値は常に None なのでこの変数に意味はなく None 以外なら何でもいい
|
|
121
|
+
ModelError, # 生きてるのに失敗した場合
|
|
122
|
+
error_message=f'モデル再構築に失敗しました.',
|
|
123
|
+
is_Gaudi_method=True,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# femprj モデルの変数も更新
|
|
127
|
+
super().update_model(parameters)
|
|
128
|
+
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from time import sleep, time
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from dask.distributed import get_worker
|
|
7
|
+
|
|
8
|
+
from win32com.client import DispatchEx
|
|
9
|
+
from pythoncom import CoInitialize, CoUninitialize
|
|
10
|
+
|
|
11
|
+
from pyfemtet.core import ModelError
|
|
12
|
+
from pyfemtet.opt.interface import FemtetInterface, logger
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FemtetWithSolidworksInterface(FemtetInterface):
|
|
16
|
+
# 定数の宣言
|
|
17
|
+
swThisConfiguration = 1 # https://help.solidworks.com/2023/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swInConfigurationOpts_e.html
|
|
18
|
+
swAllConfiguration = 2
|
|
19
|
+
swSpecifyConfiguration = 3 # use with ConfigName argument
|
|
20
|
+
swSaveAsCurrentVersion = 0
|
|
21
|
+
swSaveAsOptions_Copy = 2 #
|
|
22
|
+
swSaveAsOptions_Silent = 1 # https://help.solidworks.com/2021/english/api/swconst/solidworks.interop.swconst~solidworks.interop.swconst.swsaveasoptions_e.html
|
|
23
|
+
swSaveWithReferencesOptions_None = 0 # https://help-solidworks-com.translate.goog/2023/english/api/swconst/SolidWorks.Interop.swconst~SolidWorks.Interop.swconst.swSaveWithReferencesOptions_e.html?_x_tr_sl=auto&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=wapp
|
|
24
|
+
swDocPART = 1 # https://help.solidworks.com/2023/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swDocumentTypes_e.html
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
sldprt_path,
|
|
29
|
+
femprj_path=None,
|
|
30
|
+
model_name=None,
|
|
31
|
+
connect_method='auto',
|
|
32
|
+
strictly_pid_specify=True,
|
|
33
|
+
):
|
|
34
|
+
# 引数の処理
|
|
35
|
+
# dask サブプロセスのときは space 直下の sldprt_path を参照する
|
|
36
|
+
try:
|
|
37
|
+
worker = get_worker()
|
|
38
|
+
space = worker.local_directory
|
|
39
|
+
self.sldprt_path = os.path.join(space, os.path.basename(sldprt_path))
|
|
40
|
+
except ValueError: # get_worker に失敗した場合
|
|
41
|
+
self.sldprt_path = os.path.abspath(sldprt_path)
|
|
42
|
+
|
|
43
|
+
# FemtetInterface の設定 (femprj_path, model_name の更新など)
|
|
44
|
+
# + restore 情報の上書き
|
|
45
|
+
super().__init__(
|
|
46
|
+
femprj_path=femprj_path,
|
|
47
|
+
model_name=model_name,
|
|
48
|
+
connect_method=connect_method,
|
|
49
|
+
strictly_pid_specify=strictly_pid_specify,
|
|
50
|
+
sldprt_path=self.sldprt_path,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def initialize_sldworks_connection(self):
|
|
54
|
+
# SolidWorks を捕まえ、ファイルを開く
|
|
55
|
+
self.swApp = DispatchEx('SLDWORKS.Application')
|
|
56
|
+
self.swApp.Visible = True
|
|
57
|
+
|
|
58
|
+
# open model
|
|
59
|
+
self.swApp.OpenDoc(self.sldprt_path, self.swDocPART)
|
|
60
|
+
self.swModel = self.swApp.ActiveDoc
|
|
61
|
+
self.swEqnMgr = self.swModel.GetEquationMgr
|
|
62
|
+
self.nEquation = self.swEqnMgr.GetCount
|
|
63
|
+
|
|
64
|
+
def check_param_value(self, param_name):
|
|
65
|
+
"""Override FemtetInterface.check_param_value().
|
|
66
|
+
|
|
67
|
+
Do nothing because the parameter can be registered
|
|
68
|
+
to not only .femprj but also .SLDPRT.
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
def _setup_before_parallel(self, client):
|
|
74
|
+
client.upload_file(
|
|
75
|
+
self.kwargs['sldprt_path'],
|
|
76
|
+
False
|
|
77
|
+
)
|
|
78
|
+
super()._setup_before_parallel(client)
|
|
79
|
+
|
|
80
|
+
def _setup_after_parallel(self):
|
|
81
|
+
CoInitialize()
|
|
82
|
+
self.initialize_sldworks_connection()
|
|
83
|
+
|
|
84
|
+
def update_model(self, parameters: pd.DataFrame):
|
|
85
|
+
"""Update .x_t"""
|
|
86
|
+
|
|
87
|
+
self.parameters = parameters.copy()
|
|
88
|
+
|
|
89
|
+
# Femtet が参照している x_t パスを取得する
|
|
90
|
+
x_t_path = self.Femtet.Gaudi.LastXTPath
|
|
91
|
+
|
|
92
|
+
# 前のが存在するならば消しておく
|
|
93
|
+
if os.path.isfile(x_t_path):
|
|
94
|
+
os.remove(x_t_path)
|
|
95
|
+
|
|
96
|
+
# solidworks のモデルの更新
|
|
97
|
+
self.update_sw_model(parameters)
|
|
98
|
+
|
|
99
|
+
# export as x_t
|
|
100
|
+
self.swModel.SaveAs(x_t_path)
|
|
101
|
+
|
|
102
|
+
# 30 秒待っても x_t ができてなければエラー(COM なので)
|
|
103
|
+
timeout = 30
|
|
104
|
+
start = time()
|
|
105
|
+
while True:
|
|
106
|
+
if os.path.isfile(x_t_path):
|
|
107
|
+
break
|
|
108
|
+
if time() - start > timeout:
|
|
109
|
+
raise ModelError('モデル再構築に失敗しました')
|
|
110
|
+
sleep(1)
|
|
111
|
+
|
|
112
|
+
# モデルの再インポート
|
|
113
|
+
self._call_femtet_api(
|
|
114
|
+
self.Femtet.Gaudi.ReExecute,
|
|
115
|
+
False,
|
|
116
|
+
ModelError, # 生きてるのに失敗した場合
|
|
117
|
+
error_message=f'モデル再構築に失敗しました.',
|
|
118
|
+
is_Gaudi_method=True,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# 処理を確定
|
|
122
|
+
self._call_femtet_api(
|
|
123
|
+
self.Femtet.Redraw,
|
|
124
|
+
False, # 戻り値は常に None なのでこの変数に意味はなく None 以外なら何でもいい
|
|
125
|
+
ModelError, # 生きてるのに失敗した場合
|
|
126
|
+
error_message=f'モデル再構築に失敗しました.',
|
|
127
|
+
is_Gaudi_method=True,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# femprj モデルの変数も更新
|
|
131
|
+
super().update_model(parameters)
|
|
132
|
+
|
|
133
|
+
def update_sw_model(self, parameters: pd.DataFrame):
|
|
134
|
+
"""Update .sldprt"""
|
|
135
|
+
# df を dict に変換
|
|
136
|
+
user_param_dict = {}
|
|
137
|
+
for i, row in parameters.iterrows():
|
|
138
|
+
user_param_dict[row['name']] = row['value']
|
|
139
|
+
|
|
140
|
+
# プロパティを退避
|
|
141
|
+
buffer_aso = self.swEqnMgr.AutomaticSolveOrder
|
|
142
|
+
buffer_ar = self.swEqnMgr.AutomaticRebuild
|
|
143
|
+
self.swEqnMgr.AutomaticSolveOrder = False
|
|
144
|
+
self.swEqnMgr.AutomaticRebuild = False
|
|
145
|
+
|
|
146
|
+
for i in range(self.nEquation):
|
|
147
|
+
# name, equation の取得
|
|
148
|
+
current_equation = self.swEqnMgr.Equation(i)
|
|
149
|
+
current_name = self._get_name_from_equation(current_equation)
|
|
150
|
+
# 対象なら処理
|
|
151
|
+
if current_name in list(user_param_dict.keys()):
|
|
152
|
+
new_equation = f'"{current_name}" = {user_param_dict[current_name]}'
|
|
153
|
+
self.swEqnMgr.Equation(i, new_equation)
|
|
154
|
+
|
|
155
|
+
# 式の計算
|
|
156
|
+
# noinspection PyStatementEffect
|
|
157
|
+
self.swEqnMgr.EvaluateAll # always returns -1
|
|
158
|
+
|
|
159
|
+
# プロパティをもとに戻す
|
|
160
|
+
self.swEqnMgr.AutomaticSolveOrder = buffer_aso
|
|
161
|
+
self.swEqnMgr.AutomaticRebuild = buffer_ar
|
|
162
|
+
|
|
163
|
+
# 更新する(ここで失敗はしうる)
|
|
164
|
+
result = self.swModel.EditRebuild3 # モデル再構築
|
|
165
|
+
if not result:
|
|
166
|
+
raise ModelError('モデル再構築に失敗しました')
|
|
167
|
+
|
|
168
|
+
def _get_name_from_equation(self, equation: str):
|
|
169
|
+
pattern = r'^\s*"(.+?)"\s*$'
|
|
170
|
+
matched = re.match(pattern, equation.split('=')[0])
|
|
171
|
+
if matched:
|
|
172
|
+
return matched.group(1)
|
|
173
|
+
else:
|
|
174
|
+
return None
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# typing
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
|
|
4
|
+
# built-in
|
|
5
|
+
import json
|
|
6
|
+
from time import sleep
|
|
7
|
+
|
|
8
|
+
# 3rd-party
|
|
9
|
+
import numpy as np
|
|
10
|
+
import pandas as pd
|
|
11
|
+
|
|
12
|
+
# pyfemtet relative
|
|
13
|
+
from pyfemtet.opt.interface import FemtetInterface
|
|
14
|
+
from pyfemtet.opt._femopt_core import OptimizationStatus
|
|
15
|
+
|
|
16
|
+
# logger
|
|
17
|
+
import logging
|
|
18
|
+
from pyfemtet.logger import get_logger
|
|
19
|
+
logger = get_logger('opt')
|
|
20
|
+
logger.setLevel(logging.INFO)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AbstractOptimizer(ABC):
|
|
24
|
+
"""Abstract base class for an interface of optimization library.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
fem (FEMInterface): The finite element method object.
|
|
28
|
+
fem_class (type): The class of the finite element method object.
|
|
29
|
+
fem_kwargs (dict): The keyword arguments used to instantiate the finite element method object.
|
|
30
|
+
parameters (pd.DataFrame): The parameters used in the optimization.
|
|
31
|
+
objectives (dict): A dictionary containing the objective functions used in the optimization.
|
|
32
|
+
constraints (dict): A dictionary containing the constraint functions used in the optimization.
|
|
33
|
+
entire_status (OptimizationStatus): The status of the entire optimization process.
|
|
34
|
+
history (History): An actor object that records the history of each iteration in the optimization process.
|
|
35
|
+
worker_status (OptimizationStatus): The status of each worker in a distributed computing environment.
|
|
36
|
+
message (str): A message associated with the current state of the optimization process.
|
|
37
|
+
seed (int or None): The random seed used for random number generation during the optimization process.
|
|
38
|
+
timeout (float or int or None): The maximum time allowed for each iteration of the optimization process. If exceeded, it will be interrupted and terminated early.
|
|
39
|
+
n_trials (int or None): The maximum number of trials allowed for each iteration of the optimization process. If exceeded, it will be interrupted and terminated early.
|
|
40
|
+
is_cluster (bool): Flag indicating if running on a distributed computing cluster.
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self):
|
|
45
|
+
self.fem = None
|
|
46
|
+
self.fem_class = None
|
|
47
|
+
self.fem_kwargs = dict()
|
|
48
|
+
self.parameters = pd.DataFrame()
|
|
49
|
+
self.objectives = dict()
|
|
50
|
+
self.constraints = dict()
|
|
51
|
+
self.entire_status = None # actor
|
|
52
|
+
self.history = None # actor
|
|
53
|
+
self.worker_status = None # actor
|
|
54
|
+
self.message = ''
|
|
55
|
+
self.seed = None
|
|
56
|
+
self.timeout = None
|
|
57
|
+
self.n_trials = None
|
|
58
|
+
self.is_cluster = False
|
|
59
|
+
self.subprocess_idx = None
|
|
60
|
+
|
|
61
|
+
def f(self, x):
|
|
62
|
+
"""Get x, update fem analysis, return objectives (and constraints)."""
|
|
63
|
+
# interruption の実装は具象クラスに任せる
|
|
64
|
+
|
|
65
|
+
# x の更新
|
|
66
|
+
self.parameters['value'] = x
|
|
67
|
+
|
|
68
|
+
# FEM の更新
|
|
69
|
+
logger.debug('fem.update() start')
|
|
70
|
+
self.fem.update(self.parameters)
|
|
71
|
+
|
|
72
|
+
# y, _y, c の更新
|
|
73
|
+
logger.debug('calculate y start')
|
|
74
|
+
y = [obj.calc(self.fem) for obj in self.objectives.values()]
|
|
75
|
+
|
|
76
|
+
logger.debug('calculate _y start')
|
|
77
|
+
_y = [obj.convert(value) for obj, value in zip(self.objectives.values(), y)]
|
|
78
|
+
|
|
79
|
+
logger.debug('calculate c start')
|
|
80
|
+
c = [cns.calc(self.fem) for cns in self.constraints.values()]
|
|
81
|
+
|
|
82
|
+
logger.debug('history.record start')
|
|
83
|
+
self.history.record(
|
|
84
|
+
self.parameters,
|
|
85
|
+
self.objectives,
|
|
86
|
+
self.constraints,
|
|
87
|
+
y,
|
|
88
|
+
c,
|
|
89
|
+
self.message,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
logger.debug('history.record end')
|
|
93
|
+
return np.array(y), np.array(_y), np.array(c)
|
|
94
|
+
|
|
95
|
+
def _reconstruct_fem(self, skip_reconstruct=False):
|
|
96
|
+
"""Reconstruct FEMInterface in a subprocess."""
|
|
97
|
+
# reconstruct fem
|
|
98
|
+
if not skip_reconstruct:
|
|
99
|
+
self.fem = self.fem_class(**self.fem_kwargs)
|
|
100
|
+
|
|
101
|
+
# COM 定数の restore
|
|
102
|
+
for obj in self.objectives.values():
|
|
103
|
+
obj._restore_constants()
|
|
104
|
+
for cns in self.constraints.values():
|
|
105
|
+
cns._restore_constants()
|
|
106
|
+
|
|
107
|
+
def get_parameter(self, format='dict'):
|
|
108
|
+
"""Returns the parameters in the specified format.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
format (str, optional): The desired format of the parameters. Can be 'df' (DataFrame), 'values', or 'dict'. Defaults to 'dict'.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
object: The parameters in the specified format.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValueError: If an invalid format is provided.
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
if format == 'df':
|
|
121
|
+
return self.parameters
|
|
122
|
+
elif format == 'values' or format == 'value':
|
|
123
|
+
return self.parameters.value.values
|
|
124
|
+
elif format == 'dict':
|
|
125
|
+
ret = {}
|
|
126
|
+
for i, row in self.parameters.iterrows():
|
|
127
|
+
ret[row['name']] = row.value
|
|
128
|
+
return ret
|
|
129
|
+
else:
|
|
130
|
+
raise ValueError('get_parameter() got invalid format: {format}')
|
|
131
|
+
|
|
132
|
+
def _check_interruption(self):
|
|
133
|
+
""""""
|
|
134
|
+
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
135
|
+
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
136
|
+
self._finalize()
|
|
137
|
+
return True
|
|
138
|
+
else:
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
def _finalize(self):
|
|
142
|
+
"""Destruct fem and set worker status."""
|
|
143
|
+
del self.fem
|
|
144
|
+
self.worker_status.set(OptimizationStatus.TERMINATED)
|
|
145
|
+
|
|
146
|
+
def _run(
|
|
147
|
+
self,
|
|
148
|
+
subprocess_idx,
|
|
149
|
+
worker_status_list,
|
|
150
|
+
wait_setup,
|
|
151
|
+
skip_set_fem=False,
|
|
152
|
+
) -> None:
|
|
153
|
+
|
|
154
|
+
# 自分の worker_status の取得
|
|
155
|
+
self.subprocess_idx = subprocess_idx
|
|
156
|
+
self.worker_status = worker_status_list[subprocess_idx]
|
|
157
|
+
self.worker_status.set(OptimizationStatus.LAUNCHING_FEM)
|
|
158
|
+
|
|
159
|
+
if self._check_interruption():
|
|
160
|
+
return None
|
|
161
|
+
|
|
162
|
+
# set_fem をはじめ、終了したらそれを示す
|
|
163
|
+
if not skip_set_fem: # なくても動く??
|
|
164
|
+
self._reconstruct_fem()
|
|
165
|
+
self.fem._setup_after_parallel()
|
|
166
|
+
self.worker_status.set(OptimizationStatus.WAIT_OTHER_WORKERS)
|
|
167
|
+
|
|
168
|
+
# wait_setup or not
|
|
169
|
+
if wait_setup:
|
|
170
|
+
while True:
|
|
171
|
+
if self._check_interruption():
|
|
172
|
+
return None
|
|
173
|
+
# 他のすべての worker_status が wait 以上になったら break
|
|
174
|
+
if all([ws.get() >= OptimizationStatus.WAIT_OTHER_WORKERS for ws in worker_status_list]):
|
|
175
|
+
break
|
|
176
|
+
sleep(1)
|
|
177
|
+
else:
|
|
178
|
+
if self._check_interruption():
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
# set status running
|
|
182
|
+
if self.entire_status.get() < OptimizationStatus.RUNNING:
|
|
183
|
+
self.entire_status.set(OptimizationStatus.RUNNING)
|
|
184
|
+
self.worker_status.set(OptimizationStatus.RUNNING)
|
|
185
|
+
|
|
186
|
+
# run and finalize
|
|
187
|
+
try:
|
|
188
|
+
self.run()
|
|
189
|
+
finally:
|
|
190
|
+
self._finalize()
|
|
191
|
+
|
|
192
|
+
return None
|
|
193
|
+
|
|
194
|
+
@abstractmethod
|
|
195
|
+
def run(self) -> None:
|
|
196
|
+
"""Start calcuration using optimization library."""
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
@abstractmethod
|
|
200
|
+
def _setup_before_parallel(self, *args, **kwargs):
|
|
201
|
+
"""Setup before parallel processes are launched."""
|
|
202
|
+
pass
|