From d48d67c233e66c27427743d495b98fec98dc1eaa Mon Sep 17 00:00:00 2001 From: Thorsten Liebig Date: Mon, 14 Oct 2013 22:47:11 +0200 Subject: [PATCH] matlab: new strip-line port and examples Signed-off-by: Thorsten Liebig --- matlab/AddStripLinePort.m | 283 ++++++++++++++++++ matlab/calcPort.m | 2 +- matlab/calcTLPort.m | 14 +- .../transmission_lines/Finite_Stripline.m | 91 ++++++ .../examples/transmission_lines/Stripline.m | 78 +++++ 5 files changed, 465 insertions(+), 3 deletions(-) create mode 100644 matlab/AddStripLinePort.m create mode 100644 matlab/examples/transmission_lines/Finite_Stripline.m create mode 100644 matlab/examples/transmission_lines/Stripline.m diff --git a/matlab/AddStripLinePort.m b/matlab/AddStripLinePort.m new file mode 100644 index 0000000..96b5a61 --- /dev/null +++ b/matlab/AddStripLinePort.m @@ -0,0 +1,283 @@ +function [CSX,port] = AddStripLinePort( CSX, prio, portnr, materialname, start, stop, height, dir, evec, varargin ) +% [CSX,port] = AddStripLinePort( CSX, prio, portnr, materialname, start, stop, height, dir, evec, varargin ) +% +% CSX: CSX-object created by InitCSX() +% prio: priority for excitation and probe boxes +% portnr: (integer) number of the port +% materialname: property for the MSL (created by AddMetal()) +% start: 3D start rowvector for port definition +% stop: 3D end rowvector for port definition +% height: height of the stripline (top and bottom) +% dir: direction of wave propagation (choices: 0, 1, 2 or 'x','y','z') +% evec: excitation vector, which defines the direction of the e-field (must be the same as used in AddExcitation()) +% +% variable input: +% varargin: optional additional excitations options, see also AddExcitation +% 'ExcitePort' true/false to make the port an active feeding port (default +% is false) +% 'FeedShift' shift to port from start by a given distance in drawing +% units. Default is 0. Only active if 'ExcitePort' is set! +% 'Feed_R' Specifiy a lumped port resistance. Default is no lumped +% port resistance --> port has to end in an ABC. +% 'MeasPlaneShift' Shift the measurement plane from start t a given distance +% in drawing units. Default is the middle of start/stop. +% 'PortNamePrefix' a prefix to the port name +% +% Important: The mesh has to be already set and defined by DefineRectGrid! +% +% example: +% CSX = AddMetal( CSX, 'metal' ); %create a PEC called 'metal' +% start = [0 -width/2 0]; +% stop = [length +width/2 0]; +% [CSX,port] = AddStripLinePort( CSX, 0, 1, 'metal', start, stop, height, 'x', ... +% [0 0 -1], 'ExcitePort', true, 'Feed_R', 50 ) +% Explanation: +% - this defines a stripline in x-direction (dir='x') +% --> the wave travels along the x-direction +% - with an e-field excitation in -z-direction (evec=[0 0 -1]) +% - the excitation is active and placed at x=start(1) ('ExcitePort', true) +% - a 50 Ohm lumped port resistance is placed at x=start(1) ('Feed_R', 50) +% - the width-direction is determined by the cross product of the +% direction of propagtion (dir='x') and the excitation vector +% (evec=[0 0 -1]), in this case it is the y-direction +% - the stripline-metal is created in a xy-plane at a height at z=start(3) +% --> The upper and lower reference plane (ground) must be defined by +% the user +% +% Thorsten Liebig (c) 2013 +% +% See also InitCSX DefineRectGrid AddMetal AddMaterial AddExcitation calcPort + +%% validate arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%check mesh +if ~isfield(CSX,'RectilinearGrid') + error 'mesh needs to be defined! Use DefineRectGrid() first!'; +end +if (~isfield(CSX.RectilinearGrid,'XLines') || ~isfield(CSX.RectilinearGrid,'YLines') || ~isfield(CSX.RectilinearGrid,'ZLines')) + error 'mesh needs to be defined! Use DefineRectGrid() first!'; +end + +% check dir +dir = DirChar2Int(dir); + +% check evec +if ~(evec(1) == evec(2) == 0) && ~(evec(1) == evec(3) == 0) && ~(evec(2) == evec(3) == 0) || (sum(evec) == 0) + error 'evec must have exactly one component ~= 0' +end +evec0 = evec ./ sum(evec); % evec0 is a unit vector + +%set defaults +feed_shift = 0; +feed_R = inf; %(default is open, no resitance) +excite = false; +measplanepos = nan; +PortNamePrefix = ''; + +excite_args = {}; + +%% read optional arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +for n=1:2:numel(varargin) + if (strcmp(varargin{n},'FeedShift')==1); + feed_shift = varargin{n+1}; + if (numel(feed_shift)>1) + error 'FeedShift must be a scalar value' + end + elseif (strcmp(varargin{n},'Feed_R')==1); + feed_R = varargin{n+1}; + if (numel(feed_shift)>1) + error 'Feed_R must be a scalar value' + end + elseif (strcmp(varargin{n},'MeasPlaneShift')==1); + measplanepos = varargin{n+1}; + if (numel(feed_shift)>1) + error 'MeasPlaneShift must be a scalar value' + end + elseif (strcmp(varargin{n},'ExcitePort')==1); + if ischar(varargin{n+1}) + warning('CSXCAD:AddMSLPort','depreceated: a string as excite option is no longer supported and will be removed in the future, please use true or false'); + if ~isempty(excite) + excite = true; + else + excite = false; + end + else + excite = varargin{n+1}; + end + elseif (strcmpi(varargin{n},'PortNamePrefix')) + PortNamePrefix = varargin{n+1}; + else + excite_args{end+1} = varargin{n}; + excite_args{end+1} = varargin{n+1}; + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% normalize start and stop +nstart = min( [start;stop] ); +nstop = max( [start;stop] ); + +% determine index (1, 2 or 3) of propagation (length of MSL) +idx_prop = dir + 1; + +% determine index (1, 2 or 3) of width of MSL +dir = [0 0 0]; +dir(idx_prop) = 1; +idx_width = abs(cross(dir,evec0)) * [1;2;3]; + +% determine index (1, 2 or 3) of height +idx_height = abs(evec0) * [1;2;3]; + +if (start(idx_height)~=stop(idx_height)) + error('openEMS:AddStripLinePort','start/stop in height direction must be equal'); +end + +% direction of propagation +if stop(idx_prop)-start(idx_prop) > 0 + direction = +1; +else + direction = -1; +end + +% create the metal/material for the MSL +SL_start = start; +SL_stop = stop; +CSX = AddBox( CSX, materialname, prio, SL_start, SL_stop ); + +if isnan(measplanepos) + measplanepos = (nstart(idx_prop)+nstop(idx_prop))/2; +else + measplanepos = start(idx_prop)+direction*measplanepos; +end + +% calculate position of the voltage probes +mesh{1} = sort(CSX.RectilinearGrid.XLines); +mesh{2} = sort(CSX.RectilinearGrid.YLines); +mesh{3} = sort(CSX.RectilinearGrid.ZLines); +meshlines = interp1( mesh{idx_prop}, 1:numel(mesh{idx_prop}), measplanepos, 'nearest' ); +meshlines = mesh{idx_prop}(meshlines-1:meshlines+1); % get three lines (approx. at center) +if direction == -1 + meshlines = fliplr(meshlines); +end +SL_w2 = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), (nstart(idx_width)+nstop(idx_width))/2, 'nearest' ); +SL_w2 = mesh{idx_width}(SL_w2); % get e-line at center of MSL (SL_width/2) +v1_start(idx_prop) = meshlines(1); +v1_start(idx_width) = SL_w2; +v1_start(idx_height) = start(idx_height); +v1_stop = v1_start; +v1_stop(idx_height) = v1_start(idx_height); +v2_start = v1_start; +v2_stop = v1_stop; +v2_start(idx_prop) = meshlines(2); +v2_stop(idx_prop) = meshlines(2); +v3_start = v2_start; +v3_stop = v2_stop; +v3_start(idx_prop) = meshlines(3); +v3_stop(idx_prop) = meshlines(3); + +height_vector = [0 0 0]; +height_vector(idx_height) = height; + +weight = 0.5; +% create the voltage-probes +port.U_filename{1,1} = [PortNamePrefix 'port_ut' num2str(portnr) 'A1']; +CSX = AddProbe( CSX, port.U_filename{1,1}, 0, 'weight', weight ); +CSX = AddBox( CSX, port.U_filename{1,1}, prio, v1_start, v1_stop+height_vector); + +port.U_filename{1,2} = [PortNamePrefix 'port_ut' num2str(portnr) 'A2']; +CSX = AddProbe( CSX, port.U_filename{1,2}, 0, 'weight', -1*weight ); +CSX = AddBox( CSX, port.U_filename{1,2}, prio, v1_start, v1_stop-height_vector); + + +port.U_filename{2,1} = [PortNamePrefix 'port_ut' num2str(portnr) 'B1']; +CSX = AddProbe( CSX, port.U_filename{2,1}, 0, 'weight', weight ); +CSX = AddBox( CSX, port.U_filename{2,1}, prio, v2_start, v2_stop+height_vector ); + +port.U_filename{2,2} = [PortNamePrefix 'port_ut' num2str(portnr) 'B2']; +CSX = AddProbe( CSX, port.U_filename{2,2}, 0, 'weight', -1*weight ); +CSX = AddBox( CSX, port.U_filename{2,2}, prio, v2_start, v2_stop-height_vector ); + + +port.U_filename{3,1} = [PortNamePrefix 'port_ut' num2str(portnr) 'C1']; +CSX = AddProbe( CSX, port.U_filename{3,1}, 0, 'weight', weight ); +CSX = AddBox( CSX, port.U_filename{3,1}, prio, v3_start, v3_stop+height_vector ); + +port.U_filename{3,2} = [PortNamePrefix 'port_ut' num2str(portnr) 'C2']; +CSX = AddProbe( CSX, port.U_filename{3,2}, 0, 'weight', weight ); +CSX = AddBox( CSX, port.U_filename{3,2}, prio, v3_start, v3_stop-height_vector ); + +% calculate position of the current probes +idx = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), nstart(idx_width), 'nearest' ); +i1_start(idx_width) = mesh{idx_width}(idx) - diff(mesh{idx_width}(idx-1:idx))/2; +idx = interp1( mesh{idx_height}, 1:numel(mesh{idx_height}), start(idx_height), 'nearest' ); +i1_start(idx_height) = mesh{idx_height}(idx-1) - diff(mesh{idx_height}(idx-2:idx-1))/2; +i1_stop(idx_height) = mesh{idx_height}(idx+1) + diff(mesh{idx_height}(idx+1:idx+2))/2; +i1_start(idx_prop) = sum(meshlines(1:2))/2; +i1_stop(idx_prop) = i1_start(idx_prop); +idx = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), nstop(idx_width), 'nearest' ); +i1_stop(idx_width) = mesh{idx_width}(idx) + diff(mesh{idx_width}(idx:idx+1))/2; +i2_start = i1_start; +i2_stop = i1_stop; +i2_start(idx_prop) = sum(meshlines(2:3))/2; +i2_stop(idx_prop) = i2_start(idx_prop); + +% create the curr-probes +weight = direction; +port.I_filename{1} = [PortNamePrefix 'port_it' num2str(portnr) 'A']; +CSX = AddProbe( CSX, port.I_filename{1}, 1, 'weight', weight ); +CSX = AddBox( CSX, port.I_filename{1}, prio, i1_start, i1_stop ); +port.I_filename{2} = [PortNamePrefix 'port_it' num2str(portnr) 'B']; +CSX = AddProbe( CSX, port.I_filename{2}, 1,'weight', weight ); +CSX = AddBox( CSX, port.I_filename{2}, prio, i2_start, i2_stop ); + +% create port structure +port.LengthScale = 1; +if ((CSX.ATTRIBUTE.CoordSystem==1) && (idx_prop==2)) + port.LengthScale = SL_stop(idx_height); +end +port.nr = portnr; +port.type = 'StripLine'; +port.drawingunit = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit; +port.v_delta = diff(meshlines)*port.LengthScale; +port.i_delta = diff( meshlines(1:end-1) + diff(meshlines)/2 )*port.LengthScale; +port.direction = direction; +port.excite = 0; +port.measplanepos = abs(v2_start(idx_prop) - start(idx_prop))*port.LengthScale; +% port + +% create excitation (if enabled) and port resistance +meshline = interp1( mesh{idx_prop}, 1:numel(mesh{idx_prop}), start(idx_prop) + feed_shift*direction, 'nearest' ); +ex_start(idx_prop) = mesh{idx_prop}(meshline) ; +ex_start(idx_width) = nstart(idx_width); +ex_start(idx_height) = nstart(idx_height); +ex_stop(idx_prop) = ex_start(idx_prop); +ex_stop(idx_width) = nstop(idx_width); +ex_stop(idx_height) = nstop(idx_height); + +port.excite = 0; +if excite + port.excite = 1; + CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_1_' num2str(portnr)], 0, evec, excite_args{:} ); + CSX = AddBox( CSX, [PortNamePrefix 'port_excite_1_' num2str(portnr)], prio, ex_start, ex_stop+height_vector ); + CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_2_' num2str(portnr)], 0, -evec, excite_args{:} ); + CSX = AddBox( CSX, [PortNamePrefix 'port_excite_2_' num2str(portnr)], prio, ex_start, ex_stop-height_vector ); +end + +%% MSL resitance at start of MSL line +ex_start(idx_prop) = start(idx_prop); +ex_stop(idx_prop) = ex_start(idx_prop); + +if (feed_R > 0) && ~isinf(feed_R) + CSX = AddLumpedElement( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], idx_height-1, 'R', 2*feed_R ); + CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, ex_start, ex_stop+height_vector ); + CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, ex_start, ex_stop-height_vector ); +elseif isinf(feed_R) + % do nothing --> open port +elseif feed_R == 0 + %port "resistance" as metal + CSX = AddBox( CSX, materialname, prio, ex_start, ex_stop+height_vector ); + CSX = AddBox( CSX, materialname, prio, ex_start, ex_stop-height_vector ); +else + error('openEMS:AddMSLPort','MSL port with resitance <= 0 it not possible'); +end +end diff --git a/matlab/calcPort.m b/matlab/calcPort.m index 1a31698..15101fb 100644 --- a/matlab/calcPort.m +++ b/matlab/calcPort.m @@ -50,7 +50,7 @@ if isempty(port) return; end -if (strcmpi(port.type,'MSL') || strcmpi(port.type,'Coaxial')) +if (strcmpi(port.type,'MSL') || strcmpi(port.type,'Coaxial') || strcmpi(port.type,'StripLine')) port = calcTLPort( port, SimDir, f, varargin{:}); return elseif strcmpi(port.type,'WaveGuide') diff --git a/matlab/calcTLPort.m b/matlab/calcTLPort.m index 8c10174..be51a14 100644 --- a/matlab/calcTLPort.m +++ b/matlab/calcTLPort.m @@ -48,7 +48,7 @@ if (iscell(port)) return; end -if ((strcmpi(port.type,'MSL')~=1) && (strcmpi(port.type,'Coaxial')~=1)) +if ((strcmpi(port.type,'MSL')~=1) && (strcmpi(port.type,'Coaxial')~=1) && (strcmpi(port.type,'StripLine')~=1)) error('openEMS:calcTLPort','error, type is not a transmission line port'); end @@ -82,8 +82,18 @@ for n=1:2:numel(varargin) end end +if (strcmpi(port.type,'StripLine')==1) + U1 = ReadUI( port.U_filename(:,1), SimDir, f, UI_args{:} ); + U2 = ReadUI( port.U_filename(:,1), SimDir, f, UI_args{:} ); + U = U1; + for n=1:3 + U.TD{n}.val = U1.TD{n}.val+U2.TD{n}.val; + U.FD{n}.val = U1.FD{n}.val+U2.FD{n}.val; + end +else + U = ReadUI( port.U_filename, SimDir, f, UI_args{:} ); +end % read time domain data (multiples files) -U = ReadUI( port.U_filename, SimDir, f, UI_args{:} ); I = ReadUI( port.I_filename, SimDir, f, UI_args{:} ); % store the original frequency domain waveforms diff --git a/matlab/examples/transmission_lines/Finite_Stripline.m b/matlab/examples/transmission_lines/Finite_Stripline.m new file mode 100644 index 0000000..da2b4a3 --- /dev/null +++ b/matlab/examples/transmission_lines/Finite_Stripline.m @@ -0,0 +1,91 @@ +% example demonstrating the use of a stripline terminated by a resistance +% (c) 2013 Thorsten Liebig + +close all +clear +clc + +%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +physical_constants; +unit = 1e-6; % specify everything in um +SL_length = 50000; +SL_width = 520; +SL_height = 500; +substrate_thickness = SL_height; +substrate_epr = 3.66; +f_max = 7e9; + +Air_Spacer = 20000; + +%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%% +FDTD = InitFDTD(); +FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 ); +BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; +FDTD = SetBoundaryCond( FDTD, BC ); + +%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CSX = InitCSX(); +resolution = c0/(f_max*sqrt(substrate_epr))/unit /50; % resolution of lambda/50 +mesh.x = SmoothMeshLines( [-SL_length/2 0 SL_length/2], resolution, 1.5 ,0 ); +mesh.y = SmoothMeshLines( [0 SL_width/2+[-resolution/3 +resolution/3*2]/4], resolution/4 , 1.5 ,0); +mesh.y = SmoothMeshLines( [-10*SL_width -mesh.y mesh.y 10*SL_width], resolution, 1.3 ,0); +mesh.z = linspace(0,substrate_thickness,5); +mesh.z = sort(unique([mesh.z -mesh.z])); + +%% substrate +CSX = AddMaterial( CSX, 'RO4350B' ); +CSX = SetMaterialProperty( CSX, 'RO4350B', 'Epsilon', substrate_epr ); +start = [mesh.x(1), mesh.y(1), mesh.z(1)]; +stop = [mesh.x(end), mesh.y(end), mesh.z(end)]; +CSX = AddBox( CSX, 'RO4350B', 0, start, stop ); + +%% add air spacer +mesh.x = [mesh.x mesh.x(1)-Air_Spacer mesh.x(end)+Air_Spacer]; +mesh.y = [mesh.y mesh.y(1)-Air_Spacer mesh.y(end)+Air_Spacer]; +mesh.z = [mesh.z mesh.z(1)-Air_Spacer mesh.z(end)+Air_Spacer]; +mesh = SmoothMesh(mesh, c0/f_max/unit/20); +CSX = DefineRectGrid( CSX, unit, mesh ); + +%% SL port +CSX = AddMetal( CSX, 'PEC' ); +portstart = [ -SL_length/2, -SL_width/2, 0]; +portstop = [ 0, SL_width/2, 0]; +[CSX,port{1}] = AddStripLinePort( CSX, 999, 1, 'PEC', portstart, portstop, SL_height, 'x', [0 0 -1], 'ExcitePort', true, 'Feed_R', 50, 'MeasPlaneShift', SL_length/3); + +portstart = [+SL_length/2, -SL_width/2, 0]; +portstop = [0 , SL_width/2, 0]; +[CSX,port{2}] = AddStripLinePort( CSX, 999, 2, 'PEC', portstart, portstop, SL_height, 'x', [0 0 -1], 'MeasPlaneShift', SL_length/3, 'Feed_R', 50); + +% bottom PEC plane +CSX = AddBox(CSX, 'PEC', 999, [-SL_length/2 -10*SL_width -SL_height],[+SL_length/2 +10*SL_width -SL_height]); +% top PEC plane +CSX = AddBox(CSX, 'PEC', 999, [-SL_length/2 -10*SL_width SL_height],[+SL_length/2 +10*SL_width SL_height]); + +%% write/show/run the openEMS compatible xml-file +Sim_Path = ['tmp_' mfilename]; +Sim_CSX = 'stripline.xml'; + +[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory +[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder + +WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX ); +CSXGeomPlot( [Sim_Path '/' Sim_CSX] ); +RunOpenEMS( Sim_Path, Sim_CSX ); + +%% post-processing +close all +f = linspace( 1e6, f_max, 1601 ); +port = calcPort( port, Sim_Path, f, 'RefImpedance', 50); + +s11 = port{1}.uf.ref./ port{1}.uf.inc; +s21 = port{2}.uf.ref./ port{1}.uf.inc; + +plot(f/1e9,20*log10(abs(s11)),'k-','LineWidth',2); +hold on; +grid on; +plot(f/1e9,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([-50 2]); + diff --git a/matlab/examples/transmission_lines/Stripline.m b/matlab/examples/transmission_lines/Stripline.m new file mode 100644 index 0000000..71fd774 --- /dev/null +++ b/matlab/examples/transmission_lines/Stripline.m @@ -0,0 +1,78 @@ +% example demonstrating the use of a stripline terminated by the pml +% (c) 2013 Thorsten Liebig + +close all +clear +clc + +%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +physical_constants; +unit = 1e-6; % specify everything in um +SL_length = 50000; +SL_width = 520; +SL_height = 500; +substrate_thickness = SL_height; +substrate_epr = 3.66; +f_max = 7e9; + +%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%% +FDTD = InitFDTD(); +FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 ); +BC = {'PML_8' 'PML_8' 'PMC' 'PMC' 'PEC' 'PEC'}; +FDTD = SetBoundaryCond( FDTD, BC ); + +%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CSX = InitCSX(); +resolution = c0/(f_max*sqrt(substrate_epr))/unit /50; % resolution of lambda/50 +mesh.x = SmoothMeshLines( [-SL_length/2 0 SL_length/2], resolution, 1.5 ,0 ); +mesh.y = SmoothMeshLines( [0 SL_width/2+[-resolution/3 +resolution/3*2]/4], resolution/4 , 1.5 ,0); +mesh.y = SmoothMeshLines( [-10*SL_width -mesh.y mesh.y 10*SL_width], resolution, 1.3 ,0); +mesh.z = linspace(0,substrate_thickness,5); +mesh.z = sort(unique([mesh.z -mesh.z])); +CSX = DefineRectGrid( CSX, unit, mesh ); + +%% substrate +CSX = AddMaterial( CSX, 'RO4350B' ); +CSX = SetMaterialProperty( CSX, 'RO4350B', 'Epsilon', substrate_epr ); +start = [mesh.x(1), mesh.y(1), mesh.z(1)]; +stop = [mesh.x(end), mesh.y(end), mesh.z(end)]; +CSX = AddBox( CSX, 'RO4350B', 0, start, stop ); + +%% SL port +CSX = AddMetal( CSX, 'PEC' ); +portstart = [ mesh.x(1), -SL_width/2, 0]; +portstop = [ 0, SL_width/2, 0]; +[CSX,port{1}] = AddStripLinePort( CSX, 999, 1, 'PEC', portstart, portstop, SL_height, 'x', [0 0 -1], 'ExcitePort', true, 'FeedShift', 10*resolution, 'MeasPlaneShift', SL_length/3); + +portstart = [mesh.x(end), -SL_width/2, 0]; +portstop = [0 , SL_width/2, 0]; +[CSX,port{2}] = AddStripLinePort( CSX, 999, 2, 'PEC', portstart, portstop, SL_height, 'x', [0 0 -1], 'MeasPlaneShift', SL_length/3 ); + +%% write/show/run the openEMS compatible xml-file +Sim_Path = ['tmp_' mfilename]; +Sim_CSX = 'stripline.xml'; + +[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory +[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder + +WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX ); +CSXGeomPlot( [Sim_Path '/' Sim_CSX] ); +RunOpenEMS( Sim_Path, Sim_CSX ); + +%% post-processing +close all +f = linspace( 1e6, f_max, 1601 ); +port = calcPort( port, Sim_Path, f, 'RefImpedance', 50); + +s11 = port{1}.uf.ref./ port{1}.uf.inc; +s21 = port{2}.uf.ref./ port{1}.uf.inc; + +plot(f/1e9,20*log10(abs(s11)),'k-','LineWidth',2); +hold on; +grid on; +plot(f/1e9,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([-50 2]); +