pyfemtet 0.4.1__py3-none-any.whl → 0.4.3__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 +60 -31
- pyfemtet/FemtetPJTSample/Sldworks_ex01/Sldworks_ex01.py +61 -39
- pyfemtet/FemtetPJTSample/_her_ex40_parametric.py +148 -0
- pyfemtet/FemtetPJTSample/gau_ex08_parametric.py +25 -22
- pyfemtet/FemtetPJTSample/her_ex40_parametric.py +59 -47
- pyfemtet/FemtetPJTSample/wat_ex14_parallel_parametric.py +31 -29
- pyfemtet/FemtetPJTSample/wat_ex14_parametric.py +29 -27
- pyfemtet/__init__.py +1 -1
- pyfemtet/opt/_femopt_core.py +3 -1
- pyfemtet/opt/femprj_sample/cad_ex01_NX.femprj +0 -0
- pyfemtet/opt/femprj_sample/cad_ex01_NX.prt +0 -0
- pyfemtet/opt/femprj_sample/cad_ex01_NX.py +132 -0
- pyfemtet/opt/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
- pyfemtet/opt/femprj_sample/cad_ex01_SW.femprj +0 -0
- pyfemtet/opt/femprj_sample/cad_ex01_SW.py +132 -0
- pyfemtet/opt/femprj_sample/gal_ex58_parametric.femprj +0 -0
- pyfemtet/opt/femprj_sample/gal_ex58_parametric.py +75 -0
- pyfemtet/opt/femprj_sample/gau_ex08_parametric.femprj +0 -0
- pyfemtet/opt/femprj_sample/gau_ex08_parametric.py +59 -0
- pyfemtet/opt/femprj_sample/her_ex40_parametric.femprj +0 -0
- pyfemtet/opt/femprj_sample/her_ex40_parametric.py +137 -0
- pyfemtet/opt/femprj_sample/paswat_ex1_parametric.femprj +0 -0
- pyfemtet/opt/femprj_sample/paswat_ex1_parametric.py +61 -0
- pyfemtet/opt/femprj_sample/paswat_ex1_parametric_parallel.py +62 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.femprj +0 -0
- pyfemtet/opt/femprj_sample/wat_ex14_parametric.py +59 -0
- pyfemtet/opt/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/cad_ex01_NX_jp.py +126 -0
- pyfemtet/opt/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/cad_ex01_SW_jp.py +126 -0
- pyfemtet/opt/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/gal_ex58_parametric_jp.py +71 -0
- pyfemtet/opt/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/gau_ex08_parametric_jp.py +58 -0
- pyfemtet/opt/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/her_ex40_parametric_jp.py +137 -0
- pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_jp.py +59 -0
- pyfemtet/opt/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +60 -0
- pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.femprj +0 -0
- pyfemtet/opt/femprj_sample_jp/wat_ex14_parametric_jp.py +57 -0
- pyfemtet/opt/interface/_femtet.py +6 -2
- pyfemtet/opt/interface/_femtet_with_nx/_interface.py +2 -8
- pyfemtet/opt/interface/_femtet_with_sldworks.py +2 -8
- pyfemtet/opt/opt/_optuna.py +6 -0
- {pyfemtet-0.4.1.dist-info → pyfemtet-0.4.3.dist-info}/METADATA +3 -2
- pyfemtet-0.4.3.dist-info/RECORD +71 -0
- pyfemtet-0.4.1.dist-info/RECORD +0 -38
- {pyfemtet-0.4.1.dist-info → pyfemtet-0.4.3.dist-info}/LICENSE +0 -0
- {pyfemtet-0.4.1.dist-info → pyfemtet-0.4.3.dist-info}/WHEEL +0 -0
- {pyfemtet-0.4.1.dist-info → pyfemtet-0.4.3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Single-objective optimization: bending with consideration for springback.
|
|
2
|
+
|
|
3
|
+
Using Femtet's stress analysis solver, we will determine the bending angle
|
|
4
|
+
to achieve the desired material bend angle with consideration for springback.
|
|
5
|
+
Elasto-plastic analysis is available in an optional package.
|
|
6
|
+
|
|
7
|
+
Corresponding project: gal_ex58_parametric.femprj
|
|
8
|
+
"""
|
|
9
|
+
import numpy as np
|
|
10
|
+
from win32com.client import constants
|
|
11
|
+
from optuna.integration.botorch import BoTorchSampler
|
|
12
|
+
|
|
13
|
+
from pyfemtet.opt import FEMOpt, OptunaOptimizer
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def bending(Femtet):
|
|
17
|
+
"""Get the material bend angle.
|
|
18
|
+
|
|
19
|
+
Note:
|
|
20
|
+
The objective or constraint function should take Femtet
|
|
21
|
+
as its first argument and return a float as the output.
|
|
22
|
+
|
|
23
|
+
Params:
|
|
24
|
+
Femtet: This is an instance for manipulating Femtet with macros. For detailed information, please refer to "Femtet Macro Help".
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
float: material bend angle.
|
|
28
|
+
"""
|
|
29
|
+
Gogh = Femtet.Gogh
|
|
30
|
+
|
|
31
|
+
# Set the mode after unloading.
|
|
32
|
+
Gogh.Galileo.Mode = Gogh.Galileo.nMode - 1
|
|
33
|
+
|
|
34
|
+
# Obtain the displacement of the measurement target point.
|
|
35
|
+
Gogh.Galileo.Vector = constants.GALILEO_DISPLACEMENT_C
|
|
36
|
+
succeed, (x, y, z) = Gogh.Galileo.GetVectorAtPoint_py(200, 0, 0)
|
|
37
|
+
|
|
38
|
+
# Calculate the angle formed by the line segment
|
|
39
|
+
# connecting the bending origin (100, 0) and the
|
|
40
|
+
# deformed point with the X-axis.
|
|
41
|
+
bending_point = np.array((100, 0))
|
|
42
|
+
bended_point = np.array((200 + 1000 * x.Real, 1000 * z.Real))
|
|
43
|
+
dx, dz = bended_point - bending_point
|
|
44
|
+
degree = np.arctan2(-dz, dx)
|
|
45
|
+
|
|
46
|
+
return degree * 360 / (2*np.pi) # unit: degree
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == '__main__':
|
|
50
|
+
|
|
51
|
+
# Initialize the numerical optimization problem.
|
|
52
|
+
# (determine the optimization method)
|
|
53
|
+
opt = OptunaOptimizer(
|
|
54
|
+
sampler_class=BoTorchSampler,
|
|
55
|
+
sampler_kwargs=dict(
|
|
56
|
+
n_startup_trials=3,
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Initialize the FEMOpt object.
|
|
61
|
+
# (establish connection between the optimization problem and Femtet)
|
|
62
|
+
femopt = FEMOpt(opt=opt)
|
|
63
|
+
|
|
64
|
+
# Add design variables to the optimization problem.
|
|
65
|
+
# (Specify the variables registered in the femprj file.)
|
|
66
|
+
femopt.add_parameter("rot", 90, lower_bound=80, upper_bound=100)
|
|
67
|
+
|
|
68
|
+
# Add the objective function to the optimization problem.
|
|
69
|
+
# The target bending angle is 90 degrees.
|
|
70
|
+
femopt.add_objective(bending, name='final angle (degree)', direction=90)
|
|
71
|
+
|
|
72
|
+
# Run optimization.
|
|
73
|
+
femopt.set_random_seed(42)
|
|
74
|
+
femopt.optimize(n_trials=10)
|
|
75
|
+
femopt.terminate_all()
|
|
Binary file
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Single-objective optimization: Self-inductance of a finite-length helical coil.
|
|
2
|
+
|
|
3
|
+
Using Femtet's magnetic field analysis solver, design to achieve
|
|
4
|
+
the target value for the self-inductance of a finite-length helical coil.
|
|
5
|
+
|
|
6
|
+
Corresponding project: gau_ex08_parametric.femprj
|
|
7
|
+
"""
|
|
8
|
+
from optuna.integration.botorch import BoTorchSampler
|
|
9
|
+
from pyfemtet.opt import FEMOpt, OptunaOptimizer
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def inductance(Femtet):
|
|
13
|
+
"""Obtain the self-inductance.
|
|
14
|
+
|
|
15
|
+
Note:
|
|
16
|
+
The objective or constraint function should take Femtet
|
|
17
|
+
as its first argument and return a float as the output.
|
|
18
|
+
|
|
19
|
+
Params:
|
|
20
|
+
Femtet: This is an instance for manipulating Femtet with macros. For detailed information, please refer to "Femtet Macro Help".
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
float: Self-inductance.
|
|
24
|
+
"""
|
|
25
|
+
Gogh = Femtet.Gogh
|
|
26
|
+
|
|
27
|
+
coil_name = Gogh.Gauss.GetCoilList()[0]
|
|
28
|
+
return Gogh.Gauss.GetL(coil_name, coil_name) # unit: F
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == '__main__':
|
|
32
|
+
|
|
33
|
+
# Initialize the numerical optimization problem.
|
|
34
|
+
# (determine the optimization method)
|
|
35
|
+
opt = OptunaOptimizer(
|
|
36
|
+
sampler_class=BoTorchSampler,
|
|
37
|
+
sampler_kwargs=dict(
|
|
38
|
+
n_startup_trials=5,
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Initialize the FEMOpt object.
|
|
43
|
+
# (establish connection between the optimization problem and Femtet)
|
|
44
|
+
femopt = FEMOpt(opt=opt)
|
|
45
|
+
|
|
46
|
+
# Add design variables to the optimization problem.
|
|
47
|
+
# (Specify the variables registered in the femprj file.)
|
|
48
|
+
femopt.add_parameter("helical_pitch", 6, lower_bound=4.2, upper_bound=8)
|
|
49
|
+
femopt.add_parameter("coil_radius", 10, lower_bound=1, upper_bound=10)
|
|
50
|
+
femopt.add_parameter("n_turns", 5, lower_bound=1, upper_bound=5)
|
|
51
|
+
|
|
52
|
+
# Add the objective function to the optimization problem.
|
|
53
|
+
# The target inductance is 0.1 uF.
|
|
54
|
+
femopt.add_objective(inductance, name='self-inductance (F)', direction=1e-7)
|
|
55
|
+
|
|
56
|
+
# Run optimization.
|
|
57
|
+
femopt.set_random_seed(42)
|
|
58
|
+
femopt.optimize(n_trials=20)
|
|
59
|
+
femopt.terminate_all()
|
|
Binary file
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Single-objective optimization: Resonant frequency of a circular patch antenna
|
|
2
|
+
|
|
3
|
+
Using Femtet’s electromagnetic wave analysis solver,
|
|
4
|
+
we explain an example of setting the resonant frequency
|
|
5
|
+
of a circular patch antenna to a specific value.
|
|
6
|
+
|
|
7
|
+
Corresponding project: her_ex40_parametric.femprj
|
|
8
|
+
"""
|
|
9
|
+
from time import sleep
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from scipy.signal import find_peaks
|
|
13
|
+
from tqdm import tqdm
|
|
14
|
+
from optuna.integration.botorch import BoTorchSampler
|
|
15
|
+
|
|
16
|
+
from pyfemtet.core import SolveError
|
|
17
|
+
from pyfemtet.opt import OptunaOptimizer, FEMOpt
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SParameterCalculator:
|
|
21
|
+
"""Calculating S-parameters and resonance frequencies."""
|
|
22
|
+
|
|
23
|
+
def __init__(self):
|
|
24
|
+
self.freq = []
|
|
25
|
+
self.S = []
|
|
26
|
+
self.interpolated_function = None
|
|
27
|
+
self.resonance_frequency = None
|
|
28
|
+
self.minimum_S = None
|
|
29
|
+
|
|
30
|
+
def _get_freq_and_S_parameter(self, Femtet):
|
|
31
|
+
"""Obtain the relationship between frequency and S-parameter"""
|
|
32
|
+
|
|
33
|
+
Gogh = Femtet.Gogh
|
|
34
|
+
|
|
35
|
+
freq_list = []
|
|
36
|
+
dB_S_list = []
|
|
37
|
+
for mode in tqdm(range(Gogh.Hertz.nMode), 'Obtain frequency and S-parameter.'):
|
|
38
|
+
# mode setting
|
|
39
|
+
Gogh.Hertz.Mode = mode
|
|
40
|
+
sleep(0.01)
|
|
41
|
+
|
|
42
|
+
# Obtain frequency
|
|
43
|
+
freq = Gogh.Hertz.GetFreq().Real
|
|
44
|
+
|
|
45
|
+
# Obtain S(1, 1)
|
|
46
|
+
comp_S = Gogh.Hertz.GetSMatrix(0, 0)
|
|
47
|
+
norm = np.linalg.norm((comp_S.Real, comp_S.Imag))
|
|
48
|
+
dB_S = 20 * np.log10(norm)
|
|
49
|
+
|
|
50
|
+
# Save them
|
|
51
|
+
freq_list.append(freq)
|
|
52
|
+
dB_S_list.append(dB_S)
|
|
53
|
+
|
|
54
|
+
self.freq = freq_list
|
|
55
|
+
self.S = dB_S_list
|
|
56
|
+
|
|
57
|
+
def _calc_resonance_frequency(self):
|
|
58
|
+
"""Compute the frequency that gives the first peak for S-parameter."""
|
|
59
|
+
peaks, _ = find_peaks(-np.array(self.S), height=None, threshold=None, distance=None, prominence=0.5, width=None, wlen=None, rel_height=0.5, plateau_size=None)
|
|
60
|
+
if len(peaks) == 0:
|
|
61
|
+
raise SolveError('No S(1,1) peaks detected.')
|
|
62
|
+
self.resonance_frequency = self.freq[peaks[0]]
|
|
63
|
+
self.minimum_S = self.S[peaks[0]]
|
|
64
|
+
|
|
65
|
+
def get_resonance_frequency(self, Femtet):
|
|
66
|
+
"""Calculate the resonant frequency.
|
|
67
|
+
|
|
68
|
+
Note:
|
|
69
|
+
The objective or constraint function should take Femtet
|
|
70
|
+
as its first argument and return a float as the output.
|
|
71
|
+
|
|
72
|
+
Params:
|
|
73
|
+
Femtet: This is an instance for manipulating Femtet with macros. For detailed information, please refer to "Femtet Macro Help".
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
float: A resonance frequency of the antenna.
|
|
77
|
+
"""
|
|
78
|
+
self._get_freq_and_S_parameter(Femtet)
|
|
79
|
+
self._calc_resonance_frequency()
|
|
80
|
+
return self.resonance_frequency # unit: Hz
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def antenna_is_smaller_than_substrate(Femtet):
|
|
84
|
+
"""Calculate the relationship between antenna size and board size.
|
|
85
|
+
|
|
86
|
+
This function is used to constrain the model
|
|
87
|
+
from breaking down while changing parameters.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
float: Difference between the substrate size and antenna size. Must be equal to or grater than 1 mm.
|
|
91
|
+
"""
|
|
92
|
+
r = Femtet.GetVariableValue('antenna_radius')
|
|
93
|
+
w = Femtet.GetVariableValue('substrate_w')
|
|
94
|
+
return w / 2 - r # unit: mm
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def port_is_inside_antenna(Femtet):
|
|
98
|
+
"""Calculate the relationship between the feed port location and antenna size."""
|
|
99
|
+
r = Femtet.GetVariableValue('antenna_radius')
|
|
100
|
+
x = Femtet.GetVariableValue('port_x')
|
|
101
|
+
return r - x # unit: mm. Must be equal to or grater than 1 mm.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == '__main__':
|
|
105
|
+
# Initialize the object for calculating frequency characteristics.
|
|
106
|
+
s = SParameterCalculator()
|
|
107
|
+
|
|
108
|
+
# Initialize the numerical optimization problem.
|
|
109
|
+
# (determine the optimization method)
|
|
110
|
+
opt = OptunaOptimizer(
|
|
111
|
+
sampler_class=BoTorchSampler,
|
|
112
|
+
sampler_kwargs=dict(
|
|
113
|
+
n_startup_trials=10,
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Initialize the FEMOpt object.
|
|
118
|
+
# (establish connection between the optimization problem and Femtet)
|
|
119
|
+
femopt = FEMOpt(opt=opt)
|
|
120
|
+
|
|
121
|
+
# Add design variables to the optimization problem.
|
|
122
|
+
# (Specify the variables registered in the femprj file.)
|
|
123
|
+
femopt.add_parameter('antenna_radius', 10, 5, 20)
|
|
124
|
+
femopt.add_parameter('substrate_w', 50, 40, 60)
|
|
125
|
+
femopt.add_parameter('port_x', 5, 1, 20)
|
|
126
|
+
|
|
127
|
+
# Add the constraint function to the optimization problem.
|
|
128
|
+
femopt.add_constraint(antenna_is_smaller_than_substrate, 'antenna and substrate clearance', lower_bound=1)
|
|
129
|
+
femopt.add_constraint(port_is_inside_antenna, 'antenna and port clearance', lower_bound=1)
|
|
130
|
+
|
|
131
|
+
# Add the objective function to the optimization problem.
|
|
132
|
+
# The target frequency is 3.0 GHz.
|
|
133
|
+
femopt.add_objective(s.get_resonance_frequency, 'first resonant frequency(Hz)', direction=3.0 * 1e9)
|
|
134
|
+
|
|
135
|
+
femopt.set_random_seed(42)
|
|
136
|
+
femopt.optimize(n_trials=15)
|
|
137
|
+
femopt.terminate_all()
|
|
Binary file
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Multi-objective optimization: Air cooling of IC on a printed circuit board (forced convection).
|
|
2
|
+
|
|
3
|
+
Using Femtet's simple fluid-thermal analysis solver,
|
|
4
|
+
design a solution that reduces the chip temperature
|
|
5
|
+
while minimizing the substrate size.
|
|
6
|
+
|
|
7
|
+
Related project: paswat_ex1_parametric.femprj
|
|
8
|
+
"""
|
|
9
|
+
from pyfemtet.opt import FEMOpt
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def chip_temp(Femtet, chip_name):
|
|
13
|
+
"""Obtain the maximum temperature of the chip.
|
|
14
|
+
|
|
15
|
+
Note:
|
|
16
|
+
The objective or constraint function should take Femtet
|
|
17
|
+
as its first argument and return a float as the output.
|
|
18
|
+
|
|
19
|
+
Params:
|
|
20
|
+
Femtet: An instance for manipulating Femtet with macros. For detailed information, please refer to "Femtet Macro Help".
|
|
21
|
+
chip_name (str): The body attribute name defined in femprj. Valid values are 'MAINCHIP' or 'SUBCHIP'.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
float: The maximum temperature of the body with the specified body attribute name.
|
|
25
|
+
"""
|
|
26
|
+
Gogh = Femtet.Gogh
|
|
27
|
+
|
|
28
|
+
max_temperature, min_temperature, mean_temperature = Gogh.Watt.GetTemp(chip_name)
|
|
29
|
+
|
|
30
|
+
return max_temperature # unit: degree
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def substrate_size(Femtet):
|
|
34
|
+
"""Calculate the occupied area on the XY plane of the substrate."""
|
|
35
|
+
substrate_w = Femtet.GetVariableValue('substrate_w')
|
|
36
|
+
substrate_d = Femtet.GetVariableValue('substrate_d')
|
|
37
|
+
return substrate_w * substrate_d # unit: mm2
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == '__main__':
|
|
41
|
+
|
|
42
|
+
# Initialize the FEMOpt object.
|
|
43
|
+
# (establish connection between the optimization problem and Femtet)
|
|
44
|
+
femopt = FEMOpt()
|
|
45
|
+
|
|
46
|
+
# Add design variables to the optimization problem.
|
|
47
|
+
# (Specify the variables registered in the femprj file.)
|
|
48
|
+
femopt.add_parameter("substrate_w", 40, lower_bound=22, upper_bound=60)
|
|
49
|
+
femopt.add_parameter("substrate_d", 60, lower_bound=34, upper_bound=60)
|
|
50
|
+
femopt.add_parameter("rot", 0, lower_bound=0, upper_bound=180)
|
|
51
|
+
|
|
52
|
+
# Add the objective function to the optimization problem.
|
|
53
|
+
# The target bending angle is 90 degrees.
|
|
54
|
+
femopt.add_objective(chip_temp, name='max temp. of<br>MAINCHIP (degree)', direction='minimize', args=('MAINCHIP',))
|
|
55
|
+
femopt.add_objective(chip_temp, name='max temp. of<br>SUBCHIP (degree)', direction='minimize', args=('SUBCHIP',))
|
|
56
|
+
femopt.add_objective(substrate_size, name='substrate size (mm2)', direction='minimize')
|
|
57
|
+
|
|
58
|
+
# Run optimization.
|
|
59
|
+
femopt.set_random_seed(42)
|
|
60
|
+
femopt.optimize(n_trials=15)
|
|
61
|
+
femopt.terminate_all()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Multi-objective optimization: Air cooling of IC on a printed circuit board (forced convection).
|
|
2
|
+
|
|
3
|
+
Using Femtet's simple fluid-thermal analysis solver,
|
|
4
|
+
design a solution that reduces the chip temperature
|
|
5
|
+
while minimizing the substrate size.
|
|
6
|
+
|
|
7
|
+
Related project: paswat_ex1_parametric.femprj
|
|
8
|
+
"""
|
|
9
|
+
from pyfemtet.opt import FEMOpt
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def chip_temp(Femtet, chip_name):
|
|
13
|
+
"""Obtain the maximum temperature of the chip.
|
|
14
|
+
|
|
15
|
+
Note:
|
|
16
|
+
The objective or constraint function should take Femtet
|
|
17
|
+
as its first argument and return a float as the output.
|
|
18
|
+
|
|
19
|
+
Params:
|
|
20
|
+
Femtet: An instance for manipulating Femtet with macros. For detailed information, please refer to "Femtet Macro Help".
|
|
21
|
+
chip_name (str): The body attribute name defined in femprj. Valid values are 'MAINCHIP' or 'SUBCHIP'.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
float: The maximum temperature of the body with the specified body attribute name.
|
|
25
|
+
"""
|
|
26
|
+
Gogh = Femtet.Gogh
|
|
27
|
+
|
|
28
|
+
max_temperature, min_temperature, mean_temperature = Gogh.Watt.GetTemp(chip_name)
|
|
29
|
+
|
|
30
|
+
return max_temperature # unit: degree
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def substrate_size(Femtet):
|
|
34
|
+
"""Calculate the occupied area on the XY plane of the substrate."""
|
|
35
|
+
substrate_w = Femtet.GetVariableValue('substrate_w')
|
|
36
|
+
substrate_d = Femtet.GetVariableValue('substrate_d')
|
|
37
|
+
return substrate_w * substrate_d # unit: mm2
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == '__main__':
|
|
41
|
+
|
|
42
|
+
# Initialize the FEMOpt object.
|
|
43
|
+
# (establish connection between the optimization problem and Femtet)
|
|
44
|
+
femopt = FEMOpt()
|
|
45
|
+
|
|
46
|
+
# Add design variables to the optimization problem.
|
|
47
|
+
# (Specify the variables registered in the femprj file.)
|
|
48
|
+
femopt.add_parameter("substrate_w", 40, lower_bound=22, upper_bound=60)
|
|
49
|
+
femopt.add_parameter("substrate_d", 60, lower_bound=34, upper_bound=60)
|
|
50
|
+
femopt.add_parameter("rot", 0, lower_bound=0, upper_bound=180)
|
|
51
|
+
|
|
52
|
+
# Add the objective function to the optimization problem.
|
|
53
|
+
# The target bending angle is 90 degrees.
|
|
54
|
+
femopt.add_objective(chip_temp, name='max temp. of<br>MAINCHIP (degree)', direction='minimize', args=('MAINCHIP',))
|
|
55
|
+
femopt.add_objective(chip_temp, name='max temp. of<br>SUBCHIP (degree)', direction='minimize', args=('SUBCHIP',))
|
|
56
|
+
femopt.add_objective(substrate_size, name='substrate size (mm2)', direction='minimize')
|
|
57
|
+
|
|
58
|
+
# Run optimization.
|
|
59
|
+
femopt.set_random_seed(42)
|
|
60
|
+
# femopt.optimize(n_trials=15)
|
|
61
|
+
femopt.optimize(n_trials=30, n_parallel=3) # This line is the only difference with no parallel pattern.
|
|
62
|
+
femopt.terminate_all()
|
|
Binary file
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Multi-objective optimization: heating element on substrate.
|
|
2
|
+
|
|
3
|
+
Using Femtet's heat conduction analysis solver, we will design
|
|
4
|
+
to reduce the chip temperature and shrink the board size.
|
|
5
|
+
|
|
6
|
+
Corresponding project: wat_ex14_parametric.femprj
|
|
7
|
+
"""
|
|
8
|
+
from pyfemtet.opt import FEMOpt
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def chip_temp(Femtet, chip_name):
|
|
12
|
+
"""Obtain the maximum temperature of the chip.
|
|
13
|
+
|
|
14
|
+
Note:
|
|
15
|
+
The objective or constraint function should take Femtet
|
|
16
|
+
as its first argument and return a float as the output.
|
|
17
|
+
|
|
18
|
+
Params:
|
|
19
|
+
Femtet: An instance for manipulating Femtet with macros. For detailed information, please refer to "Femtet Macro Help".
|
|
20
|
+
chip_name (str): The body attribute name defined in femprj. Valid values are 'MAINCHIP' or 'SUBCHIP'.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
float: The maximum temperature of the body with the specified body attribute name.
|
|
24
|
+
"""
|
|
25
|
+
Gogh = Femtet.Gogh
|
|
26
|
+
|
|
27
|
+
max_temperature, min_temperature, mean_temperature = Gogh.Watt.GetTemp(chip_name)
|
|
28
|
+
|
|
29
|
+
return max_temperature # unit: degree
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def substrate_size(Femtet):
|
|
33
|
+
"""Calculate the occupied area on the XY plane of the substrate."""
|
|
34
|
+
substrate_w = Femtet.GetVariableValue('substrate_w')
|
|
35
|
+
substrate_d = Femtet.GetVariableValue('substrate_d')
|
|
36
|
+
return substrate_w * substrate_d # unit: mm2
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == '__main__':
|
|
40
|
+
|
|
41
|
+
# Initialize the FEMOpt object.
|
|
42
|
+
# (establish connection between the optimization problem and Femtet)
|
|
43
|
+
femopt = FEMOpt()
|
|
44
|
+
|
|
45
|
+
# Add design variables to the optimization problem.
|
|
46
|
+
# (Specify the variables registered in the femprj file.)
|
|
47
|
+
femopt.add_parameter("substrate_w", 40, lower_bound=22, upper_bound=40)
|
|
48
|
+
femopt.add_parameter("substrate_d", 60, lower_bound=33, upper_bound=60)
|
|
49
|
+
|
|
50
|
+
# Add the objective function to the optimization problem.
|
|
51
|
+
# The target bending angle is 90 degrees.
|
|
52
|
+
femopt.add_objective(chip_temp, name='max temp. of<br>MAINCHIP (degree)', direction='minimize', args=('MAINCHIP',))
|
|
53
|
+
femopt.add_objective(chip_temp, name='max temp. of<br>SUBCHIP (degree)', direction='minimize', args=('SUBCHIP',))
|
|
54
|
+
femopt.add_objective(substrate_size, name='substrate size')
|
|
55
|
+
|
|
56
|
+
# Run optimization.
|
|
57
|
+
femopt.set_random_seed(42)
|
|
58
|
+
femopt.optimize(n_trials=15)
|
|
59
|
+
femopt.terminate_all()
|
|
Binary file
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""外部 CAD (NX) 連携
|
|
2
|
+
|
|
3
|
+
Femtet の応力解析ソルバ、および
|
|
4
|
+
Siemens 社製 CAD ソフト NX を用いて
|
|
5
|
+
軽量かつ高剛性な H 型鋼の設計を行います。
|
|
6
|
+
|
|
7
|
+
事前準備として、下記の手順を実行してください。
|
|
8
|
+
- NX のインストール
|
|
9
|
+
- C:\temp フォルダを作成する
|
|
10
|
+
- Note: NX が .x_t ファイルをこのフォルダに保存します。
|
|
11
|
+
- 以下のファイルを同じフォルダに配置
|
|
12
|
+
- cad_ex01_NX_jp.py (このファイル)
|
|
13
|
+
- cad_ex01_NX.prt
|
|
14
|
+
- cad_ex01_NX_jp.femprj
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
from win32com.client import constants
|
|
20
|
+
|
|
21
|
+
from pyfemtet.opt import FEMOpt
|
|
22
|
+
from pyfemtet.opt.interface import FemtetWithNXInterface
|
|
23
|
+
from pyfemtet.core import ModelError
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
here, me = os.path.split(__file__)
|
|
27
|
+
os.chdir(here)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def von_mises(Femtet):
|
|
31
|
+
"""モデルの最大フォン・ミーゼス応力を取得します。
|
|
32
|
+
|
|
33
|
+
Note:
|
|
34
|
+
目的関数または制約関数は、
|
|
35
|
+
第一引数としてFemtetを受け取り、
|
|
36
|
+
戻り値としてfloat型を返す必要があります。
|
|
37
|
+
|
|
38
|
+
Warning:
|
|
39
|
+
CAD 連携機能では、意図しない位置に境界条件が設定される可能性があります。
|
|
40
|
+
|
|
41
|
+
この例では、境界条件が意図したとおりに割り当てられている場合、
|
|
42
|
+
最大変位は常に負になります。最大変位が正の場合、境界条件の割り当てが
|
|
43
|
+
失敗したとみなし、ModelError を送出します。
|
|
44
|
+
|
|
45
|
+
最適化中に ModelError、MeshError、または SolveError が発生した場合、
|
|
46
|
+
最適化プロセスは試行を失敗とみなし、次のトライアルにスキップします。
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# 簡易的な境界条件の正しさチェック
|
|
50
|
+
dx, dy, dz = Femtet.Gogh.Galileo.GetMaxDisplacement_py()
|
|
51
|
+
if dz >= 0:
|
|
52
|
+
raise ModelError('境界条件の設定が間違っています。')
|
|
53
|
+
|
|
54
|
+
# ミーゼス応力計算
|
|
55
|
+
Gogh = Femtet.Gogh
|
|
56
|
+
Gogh.Galileo.Potential = constants.GALILEO_VON_MISES_C
|
|
57
|
+
succeed, (x, y, z), mises = Gogh.Galileo.GetMAXPotentialPoint_py(constants.CMPX_REAL_C)
|
|
58
|
+
|
|
59
|
+
return mises
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def mass(Femtet):
|
|
63
|
+
"""モデルの質量を取得します。"""
|
|
64
|
+
return Femtet.Gogh.Galileo.GetMass('H_beam')
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def C_minus_B(Femtet, opt):
|
|
68
|
+
"""C 寸法と B 寸法の差を計算します。
|
|
69
|
+
|
|
70
|
+
別の例では、次のスニペットを使用して設計変数にアクセスします。
|
|
71
|
+
|
|
72
|
+
A = Femtet.GetVariableValue('A')
|
|
73
|
+
|
|
74
|
+
ただし、CAD 連携機能を使用する場合、設計変数が .femprj ファイルに
|
|
75
|
+
設定されていないため、この方法は機能しません。
|
|
76
|
+
|
|
77
|
+
CAD 連携機能を使用する場合、以下の方法で設計変数にアクセスすることができます。
|
|
78
|
+
|
|
79
|
+
# add_parameter() で追加したパラメータの変数名をキーとする辞書を得る方法
|
|
80
|
+
params: dict = opt.get_parameter()
|
|
81
|
+
A = params['A']
|
|
82
|
+
|
|
83
|
+
又は
|
|
84
|
+
|
|
85
|
+
# add_parameter() で追加した順のパラメータの値の配列を得る方法
|
|
86
|
+
values: np.ndarray = opt.get_parameter('values')
|
|
87
|
+
A, B, C = values
|
|
88
|
+
|
|
89
|
+
目的関数と拘束関数は、最初の引数の後に任意の変数を取ることができます。
|
|
90
|
+
FEMOpt のメンバ変数 opt には get_parameter() というメソッドがあります。
|
|
91
|
+
このメソッドによって add_parameter() で追加された設計変数を取得できます。
|
|
92
|
+
opt を第 2 引数として取ることにより、目的関数または拘束関数内で
|
|
93
|
+
get_parameter() を実行して設計変数を取得できます。
|
|
94
|
+
"""
|
|
95
|
+
A, B, C = opt.get_parameter('values')
|
|
96
|
+
return C - B
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
if __name__ == '__main__':
|
|
100
|
+
|
|
101
|
+
# NX-Femtet 連携オブジェクトの初期化
|
|
102
|
+
# この処理により、Python プロセスは Femtet に接続を試みます。
|
|
103
|
+
fem = FemtetWithNXInterface(
|
|
104
|
+
prt_path='cad_ex01_NX.prt',
|
|
105
|
+
open_result_with_gui=False,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# FEMOpt オブジェクトの初期化 (最適化問題とFemtetとの接続を行います)
|
|
109
|
+
femopt = FEMOpt(fem=fem)
|
|
110
|
+
|
|
111
|
+
# 設計変数を最適化問題に追加 (femprj ファイルに登録されている変数を指定してください)
|
|
112
|
+
femopt.add_parameter('A', 10, lower_bound=1, upper_bound=59)
|
|
113
|
+
femopt.add_parameter('B', 10, lower_bound=1, upper_bound=40)
|
|
114
|
+
femopt.add_parameter('C', 20, lower_bound=5, upper_bound=59)
|
|
115
|
+
|
|
116
|
+
# 拘束関数を最適化問題に追加
|
|
117
|
+
femopt.add_constraint(C_minus_B, 'C>B', lower_bound=1, args=femopt.opt)
|
|
118
|
+
|
|
119
|
+
# 目的関数を最適化問題に追加
|
|
120
|
+
femopt.add_objective(von_mises, name='von Mises (Pa)')
|
|
121
|
+
femopt.add_objective(mass, name='mass (kg)')
|
|
122
|
+
|
|
123
|
+
# 最適化を実行
|
|
124
|
+
femopt.set_random_seed(42)
|
|
125
|
+
femopt.optimize(n_trials=20)
|
|
126
|
+
femopt.terminate_all()
|
|
Binary file
|