定数を、ちょこちょこ変えながら確認するのって大変です、、、1ポートだとあっち回してこっち回してが通用しますが、2ポートだとあっちをこっちに回すとこっちはあっちに動いて、、、ってなってもう無理ーってなります。いや実物で測定しながらやるのよりは全然いいですけど。まぁ最後は実物でちょこちょこやらんといかんのですが。
ここによると、scipyの最適化ライブラリで値を出すことが示されています。が、うちではexampleの通りでは動かなかったので、同じくscipyの最適化ライブラリの別のアルゴリズムだと動いたのでその記録、、、ていうかいつも通り結論だけ。
引数が(値を最適化したい)変数だけで、最適化状態と計算結果との差異を出す関数(ゴールに近いほど値が小さくなり、遠いほど値が大きくなるような関数)を定義します。うちではget_err(x)です。このget_errを最小化するような変数xを探索してくれます。
import numpy as np import skrf as rf import matplotlib.pyplot as plt import scipy def Calc_Network(FIL1,C1,C2,L1,L2,gnd,port1,port2): cnx = [ [(port1, 0), (C1, 0)], [(C1, 1), (L1, 0), (FIL1, 0)], [(FIL1, 1), (L2, 0), (C2, 0)], [(port2, 0), (C2, 1)], [(gnd, 0), (L1, 1), (L2, 1)] ] cir = rf.Circuit(cnx) ntw = cir.network return ntw FIL1 = rf.Network('out.s2p') FIL1.name='FIL1' freq=FIL1.frequency tl_media = rf.DefinedGammaZ0(freq, z0=50) gnd = rf.Circuit.Ground(freq, name='gnd') port1 = rf.Circuit.Port(freq, name='port1', z0=50) port2 = rf.Circuit.Port(freq, name='port2', z0=50) C1_def=100e-12 C2_def=100e-12 L1_def=100e-9 L2_def=100e-9 #C1_def=9e-12 #C2_def=9e-12 #L1_def=25e-9 #L2_def=25e-9 x0=(C1_def,C2_def,L1_def,L2_def) f_range_lower=314.8e6 f_range_upper=315.2e6 vswr_max=1.5 def matching_network(C1_val,C2_val,L1_val,L2_val): C1 = tl_media.capacitor(C1_val, name='C1') C2 = tl_media.capacitor(C2_val, name='C2') L1 = tl_media.inductor(L1_val, name='L1') L2 = tl_media.inductor(L2_val, name='L2') ntw=Calc_Network(FIL1,C1,C2,L1,L2,gnd,port1,port2) return ntw def get_err(x): ntw=matching_network(*x) irange=np.where((ntw.f>=f_range_lower)&(ntw.f<=f_range_upper)) vswr1=ntw.s_vswr[irange,0,0] vswr2=ntw.s_vswr[irange,1,1] tgt=np.ones_like(vswr1)*vswr_max eval1=vswr1-tgt eval2=vswr2-tgt err1=np.where(eval1<0,0,eval1) err2=np.where(eval2<0,0,eval2) return (np.sum(err1)+np.sum(err2)) res=scipy.optimize.fmin(get_err,x0) print(res) res=scipy.optimize.fmin(get_err,res) print(res) ntw=matching_network(*res) fig=plt.figure() ax1=fig.add_subplot(2,2,1) ntw.plot_s_smith(ax=ax1,m=0, n=0, lw=2) ax2_1=fig.add_subplot(2,2,2) ax2_2=ax2_1.twinx() ntw.plot_s_db(ax=ax2_1,m=1, n=0, lw=2, show_legend=False) ntw.plot_s_vswr(ax=ax2_2,m=0, n=0, lw=2, show_legend=False, color='orangered') ax2_2.set_ylim(1,6) handler1, label1 = ax2_1.get_legend_handles_labels() handler2, label2 = ax2_2.get_legend_handles_labels() ax2_1.legend(handler1 + handler2, label1 + label2, loc=2, borderaxespad=0.) ax3=fig.add_subplot(2,2,3) ntw.plot_s_db(ax=ax3,m=0, n=1, lw=2) ax4=fig.add_subplot(2,2,4) ntw.plot_s_smith(ax=ax4,m=1, n=1, lw=2) fig.tight_layout() plt.show()
ちょっと雑然としていてかつ長いですが、たったこれだけで、最適化してくれるんだからいいですよね、、、
今回、ちょっと帯域幅に欲を出しています。ちょっとくらいミスマッチが出てもちょっと帯域を広げたいときってありますよね。
なんとなく1回では収束しなかったので、2回最適化しています。この辺の設定も決められるんだろうけど、後で調べるかもしれない。
出力はこんなのが出ます。
Optimization terminated successfully.
Current function value: 244.303714
Iterations: 210
Function evaluations: 355
[2.62032969e-10 8.35302699e-12 5.23056775e-08 2.62671216e-08]
Optimization terminated successfully.
Current function value: 70.789551
Iterations: 341
Function evaluations: 580
[1.09647196e-11 1.09630758e-11 2.69960441e-08 2.69959050e-08]
波形はいい感じです。まぁ、最適化しても実際の部品でその値そのものは実現できないし、実測するとちょっと違ったりするので、参考ですよね。
これだけのことをたったの89行でできるってのが、人類の進歩(大げさ)を感じるとともに、プログラミングが専門家のものではなくなった感じがする。ソフトとしての体裁なんか不要で、ひとりひとりが思いついたことをちょちょっと調べてすぐ実現できるのが今の時代にマッチしているんだろうなー。
コメントをお書きください