pyfemtet 0.7.1__py3-none-any.whl → 0.8.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/_message/locales/ja/LC_MESSAGES/messages.mo +0 -0
- pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +112 -90
- pyfemtet/_message/locales/messages.pot +105 -89
- pyfemtet/_message/messages.py +6 -2
- pyfemtet/_util/excel_parse_util.py +138 -0
- pyfemtet/_util/sample.xlsx +0 -0
- pyfemtet/brep/__init__.py +0 -3
- pyfemtet/brep/_impl.py +7 -3
- pyfemtet/opt/_femopt.py +42 -14
- pyfemtet/opt/_femopt_core.py +93 -34
- pyfemtet/opt/advanced_samples/excel_ui/(ref) original_project.femprj +0 -0
- pyfemtet/opt/advanced_samples/excel_ui/femtet-macro.xlsm +0 -0
- pyfemtet/opt/advanced_samples/excel_ui/pyfemtet-core.py +291 -0
- pyfemtet/opt/advanced_samples/excel_ui/test-pyfemtet-core.cmd +22 -0
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data.py +60 -0
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data_jp.py +57 -0
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate.py +100 -0
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate_jp.py +90 -0
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_parametric.femprj +0 -0
- pyfemtet/opt/interface/__init__.py +2 -0
- pyfemtet/opt/interface/_base.py +3 -0
- pyfemtet/opt/interface/_excel_interface.py +296 -124
- pyfemtet/opt/interface/_femtet.py +19 -9
- pyfemtet/opt/interface/_surrogate/__init__.py +5 -0
- pyfemtet/opt/interface/_surrogate/_base.py +85 -0
- pyfemtet/opt/interface/_surrogate/_chaospy.py +71 -0
- pyfemtet/opt/interface/_surrogate/_singletaskgp.py +70 -0
- pyfemtet/opt/optimizer/_base.py +28 -18
- pyfemtet/opt/optimizer/_optuna/_optuna.py +20 -8
- pyfemtet/opt/optimizer/_optuna/_pof_botorch.py +60 -18
- pyfemtet/opt/prediction/_base.py +8 -0
- pyfemtet/opt/prediction/single_task_gp.py +85 -62
- pyfemtet/opt/visualization/_complex_components/main_figure_creator.py +5 -5
- pyfemtet/opt/visualization/_complex_components/main_graph.py +7 -1
- pyfemtet/opt/visualization/_complex_components/pm_graph.py +1 -1
- pyfemtet/opt/visualization/_process_monitor/application.py +2 -2
- pyfemtet/opt/visualization/_process_monitor/pages.py +1 -1
- pyfemtet/opt/visualization/result_viewer/pages.py +1 -1
- {pyfemtet-0.7.1.dist-info → pyfemtet-0.8.1.dist-info}/METADATA +8 -8
- {pyfemtet-0.7.1.dist-info → pyfemtet-0.8.1.dist-info}/RECORD +44 -28
- {pyfemtet-0.7.1.dist-info → pyfemtet-0.8.1.dist-info}/WHEEL +1 -1
- {pyfemtet-0.7.1.dist-info → pyfemtet-0.8.1.dist-info}/LICENSE +0 -0
- {pyfemtet-0.7.1.dist-info → pyfemtet-0.8.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from time import sleep
|
|
3
|
+
|
|
4
|
+
from optuna.samplers import RandomSampler
|
|
5
|
+
|
|
6
|
+
from pyfemtet.opt import FEMOpt, FemtetInterface, OptunaOptimizer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_res_freq(Femtet):
|
|
10
|
+
Galileo = Femtet.Gogh.Galileo
|
|
11
|
+
Galileo.Mode = 0
|
|
12
|
+
sleep(0.01)
|
|
13
|
+
return Galileo.GetFreq().Real
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if __name__ == '__main__':
|
|
17
|
+
|
|
18
|
+
os.chdir(os.path.dirname(__file__))
|
|
19
|
+
|
|
20
|
+
# Connect to Femtet.
|
|
21
|
+
fem = FemtetInterface(
|
|
22
|
+
femprj_path='gal_ex13_parametric.femprj',
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Initialize the optimization object.
|
|
26
|
+
# However, this script is not for optimization;
|
|
27
|
+
# instead, it is for creating training data.
|
|
28
|
+
# Therefore, we will use Optuna's random sampling
|
|
29
|
+
# class to select the design variables.
|
|
30
|
+
opt = OptunaOptimizer(
|
|
31
|
+
sampler_class=RandomSampler,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# We will set up the FEMOpt object. To refer to
|
|
35
|
+
# history_path in the optimization script, we will
|
|
36
|
+
# specify a clear CSV file name.
|
|
37
|
+
femopt = FEMOpt(
|
|
38
|
+
fem=fem,
|
|
39
|
+
opt=opt,
|
|
40
|
+
history_path='training_data.csv'
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Set the design variables.
|
|
44
|
+
femopt.add_parameter('length', 0.1, 0.02, 0.2)
|
|
45
|
+
femopt.add_parameter('width', 0.01, 0.001, 0.02)
|
|
46
|
+
femopt.add_parameter('base_radius', 0.008, 0.006, 0.01)
|
|
47
|
+
|
|
48
|
+
# Set the objective function. Since this is random
|
|
49
|
+
# sampling, specifying the direction does not affect
|
|
50
|
+
# the sampling.
|
|
51
|
+
femopt.add_objective(fun=get_res_freq, name='First Resonant Frequency (Hz)')
|
|
52
|
+
|
|
53
|
+
# Create the training data.
|
|
54
|
+
# If no termination condition is specified,
|
|
55
|
+
# it will continue creating training data until
|
|
56
|
+
# manually stopped.
|
|
57
|
+
femopt.set_random_seed(42)
|
|
58
|
+
femopt.optimize(
|
|
59
|
+
# n_trials=100
|
|
60
|
+
)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from time import sleep
|
|
3
|
+
|
|
4
|
+
from optuna.samplers import RandomSampler
|
|
5
|
+
|
|
6
|
+
from pyfemtet.opt import FEMOpt, FemtetInterface, OptunaOptimizer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_res_freq(Femtet):
|
|
10
|
+
Galileo = Femtet.Gogh.Galileo
|
|
11
|
+
Galileo.Mode = 0
|
|
12
|
+
sleep(0.01)
|
|
13
|
+
return Galileo.GetFreq().Real
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if __name__ == '__main__':
|
|
17
|
+
|
|
18
|
+
os.chdir(os.path.dirname(__file__))
|
|
19
|
+
|
|
20
|
+
# Femtet との接続を行います。
|
|
21
|
+
fem = FemtetInterface(
|
|
22
|
+
femprj_path='gal_ex13_parametric.femprj',
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# 最適化用オブジェクトの設定を行います。
|
|
26
|
+
# ただしこのスクリプトでは最適化ではなく
|
|
27
|
+
# 学習データ作成を行うので、 optuna の
|
|
28
|
+
# ランダムサンプリングクラスを用いて
|
|
29
|
+
# 設計変数の選定を行います。
|
|
30
|
+
opt = OptunaOptimizer(
|
|
31
|
+
sampler_class=RandomSampler,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# FEMOpt オブジェクトを設定します。
|
|
35
|
+
# 最適化スクリプトで history_path を参照するため、
|
|
36
|
+
# わかりやすい csv ファイル名を指定します。
|
|
37
|
+
femopt = FEMOpt(
|
|
38
|
+
fem=fem,
|
|
39
|
+
opt=opt,
|
|
40
|
+
history_path='training_data.csv'
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# 設計変数を設定します。
|
|
44
|
+
femopt.add_parameter('length', 0.1, 0.02, 0.2)
|
|
45
|
+
femopt.add_parameter('width', 0.01, 0.001, 0.02)
|
|
46
|
+
femopt.add_parameter('base_radius', 0.008, 0.006, 0.01)
|
|
47
|
+
# 目的関数を設定します。ランダムサンプリングなので
|
|
48
|
+
# direction は指定してもサンプリングに影響しません。
|
|
49
|
+
femopt.add_objective(fun=get_res_freq, name='第一共振周波数(Hz)')
|
|
50
|
+
|
|
51
|
+
# 学習データ作成を行います。
|
|
52
|
+
# 終了条件を指定しない場合、手動で停止するまで
|
|
53
|
+
# 学習データ作成を続けます。
|
|
54
|
+
femopt.set_random_seed(42)
|
|
55
|
+
femopt.optimize(
|
|
56
|
+
# n_trials=100
|
|
57
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from optuna.samplers import TPESampler
|
|
4
|
+
|
|
5
|
+
from pyfemtet.opt import FEMOpt, OptunaOptimizer
|
|
6
|
+
from pyfemtet.opt.interface import PoFBoTorchInterface
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main(target):
|
|
10
|
+
|
|
11
|
+
os.chdir(os.path.dirname(__file__))
|
|
12
|
+
|
|
13
|
+
# Instead of connecting with Femtet, create
|
|
14
|
+
# a surrogate model. Read the CSV file created
|
|
15
|
+
# by the training data creation script to build
|
|
16
|
+
# the surrogate model.
|
|
17
|
+
fem = PoFBoTorchInterface(
|
|
18
|
+
history_path='training_data.csv'
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Set up the optimization object.
|
|
22
|
+
opt = OptunaOptimizer(
|
|
23
|
+
sampler_class=TPESampler,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Set up the FEMOpt object.
|
|
27
|
+
femopt = FEMOpt(
|
|
28
|
+
fem=fem,
|
|
29
|
+
opt=opt,
|
|
30
|
+
history_path=f'optimized_result_target_{target}.csv'
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Set up the design variables.
|
|
34
|
+
# The upper and lower limits can differ from
|
|
35
|
+
# those in the training data creation script,
|
|
36
|
+
# but please note that extrapolation will
|
|
37
|
+
# occur outside the range that has not been
|
|
38
|
+
# trained, which may reduce the prediction
|
|
39
|
+
# accuracy of the surrogate model.
|
|
40
|
+
femopt.add_parameter('length', 0.1, 0.02, 0.2)
|
|
41
|
+
femopt.add_parameter('width', 0.01, 0.001, 0.02)
|
|
42
|
+
|
|
43
|
+
# If there are parameters that were set as
|
|
44
|
+
# design variables during training and wanted
|
|
45
|
+
# to fix during optimization, specify only the
|
|
46
|
+
# `initial_value` and set the `fix` argument True.
|
|
47
|
+
# You cannot add design variables that were not
|
|
48
|
+
# set during training for optimization.
|
|
49
|
+
femopt.add_parameter('base_radius', 0.008, fix=True)
|
|
50
|
+
|
|
51
|
+
# Specify the objective functions set during
|
|
52
|
+
# training that you want to optimize.
|
|
53
|
+
# You may provide the fun argument, but it will
|
|
54
|
+
# be overwritten during surrogate model creation,
|
|
55
|
+
# so it will be ignored.
|
|
56
|
+
# You cannot use objective functions that were
|
|
57
|
+
# not set during training for optimization.
|
|
58
|
+
obj_name = 'First Resonant Frequency (Hz)'
|
|
59
|
+
femopt.add_objective(
|
|
60
|
+
name=obj_name,
|
|
61
|
+
direction=target,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Execute the optimization.
|
|
65
|
+
femopt.set_random_seed(42)
|
|
66
|
+
df = femopt.optimize(
|
|
67
|
+
n_trials=50,
|
|
68
|
+
confirm_before_exit=False
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Display the optimal solution.
|
|
72
|
+
prm_names = femopt.history.prm_names
|
|
73
|
+
obj_names = femopt.history.obj_names
|
|
74
|
+
prm_values = df[df['non_domi'] == True][prm_names].values[0]
|
|
75
|
+
obj_values = df[df['non_domi'] == True][obj_names].values[0]
|
|
76
|
+
|
|
77
|
+
message = f'''
|
|
78
|
+
===== Optimization Results =====
|
|
79
|
+
Target Value: {target}
|
|
80
|
+
Prediction by Surrogate Model:
|
|
81
|
+
'''
|
|
82
|
+
for name, value in zip(prm_names, prm_values):
|
|
83
|
+
message += f' {name}: {value}\n'
|
|
84
|
+
for name, value in zip(obj_names, obj_values):
|
|
85
|
+
message += f' {name}: {value}\n'
|
|
86
|
+
|
|
87
|
+
return message
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if __name__ == '__main__':
|
|
91
|
+
# Using the surrogate model created from the training data,
|
|
92
|
+
# we will find a design that results in a resonant frequency of 1000.
|
|
93
|
+
message_1000 = main(target=1000)
|
|
94
|
+
|
|
95
|
+
# Next, using the same surrogate model,
|
|
96
|
+
# we will find a design that results in a resonant frequency of 2000.
|
|
97
|
+
message_2000 = main(target=2000)
|
|
98
|
+
|
|
99
|
+
print(message_1000)
|
|
100
|
+
print(message_2000)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from optuna.samplers import TPESampler
|
|
4
|
+
|
|
5
|
+
from pyfemtet.opt import FEMOpt, OptunaOptimizer
|
|
6
|
+
from pyfemtet.opt.interface import PoFBoTorchInterface
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main(target):
|
|
10
|
+
|
|
11
|
+
os.chdir(os.path.dirname(__file__))
|
|
12
|
+
|
|
13
|
+
# Femtet との接続の代わりに、サロゲートモデルを作成します。
|
|
14
|
+
# 学習データ作成スクリプトで作成した csv ファイルを読み込んで
|
|
15
|
+
# サロゲートモデルを作成します。
|
|
16
|
+
fem = PoFBoTorchInterface(
|
|
17
|
+
history_path='training_data.csv'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# 最適化用オブジェクトの設定を行います。
|
|
21
|
+
opt = OptunaOptimizer(
|
|
22
|
+
sampler_class=TPESampler,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# FEMOpt オブジェクトの設定を行います。
|
|
26
|
+
femopt = FEMOpt(
|
|
27
|
+
fem=fem,
|
|
28
|
+
opt=opt,
|
|
29
|
+
history_path=f'optimized_result_target_{target}.csv'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# 設計変数の設定を行います。
|
|
33
|
+
# 上下限は学習データ作成スクリプトと異なっても良いですが、
|
|
34
|
+
# 学習していない範囲は外挿となりサロゲートモデルによる
|
|
35
|
+
# 予測精度が低下することに注意してください。
|
|
36
|
+
femopt.add_parameter('length', 0.1, 0.02, 0.2)
|
|
37
|
+
femopt.add_parameter('width', 0.01, 0.001, 0.02)
|
|
38
|
+
|
|
39
|
+
# 学習時は設計変数としていたが最適化時に固定したいパラメータがある場合
|
|
40
|
+
# initial_value のみを指定して fix 引数を True にしてください。
|
|
41
|
+
# 学習時に設定しなかった設計変数を最適化時に追加することはできません。
|
|
42
|
+
femopt.add_parameter('base_radius', 0.008, fix=True)
|
|
43
|
+
|
|
44
|
+
# 学習時に設定した目的関数のうち
|
|
45
|
+
# 最適化したいものを指定します。
|
|
46
|
+
# fun 引数は与えてもいいですが、サロゲートモデル作成時に上書きされるため無視されます。
|
|
47
|
+
# 学習時に設定しなかった目的関数を最適化時に使用することはできません。
|
|
48
|
+
obj_name = '第一共振周波数(Hz)'
|
|
49
|
+
femopt.add_objective(
|
|
50
|
+
name=obj_name,
|
|
51
|
+
direction=target,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# 最適化を実行します。
|
|
55
|
+
femopt.set_random_seed(42)
|
|
56
|
+
df = femopt.optimize(
|
|
57
|
+
n_trials=50,
|
|
58
|
+
confirm_before_exit=False
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# 最適解を表示します。
|
|
62
|
+
prm_names = femopt.history.prm_names
|
|
63
|
+
obj_names = femopt.history.obj_names
|
|
64
|
+
prm_values = df[df['non_domi'] == True][prm_names].values[0]
|
|
65
|
+
obj_values = df[df['non_domi'] == True][obj_names].values[0]
|
|
66
|
+
|
|
67
|
+
message = f'''
|
|
68
|
+
===== 最適化結果 =====
|
|
69
|
+
ターゲット値: {target}
|
|
70
|
+
サロゲートモデルによる予測:
|
|
71
|
+
'''
|
|
72
|
+
for name, value in zip(prm_names, prm_values):
|
|
73
|
+
message += f' {name}: {value}\n'
|
|
74
|
+
for name, value in zip(obj_names, obj_values):
|
|
75
|
+
message += f' {name}: {value}\n'
|
|
76
|
+
|
|
77
|
+
return message
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == '__main__':
|
|
81
|
+
# 学習データから作成したサロゲートモデルで
|
|
82
|
+
# 共振周波数が 1000 になる設計を見つけます。
|
|
83
|
+
message_1000 = main(target=1000)
|
|
84
|
+
|
|
85
|
+
# 続いて、同じサロゲートモデルで
|
|
86
|
+
# 共振周波数が 2000 になる設計を見つけます。
|
|
87
|
+
message_2000 = main(target=2000)
|
|
88
|
+
|
|
89
|
+
print(message_1000)
|
|
90
|
+
print(message_2000)
|
|
Binary file
|
|
@@ -3,6 +3,7 @@ from pyfemtet.opt.interface._base import NoFEM
|
|
|
3
3
|
from pyfemtet.opt.interface._femtet import FemtetInterface
|
|
4
4
|
from pyfemtet.opt.interface._femtet_with_sldworks import FemtetWithSolidworksInterface
|
|
5
5
|
from pyfemtet.opt.interface._femtet_with_nx import FemtetWithNXInterface
|
|
6
|
+
from pyfemtet.opt.interface._surrogate import PoFBoTorchInterface
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
@@ -11,4 +12,5 @@ __all__ = [
|
|
|
11
12
|
'FemtetInterface',
|
|
12
13
|
'FemtetWithNXInterface',
|
|
13
14
|
'FemtetWithSolidworksInterface',
|
|
15
|
+
'PoFBoTorchInterface',
|
|
14
16
|
]
|
pyfemtet/opt/interface/_base.py
CHANGED
|
@@ -55,6 +55,9 @@ class FEMInterface(ABC):
|
|
|
55
55
|
def load_objective(self, opt) -> None: # opt: AbstractOptimizer
|
|
56
56
|
raise NotImplementedError()
|
|
57
57
|
|
|
58
|
+
def load_constraint(self, opt) -> None: # opt: AbstractOptimizer
|
|
59
|
+
raise NotImplementedError()
|
|
60
|
+
|
|
58
61
|
def _setup_before_parallel(self, client) -> None:
|
|
59
62
|
"""Preprocessing before launching a dask worker (if implemented in concrete class).
|
|
60
63
|
|