pyfemtet 0.4.7__tar.gz → 0.4.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyfemtet might be problematic. Click here for more details.
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/PKG-INFO +1 -1
- pyfemtet-0.4.9/pyfemtet/__init__.py +1 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/_test_util.py +21 -1
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/_femopt.py +1 -4
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/_femopt_core.py +21 -4
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_NX.py +11 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_SW.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/gal_ex58_parametric.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/gau_ex08_parametric.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/her_ex40_parametric.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/paswat_ex1_parametric.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/paswat_ex1_parametric_parallel.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/wat_ex14_parametric.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/cad_ex01_NX_jp.py +11 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/cad_ex01_SW_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/gal_ex58_parametric_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/gau_ex08_parametric_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/her_ex40_parametric_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.py +7 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_base.py +6 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_femtet.py +159 -19
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_femtet_with_nx/_interface.py +35 -2
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_femtet_with_nx/update_model.py +36 -28
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/opt/_base.py +2 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/visualization/_graphs.py +10 -13
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/visualization/_monitor.py +89 -11
- pyfemtet-0.4.9/pyfemtet/opt/visualization/result_viewer.py +13 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyproject.toml +2 -2
- pyfemtet-0.4.7/pyfemtet/__init__.py +0 -1
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/LICENSE +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/README.md +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.prt +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/NX_ex01/NX_ex01.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/Sldworks_ex01/Sldworks_ex01.SLDPRT +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/Sldworks_ex01/Sldworks_ex01.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/Sldworks_ex01/Sldworks_ex01.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/_her_ex40_parametric.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/gau_ex08_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/gau_ex08_parametric.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/her_ex40_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/her_ex40_parametric.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/wat_ex14_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/FemtetPJTSample/wat_ex14_parametric.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/core.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/dispatch_extensions.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/logger.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/__init__.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_NX.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_NX.prt +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_NX_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_SW.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/cad_ex01_SW_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/gal_ex58_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/gal_ex58_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/gau_ex08_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/gau_ex08_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/her_ex40_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/her_ex40_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/paswat_ex1_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/paswat_ex1_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/wat_ex14_parametric.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/wat_ex14_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.femprj +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/__init__.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_femtet_parametric.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/opt/__init__.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/opt/_optuna.py +0 -0
- {pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/visualization/__init__.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.9"
|
|
@@ -86,10 +86,30 @@ def _get_obj_from_csv(csv_path):
|
|
|
86
86
|
return out, columns
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
def is_equal_result(csv1, csv2):
|
|
89
|
+
def is_equal_result(csv1, csv2, result_save_to=None):
|
|
90
90
|
"""Check the equality of two result csv files."""
|
|
91
91
|
df1, columns1 = _get_obj_from_csv(csv1)
|
|
92
92
|
df2, columns2 = _get_obj_from_csv(csv2)
|
|
93
|
+
|
|
94
|
+
if result_save_to is not None:
|
|
95
|
+
import datetime
|
|
96
|
+
with open(result_save_to, 'a', encoding='utf-8', newline='\n') as f:
|
|
97
|
+
name = os.path.basename(csv1)
|
|
98
|
+
content = [
|
|
99
|
+
f'===== result of {name} =====\n',
|
|
100
|
+
f'{datetime.datetime.now()}\n',
|
|
101
|
+
f'----- column numbers -----\n',
|
|
102
|
+
f'csv1: {len(columns1)} columns\n',
|
|
103
|
+
f'csv2: {len(columns2)} columns\n',
|
|
104
|
+
f'----- row numbers -----\n',
|
|
105
|
+
f'csv1: {len(df1)} columns\n',
|
|
106
|
+
f'csv2: {len(df2)} columns\n',
|
|
107
|
+
f'----- difference -----\n',
|
|
108
|
+
f'max difference ratio: {(np.abs(df1.values - df2.values) / np.abs(df2.values)).max() * 100}%\n',
|
|
109
|
+
'\n'
|
|
110
|
+
]
|
|
111
|
+
f.writelines(content)
|
|
112
|
+
|
|
93
113
|
assert len(columns1) == len(columns2), '結果 csv の column 数が異なります。'
|
|
94
114
|
assert len(df1) == len(df2), '結果 csv の row 数が異なります。'
|
|
95
115
|
assert (np.abs(df1.values - df2.values) / np.abs(df2.values)).max() <= 0.01, '前回の結果と 1% を超える相違があります。'
|
|
@@ -513,10 +513,7 @@ class FEMOpt:
|
|
|
513
513
|
sleep(1)
|
|
514
514
|
|
|
515
515
|
# terminate monitor process
|
|
516
|
-
|
|
517
|
-
self.status.set(OptimizationStatus.CRASHED)
|
|
518
|
-
else:
|
|
519
|
-
self.status.set(OptimizationStatus.TERMINATE_ALL)
|
|
516
|
+
self.status.set(OptimizationStatus.TERMINATE_ALL)
|
|
520
517
|
logger.info(self.monitor_process_future.result())
|
|
521
518
|
sleep(1)
|
|
522
519
|
|
|
@@ -14,7 +14,7 @@ import numpy as np
|
|
|
14
14
|
import pandas as pd
|
|
15
15
|
from scipy.stats.qmc import LatinHypercube
|
|
16
16
|
from optuna._hypervolume import WFG
|
|
17
|
-
from dask.distributed import Lock
|
|
17
|
+
from dask.distributed import Lock, get_client
|
|
18
18
|
|
|
19
19
|
# win32com
|
|
20
20
|
from win32com.client import constants, Constants
|
|
@@ -532,7 +532,17 @@ class History:
|
|
|
532
532
|
|
|
533
533
|
return columns, metadata
|
|
534
534
|
|
|
535
|
-
def record(
|
|
535
|
+
def record(
|
|
536
|
+
self,
|
|
537
|
+
parameters,
|
|
538
|
+
objectives,
|
|
539
|
+
constraints,
|
|
540
|
+
obj_values,
|
|
541
|
+
cns_values,
|
|
542
|
+
message,
|
|
543
|
+
postprocess_func,
|
|
544
|
+
postprocess_args,
|
|
545
|
+
):
|
|
536
546
|
"""Records the optimization results in the history.
|
|
537
547
|
|
|
538
548
|
Record only. NOT save.
|
|
@@ -544,7 +554,8 @@ class History:
|
|
|
544
554
|
obj_values (list): The objective values.
|
|
545
555
|
cns_values (list): The constraint values.
|
|
546
556
|
message (str): Additional information or messages related to the optimization results.
|
|
547
|
-
|
|
557
|
+
postprocess_func (Callable): fem method to call after solving. i.e. save result file. Must take trial(int) for 1st argument.
|
|
558
|
+
postprocess_args (dict): arguments for `postprocess_func`. i.e. create binary data of result file in the worker process.
|
|
548
559
|
"""
|
|
549
560
|
|
|
550
561
|
# create row
|
|
@@ -591,6 +602,12 @@ class History:
|
|
|
591
602
|
self._calc_hypervolume(objectives) # update self.local_data
|
|
592
603
|
self.actor_data = self.local_data
|
|
593
604
|
|
|
605
|
+
# save file
|
|
606
|
+
if postprocess_args is not None:
|
|
607
|
+
trial = self.local_data['trial'].values[-1]
|
|
608
|
+
client = get_client() # always returns valid client
|
|
609
|
+
client.run_on_scheduler(postprocess_func, trial, **postprocess_args)
|
|
610
|
+
|
|
594
611
|
def _calc_non_domi(self, objectives):
|
|
595
612
|
|
|
596
613
|
# 目的関数の履歴を取り出してくる
|
|
@@ -696,8 +713,8 @@ class OptimizationStatus:
|
|
|
696
713
|
RUNNING = 30
|
|
697
714
|
INTERRUPTING = 40
|
|
698
715
|
TERMINATED = 50
|
|
699
|
-
CRASHED = 55
|
|
700
716
|
TERMINATE_ALL = 60
|
|
717
|
+
CRASHED = 70
|
|
701
718
|
|
|
702
719
|
def __init__(self, client, name='entire'):
|
|
703
720
|
self._future = client.submit(_OptimizationStatusActor, actor=True)
|
|
@@ -107,6 +107,10 @@ if __name__ == '__main__':
|
|
|
107
107
|
fem = FemtetWithNXInterface(
|
|
108
108
|
prt_path='cad_ex01_NX.prt',
|
|
109
109
|
open_result_with_gui=False, # To calculate von Mises stress, set this argument to False. See Femtet Macro Help.
|
|
110
|
+
export_curves=False,
|
|
111
|
+
export_surfaces=False,
|
|
112
|
+
export_solids=True,
|
|
113
|
+
export_flattened_assembly=False,
|
|
110
114
|
)
|
|
111
115
|
|
|
112
116
|
# Initialize the FEMOpt object.
|
|
@@ -129,4 +133,11 @@ if __name__ == '__main__':
|
|
|
129
133
|
# Run optimization.
|
|
130
134
|
femopt.set_random_seed(42)
|
|
131
135
|
femopt.optimize(n_trials=20)
|
|
136
|
+
|
|
137
|
+
# Stop script to keep process alive
|
|
138
|
+
# while you check the result in process monitor.
|
|
139
|
+
print('================================')
|
|
140
|
+
print('Finished. Press Enter to quit...')
|
|
141
|
+
print('================================')
|
|
142
|
+
input()
|
|
132
143
|
femopt.terminate_all()
|
|
@@ -129,4 +129,11 @@ if __name__ == '__main__':
|
|
|
129
129
|
# Run optimization.
|
|
130
130
|
femopt.set_random_seed(42)
|
|
131
131
|
femopt.optimize(n_trials=20)
|
|
132
|
+
|
|
133
|
+
# Stop script to keep process alive
|
|
134
|
+
# while you check the result in process monitor.
|
|
135
|
+
print('================================')
|
|
136
|
+
print('Finished. Press Enter to quit...')
|
|
137
|
+
print('================================')
|
|
138
|
+
input()
|
|
132
139
|
femopt.terminate_all()
|
|
@@ -72,4 +72,11 @@ if __name__ == '__main__':
|
|
|
72
72
|
# Run optimization.
|
|
73
73
|
femopt.set_random_seed(42)
|
|
74
74
|
femopt.optimize(n_trials=10)
|
|
75
|
+
|
|
76
|
+
# Stop script to keep process alive
|
|
77
|
+
# while you check the result in process monitor.
|
|
78
|
+
print('================================')
|
|
79
|
+
print('Finished. Press Enter to quit...')
|
|
80
|
+
print('================================')
|
|
81
|
+
input()
|
|
75
82
|
femopt.terminate_all()
|
|
@@ -56,4 +56,11 @@ if __name__ == '__main__':
|
|
|
56
56
|
# Run optimization.
|
|
57
57
|
femopt.set_random_seed(42)
|
|
58
58
|
femopt.optimize(n_trials=20)
|
|
59
|
+
|
|
60
|
+
# Stop script to keep process alive
|
|
61
|
+
# while you check the result in process monitor.
|
|
62
|
+
print('================================')
|
|
63
|
+
print('Finished. Press Enter to quit...')
|
|
64
|
+
print('================================')
|
|
65
|
+
input()
|
|
59
66
|
femopt.terminate_all()
|
|
@@ -134,4 +134,11 @@ if __name__ == '__main__':
|
|
|
134
134
|
|
|
135
135
|
femopt.set_random_seed(42)
|
|
136
136
|
femopt.optimize(n_trials=15)
|
|
137
|
+
|
|
138
|
+
# Stop script to keep process alive
|
|
139
|
+
# while you check the result in process monitor.
|
|
140
|
+
print('================================')
|
|
141
|
+
print('Finished. Press Enter to quit...')
|
|
142
|
+
print('================================')
|
|
143
|
+
input()
|
|
137
144
|
femopt.terminate_all()
|
|
@@ -58,4 +58,11 @@ if __name__ == '__main__':
|
|
|
58
58
|
# Run optimization.
|
|
59
59
|
femopt.set_random_seed(42)
|
|
60
60
|
femopt.optimize(n_trials=15)
|
|
61
|
+
|
|
62
|
+
# Stop script to keep process alive
|
|
63
|
+
# while you check the result in process monitor.
|
|
64
|
+
print('================================')
|
|
65
|
+
print('Finished. Press Enter to quit...')
|
|
66
|
+
print('================================')
|
|
67
|
+
input()
|
|
61
68
|
femopt.terminate_all()
|
{pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample/paswat_ex1_parametric_parallel.py
RENAMED
|
@@ -59,4 +59,11 @@ if __name__ == '__main__':
|
|
|
59
59
|
femopt.set_random_seed(42)
|
|
60
60
|
# femopt.optimize(n_trials=15)
|
|
61
61
|
femopt.optimize(n_trials=30, n_parallel=3) # This line is the only difference with no parallel pattern.
|
|
62
|
+
|
|
63
|
+
# Stop script to keep process alive
|
|
64
|
+
# while you check the result in process monitor.
|
|
65
|
+
print('================================')
|
|
66
|
+
print('Finished. Press Enter to quit...')
|
|
67
|
+
print('================================')
|
|
68
|
+
input()
|
|
62
69
|
femopt.terminate_all()
|
|
@@ -56,4 +56,11 @@ if __name__ == '__main__':
|
|
|
56
56
|
# Run optimization.
|
|
57
57
|
femopt.set_random_seed(42)
|
|
58
58
|
femopt.optimize(n_trials=15)
|
|
59
|
+
|
|
60
|
+
# Stop script to keep process alive
|
|
61
|
+
# while you check the result in process monitor.
|
|
62
|
+
print('================================')
|
|
63
|
+
print('Finished. Press Enter to quit...')
|
|
64
|
+
print('================================')
|
|
65
|
+
input()
|
|
59
66
|
femopt.terminate_all()
|
|
@@ -103,6 +103,10 @@ if __name__ == '__main__':
|
|
|
103
103
|
fem = FemtetWithNXInterface(
|
|
104
104
|
prt_path='cad_ex01_NX.prt',
|
|
105
105
|
open_result_with_gui=False,
|
|
106
|
+
export_curves=False,
|
|
107
|
+
export_surfaces=False,
|
|
108
|
+
export_solids=True,
|
|
109
|
+
export_flattened_assembly=False,
|
|
106
110
|
)
|
|
107
111
|
|
|
108
112
|
# FEMOpt オブジェクトの初期化 (最適化問題とFemtetとの接続を行います)
|
|
@@ -123,4 +127,11 @@ if __name__ == '__main__':
|
|
|
123
127
|
# 最適化を実行
|
|
124
128
|
femopt.set_random_seed(42)
|
|
125
129
|
femopt.optimize(n_trials=20)
|
|
130
|
+
|
|
131
|
+
# プロセスモニタで結果を確認するために
|
|
132
|
+
# Enter キーが押されるまで処理を停止します。
|
|
133
|
+
print('================================')
|
|
134
|
+
print('Finished. Press Enter to quit...')
|
|
135
|
+
print('================================')
|
|
136
|
+
input()
|
|
126
137
|
femopt.terminate_all()
|
|
@@ -123,4 +123,11 @@ if __name__ == '__main__':
|
|
|
123
123
|
# 最適化を実行
|
|
124
124
|
femopt.set_random_seed(42)
|
|
125
125
|
femopt.optimize(n_trials=20)
|
|
126
|
+
|
|
127
|
+
# プロセスモニタで結果を確認するために
|
|
128
|
+
# Enter キーが押されるまで処理を停止します。
|
|
129
|
+
print('================================')
|
|
130
|
+
print('Finished. Press Enter to quit...')
|
|
131
|
+
print('================================')
|
|
132
|
+
input()
|
|
126
133
|
femopt.terminate_all()
|
|
@@ -68,4 +68,11 @@ if __name__ == '__main__':
|
|
|
68
68
|
# 最適化を実行
|
|
69
69
|
femopt.set_random_seed(42)
|
|
70
70
|
femopt.optimize(n_trials=10)
|
|
71
|
+
|
|
72
|
+
# プロセスモニタで結果を確認するために
|
|
73
|
+
# Enter キーが押されるまで処理を停止します。
|
|
74
|
+
print('================================')
|
|
75
|
+
print('Finished. Press Enter to quit...')
|
|
76
|
+
print('================================')
|
|
77
|
+
input()
|
|
71
78
|
femopt.terminate_all()
|
|
@@ -55,4 +55,11 @@ if __name__ == '__main__':
|
|
|
55
55
|
# 最適化を実行
|
|
56
56
|
femopt.set_random_seed(42)
|
|
57
57
|
femopt.optimize(n_trials=20)
|
|
58
|
+
|
|
59
|
+
# プロセスモニタで結果を確認するために
|
|
60
|
+
# Enter キーが押されるまで処理を停止します。
|
|
61
|
+
print('================================')
|
|
62
|
+
print('Finished. Press Enter to quit...')
|
|
63
|
+
print('================================')
|
|
64
|
+
input()
|
|
58
65
|
femopt.terminate_all()
|
|
@@ -134,4 +134,11 @@ if __name__ == '__main__':
|
|
|
134
134
|
|
|
135
135
|
femopt.set_random_seed(42)
|
|
136
136
|
femopt.optimize(n_trials=15)
|
|
137
|
+
|
|
138
|
+
# プロセスモニタで結果を確認するために
|
|
139
|
+
# Enter キーが押されるまで処理を停止します。
|
|
140
|
+
print('================================')
|
|
141
|
+
print('Finished. Press Enter to quit...')
|
|
142
|
+
print('================================')
|
|
143
|
+
input()
|
|
137
144
|
femopt.terminate_all()
|
|
@@ -56,4 +56,11 @@ if __name__ == '__main__':
|
|
|
56
56
|
# 最適化を実行
|
|
57
57
|
femopt.set_random_seed(42)
|
|
58
58
|
femopt.optimize(n_trials=15)
|
|
59
|
+
|
|
60
|
+
# プロセスモニタで結果を確認するために
|
|
61
|
+
# Enter キーが押されるまで処理を停止します。
|
|
62
|
+
print('================================')
|
|
63
|
+
print('Finished. Press Enter to quit...')
|
|
64
|
+
print('================================')
|
|
65
|
+
input()
|
|
59
66
|
femopt.terminate_all()
|
{pyfemtet-0.4.7 → pyfemtet-0.4.9}/pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py
RENAMED
|
@@ -57,4 +57,11 @@ if __name__ == '__main__':
|
|
|
57
57
|
femopt.set_random_seed(42)
|
|
58
58
|
# femopt.optimize(n_trials=15)
|
|
59
59
|
femopt.optimize(n_trials=30, n_parallel=3) # 並列計算しない場合との差はこの行のみです。
|
|
60
|
+
|
|
61
|
+
# プロセスモニタで結果を確認するために
|
|
62
|
+
# Enter キーが押されるまで処理を停止します。
|
|
63
|
+
print('================================')
|
|
64
|
+
print('Finished. Press Enter to quit...')
|
|
65
|
+
print('================================')
|
|
66
|
+
input()
|
|
60
67
|
femopt.terminate_all()
|
|
@@ -54,4 +54,11 @@ if __name__ == '__main__':
|
|
|
54
54
|
# 最適化を実行
|
|
55
55
|
femopt.set_random_seed(42)
|
|
56
56
|
femopt.optimize(n_trials=15)
|
|
57
|
+
|
|
58
|
+
# プロセスモニタで結果を確認するために
|
|
59
|
+
# Enter キーが押されるまで処理を停止します。
|
|
60
|
+
print('================================')
|
|
61
|
+
print('Finished. Press Enter to quit...')
|
|
62
|
+
print('================================')
|
|
63
|
+
input()
|
|
57
64
|
femopt.terminate_all()
|
|
@@ -63,6 +63,12 @@ class FEMInterface(ABC):
|
|
|
63
63
|
"""Preprocessing after launching a dask worker and before run optimization (if implemented in concrete class)."""
|
|
64
64
|
pass
|
|
65
65
|
|
|
66
|
+
def postprocess_func(self, trial: int, *args, dask_scheduler=None, **kwargs):
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
def create_postprocess_args(self):
|
|
70
|
+
pass
|
|
71
|
+
|
|
66
72
|
|
|
67
73
|
class NoFEM(FEMInterface):
|
|
68
74
|
"""Interface with no FEM for debug."""
|
|
@@ -59,9 +59,10 @@ class FemtetInterface(FEMInterface):
|
|
|
59
59
|
self,
|
|
60
60
|
femprj_path=None,
|
|
61
61
|
model_name=None,
|
|
62
|
-
connect_method='auto',
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
connect_method='auto', # dask worker では __init__ の中で 'new' にするので super() の引数にしない。(しても意味がない)
|
|
63
|
+
save_pdt='all', # 'all' or None
|
|
64
|
+
strictly_pid_specify=True, # dask worker では True にしたいので super() の引数にしない。
|
|
65
|
+
allow_without_project=False, # main でのみ True を許容したいので super() の引数にしない。
|
|
65
66
|
open_result_with_gui=True,
|
|
66
67
|
parametric_output_indexes_use_as_objective=None,
|
|
67
68
|
**kwargs # 継承されたクラスからの引数
|
|
@@ -80,6 +81,7 @@ class FemtetInterface(FEMInterface):
|
|
|
80
81
|
self.allow_without_project = allow_without_project
|
|
81
82
|
self.original_femprj_path = self.femprj_path
|
|
82
83
|
self.open_result_with_gui = open_result_with_gui
|
|
84
|
+
self.save_pdt = save_pdt
|
|
83
85
|
|
|
84
86
|
# その他のメンバーの宣言や初期化
|
|
85
87
|
self.Femtet = None
|
|
@@ -106,6 +108,15 @@ class FemtetInterface(FEMInterface):
|
|
|
106
108
|
# 開かれたモデルに応じて femprj_path と model を更新する
|
|
107
109
|
self._connect_and_open_femtet()
|
|
108
110
|
|
|
111
|
+
# original_fem_prj が None なら必ず
|
|
112
|
+
# dask worker でないプロセスがオリジナルファイルを開いている
|
|
113
|
+
if self.original_femprj_path is None:
|
|
114
|
+
# dask worker でなければ original のはず
|
|
115
|
+
try:
|
|
116
|
+
worker = get_worker()
|
|
117
|
+
except ValueError:
|
|
118
|
+
self.original_femprj_path = self.femprj_path
|
|
119
|
+
|
|
109
120
|
# 接続した Femtet の種類に応じて del 時に quit するかどうか決める
|
|
110
121
|
self.quit_when_destruct = self.connected_method == 'new'
|
|
111
122
|
|
|
@@ -117,26 +128,13 @@ class FemtetInterface(FEMInterface):
|
|
|
117
128
|
model_name=self.model_name,
|
|
118
129
|
open_result_with_gui=self.open_result_with_gui,
|
|
119
130
|
parametric_output_indexes_use_as_objective=self.parametric_output_indexes_use_as_objective,
|
|
131
|
+
save_pdt=self.save_pdt,
|
|
120
132
|
**kwargs
|
|
121
133
|
)
|
|
122
134
|
|
|
123
135
|
def __del__(self):
|
|
124
136
|
if self.quit_when_destruct:
|
|
125
|
-
|
|
126
|
-
# 強制終了 TODO: 自動保存を回避する
|
|
127
|
-
hwnd = self.Femtet.hWnd
|
|
128
|
-
pid = _get_pid(hwnd)
|
|
129
|
-
util.close_femtet(hwnd, 1, True)
|
|
130
|
-
start = time()
|
|
131
|
-
while psutil.pid_exists(pid):
|
|
132
|
-
if time() - start > 30: # 30 秒経っても存在するのは何かおかしい
|
|
133
|
-
os.kill(pid, signal.SIGKILL)
|
|
134
|
-
break
|
|
135
|
-
sleep(1)
|
|
136
|
-
sleep(1)
|
|
137
|
-
|
|
138
|
-
except (AttributeError, OSError): # already dead
|
|
139
|
-
pass
|
|
137
|
+
self.quit()
|
|
140
138
|
# CoUninitialize() # Win32 exception occurred releasing IUnknown at 0x0000022427692748
|
|
141
139
|
|
|
142
140
|
def _connect_new_femtet(self):
|
|
@@ -626,8 +624,25 @@ class FemtetInterface(FEMInterface):
|
|
|
626
624
|
print('================')
|
|
627
625
|
input('終了するには Enter を押してください。')
|
|
628
626
|
raise e
|
|
627
|
+
|
|
629
628
|
else:
|
|
630
|
-
|
|
629
|
+
hwnd = self.Femtet.hWnd
|
|
630
|
+
|
|
631
|
+
# terminate
|
|
632
|
+
util.close_femtet(hwnd, timeout, force)
|
|
633
|
+
|
|
634
|
+
try:
|
|
635
|
+
pid = _get_pid(hwnd)
|
|
636
|
+
start = time()
|
|
637
|
+
while psutil.pid_exists(pid):
|
|
638
|
+
if time() - start > 30: # 30 秒経っても存在するのは何かおかしい
|
|
639
|
+
logger.error('Femtet の終了に失敗しました。')
|
|
640
|
+
break
|
|
641
|
+
sleep(1)
|
|
642
|
+
sleep(1)
|
|
643
|
+
|
|
644
|
+
except (AttributeError, OSError): # already dead
|
|
645
|
+
pass
|
|
631
646
|
|
|
632
647
|
def _setup_before_parallel(self, client):
|
|
633
648
|
client.upload_file(
|
|
@@ -637,3 +652,128 @@ class FemtetInterface(FEMInterface):
|
|
|
637
652
|
|
|
638
653
|
def _version(self):
|
|
639
654
|
return _version(Femtet=self.Femtet)
|
|
655
|
+
|
|
656
|
+
def create_postprocess_args(self):
|
|
657
|
+
file_content = self.create_result_file_content()
|
|
658
|
+
jpg_content = self.create_jpg_content()
|
|
659
|
+
|
|
660
|
+
out = dict(
|
|
661
|
+
original_femprj_path=self.original_femprj_path,
|
|
662
|
+
model_name=self.model_name,
|
|
663
|
+
pdt_file_content=file_content,
|
|
664
|
+
jpg_file_content=jpg_content,
|
|
665
|
+
)
|
|
666
|
+
return out
|
|
667
|
+
|
|
668
|
+
@staticmethod
|
|
669
|
+
def postprocess_func(
|
|
670
|
+
trial: int,
|
|
671
|
+
original_femprj_path: str,
|
|
672
|
+
model_name: str,
|
|
673
|
+
pdt_file_content=None,
|
|
674
|
+
jpg_file_content=None,
|
|
675
|
+
dask_scheduler=None
|
|
676
|
+
):
|
|
677
|
+
result_dir = original_femprj_path.replace('.femprj', '.Results')
|
|
678
|
+
if pdt_file_content is not None:
|
|
679
|
+
pdt_path = os.path.join(result_dir, model_name + f'_trial{trial}.pdt')
|
|
680
|
+
with open(pdt_path, 'wb') as f:
|
|
681
|
+
f.write(pdt_file_content)
|
|
682
|
+
|
|
683
|
+
if jpg_file_content is not None:
|
|
684
|
+
jpg_path = os.path.join(result_dir, model_name + f'_trial{trial}.jpg')
|
|
685
|
+
with open(jpg_path, 'wb') as f:
|
|
686
|
+
f.write(jpg_file_content)
|
|
687
|
+
|
|
688
|
+
def create_result_file_content(self):
|
|
689
|
+
"""Called after solve"""
|
|
690
|
+
if self.save_pdt == 'all':
|
|
691
|
+
# save to worker space
|
|
692
|
+
result_dir = self.femprj_path.replace('.femprj', '.Results')
|
|
693
|
+
pdt_path = os.path.join(result_dir, self.model_name + '.pdt')
|
|
694
|
+
succeed = self.Femtet.SavePDT(pdt_path, True)
|
|
695
|
+
|
|
696
|
+
# convert .pdt to ByteIO
|
|
697
|
+
if succeed:
|
|
698
|
+
with open(pdt_path, 'rb') as f:
|
|
699
|
+
content = f.read()
|
|
700
|
+
return content
|
|
701
|
+
|
|
702
|
+
else:
|
|
703
|
+
raise Exception('pdt ファイルの保存でエラーが発生しました。')
|
|
704
|
+
|
|
705
|
+
else:
|
|
706
|
+
return None
|
|
707
|
+
|
|
708
|
+
def create_jpg_content(self):
|
|
709
|
+
result_dir = self.femprj_path.replace('.femprj', '.Results')
|
|
710
|
+
jpg_path = os.path.join(result_dir, self.model_name + '.jpg')
|
|
711
|
+
|
|
712
|
+
# モデル表示画面の設定
|
|
713
|
+
self.Femtet.SetWindowSize(200, 200)
|
|
714
|
+
self.Femtet.Fit()
|
|
715
|
+
self.Femtet.ViewNumeric.SetCoord(1, 1, 1)
|
|
716
|
+
|
|
717
|
+
# ---モデルの画面を保存---
|
|
718
|
+
self.Femtet.Redraw() # 再描画
|
|
719
|
+
succeed = self.Femtet.SavePicture(jpg_path, 200, 200, 80)
|
|
720
|
+
|
|
721
|
+
self.Femtet.RedrawMode = True # 逐一の描画をオン
|
|
722
|
+
|
|
723
|
+
if not succeed:
|
|
724
|
+
raise Exception('jpg ファイルの保存でエラーが発生しました。')
|
|
725
|
+
|
|
726
|
+
if not os.path.exists(jpg_path):
|
|
727
|
+
raise Exception('保存した jpg ファイルが見つかりませんでした。')
|
|
728
|
+
|
|
729
|
+
with open(jpg_path, 'rb') as f:
|
|
730
|
+
content = f.read()
|
|
731
|
+
|
|
732
|
+
return content
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
from win32com.client import Dispatch, constants
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
class _UnPicklableNoFEM(FemtetInterface):
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
original_femprj_path = 'dummy'
|
|
742
|
+
model_name = 'dummy'
|
|
743
|
+
parametric_output_indexes_use_as_objective = None
|
|
744
|
+
kwargs = dict()
|
|
745
|
+
Femtet = None
|
|
746
|
+
quit_when_destruct = False
|
|
747
|
+
|
|
748
|
+
def __init__(self):
|
|
749
|
+
CoInitialize()
|
|
750
|
+
self.unpicklable_member = Dispatch('FemtetMacro.Femtet')
|
|
751
|
+
self.cns = constants
|
|
752
|
+
|
|
753
|
+
def _setup_before_parallel(self, *args, **kwargs):
|
|
754
|
+
pass
|
|
755
|
+
|
|
756
|
+
def check_param_value(self, *args, **kwargs):
|
|
757
|
+
pass
|
|
758
|
+
|
|
759
|
+
def update_parameter(self, *args, **kwargs):
|
|
760
|
+
pass
|
|
761
|
+
|
|
762
|
+
def update(self, *args, **kwargs):
|
|
763
|
+
pass
|
|
764
|
+
|
|
765
|
+
def create_result_file_content(self):
|
|
766
|
+
"""Called after solve"""
|
|
767
|
+
|
|
768
|
+
# save to worker space
|
|
769
|
+
with open(__file__, 'rb') as f:
|
|
770
|
+
content = f.read()
|
|
771
|
+
|
|
772
|
+
return content
|
|
773
|
+
|
|
774
|
+
def create_file_path(self, trial: int):
|
|
775
|
+
# return path of scheduler environment
|
|
776
|
+
here = os.path.dirname(__file__)
|
|
777
|
+
pdt_path = os.path.join(here, f'trial{trial}.pdt')
|
|
778
|
+
return pdt_path
|
|
779
|
+
|
|
@@ -17,6 +17,10 @@ class FemtetWithNXInterface(FemtetInterface):
|
|
|
17
17
|
|
|
18
18
|
Args:
|
|
19
19
|
prt_path: The path to the prt file.
|
|
20
|
+
export_curves(bool or None): Parasolid export setting of NX. If None, PyFemtet does not change the setting of NX. Defaults to None.
|
|
21
|
+
export_surfaces(bool or None): Parasolid export setting of NX. If None, PyFemtet does not change the setting of NX. Defaults to None.
|
|
22
|
+
export_solids(bool or None): Parasolid export setting of NX. If None, PyFemtet does not change the setting of NX. Defaults to None.
|
|
23
|
+
export_flattened_assembly(bool or None): Parasolid export setting of NX. If None, PyFemtet does not change the setting of NX. Defaults to None.
|
|
20
24
|
|
|
21
25
|
For details of The other arguments, see ``FemtetInterface``.
|
|
22
26
|
|
|
@@ -27,9 +31,12 @@ class FemtetWithNXInterface(FemtetInterface):
|
|
|
27
31
|
def __init__(
|
|
28
32
|
self,
|
|
29
33
|
prt_path,
|
|
34
|
+
export_curves: bool or None = None,
|
|
35
|
+
export_surfaces: bool or None = None,
|
|
36
|
+
export_solids: bool or None = None,
|
|
37
|
+
export_flattened_assembly: bool or None = None,
|
|
30
38
|
**kwargs
|
|
31
39
|
):
|
|
32
|
-
|
|
33
40
|
# check NX installation
|
|
34
41
|
self.run_journal_path = os.path.join(os.environ.get('UGII_BASE_DIR'), 'NXBIN', 'run_journal.exe')
|
|
35
42
|
if not os.path.isfile(self.run_journal_path):
|
|
@@ -45,10 +52,19 @@ class FemtetWithNXInterface(FemtetInterface):
|
|
|
45
52
|
except ValueError: # get_worker に失敗した場合
|
|
46
53
|
self.prt_path = os.path.abspath(prt_path)
|
|
47
54
|
|
|
55
|
+
self.export_curves = export_curves
|
|
56
|
+
self.export_surfaces = export_surfaces
|
|
57
|
+
self.export_solids = export_solids
|
|
58
|
+
self.export_flattened_assembly = export_flattened_assembly
|
|
59
|
+
|
|
48
60
|
# FemtetInterface の設定 (femprj_path, model_name の更新など)
|
|
49
61
|
# + restore 情報の上書き
|
|
50
62
|
super().__init__(
|
|
51
63
|
prt_path=self.prt_path,
|
|
64
|
+
export_curves=self.export_curves,
|
|
65
|
+
export_surfaces=self.export_surfaces,
|
|
66
|
+
export_solids=self.export_solids,
|
|
67
|
+
export_flattened_assembly=self.export_flattened_assembly,
|
|
52
68
|
**kwargs
|
|
53
69
|
)
|
|
54
70
|
|
|
@@ -86,10 +102,27 @@ class FemtetWithNXInterface(FemtetInterface):
|
|
|
86
102
|
tmp_dict[row['name']] = row['value']
|
|
87
103
|
str_json = json.dumps(tmp_dict)
|
|
88
104
|
|
|
105
|
+
# create dumped json of export settings
|
|
106
|
+
tmp_dict = dict(
|
|
107
|
+
include_curves=self.export_curves,
|
|
108
|
+
include_surfaces=self.export_surfaces,
|
|
109
|
+
include_solids=self.export_solids,
|
|
110
|
+
flatten_assembly=self.export_flattened_assembly,
|
|
111
|
+
)
|
|
112
|
+
dumped_json_export_settings = json.dumps(tmp_dict)
|
|
113
|
+
|
|
89
114
|
# NX journal を使ってモデルを編集する
|
|
90
115
|
env = os.environ.copy()
|
|
91
116
|
subprocess.run(
|
|
92
|
-
[
|
|
117
|
+
[
|
|
118
|
+
self.run_journal_path, # run_journal.exe
|
|
119
|
+
self._JOURNAL_PATH, # update_model.py
|
|
120
|
+
'-args',
|
|
121
|
+
self.prt_path,
|
|
122
|
+
str_json,
|
|
123
|
+
x_t_path,
|
|
124
|
+
dumped_json_export_settings,
|
|
125
|
+
],
|
|
93
126
|
env=env,
|
|
94
127
|
shell=True,
|
|
95
128
|
cwd=os.path.dirname(self.prt_path)
|