円形パッチアンテナの共振周波数
Femtet の電磁波解析ソルバーを用い、 円形パッチアンテナの共振周波数を 特定の値にする例題を解説します。
サンプルファイル
注釈
サンプルプロジェクト を Femtet で開いたまま、 サンプルコード をダブルクリックして実行してください。
注釈
FEM 問題としての詳細については、FemtetHelp / 例題集 / 電磁波解析 / 例題40 を参照してください。
設計変数
モデルの外観
変数名 |
説明 |
|---|---|
ant_r |
円形アンテナの半径 |
sx |
基板のサイズ |
xf |
給電ポートの位置 |
目的関数
S(1,1) の第一ピークを与える共振周波数
サンプルコード
her_ex40_parametric.py
1"""単目的最適化: 円形パッチアンテナの共振周波数
2
3Femtet の電磁波解析ソルバを利用して、円形パッチアンテナの
4電磁波調和解析を行い、共振特性を目標の値にする設計を行います。
5
6対応プロジェクト: her_ex40_parametric_jp.femprj
7"""
8from time import sleep
9
10import numpy as np
11from scipy.signal import find_peaks
12from tqdm import tqdm
13
14from pyfemtet.opt.exceptions import SolveError
15from pyfemtet.opt import FemtetInterface, OptunaOptimizer, FEMOpt
16from pyfemtet.opt.optimizer import PoFBoTorchSampler, PartialOptimizeACQFConfig
17
18
19class SParameterCalculator:
20 """Sパラメータ計算用クラス"""
21
22 def __init__(self):
23 self.freq = []
24 self.S = []
25 self.interpolated_function = None
26 self.resonance_frequency = None
27 self.minimum_S = None
28
29 def _get_freq_and_S_parameter(self, Femtet):
30 """周波数とSパラメータの関係を取得します。"""
31
32 Gogh = Femtet.Gogh
33
34 freq_list = []
35 dB_S_list = []
36 for mode in tqdm(range(Gogh.Hertz.nMode), '周波数と S(1, 1) の関係を取得'):
37 # 周波数モード設定
38 Gogh.Hertz.Mode = mode
39 sleep(0.1)
40
41 # 周波数を取得
42 freq = Gogh.Hertz.GetFreq().Real
43
44 # S(1, 1) を取得
45 comp_S = Gogh.Hertz.GetSMatrix(0, 0)
46 norm = np.linalg.norm((comp_S.Real, comp_S.Imag))
47 dB_S = 20 * np.log10(norm)
48
49 # 結果を保存
50 freq_list.append(freq)
51 dB_S_list.append(dB_S)
52
53 self.freq = freq_list
54 self.S = dB_S_list
55
56 def _calc_resonance_frequency(self):
57 """Sパラメータの第一ピークを与える周波数を取得します。"""
58 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)
59 if len(peaks) == 0:
60 raise SolveError('S(1,1) のピークを取得できませんでした。')
61 self.resonance_frequency = self.freq[peaks[0]]
62 self.minimum_S = self.S[peaks[0]]
63
64 def get_resonance_frequency(self, Femtet):
65 """パッチアンテナの共振周波数を計算します。
66
67 Note:
68 目的関数または制約関数は、
69 第一引数としてFemtetを受け取り、
70 戻り値としてfloat型を返す必要があります。
71
72 Params:
73 Femtet: Femtet をマクロで操作するためのインスタンスです。詳細な情報については、「Femtet マクロヘルプ」をご覧ください。
74
75 Returns:
76 float: パッチアンテナの共振周波数。
77 """
78 self._get_freq_and_S_parameter(Femtet)
79 self._calc_resonance_frequency()
80 return self.resonance_frequency # 単位: Hz
81
82
83def antenna_is_smaller_than_substrate(Femtet, opt):
84 """アンテナの大きさと基板の大きさの関係を計算します。
85
86 この関数は、変数の更新によってモデル形状が破綻しないように
87 変数の組み合わせを拘束するために使われます。
88
89 Params:
90 Femtet: Femtet をマクロで操作するためのインスタンスです。詳細な情報については、「Femtet マクロヘルプ」をご覧ください。
91
92 Returns:
93 float: 基板エッジとアンテナエッジの間隙。1 mm 以上が必要です。
94 """
95 params = opt.get_parameter()
96 r = params['antenna_radius']
97 w = params['substrate_w']
98 return w / 2 - r # 単位: mm
99
100
101def port_is_inside_antenna(Femtet, opt):
102 """給電ポートの位置とアンテナの大きさの関係を計算します。"""
103 params = opt.get_parameter()
104 r = params['antenna_radius']
105 x = params['port_x']
106 return r - x # 単位: mm。1 mm 以上が必要です。
107
108
109if __name__ == '__main__':
110 # 周波数特性を計算するためのオブジェクトを初期化
111 s = SParameterCalculator()
112
113 # 数値最適化問題の初期化 (最適化手法を決定します)
114 opt = OptunaOptimizer(
115 sampler_class=PoFBoTorchSampler,
116 sampler_kwargs=dict(
117 n_startup_trials=4,
118 partial_optimize_acqf_kwargs=PartialOptimizeACQFConfig(
119 timeout_sec=30.,
120 ),
121 )
122 )
123
124 # Femtet との接続 (モード切替の描画負荷を軽減するため GUI 設定を OFF にする)
125 fem = FemtetInterface(
126 open_result_with_gui=False
127 )
128
129 # FEMOpt オブジェクトの初期化 (最適化問題とFemtetとの接続を行います)
130 femopt = FEMOpt(fem=fem, opt=opt)
131
132 # 設計変数を最適化問題に追加 (femprj ファイルに登録されている変数を指定してください)
133 femopt.add_parameter('antenna_radius', 10, 5, 20)
134 femopt.add_parameter('substrate_w', 50, 40, 60)
135 femopt.add_parameter('port_x', 5, 1, 20)
136
137 # 拘束関数を最適化問題に追加
138 femopt.add_constraint(fun=antenna_is_smaller_than_substrate, name='アンテナと基板エッジの間隙', lower_bound=1, args=(opt,))
139 femopt.add_constraint(fun=port_is_inside_antenna, name='アンテナエッジと給電ポートの間隙', lower_bound=1, args=(opt,))
140
141 # 目的関数を最適化問題に追加
142 # 共振周波数の目標は 3.0 GHz です。
143 femopt.add_objective(fun=s.get_resonance_frequency, name='第一共振周波数(Hz)', direction=3.3 * 1e9)
144
145 femopt.set_random_seed(42)
146 femopt.optimize(n_trials=10)
サンプルコードの実行結果
her_ex40_parametric.py の実行結果。 横軸が試行回数、 縦軸が共振周波数です。
10 回の反復計算の結果、 最良の共振周波数は 3.29 GHz となります。
注釈
Femtet, PyFemtet および依存する最適化エンジンのバージョンにより、結果は多少異なる場合があります。