以前ギブアップしていたopenEMSにもう一度チャレンジする。
実は前回のやつはAddLumpedElementってやつでキャパシタを入れていたので、キャパシタがない状態でシミュレーションしてみて、後からSパラに対してキャパシタを追加した場合と比較してみたい。
しばらく無言で絵を貼り続ける
で、Octaveのコードが、こう。
- % tutorial for hyp2mat - capacitor in a microstrip.
- %
- % run from openems matlab command prompt
- % See hyp2mat(1) - convert hyperlynx files to matlab scripts.
- % (C) 2011,2012 Thorsten Liebig <thorsten.liebig@gmx.de>
- % Copyright 2012 Koen De Vleeschauwer.
- %
- % This file is part of hyp2mat.
- %
- % This program is free software: you can redistribute it and/or modify
- % it under the terms of the GNU General Public License as published by
- % the Free Software Foundation, either version 3 of the License, or
- % (at your option) any later version.
- %
- % This program is distributed in the hope that it will be useful,
- % but WITHOUT ANY WARRANTY; without even the implied warranty of
- % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- % GNU General Public License for more details.
- %
- % You should have received a copy of the GNU General Public License
- % along with this program. If not, see <http://www.gnu.org/licenses/>.
- close all
- clear
- clc
- function port_return=Execute_main(Sim_Path,f_max,show_structure,port_active)
- % initialize
- physical_constants;
- %f_max = 1e9;
- % Importing printed circuit board
- CSX = InitCSX();
- CSX = ImportHyperLynx(CSX, 'small_loop_antenna2.hyp');
- % Adding a component
- ## [pad1_material, pad1_start, pad1_stop] = GetHyperLynxPort(CSX, 'C1.1');
- ## [pad2_material, pad2_start, pad2_stop] = GetHyperLynxPort(CSX, 'C1.2');
- ##
- ## c1_height = pad1_stop - pad1_start;
- ## c1_start = [(pad1_start(1)+pad1_stop(1))/2, pad1_start(2), pad1_start(3)];
- ## c1_stop = [(pad2_start(1)+pad2_stop(1))/2, pad2_stop(2), pad2_stop(3)+c1_height];
- ##
- ## CSX = AddLumpedElement( CSX, 'Capacitor', 0, 'Caps', 1, 'C', 1e-12);
- ## CSX = AddBox( CSX, 'Capacitor', 0, c1_start, c1_stop );
- % Adding excitation and load
- [port1_material, port1_start, port1_stop] = GetHyperLynxPort(CSX, 'TP1.1');
- [gnd1_material, gnd1_start, gnd1_stop] = GetHyperLynxPort(CSX, 'TP3.1');
- [port2_material, port2_start, port2_stop] = GetHyperLynxPort(CSX, 'TP2.1');
- [gnd2_material, gnd2_start, gnd2_stop] = GetHyperLynxPort(CSX, 'TP4.1');
- if(port_active==1)
- [CSX, port{1}] = AddLumpedPort( CSX, 999, 1, 50, gnd1_start, port1_stop, [0 0 -1], true);
- [CSX, port{2}] = AddLumpedPort( CSX, 999, 2, 50, gnd2_start, port2_stop, [0 0 -1]);
- else
- [CSX, port{1}] = AddLumpedPort( CSX, 999, 1, 50, gnd1_start, port1_stop, [0 0 -1]);
- [CSX, port{2}] = AddLumpedPort( CSX, 999, 2, 50, gnd2_start, port2_stop, [0 0 -1], true);
- endif
- % Setting up a mesh
- unit = GetUnits(CSX);
- substrate_epr = GetEpsilon(CSX);
- resolution = c0 / f_max / sqrt(substrate_epr) / unit / 25;
- AirBox = c0 / f_max / unit / 25;
- z_top = port1_start(3);
- z_bottom = gnd1_start(3);
- z_middle = (z_top+z_bottom)/2;
- mesh.x = [];
- mesh.y = [];
- mesh.z = [ z_middle ];
- mesh = DetectEdges(CSX, mesh);
- mesh.x = [min(mesh.x)-AirBox max(mesh.x)+AirBox mesh.x];
- mesh.y = [min(mesh.y)-AirBox max(mesh.y)+AirBox mesh.y];
- mesh.z = [min(mesh.z)-AirBox max(mesh.z)+2*AirBox mesh.z];
- %mesh = SmoothMesh(mesh, resolution);
- mesh = SmoothMesh(mesh, resolution, 'algorithm', [ 1 ]);
- % Setting boundary conditions
- FDTD = InitFDTD();
- FDTD = SetGaussExcite(FDTD, f_max/2, f_max/2);
- BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'};
- FDTD = SetBoundaryCond(FDTD, BC );
- mesh = AddPML(mesh, 8);
- CSX = DefineRectGrid(CSX, unit, mesh);
- % Simulation
- %Sim_Path = 'tmp';
- Sim_CSX = 'msl.xml';
- disp([ 'Estimated simulation runtime: 6500 timesteps' ]); % inform user this may take a while...
- WriteOpenEMS([Sim_Path '/' Sim_CSX], FDTD, CSX);
- if(show_structure>0)
- CSXGeomPlot([Sim_Path '/' Sim_CSX]);
- endif
- RunOpenEMS(Sim_Path, Sim_CSX);
- port_return=port;
- endfunction
- f_max = 1e9;
- Sim_Path1='tmp1'
- [status, message, messageid] = rmdir(Sim_Path1, 's'); % clear previous directory
- [status, message, messageid] = mkdir(Sim_Path1 ); % create empty simulation folder
- Sim_Path2='tmp2'
- [status, message, messageid] = rmdir(Sim_Path2, 's'); % clear previous directory
- [status, message, messageid] = mkdir(Sim_Path2 ); % create empty simulation folder
- port=Execute_main(Sim_Path1,f_max,1,1)
- % Calculating the s-parameters
- f = linspace( 100e6, f_max, 1601 );
- port = calcPort( port, Sim_Path1, f, 'RefImpedance', 50);
- s11 = port{1}.uf.ref./ port{1}.uf.inc;
- s21 = port{2}.uf.ref./ port{1}.uf.inc;
- port=Execute_main(Sim_Path2,f_max,0,2)
- % Calculating the s-parameters
- port = calcPort( port, Sim_Path2, f, 'RefImpedance', 50);
- s12 = port{1}.uf.ref./ port{2}.uf.inc;
- s22 = port{2}.uf.ref./ port{2}.uf.inc;
- s_param=[];
- s_param(1,1,:) = s11;
- s_param(1,2,:) = s12;
- s_param(2,1,:) = s21;
- s_param(2,2,:) = s22;
- write_touchstone('s',f,s_param,'out.s2p');
- close all
- semilogx(f/1e6,20*log10(abs(s11)),'k-','LineWidth',2);
- hold on;
- grid on;
- semilogx(f/1e6,20*log10(abs(s21)),'r--','LineWidth',2);
- legend('S_{11}','S_{21}');
- ylabel('S-Parameter (dB)','FontSize',12);
- xlabel('frequency (GHz) \rightarrow','FontSize',12);
- ylim([-80 10]);
- print('sparam.png', '-dpng');
- % not truncated
- {VERSION=2.14}
- {UNITS=ENGLISH LENGTH}
- {BOARD "small_loop_antenna2.kicad_pcb"
- (PERIMETER_SEGMENT X1=6.100000000 Y1=4.050000000 X2=4.900000000 Y2=4.050000000)
- (PERIMETER_SEGMENT X1=4.900000000 Y1=4.050000000 X2=4.900000000 Y2=2.850000000)
- (PERIMETER_SEGMENT X1=4.900000000 Y1=2.850000000 X2=6.100000000 Y2=2.850000000)
- (PERIMETER_SEGMENT X1=6.100000000 Y1=2.850000000 X2=6.100000000 Y2=4.050000000)
- }
- {STACKUP
- (SIGNAL T=0.00137795 P=0 C=1.724e-08 L="F.Cu" M=COPPER)
- (DIELECTRIC T=0.03937 C=4.4 L="DE_F.Cu" M="FR4")
- (SIGNAL T=0.00137795 P=0 C=1.724e-08 L="B.Cu" M=COPPER)
- }
- {DEVICES
- (? REF="TP1" L="F.Cu")
- (? REF="TP2" L="F.Cu")
- (? REF="TP4" L="B.Cu")
- (? REF="TP3" L="B.Cu")
- }
- {PADSTACK=0, 0.000000000
- ("F.Cu", 1, 0.039370079, 0.039370079, 180.0, M)
- }
- {PADSTACK=1, 0.000000000
- ("B.Cu", 1, 0.039370079, 0.039370079, 0.0, M)
- }
- {NET="GND"
- (PIN X=5.4500000000 Y=4.0000000000 R="TP4.1" P=1)
- (PIN X=5.5500000000 Y=4.0000000000 R="TP3.1" P=1)
- (SEG X1=5.4500000000 Y1=4.0000000000 X2=5.5500000000 Y2=4.0000000000 W=0.0393700787 L="B.Cu")
- }
- {NET="Net-(TP1-Pad1)"
- (PIN X=5.5500000000 Y=4.0000000000 R="TP1.1" P=0)
- (PIN X=5.4500000000 Y=4.0000000000 R="TP2.1" P=0)
- (SEG X1=5.4500000000 Y1=3.9000000000 X2=5.4000000000 Y2=3.8500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.4500000000 Y1=4.0000000000 X2=5.4500000000 Y2=3.9000000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.1000000000 Y1=3.0000000000 X2=5.0000000000 Y2=3.1000000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.9000000000 Y1=3.0000000000 X2=5.1000000000 Y2=3.0000000000 W=0.0393700787 L="F.Cu")
- (SEG X1=6.0000000000 Y1=3.1000000000 X2=5.9000000000 Y2=3.0000000000 W=0.0393700787 L="F.Cu")
- (SEG X1=6.0000000000 Y1=3.1000000000 X2=6.0000000000 Y2=3.6500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.4000000000 Y1=3.8000000000 X2=5.4000000000 Y2=3.8500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.6000000000 Y1=3.7500000000 X2=5.5500000000 Y2=3.8000000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.0000000000 Y1=3.1000000000 X2=5.0000000000 Y2=3.6500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.0000000000 Y1=3.6500000000 X2=5.1000000000 Y2=3.7500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.9000000000 Y1=3.7500000000 X2=5.6000000000 Y2=3.7500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.3500000000 Y1=3.7500000000 X2=5.4000000000 Y2=3.8000000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.1000000000 Y1=3.7500000000 X2=5.3500000000 Y2=3.7500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=6.0000000000 Y1=3.6500000000 X2=5.9000000000 Y2=3.7500000000 W=0.0393700787 L="F.Cu")
- (SEG X1=5.5500000000 Y1=3.8000000000 X2=5.5500000000 Y2=4.0000000000 W=0.0393700787 L="F.Cu")
- }
こんなパタンとして読み込まれている。
そしてしばらく待つ、、、意外と早かった、、、6+6分。で、こうなる。
で、Pythonで見てみる。前回と同じコード。
- import numpy as np
- import skrf as rf
- import matplotlib.pyplot as plt
- import scipy
-
- def main():
-
- ANT1 = rf.Network('out.s2p')
- ANT1.name='ANT1'
- freq=ANT1.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)
- cnx=[[(port1,0),(ANT1,0)],
- [(ANT1,1),(port2,0)],
- [(gnd,0)]]
- cir=rf.Circuit(cnx)
- ntw=cir.network
- ntw.frequency.unit='MHz'
- 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()
- if __name__ == "__main__":
- main()
で、キャパシタを入れてみる。こんなかんじで
- import numpy as np
- import skrf as rf
- import matplotlib.pyplot as plt
- import scipy
-
- def main():
-
- ANT1 = rf.Network('out.s2p')
- ANT1.name='ANT1'
- freq=ANT1.frequency
- tl_media = rf.DefinedGammaZ0(freq, z0=50)
- C11 = tl_media.capacitor(1e-12, name='C11')
- 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)
- cnx=[[(port1,0),(ANT1,0)],
- [(ANT1,1),(C11,0)],
- [(C11,1),(port2,0)],
- [(gnd,0)]]
- cir=rf.Circuit(cnx)
- ntw=cir.network
- ntw.frequency.unit='MHz'
- 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()
- if __name__ == "__main__":
- main()
キャパシタまで一緒にOpenEMSで計算したのとほんのちょっとだけ違うけど、だいたいあってるよね。OpenEMSのAddLumpedElementがそれなりにちゃんと計算しているってことがわかる。ナイス!が、AddLumpedElementするために構造が複雑になってシミュレーションにめちゃ時間かかるので、使いどころはびみょー。実際のことろ実物とどのくらい一致するのかわからんけどOpenEMSなかなかおもしろい。
0 件のコメント:
コメントを投稿