1function [CSX,port] = AddMSLPort( CSX, prio, portnr, materialname, start, stop, dir, evec, varargin ) 2% [CSX,port] = AddMSLPort( CSX, prio, portnr, materialname, start, stop, dir, evec, varargin ) 3% 4% CSX: CSX-object created by InitCSX() 5% prio: priority for excitation and probe boxes 6% portnr: (integer) number of the port 7% materialname: property for the MSL (created by AddMetal()) 8% start: 3D start rowvector for port definition 9% stop: 3D end rowvector for port definition 10% dir: direction of wave propagation (choices: 0, 1, 2 or 'x','y','z') 11% evec: excitation vector, which defines the direction of the e-field (must be the same as used in AddExcitation()) 12% 13% variable input: 14% varargin: optional additional excitations options, see also AddExcitation 15% 'ExcitePort' true/false to make the port an active feeding port (default 16% is false) 17% 'FeedShift' shift to port from start by a given distance in drawing 18% units. Default is 0. Only active if 'ExcitePort' is set! 19% 'Feed_R' Specify a lumped port resistance. Default is no lumped 20% port resistance --> port has to end in an ABC. 21% 'MeasPlaneShift' Shift the measurement plane from start t a given distance 22% in drawing units. Default is the middle of start/stop. 23% 'PortNamePrefix' a prefix to the port name 24% 25% Important: The mesh has to be already set and defined by DefineRectGrid! 26% 27% example: 28% CSX = AddMetal( CSX, 'metal' ); %create a PEC called 'metal' 29% start = [0 -width/2 height]; 30% stop = [length +width/2 0 ]; 31% [CSX,port] = AddMSLPort( CSX, 0, 1, 'metal', start, stop, 'x', [0 0 -1], ... 32% 'ExcitePort', true, 'Feed_R', 50 ) 33% Explanation: 34% - this defines a MSL in x-direction (dir='x') 35% --> the wave travels along the x-direction 36% - with an e-field excitation in -z-direction (evec=[0 0 -1]) 37% - the excitation is active and placed at x=start(1) ('ExcitePort', true) 38% - a 50 Ohm lumped port resistance is placed at x=start(1) ('Feed_R', 50) 39% - the width-direction is determined by the cross product of the 40% direction of propagation (dir='x') and the excitation vector 41% (evec=[0 0 -1]), in this case it is the y-direction 42% - the MSL-metal is created in a xy-plane at a height at z=start(3) 43% --> It is important to define the MSL height in the start coordinate! 44% - the ground (xy-plane, not defined by the port) is assumed at z=stop(3) 45% --> The reference plane (ground) is defined in the stop coordinate! 46% 47% Sebastian Held <sebastian.held@gmx.de> May 13 2010 48% Thorsten Liebig <thorsten.liebig@gmx.de> (c) 2011-2013 49% 50% See also InitCSX DefineRectGrid AddMetal AddMaterial AddExcitation calcPort 51 52%% validate arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 53%check mesh 54if ~isfield(CSX,'RectilinearGrid') 55 error 'mesh needs to be defined! Use DefineRectGrid() first!'; 56end 57if (~isfield(CSX.RectilinearGrid,'XLines') || ~isfield(CSX.RectilinearGrid,'YLines') || ~isfield(CSX.RectilinearGrid,'ZLines')) 58 error 'mesh needs to be defined! Use DefineRectGrid() first!'; 59end 60 61% check dir 62dir = DirChar2Int(dir); 63 64% check evec 65if ~(evec(1) == evec(2) == 0) && ~(evec(1) == evec(3) == 0) && ~(evec(2) == evec(3) == 0) || (sum(evec) == 0) 66 error 'evec must have exactly one component ~= 0' 67end 68evec0 = evec ./ sum(evec); % evec0 is a unit vector 69 70%set defaults 71feed_shift = 0; 72feed_R = inf; %(default is open, no resitance) 73excite = false; 74measplanepos = nan; 75PortNamePrefix = ''; 76 77excite_args = {}; 78 79%% read optional arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80for n=1:2:numel(varargin) 81 if (strcmp(varargin{n},'FeedShift')==1); 82 feed_shift = varargin{n+1}; 83 if (numel(feed_shift)>1) 84 error 'FeedShift must be a scalar value' 85 end 86 elseif (strcmp(varargin{n},'Feed_R')==1); 87 feed_R = varargin{n+1}; 88 if (numel(feed_R)>1) 89 error 'Feed_R must be a scalar value' 90 end 91 elseif (strcmp(varargin{n},'MeasPlaneShift')==1); 92 measplanepos = varargin{n+1}; 93 if (numel(measplanepos)>1) 94 error 'MeasPlaneShift must be a scalar value' 95 end 96 elseif (strcmp(varargin{n},'ExcitePort')==1); 97 if ischar(varargin{n+1}) 98 warning('CSXCAD:AddMSLPort','deprecated: a string as excite option is no longer supported and will be removed in the future, please use true or false'); 99 if ~isempty(excite) 100 excite = true; 101 else 102 excite = false; 103 end 104 else 105 excite = varargin{n+1}; 106 end 107 elseif (strcmpi(varargin{n},'PortNamePrefix')) 108 PortNamePrefix = varargin{n+1}; 109 else 110 excite_args{end+1} = varargin{n}; 111 excite_args{end+1} = varargin{n+1}; 112 end 113end 114 115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 116 117% normalize start and stop 118nstart = min( [start;stop] ); 119nstop = max( [start;stop] ); 120 121% determine index (1, 2 or 3) of propagation (length of MSL) 122idx_prop = dir + 1; 123 124% determine index (1, 2 or 3) of width of MSL 125dir = [0 0 0]; 126dir(idx_prop) = 1; 127idx_width = abs(cross(dir,evec0)) * [1;2;3]; 128 129% determine index (1, 2 or 3) of height 130idx_height = abs(evec0) * [1;2;3]; 131 132% direction of propagation 133if stop(idx_prop)-start(idx_prop) > 0 134 direction = +1; 135else 136 direction = -1; 137end 138 139% direction of propagation 140if stop(idx_height)-start(idx_height) > 0 141 upsidedown = +1; 142else 143 upsidedown = -1; 144end 145 146% create the metal/material for the MSL 147MSL_start = start; 148MSL_stop = stop; 149MSL_stop(idx_height) = MSL_start(idx_height); 150CSX = AddBox( CSX, materialname, prio, MSL_start, MSL_stop ); 151 152if isnan(measplanepos) 153 measplanepos = (nstart(idx_prop)+nstop(idx_prop))/2; 154else 155 measplanepos = start(idx_prop)+direction*measplanepos; 156end 157 158% calculate position of the voltage probes 159try 160 mesh{1} = sort(CSX.RectilinearGrid.XLines); 161 mesh{2} = sort(CSX.RectilinearGrid.YLines); 162 mesh{3} = sort(CSX.RectilinearGrid.ZLines); 163 meshlines = interp1( mesh{idx_prop}, 1:numel(mesh{idx_prop}), measplanepos, 'nearest' ); 164 meshlines = mesh{idx_prop}(meshlines-1:meshlines+1); % get three lines (approx. at center) 165 if direction == -1 166 meshlines = fliplr(meshlines); 167 end 168 MSL_w2 = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), (nstart(idx_width)+nstop(idx_width))/2, 'nearest' ); 169 MSL_w2 = mesh{idx_width}(MSL_w2); % get e-line at center of MSL (MSL_width/2) 170 v1_start(idx_prop) = meshlines(1); 171 v1_start(idx_width) = MSL_w2; 172 v1_start(idx_height) = start(idx_height); 173 v1_stop = v1_start; 174 v1_stop(idx_height) = stop(idx_height); 175 v2_start = v1_start; 176 v2_stop = v1_stop; 177 v2_start(idx_prop) = meshlines(2); 178 v2_stop(idx_prop) = meshlines(2); 179 v3_start = v2_start; 180 v3_stop = v2_stop; 181 v3_start(idx_prop) = meshlines(3); 182 v3_stop(idx_prop) = meshlines(3); 183catch 184 error('Unable to place voltage probe on mesh; check the location of the MSL and the probe (MeasPlaneShift), and make sure that the mesh is large enough'); 185end 186 187% calculate position of the current probes 188try 189 idx = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), nstart(idx_width), 'nearest' ); 190 i1_start(idx_width) = mesh{idx_width}(idx) - diff(mesh{idx_width}(idx-1:idx))/2; 191 idx = interp1( mesh{idx_height}, 1:numel(mesh{idx_height}), start(idx_height), 'nearest' ); 192 i1_start(idx_height) = mesh{idx_height}(idx-1) - diff(mesh{idx_height}(idx-2:idx-1))/2; 193 i1_stop(idx_height) = mesh{idx_height}(idx+1) + diff(mesh{idx_height}(idx+1:idx+2))/2; 194 i1_start(idx_prop) = sum(meshlines(1:2))/2; 195 i1_stop(idx_prop) = i1_start(idx_prop); 196 idx = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), nstop(idx_width), 'nearest' ); 197 i1_stop(idx_width) = mesh{idx_width}(idx) + diff(mesh{idx_width}(idx:idx+1))/2; 198 i2_start = i1_start; 199 i2_stop = i1_stop; 200 i2_start(idx_prop) = sum(meshlines(2:3))/2; 201 i2_stop(idx_prop) = i2_start(idx_prop); 202catch 203 error('Unable to place current probe on mesh; check the location of the MSL, and make sure that the mesh is large enough'); 204end 205 206% create the probes 207port.U_filename{1} = [PortNamePrefix 'port_ut' num2str(portnr) 'A']; 208% weight = sign(stop(idx_height)-start(idx_height)) 209weight = upsidedown; 210CSX = AddProbe( CSX, port.U_filename{1}, 0, 'weight', weight ); 211CSX = AddBox( CSX, port.U_filename{1}, prio, v1_start, v1_stop ); 212port.U_filename{2} = [PortNamePrefix 'port_ut' num2str(portnr) 'B']; 213CSX = AddProbe( CSX, port.U_filename{2}, 0, 'weight', weight ); 214CSX = AddBox( CSX, port.U_filename{2}, prio, v2_start, v2_stop ); 215port.U_filename{3} = [PortNamePrefix 'port_ut' num2str(portnr) 'C']; 216CSX = AddProbe( CSX, port.U_filename{3}, 0, 'weight', weight ); 217CSX = AddBox( CSX, port.U_filename{3}, prio, v3_start, v3_stop ); 218 219weight = direction; 220port.I_filename{1} = [PortNamePrefix 'port_it' num2str(portnr) 'A']; 221CSX = AddProbe( CSX, port.I_filename{1}, 1, 'weight', weight ); 222CSX = AddBox( CSX, port.I_filename{1}, prio, i1_start, i1_stop ); 223port.I_filename{2} = [PortNamePrefix 'port_it' num2str(portnr) 'B']; 224CSX = AddProbe( CSX, port.I_filename{2}, 1,'weight', weight ); 225CSX = AddBox( CSX, port.I_filename{2}, prio, i2_start, i2_stop ); 226 227% create port structure 228port.LengthScale = 1; 229if ((CSX.ATTRIBUTE.CoordSystem==1) && (idx_prop==2)) 230 port.LengthScale = MSL_stop(idx_height); 231end 232port.nr = portnr; 233port.type = 'MSL'; 234port.drawingunit = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit; 235port.v_delta = diff(meshlines)*port.LengthScale; 236port.i_delta = diff( meshlines(1:end-1) + diff(meshlines)/2 )*port.LengthScale; 237port.direction = direction; 238port.excite = 0; 239port.measplanepos = abs(v2_start(idx_prop) - start(idx_prop))*port.LengthScale; 240% port 241 242% create excitation (if enabled) and port resistance 243try 244 meshline = interp1( mesh{idx_prop}, 1:numel(mesh{idx_prop}), start(idx_prop) + feed_shift*direction, 'nearest' ); 245 ex_start(idx_prop) = mesh{idx_prop}(meshline) ; 246 ex_start(idx_width) = nstart(idx_width); 247 ex_start(idx_height) = nstart(idx_height); 248 ex_stop(idx_prop) = ex_start(idx_prop); 249 ex_stop(idx_width) = nstop(idx_width); 250 ex_stop(idx_height) = nstop(idx_height); 251catch 252 error('Unable to place excitation on mesh; check the location of the MSL and the excitation (FeedShift), and make sure that the mesh is large enough'); 253end 254 255port.excite = 0; 256if excite 257 port.excite = 1; 258 CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], 0, evec, excite_args{:} ); 259 CSX = AddBox( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], prio, ex_start, ex_stop ); 260end 261 262%% MSL resistance at start of MSL line 263ex_start(idx_prop) = start(idx_prop); 264ex_stop(idx_prop) = ex_start(idx_prop); 265 266if (feed_R > 0) && ~isinf(feed_R) 267 CSX = AddLumpedElement( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], idx_height-1, 'R', feed_R ); 268 CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, ex_start, ex_stop ); 269elseif isinf(feed_R) 270 % do nothing --> open port 271elseif feed_R == 0 272 %port "resistance" as metal 273 CSX = AddBox( CSX, materialname, prio, ex_start, ex_stop ); 274else 275 error('openEMS:AddMSLPort','MSL port with resistance <= 0 it not possible'); 276end 277end 278