以前ギブアップしていた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 <[email protected]> -
% 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なかなかおもしろい。












コメントをお書きください