円形パッチアンテナの共振周波数

Femtet の電磁波解析ソルバーを用い、 円形パッチアンテナの共振周波数を 特定の値にする例題を解説します。

サンプルファイル

注釈

サンプルプロジェクト を Femtet で開いたまま、 サンプルコード をダブルクリックして実行してください。

注釈

FEM 問題としての詳細については、FemtetHelp / 例題集 / 電磁波解析 / 例題40 を参照してください。

設計変数

../../_images/her_ex40_model.png

モデルの外観

変数名

説明

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)

サンプルコードの実行結果

../../_images/her_ex40_result.png

her_ex40_parametric.py の実行結果。 横軸が試行回数、 縦軸が共振周波数です。

10 回の反復計算の結果、 最良の共振周波数は 3.29 GHz となります。

注釈

Femtet, PyFemtet および依存する最適化エンジンのバージョンにより、結果は多少異なる場合があります。