summaryrefslogtreecommitdiff
path: root/openEMS/matlab
diff options
context:
space:
mode:
Diffstat (limited to 'openEMS/matlab')
-rw-r--r--openEMS/matlab/AR_estimate.m115
-rw-r--r--openEMS/matlab/Add2Queue.m48
-rw-r--r--openEMS/matlab/AddCPWPort.m285
-rw-r--r--openEMS/matlab/AddCircWaveGuidePort.m109
-rw-r--r--openEMS/matlab/AddCoaxialPort.m232
-rw-r--r--openEMS/matlab/AddCurvePort.m182
-rw-r--r--openEMS/matlab/AddLumpedPort.m129
-rw-r--r--openEMS/matlab/AddMRStub.m73
-rw-r--r--openEMS/matlab/AddMSLPort.m265
-rw-r--r--openEMS/matlab/AddPML.m92
-rw-r--r--openEMS/matlab/AddRectWaveGuidePort.m92
-rw-r--r--openEMS/matlab/AddStripLinePort.m283
-rw-r--r--openEMS/matlab/AddWaveGuidePort.m119
-rw-r--r--openEMS/matlab/AnalyzeNF2FF.m231
-rw-r--r--openEMS/matlab/CalcNF2FF.m161
-rw-r--r--openEMS/matlab/CheckQueue.m60
-rw-r--r--openEMS/matlab/ConvertHDF5_VTK.m100
-rw-r--r--openEMS/matlab/CreateNF2FFBox.m94
-rw-r--r--openEMS/matlab/DFT_time2freq.m47
-rw-r--r--openEMS/matlab/Dump2VTK.m179
-rw-r--r--openEMS/matlab/DumpFF2VTK.m105
-rw-r--r--openEMS/matlab/FFT_time2freq.m18
-rw-r--r--openEMS/matlab/FindFreeSSH.m87
-rw-r--r--openEMS/matlab/FinishQueue.m40
-rw-r--r--openEMS/matlab/GetField_Interpolation.m147
-rw-r--r--openEMS/matlab/GetField_Range.m71
-rw-r--r--openEMS/matlab/GetField_SubSampling.m63
-rw-r--r--openEMS/matlab/GetField_TD2FD.m48
-rw-r--r--openEMS/matlab/InitCylindricalFDTD.m21
-rw-r--r--openEMS/matlab/InitFDTD.m64
-rw-r--r--openEMS/matlab/InitQueue.m90
-rw-r--r--openEMS/matlab/PlotHDF5FieldData.m94
-rw-r--r--openEMS/matlab/ReadHDF5Attribute.m33
-rw-r--r--openEMS/matlab/ReadHDF5Dump.m92
-rw-r--r--openEMS/matlab/ReadHDF5FieldData.m119
-rw-r--r--openEMS/matlab/ReadHDF5Mesh.m80
-rw-r--r--openEMS/matlab/ReadUI.m107
-rw-r--r--openEMS/matlab/ResultsQueue.m24
-rw-r--r--openEMS/matlab/RunOpenEMS.m186
-rw-r--r--openEMS/matlab/RunOpenEMS_MPI.m125
-rw-r--r--openEMS/matlab/RunOpenEMS_Parallel.m92
-rw-r--r--openEMS/matlab/SetBoundaryCond.m68
-rw-r--r--openEMS/matlab/SetCustomExcite.m21
-rw-r--r--openEMS/matlab/SetDiracExcite.m3
-rw-r--r--openEMS/matlab/SetGaussExcite.m18
-rw-r--r--openEMS/matlab/SetSinusExcite.m14
-rw-r--r--openEMS/matlab/SetStepExcite.m3
-rw-r--r--openEMS/matlab/SetupMPI.m17
-rw-r--r--openEMS/matlab/Tutorials/Bent_Patch_Antenna.m197
-rw-r--r--openEMS/matlab/Tutorials/CRLH_Extraction.m155
-rw-r--r--openEMS/matlab/Tutorials/CRLH_LeakyWaveAnt.m168
-rw-r--r--openEMS/matlab/Tutorials/Circ_Waveguide.m105
-rw-r--r--openEMS/matlab/Tutorials/Conical_Horn_Antenna.m180
-rw-r--r--openEMS/matlab/Tutorials/CreateCRLH.m55
-rw-r--r--openEMS/matlab/Tutorials/CylindricalWave_CC.m104
-rw-r--r--openEMS/matlab/Tutorials/Dipole_SAR.m221
-rw-r--r--openEMS/matlab/Tutorials/Helical_Antenna.m202
-rw-r--r--openEMS/matlab/Tutorials/Horn_Antenna.m202
-rw-r--r--openEMS/matlab/Tutorials/MRI_LP_Birdcage.m320
-rw-r--r--openEMS/matlab/Tutorials/MRI_Loop_Coil.m334
-rw-r--r--openEMS/matlab/Tutorials/MSL_NotchFilter.m92
-rw-r--r--openEMS/matlab/Tutorials/Parallel_Plate_Waveguide.m51
-rw-r--r--openEMS/matlab/Tutorials/Patch_Antenna_Array.m170
-rw-r--r--openEMS/matlab/Tutorials/Patch_Antenna_Phased_Array.m166
-rw-r--r--openEMS/matlab/Tutorials/RCS_Sphere.m138
-rw-r--r--openEMS/matlab/Tutorials/Rect_Waveguide.m121
-rw-r--r--openEMS/matlab/Tutorials/Simple_Patch_Antenna.m180
-rw-r--r--openEMS/matlab/Tutorials/readme1
-rw-r--r--openEMS/matlab/WriteHDF5.m73
-rw-r--r--openEMS/matlab/WriteOpenEMS.m19
-rw-r--r--openEMS/matlab/calcLumpedPort.m107
-rw-r--r--openEMS/matlab/calcPort.m82
-rw-r--r--openEMS/matlab/calcTLPort.m173
-rw-r--r--openEMS/matlab/calcWGPort.m145
-rw-r--r--openEMS/matlab/calc_ypar.m69
-rw-r--r--openEMS/matlab/examples/__deprecated__/MSL2.m254
-rw-r--r--openEMS/matlab/examples/antennas/Bi_Quad_Antenna.m139
-rw-r--r--openEMS/matlab/examples/antennas/Patch_Antenna.m218
-rw-r--r--openEMS/matlab/examples/antennas/Patch_Antenna_Array.m256
-rw-r--r--openEMS/matlab/examples/antennas/infDipol.m121
-rw-r--r--openEMS/matlab/examples/antennas/inverted_f.m205
-rw-r--r--openEMS/matlab/examples/optimizer/optimizer_asco.m36
-rw-r--r--openEMS/matlab/examples/optimizer/optimizer_simfun.m134
-rw-r--r--openEMS/matlab/examples/other/Helix.m154
-rw-r--r--openEMS/matlab/examples/other/LumpedElement.m158
-rw-r--r--openEMS/matlab/examples/other/Metamaterial_PlaneWave_Drude.m147
-rw-r--r--openEMS/matlab/examples/other/PML_reflection_analysis.m196
-rw-r--r--openEMS/matlab/examples/other/PlaneWave.m69
-rw-r--r--openEMS/matlab/examples/other/gauss_excitation_test.m72
-rw-r--r--openEMS/matlab/examples/other/resistance_sheet.m207
-rw-r--r--openEMS/matlab/examples/transmission_lines/CPW_Line.m125
-rw-r--r--openEMS/matlab/examples/transmission_lines/Finite_Stripline.m91
-rw-r--r--openEMS/matlab/examples/transmission_lines/MSL.m185
-rw-r--r--openEMS/matlab/examples/transmission_lines/MSL_Losses.m102
-rw-r--r--openEMS/matlab/examples/transmission_lines/Stripline.m78
-rw-r--r--openEMS/matlab/examples/transmission_lines/directional_coupler.m261
-rw-r--r--openEMS/matlab/examples/waveguide/Circ_Waveguide.m207
-rw-r--r--openEMS/matlab/examples/waveguide/Circ_Waveguide_CylinderCoords.m204
-rw-r--r--openEMS/matlab/examples/waveguide/Coax.m120
-rw-r--r--openEMS/matlab/examples/waveguide/Coax_CylinderCoords.m190
-rw-r--r--openEMS/matlab/examples/waveguide/Coax_Cylindrical_MG.m155
-rw-r--r--openEMS/matlab/examples/waveguide/Rect_Waveguide.m240
-rwxr-xr-xopenEMS/matlab/h5readatt_octave.cc135
-rw-r--r--openEMS/matlab/harminv.m77
-rw-r--r--openEMS/matlab/optimize.m203
-rw-r--r--openEMS/matlab/optimizer_asco_sim.m88
-rw-r--r--openEMS/matlab/physical_constants.m12
-rw-r--r--openEMS/matlab/plotFF3D.m91
-rw-r--r--openEMS/matlab/plotFFdB.m78
-rw-r--r--openEMS/matlab/polarFF.m172
-rw-r--r--openEMS/matlab/private/ReadNF2FF.m82
-rw-r--r--openEMS/matlab/private/invoke_openEMS.m47
-rw-r--r--openEMS/matlab/queue_addProcess.m22
-rw-r--r--openEMS/matlab/queue_checkProcess.m25
-rw-r--r--openEMS/matlab/queue_delProcess.m40
-rw-r--r--openEMS/matlab/setup.m36
116 files changed, 14008 insertions, 0 deletions
diff --git a/openEMS/matlab/AR_estimate.m b/openEMS/matlab/AR_estimate.m
new file mode 100644
index 0000000..ab6e293
--- /dev/null
+++ b/openEMS/matlab/AR_estimate.m
@@ -0,0 +1,115 @@
+function [val_ar t_ar f_val_ar EC] = AR_estimate( t, val, freq, nu, mu, expand_factor)
+% [val_ar t_ar f_val_ar EC] = AR_estimate( t, val, freq, < nu, mu, expand_factor >)
+%
+% apply autoregressive signal model to improve dft results
+%
+% t : time vector
+% val : time domain values
+% freq : frequency vector for dft
+%
+% optional
+% nu : AR order (default 40)
+% mu : number of timesteps to train the model (default 3*nu)
+% expand_factor : increase signal length by this factor (default 5)
+%
+% return values:
+% val_ar: AR estimated time signal
+% t_ar: time vector
+% f_val_ar: FD transformed AR estimated signal
+% EC: error code
+% 0 --> no error
+% 1 --> input error: t and val mismatch
+% 2 --> input error: mu has to be larger than 2*nu
+% 3 --> inout error: expand_factor has to be larger than 1
+% 10 --> AR error: signal is to short for AR estimate --> decrease AR order
+% 11 --> AR error: estimated signal appears to be unstable --> use a different mu
+%
+% openEMS matlab interface
+% -----------------------
+% Author: Thorsten Liebig, 2011
+%
+% See also ReadUI, DFT_time2freq
+
+EC = 0;
+val_ar = [];
+t_ar = [];
+f_val_ar = [];
+
+
+if numel(t) ~= numel(val)
+ if (nargout<4)
+ error 'numel(t) ~= numel(val)'
+ else
+ EC = 1;
+ return
+ end
+end
+
+if (nargin<4)
+ nu = 40;
+end
+if (nargin<5)
+ mu = 3*nu;
+end
+if (nargin<6)
+ expand_factor=5;
+end
+
+if (mu<=2*nu)
+ if (nargout<4)
+ error 'mu has to be larger than 2*nu'
+ else
+ EC = 2;
+ return
+ end
+end
+
+if (expand_factor<=1)
+ if (nargout<4)
+ error 'expand_factor has to be larger than 1'
+ else
+ EC = 3;
+ return
+ end
+end
+
+dt = t(2)-t(1);
+
+M = numel(t);
+
+if (M<0.6*mu)
+ if (nargout<4)
+ error 'signal is to short for AR estimate --> decrease AR order'
+ else
+ EC = 10;
+ return
+ end
+end
+
+for n=1:mu-nu
+ b(n) = val(end-n+1);
+ for m=1:nu
+ A(n,m)=val(end-n+1-m);
+ end
+end
+
+a = ((A'*A)\A')*b';
+
+val_ar = val;
+t_ar = t;
+for k=M:expand_factor*M
+ val_ar(k) = 0;
+ t_ar(k) = t_ar(k-1)+dt;
+ val_ar(k) = sum(a.*val_ar(k-(1:nu))');
+end
+
+if (max(val_ar(M:end)) > max(val))
+ if (nargout<4)
+ error 'estimated signal appears to be unstable --> use a different mu'
+ else
+ EC = 11;
+ return
+ end
+end
+
+f_val_ar = DFT_time2freq(t_ar, val_ar, freq);
diff --git a/openEMS/matlab/Add2Queue.m b/openEMS/matlab/Add2Queue.m
new file mode 100644
index 0000000..a80bdc9
--- /dev/null
+++ b/openEMS/matlab/Add2Queue.m
@@ -0,0 +1,48 @@
+function [queue] = Add2Queue(queue,func_name, func_args, varargin)
+% function [queue] = Add2Queue(queue,func_name, func_args, varargin)
+%
+% Use this function to add a funtion to the queue.
+%
+% For more details see: InitQueue
+%
+% See also: InitQueue, FinishQueue, ResultsQueue, RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if isfield(queue,'jobs')
+ jobnum = numel(queue.jobs)+1;
+else
+ jobnum = 1;
+end
+
+running = numel(queue.jobs_finished) - sum(queue.jobs_finished);
+
+while (running>=queue.maxThreads)
+ [queue running] = CheckQueue(queue);
+end
+
+
+if (queue.verbose>=1)
+ disp(['Add2Queue: Job #' num2str(jobnum) ' starting...']);
+end
+
+queue.jobs_finished(jobnum) = 0;
+
+queue.jobs{jobnum}.argsfile = [tempname '.mat'];
+save(queue.jobs{jobnum}.argsfile,'func_args');
+
+queue.jobs{jobnum}.nargout = nargout(func_name);
+queue.jobs{jobnum}.outargsfile = [tempname '.mat'];
+
+queue.jobs{jobnum}.command = [queue.bin queue.bin_options ' "load(''' queue.jobs{jobnum}.argsfile ''');' ...
+ queue.DependPath ...
+ 'err=[];' ...
+ 'try;' ...
+ '[outargs{1:' num2str(queue.jobs{jobnum}.nargout) '}]=' func_name '(func_args{:});' ...
+ 'catch err;outargs=0;end;' ...
+ 'save(''-V7'',''' queue.jobs{jobnum}.outargsfile ''',''outargs'',''err'');' ...
+ 'exit;"'];
+
+[queue.jobs{jobnum}.pid, queue.jobs{jobnum}.filenames] = queue_addProcess( queue.jobs{jobnum}.command );
diff --git a/openEMS/matlab/AddCPWPort.m b/openEMS/matlab/AddCPWPort.m
new file mode 100644
index 0000000..ba4fc4a
--- /dev/null
+++ b/openEMS/matlab/AddCPWPort.m
@@ -0,0 +1,285 @@
+function [CSX,port] = AddCPWPort( CSX, prio, portnr, materialname, start, stop, gap_width, dir, evec, varargin )
+% [CSX,port] = AddCPWPort( CSX, prio, portnr, materialname, start, stop, gap_width, 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 CPW (created by AddMetal())
+% start: 3D start rowvector for port definition
+% stop: 3D end rowvector for port definition
+% gap_width: width of the CPW gap (left and right)
+% 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] = AddCPWPort( CSX, 0, 1, 'metal', start, stop, gap_width, '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 <thorsten.liebig@gmx.de> (c) 2014
+%
+% 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:AddCPWPort','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 CPW)
+idx_prop = dir + 1;
+
+% determine index (1, 2 or 3) of width of CPW
+dir = [0 0 0];
+dir(idx_prop) = 1;
+idx_height = abs(cross(dir,evec0)) * [1;2;3];
+
+% determine index (1, 2 or 3) of height
+idx_width = abs(evec0) * [1;2;3];
+
+
+if (start(idx_height)~=stop(idx_height))
+ error('openEMS:AddCPWPort','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 CPW
+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 CPW (SL_width/2)
+v1_start(idx_prop) = meshlines(1);
+v1_start(idx_width) = (nstart(idx_width)+nstop(idx_width))/2;
+v1_start(idx_height) = start(idx_height);
+v1_stop = v1_start;
+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);
+
+width_add_start = [0 0 0];
+width_add_stop = [0 0 0];
+width_add_start(idx_width) = (nstop(idx_width)-nstart(idx_width))/2;
+width_add_stop(idx_width) = (nstop(idx_width)-nstart(idx_width))/2+gap_width;
+
+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', -1*weight );
+CSX = AddBox( CSX, port.U_filename{1,1}, prio, v1_start-width_add_start, v1_stop-width_add_stop);
+
+port.U_filename{1,2} = [PortNamePrefix 'port_ut' num2str(portnr) 'A2'];
+CSX = AddProbe( CSX, port.U_filename{1,2}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{1,2}, prio, v1_start+width_add_start, v1_stop+width_add_stop);
+
+
+port.U_filename{2,1} = [PortNamePrefix 'port_ut' num2str(portnr) 'B1'];
+CSX = AddProbe( CSX, port.U_filename{2,1}, 0, 'weight', -1*weight );
+CSX = AddBox( CSX, port.U_filename{2,1}, prio, v2_start-width_add_start, v2_stop-width_add_stop );
+
+port.U_filename{2,2} = [PortNamePrefix 'port_ut' num2str(portnr) 'B2'];
+CSX = AddProbe( CSX, port.U_filename{2,2}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{2,2}, prio, v2_start+width_add_start, v2_stop+width_add_stop );
+
+
+port.U_filename{3,1} = [PortNamePrefix 'port_ut' num2str(portnr) 'C1'];
+CSX = AddProbe( CSX, port.U_filename{3,1}, 0, 'weight', -1*weight );
+CSX = AddBox( CSX, port.U_filename{3,1}, prio, v3_start-width_add_start, v3_stop-width_add_stop );
+
+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+width_add_start, v3_stop+width_add_stop );
+
+% 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 = 'CPW';
+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)+nstop(idx_width))/2;
+ex_start(idx_height) = nstart(idx_height);
+ex_stop(idx_prop) = ex_start(idx_prop);
+ex_stop(idx_width) = (nstart(idx_width)+nstop(idx_width))/2;
+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-width_add_start, ex_stop-width_add_stop );
+ 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+width_add_start, ex_stop+width_add_stop );
+end
+
+%% CPW resitance at start of CPW 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_width-1, 'R', 2*feed_R );
+ CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, ex_start-width_add_start, ex_stop-width_add_stop );
+ CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, ex_start+width_add_start, ex_stop+width_add_stop );
+elseif isinf(feed_R)
+ % do nothing --> open port
+elseif feed_R == 0
+ %port "resistance" as metal
+ CSX = AddBox( CSX, materialname, prio, ex_start-width_add_start, ex_stop-width_add_stop );
+ CSX = AddBox( CSX, materialname, prio, ex_start+width_add_start, ex_stop+width_add_stop );
+else
+ error('openEMS:AddCPWPort','CPW port with resitance <= 0 it not possible');
+end
+end
diff --git a/openEMS/matlab/AddCircWaveGuidePort.m b/openEMS/matlab/AddCircWaveGuidePort.m
new file mode 100644
index 0000000..2d2e7ff
--- /dev/null
+++ b/openEMS/matlab/AddCircWaveGuidePort.m
@@ -0,0 +1,109 @@
+function [CSX,port] = AddCircWaveGuidePort( CSX, prio, portnr, start, stop, radius, mode_name, pol_ang, exc_amp, varargin )
+% function [CSX,port] = AddCircWaveGuidePort( CSX, prio, portnr, start, stop, radius, mode_name, pol_ang, exc_amp, varargin )
+%
+% Create a circular waveguide port, including an optional excitation and probes
+%
+% Note: - The excitation will be located at the start position in the given direction
+% - The voltage and current probes at the stop position in the given direction
+%
+% input:
+% CSX: complete CSX structure (must contain a mesh)
+% prio: priority of primitives
+% start: start coordinates of waveguide port box
+% stop: stop coordinates of waveguide port box
+% radius: circular waveguide radius (in meter)
+% mode_name: mode name, e.g. 'TE11' or 'TM21'
+% pol_ang: polarization angle (e.g. 0 = horizontal, pi/2 = vertical)
+% exc_amp: excitation amplitude (set 0 to be passive)
+%
+% optional (key/values):
+% varargin: optional additional excitations options, see also AddExcitation
+% 'PortNamePrefix': a prefix to the port name
+%
+% output:
+% CSX: modified CSX structure
+% port: port structure to use with calcPort
+%
+% example:
+% % create a TE11 circular waveguide mode, using cylindircal coordinates
+% start=[mesh.r(1) mesh.a(1) 0 ];
+% stop =[mesh.r(end) mesh.a(end) 100];
+% [CSX,port] = AddCircWaveGuidePort( CSX, 99, 1, start, stop, 320e-3, 'TE11', 0, 1);
+%
+% openEMS matlab interface
+% -----------------------
+% (c) 2013 Thorsten Liebig (thorsten.liebig@gmx.de)
+%
+% See also InitCSX, AddExcitation, calcWGPort, calcPort
+
+if (~strcmpi(mode_name(1:2),'TE'))
+ error 'currently only TE type modes are supported'
+end
+
+if (nargin<9)
+ exc_amp = 0;
+end
+if (nargin<8)
+ pol_ang = 0;
+end
+
+pnm = 0;
+n = str2double(mode_name(3));
+m = str2double(mode_name(4));
+
+% values by David M. Pozar, Microwave Engineering, third edition
+if ((n==0) && (m==1))
+ pnm = 3.832;
+elseif ((n==1) && (m==1))
+ pnm = 1.841;
+elseif ((n==2) && (m==1))
+ pnm = 3.054;
+elseif ((n==0) && (m==2))
+ pnm = 7.016;
+elseif ((n==1) && (m==2))
+ pnm = 5.331;
+elseif ((n==2) && (m==2))
+ pnm = 6.706;
+elseif ((n==0) && (m==3))
+ pnm = 10.174;
+elseif ((n==1) && (m==3))
+ pnm = 8.536;
+elseif ((n==2) && (m==3))
+ pnm = 9.970;
+else
+ error 'invalid TE_nm mode'
+end
+
+if ~isfield(CSX,'RectilinearGrid')
+ error 'mesh needs to be defined! Use DefineRectGrid() first!';
+end
+
+unit = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit;
+kc = pnm/radius;
+kc_draw = kc*unit;
+
+angle = ['a-' num2str(pol_ang)];
+% functions by David M. Pozar, Microwave Engineering, third edition
+% electric field mode profile
+func_Er = [ num2str(-1/kc_draw^2,15) '/rho*cos(' angle ')*j1(' num2str(kc_draw,15) '*rho)'];
+func_Ea = [ num2str(1/kc_draw,15) '*sin(' angle ')*0.5*(j0(' num2str(kc_draw,15) '*rho)-jn(2,' num2str(kc_draw,15) '*rho))'];
+
+% magnetic field mode profile
+func_Hr = [ num2str(-1/kc_draw,15) '*sin(' angle ')*0.5*(j0(' num2str(kc_draw,15) '*rho)-jn(2,' num2str(kc_draw,15) '*rho))'];
+func_Ha = [ num2str(-1/kc_draw^2,15) '/rho*cos(' angle ')*j1(' num2str(kc_draw,15) '*rho)'];
+
+if (CSX.ATTRIBUTE.CoordSystem==1)
+ func_E = {func_Er, func_Ea, 0};
+ func_H = {func_Hr, func_Ha, 0};
+else
+ func_Ex = ['(' func_Er '*cos(a) - ' func_Ea '*sin(a) ) * (rho<' num2str(radius/unit) ')'];
+ func_Ey = ['(' func_Er '*sin(a) + ' func_Ea '*cos(a) ) * (rho<' num2str(radius/unit) ')'];
+ func_E = {func_Ex, func_Ey, 0};
+
+ func_Hx = ['(' func_Hr '*cos(a) - ' func_Ha '*sin(a) ) * (rho<' num2str(radius/unit) ')'];
+ func_Hy = ['(' func_Hr '*sin(a) + ' func_Ha '*cos(a) ) * (rho<' num2str(radius/unit) ')'];
+ func_H = {func_Hx, func_Hy, 0};
+end
+
+[CSX,port] = AddWaveGuidePort( CSX, prio, portnr, start, stop, 2, func_E, func_H, kc, exc_amp, varargin{:} );
+
diff --git a/openEMS/matlab/AddCoaxialPort.m b/openEMS/matlab/AddCoaxialPort.m
new file mode 100644
index 0000000..45c0d2b
--- /dev/null
+++ b/openEMS/matlab/AddCoaxialPort.m
@@ -0,0 +1,232 @@
+function [CSX,port] = AddCoaxialPort( CSX, prio, portnr, pec_name, materialname, start, stop, dir, r_i, r_o, r_os, varargin )
+% function [CSX,port] = AddCoaxialPort( CSX, prio, portnr, pec_name, materialname, start, stop, dir, r_i, r_o, r_os, varargin )
+%
+% CSX: CSX-object created by InitCSX()
+% prio: priority for excitation and probe boxes
+% portnr: (integer) number of the port
+% pec_name: metal property for coaxial inner/outer conductor (created by AddMetal())
+% materialname: substrate property for coaxial line (created by AddMaterial())
+% Note: this may be empty for an "air filled" coaxial line
+% start: 3D start rowvector for coaxial cable axis
+% stop: 3D end rowvector for coaxial cable axis
+% dir: direction of wave propagation (choices: 0, 1, 2 or 'x','y','z')
+% r_i: inner coaxial radius (in drawing unit)
+% r_o: outer coaxial radius (in drawing unit)
+% r_os: outer shell coaxial radius (in drawing unit)
+%
+% variable input:
+% varargin: optional additional excitations options, see also AddExcitation
+% 'ExciteAmp' excitation amplitude of transversal electric field profile,
+% set to 0 (default) for a passive port
+% 'FeedShift' shift to port from start by a given distance in drawing
+% units. Default is 0. Only active if 'ExciteAmp' 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
+%
+% the mesh must be already initialized
+%
+% example:
+%
+% openEMS matlab interface
+% -----------------------
+% Thorsten Liebig <thorsten.liebig@gmx.de> (c) 2013
+%
+% See also InitCSX 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);
+
+%set defaults
+feed_shift = 0;
+feed_R = inf; %(default is open, no resitance)
+excite_amp = 0;
+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},'ExciteAmp')==1);
+ excite_amp = varargin{n+1};
+ 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
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% determine index (1, 2 or 3) of propagation (length of MSL)
+idx_prop_n = dir + 1;
+idx_prop_nP = mod((dir+1),3)+1;
+idx_prop_nPP = mod((dir+2),3)+1;
+
+% direction of propagation
+if stop(idx_prop_n)-start(idx_prop_n) > 0
+ direction = +1;
+else
+ direction = -1;
+end
+
+% create the metal for the coaxial line
+CSX = AddCylinder( CSX, pec_name, prio, start, stop, r_i );
+CSX = AddCylindricalShell( CSX, pec_name, prio, start, stop, 0.5*(r_o+r_os), r_os-r_o );
+
+% create the material filling for the coaxial line
+if (~isempty(materialname))
+ CSX = AddCylindricalShell( CSX, materialname, prio-1, start, stop, 0.5*(r_o+r_i), r_o-r_i );
+end
+
+if isnan(measplanepos)
+ measplanepos = (start(idx_prop_n)+stop(idx_prop_n))/2;
+else
+ measplanepos = start(idx_prop_n)+direction*measplanepos;
+end
+
+% calculate position of the voltage probes
+mesh{1} = sort(unique(CSX.RectilinearGrid.XLines));
+mesh{2} = sort(unique(CSX.RectilinearGrid.YLines));
+mesh{3} = sort(unique(CSX.RectilinearGrid.ZLines));
+meshlines = interp1( mesh{idx_prop_n}, 1:numel(mesh{idx_prop_n}), measplanepos, 'nearest' );
+meshlines = mesh{idx_prop_n}(meshlines-1:meshlines+1); % get three lines (approx. at center)
+if direction == -1
+ meshlines = fliplr(meshlines);
+end
+v1_start(idx_prop_n) = meshlines(1);
+v1_start(idx_prop_nP) = start(idx_prop_nP)+r_i;
+v1_start(idx_prop_nPP) = start(idx_prop_nPP);
+v1_stop = v1_start;
+v1_stop(idx_prop_nP) = start(idx_prop_nP)+r_o;
+v2_start = v1_start;
+v2_stop = v1_stop;
+v2_start(idx_prop_n) = meshlines(2);
+v2_stop(idx_prop_n) = meshlines(2);
+v3_start = v2_start;
+v3_stop = v2_stop;
+v3_start(idx_prop_n) = meshlines(3);
+v3_stop(idx_prop_n) = meshlines(3);
+
+% calculate position of the current probes
+i1_start(idx_prop_n) = 0.5*(meshlines(1)+meshlines(2));
+i1_start(idx_prop_nP) = start(idx_prop_nP)-r_i-0.1*(r_o-r_i);
+i1_start(idx_prop_nPP) = start(idx_prop_nPP)-r_i-0.1*(r_o-r_i);
+i1_stop = i1_start;
+i1_stop(idx_prop_nP) = start(idx_prop_nP)+r_i+0.1*(r_o-r_i);
+i1_stop(idx_prop_nPP) = start(idx_prop_nPP)+r_i+0.1*(r_o-r_i);
+
+i2_start = i1_start;
+i2_stop = i1_stop;
+i2_start(idx_prop_n) = 0.5*(meshlines(2)+meshlines(3));
+i2_stop(idx_prop_n) = 0.5*(meshlines(2)+meshlines(3));
+
+% create the probes
+port.U_filename{1} = [PortNamePrefix 'port_ut' num2str(portnr) 'A'];
+weight = 1;
+CSX = AddProbe( CSX, port.U_filename{1}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{1}, prio, v1_start, v1_stop );
+port.U_filename{2} = [PortNamePrefix 'port_ut' num2str(portnr) 'B'];
+CSX = AddProbe( CSX, port.U_filename{2}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{2}, prio, v2_start, v2_stop );
+port.U_filename{3} = [PortNamePrefix 'port_ut' num2str(portnr) 'C'];
+CSX = AddProbe( CSX, port.U_filename{3}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{3}, prio, v3_start, v3_stop );
+
+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;
+port.nr = portnr;
+port.type = 'Coaxial';
+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_n) - start(idx_prop_n))*port.LengthScale;
+
+port.r_i = r_i;
+port.r_o = r_o;
+
+% create excitation (if enabled) and port resistance
+meshline = interp1( mesh{idx_prop_n}, 1:numel(mesh{idx_prop_n}), start(idx_prop_n) + feed_shift*direction, 'nearest' );
+min_cell_prop = min(diff(mesh{idx_prop_n}));
+ex_start = start;
+ex_start(idx_prop_n) = mesh{idx_prop_n}(meshline) - 0.01*min_cell_prop;
+ex_stop = ex_start;
+ex_stop(idx_prop_n) = mesh{idx_prop_n}(meshline) + 0.01*min_cell_prop;
+
+port.excite = 0;
+if (excite_amp~=0)
+ dir_names={'x','y','z'};
+ nameX = ['(' dir_names{idx_prop_nP} '-' num2str(start(idx_prop_nP)) ')'];
+ nameY = ['(' dir_names{idx_prop_nPP} '-' num2str(start(idx_prop_nPP)) ')'];
+
+ func_Ex = [ nameX '/(' nameX '*' nameX '+' nameY '*' nameY ') * (sqrt(' nameX '*' nameX '+' nameY '*' nameY ')<' num2str(r_o) ') * (sqrt(' nameX '*' nameX '+' nameY '*' nameY ')>' num2str(r_i) ')'];
+ func_Ey = [ nameY '/(' nameX '*' nameX '+' nameY '*' nameY ') * (sqrt(' nameX '*' nameX '+' nameY '*' nameY ')<' num2str(r_o) ') * (sqrt(' nameX '*' nameX '+' nameY '*' nameY ')>' num2str(r_i) ')'];
+
+ func_E{idx_prop_n} = 0;
+ func_E{idx_prop_nP} = func_Ex;
+ func_E{idx_prop_nPP} = func_Ey;
+
+ port.excite = 1;
+ evec = [1 1 1];
+ evec(idx_prop_n) = 0;
+
+ CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], 0, evec, excite_args{:} );
+ CSX = SetExcitationWeight(CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], func_E );
+ CSX = AddCylindricalShell(CSX,[PortNamePrefix 'port_excite_' num2str(portnr)],0 ,ex_start,ex_stop,0.5*(r_i+r_o),(r_o-r_i));
+end
+
+%% resitance at start of coaxial line
+ex_start = start;
+ex_stop = stop;
+ex_stop(idx_prop_n) = ex_start(idx_prop_n);
+
+if (feed_R > 0) && ~isinf(feed_R)
+ error 'feed_R not yet implemented'
+elseif isinf(feed_R)
+ % do nothing --> open port
+elseif feed_R == 0
+ %port "resistance" as metal
+ CSX = AddBox( CSX, pec_name, prio, ex_start, ex_stop );
+ CSX = AddCylindricalShell(CSX, pec_name, prio ,ex_start, ex_stop, 0.5*(r_i+r_o),(r_o-r_i));
+else
+ error('openEMS:AddMSLPort','MSL port with resitance <= 0 it not possible');
+end
+end
diff --git a/openEMS/matlab/AddCurvePort.m b/openEMS/matlab/AddCurvePort.m
new file mode 100644
index 0000000..6ea99aa
--- /dev/null
+++ b/openEMS/matlab/AddCurvePort.m
@@ -0,0 +1,182 @@
+function [CSX,port] = AddCurvePort( CSX, prio, portnr, R, start, stop, excite, varargin )
+%[CSX,port] = AddCurvePort( CSX, prio, portnr, R, start, stop [, excite, varargin] )
+%
+% Creates a curve port (1-dimensional).
+% The mesh must already be initialized.
+%
+% input:
+% CSX: CSX-object created by InitCSX()
+% prio: priority for excitation, metal, sheet and probe boxes
+% portnr: (integer) number of the port
+% R: internal resistance of the port
+% start: 3D start rowvector for port definition
+% stop: 3D end rowvector for port definition
+% excite (optional): if true, the port will be switched on (see AddExcitation())
+% Note: for legacy support a string will be accepted
+% optional (key/values):
+% varargin: optional additional excitations options, see also AddExcitation
+% 'PortNamePrefix': a prefix to the port name
+%
+% output:
+% CSX:
+% port:
+%
+% example:
+% start = [0 0 0]; stop = [0 0 12];
+% this defines a lumped port in z-direction
+% the excitation/probe is placed between start(1) and stop(1)
+%
+% (C) 2010 Sebastian Held <sebastian.held@uni-due.de>
+% See also InitCSX AddExcitation
+
+port.type='Lumped';
+port.nr=portnr;
+
+PortNamePrefix = '';
+
+varargin_tmp = varargin;
+for n=1:2:numel(varargin_tmp)
+ if strcmpi('PortNamePrefix',varargin_tmp{n})
+ PortNamePrefix = varargin_tmp{n+1};
+ varargin([n n+1]) = [];
+ end
+end
+
+% make row vector
+start = reshape( start, 1, [] );
+stop = reshape( stop , 1, [] );
+
+% get grid
+mesh{1} = sort(unique(CSX.RectilinearGrid.XLines));
+mesh{2} = sort(unique(CSX.RectilinearGrid.YLines));
+mesh{3} = sort(unique(CSX.RectilinearGrid.ZLines));
+unit = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit;
+
+% find port direction
+dir = abs(stop - start);
+[dummy,dir] = max(dir);
+
+% other directions
+dir1 = mod(dir,3)+1;
+dir2 = mod(dir+1,3)+1;
+
+% normalize start and stop
+if start(dir) < stop(dir)
+ nstart = start;
+ nstop = stop;
+else
+ nstart = stop;
+ nstop = start;
+end
+
+% snap to grid
+start_idx = zeros(1,3);
+stop_idx = zeros(1,3);
+for n=1:3
+ start_idx(n) = interp1( mesh{n}, 1:numel(mesh{n}), nstart(n), 'nearest' );
+ stop_idx(n) = interp1( mesh{n}, 1:numel(mesh{n}), nstop(n), 'nearest' );
+end
+
+% calculate position
+port_start_idx = start_idx;
+port_stop_idx = stop_idx;
+if abs(start_idx(dir) - stop_idx(dir)) ~= 1
+ % calc port position
+ idx = interp1( mesh{dir}, 1:numel(mesh{dir}), (nstart(dir)+nstop(dir))/2, 'nearest' );
+ idx1 = interp1( mesh{dir1}, 1:numel(mesh{dir1}), (nstart(dir1)+nstop(dir1))/2, 'nearest' );
+ idx2 = interp1( mesh{dir2}, 1:numel(mesh{dir2}), (nstart(dir2)+nstop(dir2))/2, 'nearest' );
+ port_start_idx(dir) = idx;
+ port_start_idx(dir1) = idx1;
+ port_start_idx(dir2) = idx2;
+ port_stop_idx(dir) = idx+1;
+ port_stop_idx(dir1) = idx1;
+ port_stop_idx(dir2) = idx2;
+ metalname = [PortNamePrefix 'port' num2str(portnr) '_PEC'];
+ CSX = AddMetal( CSX, metalname );
+ CSX = AddCurve( CSX, metalname, prio, [nstart.' [mesh{1}(port_start_idx(1));mesh{2}(port_start_idx(2));mesh{3}(port_start_idx(3))]] );
+ CSX = AddCurve( CSX, metalname, prio, [nstop.' [mesh{1}(port_stop_idx(1));mesh{2}(port_stop_idx(2));mesh{3}(port_stop_idx(3))]] );
+end
+
+% calculate position of resistive material
+delta1_n = mesh{dir1}(port_start_idx(dir1)) - mesh{dir1}(port_start_idx(dir1)-1);
+delta1_p = mesh{dir1}(port_start_idx(dir1)+1) - mesh{dir1}(port_start_idx(dir1));
+delta2_n = mesh{dir2}(port_start_idx(dir2)) - mesh{dir2}(port_start_idx(dir2)-1);
+delta2_p = mesh{dir2}(port_start_idx(dir2)+1) - mesh{dir2}(port_start_idx(dir2));
+m_start = zeros(1,3);
+m_stop = zeros(1,3);
+for n=1:3
+ m_start(n) = mesh{n}(port_start_idx(n));
+ m_stop(n) = mesh{n}(port_stop_idx(n));
+end
+m_start(dir1) = m_start(dir1) - delta1_n/2;
+m_stop(dir1) = m_stop(dir1) + delta1_p/2;
+m_start(dir2) = m_start(dir2) - delta2_n/2;
+m_stop(dir2) = m_stop(dir2) + delta2_p/2;
+
+% calculate position of the voltage probe & excitation
+v_start = [mesh{1}(port_start_idx(1)), mesh{2}(port_start_idx(2)), mesh{3}(port_start_idx(3))];
+v_stop = [mesh{1}(port_stop_idx(1)), mesh{2}(port_stop_idx(2)), mesh{3}(port_stop_idx(3))];
+
+% calculate position of the current probe
+i_start = m_start;
+i_stop = m_stop;
+i_start(dir) = (i_start(dir)+i_stop(dir))/2;
+i_stop(dir) = i_start(dir);
+
+% create the probes
+port.U_filename = [PortNamePrefix 'port_ut' num2str(portnr)];
+weight = -1;
+CSX = AddProbe( CSX, port.U_filename, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename, prio, v_start, v_stop );
+port.I_filename = [PortNamePrefix 'port_it' num2str(portnr)];
+weight = 1;
+CSX = AddProbe( CSX, port.I_filename, 1, 'weight', weight );
+CSX = AddBox( CSX, port.I_filename, prio, i_start, i_stop );
+
+% create port structure
+port.drawingunit = unit;
+% port.start = start;
+% port.stop = stop;
+% port.v_start = v_start;
+% port.v_stop = v_stop;
+% port.i_start = i_start;
+% port.i_stop = i_stop;
+% port.dir = dir;
+% port.direction = direction;
+% port.idx_cal = idx_cal;
+% port.idx1 = idx1;
+% port.idx1 = idx1;
+
+if (nargin < 7)
+ excite = false;
+end
+
+% legacy support, will be removed at some point
+if ischar(excite)
+ warning('CSXCAD:AddCurvePort','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
+end
+
+port.excite = excite;
+
+% create excitation
+if (excite)
+ % excitation of this port is enabled
+ port.excite = 1;
+ e_start = v_start;
+ e_stop = v_stop;
+ CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], 0, start_idx ~= stop_idx, varargin{:});
+ CSX = AddBox( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], prio, e_start, e_stop );
+end
+
+port.Feed_R = R;
+if (R>0 && (~isinf(R)))
+ CSX = AddLumpedElement( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], dir-1, 'R', R);
+ CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, v_start, v_stop );
+elseif (R==0)
+ CSX = AddBox(CSX,metalname, prio, v_start, v_stop);
+end \ No newline at end of file
diff --git a/openEMS/matlab/AddLumpedPort.m b/openEMS/matlab/AddLumpedPort.m
new file mode 100644
index 0000000..ad6d5fa
--- /dev/null
+++ b/openEMS/matlab/AddLumpedPort.m
@@ -0,0 +1,129 @@
+function [CSX, port] = AddLumpedPort( CSX, prio, portnr, R, start, stop, dir, excite, varargin )
+% [CSX, port] = AddLumpedPort( CSX, prio, portnr, R, start, stop, dir, excite, varargin )
+%
+% Add a lumped port as an excitation.
+%
+% A lumped port consists of an excitation, a lumped resistor, a voltage and
+% current probe.
+%
+% CSX: CSX-object created by InitCSX()
+% prio: priority for substrate and probe boxes
+% portnr: (integer) number of the port
+% R: internal resistance of the port (lumped element)
+% start: 3D start rowvector for port definition
+% stop: 3D end rowvector for port definition
+% dir: direction/amplitude of port (e.g.: [1 0 0], [0 1 0] or [0 0 1])
+% excite (optional): if true, the port will be switched on (see AddExcitation())
+% Note: for legacy support a string will be accepted
+% V_Probe_Weight: additional weigth for the voltage probes
+% I_Probe_Weight: additional weigth for the current probes
+% optional (key/values):
+% 'PortNamePrefix': an prefix to the port name
+% varargin (optional): additional excitations options, see also AddExcitation
+%
+% example:
+% start = [0 -width/2 0];
+% stop = [0 width/2 height];
+% [CSX] = AddLumpedPort(CSX, 5 ,1 , 50, start, stop, [0 0 1], true);
+% %this defines an active lumped port in z-direction with a 50 Ohm port impedence
+%
+% openEMS matlab interface
+% -----------------------
+% Sebastian Held <sebastian.held@gmx.de>
+% Jun 1 2010
+% Thorsten Liebig
+% Jul 13 2011
+%
+% See also InitCSX AddExcitation
+
+% check dir
+
+port.type='Lumped';
+port.nr=portnr;
+
+V_Probe_Weight = 1;
+I_Probe_Weight = 1;
+
+if (dir(1)~=0) && (dir(2) == 0) && (dir(3)==0)
+ n_dir = 1;
+elseif (dir(1)==0) && (dir(2) ~= 0) && (dir(3)==0)
+ n_dir = 2;
+elseif (dir(1)==0) && (dir(2) == 0) && (dir(3)~=0)
+ n_dir = 3;
+else
+ error 'dir must have exactly one component ~= 0'
+end
+
+PortNamePrefix = '';
+
+varargin_tmp = varargin;
+for n=1:2:numel(varargin_tmp)
+ if strcmpi('PortNamePrefix',varargin_tmp{n})
+ PortNamePrefix = varargin_tmp{n+1};
+ varargin([n n+1]) = [];
+ elseif strcmpi('V_Probe_Weight',varargin_tmp{n})
+ V_Probe_Weight = varargin_tmp{n+1};
+ elseif strcmpi('I_Probe_Weight',varargin_tmp{n})
+ I_Probe_Weight = varargin_tmp{n+1};
+ end
+end
+
+if (stop(n_dir)==start(n_dir))
+ error 'start/stop in excitation direction in must not be equal'
+end
+
+if (stop(n_dir)-start(n_dir)) > 0
+ direction = +1;
+else
+ direction = -1;
+end
+port.direction = direction;
+
+port.Feed_R = R;
+if (R>0 && (~isinf(R)))
+ CSX = AddLumpedElement(CSX,[PortNamePrefix 'port_resist_' int2str(portnr)], n_dir-1, 'Caps', 1, 'R', R);
+ CSX = AddBox(CSX,[PortNamePrefix 'port_resist_' int2str(portnr)], prio, start, stop);
+elseif (R<=0)
+ CSX = AddMetal(CSX,[PortNamePrefix 'port_resist_' int2str(portnr)]);
+ CSX = AddBox(CSX,[PortNamePrefix 'port_resist_' int2str(portnr)], prio, start, stop);
+end
+
+if (nargin < 8)
+ excite = false;
+end
+
+% legacy support, will be removed at some point
+if ischar(excite)
+ warning('CSXCAD:AddLumpedPort','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
+end
+
+port.excite = excite;
+% create excitation
+if (excite)
+ CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], 0, -dir*direction, varargin{:});
+ CSX = AddBox( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], prio, start, stop );
+end
+
+u_start = 0.5*(start + stop);
+u_stop = 0.5*(start + stop);
+u_start(n_dir) = start(n_dir);
+u_stop(n_dir) = stop(n_dir);
+
+port.U_filename = [PortNamePrefix 'port_ut' int2str(portnr)];
+CSX = AddProbe(CSX, port.U_filename, 0, 'weight', -direction*V_Probe_Weight);
+CSX = AddBox(CSX, port.U_filename, prio, u_start, u_stop);
+
+i_start = start;
+i_stop = stop;
+i_start(n_dir) = 0.5*(start(n_dir)+stop(n_dir));
+i_stop(n_dir) = 0.5*(start(n_dir)+stop(n_dir));
+
+port.I_filename = [PortNamePrefix 'port_it' int2str(portnr)];
+CSX = AddProbe(CSX, port.I_filename, 1, 'weight', direction*I_Probe_Weight, 'NormDir', n_dir-1);
+CSX = AddBox(CSX, port.I_filename, prio, i_start, i_stop);
+
diff --git a/openEMS/matlab/AddMRStub.m b/openEMS/matlab/AddMRStub.m
new file mode 100644
index 0000000..432fa6a
--- /dev/null
+++ b/openEMS/matlab/AddMRStub.m
@@ -0,0 +1,73 @@
+function CSX = AddMRStub( CSX, materialname, prio, MSL_width, len, alpha, resolution, orientation, normVector, position )
+% CSX = AddMRStub( CSX, materialname, prio, MSL_width, len, alpha,
+% resolution, orientation, normVector, position )
+%
+% Microstrip Radial Stub
+%
+% CSX: CSX-object created by InitCSX()
+% materialname: property for the MSL (created by AddMetal() or AddMaterial())
+% prio: priority
+% MSL_width: width of the MSL to connect the stub to
+% len: length of the radial stub
+% alpha: angle subtended by the radial stub (degrees)
+% resolution: discrete angle spacing (degrees)
+% orientation: angle of main direction of the radial stub (degrees)
+% normVector: normal vector of the stub
+% position: position of the end of the MSL
+%
+% This radial stub definition is equivalent to the one Agilent ADS uses.
+%
+% example:
+% CSX = AddMRStub( CSX, 'PEC', 10, 1000, 5900, 30, 1, -90, [0 0 1], [0 -10000 254] );
+%
+%
+% Sebastian Held <sebastian.held@gmx.de>
+% Jun 1 2010
+%
+% See also InitCSX AddMetal AddMaterial
+
+% check normVector
+if ~(normVector(1) == normVector(2) == 0) && ...
+ ~(normVector(1) == normVector(3) == 0) && ...
+ ~(normVector(2) == normVector(3) == 0) || (sum(normVector) == 0)
+ error 'normVector must have exactly one component ~= 0'
+end
+normVector = normVector ./ sum(normVector); % normVector is now a unit vector
+
+% convert angles to radians
+alpha_rad = alpha/180*pi;
+orientation_rad = orientation/180*pi;
+resolution_rad = resolution/180*pi;
+
+%
+% build stub at origin (0,0,0) and translate/rotate it later
+%
+
+D = 0.5 * MSL_width / sin(alpha_rad/2);
+R = cos(alpha_rad/2) * D;
+
+% point at the center of the MSL
+p(1,1) = 0;
+p(2,1) = -MSL_width/2;
+p(1,2) = 0;
+p(2,2) = MSL_width/2;
+
+for a = alpha_rad/2 : -resolution_rad : -alpha_rad/2
+ p(1,end+1) = cos(a) * (D+len) - R;
+ p(2,end) = sin(a) * (D+len);
+end
+
+% rotate
+rot = [cos(-orientation_rad), -sin(-orientation_rad); sin(-orientation_rad), cos(-orientation_rad)];
+p = (p.' * rot).';
+
+% translate
+idx_elevation = [1 2 3];
+idx_elevation = idx_elevation(normVector>0);
+dim1 = mod( idx_elevation, 3 ) + 1;
+dim2 = mod( idx_elevation+1, 3 ) + 1;
+p(1,:) = p(1,:) + position(dim1);
+p(2,:) = p(2,:) + position(dim2);
+
+elevation = position(idx_elevation);
+CSX = AddPolygon( CSX, materialname, prio, normVector, elevation, p );
diff --git a/openEMS/matlab/AddMSLPort.m b/openEMS/matlab/AddMSLPort.m
new file mode 100644
index 0000000..462db14
--- /dev/null
+++ b/openEMS/matlab/AddMSLPort.m
@@ -0,0 +1,265 @@
+function [CSX,port] = AddMSLPort( CSX, prio, portnr, materialname, start, stop, dir, evec, varargin )
+% [CSX,port] = AddMSLPort( CSX, prio, portnr, materialname, start, stop, 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
+% 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 height];
+% stop = [length +width/2 0 ];
+% [CSX,port] = AddMSLPort( CSX, 0, 1, 'metal', start, stop, 'x', [0 0 -1], ...
+% 'ExcitePort', true, 'Feed_R', 50 )
+% Explanation:
+% - this defines a MSL 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 MSL-metal is created in a xy-plane at a height at z=start(3)
+% --> It is important to define the MSL height in the start coordinate!
+% - the ground (xy-plane, not defined by the port) is assumed at z=stop(3)
+% --> The reference plane (ground) is defined in the stop coordinate!
+%
+% Sebastian Held <sebastian.held@gmx.de> May 13 2010
+% Thorsten Liebig <thorsten.liebig@gmx.de> (c) 2011-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];
+
+% direction of propagation
+if stop(idx_prop)-start(idx_prop) > 0
+ direction = +1;
+else
+ direction = -1;
+end
+
+% direction of propagation
+if stop(idx_height)-start(idx_height) > 0
+ upsidedown = +1;
+else
+ upsidedown = -1;
+end
+
+% create the metal/material for the MSL
+MSL_start = start;
+MSL_stop = stop;
+MSL_stop(idx_height) = MSL_start(idx_height);
+CSX = AddBox( CSX, materialname, prio, MSL_start, MSL_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
+MSL_w2 = interp1( mesh{idx_width}, 1:numel(mesh{idx_width}), (nstart(idx_width)+nstop(idx_width))/2, 'nearest' );
+MSL_w2 = mesh{idx_width}(MSL_w2); % get e-line at center of MSL (MSL_width/2)
+v1_start(idx_prop) = meshlines(1);
+v1_start(idx_width) = MSL_w2;
+v1_start(idx_height) = start(idx_height);
+v1_stop = v1_start;
+v1_stop(idx_height) = stop(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);
+
+% 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 probes
+port.U_filename{1} = [PortNamePrefix 'port_ut' num2str(portnr) 'A'];
+% weight = sign(stop(idx_height)-start(idx_height))
+weight = upsidedown;
+CSX = AddProbe( CSX, port.U_filename{1}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{1}, prio, v1_start, v1_stop );
+port.U_filename{2} = [PortNamePrefix 'port_ut' num2str(portnr) 'B'];
+CSX = AddProbe( CSX, port.U_filename{2}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{2}, prio, v2_start, v2_stop );
+port.U_filename{3} = [PortNamePrefix 'port_ut' num2str(portnr) 'C'];
+CSX = AddProbe( CSX, port.U_filename{3}, 0, 'weight', weight );
+CSX = AddBox( CSX, port.U_filename{3}, prio, v3_start, v3_stop );
+
+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 = MSL_stop(idx_height);
+end
+port.nr = portnr;
+port.type = 'MSL';
+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_' num2str(portnr)], 0, evec, excite_args{:} );
+ CSX = AddBox( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], prio, ex_start, ex_stop );
+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', feed_R );
+ CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, ex_start, ex_stop );
+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 );
+else
+ error('openEMS:AddMSLPort','MSL port with resitance <= 0 it not possible');
+end
+end
diff --git a/openEMS/matlab/AddPML.m b/openEMS/matlab/AddPML.m
new file mode 100644
index 0000000..4e7ba80
--- /dev/null
+++ b/openEMS/matlab/AddPML.m
@@ -0,0 +1,92 @@
+function mesh = AddPML( mesh, numcells, CoordSystem )
+% mesh = AddPML( mesh, numcells, <CoordSystem> )
+%
+% Adds equidistant cells to the specified directions of the simulation
+% area. This is used to put a PML (perfectly matched layer) absorber there.
+% Remember: this function only adds space for the PML, the boundary
+% conditions need to be set correctly to really add PML material.
+%
+% The mesh is sorted and duplicate lines are removed.
+%
+% input:
+% mesh: mesh structure
+% numcells: 1x6 vector (xmin,xmax,ymin,ymax,zmin,zmax) with number of
+% cells to add to this direction
+% CoordSystem (optional): set to 1 in case of cylindrical mesh using
+% mesh.r, mesh.a and mesh.z
+%
+% output:
+% mesh: new mesh with the added lines
+%
+% example:
+% % some fixed mesh lines
+% mesh.x = [-100 0 100];
+% mesh.y = [-100 0 100];
+% mesh.z = [0 500];
+% mesh = DetectEdges(CSX, mesh); %detect edges
+% mesh = SmoothMesh(mesh, c0/fmax/20/unit); % smooth the mesh
+%
+% mesh = AddPML(mesh, 8); % add 8 lines to all directions
+% % or
+% mesh = AddPML(mesh, [0 0 0 0 8 8]); % add 8 lines in both z-directions
+%
+% See also DefineRectGrid, SmoothMesh, DetectEdges
+%
+% openEMS matlab interface
+% -----------------------
+% Sebastian Held <sebastian.held@uni-due.de>
+
+% check
+error( nargchk(2,3,nargin) );
+
+if (numel(numcells)==1)
+ numcells = ones(6,1)*numcells;
+end
+
+numcells = reshape( numcells, 1, [] );
+if numel(numcells) ~= 6
+ error( 'argument numcells needs to have exactly 6 elements' );
+end
+
+if (nargin<3)
+ CoordSystem = 0;
+end
+
+dir_names = 'xyz';
+if (CoordSystem==1)
+ dir_names = 'raz';
+end
+
+mesh.(dir_names(1)) = unique(sort(mesh.(dir_names(1))));
+mesh.(dir_names(2)) = unique(sort(mesh.(dir_names(2))));
+mesh.(dir_names(3)) = unique(sort(mesh.(dir_names(3))));
+
+% xmin
+delta = mesh.(dir_names(1))(2) - mesh.(dir_names(1))(1);
+start = mesh.(dir_names(1))(1) - numcells(1)*delta;
+mesh.(dir_names(1)) = [start:delta:(mesh.(dir_names(1))(1)-delta), mesh.(dir_names(1))];
+
+% xmax
+delta = mesh.(dir_names(1))(end) - mesh.(dir_names(1))(end-1);
+stop = mesh.(dir_names(1))(end) + numcells(2)*delta;
+mesh.(dir_names(1)) = [mesh.(dir_names(1)), (mesh.(dir_names(1))(end)+delta):delta:stop];
+
+% ymin
+delta = mesh.(dir_names(2))(2) - mesh.(dir_names(2))(1);
+start = mesh.(dir_names(2))(1) - numcells(3)*delta;
+mesh.(dir_names(2)) = [start:delta:(mesh.(dir_names(2))(1)-delta), mesh.(dir_names(2))];
+
+% ymax
+delta = mesh.(dir_names(2))(end) - mesh.(dir_names(2))(end-1);
+stop = mesh.(dir_names(2))(end) + numcells(4)*delta;
+mesh.(dir_names(2)) = [mesh.(dir_names(2)), (mesh.(dir_names(2))(end)+delta):delta:stop];
+
+% zmin
+delta = mesh.(dir_names(3))(2) - mesh.(dir_names(3))(1);
+start = mesh.(dir_names(3))(1) - numcells(5)*delta;
+mesh.(dir_names(3)) = [start:delta:(mesh.(dir_names(3))(1)-delta), mesh.(dir_names(3))];
+
+% zmax
+delta = mesh.(dir_names(3))(end) - mesh.(dir_names(3))(end-1);
+stop = mesh.(dir_names(3))(end) + numcells(6)*delta;
+mesh.(dir_names(3)) = [mesh.(dir_names(3)), (mesh.(dir_names(3))(end)+delta):delta:stop];
diff --git a/openEMS/matlab/AddRectWaveGuidePort.m b/openEMS/matlab/AddRectWaveGuidePort.m
new file mode 100644
index 0000000..8233f77
--- /dev/null
+++ b/openEMS/matlab/AddRectWaveGuidePort.m
@@ -0,0 +1,92 @@
+function [CSX,port] = AddRectWaveGuidePort( CSX, prio, portnr, start, stop, dir, a, b, mode_name, exc_amp, varargin )
+% function [CSX,port] = AddRectWaveGuidePort( CSX, prio, portnr, start, stop, dir, a, b, mode_name, exc_amp, varargin )
+%
+% Create a rectangular waveguide port, including an optional excitation and probes
+%
+% Note: - The excitation will be located at the start position in the given direction
+% - The voltage and current probes at the stop position in the given direction
+%
+% input:
+% CSX: complete CSX structure (must contain a mesh)
+% prio: priority of primitives
+% start: start coordinates of waveguide port box
+% stop: stop coordinates of waveguide port box
+% dir: direction of port (0/1/2 or 'x'/'y'/'z'-direction)
+% a,b: rectangular waveguide width and height (in meter)
+% mode_name: mode name, e.g. 'TE11' or 'TM21'
+% exc_amp: excitation amplitude (set 0 to be passive)
+%
+% optional (key/values):
+% varargin: optional additional excitations options, see also AddExcitation
+% 'PortNamePrefix': a prefix to the port name
+%
+% output:
+% CSX: modified CSX structure
+% port: port structure to use with calcPort
+%
+% example:
+% % create a TE10 circular waveguide mode, using cylindircal coordinates
+% start=[mesh.r(1) mesh.a(1) 0 ];
+% stop =[mesh.r(end) mesh.a(end) 100];
+% [CSX,port] = AddCircWaveGuidePort( CSX, 99, 1, start, stop, 320e-3, 'TE11', 0, 1);
+%
+% openEMS matlab interface
+% -----------------------
+% (c) 2013 Thorsten Liebig (thorsten.liebig@gmx.de)
+%
+% See also InitCSX, AddExcitation, calcWGPort, calcPort
+
+if (~strcmpi(mode_name(1:2),'TE'))
+ error 'currently only TE type modes are supported'
+end
+
+if (nargin<10)
+ exc_amp = 0;
+end
+
+m = str2double(mode_name(3));
+n = str2double(mode_name(4));
+
+% values by David M. Pozar, Microwave Engineering, third edition
+kc = sqrt((m*pi/a)^2 + (n*pi/b)^2);
+
+if ~isfield(CSX,'RectilinearGrid')
+ error 'mesh needs to be defined! Use DefineRectGrid() first!';
+ if (~isfield(CSX.RectilinearGrid,'XLines') || ~isfield(CSX.RectilinearGrid,'YLines') || ~isfield(CSX.RectilinearGrid,'ZLines'))
+ error 'mesh needs to be defined! Use DefineRectGrid() first!';
+ end
+end
+
+unit = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit;
+
+dir = DirChar2Int(dir);
+dir_names={'x','y','z'};
+
+dirP = mod((dir+1),3)+1;
+dirPP = mod((dir+2),3)+1;
+nameX = ['(' dir_names{dirP} '-' num2str(start(dirP)) ')'];
+nameY = ['(' dir_names{dirPP} '-' num2str(start(dirPP)) ')'];
+
+%convert a&b to drawing units
+a = a/unit;
+b = b/unit;
+% functions by David M. Pozar, Microwave Engineering, third edition
+% electric field mode profile
+func_Ex = [num2str( n/b) '*cos(' num2str(m*pi/a) '*' nameX ')*sin(' num2str(n*pi/b) '*' nameY ')'];
+func_Ey = [num2str(-m/a) '*sin(' num2str(m*pi/a) '*' nameX ')*cos(' num2str(n*pi/b) '*' nameY ')'];
+
+% magnetic field mode profile
+func_Hx = [num2str(m/a) '*sin(' num2str(m*pi/a) '*' nameX ')*cos(' num2str(n*pi/b) '*' nameY ')'];
+func_Hy = [num2str(n/b) '*cos(' num2str(m*pi/a) '*' nameX ')*sin(' num2str(n*pi/b) '*' nameY ')'];
+
+
+func_E{dir+1} = 0;
+func_E{dirP} = func_Ex;
+func_E{dirPP} = func_Ey;
+
+func_H{dir+1} = 0;
+func_H{dirP} = func_Hx;
+func_H{dirPP} = func_Hy;
+
+[CSX,port] = AddWaveGuidePort( CSX, prio, portnr, start, stop, dir, func_E, func_H, kc, exc_amp, varargin{:} );
+
diff --git a/openEMS/matlab/AddStripLinePort.m b/openEMS/matlab/AddStripLinePort.m
new file mode 100644
index 0000000..70dd065
--- /dev/null
+++ b/openEMS/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 <thorsten.liebig@gmx.de> (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', -1*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/openEMS/matlab/AddWaveGuidePort.m b/openEMS/matlab/AddWaveGuidePort.m
new file mode 100644
index 0000000..1a17db2
--- /dev/null
+++ b/openEMS/matlab/AddWaveGuidePort.m
@@ -0,0 +1,119 @@
+function [CSX,port] = AddWaveGuidePort( CSX, prio, portnr, start, stop, dir, E_WG_func, H_WG_func, kc, exc_amp, varargin )
+% function [CSX,port] = AddWaveGuidePort( CSX, prio, portnr, start, stop, dir, E_WG_func, H_WG_func, kc, exc_amp, varargin )
+%
+% Create a waveguide port, including an optional excitation and probes
+%
+% Note: - The excitation will be located at the start position in the given direction
+% - The voltage and current probes at the stop position in the given direction
+%
+% parameter:
+% CSX: complete CSX structure (must contain a mesh)
+% prio: priority of primitives
+% start: start coordinates of waveguide port box
+% stop: stop coordinates of waveguide port box
+% dir: direction of port (0/1/2 or 'x'/'y'/'z'-direction)
+% E_WG_func: electric field mode profile function as a string
+% H_WG_func: magnetic field mode profile function as a string
+% kc: cutoff wavenumber (defined by the waveguide dimensions)
+% exc_amp: excitation amplitude (set 0 to be passive)
+%
+% optional (key/values):
+% varargin: optional additional excitations options, see also AddExcitation
+% 'PortNamePrefix': a prefix to the port name
+%
+% output:
+% CSX: modified CSX structure
+% port: port structure to use with calcPort
+%
+% example:
+% % create a TE11 circular waveguide mode, using cylindircal coordinates
+% p11 = 1.841;
+% kc = p11 / radius; % cutoff wavenumber with radius in meter
+% kc_draw = kc*unit; % cutoff wavenumber in drawing units
+%
+% % electric field mode profile
+% func_E{1} = [ num2str(-1/kc_draw^2,15) '/rho*cos(a)*j1(' num2str(kc_draw,15) '*rho)'];
+% func_E{2} = [ num2str(1/kc_draw,15) '*sin(a)*0.5*(j0(' num2str(kc_draw,15) '*rho)-jn(2,' num2str(kc_draw,15) '*rho))'];
+% func_E{3} = 0;
+%
+% % magnetic field mode profile
+% func_H{1} = [ '-1*' num2str(1/kc_draw,15) '*sin(a)*0.5*(j0(' num2str(kc_draw,15) '*rho)-jn(2,' num2str(kc_draw,15) '*rho))'];
+% func_H{2} = [ num2str(-1/kc_draw^2,15) '/rho*cos(a)*j1(' num2str(kc_draw,15) '*rho)'];
+% func_H{3} = 0;
+%
+% start=[mesh.r(1) mesh.a(1) 0 ];
+% stop =[mesh.r(end) mesh.a(end) 100];
+% [CSX, port{1}] = AddWaveGuidePort(CSX, 0, 1, start, stop, 2, func_E, func_H, kc, 1);
+%
+% openEMS matlab interface
+% -----------------------
+% (c) 2013 Thorsten Liebig (thorsten.liebig@gmx.de)
+%
+% See also InitCSX, AddExcitation, calcWGPort, calcPort
+
+%check mesh
+if ~isfield(CSX,'RectilinearGrid')
+ error 'mesh needs to be defined! Use DefineRectGrid() first!';
+end
+
+dir = DirChar2Int(dir);
+
+port.type='WaveGuide';
+port.nr=portnr;
+port.kc = kc;
+port.dir = dir;
+port.drawingunit = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit;
+
+PortNamePrefix = '';
+
+varargin_tmp = varargin;
+for n=1:2:numel(varargin_tmp)
+ if strcmpi('PortNamePrefix',varargin_tmp{n})
+ PortNamePrefix = varargin_tmp{n+1};
+ varargin([n n+1]) = [];
+ end
+end
+
+% matlab adressing
+dir = dir + 1;
+dir_sign = sign(stop(dir) - start(dir));
+if (dir_sign==0)
+ dir_sign = 1;
+end
+
+port.direction = dir_sign;
+
+E_WG_func{dir} = 0;
+H_WG_func{dir} = 0;
+
+port.excite = 0;
+if (exc_amp~=0)
+ if (start(dir)==stop(dir))
+ error 'if waveguide port is to be excited, the length in propagation direction must not be zero'
+ end
+ e_start = start;
+ e_stop = stop;
+ e_stop(dir) = e_start(dir);
+ port.excite = 1;
+ port.excitepos = e_start(dir);
+ e_vec = [1 1 1]*exc_amp;
+ e_vec(dir) = 0;
+ exc_name = [PortNamePrefix 'port_excite_' num2str(portnr)];
+ CSX = AddExcitation( CSX, exc_name, 0, e_vec, varargin{:});
+ CSX = SetExcitationWeight(CSX, exc_name, E_WG_func );
+ CSX = AddBox( CSX, exc_name, prio, e_start, e_stop);
+end
+
+% voltage/current planes
+m_start = start;
+m_stop = stop;
+m_start(dir) = stop(dir);
+
+port.measplanepos = m_start(dir);
+port.U_filename = [PortNamePrefix 'port_ut' int2str(portnr)];
+CSX = AddProbe(CSX, port.U_filename, 10, 'ModeFunction', E_WG_func);
+CSX = AddBox(CSX, port.U_filename, 0 ,m_start, m_stop);
+
+port.I_filename = [PortNamePrefix 'port_it' int2str(portnr)];
+CSX = AddProbe(CSX, port.I_filename, 11, 'ModeFunction', H_WG_func, 'weight', dir_sign);
+CSX = AddBox(CSX, port.I_filename, 0 ,m_start, m_stop);
diff --git a/openEMS/matlab/AnalyzeNF2FF.m b/openEMS/matlab/AnalyzeNF2FF.m
new file mode 100644
index 0000000..bc88b72
--- /dev/null
+++ b/openEMS/matlab/AnalyzeNF2FF.m
@@ -0,0 +1,231 @@
+function [E_theta,E_phi,Prad,Dmax] = AnalyzeNF2FF( Sim_Path, nf2ff, f, theta, phi, r )
+% [E_theta,E_phi,Prad,Dmax] = AnalyzeNF2FF( Sim_Path, filenames_E, filenames_H, f, theta, phi, r )
+%
+% calculates the farfield via a near field to far field transformation
+%
+% input:
+% Sim_Path: simulation directory
+% nf2ff: structure on filenames etc. as created by CreateNF2FFBox
+% f: frequency (Hz) for far field calculation
+% theta: (degrees) vector of discrete theta values to calculate the far field for
+% phi: (degrees) vector of discrete phi values to calculate the far field for
+% r: (optional) Radius (m) at which the E-fields are calculated (default: 1 m)
+%
+% output:
+% E_theta: E_theta(theta,phi); theta component of the electric field strength at radius r
+% E_phi: E_phi(theta,phi); phi component of the electric field strength at radius r
+% Prad: time averaged radiated power
+% Dmax: maximum directivity
+%
+% example:
+% see examples/NF2FF/infDipol.m
+%
+% See also CreateNF2FFBox
+%
+% (C) 2010 Sebastian Held <sebastian.held@gmx.de>
+% (C) 2011 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+% check arguments
+error( nargchk(6,6,nargin) );
+if ~isscalar(f)
+ error 'Currently only one frequency is supported. Call this function multiple times.'
+end
+
+warning('openEMS:AnalyzeNF2FF','This function is deprecated, use CalcNF2FF instead');
+
+filenames_E = nf2ff.filenames_E;
+filenames_H = nf2ff.filenames_H;
+
+if (~isrow(nf2ff.directions))
+ nf2ff.directions = nf2ff.directions';
+end
+
+% read time domain field data and transform into frequency domain
+for n=find(nf2ff.directions==1)
+ [Ef{n}, E_mesh{n}] = ReadHDF5Dump( [Sim_Path '/' filenames_E{n} '.h5'], 'Frequency', f );
+
+ if (Ef{n}.FD.frequency(1) ~= f)
+ error 'frequency mismach'
+ end
+
+ %clear out time domain data
+ if isfield(Ef{n},'TD')
+ Ef{n} = rmfield(Ef{n},'TD');
+ end
+
+ [Hf{n}, H_mesh{n}] = ReadHDF5Dump( [Sim_Path '/' filenames_H{n} '.h5'], 'Frequency', f );
+ %clear out time domain data
+ if isfield(Hf{n},'TD')
+ Hf{n} = rmfield(Hf{n},'TD');
+ end
+
+ % reshape mesh into row vector
+ mesh{n}.x = reshape( E_mesh{n}.lines{1}, 1, [] );
+ mesh{n}.y = reshape( E_mesh{n}.lines{2}, 1, [] );
+ mesh{n}.z = reshape( E_mesh{n}.lines{3}, 1, [] );
+end
+
+% create a normal vector for every plane
+% FIXME!!! this is dependent upon the order of filenames_*
+n = {};
+for a=1:6
+ temp = [(a<=2), ((a>=3)&&(a<=4)), (a>=5)];
+ n{a} = temp - 2*mod(a,2)*temp;
+end
+
+
+physical_constants
+
+k = 2*pi*f/c0;
+center = [0 0 0];
+Umax = 0;
+
+phi_idx = 0;
+for phi_deg_aufpunkt = phi
+ phi_rad_aufpunkt = phi_deg_aufpunkt/180*pi; % radiant
+ phi_idx = phi_idx + 1;
+
+ theta_idx = 0;
+ for theta_deg_aufpunkt = theta
+ theta_rad_aufpunkt = theta_deg_aufpunkt/180*pi; % radiant
+ theta_idx = theta_idx + 1;
+
+ N_theta = 0;
+ N_phi = 0;
+ L_theta = 0;
+ L_phi = 0;
+ for a=find(nf2ff.directions==1)
+ [N_theta_,N_phi_,L_theta_,L_phi_] = process_plane( k, n{a}, center, mesh{a}, Ef{a}.FD.values{1}, Hf{a}.FD.values{1}, theta_rad_aufpunkt, phi_rad_aufpunkt );
+ N_theta = N_theta + N_theta_; N_phi = N_phi + N_phi_;
+ L_theta = L_theta + L_theta_; L_phi = L_phi + L_phi_;
+ end
+
+ % E-fields
+ erg_E_theta = -1i*k*exp(-1i*k*r) / (4*pi*r)*(L_phi+Z0*N_theta);
+ erg_E_phi = 1i*k*exp(-1i*k*r) / (4*pi*r)*(L_theta-Z0*N_phi);
+
+ % output
+ E_theta(theta_idx,phi_idx) = erg_E_theta;
+ E_phi(theta_idx,phi_idx) = erg_E_phi;
+
+ % directivity
+ U = r^2/(2*Z0) * sum(abs([erg_E_theta erg_E_phi]).^2);
+ Umax = max( [Umax U] );
+ end
+end
+
+% power
+Prad = 0;
+for a=find(nf2ff.directions==1)
+ [~,~,~,~,P] = process_plane( k, n{a}, center, mesh{a}, Ef{a}.FD.values{1}, Hf{a}.FD.values{1}, theta_rad_aufpunkt, phi_rad_aufpunkt );
+ Prad = Prad + P;
+end
+
+% directivity
+Dmax = 4*pi*Umax / Prad;
+
+
+% integrate over one plane
+function [N_theta,N_phi,L_theta,L_phi,Prad] = process_plane( k, n, center, mesh, E_field, H_field, theta_rad_aufpunkt, phi_rad_aufpunkt )
+% [N_theta,N_phi,L_theta,L_phi,Prad] = process_plane( k, n, center, mesh, E_field, H_field, theta_rad_aufpunkt, phi_rad_aufpunkt )
+%
+% k: wave number
+% n: normal vector of the plane
+% center: correction coordinates for the center of the antenna
+% mesh: mesh info
+% E_field: E field array ?x?x?x3
+% H_field: H field array ?x?x?x3
+
+% speed up
+sin__theta_rad_aufpunkt = sin(theta_rad_aufpunkt);
+cos__theta_rad_aufpunkt = cos(theta_rad_aufpunkt);
+sin__phi_rad_aufpunkt = sin(phi_rad_aufpunkt);
+cos__phi_rad_aufpunkt = cos(phi_rad_aufpunkt);
+
+if abs(n(1)) == 1
+ % x-plane
+ x = mesh.x(1);
+ [y z] = ndgrid( mesh.y, mesh.z );
+ coord1 = mesh.y.';
+ coord2 = mesh.z.';
+ Ex = squeeze( E_field(1,:,:,1) );
+ Ey = squeeze( E_field(1,:,:,2) );
+ Ez = squeeze( E_field(1,:,:,3) );
+ Hx = squeeze( H_field(1,:,:,1) );
+ Hy = squeeze( H_field(1,:,:,2) );
+ Hz = squeeze( H_field(1,:,:,3) );
+elseif abs(n(2)) == 1
+ % y-plane
+ y = mesh.y(1);
+ [x z] = ndgrid( mesh.x, mesh.z );
+ coord1 = mesh.x.';
+ coord2 = mesh.z.';
+ Ex = squeeze( E_field(:,1,:,1) );
+ Ey = squeeze( E_field(:,1,:,2) );
+ Ez = squeeze( E_field(:,1,:,3) );
+ Hx = squeeze( H_field(:,1,:,1) );
+ Hy = squeeze( H_field(:,1,:,2) );
+ Hz = squeeze( H_field(:,1,:,3) );
+elseif abs(n(3)) == 1
+ % z-plane
+ z = mesh.z(1);
+ [x y] = ndgrid( mesh.x, mesh.y );
+ coord1 = mesh.x.';
+ coord2 = mesh.y.';
+ Ex = squeeze( E_field(:,:,1,1) );
+ Ey = squeeze( E_field(:,:,1,2) );
+ Ez = squeeze( E_field(:,:,1,3) );
+ Hx = squeeze( H_field(:,:,1,1) );
+ Hy = squeeze( H_field(:,:,1,2) );
+ Hz = squeeze( H_field(:,:,1,3) );
+end
+
+Jx = n(2) .* Hz - n(3) .* Hy;
+Jy = n(3) .* Hx - n(1) .* Hz;
+Jz = n(1) .* Hy - n(2) .* Hx;
+Mx = -n(2) .* Ez + n(3) .* Ey;
+My = -n(3) .* Ex + n(1) .* Ez;
+Mz = -n(1) .* Ey + n(2) .* Ex;
+r_cos_psi = x*sin__theta_rad_aufpunkt*cos__phi_rad_aufpunkt + y*sin__theta_rad_aufpunkt*sin__phi_rad_aufpunkt + z*cos__theta_rad_aufpunkt;
+e_fkt = exp( +1i*k*r_cos_psi );
+N_theta = dbltrapz( ( Jx*cos__theta_rad_aufpunkt*cos__phi_rad_aufpunkt + Jy*cos__theta_rad_aufpunkt*sin__phi_rad_aufpunkt - Jz*sin__theta_rad_aufpunkt) .* e_fkt, coord1, coord2 );
+N_phi = dbltrapz( (-Jx*sin__phi_rad_aufpunkt + Jy*cos__phi_rad_aufpunkt) .* e_fkt, coord1, coord2 );
+L_theta = dbltrapz( ( Mx*cos__theta_rad_aufpunkt*cos__phi_rad_aufpunkt + My*cos__theta_rad_aufpunkt*sin__phi_rad_aufpunkt - Mz*sin__theta_rad_aufpunkt) .* e_fkt, coord1, coord2 );
+L_phi = dbltrapz( (-Mx*sin__phi_rad_aufpunkt + My*cos__phi_rad_aufpunkt) .* e_fkt, coord1, coord2 );
+
+if nargout > 4
+ % Prad requested
+
+ % this is crap! recode it!
+ EH = zeros(size(Ex));
+ for i1 = 1:numel(coord1)
+ for i2 = 1:numel(coord2)
+ E = [Ex(i1,i2) Ey(i1,i2) Ez(i1,i2)];
+ H = [Hx(i1,i2) Hy(i1,i2) Hz(i1,i2)];
+ EH(i1,i2) = real( dot(cross(E,conj(H)),n) );
+ end
+ end
+ Prad = 0.5 * dbltrapz( EH, coord1, coord2 );
+end
+
+
+
+
+function Q = dbltrapz(matrix,a,b)
+%DBLTRAPZ Trapezoidal numerical integration in two dimensions.
+% Z = DBLTRAPZ(MATRIX,A,B) computes an approximation of the double integral
+% of MATRIX via the trapezoidal method (with respect to A and B). A and B must be
+% column vectors of the same length.
+% index like this: MATRIX(A,B)
+
+if nargin < 3, error('MATLAB:dblquad:NotEnoughInputs',...
+ 'Requires at least three inputs.'); end
+if size(a,2) ~= 1, error('column vectors required'); end
+if size(b,2) ~= 1, error('column vectors required'); end
+
+temp = zeros(size(b));
+for i = 1:length(b)
+ temp(i) = trapz( a, matrix(:,i) );
+end
+
+Q = trapz( b, temp );
diff --git a/openEMS/matlab/CalcNF2FF.m b/openEMS/matlab/CalcNF2FF.m
new file mode 100644
index 0000000..c80b52e
--- /dev/null
+++ b/openEMS/matlab/CalcNF2FF.m
@@ -0,0 +1,161 @@
+function nf2ff = CalcNF2FF(nf2ff, Sim_Path, freq, theta, phi, varargin)
+% function nf2ff = CalcNF2FF(nf2ff, Sim_Path, freq, theta, phi, varargin)
+%
+% Calculate the near-field to far-field transformation created by
+% CreateNF2FFBox
+%
+% IMPORTANT:
+% Make sure to define the correct nf2ff phase center, aka. central antenna
+% position! See optional parameter below!! Default is [0 0 0]
+%
+% parameter:
+% nf2ff: data structure created by CreateNF2FFBox
+% Sim_Path: path to simulation data
+% freq: array of frequencies to analyse
+% theta,phi: spherical coordinates to evaluate the far-field on (in radians)
+%
+% optional paramater:
+% 'Center': nf2ff phase center, default is [0 0 0]
+% !! Make sure the center is never outside of your nf2ff box!!
+% Definition is the correct coordinate system necessary
+% --> either Cartesian or cylindrical coordinates
+% 'Mode': 'Mode', 0 -> read only, if data already exist (default)
+% 'Mode', 1 -> calculate anyway, overwrite existing
+% 'Mode', 2 -> read only, fail if not existing
+% 'Outfile': alternative nf2ff result hdf5 file name
+% default is: <nf2ff.name>.h5
+% 'Verbose': set verbose level for the nf2ff calculation 0-2 supported
+% 'Radius': specify the radius for the nf2ff
+% 'Eps_r': specify the relative electric permittivity for the nf2ff
+% 'Mue_r': specify the relative magnetic permeability for the nf2ff
+%
+% 'Mirror': Add mirroring in a given direction (dir), with a given
+% mirror type (PEC or PMC) and a mirror position in the given
+% direction.
+% Example: 'Mirror', {0, 'PMC', +100}
+%
+% See also: CreateNF2FFBox, ReadNF2FF
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig, 2012
+
+mode = 0;
+
+filename = nf2ff.name;
+nf2ff_xml.Planes = {};
+
+nf2ff_xml.ATTRIBUTE.Outfile = [filename '.h5'];
+
+if (isfield(nf2ff,'Eps_r'))
+ nf2ff_xml.ATTRIBUTE.Eps_r = nf2ff.Eps_r;
+end
+if (isfield(nf2ff,'Mue_r'))
+ nf2ff_xml.ATTRIBUTE.Mue_r = nf2ff.Mue_r;
+end
+
+for n=1:2:numel(varargin)-1
+ if (strcmp(varargin{n},'Mode'))
+ mode = varargin{n+1};
+ elseif (strcmp(varargin{n},'Mirror'))
+ if isfield(nf2ff_xml,'Mirror')
+ pos = length(nf2ff_xml.Mirror)+1;
+ else
+ pos = 1;
+ end
+ nf2ff_xml.Mirror{pos}.ATTRIBUTE.Dir=varargin{n+1}{1};
+ nf2ff_xml.Mirror{pos}.ATTRIBUTE.Type=varargin{n+1}{2};
+ nf2ff_xml.Mirror{pos}.ATTRIBUTE.Pos=varargin{n+1}{3};
+ else
+ nf2ff_xml.ATTRIBUTE.(varargin{n})=varargin{n+1};
+ end
+end
+
+for (n=1:numel(nf2ff.filenames_E))
+ if (nf2ff.directions(n)~=0)
+ files_E = dir([Sim_Path '/*' nf2ff.filenames_E{n} '.h5']);
+ files_H = dir([Sim_Path '/*' nf2ff.filenames_H{n} '.h5']);
+ if (numel(files_E)~=numel(files_H))
+ error 'number of E/H planes mismatch!'
+ end
+ for fn = 1:numel(files_E)
+ nf2ff_xml.Planes{end+1}.ATTRIBUTE.E_Field = files_E(fn).name;
+ nf2ff_xml.Planes{end}.ATTRIBUTE.H_Field = files_H(fn).name;
+ end
+ end
+end
+
+nf2ff_xml.ATTRIBUTE.freq = freq;
+nf2ff_xml.theta = theta;
+nf2ff_xml.phi = phi;
+
+nf2ff.xml = [Sim_Path '' filesep '' filename '.xml'];
+nf2ff.hdf5 = [Sim_Path '' filesep '' nf2ff_xml.ATTRIBUTE.Outfile];
+
+% create nf2ff structure
+struct_2_xml(nf2ff.xml,nf2ff_xml,'nf2ff');
+
+m_filename = mfilename('fullpath');
+dir_name = fileparts( m_filename );
+
+if isunix
+ nf2ff_bin = searchBinary('nf2ff', ...
+ {[dir_name filesep '..' filesep 'nf2ff' filesep], ...
+ [dir_name filesep '..' filesep '..' filesep '..' filesep 'bin' filesep]}, 0);
+else
+ nf2ff_bin = searchBinary('nf2ff.exe',[dir_name filesep '..' filesep], 0);
+end
+
+if ((exist(nf2ff.hdf5,'file') && (mode==0)) || (mode==2))
+ disp('CalcNF2FF: Reading nf2ff data only...')
+ nf2ff = ReadNF2FF(nf2ff);
+
+ % verify read data
+ if ( (vectorEqual(nf2ff.freq,freq)==0) || (vectorEqual(nf2ff.theta,theta)==0) || (vectorEqual(nf2ff.phi,phi)==0) )
+ error('openEMS:CalcNF2FF','data mismatch between read and requested data --> recalculate nf2ff --> Set Mode to 1 ');
+ end
+ return;
+end
+
+savePath = pwd;
+cd(Sim_Path);
+
+try
+ if (isempty(nf2ff_bin))
+ error('openEMS:CalcNF2FF','nf2ff binary not found!');
+ end
+ if isunix
+ % remove LD_LIBRARY_PATH set by matlab
+ system(['export LD_LIBRARY_PATH=; ' nf2ff_bin ' ' filename '.xml']);
+ else
+ system([nf2ff_bin ' ' filename '.xml']);
+ end
+ nf2ff.hdf5;
+ cd(savePath);
+catch
+ cd(savePath);
+ error 'CalcNF2FF: failed'
+end
+
+nf2ff = ReadNF2FF(nf2ff);
+
+% verify read data
+if ( (vectorEqual(nf2ff.freq,freq)==0) || (vectorEqual(nf2ff.theta,theta)==0) || (vectorEqual(nf2ff.phi,phi)==0) )
+ error('openEMS:CalcNF2FF','data mismatch between read and requested data --> THIS SHOULD NOT HAPPEN!');
+end
+
+function equal = vectorEqual(v1, v2, acc)
+if (nargin<3)
+ acc = 1e-6;
+end
+
+equal = 0;
+if numel(v1)~=numel(v2)
+ return;
+end
+
+if sum(abs((v1(:)-v2(:))/v1(:)) > acc)>0
+ return;
+end
+equal = 1;
+return
diff --git a/openEMS/matlab/CheckQueue.m b/openEMS/matlab/CheckQueue.m
new file mode 100644
index 0000000..748d706
--- /dev/null
+++ b/openEMS/matlab/CheckQueue.m
@@ -0,0 +1,60 @@
+function [queue running] = CheckQueue(queue, query_time)
+% function [queue running] = CheckQueue(queue, <query_time>)
+%
+% Check the given queue for finished tasks.
+%
+% Parameter:
+% query_time (optional): time interval to check for finished tasks
+% (in seconds, default is 5)
+%
+% For more details see: InitQueue
+%
+% See also: InitQueue, ResultsQueue, Add2Queue, RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if ~isfield(queue,'jobs')
+ running = 0;
+ return
+end
+
+if (nargin<2)
+ query_time = 5;
+end
+
+numJobs = numel(queue.jobs);
+
+pause(query_time);
+
+for n=1:numJobs
+ if (queue.jobs_finished(n)==0)
+ if (queue_checkProcess( queue.jobs{n}.pid, queue.jobs{n}.filenames)==0)
+ queue.jobs_finished(n)=1;
+ load(queue.jobs{n}.outargsfile);
+ if ~isempty(err)
+ disp(['Job with number ' num2str(n) ' failed to execute: Error message:']);
+ error(['CheckQueue:' err.message]);
+ end
+ queue.jobs{n}.outargs = outargs;
+
+ % read in output and cleanup
+ [queue.jobs{n}.stdout,queue.jobs{n}.stderr] = queue_delProcess( queue.jobs{n}.pid, queue.jobs{n}.filenames );
+
+ % cleanup
+ delete( queue.jobs{n}.argsfile );
+ clear queue.jobs{n}.argsfile;
+ delete( queue.jobs{n}.outargsfile );
+ clear queue.jobs{n}.outargsfile;
+
+ queue.jobs_finished(n) = 1;
+
+ if (queue.verbose>=1)
+ disp(['CheckQueue: Job #' num2str(n) ' is finished!']);
+ end
+ end
+ end
+end
+
+running = numel(queue.jobs_finished) - sum(queue.jobs_finished);
diff --git a/openEMS/matlab/ConvertHDF5_VTK.m b/openEMS/matlab/ConvertHDF5_VTK.m
new file mode 100644
index 0000000..545ba01
--- /dev/null
+++ b/openEMS/matlab/ConvertHDF5_VTK.m
@@ -0,0 +1,100 @@
+function ConvertHDF5_VTK(hdf_file, vtk_prefix, varargin)
+% ConvertHDF5_VTK(hdf_file, vtk_prefix, varargin)
+%
+% Convert openEMS field data stored in the given hdf5 file to a vtk file.
+%
+% arguments:
+% hdf_file: source hdf5 file
+% vtk_prefix: output vtk files prefix
+%
+% optional arguments:
+% 'TD_Dump': activate dump for time-domain data (default is off)
+% 'FD_Dump': activate dump for frequency-domain data (default is on)
+% 'NumPhase': number of phase to dump frequency domain data animation
+% (default is 36 --> 10°)
+% 'FieldName': field name written to vtk, e.g. 'E-Field'
+% 'weight': field weighting
+%
+% for more optional aguments have a look at ReadHDF5Dump
+%
+% example:
+% % read time-domian data from hdf5, perform dft and dump as vtk
+% ConvertHDF5_VTK('Et.h5','Ef','NumPhase',18,'Frequency',1e9)
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5Dump Dump2VTK
+
+do_FD_dump = 1;
+do_TD_dump = 0;
+phase_N = 36;
+weight = 1;
+
+fieldname = 'unknown';
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'TD_Dump')==1);
+ do_TD_dump = varargin{n+1};
+ elseif (strcmp(varargin{n},'FD_Dump')==1);
+ do_FD_dump = varargin{n+1};
+ elseif (strcmp(varargin{n},'NumPhase')==1);
+ phase_N = varargin{n+1};
+ elseif (strcmp(varargin{n},'FieldName')==1);
+ fieldname = varargin{n+1};
+ elseif (strcmp(varargin{n},'weight')==1);
+ weight = varargin{n+1};
+ end
+end
+
+[field mesh] = ReadHDF5Dump(hdf_file, varargin{:});
+
+if ((do_TD_dump==0) && (do_FD_dump==0))
+ warning('openEMS:ConvertHDF5_VTK','FD and TD dump disabled, nothing to be done...');
+end
+
+if (do_FD_dump)
+ if (~isfield(field,'FD'))
+ warning('openEMS:ConvertHDF5_VTK','no FD data found skipping frequency domian vtk dump...');
+ else
+ %set weighting
+ if (numel(weight)~=numel(field.FD.frequency))
+ FD_weight = ones(size(field.FD.frequency))*weight(1);
+ else
+ FD_weight = weight;
+ end
+ if (field.FD.DataType==1) % dump complex value FD data
+ ph = linspace(0,360,phase_N+1);
+ ph = ph(1:end-1);
+ for n = 1:numel(field.FD.frequency)
+ for p = ph
+ filename = [vtk_prefix '_' num2str(field.FD.frequency(n)) '_' num2str(p,'%03d') '.vtk' ];
+ Dump2VTK(filename, real(FD_weight(n)*field.FD.values{n}*exp(1j*p*pi/180)), mesh, fieldname, varargin{:});
+ end
+ filename = [vtk_prefix '_' num2str(field.FD.frequency(n)) '_abs.vtk' ];
+ Dump2VTK(filename, abs(FD_weight(n)*field.FD.values{n}), mesh, fieldname, varargin{:});
+ filename = [vtk_prefix '_' num2str(field.FD.frequency(n)) '_ang.vtk' ];
+ Dump2VTK(filename, angle(FD_weight(n)*field.FD.values{n}), mesh, fieldname, varargin{:});
+ end
+ else % dump real value FD data
+ for n = 1:numel(field.FD.frequency)
+ filename = [vtk_prefix '_' num2str(field.FD.frequency(n)) '.vtk' ];
+ Dump2VTK(filename, real(FD_weight(n)*field.FD.values{n}), mesh, fieldname, varargin{:});
+ end
+ end
+ end
+end
+
+if (do_TD_dump)
+ if (~isfield(field,'TD'))
+ warning('openEMS:ConvertHDF5_VTK','no TD data found skipping time domian vtk dump...');
+ else
+ disp('dumping time domain data...')
+ acc = ['%0' int2str(ceil(log10(numel(field.TD.time)+1))) 'd'];
+ for n = 1:numel(field.TD.time)
+ filename = [vtk_prefix '_TD_' num2str(n,acc) '.vtk' ];
+ Dump2VTK(filename, abs(weight(1))*field.TD.values{n}, mesh, fieldname, varargin{:});
+ end
+ end
+end
diff --git a/openEMS/matlab/CreateNF2FFBox.m b/openEMS/matlab/CreateNF2FFBox.m
new file mode 100644
index 0000000..a97f0d2
--- /dev/null
+++ b/openEMS/matlab/CreateNF2FFBox.m
@@ -0,0 +1,94 @@
+function [CSX nf2ff] = CreateNF2FFBox(CSX, name, start, stop, varargin)
+% function [CSX nf2ff] = CreateNF2FFBox(CSX, name, start, stop, varargin)
+%
+% create the dump boxes needed for the near field to far field transformation
+%
+% input:
+% name: name of this nf2ff box
+% start/stop: start/stop coordinates for the nf2ff box (this box has to
+% enclose all radiating structures!)
+% optional inputs:
+% 'Directions': enable/disable specific directions, e.g.
+% 'Directions',[1 1 0 0 1 1]
+% -> disable nf2ff in +/-y direction
+% 'Frequency': dump nf2ff in frequency domain, this will save disk-space
+% but is less flexible, since only this frequencies can be
+% used for the nf2ff calculations by CalcNF2FF
+% See also AddDump for more information
+% 'OptResolution': specify a dump resolution, this will save disk-space
+% See also AddDump for more information
+% e.g.: 'OptResolution', c0/max_freq/unit/15
+%
+% example:
+% see Tutorials/Simple_Patch_Antenna.m
+% see Tutorials/Helical_Antenna.m
+%
+% See also CalcNF2FF
+%
+% (C) 2010 Sebastian Held <sebastian.held@gmx.de>
+% (C) 2010-2012 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+if (nargin<5)
+ directions = ones(6,1);
+end
+
+directions = ones(6,1);
+add_args = {};
+dump_type = 0;
+dump_mode = 1;
+
+for n=1:numel(varargin)/2
+ if strcmp(varargin{2*n-1},'Frequency')
+ add_args = {add_args{:}, 'Frequency', varargin{2*n}};
+ dump_type = 10;
+ elseif strcmp(varargin{2*n-1},'Directions')
+ directions=varargin{2*n};
+ else
+ add_args = {add_args{:}, varargin{2*n-1}, varargin{2*n}};
+ end
+end
+
+nf2ff.name = name;
+nf2ff.filenames_E = {[name '_E_xn'],[name '_E_xp'],[name '_E_yn'],[name '_E_yp'],[name '_E_zn'],[name '_E_zp']};
+nf2ff.filenames_H = {[name '_H_xn'],[name '_H_xp'],[name '_H_yn'],[name '_H_yp'],[name '_H_zn'],[name '_H_zp']};
+nf2ff.directions = directions;
+
+if (isfield(CSX,'ATTRIBUTE'))
+ if (isfield(CSX.ATTRIBUTE,'CoordSystem'))
+ nf2ff.CoordSystem = CSX.ATTRIBUTE.CoordSystem;
+ end
+ if (isfield(CSX,'BackgroundMaterial'))
+ if (isfield(CSX.ATTRIBUTE,'Epsilon'))
+ nf2ff.Eps_r = CSX.ATTRIBUTE.BG_epsR;
+ end
+ if (isfield(CSX.ATTRIBUTE,'Mue'))
+ nf2ff.Mue_r = CSX.ATTRIBUTE.BG_mueR;
+ end
+ end
+end
+
+for nd = 1:3
+ pos = 2*nd-1;
+ if (directions(pos))
+ l_start = start;
+ l_stop = stop;
+ l_stop(nd) = start(nd);
+ CSX = AddBox( AddDump(CSX,nf2ff.filenames_E{pos},'DumpType',dump_type,'DumpMode',dump_mode,'FileType',1,add_args{:}), nf2ff.filenames_E{pos}, 0, l_start, l_stop );
+ CSX = AddBox( AddDump(CSX,nf2ff.filenames_H{pos},'DumpType',dump_type+1,'DumpMode',dump_mode,'FileType',1,add_args{:}), nf2ff.filenames_H{pos}, 0, l_start, l_stop );
+ else
+ nf2ff.filenames_E{pos}='';
+ nf2ff.filenames_H{pos}='';
+ end
+ pos = 2*nd;
+ if (directions(pos))
+ l_start = start;
+ l_stop = stop;
+ l_start(nd) = stop(nd);
+ CSX = AddBox( AddDump(CSX,nf2ff.filenames_E{pos},'DumpType',dump_type,'DumpMode',dump_mode,'FileType',1,add_args{:}), nf2ff.filenames_E{pos}, 0, l_start, l_stop );
+ CSX = AddBox( AddDump(CSX,nf2ff.filenames_H{pos},'DumpType',dump_type+1,'DumpMode',dump_mode,'FileType',1,add_args{:}), nf2ff.filenames_H{pos}, 0, l_start, l_stop );
+ else
+ nf2ff.filenames_E{pos}='';
+ nf2ff.filenames_H{pos}='';
+ end
+end
+
diff --git a/openEMS/matlab/DFT_time2freq.m b/openEMS/matlab/DFT_time2freq.m
new file mode 100644
index 0000000..ac84035
--- /dev/null
+++ b/openEMS/matlab/DFT_time2freq.m
@@ -0,0 +1,47 @@
+function f_val = DFT_time2freq( t, val, freq, signal_type )
+% f_val = DFT_time2freq( t, val, freq, signal_type )
+%
+% computes the DFT at the given frequencies
+%
+% parameter:
+% t : time vector
+% val: data vector
+% freq: DFT frequency vector
+% signal_type: 'pulse' (default), 'periodic'
+%
+% return values:
+% f_val: single-sided spectrum
+%
+% example:
+% t=linspace(0,1,100);
+% t_val=0.9*sin(2*pi*3*t); % sine wave; amplitude 0.9; frequency 3 Hz
+% f=linspace(1,5,101);
+% f_val=DFT_time2freq( t, t_val, f, 'periodic' );
+% interp1(f,abs(f_val),3)
+% ans = 0.8910
+% plot( t, t_val )
+% plot( f, abs(f_val) )
+
+if numel(t) ~= numel(val)
+ error 'numel(t) ~= numel(val)'
+end
+
+if nargin<4
+ signal_type = 'pulse';
+end
+
+f_val = zeros(1,numel(freq));
+for f_idx=1:numel(freq)
+ f_val(f_idx) = sum( val .* exp( -1i * 2*pi*freq(f_idx) * t ) );
+end
+
+if strcmpi(signal_type, 'pulse')
+ dt = t(2)-t(1);
+ f_val = f_val * dt;
+elseif strcmpi(signal_type, 'periodic')
+ f_val = f_val / length(t);
+else
+ error 'unknown signal type'
+end
+
+f_val = f_val * 2; % single-sided spectrum
diff --git a/openEMS/matlab/Dump2VTK.m b/openEMS/matlab/Dump2VTK.m
new file mode 100644
index 0000000..e57b153
--- /dev/null
+++ b/openEMS/matlab/Dump2VTK.m
@@ -0,0 +1,179 @@
+function Dump2VTK(filename, fields, mesh, fieldname, varargin)
+% Dump2VTK(filename, fields, mesh, fieldname, varargin)
+%
+% Dump fields extraced from an hdf5 file to a vtk file format
+%
+% possible arguments:
+% 'NativeDump': 0 (default) / 1, dump in native coordinate system
+% 'CloseAlpha': 0 (default) / 1, repeat first/last line in
+% alpha-direction for a full cylindrical mesh
+%
+% example:
+%
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5FieldData ReadHDF5Mesh GetField_TD2FD GetField_Interpolation
+
+NativeDump = 0;
+CloseAlpha = 0;
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'NativeDump')==1);
+ NativeDump = varargin{n+1};
+ elseif (strcmp(varargin{n},'CloseAlpha')==1);
+ CloseAlpha = varargin{n+1};
+ end
+end
+
+x = mesh.lines{1};
+y = mesh.lines{2};
+z = mesh.lines{3};
+
+fid = fopen(filename,'w+');
+
+% set nan values to zero
+ind = find(isnan(fields));
+if (~isempty(ind))
+ warning('openEMS:Dump2VTK','field contains nan, setting to zero');
+ fields(ind)=0;
+end
+
+% set inf values to zero
+ind = find(isinf(fields));
+if (~isempty(ind))
+ warning('openEMS:Dump2VTK','field contains inf, setting to zero');
+ fields(ind)=0;
+end
+
+if ((CloseAlpha~=0) && (mesh.type==1) && (range(y)<2*pi))
+ y(end+1) = y(1)+2*pi;
+ fields(:,end+1,:,:) = fields(:,1,:,:);
+end
+
+if (mesh.type==0) %write cartesian mesh to vtk
+ fprintf(fid,'# vtk DataFile Version 2.0\n');
+ fprintf(fid,'Rectilinear Grid by matlab-interface of openEMS\n');
+ fprintf(fid,'ASCII\n');
+ fprintf(fid,'DATASET RECTILINEAR_GRID\n');
+
+ fprintf(fid,'DIMENSIONS %d %d %d\n',numel(x),numel(y),numel(z));
+
+ fprintf(fid,'X_COORDINATES %d double\n',numel(x));
+ fprintf(fid,'%e',x(1));
+ for n=2:numel(x)
+ fprintf(fid,' %e',x(n));
+ end
+ fprintf(fid,'\n');
+
+ fprintf(fid,'Y_COORDINATES %d double\n',numel(y));
+ fprintf(fid,'%e',y(1));
+ for n=2:numel(y)
+ fprintf(fid,' %e',y(n));
+ end
+ fprintf(fid,'\n');
+
+ fprintf(fid,'Z_COORDINATES %d double\n',numel(z));
+ fprintf(fid,'%e',z(1));
+ for n=2:numel(z)
+ fprintf(fid,' %e',z(n));
+ end
+
+elseif (mesh.type==1) %write cylindrical mesh to vtk
+ fprintf(fid,'# vtk DataFile Version 3.0\n');
+ fprintf(fid,'Structured Grid by matlab-interface of openEMS\n');
+ fprintf(fid,'ASCII\n');
+ fprintf(fid,'DATASET STRUCTURED_GRID\n');
+
+ fprintf(fid,'DIMENSIONS %d %d %d\n',numel(x),numel(y),numel(z));
+
+ fprintf(fid,'POINTS %d double\n',numel(x)*numel(y)*numel(z));
+
+ for nz=1:numel(z)
+ for ny=1:numel(y)
+ for nx=1:numel(x)
+ fprintf(fid,'%e %e %e\n',x(nx)*cos(y(ny)),x(nx)*sin(y(ny)),z(nz));
+ end
+ end
+ end
+ if ((ndims(fields)==4) && (NativeDump==0))
+ [R A Z] = ndgrid(x,y,z);
+ sinA = sin(A);
+ cosA = cos(A);
+ field_CC(:,:,:,1) = fields(:,:,:,1) .* cosA - fields(:,:,:,2) .* sinA;
+ field_CC(:,:,:,2) = fields(:,:,:,1) .* sinA + fields(:,:,:,2) .* cosA;
+ field_CC(:,:,:,3) = fields(:,:,:,3);
+ fields = field_CC;
+ clear R A Z sinA cosA field_CC
+ end
+elseif (mesh.type==2) %write spherical mesh to vtk
+ fprintf(fid,'# vtk DataFile Version 3.0\n');
+ fprintf(fid,'Structured Grid by matlab-interface of openEMS\n');
+ fprintf(fid,'ASCII\n');
+ fprintf(fid,'DATASET STRUCTURED_GRID\n');
+
+ fprintf(fid,'DIMENSIONS %d %d %d\n',numel(x),numel(y),numel(z));
+
+ fprintf(fid,'POINTS %d double\n',numel(x)*numel(y)*numel(z));
+
+ for nz=1:numel(z)
+ for ny=1:numel(y)
+ for nx=1:numel(x)
+ fprintf(fid,'%e %e %e\n',...
+ x(nx)*sin(y(ny))*cos(z(nz)),...
+ x(nx)*sin(y(ny))*sin(z(nz)),...
+ x(nx)*cos(y(ny)));
+ end
+ end
+ end
+
+ if ((ndims(fields)==4) && (NativeDump==0))
+ [R T A] = ndgrid(x,y,z);
+ sinA = sin(A);
+ cosA = cos(A);
+ sinT = sin(T);
+ cosT = cos(T);
+ field_CC(:,:,:,1) = fields(:,:,:,1) .* sinT .* cosA + fields(:,:,:,2) .*cosT .* cosA - fields(:,:,:,3) .* sinA;
+ field_CC(:,:,:,2) = fields(:,:,:,1) .* sinT .* cosA + fields(:,:,:,2) .*cosT .* sinA + fields(:,:,:,3) .* cosA;
+ field_CC(:,:,:,3) = fields(:,:,:,1) .* cosT - fields(:,:,:,2) .*sinT;
+ fields = field_CC;
+ clear R A T sinA cosA sinT cosT field_CC
+ end
+end
+
+
+fprintf(fid,'\n\n');
+
+fprintf(fid,'POINT_DATA %d\n',numel(x)*numel(y)*numel(z));
+% dump vector field data
+if (size(fields,4)>1)
+ if (nargin>3)
+ fprintf(fid,['VECTORS ' fieldname ' double\n']);
+ else
+ fprintf(fid,'VECTORS field double\n');
+ end
+ fclose(fid);
+ field_x = fields(:,:,:,1);
+ field_y = fields(:,:,:,2);
+ field_z = fields(:,:,:,3);
+ clear fields
+ dumpField(:,1) = field_x(:);
+ dumpField(:,2) = field_y(:);
+ dumpField(:,3) = field_z(:);
+ save('-ascii','-append',filename,'dumpField')
+ return
+elseif (size(fields,4)==1) % scalar field
+ if (nargin>3)
+ fprintf(fid,['SCALARS ' fieldname ' double 1\nLOOKUP_TABLE default\n']);
+ else
+ fprintf(fid,'SCALARS field double 1\nLOOKUP_TABLE default\n');
+ end
+ fclose(fid);
+ dumpField = fields(:);
+ save('-ascii','-append',filename,'dumpField')
+ return
+end
+
+fclose(fid);
diff --git a/openEMS/matlab/DumpFF2VTK.m b/openEMS/matlab/DumpFF2VTK.m
new file mode 100644
index 0000000..8e6e2f8
--- /dev/null
+++ b/openEMS/matlab/DumpFF2VTK.m
@@ -0,0 +1,105 @@
+function DumpFF2VTK(filename, farfield, thetaRange, phiRange, varargin)
+% DumpFF2VTK(filename, farfield, thetaRange, phiRange, varargin)
+%
+% Dump 3D far field pattern to a vtk file
+%
+% input:
+% filename: filename of VTK file, existing file will be overwritten
+% farfield: farfield in V/m
+% thetaRange: theta range in deg
+% phiRange: phi range in deg
+%
+% variable input:
+% 'scale': - linear scale of plot, doesn't affect gain values
+% 'logscale': - if set, show farfield with logarithmic scale
+% - set the dB value for point of origin
+% - values below will be clamped
+% 'maxgain': - add max gain in dB to normalized farfield
+% - only valid if logscale is set
+% - default is 0dB
+%
+% example:
+% DumpFF2VTK(filename, farfield, thetaRange, phiRange, ...
+% 'scale', 2, 'logscale', -20, 'maxgain', 3)
+%
+% see also examples/NF2FF/infDipol.m
+%
+% See also CreateNF2FFBox, CalcNF2FF
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+
+% defaults
+scale = 1;
+maxgain = 0;
+logscale = [];
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'maxgain')==1);
+ maxgain = varargin{n+1};
+ elseif (strcmp(varargin{n},'logscale')==1);
+ logscale = varargin{n+1};
+ elseif (strcmp(varargin{n},'scale')==1);
+ scale = varargin{n+1};
+ end
+end
+
+if ~isempty(logscale)
+ farfield = 20*log10(farfield) + maxgain - logscale;
+ ind = find(farfield<0);
+ farfield(ind)=0;
+else
+ % force 0 for linear plot
+ logscale = 0;
+end
+
+t = thetaRange*pi/180;
+a = phiRange*pi/180;
+
+fid = fopen(filename,'w+');
+
+% set nan values to zero
+ind = find(isnan(farfield));
+if (~isempty(ind))
+ warning('openEMS:Dump2VTK','field contains nan, setting to zero');
+ farfield(ind)=0;
+end
+
+% set inf values to zero
+ind = find(isinf(farfield));
+if (~isempty(ind))
+ warning('openEMS:Dump2VTK','field contains inf, setting to zero');
+ farfield(ind)=0;
+end
+
+
+fprintf(fid,'# vtk DataFile Version 3.0\n');
+fprintf(fid,'Structured Grid by matlab-interface of openEMS\n');
+fprintf(fid,'ASCII\n');
+fprintf(fid,'DATASET STRUCTURED_GRID\n');
+
+fprintf(fid,'DIMENSIONS %d %d %d\n',1,numel(t),numel(a));
+
+fprintf(fid,'POINTS %d double\n',numel(t)*numel(a));
+
+for na=1:numel(phiRange)
+ for nt=1:numel(thetaRange)
+ fprintf(fid,'%e %e %e\n',...
+ scale*farfield(nt,na)*sin(t(nt))*cos(a(na)),...
+ scale*farfield(nt,na)*sin(t(nt))*sin(a(na)),...
+ scale*farfield(nt,na)*cos(t(nt)));
+ end
+end
+
+
+
+fprintf(fid,'\n\n');
+
+fprintf(fid,'POINT_DATA %d\n',numel(t)*numel(a));
+
+fprintf(fid,['SCALARS gain double 1\nLOOKUP_TABLE default\n']);
+fclose(fid);
+dumpField = farfield(:) + logscale;
+save('-ascii','-append',filename,'dumpField')
diff --git a/openEMS/matlab/FFT_time2freq.m b/openEMS/matlab/FFT_time2freq.m
new file mode 100644
index 0000000..a82c435
--- /dev/null
+++ b/openEMS/matlab/FFT_time2freq.m
@@ -0,0 +1,18 @@
+function [f,val] = FFT_time2freq( t, val )
+% [f,val] = FFT_time2freq( t, val )
+%
+% Note: This function can only be used for pulse signals
+%
+% See also DFT_time2freq
+
+dt=t(2)-t(1); % timestep
+L=numel(val); % signal length
+NFFT = 2^nextpow2(L); % next power of 2 (makes fft fast)
+%very fine freq resolution... NFFT = NFFT+100000;
+val = fft( val, NFFT)*dt;
+f = 1/(2*dt) * linspace(0,1,NFFT/2+1);
+
+val = 2*val(1:NFFT/2+1); % single-sided spectrum
+
+%correct phase for time-shifted signals
+val = val .* exp(-1j*2*pi*f * t(1));
diff --git a/openEMS/matlab/FindFreeSSH.m b/openEMS/matlab/FindFreeSSH.m
new file mode 100644
index 0000000..8fd6c22
--- /dev/null
+++ b/openEMS/matlab/FindFreeSSH.m
@@ -0,0 +1,87 @@
+function host = FindFreeSSH(host_list, Settings, wait_time, command)
+% function host = FindFreeSSH(host_list, Settings, wait_time, command)
+%
+% Find a free ssh host not running openEMS
+%
+% internal function used by RunOpenEMS
+%
+% host_list: give a list of possible host
+%
+% wait_time: wait x seconds after not finding a free host and rechecking
+% default: 600 seconds
+%
+% command: unix command to check for free host (empty result --> free)
+% default: 'ps -e | grep openEMS'
+%
+% See also RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if (nargin<4)
+ % command which should return an empty string if host is available
+ command = 'ps -e | grep openEMS';
+end
+
+% 10 seconds ssh timeout
+time_out = 10;
+
+if (nargin<3)
+ wait_time = 600;
+end
+
+if ~isunix
+ ssh_command = [Settings.SSH.Putty.Path '/plink '];
+ ssh_options = [' -i ' Settings.SSH.Putty.Key];
+ command = ['"' command '"'];
+else
+ ssh_command = 'ssh';
+ ssh_options = ['-o ConnectTimeout=' num2str(time_out)];
+ command = ['''' command ''''];
+end
+
+if ischar(host_list)
+ fid=fopen(host_list);
+ if (fid==-1)
+ error('FindFreeSSH: cant open host file');
+ end
+ clear host_list;
+ host_list = {};
+ while 1
+ line = fgetl(fid);
+ if ischar(line)
+ host_list{end+1} = line;
+ else
+ break;
+ end
+ end
+ fclose(fid);
+elseif ~iscell(host_list)
+ error('FindFreeSSH: unknown host list format');
+end
+
+while 1
+ for n = 1:numel(host_list)
+ host = host_list{n};
+ [status, result] = unix([ssh_command ' ' ssh_options ' ' host ' ' command ]);
+ if (isempty(result) && status==1)
+ disp(['FindFreeSSH:: found a free host: ' host ]);
+ return
+ elseif (~isempty(result) && status==0)
+ disp(['FindFreeSSH:: ' host ' is busy running openEMS ... ' ]);
+ else
+ disp(['FindFreeSSH:: shh connection to ' host ' failed ... ' ]);
+ end
+ end
+
+ host = '';
+
+ if (wait_time<=0)
+ warning('openEMS:FindFreeSSH',' unable to find a free host ');
+ return
+ end
+
+ disp([' no free host found waiting for ' num2str(wait_time) ' seconds ... '])
+ pause(wait_time)
+end \ No newline at end of file
diff --git a/openEMS/matlab/FinishQueue.m b/openEMS/matlab/FinishQueue.m
new file mode 100644
index 0000000..10020c5
--- /dev/null
+++ b/openEMS/matlab/FinishQueue.m
@@ -0,0 +1,40 @@
+function [queue] = FinishQueue(queue, query_time)
+% function [queue] = FinishQueue(queue, <query_time>)
+%
+% Wait for the given queue to finish.
+%
+% Parameter:
+% query_time (optional): time interval to check for finished tasks
+% (in seconds, default is 5)
+%
+% For more details see: InitQueue
+%
+% See also: InitQueue, ResultsQueue, Add2Queue, RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if ~isfield(queue,'jobs')
+ return
+end
+
+if (nargin<2)
+ query_time = 5;
+end
+
+numJobs = numel(queue.jobs);
+
+if (queue.verbose>=1)
+ disp(['FinishQueue: Waiting for ' num2str(sum(~queue.jobs_finished)) ' of ' num2str(numJobs) ' jobs to finish...']);
+end
+
+running = numel(queue.jobs_finished) - sum(queue.jobs_finished);
+
+while sum(running)>0
+ [queue running] = CheckQueue(queue, query_time);
+end
+
+if (queue.verbose>=1)
+ disp(['FinishQueue: All jobs done!'])
+end
diff --git a/openEMS/matlab/GetField_Interpolation.m b/openEMS/matlab/GetField_Interpolation.m
new file mode 100644
index 0000000..6682a83
--- /dev/null
+++ b/openEMS/matlab/GetField_Interpolation.m
@@ -0,0 +1,147 @@
+function [field_i mesh_i] = GetField_Interpolation(field, mesh, lines, varargin)
+% [field_i mesh_i] = GetField_Interpolation(field, mesh, lines, varargin)
+%
+% Get an interpolated field, e.g. read by ReadHDF5Dump
+%
+% homogen interpolation given by a 3x1 vector: e.g. [21,1,101]
+%
+% abitrary interpolation on a given mesh:
+% e.g.: mesh_interp{1} = linspace(0, 1,101) * 1e-3;
+% mesh_interp{2} = linspace(0,0.5, 51) * 1e-3;
+% mesh_interp{3} = linspace(0,0.2, 21) * 1e-3;
+%
+% example:
+% [field mesh] = ReadHDF5Dump('Et.h5');
+% %interpolate on a mesh with 21x21x101 lines
+% [field_i mesh_i] = GetField_Interpolation(field, mesh, [21 21 101]);
+% or
+% [field_i mesh_i] = GetField_Interpolation(field, mesh, mesh_interp);
+%
+% %or both steps in one with the same result:
+% [field_i mesh_i] = ReadHDF5Dump('Et.h5','Interpolation', [21 21 101]);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5Dump ReadHDF5FieldData ReadHDF5Mesh
+
+if ((~iscell(lines) && ~isnumeric(lines)) || numel(lines)~=3)
+ error('openEMS:GetField_Interpolation: numLines for interpolation must be a vector...');
+end
+
+x = mesh.lines{1};
+y = mesh.lines{2};
+z = mesh.lines{3};
+
+if (isnumeric(lines))
+ if (lines(1)==0)
+ x_i = x;
+ else
+ x_i = linspace(x(1),x(end),lines(1));
+ end
+ if (lines(2)==0)
+ y_i = y;
+ else
+ y_i = linspace(y(1),y(end),lines(2));
+ end
+ if (lines(3)==0)
+ z_i = z;
+ else
+ z_i = linspace(z(1),z(end),lines(3));
+ end
+else
+ if isempty(lines{1})
+ x_i = x;
+ else
+ x_i = lines{1};
+ end
+ if isempty(lines{2})
+ y_i = y;
+ else
+ y_i = lines{2};
+ end
+ if isempty(lines{3})
+ z_i = z;
+ else
+ z_i = lines{3};
+ end
+end
+
+field_i = field;
+mesh_i = mesh;
+mesh_i.lines{1} = x_i;
+mesh_i.lines{2} = y_i;
+mesh_i.lines{3} = z_i;
+
+% clear or create empty original indices list, since such do not make any
+% sense with interpolated field values
+mesh_i.original_indices = {};
+
+if (isfield(field,'TD'))
+ field_i.TD = interpolate_fields(field.TD,x,y,z, x_i, y_i, z_i);
+ field_i.TD.time = field.TD.time;
+ field_i.TD.names= field.TD.names;
+end
+
+if (isfield(field,'FD'))
+ field_i.FD = interpolate_fields(field.FD,x,y,z, x_i, y_i, z_i);
+ field_i.FD.frequency = field.FD.frequency;
+ field_i.FD.DataType = field.FD.DataType;
+end
+
+return
+
+function field_i = interpolate_fields(field, x,y,z, x_i, y_i, z_i)
+
+% matlab cannot handle 3D data to be 2D data, workaround for these cases
+if (numel(x)==1)
+ [Y Z] = ndgrid(y,z);
+ [Y_I Z_I] = ndgrid(y_i,z_i);
+ for n=1:numel(field.values)
+ field_i.values{n}(1,:,:,1) = interpn(Y,Z,squeeze(field.values{n}(1,:,:,1)),Y_I,Z_I);
+ if (size(field.values{n},4)>1)
+ field_i.values{n}(1,:,:,2) = interpn(Y,Z,squeeze(field.values{n}(1,:,:,2)),Y_I,Z_I);
+ field_i.values{n}(1,:,:,3) = interpn(Y,Z,squeeze(field.values{n}(1,:,:,3)),Y_I,Z_I);
+ end
+ end
+ return;
+end
+
+if (numel(y)==1)
+ [X Z] = ndgrid(x,z);
+ [X_I Z_I] = ndgrid(x_i,z_i);
+ for n=1:numel(field.values)
+ field_i.values{n}(:,1,:,1) = interpn(X,Z,squeeze(field.values{n}(:,1,:,1)),X_I,Z_I);
+ if (size(field.values{n},4)>1)
+ field_i.values{n}(:,1,:,2) = interpn(X,Z,squeeze(field.values{n}(:,1,:,2)),X_I,Z_I);
+ field_i.values{n}(:,1,:,3) = interpn(X,Z,squeeze(field.values{n}(:,1,:,3)),X_I,Z_I);
+ end
+ end
+ return;
+end
+
+if (numel(z)==1)
+ [X Y] = ndgrid(x,y);
+ [X_I Y_I] = ndgrid(x_i,y_i);
+ for n=1:numel(field.values)
+ field_i.values{n}(:,:,1,1) = interpn(X,Y,squeeze(field.values{n}(:,:,1,1)),X_I,Y_I);
+ if (size(field.values{n},4)>1)
+ field_i.values{n}(:,:,1,2) = interpn(X,Y,squeeze(field.values{n}(:,:,1,2)),X_I,Y_I);
+ field_i.values{n}(:,:,1,3) = interpn(X,Y,squeeze(field.values{n}(:,:,1,3)),X_I,Y_I);
+ end
+ end
+ return;
+end
+
+
+%real 3D case
+[X Y Z] = ndgrid(x,y,z);
+[X_I Y_I Z_I] = ndgrid(x_i,y_i,z_i);
+for n=1:numel(field.values)
+ field_i.values{n}(:,:,:,1) = interpn(X,Y,Z,field.values{n}(:,:,:,1),X_I,Y_I,Z_I);
+ if (size(field.values{n},4)>1)
+ field_i.values{n}(:,:,:,2) = interpn(X,Y,Z,field.values{n}(:,:,:,2),X_I,Y_I,Z_I);
+ field_i.values{n}(:,:,:,3) = interpn(X,Y,Z,field.values{n}(:,:,:,3),X_I,Y_I,Z_I);
+ end
+end
diff --git a/openEMS/matlab/GetField_Range.m b/openEMS/matlab/GetField_Range.m
new file mode 100644
index 0000000..8d489b9
--- /dev/null
+++ b/openEMS/matlab/GetField_Range.m
@@ -0,0 +1,71 @@
+function [field_i mesh_i] = GetField_Range(field, mesh, range)
+% [field_i mesh_i] = GetField_Range(field, mesh, range)
+%
+% Get a field dump subset within a given mesh range
+%
+% example:
+% % specify a mesh range
+% range{1} = [0 150] * 1e-3; % x in range 0..150mm
+% range{2} = [0]; % only one line close to y==0
+% range{3} = []; % no range restriction
+%
+% % read hdf data
+% [field mesh] = ReadHDF5Dump('Et.h5');
+% % extract a ranged subset
+% [field_i mesh_i] = GetField_Range(field, mesh, range);
+%
+% %or both steps in one with the same result:
+% [field_i mesh_i] = ReadHDF5Dump('Et.h5','Range', range);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5Dump ReadHDF5FieldData ReadHDF5Mesh
+
+mesh_i = mesh;
+for n=1:3
+ if (numel(range{n})==0)
+ ind_range{n} = [];
+
+ ind_range{n} = 1:numel( mesh.lines{n});
+
+ elseif (numel(range{n})==1)
+ ind_range{n} = find( mesh.lines{n}>=range{n}(1) , 1);
+
+ if (isempty(ind_range{n}))
+ ind_range{n} = find( mesh.lines{n}>=range{n}(1) , 1, 'first');
+ end
+ if (isempty(ind_range{n}))
+ ind_range{n} = find( mesh.lines{n}<=range{n}(2) , 1, 'last');
+ end
+
+ else
+ ind_range{n} = find( mesh.lines{n}>=range{n}(1) & mesh.lines{n}<=range{n}(2));
+ end
+
+ mesh_i.lines{n} = mesh.lines{n}(ind_range{n});
+end
+
+% store original indices
+if (isfield(mesh_i,'original_indices'))
+ for n=1:3
+ mesh_i.original_indices{n} = mesh_i.original_indices{n}(ind_range{n});
+ end
+else
+ mesh_i.original_indices = ind_range;
+end
+
+field_i = field;
+
+if (isfield(field,'FD'))
+ for n=1:numel(field.FD.values)
+ field_i.FD.values{n} = field.FD.values{n}(ind_range{1},ind_range{2},ind_range{3},:);
+ end
+end
+
+if (isfield(field,'TD'))
+ for n=1:numel(field.TD.values)
+ field_i.TD.values{n} = field.TD.values{n}(ind_range{1},ind_range{2},ind_range{3},:);
+ end
+end
diff --git a/openEMS/matlab/GetField_SubSampling.m b/openEMS/matlab/GetField_SubSampling.m
new file mode 100644
index 0000000..9c792e0
--- /dev/null
+++ b/openEMS/matlab/GetField_SubSampling.m
@@ -0,0 +1,63 @@
+function [field_i mesh_i] = GetField_SubSampling(field, mesh, subsampling, varargin)
+% [field_i mesh_i] = GetField_SubSampling(field, mesh, subsampling, varargin)
+%
+% Get a sub-sampled field, e.g. read by ReadHDF5Dump
+%
+% sub-sampling e.g. skipping every second line in x/r direction: [2 1 1]
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5Dump ReadHDF5FieldData ReadHDF5Mesh
+
+if (~isnumeric(subsampling) || numel(subsampling)~=3)
+ error('openEMS:GetField_Interpolation: numLines for interpolation must be a vector...');
+end
+
+x = mesh.lines{1};
+y = mesh.lines{2};
+z = mesh.lines{3};
+
+ss_idx{1} = 1:subsampling(1):numel(x);
+ss_idx{2} = 1:subsampling(2):numel(y);
+ss_idx{3} = 1:subsampling(3):numel(z);
+
+x_i = x(ss_idx{1});
+y_i = y(ss_idx{2});
+z_i = z(ss_idx{3});
+
+field_i = field;
+mesh_i = mesh;
+mesh_i.lines{1} = x_i;
+mesh_i.lines{2} = y_i;
+mesh_i.lines{3} = z_i;
+
+% store original indices
+if (isfield(mesh_i,'original_indices'))
+ for n=1:3
+ mesh_i.original_indices{n} = mesh_i.original_indices{n}(ss_idx{n});
+ end
+else
+ mesh_i.original_indices = ss_idx;
+end
+
+if (isfield(field,'TD'))
+ field_i.TD = subsample_fields(field.TD,ss_idx);
+ field_i.TD.time = field.TD.time;
+ field_i.TD.names= field.TD.names;
+end
+
+if (isfield(field,'FD'))
+ field_i.FD = subsample_fields(field.FD,ss_idx);
+ field_i.FD.frequency = field.FD.frequency;
+ field_i.FD.DataType = field.FD.DataType;
+end
+
+return
+
+function field_i = subsample_fields(field, ss_idx)
+
+for n=1:numel(field.values)
+ field_i.values{n} = field.values{n}(ss_idx{1},ss_idx{2},ss_idx{3},:);
+end
diff --git a/openEMS/matlab/GetField_TD2FD.m b/openEMS/matlab/GetField_TD2FD.m
new file mode 100644
index 0000000..014c6d6
--- /dev/null
+++ b/openEMS/matlab/GetField_TD2FD.m
@@ -0,0 +1,48 @@
+function field = GetField_TD2FD(field, freq)
+% function field = GetField_TD2FD(field, freq)
+%
+% Transforms time-domain field data into the frequency domain
+% Autocorrects the half-timestep offset of the H-field
+%
+% example:
+% freq = linspace(0,1e9,100); %target frequency vector (Hz)
+% field = ReadHDF5FieldData('tmp/Ht.h5');
+% field_FD = GetField_TD2FD(field, freq);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5FieldData
+
+if (~isfield(field,'TD'))
+ warning('openEMS:GetField_TD2FD','field has no time domain data... skipping FD transformation...');
+ return
+end
+
+t = field.TD.time;
+dt = t(2)-t(1);
+
+clear field.FD
+
+field.FD.frequency = freq;
+
+for nf = 1:numel(freq)
+ field.FD.values{nf} = 0;
+end
+
+numTS = numel(field.TD.values);
+
+for n=1:numTS
+ for nf = 1:numel(freq)
+ f = freq(nf);
+ field.FD.values{nf} = field.FD.values{nf} + field.TD.values{n}.*exp(-1i*2*pi*f*t(n)) * 2 * dt;
+ % t(n) is absolute time and therefore the half-timestep offset of
+ % the H-field is automatically compensated
+ % openEMS output: E-fields start at t=0
+ % openEMS output: H-fields start at t=delta_t/2
+ end
+end
+
+field.FD.DataType=1;
+
diff --git a/openEMS/matlab/InitCylindricalFDTD.m b/openEMS/matlab/InitCylindricalFDTD.m
new file mode 100644
index 0000000..9da649f
--- /dev/null
+++ b/openEMS/matlab/InitCylindricalFDTD.m
@@ -0,0 +1,21 @@
+function FDTD = InitCylindricalFDTD(NrTS, endCrit, varargin)
+% function FDTD = InitCylindricalFDTD(NrTS, endCrit, varargin)
+%
+% see also InitFDTD
+%
+% e.g FDTD = InitCylindricalFDTD(5e5,1e-6,'OverSampling',10)
+%
+% WARNING: This function is depreciated, use InitFDTD with 'CoordSystem',1
+% e.g.: InitFDTD(5e5,1e-6,'OverSampling',10, 'CoordSystem',1)
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+warning('InitCylindricalFDTD: This function is depreciated, use InitFDTD with ''CoordSystem'',1');
+
+FDTD = InitFDTD(NrTS, endCrit, varargin{:});
+
+FDTD.ATTRIBUTE.CylinderCoords=1;
+
+
diff --git a/openEMS/matlab/InitFDTD.m b/openEMS/matlab/InitFDTD.m
new file mode 100644
index 0000000..dba5120
--- /dev/null
+++ b/openEMS/matlab/InitFDTD.m
@@ -0,0 +1,64 @@
+function FDTD = InitFDTD(varargin)
+% function FDTD = InitFDTD(varargin)
+%
+% Inititalize the FDTD data-structure.
+%
+% optional field arguments for usage with openEMS:
+% NrTS: max. number of timesteps to simulate (e.g. default=1e9)
+% EndCriteria: end criteria, e.g. 1e-5, simulations stops if energy has
+% decayed by this value (<1e-4 is recommended, default=1e-5)
+% MaxTime: max. real time in seconds to simulate
+% OverSampling: nyquist oversampling of time domain dumps
+% CoordSystem: choose coordinate system (0 Cartesian, 1 Cylindrical)
+% MultiGrid: define a cylindrical sub-grid radius
+% TimeStep: force to use a given timestep (dangerous!)
+% TimeStepFactor: reduce the timestep by a given factor (>0 to <=1)
+% TimeStepMethod: 1 or 3 chose timestep method (1=CFL, 3=Rennigs (default))
+% CellConstantMaterial: set to 1 to assume a material is constant inside
+% a cell (material probing in cell center)
+%
+% examples:
+% %default init with 1e9 max. timesteps and -50dB end-criteria
+% FDTD = InitFDTD();
+%
+% %init with 1e6 max. timesteps and -60dB end-criteria
+% FDTD = InitFDTD('NrTS', 1e6, 'EndCriteria', 1e-6);
+%
+% %cylindrical FDTD simulation
+% FDTD = InitFDTD('CoordSystem', 1);
+%
+% See also InitCSX
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig (c) 2010-2013
+
+% default values
+NrTS = 1e9;
+endCrit = 1e-5;
+
+% legacy support
+if ((nargin==1) && (isnumeric(varargin{1})))
+ NrTS = varargin{1};
+ warning('openEMS:InitFDTD',['Syntax for InitFDTD has changed, use: "InitFDTD(''NrTS'', ' num2str(NrTS) ')" instead! Legacy support enabled.']);
+elseif ((nargin>1) && (isnumeric(varargin{1})) && (isnumeric(varargin{2})))
+ NrTS = varargin{1};
+ endCrit = varargin{2};
+ varargin(1:2) = [];
+ warning('openEMS:InitFDTD',['Syntax for InitFDTD has changed, use: "InitFDTD(''NrTS'', ' num2str(NrTS) ', ''EndCriteria'', ' num2str(endCrit) ')" instead! Legacy support enabled.']);
+end
+
+for n=1:numel(varargin)/2
+ if strcmpi(varargin{2*n-1},'CoordSystem')==1
+ FDTD.ATTRIBUTE.CylinderCoords=varargin{2*n}==1;
+ elseif strcmpi(varargin{2*n-1},'NrTS')==1
+ NrTS=varargin{2*n};
+ elseif strcmpi(varargin{2*n-1},'EndCriteria')==1
+ endCrit=varargin{2*n};
+ else
+ FDTD.ATTRIBUTE.(varargin{2*n-1})=varargin{2*n};
+ end
+end
+
+FDTD.ATTRIBUTE.NumberOfTimesteps=NrTS;
+FDTD.ATTRIBUTE.endCriteria=endCrit;
diff --git a/openEMS/matlab/InitQueue.m b/openEMS/matlab/InitQueue.m
new file mode 100644
index 0000000..feec5cc
--- /dev/null
+++ b/openEMS/matlab/InitQueue.m
@@ -0,0 +1,90 @@
+function [queue] = InitQueue(varargin)
+% function [queue] = InitQueue(varargin)
+%
+% Use this function to initialize a queue to run one or more matlab scripts
+% in parallel.
+% This can be used to efficiently run an openEMS parameter sweep in parallel
+% on multiple remote machines.
+%
+% Options:
+% DependPath: Add multiple paths, your script may depend on
+% UseOctave: Enable/Disable octave usage
+% MaxThreads: max. number of parallel executions
+%
+% Note:
+% - Currently only Linux/Unix is supported
+% - By default Octave is used to spawn parallel functions (saves
+% licenses), but this can be changed by:
+% [queue] = InitQueue('UseOctave', 0);
+% You may need to change this, if your script is not octave compatible
+% - To efficiently run openEMS in parallel, you need to run it on several
+% machines using a SSH.host_list setting --> See also RunOpenEMS
+%
+% Example:
+% %serial version:
+% for n=1:10
+% % manipulate parameter etc.
+% [result1(n) result2(n)] = Parallel_Func_Name(param1, param2);
+% end
+%
+% %parallel version:
+% queue = InitQueue('DependPath',{'/opt/openEMS/CSXCAD/matlab', ...
+% '/opt/openEMS/openEMS/matlab'});
+% for n=1:10
+% % manipulate parameter etc.
+% queue = Add2Queue(queue, 'Parallel_Func_Name', {param1, param2});
+% end
+%
+% % wait for all to finish
+% [queue] = FinishQueue(queue);
+%
+% % retrieve result
+% for n=1:numel(stub_sweep)
+% [result1(n) result2(n)] = ResultsQueue(queue,n);
+% end
+%
+% See also: Add2Queue, FinishQueue, ResultsQueue, RunOpenEMS,
+% RunOpenEMS_Parallel, FindFreeSSH
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if ~isunix
+ error 'your OS is not supported (Unix only)'
+end
+
+queue.use_octave = exist('OCTAVE_VERSION','builtin') ~= 0;
+
+queue.verbose = 1;
+
+queue.maxThreads = Inf;
+
+% add current path
+queue.DependPath = ['addpath(''' pwd ''');'];
+
+for n=1:2:nargin
+ if strcmp(varargin{n},'DependPath');
+ for m=1:numel(varargin{n+1})
+ queue.DependPath = [queue.DependPath 'addpath(''' varargin{n+1}{m} ''');'];
+ end
+ end
+ if strcmp(varargin{n},'UseOctave');
+ queue.use_octave = varargin{n+1};
+ end
+ if strcmp(varargin{n},'MaxThreads');
+ queue.maxThreads = varargin{n+1};
+ end
+end
+
+
+% set binaries and options
+if (queue.use_octave)
+ queue.bin = ['export LD_LIBRARY_PATH=""; octave'];
+ queue.bin_options = [' --silent --eval'];
+else
+ queue.bin = [matlabroot '/bin/matlab'];
+ queue.bin_options = [' -nodesktop -nosplash -r'];
+end
+
+queue.jobs_finished = [];
diff --git a/openEMS/matlab/PlotHDF5FieldData.m b/openEMS/matlab/PlotHDF5FieldData.m
new file mode 100644
index 0000000..9aaf899
--- /dev/null
+++ b/openEMS/matlab/PlotHDF5FieldData.m
@@ -0,0 +1,94 @@
+function PlotHDF5FieldData(file, PlotArgs)
+% function PlotHDF5FieldData(file, PlotArgs)
+%
+% e.g.
+% PlotArgs.slice = {0 [10 20] 0};
+% PlotArgs.pauseTime=0.01;
+% PlotArgs.component=2;
+% PlotArgs.Limit = 'auto';
+%
+% PlotHDF5FieldData('tmp/Et.h5',PlotArgs)
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+component = PlotArgs.component;
+
+if (isfield(PlotArgs,'pauseTime'))
+ pauseT = PlotArgs.pauseTime;
+else
+ pauseT = 0.01;
+end
+
+mesh = ReadHDF5Mesh(file);
+fields = ReadHDF5FieldData(file);
+
+if (mesh.type==0)
+ % cartesian mesh
+ [X Y Z] = meshgrid(mesh.lines{1},mesh.lines{2},mesh.lines{3});
+ for n=1:numel(fields.TD.values)
+ % since Matlab 7.1SP3 the field needs to be reordered
+ fields.TD.values{n} = permute(fields.TD.values{n},[2 1 3 4]); % reorder: y,x,z (or y,x)
+ end
+else
+ disp(['PlotHDF5FieldData:: Error: unknown mesh type ' num2str(mesh.type)]);
+end
+
+max_amp = 0;
+
+if (component>0)
+ for n=1:numel(fields.TD.values)
+ Field{n} = fields.TD.values{n}(:,:,:,component);
+ end
+else
+ for n=1:numel(fields.TD.values)
+ fx = fields.TD.values{n}(:,:,:,1);
+ fy = fields.TD.values{n}(:,:,:,2);
+ fz = fields.TD.values{n}(:,:,:,3);
+ Field{n} = sqrt(fx.^2 + fy.^2 + fz.^2);
+ end
+end
+
+for n=1:numel(Field)
+ amp = max(max(max(abs(Field{n}))));
+ if (amp>max_amp)
+ max_amp = amp;
+ end
+end
+
+if (max_amp==0)
+ disp('max found amplitude was 0 --> nothing to plot');
+ return
+end
+
+for n=1:numel(Field)
+ if size(Field{n},3) > 1
+ % Field is a volume
+ hsurfaces = slice(X,Y,Z, Field{n} , PlotArgs.slice{:});
+ set(hsurfaces,'FaceColor','interp','EdgeColor','none');
+ else
+ % Field is already a 2D cut
+ pcolor(X,Y,Field{n});
+ shading( 'interp' );
+ xlabel( 'x' );
+ ylabel( 'y' );
+ end
+ title(fields.TD.names{n});
+ %view(3)
+ axis equal
+ if (isfield(PlotArgs,'Limit'))
+ if ~ischar(PlotArgs.Limit)
+ caxis(PlotArgs.Limit);
+ elseif strcmp(PlotArgs.Limit,'auto')
+ if (component>0)
+ caxis([-max_amp,max_amp]);
+ else
+ caxis([0,max_amp]);
+ end
+ end
+ end
+
+ drawnow
+ pause(pauseT)
+end
diff --git a/openEMS/matlab/ReadHDF5Attribute.m b/openEMS/matlab/ReadHDF5Attribute.m
new file mode 100644
index 0000000..3361ee9
--- /dev/null
+++ b/openEMS/matlab/ReadHDF5Attribute.m
@@ -0,0 +1,33 @@
+function attr = ReadHDF5Attribute(file, groupname, attr_name)
+% attr = ReadHDF5Attribute(file, groupname, attr_name)
+%
+% internal function for openEMS to read hdf5 attributes
+%
+% See also: ReadHDF5ComplexData
+%
+% openEMS Matlab/Octave interface
+% -----------------------
+% author: Thorsten Liebig, 2012
+
+
+if isOctave
+ if (exist('h5readatt_octave')==0)
+ warning('openEMS:ReadHDF5Attribute','function "h5readatt_octave" not found, trying to run "setup"');
+ try
+ setup
+ catch
+ error('openEMS:ReadHDF5Attribute','running "setup" failed...');
+ end
+ end
+ attr = double(h5readatt_octave(file,groupname,attr_name));
+else
+ %check for different matlab versions
+ if verLessThan('matlab','7.9')
+ attr = double(hdf5read(file,[groupname '/' attr_name]));
+ elseif verLessThan('matlab','7.12')
+ attr = double(hdf5read(file,groupname,attr_name));
+ else
+ attr = double(h5readatt(file,groupname,attr_name));
+ end
+
+end \ No newline at end of file
diff --git a/openEMS/matlab/ReadHDF5Dump.m b/openEMS/matlab/ReadHDF5Dump.m
new file mode 100644
index 0000000..9fc8c43
--- /dev/null
+++ b/openEMS/matlab/ReadHDF5Dump.m
@@ -0,0 +1,92 @@
+function [field mesh] = ReadHDF5Dump(file, varargin)
+%[field mesh] = ReadHDF5Dump(file, varargin)
+%
+% Read a hdf5 field dump, including an interpolation and frequency domain
+% transformation.
+%
+% For more information about the output, refer to the help of
+% ReadHDF5Mesh and ReadHDF5FieldData
+%
+% possible arguments:
+% 'Range' see GetField_Range
+% 'Interpolation' see GetField_Interpolation
+% 'SubSampling' see GetField_SubSampling
+% 'Frequency' see GetField_TD2FD
+% 'CloseAlpha': 0 (default) / 1
+%
+% example:
+% [field mesh] = ReadHDF5Dump('Et.h5');
+% or
+% [field mesh] = ReadHDF5Dump('Et.h5','Range',{[0 100],[-20 20],[50 90]});
+% or
+% [field mesh] = ReadHDF5Dump('Et.h5','Interpolation',[21 1 101],'Frequency',300e6);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5Mesh ReadHDF5FieldData GetField_Interpolation GetField_SubSampling
+% GetField_TD2FD GetField_Range
+
+field = ReadHDF5FieldData(file);
+mesh = ReadHDF5Mesh(file);
+
+if (nargin<2)
+ return
+end
+
+% evaluate arguments in a specific order
+for n=1:2:(nargin-1)
+ if (strcmp(varargin{n},'Range')==1);
+ [field mesh] = GetField_Range(field, mesh, varargin{n+1});
+ end
+end
+
+for n=1:2:(nargin-1)
+ if (strcmp(varargin{n},'SubSampling')==1);
+ [field mesh] = GetField_SubSampling(field,mesh,varargin{n+1});
+ end
+end
+
+for n=1:2:(nargin-1)
+ if (strcmp(varargin{n},'Interpolation')==1);
+ [field mesh] = GetField_Interpolation(field,mesh,varargin{n+1});
+ end
+end
+
+for n=1:2:(nargin-1)
+ if (strcmp(varargin{n},'Frequency')==1);
+ field = GetField_TD2FD(field,varargin{n+1});
+ end
+end
+
+for n=1:2:(nargin-1)
+ if (strcmp(varargin{n},'CloseAlpha')==1);
+ if ((varargin{n+1}==1) && (mesh.type==1) && (range(mesh.lines{2})<2*pi))
+ mesh.lines{2}(end+1)=mesh.lines{2}(1)+2*pi;
+ if (isfield(field,'TD'))
+ for n = 1:numel(field.TD.values)
+ field.TD.values{n}(:,end+1,:,:) = field.TD.values{n}(:,1,:,:);
+ end
+ end
+ if (isfield(field,'FD'))
+ for n = 1:numel(field.FD.values)
+ field.FD.values{n}(:,end+1,:,:) = field.FD.values{n}(:,1,:,:);
+ end
+ end
+ if (isfield(mesh,'original_indices'))
+ if (~isempty(mesh.original_indices))
+ mesh.original_indices{2} = [mesh.original_indices{2} 1];
+ end
+ else
+ mesh.original_indices = {1:numel(mesh.lines{1}),[1:numel(mesh.lines{2}) 1],[1:numel(mesh.lines{3})]};
+ end
+ end
+ end
+end
+
+end
+
+function rng = range(x)
+ rng = max(x)-min(x);
+end \ No newline at end of file
diff --git a/openEMS/matlab/ReadHDF5FieldData.m b/openEMS/matlab/ReadHDF5FieldData.m
new file mode 100644
index 0000000..c45f9ad
--- /dev/null
+++ b/openEMS/matlab/ReadHDF5FieldData.m
@@ -0,0 +1,119 @@
+function hdf_fielddata = ReadHDF5FieldData(file)
+% function hdf_fielddata = ReadHDF5FieldData(file)
+%
+% returns:
+% % time domain data (if exist)
+% hdf_fielddata.TD.time
+% hdf_fielddata.TD.names
+% hdf_fielddata.TD.values
+% hdf_fielddata.TD.DataType (0 --> real value data)
+%
+% % frequency domain data (if exist)
+% hdf_fielddata.FD.frequency
+% hdf_fielddata.FD.values
+% hdf_fielddata.FD.DataType (0 / 1 --> real / complex value data)
+%
+% example: values of timestep 12:
+% hdf_fielddata.TD.values{12}: array (x,y,z,polarization)
+%
+% plot z-field component along y-direction for timestep 12:
+% plot( hdf_fielddata.TD.values{12}(1,:,1,3) )
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5Mesh ReadHDF5Dump
+
+if isOctave
+ hdf_fielddata = ReadHDF5FieldData_octave(file);
+ return
+end
+
+info = hdf5info(file);
+TD.names = {};
+hdf_fielddata = [];
+
+for n=1:numel(info.GroupHierarchy.Groups)
+ if strcmp(info.GroupHierarchy.Groups(n).Name,'/FieldData')
+ %found /FieldData, look for either TD or FD data
+ for nGroup=1:numel(info.GroupHierarchy.Groups(n).Groups)
+ %search and read TD data
+ if strcmp(info.GroupHierarchy.Groups(n).Groups(nGroup).Name,'/FieldData/TD')
+ for m=1:numel(info.GroupHierarchy.Groups(n).Groups(nGroup).Datasets)
+ TD.names{m} = info.GroupHierarchy.Groups(n).Groups(nGroup).Datasets(m).Name;
+ for a = 1:numel(info.GroupHierarchy.Groups(n).Groups(nGroup).Datasets(m).Attributes)
+ str = regexp(info.GroupHierarchy.Groups(n).Groups(nGroup).Datasets(m).Attributes(a).Name,'\w/*\w*','match');
+ TD.(str{end})(m) = double(info.GroupHierarchy.Groups(n).Groups(nGroup).Datasets(m).Attributes(a).Value);
+ end
+ end
+ end
+ end
+
+ end
+end
+
+if (numel(TD.names)>0)
+ hdf_fielddata.TD=TD;
+ hdf_fielddata.TD.DataType = 0; %real value data
+ for n=1:numel(hdf_fielddata.TD.names)
+ hdf_fielddata.TD.values{n} = double(hdf5read(file,hdf_fielddata.TD.names{n}));
+ end
+end
+
+% extract FD data
+try
+ hdf_fielddata.FD.frequency = ReadHDF5Attribute(file,'/FieldData/FD','frequency');
+catch err
+% disp(err)
+ return
+end
+
+for n=1:numel(hdf_fielddata.FD.frequency)
+ try
+ hdf_fielddata.FD.values{n} = double(hdf5read(file,['/FieldData/FD/f' int2str(n-1) '_real']) + 1i*hdf5read(file,['/FieldData/FD/f' int2str(n-1) '_imag']));
+ hdf_fielddata.FD.DataType = 1; %complex value data
+ catch
+ try
+ hdf_fielddata.FD.values{n} = double(hdf5read(file,['/FieldData/FD/f' int2str(n-1)]));
+ hdf_fielddata.FD.DataType = 0; %real value data
+ catch
+ error('openEMS:ReadHDF5FieldData','FD data invalid...')
+ end
+ end
+end
+
+function hdf_fielddata = ReadHDF5FieldData_octave(file)
+hdf = load( '-hdf5', file );
+if ~isfield(hdf,'FieldData')
+ error('no field data found')
+end
+if isfield(hdf.FieldData,'TD')
+ %read TD data
+ hdf_fielddata_names = fieldnames(hdf.FieldData.TD);
+ for n=1:numel(hdf_fielddata_names)
+ hdf_fielddata.TD.values{n} = hdf.FieldData.TD.(hdf_fielddata_names{n});
+ hdf_fielddata.TD.names{n} = ['/FieldData/TD/' hdf_fielddata_names{n}(2:end)];
+ hdf_fielddata.TD.time(n) = ReadHDF5Attribute(file, hdf_fielddata.TD.names{n},'time');
+ end
+ hdf_fielddata.TD.DataType = 0; %real value data
+end
+if isfield(hdf.FieldData,'FD')
+ %read FD data
+ hdf_fielddata.FD.frequency = ReadHDF5Attribute(file,'/FieldData/FD/','frequency');
+ try %try reading complex data
+ for n=1:numel(hdf_fielddata.FD.frequency)
+ hdf_fielddata.FD.values{n} = double(hdf.FieldData.FD.(['f' int2str(n-1) '_real']) +1i*hdf.FieldData.FD.(['f' int2str(n-1) '_imag']) );
+ end
+ hdf_fielddata.FD.DataType = 1; %complex value data
+ catch
+ try %try reading real value data
+ for n=1:numel(hdf_fielddata.FD.frequency)
+ hdf_fielddata.FD.values{n} = double(hdf.FieldData.FD.(['f' int2str(n-1)]));
+ end
+ hdf_fielddata.FD.DataType = 0; %real value data
+ catch
+ error('openEMS:ReadHDF5FieldData','FD data invalid...')
+ end
+ end
+end
diff --git a/openEMS/matlab/ReadHDF5Mesh.m b/openEMS/matlab/ReadHDF5Mesh.m
new file mode 100644
index 0000000..b276391
--- /dev/null
+++ b/openEMS/matlab/ReadHDF5Mesh.m
@@ -0,0 +1,80 @@
+function hdf_mesh = ReadHDF5Mesh(file)
+% function hdf_mesh = ReadHDF5Mesh(file)
+%
+% Get the raw mesh data stored in the hdf5 dump file created by openEMS
+%
+% returns:
+% hdf_mesh.type (0-> cartesian, 1-> cylindrical mesh type)
+% hdf_mesh.names (e.g. 'Mesh/y')
+% hdf_mesh.lines (e.g. [0,1,2,3,4])
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also ReadHDF5FieldData
+
+isOctave = exist('OCTAVE_VERSION','builtin') ~= 0;
+if isOctave
+ hdf_mesh = ReadHDF5Mesh_octave(file);
+ return
+end
+
+info = hdf5info(file);
+
+for n=1:numel(info.GroupHierarchy.Groups)
+ if strcmp(info.GroupHierarchy.Groups(n).Name,'/Mesh')
+ for m=1:numel(info.GroupHierarchy.Groups(n).Datasets)
+ names{m} = info.GroupHierarchy.Groups(n).Datasets(m).Name;
+ end
+ end
+end
+
+hdf_mesh.names = names;
+for n=1:numel(names)
+ hdf_mesh.lines{n} = double(hdf5read(file,names{n}));
+end
+
+if (strcmp(names{1},'/Mesh/alpha'))
+ % alpha and rho are in the wrong order, flip to have rho, alpha, z
+ hdf_mesh.names(1:2) = fliplr(hdf_mesh.names(1:2));
+ hdf_mesh.lines(1:2) = fliplr(hdf_mesh.lines(1:2));
+ hdf_mesh.type=1;
+ return
+end
+if (strcmp(names{1},'/Mesh/phi'))
+ % reorder coordinates
+ hdf_mesh.names = hdf_mesh.names([2 3 1]);
+ hdf_mesh.lines = hdf_mesh.lines([2 3 1]);
+ hdf_mesh.type=2;
+ return
+end
+
+hdf_mesh.type=0;
+
+
+function hdf_mesh = ReadHDF5Mesh_octave(file)
+hdf = load( '-hdf5', file );
+hdf_mesh.names = fieldnames(hdf.Mesh);
+hdf_mesh.type = 0; % cartesian mesh
+for n=1:numel(hdf_mesh.names)
+ hdf_mesh.lines{n} = hdf.Mesh.(hdf_mesh.names{n});
+ hdf_mesh.names{n} = ['/Mesh/' hdf_mesh.names{n}];
+ if strcmp(hdf_mesh.names{n},'/Mesh/alpha')
+ hdf_mesh.type = 1; % cylindrical mesh
+ end
+ if strcmp(hdf_mesh.names{n},'/Mesh/phi')
+ hdf_mesh.type = 2; % cylindrical mesh
+ end
+end
+
+if (hdf_mesh.type==1)
+ % alpha and rho are in the wrong order, flip to have rho, alpha, z
+ hdf_mesh.names(1:2) = fliplr(hdf_mesh.names(1:2));
+ hdf_mesh.lines(1:2) = fliplr(hdf_mesh.lines(1:2));
+end
+if (hdf_mesh.type==2)
+ % alpha and rho are in the wrong order, flip to have rho, alpha, z
+ hdf_mesh.names = hdf_mesh.names([2 3 1]);
+ hdf_mesh.lines = hdf_mesh.lines([2 3 1]);
+end
diff --git a/openEMS/matlab/ReadUI.m b/openEMS/matlab/ReadUI.m
new file mode 100644
index 0000000..23fe342
--- /dev/null
+++ b/openEMS/matlab/ReadUI.m
@@ -0,0 +1,107 @@
+function UI = ReadUI(files, path, freq, varargin)
+% function UI = ReadUI(files, path, freq, varargin)
+%
+% read current and voltages from multiple files found in path
+%
+% returns voltages/currents in time and frequency-domain
+%
+% remarks on the frequency-domain:
+% - all signals are assumed to start at t=0
+% - currents that e.g. start at t = +delta_t/2 will be phase shifted by
+% exp(-j*w*t(1))
+%
+% optional parameter:
+% freq: frequency-domain values will be calculated according to 'freq'
+% if 'freq' is not given, a (zero padded) FFT will be used
+%
+% optional key,value pairs:
+% 'AR' : auto-regressive model to improve FD accuracy
+% values: order to use within an AR model or 'auto'
+%
+% % examples:
+% U = ReadUI({'ut1_1','ut1_2'},'tmp' );
+% I = ReadUI('it1' ,'tmp',[0.5e9 1e9 1.5e9]);
+%
+% % using the auto-regressive model
+% U = ReadUI('port_ut1' , 'tmp', 'AR', 'auto');
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+%
+% See also DFT_time2freq, AR_estimate
+
+if (nargin<2)
+ path ='';
+end
+
+AR_order = 0;
+SignalType = 'pulse';
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'AR')==1)
+ AR_order = varargin{n+1};
+ elseif strcmpi(varargin{n},'SignalType')
+ SignalType = varargin{n+1};
+ else
+ warning('CSXCAD:ReadUI', ['"' varargin{n} '" is an unknown argument']);
+ end
+end
+
+if strcmpi(SignalType,'periodic') && AR_order>0
+ error 'auto-regressive model not compatible with periodic signals'
+end
+
+if (ischar(files))
+ filenames{1}=files;
+else
+ filenames=files;
+end
+
+UI.TD = {};
+UI.FD = {};
+for n=1:numel(filenames)
+ tmp = load( fullfile(path,filenames{n}) );
+ t = tmp(:,1)';
+ val = tmp(:,2)';
+
+ UI.TD{n}.t = t;
+ UI.TD{n}.val = val;
+
+ if (numel(tmp(1,:))>2)
+ UI.TD{n}.additional = tmp(:,3:end)';
+ end
+
+ if (nargin<3) || isempty(freq)
+ if strcmpi(SignalType,'periodic')
+ warning 'ReadUI: periodic signal type not supported by FFT'
+ end
+ [UI.FD{n}.f,UI.FD{n}.val] = FFT_time2freq( t,val );
+ else
+ UI.FD{n}.f = freq;
+ if strcmpi(AR_order,'auto')
+ AR_order = 2;
+ EC = -1;
+ while 1
+ [val_ar t_ar UI.FD{n}.val EC] = AR_estimate( t, val, freq, AR_order);
+ if (EC==11)
+ AR_order = AR_order*2;
+ else
+ break;
+ end
+ end
+ if (EC~=0)
+ warning('CSXCAD:ReadUI','AR estimation failed, skipping...')
+ UI.FD{n}.val = DFT_time2freq( t, val, freq, SignalType );
+ end
+ elseif (AR_order<=0)
+ UI.FD{n}.val = DFT_time2freq( t, val, freq, SignalType );
+ else
+ [val_ar t_ar UI.FD{n}.val EC] = AR_estimate( t, val, freq, AR_order);
+ if (EC~=0)
+ warning('CSXCAD:ReadUI','AR estimation failed, skipping...')
+ UI.FD{n}.val = DFT_time2freq( t, val, freq, SignalType );
+ end
+ end
+ end
+end
diff --git a/openEMS/matlab/ResultsQueue.m b/openEMS/matlab/ResultsQueue.m
new file mode 100644
index 0000000..cc9f745
--- /dev/null
+++ b/openEMS/matlab/ResultsQueue.m
@@ -0,0 +1,24 @@
+function [varargout] = ResultsQueue(queue, n)
+% function [varargout] = ResultsQueue(queue, n)
+%
+% Use this function to retrieve the results from a finished queue.
+%
+% For more details see: InitQueue
+%
+% See also: InitQueue, FinishQueue, Add2Queue, RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if n>numel(queue.jobs)
+ error 'ResultsQueue:job is missing'
+end
+
+if (nargout>numel(queue.jobs{n}.outargs))
+ error 'not enough job output arguments'
+end
+
+for k=1:numel(queue.jobs{n}.outargs)
+ varargout{k} = queue.jobs{n}.outargs{k};
+end
diff --git a/openEMS/matlab/RunOpenEMS.m b/openEMS/matlab/RunOpenEMS.m
new file mode 100644
index 0000000..a4947e3
--- /dev/null
+++ b/openEMS/matlab/RunOpenEMS.m
@@ -0,0 +1,186 @@
+function RunOpenEMS(Sim_Path, Sim_File, opts, Settings)
+% function RunOpenEMS(Sim_Path, Sim_File, <opts, Settings>)
+%
+% Run an openEMS simulation.
+%
+% arguments:
+% Sim_Path: specifiy the simulation folder (folder must exist!)
+% Sim_File: xml-filename to simulate, created by WriteOpenEMS
+%
+% optional arguments
+%
+% opts: list of openEMS options
+% possible options:
+% --disable-dumps Disable all field dumps for faster simulation
+% --debug-material Dump material distribution to a vtk file for debugging
+% --debug-PEC Dump metal distribution to a vtk file for debugging
+% --debug-operator Dump operator to vtk file for debugging
+% --debug-boxes Dump e.g. probe boxes to vtk file for debugging
+% --debug-CSX Write CSX geometry file to debugCSX.xml
+% --engine=<type> Choose engine type
+% --engine=fastest fastest available engine (default)
+% --engine=basic basic FDTD engine
+% --engine=sse engine using sse vector extensions
+% --engine=sse_compressed engine using compressed operator + sse vector extensions
+% --engine=MPI engine using compressed operator + sse vector extensions + MPI parallel processing
+% --engine=multithreaded engine using compressed operator + sse vector extensions + MPI + multithreading
+% --numThreads=<n> Force use n threads for multithreaded engine
+% --no-simulation only run preprocessing; do not simulate
+% --dump-statistics dump simulation statistics to 'openEMS_run_stats.txt' and 'openEMS_stats.txt'
+%
+% Additional global arguments
+% --showProbeDiscretization Show probe discretization information
+% --nativeFieldDumps Dump all fields using the native field components
+% -v,-vv,-vvv Set debug level: 1 to 3
+%
+%
+% settings: list of Matlab settings
+% possible settings:
+% Settings.LogFile = 'openEMS.log'
+% Settings.Silent = 0
+%
+% additional remote simulation settings
+% Note: ssh only on unix with working ssh client or windows with putty client
+% openEMS Linux server or Windows with cygwin necessary
+% Settings.SSH.host = '<hostname or ip>'
+% Settings.SSH.bin = '<path_to_openEMS>/openEMS.sh'
+% ssh optional:
+% Settings.SSH.host_list = {'list','of','hosts'}; %searches for a free host
+% %on Windows needed additionally
+% Settings.SSH.Putty.Path = '<path_to>\putty';
+% Settings.SSH.Putty.Key = '<path_to>\putty_private_key.ppk';
+%
+% MPI settings:
+% Settings.MPI.xxx --> help RunOpenEMS_MPI
+%
+%
+% example:
+% %create CSX and FDTD
+% WriteOpenEMS('/tmp/path_to_run_in/myfile.xml', FDTD, CSX)
+% RunOpenEMS('/tmp/path_to_run_in','myfile.xml','-v')
+%
+% See also WriteOpenEMS FindFreeSSH InitCSX InitFDTD RunOpenEMS_MPI
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if nargin < 2
+ error 'specify the Sim_Path and Sim_file to simulate'
+end
+
+if nargin < 3
+ opts = '';
+end
+
+if (nargin<4)
+ Settings = [];
+end
+
+if (isfield(Settings,'MPI') && isunix)
+ if (Settings.MPI.NrProc>1)
+ RunOpenEMS_MPI(Sim_Path, Sim_File, opts, Settings);
+ return;
+ end
+end
+
+ssh_command = 'ssh';
+scp_command = 'scp';
+scp_options = '';
+ssh_options = '';
+
+enable_ssh = 0;
+enable_ssh = isfield(Settings,'SSH') && isunix;
+
+if ~isunix
+ enable_ssh = isfield(Settings,'SSH') && isfield(Settings.SSH,'Putty');
+ if (enable_ssh)
+ ssh_command = [Settings.SSH.Putty.Path '/plink '];
+ ssh_options = [ssh_options ' -i ' Settings.SSH.Putty.Key];
+
+ scp_command = [Settings.SSH.Putty.Path '/pscp '];
+ scp_options = [scp_options ' -i ' Settings.SSH.Putty.Key];
+ end
+end
+
+savePath = pwd;
+cd(Sim_Path);
+
+if (enable_ssh)
+ scp_options = [scp_options ' -C'];
+ ssh_options = [ssh_options ' -x -C'];
+
+ % ssh options: no X forwarding; no password prompt (use pub keys!); no host checking
+ if (isunix)
+ ssh_options = [ssh_options ' -o "PasswordAuthentication no" -o "StrictHostKeyChecking no"'];
+ scp_options = [scp_options ' -o "PasswordAuthentication no" -o "StrictHostKeyChecking no"'];
+ end
+
+ if isfield(Settings.SSH,'host_list')
+ host = FindFreeSSH(Settings.SSH.host_list, Settings);
+ if ~isempty(host)
+ Settings.SSH.host = host;
+ else
+ error('openEMS:RunOpenEMS', 'unable to find host, abort openEMS');
+ end
+ end
+
+ % create a tmp working dir
+ [status, result] = system([ssh_command ' ' ssh_options ' ' Settings.SSH.host ' "mktemp -d /tmp/openEMS_XXXXXXXXXXXX"']);
+ if (status~=0)
+ disp(result);
+ error('openEMS:RunOpenEMS','mktemp failed to create tmp directory!');
+ end
+ ssh_work_path = strtrim(result); %remove tailing \n
+
+ disp(['Running remote openEMS on ' Settings.SSH.host ' at working dir: ' ssh_work_path]);
+
+ %copy openEMS all simulation files to the ssh host
+ [stat, res] = system([scp_command ' ' scp_options ' * ' Settings.SSH.host ':' ssh_work_path '/']);
+ if (stat~=0)
+ disp(res);
+ error('openEMS:RunOpenEMS','scp failed!');
+ end
+
+ %run openEMS (with log file if requested)
+ if isfield(Settings,'LogFile') && isunix
+ append_unix = [' 2>&1 | tee ' Settings.LogFile];
+ else
+ append_unix = [];
+ end
+ status = system([ssh_command ' ' ssh_options ' ' Settings.SSH.host ' "cd ' ssh_work_path ' && ' Settings.SSH.bin ' ' Sim_File ' ' opts '"' append_unix]);
+ if (status~=0)
+ disp(result);
+ error('openEMS:RunOpenEMS','ssh openEMS failed!');
+ end
+
+ disp( 'Remote simulation done... copying back results and cleaning up...' );
+
+ %copy back all results
+ [stat, res] = system([scp_command ' -r ' scp_options ' ' Settings.SSH.host ':' ssh_work_path '/* ' pwd '/']);
+ if (stat~=0);
+ disp(res);
+ error('openEMS:RunOpenEMS','scp failed!');
+ end
+
+ %cleanup
+ [stat, res] = system([ssh_command ' ' ssh_options ' ' Settings.SSH.host ' rm -r ' ssh_work_path]);
+ if (stat~=0);
+ disp(res);
+ warning('openEMS:RunOpenEMS','remote cleanup failed!');
+ end
+else
+ args = [Sim_File ' ' opts];
+ if isfield(Settings,'LogFile') && isfield(Settings,'Silent')
+ invoke_openEMS(args,Settings.LogFile,Settings.Silent);
+ elseif isfield(Settings,'LogFile')
+ invoke_openEMS(args,Settings.LogFile);
+ elseif isfield(Settings,'Silent')
+ invoke_openEMS(args,[],Settings.Silent);
+ else
+ invoke_openEMS(args);
+ end
+end
+
+cd(savePath);
+return
diff --git a/openEMS/matlab/RunOpenEMS_MPI.m b/openEMS/matlab/RunOpenEMS_MPI.m
new file mode 100644
index 0000000..495f7e5
--- /dev/null
+++ b/openEMS/matlab/RunOpenEMS_MPI.m
@@ -0,0 +1,125 @@
+function RunOpenEMS_MPI(Sim_Path, Sim_File, opts, Settings)
+% function RunOpenEMS_MPI(Sim_Path, Sim_File, NrProc, opts, Settings)
+%
+% Run an openEMS simulation with MPI support
+%
+% % mpi binary path on all nodes needed
+% Settings.MPI.Binary = '/opt/openEMS/openEMS';
+% % number of processes to run
+% Settings.MPI.NrProc = 3;
+% % define the mpi hosts :
+% Settings.MPI.Hosts = {'host1','host2','host3'};
+%
+% RunOpenEMS(Sim_Path, Sim_File, NrProc, opts, Settings)
+%
+% See also SetupMPI, WriteOpenEMS, RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if (isunix ~= 1)
+ error 'MPI version of openEMS currently only available using Linux'
+end
+
+if nargin < 4
+ error 'missing arguments: specify the Sim_Path, Sim_file, opts and Settings...'
+end
+
+NrProc = Settings.MPI.NrProc;
+
+if (NrProc<2)
+ error('openEMS:RunOpenEMS_MPI','MPI number of processes to small...');
+end
+
+if ~isfield(Settings,'MPI')
+ error('openEMS:RunOpenEMS_MPI','MPI settings not found...');
+end
+
+savePath = pwd;
+cd(Sim_Path);
+
+scp_options = '-C -o "PasswordAuthentication no" -o "StrictHostKeyChecking no"';
+ssh_options = [scp_options ' -x'];
+
+if isfield(Settings.MPI,'Hosts')
+ Remote_Nodes = Settings.MPI.Hosts;
+ HostList = '';
+ for n=1:numel(Remote_Nodes)
+ remote_name = Remote_Nodes{n};
+
+ if (n==1)
+ [status, result] = unix(['ssh ' ssh_options ' ' remote_name ' "mktemp -d /tmp/openEMS_MPI_XXXXXXXXXXXX"']);
+ if (status~=0)
+ disp(result);
+ error('openEMS:RunOpenEMS','mktemp failed to create tmp directory!');
+ end
+ work_path = strtrim(result); %remove tailing \n
+ HostList = remote_name;
+ else
+ [status, result] = unix(['ssh ' ssh_options ' ' remote_name ' "mkdir ' work_path '"']);
+ if (status~=0)
+ disp(result);
+ error('openEMS:RunOpenEMS',['mkdir failed to create tmp directory on remote ' remote_name ' !']);
+ end
+ HostList = [HostList ',' remote_name];
+ end
+
+ [stat, res] = unix(['scp ' scp_options ' * ' remote_name ':' work_path '/']);
+ if (stat~=0)
+ disp(res);
+ error('openEMS:RunOpenEMS',['scp to remote ' remote_name ' failed!']);
+ end
+ end
+end
+
+
+%run openEMS (with log file if requested)
+if isfield(Settings,'LogFile')
+ append_unix = [' 2>&1 | tee ' Settings.LogFile];
+else
+ append_unix = [];
+end
+
+if ~isfield(Settings.MPI,'GlobalArgs')
+ Settings.MPI.GlobalArgs = '';
+end
+
+if isfield(Settings.MPI,'Hosts')
+ disp(['Running remote openEMS_MPI in working dir: ' work_path]);
+ [status] = system(['mpiexec -host ' HostList ' -n ' int2str(NrProc) ' -wdir ' work_path ' ' Settings.MPI.Binary ' ' Sim_File ' ' opts ' ' append_unix]);
+else
+ disp('Running local openEMS_MPI');
+ [status] = system(['mpiexec ' Settings.MPI.GlobalArgs ' -n ' int2str(NrProc) ' ' Settings.MPI.Binary ' ' Sim_File ' ' opts ' ' append_unix]);
+end
+
+if (status~=0)
+ error('openEMS:RunOpenEMS','mpirun openEMS failed!');
+end
+
+if isfield(Settings.MPI,'Hosts')
+ disp( 'Remote simulation done... copying back results and cleaning up...' );
+
+ if (strncmp(work_path,'/tmp/',5)~=1) % savety precaution...
+ error('openEMS:RunOpenEMS','working path invalid for deletion');
+ end
+
+ for n=1:numel(Remote_Nodes)
+ remote_name = Remote_Nodes{n};
+ disp(['Copy data from remote node: ' remote_name]);
+ [stat, res] = unix(['scp -r ' scp_options ' ' remote_name ':' work_path '/* ''' pwd '''/']);
+ if (stat~=0);
+ disp(res);
+ error('openEMS:RunOpenEMS','remote scp failed!');
+ end
+
+ %cleanup
+ [stat, res] = unix(['ssh ' ssh_options ' ' remote_name ' rm -r ' work_path]);
+ if (stat~=0);
+ disp(res);
+ warning('openEMS:RunOpenEMS','remote cleanup failed!');
+ end
+ end
+end
+
+cd(savePath);
diff --git a/openEMS/matlab/RunOpenEMS_Parallel.m b/openEMS/matlab/RunOpenEMS_Parallel.m
new file mode 100644
index 0000000..cd5d4bd
--- /dev/null
+++ b/openEMS/matlab/RunOpenEMS_Parallel.m
@@ -0,0 +1,92 @@
+function [stdout, stderr] = RunOpenEMS_Parallel(Sim_Paths, Sim_Files, opts, Settings, varargin)
+% function [stdout, stderr] = RunOpenEMS_Parallel(Sim_Paths, Sim_Files, opts, Settings, varargin)
+%
+% Run multiple openEMS simulations in parallel, distributed on multiple
+% machines using a ssh host_list! (currently on Linux only)
+%
+% This function relies on InitQueue etc.
+%
+% input:
+% Sim_Paths: cell array of pathes to simulate by RunOpenEMS
+% Sim_Files: filename or cell array of filenames to simulate
+% opts: openEMS options. sa RunOpenEMS
+% Settings: use the settings to define multiple host for simulation
+% e.g.: Settings.SSH.bin ='<path_to_openEMS>/openEMS.sh';
+% Settings.SSH.host_list = {'list','of','hosts'};
+%
+% Note: If no SSH host_list is defined, this function will skip the
+% parallel run and switch back to a default RunOpenEMS!
+%
+% See also RunOpenEMS, FindFreeSSH, InitQueue
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig 2011
+
+pause_queue = 5; %pause between consecutive runs (needed for FindFreeSSH)
+
+skip_parallel = 0;
+
+% currently only supporting linux, run conventional RunOpenEMS
+if ~isunix
+ warning 'your OS is not supported (Unix only), running default RunOpenEMS';
+ skip_parallel = 1;
+end
+
+% in case only one path is given, run conventional RunOpenEMS
+if ischar(Sim_Paths)
+ warning 'only a single path given, running default RunOpenEMS'
+ skip_parallel = 1;
+end
+
+% in case SSH.host_list is not defined, run conventional RunOpenEMS
+if ~isfield(Settings,'SSH')
+ warning 'SSH options missing, running default RunOpenEMS'
+ skip_parallel = 1;
+elseif ~isfield(Settings.SSH,'host_list')
+ warning 'SSH.host_list option missing, running default RunOpenEMS'
+ skip_parallel = 1;
+end
+
+if (skip_parallel)
+ for n=1:numel(Sim_Paths)
+ if iscell(Sim_Files)
+ Sim_File = Sim_Files{n};
+ else
+ Sim_File = Sim_Files;
+ end
+ RunOpenEMS(Sim_Paths{n}, Sim_Files, opts, Settings)
+ end
+ stdout = [];
+ stderr = [];
+ return
+end
+
+if ~iscell(Sim_Paths)
+ error('RunOpenEMS_Parallel:needs a cell array of Sim_Paths to simulate');
+end
+
+% get the path to this file
+[dir] = fileparts( mfilename('fullpath') );
+
+queue = InitQueue('DependPath',{dir}, varargin{:});
+
+% spawn multiple simulations
+for n=1:numel(Sim_Paths)
+ if iscell(Sim_Files)
+ Sim_File = Sim_Files{n};
+ else
+ Sim_File = Sim_Files;
+ end
+
+ queue = Add2Queue(queue,'RunOpenEMS',{Sim_Paths{n}, Sim_File, opts, Settings});
+ disp(['openEMS simulation #' int2str(n) ' in directory: ' Sim_Paths{n} ' started!']);
+ pause(pause_queue);
+end
+
+[queue] = FinishQueue(queue);
+
+for n=1:numel(Sim_Paths)
+ stdout{n} = queue.jobs{n}.stdout;
+ stderr{n} = queue.jobs{n}.stderr;
+end
diff --git a/openEMS/matlab/SetBoundaryCond.m b/openEMS/matlab/SetBoundaryCond.m
new file mode 100644
index 0000000..fbfbd4c
--- /dev/null
+++ b/openEMS/matlab/SetBoundaryCond.m
@@ -0,0 +1,68 @@
+function FDTD = SetBoundaryCond(FDTD, BC, varargin)
+% FDTD = SetBoundaryCond(FDTD, BC, varargin)
+%
+% BC = [xmin xmax ymin ymax zmin zmax];
+% or BC = {xmin xmax ymin ymax zmin zmax};
+% ?min/?max:
+% 0 = PEC or 'PEC'
+% 1 = PMC or 'PMC'
+% 2 = MUR-ABC or 'MUR'
+% 3 = PML-ABC or 'PML_x' with pml size x => 4..50
+%
+% example:
+% BC = [ 1 1 0 0 2 3 ] %using numbers or
+% BC = {'PMC' 'PMC' 'PEC' 'PEC' 'MUR' 'PML_8'} %usign equivalent strings
+%
+% mur-abc definitions
+% define a phase-velocity to be used by the mur-abc
+% useful e.g. for dispersive waveguides
+% FDTD = SetBoundaryCond(FDTD,BC,'MUR_PhaseVelocity',299792457.93272);
+%
+%
+% pml definitions
+% arguments: 'PML_Grading','gradFunction'
+% Define the pml grading grading function.
+% Predefined variables in this grading function are:
+% D = depth in the pml in meter
+% dl = mesh delta inside the pml in meter
+% W = width (length) of the pml in meter
+% N = number of cells for the pml
+% Z = wave impedance at the current depth and position
+%
+% example:
+% FDTD = SetBoundaryCond(FDTD,BC);
+% or
+% FDTD = SetBoundaryCond(FDTD,BC,'PML_Grading','-log(1e-6)*log(2.5)/(2*dl*pow(2.5,W/dl)-1) * pow(2.5, D/dl) / Z');
+%
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+if (numel(BC)~=6)
+ error('openEMS:SetBoundaryCond','wrong number of boundary conditions');
+end
+
+if isnumeric(BC)
+ FDTD.BoundaryCond.ATTRIBUTE.xmin=BC(1);
+ FDTD.BoundaryCond.ATTRIBUTE.xmax=BC(2);
+ FDTD.BoundaryCond.ATTRIBUTE.ymin=BC(3);
+ FDTD.BoundaryCond.ATTRIBUTE.ymax=BC(4);
+ FDTD.BoundaryCond.ATTRIBUTE.zmin=BC(5);
+ FDTD.BoundaryCond.ATTRIBUTE.zmax=BC(6);
+elseif iscell(BC)
+ FDTD.BoundaryCond.ATTRIBUTE.xmin=BC{1};
+ FDTD.BoundaryCond.ATTRIBUTE.xmax=BC{2};
+ FDTD.BoundaryCond.ATTRIBUTE.ymin=BC{3};
+ FDTD.BoundaryCond.ATTRIBUTE.ymax=BC{4};
+ FDTD.BoundaryCond.ATTRIBUTE.zmin=BC{5};
+ FDTD.BoundaryCond.ATTRIBUTE.zmax=BC{6};
+else
+ error('openEMS:SetBoundaryCond','unknown boundary condition type');
+end
+
+
+for n=1:(nargin-2)/2
+ FDTD.BoundaryCond.ATTRIBUTE.(varargin{2*n-1}) = varargin{2*n};
+end
+ \ No newline at end of file
diff --git a/openEMS/matlab/SetCustomExcite.m b/openEMS/matlab/SetCustomExcite.m
new file mode 100644
index 0000000..6f87a49
--- /dev/null
+++ b/openEMS/matlab/SetCustomExcite.m
@@ -0,0 +1,21 @@
+function FDTD = SetCustomExcite(FDTD,f0,funcStr)
+% function FDTD = SetCustomExcite(FDTD,f0,funcStr)
+%
+% f0 : nyquist rate
+% funcStr : string desribing the excitation function e(t)
+%
+% see also SetSinusExcite SetGaussExcite
+%
+% e.g for a ramped sinus excite...
+% T = 1/f0;
+% FDTD = SetCustomExcite(FDTD,1e9,..
+% [ '(1-exp(-1*(t/' num2str(T) ')^2) ) * sin(2*pi*' num2str(f0) '*t)' ]);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+FDTD.Excitation.ATTRIBUTE.Type=10;
+FDTD.Excitation.ATTRIBUTE.f0=f0;
+FDTD.Excitation.ATTRIBUTE.Function=funcStr;
+FDTD.ATTRIBUTE.f_max=f0;
diff --git a/openEMS/matlab/SetDiracExcite.m b/openEMS/matlab/SetDiracExcite.m
new file mode 100644
index 0000000..18a342d
--- /dev/null
+++ b/openEMS/matlab/SetDiracExcite.m
@@ -0,0 +1,3 @@
+function FDTD = SetDiracExcite(FDTD)
+
+FDTD.Excitation.ATTRIBUTE.Type=2;
diff --git a/openEMS/matlab/SetGaussExcite.m b/openEMS/matlab/SetGaussExcite.m
new file mode 100644
index 0000000..be650ba
--- /dev/null
+++ b/openEMS/matlab/SetGaussExcite.m
@@ -0,0 +1,18 @@
+function FDTD = SetGaussExcite(FDTD,f0,fc)
+% function FDTD = SetGaussExcite(FDTD,f0,fc);
+%
+% f0 : center frequency
+% fc : 20dB cutoff frequency --> bandwidth is 2*fc
+%
+% see also SetSinusExcite SetCustomExcite
+%
+% e.g FDTD = SetGaussExcite(FDTD,1e9,1e8);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+FDTD.Excitation.ATTRIBUTE.Type=0;
+FDTD.Excitation.ATTRIBUTE.f0=f0;
+FDTD.Excitation.ATTRIBUTE.fc=fc;
+FDTD.ATTRIBUTE.f_max=f0+fc;
diff --git a/openEMS/matlab/SetSinusExcite.m b/openEMS/matlab/SetSinusExcite.m
new file mode 100644
index 0000000..22aadde
--- /dev/null
+++ b/openEMS/matlab/SetSinusExcite.m
@@ -0,0 +1,14 @@
+function FDTD = SetSinusExcite(FDTD,f0)
+% function FDTD = SetSinusExcite(FDTD,f0)
+%
+% see also SetGaussExcite SetCustomExcite
+%
+% e.g FDTD = SetSinusExcite(FDTD,1e9);
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+FDTD.Excitation.ATTRIBUTE.Type=1;
+FDTD.Excitation.ATTRIBUTE.f0=f0;
+FDTD.ATTRIBUTE.f_max=f0;
diff --git a/openEMS/matlab/SetStepExcite.m b/openEMS/matlab/SetStepExcite.m
new file mode 100644
index 0000000..ff87e4f
--- /dev/null
+++ b/openEMS/matlab/SetStepExcite.m
@@ -0,0 +1,3 @@
+function FDTD = SetStepExcite(FDTD)
+
+FDTD.Excitation.ATTRIBUTE.Type=3;
diff --git a/openEMS/matlab/SetupMPI.m b/openEMS/matlab/SetupMPI.m
new file mode 100644
index 0000000..51d6f65
--- /dev/null
+++ b/openEMS/matlab/SetupMPI.m
@@ -0,0 +1,17 @@
+function FDTD = SetupMPI(FDTD, varargin)
+% function FDTD = SetupMPI(FDTD, varargin);
+%
+% % example, split the FDTD mesh in 2 equal parts in x-direction
+% % and split the FDTD mesh in 3 parts in z-direction, split at z=-500 and z=500
+% % this will need a Settings.MPI.NrProc of 2*3=6
+% FDTD = SetupMPI(FDTD,'SplitN_X',2 ,'SplitPos_Z', '-500,500');
+%
+% See also RunOpenEMS_MPI
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+for n=1:(nargin-1)/2
+ FDTD.MPI.ATTRIBUTE.(varargin{2*n-1})=varargin{2*n};
+end
diff --git a/openEMS/matlab/Tutorials/Bent_Patch_Antenna.m b/openEMS/matlab/Tutorials/Bent_Patch_Antenna.m
new file mode 100644
index 0000000..33d5cac
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Bent_Patch_Antenna.m
@@ -0,0 +1,197 @@
+%
+% Tutorials / bent patch antenna
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Bent_Patch_Antenna
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2013-2015 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% patch width in alpha-direction
+patch.width = 32; % resonant length in alpha-direction
+patch.radius = 50; % radius
+patch.length = 40; % patch length in z-direction
+
+%substrate setup
+substrate.epsR = 3.38;
+substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
+substrate.width = 80;
+substrate.length = 90;
+substrate.thickness = 1.524;
+substrate.cells = 4;
+
+%setup feeding
+feed.pos = -5.5; %feeding position in x-direction
+feed.width = 2; %feeding port width
+feed.R = 50; %feed resistance
+
+% size of the simulation box
+SimBox.rad = 2*100;
+SimBox.height = 1.5*200;
+
+%% setup FDTD parameter & excitation function
+FDTD = InitFDTD('CoordSystem', 1); % init a cylindrical FDTD
+f0 = 2e9; % center frequency
+fc = 1e9; % 20 dB corner frequency
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+% init a cylindrical mesh
+CSX = InitCSX('CoordSystem',1);
+
+% calculate some width as an angle in radiant
+patch_ang_width = patch.width/(patch.radius+substrate.thickness);
+substr_ang_width = substrate.width/patch.radius;
+feed_angle = feed.pos/patch.radius;
+
+%% create patch
+CSX = AddMetal( CSX, 'patch' ); % create a perfect electric conductor (PEC)
+start = [patch.radius+substrate.thickness -patch_ang_width/2 -patch.length/2 ];
+stop = [patch.radius+substrate.thickness patch_ang_width/2 patch.length/2 ];
+CSX = AddBox(CSX,'patch',10,start,stop); % add a box-primitive to the metal property 'patch'
+
+%% create substrate
+CSX = AddMaterial( CSX, 'substrate' );
+CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa );
+start = [patch.radius -substr_ang_width/2 -substrate.length/2];
+stop = [patch.radius+substrate.thickness substr_ang_width/2 substrate.length/2];
+CSX = AddBox( CSX, 'substrate', 0, start, stop);
+
+%% save current density oon the patch
+CSX = AddDump(CSX, 'Jt_patch','DumpType',3,'FileType',1);
+start = [patch.radius+substrate.thickness -substr_ang_width/2 -substrate.length/2];
+stop = [patch.radius+substrate.thickness +substr_ang_width/2 substrate.length/2];
+CSX = AddBox( CSX, 'Jt_patch', 0, start, stop );
+
+%% create ground (not really necessary, only for esthetic reasons)
+CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
+start = [patch.radius -substr_ang_width/2 -substrate.length/2];
+stop = [patch.radius +substr_ang_width/2 +substrate.length/2];
+CSX = AddBox(CSX,'gnd',10,start,stop);
+
+%% apply the excitation & resist as a current source
+start = [patch.radius feed_angle 0];
+stop = [patch.radius+substrate.thickness feed_angle 0];
+[CSX port] = AddLumpedPort(CSX, 50 ,1 ,feed.R, start, stop, [1 0 0], true);
+
+
+%% finalize the mesh
+% detect all edges
+mesh = DetectEdges(CSX);
+
+% add the simulation domain size
+mesh.r = [mesh.r patch.radius+[-20 SimBox.rad]];
+mesh.a = [mesh.a -0.75*pi 0.75*pi];
+mesh.z = [mesh.z -SimBox.height/2 SimBox.height/2];
+
+% add some lines for the substrate
+mesh.r = [mesh.r patch.radius+linspace(0,substrate.thickness,substrate.cells)];
+
+% generate a smooth mesh with max. cell size: lambda_min / 20
+max_res = c0 / (f0+fc) / unit / 20;
+max_ang = max_res/(SimBox.rad+patch.radius); % max res in radiant
+mesh = SmoothMesh(mesh, [max_res max_ang max_res], 1.4);
+
+disp(['Num of cells: ' num2str(numel(mesh.r)*numel(mesh.a)*numel(mesh.z))]);
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create nf2ff, keep some distance to the boundary conditions, e.g. 8 cells pml
+start = [mesh.r(4) mesh.a(8) mesh.z(8)];
+stop = [mesh.r(end-9) mesh.a(end-9) mesh.z(end-9)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'Directions',[1 1 1 1 1 1]);
+
+%% prepare simulation folder & run
+Sim_Path = ['tmp_' mfilename];
+Sim_CSX = [mfilename '.xml'];
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+% show the structure
+CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+% run openEMS
+RunOpenEMS( Sim_Path, Sim_CSX);
+
+%% postprocessing & do the plots
+freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+P_in = 0.5*real(port.uf.tot .* conj(port.if.tot)); % antenna feed power
+
+% plot feed point impedance
+figure
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+drawnow
+
+%find resonance frequncy from s11
+f_res_ind = find(s11==min(s11));
+f_res = freq(f_res_ind);
+
+%%
+disp('dumping resonant current distribution to vtk file, use Paraview to visualize');
+ConvertHDF5_VTK([Sim_Path '/Jt_patch.h5'],[Sim_Path '/Jf_patch'],'Frequency',f_res,'FieldName','J-Field');
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% calculate the far field at phi=0 degree
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, [-180:2:180]*pi/180, 0,'Center',[patch.radius+substrate.thickness 0 0]*unit, 'Outfile','pattern_phi_0.h5');
+% normalized directivity as polar plot
+figure
+polarFF(nf2ff,'xaxis','theta','param',1,'normalize',1)
+
+% calculate the far field at phi=0 degree
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, pi/2, (-180:2:180)*pi/180,'Center',[patch.radius+substrate.thickness 0 0]*unit, 'Outfile','pattern_theta_90.h5');
+% normalized directivity as polar plot
+figure
+polarFF(nf2ff,'xaxis','phi','param',1,'normalize',1)
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
+disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);
+
+drawnow
+
+%%
+disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
+thetaRange = (0:2:180);
+phiRange = (0:2:360) - 180;
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5','Center',[patch.radius+substrate.thickness 0 0]*unit);
+
+figure
+plotFF3D(nf2ff,'logscale',-20);
+
diff --git a/openEMS/matlab/Tutorials/CRLH_Extraction.m b/openEMS/matlab/Tutorials/CRLH_Extraction.m
new file mode 100644
index 0000000..e0bc361
--- /dev/null
+++ b/openEMS/matlab/Tutorials/CRLH_Extraction.m
@@ -0,0 +1,155 @@
+%
+% Tutorials / CRLH_Extraction
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_CRLH_Extraction
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2011-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; % specify everything in um
+
+feed_length = 30000;
+
+substrate_thickness = [1524 101 254];
+substrate_epsr = [3.48 3.48 3.48];
+
+CRLH.LL = 14e3; %CRLH totel (line) length
+CRLH.LW = 4e3; %CRLH unit cell width (without the stubs)
+CRLH.GLB = 1950; %CRLH gap width bottom layer
+CRLH.GLT = 4700; %CRLH gap width top layer
+CRLH.SL = 7800; %CRLH stub length (bottom layer, both sides)
+CRLH.SW = 1000; %CRLH stub width (bottom layer, both sides)
+CRLH.VR = 250; %CRLH via hole radius (stub -> ground)
+CRLH.TopSig = sum(substrate_thickness); %top layer height
+CRLH.BottomSig = CRLH.TopSig - substrate_thickness(end); %bottom layer height
+
+% frequency range of interest
+f_start = 0.8e9;
+f_stop = 6e9;
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD();
+FDTD = SetGaussExcite( FDTD, (f_start+f_stop)/2, (f_stop-f_start)/2 );
+BC = {'PML_8' 'PML_8' 'MUR' 'MUR' 'PEC' 'PML_8'};
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% Setup a basic mesh and create the CRLH unit cell
+CSX = InitCSX();
+resolution = c0/(f_stop*sqrt(max(substrate_epsr)))/unit /30; % resolution of lambda/30
+
+mesh.x = [-feed_length-CRLH.LL/2 0 feed_length+CRLH.LL/2];
+mesh.y = [-30000 0 30000];
+substratelines = cumsum(substrate_thickness);
+mesh.z = [0 cumsum(substrate_thickness) linspace(substratelines(end-1),substratelines(end),4) 20000];
+
+% create the CRLH unit cell (will define additional fixed mesh lines)
+[CSX mesh] = CreateCRLH(CSX, mesh, CRLH, resolution/4);
+
+% Smooth the given mesh
+mesh = SmoothMesh(mesh, resolution, 1.5, 'algorithm',[1 3]);
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% Setup the substrate layer
+substratelines = [0 substratelines];
+for n=1:numel(substrate_thickness)
+ CSX = AddMaterial( CSX, ['substrate' int2str(n)] );
+ CSX = SetMaterialProperty( CSX, ['substrate' int2str(n)], 'Epsilon', substrate_epsr(n) );
+ start = [mesh.x(1), mesh.y(1), substratelines(n)];
+ stop = [mesh.x(end), mesh.y(end), substratelines(n+1)];
+ CSX = AddBox( CSX, ['substrate' int2str(n)], 0, start, stop );
+end
+
+%% add the feeding MSL ports
+CSX = AddMetal( CSX, 'PEC' );
+portstart = [ mesh.x(1) , -CRLH.LW/2, substratelines(end)];
+portstop = [ -CRLH.LL/2, CRLH.LW/2, 0];
+[CSX,port{1}] = AddMSLPort( CSX, 999, 1, 'PEC', portstart, portstop, 0, [0 0 -1], 'ExcitePort', true, 'FeedShift', 10*resolution(1), 'MeasPlaneShift', feed_length/2);
+
+portstart = [ mesh.x(end) , -CRLH.LW/2, substratelines(end)];
+portstop = [ +CRLH.LL/2, CRLH.LW/2, 0];
+[CSX,port{2}] = AddMSLPort( CSX, 999, 2, 'PEC', portstart, portstop, 0, [0 0 -1], 'MeasPlaneShift', feed_length/2 );
+
+%% write/show/run the openEMS compatible xml-file
+Sim_Path = 'tmp';
+Sim_CSX = 'CRLH.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( f_start, f_stop, 1601 );
+port = calcPort( port, Sim_Path, f, 'RefPlaneShift', feed_length);
+
+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);
+l = legend('S_{11}','S_{21}','Location','Best');
+set(l,'FontSize',12);
+ylabel('S-Parameter (dB)','FontSize',12);
+xlabel('frequency (GHz) \rightarrow','FontSize',12);
+ylim([-40 2]);
+
+%% extract parameter
+A = ((1+s11).*(1-s11) + s21.*s21)./(2*s21);
+C = ((1-s11).*(1-s11) - s21.*s21)./(2*s21) ./ port{2}.ZL;
+
+Y = C;
+Z = 2*(A-1)./C;
+
+iZ = imag(Z);
+iY = imag(Y);
+
+fse = interp1(iZ,f,0);
+fsh = interp1(iY,f,0);
+
+df = f(2)-f(1);
+fse_idx = find(f>fse,1);
+fsh_idx = find(f>fsh,1);
+
+LR = 0.5*(iZ(fse_idx)-iZ(fse_idx-1))./(2*pi*df);
+CL = 1/(2*pi*fse)^2/LR;
+
+CR = 0.5*(iY(fsh_idx)-iY(fsh_idx-1))./(2*pi*df);
+LL = 1/(2*pi*fsh)^2/CR;
+
+disp([' Series tank: CL = ' num2str(CL*1e12,3) 'pF; LR = ' num2str(LR*1e9,3) 'nH -> f_se = ' num2str(fse*1e-9,3) 'GHz ']);
+disp([' Shunt tank: CR = ' num2str(CR*1e12,3) 'pF; LL = ' num2str(LL*1e9,3) 'nH -> f_sh = ' num2str(fsh*1e-9,3) 'GHz ']);
+
+%% calculate analytical wave-number of an inf-array of cells
+w = 2*pi*f;
+wse = 2*pi*fse;
+wsh = 2*pi*fsh;
+beta_calc = real(acos(1-(w.^2-wse^2).*(w.^2-wsh^2)./(2*w.^2/CR/LR)));
+
+%%
+figure
+beta = -angle(s21)/CRLH.LL/unit;
+plot(abs(beta)*CRLH.LL*unit/pi,f*1e-9,'k-','LineWidth',2)
+grid on;
+hold on;
+plot(beta_calc/pi,f*1e-9,'c--','LineWidth',2)
+plot(real(port{2}.beta)*CRLH.LL*unit/pi,f*1e-9,'g-','LineWidth',2)
+ylim([1 6])
+xlabel('|\beta| p / \pi \rightarrow','FontSize',12)
+ylabel('frequency (GHz) \rightarrow','FontSize',12)
+l = legend('\beta_{CRLH, 1 cell}','\beta_{CRLH, \infty cells}','\beta_{MSL}','Location','East');
+set(l,'FontSize',12);
diff --git a/openEMS/matlab/Tutorials/CRLH_LeakyWaveAnt.m b/openEMS/matlab/Tutorials/CRLH_LeakyWaveAnt.m
new file mode 100644
index 0000000..a8359b7
--- /dev/null
+++ b/openEMS/matlab/Tutorials/CRLH_LeakyWaveAnt.m
@@ -0,0 +1,168 @@
+%
+% Tutorials / CRLH_LeakyWaveAnt
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_CRLH_Leaky_Wave_Antenna
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2011-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; % specify everything in um
+
+feed_length = 20000;
+
+substrate_thickness = [1524 101 254];
+substrate_epsr = [3.48 3.48 3.48];
+substrate_tanD = [1 1 1]*1e-3;
+
+N_Cells = 8; %number of CRLH unit cells
+
+CRLH.LL = 14e3; %CRLH totel (line) length
+CRLH.LW = 4e3; %CRLH unit cell width (without the stubs)
+CRLH.GLB = 1950; %CRLH gap width bottom layer
+CRLH.GLT = 4700; %CRLH gap width top layer
+CRLH.SL = 7800; %CRLH stub length (bottom layer, both sides)
+CRLH.SW = 1000; %CRLH stub width (bottom layer, both sides)
+CRLH.VR = 250; %CRLH via hole radius (stub -> ground)
+CRLH.TopSig = sum(substrate_thickness); %top layer height
+CRLH.BottomSig = CRLH.TopSig - substrate_thickness(end); %bottom layer height
+
+substrate_width = CRLH.LW + 2*CRLH.SL;
+Air_Spacer = 30000;
+
+% frequency range of interest
+f_start = 1e9;
+f_stop = 6e9;
+
+% frequencies to calculate the 3D radiation pattern
+f_rad = (1.9:0.05:4.2)*1e9;
+nf2ff_resolution = c0/max(f_rad)/unit/15;
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD('EndCriteria', 1e-3);
+FDTD = SetGaussExcite( FDTD, (f_start+f_stop)/2, (f_stop-f_start)/2 );
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'};
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% Setup a basic mesh and create the CRLH unit cell
+CSX = InitCSX();
+resolution = c0/(f_stop*sqrt(max(substrate_epsr)))/unit /30; % resolution of lambda/30
+
+mesh.x = [-feed_length-(N_Cells*CRLH.LL)/2-Air_Spacer -feed_length-(N_Cells*CRLH.LL)/2 0 feed_length+(N_Cells*CRLH.LL)/2 feed_length+(N_Cells*CRLH.LL)/2+Air_Spacer];
+mesh.y = [-Air_Spacer-substrate_width/2 0 Air_Spacer+substrate_width/2];
+substratelines = cumsum(substrate_thickness);
+mesh.z = [-0.5*Air_Spacer 0 cumsum(substrate_thickness) linspace(substratelines(end-1),substratelines(end),4) Air_Spacer];
+
+% create the CRLH unit cells (will define additional fixed mesh lines)
+pos_x = -(N_Cells*CRLH.LL)/2 + CRLH.LL/2;
+for n=1:N_Cells
+ [CSX mesh] = CreateCRLH(CSX, mesh, CRLH, resolution/4, [pos_x 0 0]);
+ pos_x = pos_x + CRLH.LL;
+end
+
+% Smooth the given mesh
+mesh = SmoothMesh(mesh, resolution, 1.5, 'algorithm',[1 3]);
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% Setup the substrate layer
+substratelines = [0 substratelines];
+for n=1:numel(substrate_thickness)
+ CSX = AddMaterial( CSX, ['substrate' int2str(n)] );
+ CSX = SetMaterialProperty( CSX, ['substrate' int2str(n)], 'Epsilon', substrate_epsr(n), 'Kappa', substrate_tanD(n)*substrate_epsr(n)*EPS0*2*pi*3e9 );
+ start = [-feed_length-(N_Cells*CRLH.LL)/2, -substrate_width/2, substratelines(n)];
+ stop = [+feed_length+(N_Cells*CRLH.LL)/2, substrate_width/2, substratelines(n+1)];
+ CSX = AddBox( CSX, ['substrate' int2str(n)], 0, start, stop );
+end
+
+%% add the feeding MSL ports
+%ground plane
+CSX = AddMetal( CSX, 'ground' );
+start = [-feed_length-(N_Cells*CRLH.LL)/2, -substrate_width/2, 0];
+stop = [+feed_length+(N_Cells*CRLH.LL)/2, substrate_width/2, 0];
+CSX = AddBox( CSX, 'ground', 0, start, stop );
+
+CSX = AddMetal( CSX, 'PEC' );
+portstart = [ -feed_length-(N_Cells*CRLH.LL)/2 , -CRLH.LW/2, substratelines(end)];
+portstop = [ -(N_Cells*CRLH.LL)/2, CRLH.LW/2, 0];
+[CSX,port{1}] = AddMSLPort( CSX, 999, 1, 'PEC', portstart, portstop, 0, [0 0 -1], 'ExcitePort', true, 'MeasPlaneShift', feed_length/2, 'Feed_R', 50);
+
+portstart = [ feed_length+(N_Cells*CRLH.LL)/2 , -CRLH.LW/2, substratelines(end)];
+portstop = [ +(N_Cells*CRLH.LL)/2, CRLH.LW/2, 0];
+[CSX,port{2}] = AddMSLPort( CSX, 999, 2, 'PEC', portstart, portstop, 0, [0 0 -1], 'MeasPlaneShift', feed_length/2, 'Feed_R', 50 );
+
+%% nf2ff calc
+start = [mesh.x(1) mesh.y(1) mesh.z(1) ] + 10*resolution;
+stop = [mesh.x(end) mesh.y(end) mesh.z(end)] - 10*resolution;
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'OptResolution', nf2ff_resolution);
+
+%% write/show/run the openEMS compatible xml-file
+Sim_Path = 'tmp_CRLH_LeakyWave';
+Sim_CSX = 'CRLH.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( f_start, f_stop, 1601 );
+port = calcPort( port, Sim_Path, f, 'RefPlaneShift', feed_length*unit);
+
+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);
+l = legend('S_{11}','S_{21}','Location','Best');
+set(l,'FontSize',12);
+ylabel('S-Parameter (dB)','FontSize',12);
+xlabel('frequency (GHz) \rightarrow','FontSize',12);
+ylim([-40 2]);
+
+drawnow
+
+%% calculate 3D pattern
+phi = 0:2:360;
+theta = 0:2:180;
+
+disp( 'calculating 3D far field pattern...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_rad, theta*pi/180, phi*pi/180, 'Outfile','3D_Pattern.h5', 'Mode', 0,'Verbose',1);
+
+%%
+P_in = interp1(f, port{1}.P_acc, f_rad);
+
+figure()
+
+[AX,H1,H2] = plotyy(f_rad/1e9,nf2ff.Dmax',f_rad/1e9,100*nf2ff.Prad'./P_in,'plot');
+grid on
+xlabel( 'frequency (GHz)' );
+set(get(AX(1),'Ylabel'),'String','directivity (dBi)')
+set(get(AX(2),'Ylabel'),'String','radiation efficiency (%)')
+set(H1,'Linewidth',2)
+set(H2,'Linewidth',2)
+set(H1,'Marker','*')
+set(H2,'Marker','s')
+
+drawnow
+
+%%
+disp( 'dumping 3D far field pattern to vtk, use Paraview to visualize...' );
+for n=1:numel(f_rad)
+ E_far_normalized_3D = nf2ff.E_norm{n} / max(max(nf2ff.E_norm{n})) * nf2ff.Dmax(n);
+ DumpFF2VTK( [Sim_Path '/FF_Pattern_' int2str(f_rad(n)/1e6) 'MHz.vtk'],E_far_normalized_3D,theta,phi,'scale',1e-3);
+end
+
diff --git a/openEMS/matlab/Tutorials/Circ_Waveguide.m b/openEMS/matlab/Tutorials/Circ_Waveguide.m
new file mode 100644
index 0000000..d61a713
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Circ_Waveguide.m
@@ -0,0 +1,105 @@
+%
+% Tutorials / Circ_Waveguide
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Circular_Waveguide
+%
+% Tested with
+% - Matlab 2011a / Octave 3.4.3
+% - openEMS v0.0.31
+%
+% (C) 2010-2013 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-3; %drawing unit in mm
+
+% waveguide dimensions
+length = 2000;
+rad = 350; %waveguide radius in mm
+
+% frequency range of interest
+f_start = 300e6;
+f_stop = 500e6;
+
+mesh_res = [10 2*pi/49.999 10]; %targeted mesh resolution
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD('EndCriteria',1e-4,'CoordSystem',1);
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+
+% boundary conditions
+BC = [0 0 0 0 3 3]; %pml in pos. and neg. z-direction
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX('CoordSystem',1); % init a cylindrical mesh
+mesh.r = SmoothMeshLines([0 rad], mesh_res(1)); %mesh in radial direction
+mesh.a = SmoothMeshLines([0 2*pi], mesh_res(2)); % mesh in aziumthal dir.
+mesh.z = SmoothMeshLines([0 length], mesh_res(3));
+CSX = DefineRectGrid(CSX, unit,mesh);
+
+%% apply the waveguide port %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start=[mesh.r(1) mesh.a(1) mesh.z(8)];
+stop =[mesh.r(end) mesh.a(end) mesh.z(15)];
+[CSX, port{1}] = AddCircWaveGuidePort( CSX, 0, 1, start, stop, rad*unit, 'TE11', 0, 1);
+
+start=[mesh.r(1) mesh.a(1) mesh.z(end-13)];
+stop =[mesh.r(end) mesh.a(end) mesh.z(end-14)];
+[CSX, port{2}] = AddCircWaveGuidePort( CSX, 0, 2, start, stop, rad*unit, 'TE11');
+
+%% define dump box... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','4,4,4');
+start = [mesh.r(1) mesh.a(1) mesh.z(1)];
+stop = [mesh.r(end) mesh.a(end) mesh.z(end)];
+CSX = AddBox(CSX,'Et',0 , start,stop);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Sim_Path = 'tmp';
+Sim_CSX = 'circ_wg.xml';
+
+[status, message, messageid] = rmdir(Sim_Path,'s');
+[status, message, messageid] = mkdir(Sim_Path);
+
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+RunOpenEMS(Sim_Path, Sim_CSX)
+
+%% postproc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+freq = linspace(f_start,f_stop,201);
+port = calcPort( port, Sim_Path, freq);
+
+s11 = port{1}.uf.ref./ port{1}.uf.inc;
+s21 = port{2}.uf.ref./ port{1}.uf.inc;
+ZL = port{1}.uf.tot./port{1}.if.tot;
+
+
+%% plot s-parameter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+figure
+plot(freq*1e-6,20*log10(abs(s11)),'k-','Linewidth',2);
+xlim([freq(1) freq(end)]*1e-6);
+grid on;
+hold on;
+plot(freq*1e-6,20*log10(abs(s21)),'r--','Linewidth',2);
+l = legend('S_{11}','S_{21}','Location','Best');
+set(l,'FontSize',12);
+ylabel('S-Parameter (dB)','FontSize',12);
+xlabel('frequency (MHz) \rightarrow','FontSize',12);
+
+%% compare analytic and numerical wave-impedance %%%%%%%%%%%%%%%%%%%%%%%%%%
+figure
+plot(freq*1e-6,real(ZL),'Linewidth',2);
+hold on;
+grid on;
+plot(freq*1e-6,imag(ZL),'r--','Linewidth',2);
+plot(freq*1e-6,port{1}.ZL,'g-.','Linewidth',2);
+ylabel('ZL (\Omega)','FontSize',12);
+xlabel('frequency (MHz) \rightarrow','FontSize',12);
+xlim([freq(1) freq(end)]*1e-6);
+l = legend('\Re(Z_L)','\Im(Z_L)','Z_L analytic','Location','Best');
+set(l,'FontSize',12);
+
diff --git a/openEMS/matlab/Tutorials/Conical_Horn_Antenna.m b/openEMS/matlab/Tutorials/Conical_Horn_Antenna.m
new file mode 100644
index 0000000..f266993
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Conical_Horn_Antenna.m
@@ -0,0 +1,180 @@
+%
+% Tutorials / conical horn antenna
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Conical_Horn_Antenna
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2011-2015 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% horn radius
+horn.radius = 20;
+% horn length in z-direction
+horn.length = 50;
+
+horn.feed_length = 50;
+
+horn.thickness = 2;
+
+% horn opening angle
+horn.angle = 20*pi/180;
+
+% size of the simulation box
+SimBox = [100 100 100]*2;
+
+% frequency range of interest
+f_start = 10e9;
+f_stop = 20e9;
+
+% frequency of interest
+f0 = 15e9;
+
+%% setup FDTD parameter & excitation function
+FDTD = InitFDTD( 'NrTS', 30000, 'EndCriteria', 1e-4 );
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+% currently, openEMS cannot automatically generate a mesh
+max_res = c0 / (f_stop) / unit / 15; % cell size: lambda/20
+CSX = InitCSX();
+
+%create fixed lines for the simulation box, substrate and port
+mesh.x = [-SimBox(1)/2 -horn.radius 0 horn.radius SimBox(1)/2];
+mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4); % create a smooth mesh between specified fixed mesh lines
+
+mesh.y = mesh.x;
+
+%create fixed lines for the simulation box and given number of lines inside the substrate
+mesh.z = [-horn.feed_length 0 SimBox(3) ];
+mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
+
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create horn
+% horn + waveguide, defined by a rotational polygon
+CSX = AddMetal(CSX, 'Conical_Horn');
+p(1,1) = horn.radius+horn.thickness; % x-coord point 1
+p(2,1) = -horn.feed_length; % z-coord point 1
+p(1,end+1) = horn.radius+horn.thickness; % x-coord point 1
+p(2,end) = 0; % z-coord point 1
+p(1,end+1) = horn.radius+horn.thickness + sin(horn.angle)*horn.length; % x-coord point 2
+p(2,end) = horn.length; % y-coord point 2
+p(1,end+1) = horn.radius + sin(horn.angle)*horn.length; % x-coord point 2
+p(2,end) = horn.length; % y-coord point 2
+p(1,end+1) = horn.radius; % x-coord point 1
+p(2,end) = 0; % z-coord point 1
+p(1,end+1) = horn.radius; % x-coord point 1
+p(2,end) = -horn.feed_length; % z-coord point 1
+CSX = AddRotPoly(CSX,'Conical_Horn',10,'x',p,'z');
+
+% horn aperture
+A = pi*((horn.radius + sin(horn.angle)*horn.length)*unit)^2;
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start=[-horn.radius -horn.radius mesh.z(10) ];
+stop =[+horn.radius +horn.radius mesh.z(1)+horn.feed_length/2 ];
+[CSX, port] = AddCircWaveGuidePort( CSX, 0, 1, start, stop, horn.radius*unit, 'TE11', 0, 1);
+
+%%
+CSX = AddDump(CSX,'Exc_dump');
+start=[-horn.radius -horn.radius mesh.z(8)];
+stop =[+horn.radius +horn.radius mesh.z(8)];
+CSX = AddBox(CSX,'Exc_dump',0,start,stop);
+
+%% nf2ff calc
+start = [mesh.x(9) mesh.y(9) mesh.z(9)];
+stop = [mesh.x(end-8) mesh.y(end-8) mesh.z(end-8)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'Directions', [1 1 1 1 0 1]);
+
+%% prepare simulation folder
+Sim_Path = 'tmp';
+Sim_CSX = 'horn_ant.xml';
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure
+CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+%% run openEMS
+RunOpenEMS( Sim_Path, Sim_CSX);
+
+%% postprocessing & do the plots
+freq = linspace(f_start,f_stop,201);
+
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e9, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+ylim([-60 0]);
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / GHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+drawnow
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+thetaRange = (0:2:359) - 180;
+disp( 'calculating far field at phi=[0 90] deg...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, thetaRange*pi/180, [0 90]*pi/180);
+
+Dlog=10*log10(nf2ff.Dmax);
+G_a = 4*pi*A/(c0/f0)^2;
+e_a = nf2ff.Dmax/G_a;
+
+% display some antenna parameter
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(Dlog) ' dBi'] );
+disp( ['aperture efficiency: e_a = ' num2str(e_a*100) '%'] );
+
+%%
+% normalized directivity
+figure
+plotFFdB(nf2ff,'xaxis','theta','param',[1 2]);
+drawnow
+% D_log = 20*log10(nf2ff.E_norm{1}/max(max(nf2ff.E_norm{1})));
+% D_log = D_log + 10*log10(nf2ff.Dmax);
+% plot( nf2ff.theta, D_log(:,1) ,'k-', nf2ff.theta, D_log(:,2) ,'r-' );
+
+% polar plot
+figure
+polarFF(nf2ff,'xaxis','theta','param',[1 2],'logscale',[-40 20], 'xtics', 12);
+drawnow
+% polar( nf2ff.theta, nf2ff.E_norm{1}(:,1) )
+
+%% calculate 3D pattern
+phiRange = sort( unique( [-180:5:-100 -100:2.5:-50 -50:1:50 50:2.5:100 100:5:180] ) );
+thetaRange = sort( unique([ 0:1:50 50:2.:100 100:5:180 ]));
+
+disp( 'calculating 3D far field...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, thetaRange*pi/180, phiRange*pi/180, 'Verbose',2,'Outfile','nf2ff_3D.h5');
+
+figure
+plotFF3D(nf2ff); % plot liear 3D far field
+
+%%
+E_far_normalized = nf2ff.E_norm{1}/max(nf2ff.E_norm{1}(:));
+DumpFF2VTK([Sim_Path '/Conical_Horn_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,'scale',1e-3);
diff --git a/openEMS/matlab/Tutorials/CreateCRLH.m b/openEMS/matlab/Tutorials/CreateCRLH.m
new file mode 100644
index 0000000..6c10732
--- /dev/null
+++ b/openEMS/matlab/Tutorials/CreateCRLH.m
@@ -0,0 +1,55 @@
+function [CSX mesh] = CreateCRLH(CSX, mesh, CRLH, resolution, translate)
+% function [CSX mesh] = CreateCRLH(CSX, mesh, CRLH, resolution, translate)
+%
+% support function to create a CRLH unit cell
+%
+% currently used by Tutorials/CRLH_Extraction
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.23
+%
+% (C) 2011 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+if (nargin<5)
+ translate = [0 0 0];
+end
+
+CSX = AddMetal(CSX, 'metal_top');
+one_two_third = [-resolution/3 2*resolution/3];
+
+start = [-CRLH.LL/2 -CRLH.LW/2 CRLH.TopSig]+translate;
+stop = [-CRLH.GLT/2 CRLH.LW/2 CRLH.TopSig]+translate;
+CSX = AddBox(CSX, 'metal_top', 10, start, stop);
+mesh.x = [mesh.x start(1) stop(1)+one_two_third];
+mesh.y = [mesh.y start(2)-one_two_third stop(2)+one_two_third];
+
+start = [+CRLH.LL/2 -CRLH.LW/2 CRLH.TopSig]+translate;
+stop = [+CRLH.GLT/2 CRLH.LW/2 CRLH.TopSig]+translate;
+CSX = AddBox(CSX, 'metal_top', 10, start, stop);
+mesh.x = [mesh.x start(1) stop(1)-one_two_third];
+
+CSX = AddMetal(CSX, 'metal_bot');
+start = [-(CRLH.LL-CRLH.GLB)/2 -CRLH.LW/2 CRLH.BottomSig]+translate;
+stop = [+(CRLH.LL-CRLH.GLB)/2 CRLH.LW/2 CRLH.BottomSig]+translate;
+CSX = AddBox(CSX, 'metal_bot', 10, start, stop);
+mesh.x = [mesh.x start(1)-one_two_third stop(1)+one_two_third];
+
+start = [-CRLH.SW/2 -CRLH.LW/2-CRLH.SL CRLH.BottomSig]+translate;
+stop = [+CRLH.SW/2 CRLH.LW/2+CRLH.SL CRLH.BottomSig]+translate;
+CSX = AddBox(CSX, 'metal_bot', 10, start, stop);
+mesh.x = [mesh.x start(1)-one_two_third stop(1)+one_two_third];
+mesh.y = [mesh.y start(2) stop(2)];
+
+CSX = AddMetal(CSX, 'via');
+start = [0 -CRLH.LW/2-CRLH.SL+CRLH.SW/2 0]+translate;
+stop = [0 -CRLH.LW/2-CRLH.SL+CRLH.SW/2 CRLH.BottomSig]+translate;
+CSX = AddCylinder(CSX, 'via', 10, start, stop, CRLH.VR);
+mesh.x = [mesh.x start(1)+[-1 0 1]*CRLH.VR];
+mesh.y = [mesh.y start(2)+[-1 0 1]*CRLH.VR];
+
+start(2) = -start(2);
+stop(2) = -stop(2);
+CSX = AddCylinder(CSX, 'via', 10, start, stop, CRLH.VR);
+mesh.y = [mesh.y start(2)+[-1 0 1]*CRLH.VR];
+end \ No newline at end of file
diff --git a/openEMS/matlab/Tutorials/CylindricalWave_CC.m b/openEMS/matlab/Tutorials/CylindricalWave_CC.m
new file mode 100644
index 0000000..d55c470
--- /dev/null
+++ b/openEMS/matlab/Tutorials/CylindricalWave_CC.m
@@ -0,0 +1,104 @@
+%
+% Tutorials / CylindricalWave_CC
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_2D_Cylindrical_Wave
+%
+% Tested with
+% - Matlab 2011a/ Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2011-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants
+mesh_res = 10; %desired mesh resolution
+radius = 2560; %simulation domain radius
+split = ['80,160,320,640,1280']; %radii to split the mesh into sub-grids
+split_N = 5; %number of nested sub-grids
+heigth = mesh_res*4;
+
+f0 = 1e9;
+
+exite_offset = 1300;
+excite_angle = 45;
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(100000,1e-4,'CoordSystem',1,'MultiGrid',split);
+FDTD = SetGaussExcite(FDTD,f0,f0/2);
+BC = [0 3 0 0 0 0]; % pml in positive r-direction
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 50 mesh lines for the inner most mesh
+% increase the total number of meshlines in alpha direcion for all sub-grids
+N_alpha = 50 * 2^split_N + 1;
+
+CSX = InitCSX('CoordSystem',1);
+mesh.r = SmoothMeshLines([0 radius],mesh_res);
+mesh.a = linspace(-pi,pi,N_alpha);
+mesh.z = SmoothMeshLines([-heigth/2 0 heigth/2],mesh_res);
+CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+%% add the dipol %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start = [exite_offset excite_angle/180*pi-0.001 -20];
+stop = [exite_offset excite_angle/180*pi+0.001 20];
+if (exite_offset==0)
+ start(2) = mesh.a(1);
+ stop(2) = mesh.a(1);
+end
+CSX = AddExcitation(CSX,'excite',1,[0 0 1]);
+CSX = AddBox(CSX,'excite',0 ,start,stop);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start = [mesh.r(1) mesh.a(1) 0];
+stop = [mesh.r(end-8) mesh.a(end) 0];
+
+% time domain vtk dump
+CSX = AddDump(CSX,'Et_ra','DumpType',0,'FileType',0,'SubSampling','4,10,1');
+CSX = AddBox(CSX,'Et_ra',0 , start,stop);
+
+% frequency domain hdf5 dump
+CSX = AddDump(CSX,'Ef_ra','DumpType',10,'FileType',1,'SubSampling','2,2,2','Frequency',f0);
+CSX = AddBox(CSX,'Ef_ra',0 , start,stop);
+
+%% write/run the openEMS compatible xml-file
+Sim_Path = 'tmp';
+Sim_CSX = '2D_CC_Wave.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);
+RunOpenEMS(Sim_Path, Sim_CSX);
+
+%%
+disp('use Paraview to visualize the vtk field dump...');
+
+%%
+[field mesh_h5] = ReadHDF5Dump([Sim_Path '/Ef_ra.h5']);
+
+r = mesh_h5.lines{1};
+a = mesh_h5.lines{2};
+a(end+1) = a(1); %closeup mesh for visualization
+[R A] = ndgrid(r,a);
+X = R.*cos(A);
+Y = R.*sin(A);
+
+Ez = squeeze(field.FD.values{1}(:,:,1,3));
+Ez(:,end+1) = Ez(:,1); %closeup mesh for visualization
+
+E_max = max(max(abs(Ez))); %get maximum E_z amplitude
+
+while 1
+ for ph = linspace(0,360,41) %animate phase from 0..360 degree
+ surf(X,Y,real(Ez*exp(1j*ph*pi/180)),'EdgeColor','none')
+ caxis([-E_max E_max]/10)
+ zlim([-E_max E_max])
+ pause(0.3)
+ end
+end
diff --git a/openEMS/matlab/Tutorials/Dipole_SAR.m b/openEMS/matlab/Tutorials/Dipole_SAR.m
new file mode 100644
index 0000000..a172117
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Dipole_SAR.m
@@ -0,0 +1,221 @@
+%
+% Tutorials / Dipole SAR + Power budget
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Dipole_SAR
+%
+% Tested with
+% - openEMS v0.0.33
+%
+% (C) 2013-2015 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+
+%% prepare simulation folder
+Sim_Path = 'tmp_Dipole_SAR';
+Sim_CSX = 'Dipole_SAR.xml';
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all lengths in mm
+
+feed.R = 50; % feed resistance
+
+%% define phantom
+phantom{1}.name='skin';
+phantom{1}.epsR = 50;
+phantom{1}.kappa = 0.65; % S/m
+phantom{1}.density = 1100; % kg/m^3
+phantom{1}.radius = [80 100 100]; % ellipsoide
+phantom{1}.center = [100 0 0];
+
+phantom{2}.name='headbone';
+phantom{2}.epsR = 13;
+phantom{2}.kappa = 0.1; % S/m
+phantom{2}.density = 2000; % kg/m^3
+phantom{2}.radius = [75 95 95]; % ellipsoide
+phantom{2}.center = [100 0 0];
+
+phantom{3}.name='brain';
+phantom{3}.epsR = 60;
+phantom{3}.kappa = 0.7; % S/m
+phantom{3}.density = 1040; % kg/m^3
+phantom{3}.radius = [65 85 85]; % ellipsoide
+phantom{3}.center = [100 0 0];
+
+%% setup FDTD parameter & excitation function
+f0 = 1e9; % center frequency
+lambda0 = c0/f0;
+
+f_stop = 1.5e9; % 20 dB corner frequency
+lambda_min = c0/f_stop;
+
+mesh_res_air = lambda_min/20/unit;
+mesh_res_phantom = 2.5;
+
+dipole_length = 0.46*lambda0/unit;
+disp(['Lambda-half dipole length: ' num2str(dipole_length) 'mm'])
+
+%%
+FDTD = InitFDTD();
+FDTD = SetGaussExcite( FDTD, 0, f_stop );
+% apply PML-8 boundary conditions in all directions
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'};
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+CSX = InitCSX();
+
+%% Dipole
+CSX = AddMetal( CSX, 'Dipole' ); % create a perfect electric conductor (PEC)
+CSX = AddBox(CSX, 'Dipole', 1, [0 0 -dipole_length/2], [0 0 dipole_length/2]);
+
+% mesh lines for the dipole
+mesh.x = 0;
+mesh.y = 0;
+mesh.z = [-dipole_length/2-[-1/3 2/3]*mesh_res_phantom dipole_length/2+[-1/3 2/3]*mesh_res_phantom];
+
+%% add the dielectrics
+for n=1:numel(phantom)
+ CSX = AddMaterial( CSX, phantom{n}.name );
+ CSX = SetMaterialProperty( CSX, phantom{n}.name, 'Epsilon', phantom{n}.epsR, 'Kappa', phantom{n}.kappa, 'Density', phantom{n}.density);
+ CSX = AddSphere( CSX, phantom{n}.name, 10+n, [0 0 0], 1,'Transform',{'Scale',phantom{n}.radius, 'Translate', phantom{n}.center} );
+
+ %% mesh lines for the dielectrics
+ mesh.x = [mesh.x phantom{n}.radius(1)*[-1 1]+phantom{n}.center(1) ];
+ mesh.y = [mesh.y phantom{n}.radius(2)*[-1 1]+phantom{n}.center(2) ];
+ mesh.z = [mesh.z phantom{n}.radius(3)*[-1 1]+phantom{n}.center(3) ];
+end
+
+%% apply the excitation & resist as a current source
+[CSX port] = AddLumpedPort(CSX, 100, 1, feed.R, [-0.1 -0.1 -mesh_res_phantom/2], [0.1 0.1 +mesh_res_phantom/2], [0 0 1], true);
+
+% mesh lines for the port
+mesh.z = [mesh.z -mesh_res_phantom/2 +mesh_res_phantom/2];
+
+%% smooth the mesh over the dipole and phantom
+mesh = SmoothMesh(mesh, mesh_res_phantom);
+
+%% add lines for the air-box
+mesh.x = [mesh.x -200 250+100];
+mesh.y = [mesh.y -250 250];
+mesh.z = [mesh.z -250 250];
+
+% smooth the final mesh (incl. air box)
+mesh = SmoothMesh(mesh, mesh_res_air, 1.2);
+
+%% dump SAR
+start = [-10 -100 -100];
+stop = [180 100 100];
+CSX = AddDump( CSX, 'SAR', 'DumpType', 20, 'Frequency', f0,'FileType',1,'DumpMode',2);
+CSX = AddBox( CSX, 'SAR', 0, start, stop);
+
+%% nf2ff calc
+start = [mesh.x(1) mesh.y(1) mesh.z(1)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'OptResolution', lambda_min/15/unit);
+
+%%
+% add 10 equidistant cells (air)
+% around the structure to keep the pml away from the nf2ff box
+mesh = AddPML( mesh, 10 );
+
+% Define the mesh
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%%
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+ [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+ % write openEMS compatible xml-file
+ WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+ % show the structure
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+ % run openEMS
+ RunOpenEMS( Sim_Path, Sim_CSX );
+end
+
+
+%% postprocessing & make the plots
+freq = linspace(500e6, 1500e6, 501 );
+port = calcPort(port, Sim_Path, freq);
+
+s11 = port.uf.ref./port.uf.inc;
+Zin = port.uf.tot./port.if.tot;
+
+Pin_f0 = interp1(freq, port.P_acc, f0);
+
+%%
+% plot feed point impedance
+figure
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e9, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'S_{11} (dB)' );
+
+%% read SAR and visualize
+SAR_field = ReadHDF5Dump([Sim_Path '/SAR.h5']);
+
+SAR = SAR_field.FD.values{1};
+ptotal = ReadHDF5Attribute([Sim_Path '/SAR.h5'],'/FieldData/FD/f0','power');
+
+%% calculate 3D pattern
+phi = 0:3:360;
+theta = 0:3:180;
+
+disp( 'calculating 3D far field pattern...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, theta*pi/180, phi*pi/180, 'Outfile','3D_Pattern.h5');
+
+%%
+disp(['max SAR: ' num2str(max(SAR(:))/Pin_f0) ' W/kg normalized to 1 W accepted power']);
+disp(['accepted power: ' num2str(Pin_f0) ' W (100 %)']);
+disp(['radiated power: ' num2str(nf2ff.Prad) ' W ( ' num2str(round(100*(nf2ff.Prad) / Pin_f0)) ' %)']);
+disp(['absorbed power: ' num2str(ptotal) ' W ( ' num2str(round(100*(ptotal) / Pin_f0)) ' %)']);
+disp(['power budget: ' num2str(100*(nf2ff.Prad + ptotal) / Pin_f0) ' %']);
+
+%% plot on a x/y-plane
+[SAR_field SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR.h5'],'Range',{[],[],0});
+figure
+[X Y] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{2});
+h = pcolor(X,Y,log10(SAR_field.FD.values{1}/abs(Pin_f0)));
+title( 'logarithmic SAR on an xy-plane' );
+xlabel('x -->')
+ylabel('y -->')
+axis equal tight
+set(h,'EdgeColor','none');
+
+%% plot on a x/z-plane
+[SAR_field SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR.h5'],'Range',{[],0,[]});
+figure
+[X Z] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{3});
+h = pcolor(X,Z,log10(squeeze(SAR_field.FD.values{1}))/abs(Pin_f0));
+title( 'logarithmic SAR on an xz-plane' );
+xlabel('x -->')
+ylabel('z -->')
+axis equal tight
+set(h,'EdgeColor','none');
+
+%% dump SAR to vtk file
+disp(['Full local/normalized SAR has been dumped to vtk file! Use Paraview to visualize']);
+ConvertHDF5_VTK([Sim_Path '/SAR.h5'],[Sim_Path '/SAR'],'weight',1/abs(Pin_f0),'FieldName','SAR_local' );
+
diff --git a/openEMS/matlab/Tutorials/Helical_Antenna.m b/openEMS/matlab/Tutorials/Helical_Antenna.m
new file mode 100644
index 0000000..b94ebd6
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Helical_Antenna.m
@@ -0,0 +1,202 @@
+%
+% Tutorials / helical antenna
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Helical_Antenna
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2012-2015 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+post_proc_only = 0;
+
+close all
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+f0 = 2.4e9; % center frequency, frequency of interest!
+lambda0 = round(c0/f0/unit); % wavelength in mm
+fc = 0.5e9; % 20 dB corner frequency
+
+Helix.radius = 20; % --> diameter is ~ lambda/pi
+Helix.turns = 10; % --> expected gain is G ~ 4 * 10 = 40 (16dBi)
+Helix.pitch = 30; % --> pitch is ~ lambda/4
+Helix.mesh_res = 3;
+
+gnd.radius = lambda0/2;
+
+% feeding
+feed.heigth = 3;
+feed.R = 120; %feed impedance
+
+% size of the simulation box
+SimBox = [1 1 1.5]*2*lambda0;
+
+%% setup FDTD parameter & excitation function
+FDTD = InitFDTD( );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'PML_8'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+max_res = floor(c0 / (f0+fc) / unit / 20); % cell size: lambda/20
+CSX = InitCSX();
+
+% create helix mesh
+mesh.x = SmoothMeshLines([-Helix.radius 0 Helix.radius],Helix.mesh_res);
+% add the air-box
+mesh.x = [mesh.x -SimBox(1)/2-gnd.radius SimBox(1)/2+gnd.radius];
+% create a smooth mesh between specified fixed mesh lines
+mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4);
+
+% copy x-mesh to y-direction
+mesh.y = mesh.x;
+
+% create helix mesh in z-direction
+mesh.z = SmoothMeshLines([0 feed.heigth Helix.turns*Helix.pitch+feed.heigth],Helix.mesh_res);
+% add the air-box
+mesh.z = unique([mesh.z -SimBox(3)/2 max(mesh.z)+SimBox(3)/2 ]);
+% create a smooth mesh between specified fixed mesh lines
+mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
+
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create helix using the wire primitive
+CSX = AddMetal( CSX, 'helix' ); % create a perfect electric conductor (PEC)
+
+ang = linspace(0,2*pi,21);
+coil_x = Helix.radius*cos(ang);
+coil_y = Helix.radius*sin(ang);
+coil_z = ang/2/pi*Helix.pitch;
+
+helix.x=[];
+helix.y=[];
+helix.z=[];
+zpos = feed.heigth;
+for n=0:Helix.turns-1
+ helix.x = [helix.x coil_x];
+ helix.y = [helix.y coil_y];
+ helix.z = [helix.z coil_z+zpos];
+ zpos = zpos + Helix.pitch;
+end
+clear p
+p(1,:) = helix.x;
+p(2,:) = helix.y;
+p(3,:) = helix.z;
+CSX = AddCurve(CSX, 'helix', 0, p);
+
+%% create ground circular ground
+CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
+% add a box using cylindrical coordinates
+start = [0 0 0];
+stop = [gnd.radius 2*pi 0];
+CSX = AddBox(CSX,'gnd',10,start,stop,'CoordSystem',1);
+
+%% apply the excitation & resist as a current source
+start = [Helix.radius 0 0];
+stop = [Helix.radius 0 feed.heigth];
+[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 0 1], true);
+
+%%nf2ff calc
+start = [mesh.x(11) mesh.y(11) mesh.z(11)];
+stop = [mesh.x(end-10) mesh.y(end-10) mesh.z(end-10)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'OptResolution', lambda0/15);
+
+%% prepare simulation folder
+Sim_Path = 'tmp_Helical_Ant';
+Sim_CSX = 'Helix_Ant.xml';
+
+if (post_proc_only==0)
+ [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+ [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+ %% write openEMS compatible xml-file
+ WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+ %% show the structure
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+ %% run openEMS
+ RunOpenEMS( Sim_Path, Sim_CSX);
+end
+
+%% postprocessing & do the plots
+freq = linspace( f0-fc, f0+fc, 501 );
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+
+% plot feed point impedance
+figure
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+drawnow
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%find resonance frequncy from s11
+f_res = f0;
+
+% get accepted antenna power at frequency f0
+P_in_0 = interp1(freq, port.P_acc, f0);
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+thetaRange = unique([0:0.5:90 90:180]);
+phiRange = (0:2:360) - 180;
+disp( 'calculating the 3D far field...' );
+
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Mode',0,'Outfile','3D_Pattern.h5','Verbose',1);
+
+theta_HPBW = interp1(nf2ff.E_norm{1}(:,1)/max(nf2ff.E_norm{1}(:,1)),thetaRange,1/sqrt(2))*2;
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
+disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./P_in_0) ' %']);
+disp( ['theta_HPBW = ' num2str(theta_HPBW) ' °']);
+
+
+%%
+directivity = nf2ff.P_rad{1}/nf2ff.Prad*4*pi;
+directivity_CPRH = abs(nf2ff.E_cprh{1}).^2./max(nf2ff.E_norm{1}(:)).^2*nf2ff.Dmax;
+directivity_CPLH = abs(nf2ff.E_cplh{1}).^2./max(nf2ff.E_norm{1}(:)).^2*nf2ff.Dmax;
+
+%%
+figure
+plot(thetaRange, 10*log10(directivity(:,1)'),'k-','LineWidth',2);
+hold on
+grid on
+xlabel('theta (deg)');
+ylabel('directivity (dBi)');
+plot(thetaRange, 10*log10(directivity_CPRH(:,1)'),'g--','LineWidth',2);
+plot(thetaRange, 10*log10(directivity_CPLH(:,1)'),'r-.','LineWidth',2);
+legend('norm','CPRH','CPLH');
+
+%% dump to vtk
+DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],directivity,thetaRange,phiRange,'scale',1e-3);
+DumpFF2VTK([Sim_Path '/3D_Pattern_CPRH.vtk'],directivity_CPRH,thetaRange,phiRange,'scale',1e-3);
+DumpFF2VTK([Sim_Path '/3D_Pattern_CPLH.vtk'],directivity_CPLH,thetaRange,phiRange,'scale',1e-3);
+
diff --git a/openEMS/matlab/Tutorials/Horn_Antenna.m b/openEMS/matlab/Tutorials/Horn_Antenna.m
new file mode 100644
index 0000000..d463734
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Horn_Antenna.m
@@ -0,0 +1,202 @@
+%
+% Tutorials / horn antenna
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Horn_Antenna
+%
+% Tested with
+% - Matlab 2011a / Octave 3.6.4
+% - openEMS v0.0.31
+%
+% (C) 2011,2012,2013 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% horn width in x-direction
+horn.width = 20;
+% horn height in y-direction
+horn.height = 30;
+% horn length in z-direction
+horn.length = 50;
+
+horn.feed_length = 50;
+
+horn.thickness = 2;
+
+% horn opening angle in x, y
+horn.angle = [20 20]*pi/180;
+
+% size of the simulation box
+SimBox = [200 200 200];
+
+% frequency range of interest
+f_start = 10e9;
+f_stop = 20e9;
+
+% frequency of interest
+f0 = 15e9;
+
+%waveguide TE-mode definition
+TE_mode = 'TE10';
+a = horn.width;
+b = horn.height;
+
+%% setup FDTD parameter & excitation function
+FDTD = InitFDTD('EndCriteria', 1e-4);
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+% currently, openEMS cannot automatically generate a mesh
+max_res = c0 / (f_stop) / unit / 15; % cell size: lambda/20
+CSX = InitCSX();
+
+%create fixed lines for the simulation box, substrate and port
+mesh.x = [-SimBox(1)/2 -a/2 a/2 SimBox(1)/2];
+mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4); % create a smooth mesh between specified fixed mesh lines
+
+mesh.y = [-SimBox(2)/2 -b/2 b/2 SimBox(2)/2];
+mesh.y = SmoothMeshLines( mesh.y, max_res, 1.4 );
+
+%create fixed lines for the simulation box and given number of lines inside the substrate
+mesh.z = [-horn.feed_length 0 SimBox(3)-horn.feed_length ];
+mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
+
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create horn
+% horn feed rect waveguide
+CSX = AddMetal(CSX, 'horn');
+start = [-a/2-horn.thickness -b/2 mesh.z(1)];
+stop = [-a/2 b/2 0];
+CSX = AddBox(CSX,'horn',10,start,stop);
+start = [a/2+horn.thickness -b/2 mesh.z(1)];
+stop = [a/2 b/2 0];
+CSX = AddBox(CSX,'horn',10,start,stop);
+start = [-a/2-horn.thickness b/2+horn.thickness mesh.z(1)];
+stop = [ a/2+horn.thickness b/2 0];
+CSX = AddBox(CSX,'horn',10,start,stop);
+start = [-a/2-horn.thickness -b/2-horn.thickness mesh.z(1)];
+stop = [ a/2+horn.thickness -b/2 0];
+CSX = AddBox(CSX,'horn',10,start,stop);
+
+% horn opening
+p(2,1) = a/2;
+p(1,1) = 0;
+p(2,2) = a/2 + sin(horn.angle(1))*horn.length;
+p(1,2) = horn.length;
+p(2,3) = -a/2 - sin(horn.angle(1))*horn.length;
+p(1,3) = horn.length;
+p(2,4) = -a/2;
+p(1,4) = 0;
+CSX = AddLinPoly( CSX, 'horn', 10, 1, -horn.thickness/2, p, horn.thickness, 'Transform', {'Rotate_X',horn.angle(2),'Translate',['0,' num2str(-b/2-horn.thickness/2) ',0']});
+CSX = AddLinPoly( CSX, 'horn', 10, 1, -horn.thickness/2, p, horn.thickness, 'Transform', {'Rotate_X',-horn.angle(2),'Translate',['0,' num2str(b/2+horn.thickness/2) ',0']});
+
+p(1,1) = b/2+horn.thickness;
+p(2,1) = 0;
+p(1,2) = b/2+horn.thickness + sin(horn.angle(2))*horn.length;
+p(2,2) = horn.length;
+p(1,3) = -b/2-horn.thickness - sin(horn.angle(2))*horn.length;
+p(2,3) = horn.length;
+p(1,4) = -b/2-horn.thickness;
+p(2,4) = 0;
+CSX = AddLinPoly( CSX, 'horn', 10, 0, -horn.thickness/2, p, horn.thickness, 'Transform', {'Rotate_Y',-horn.angle(2),'Translate',[ num2str(-a/2-horn.thickness/2) ',0,0']});
+CSX = AddLinPoly( CSX, 'horn', 10, 0, -horn.thickness/2, p, horn.thickness, 'Transform', {'Rotate_Y',+horn.angle(2),'Translate',[ num2str(a/2+horn.thickness/2) ',0,0']});
+
+% horn aperture
+A = (a + 2*sin(horn.angle(1))*horn.length)*unit * (b + 2*sin(horn.angle(2))*horn.length)*unit;
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start=[-a/2 -b/2 mesh.z(8) ];
+stop =[ a/2 b/2 mesh.z(1)+horn.feed_length/2 ];
+[CSX, port] = AddRectWaveGuidePort( CSX, 0, 1, start, stop, 2, a*unit, b*unit, TE_mode, 1);
+
+%% nf2ff calc
+start = [mesh.x(9) mesh.y(9) mesh.z(9)];
+stop = [mesh.x(end-8) mesh.y(end-8) mesh.z(end-8)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'Directions', [1 1 1 1 0 1]);
+
+%% prepare simulation folder
+Sim_Path = 'tmp_Horn_Antenna';
+Sim_CSX = 'horn_ant.xml';
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS([Sim_Path '/' Sim_CSX], FDTD, CSX);
+
+%% show the structure
+CSXGeomPlot([Sim_Path '/' Sim_CSX]);
+
+%% run openEMS
+RunOpenEMS(Sim_Path, Sim_CSX);
+
+%% postprocessing & do the plots
+freq = linspace(f_start,f_stop,201);
+
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+
+plot( freq/1e9, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+ylim([-60 0]);
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / GHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+drawnow
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+thetaRange = (0:2:359) - 180;
+disp( 'calculating far field at phi=[0 90] deg...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, thetaRange*pi/180, [0 90]*pi/180);
+
+Dlog=10*log10(nf2ff.Dmax);
+G_a = 4*pi*A/(c0/f0)^2;
+e_a = nf2ff.Dmax/G_a;
+
+% display some antenna parameter
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(Dlog) ' dBi'] );
+disp( ['aperture efficiency: e_a = ' num2str(e_a*100) '%'] );
+
+%%
+% normalized directivity
+figure
+plotFFdB(nf2ff,'xaxis','theta','param',[1 2]);
+drawnow
+% D_log = 20*log10(nf2ff.E_norm{1}/max(max(nf2ff.E_norm{1})));
+% D_log = D_log + 10*log10(nf2ff.Dmax);
+% plot( nf2ff.theta, D_log(:,1) ,'k-', nf2ff.theta, D_log(:,2) ,'r-' );
+
+% polar plot
+figure
+polarFF(nf2ff,'xaxis','theta','param',[1 2],'logscale',[-40 20], 'xtics', 12);
+drawnow
+% polar( nf2ff.theta, nf2ff.E_norm{1}(:,1) )
+
+%% calculate 3D pattern
+phiRange = sort( unique( [-180:5:-100 -100:2.5:-50 -50:1:50 50:2.5:100 100:5:180] ) );
+thetaRange = sort( unique([ 0:1:50 50:2.:100 100:5:180 ]));
+
+disp( 'calculating 3D far field...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, thetaRange*pi/180, phiRange*pi/180, 'Verbose',2,'Outfile','nf2ff_3D.h5');
+
+figure
+plotFF3D(nf2ff);
+
+%%
+E_far_normalized = nf2ff.E_norm{1}/max(nf2ff.E_norm{1}(:));
+DumpFF2VTK([Sim_Path '/Horn_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,'scale',1e-3);
diff --git a/openEMS/matlab/Tutorials/MRI_LP_Birdcage.m b/openEMS/matlab/Tutorials/MRI_LP_Birdcage.m
new file mode 100644
index 0000000..2434f03
--- /dev/null
+++ b/openEMS/matlab/Tutorials/MRI_LP_Birdcage.m
@@ -0,0 +1,320 @@
+%
+% Tutorials / 3T MRI Low Pass Birdcage coil
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_MRI_LP_Birdcage
+%
+% Estimated time to run: ~7h @ ~65MC/s
+% Memory requirement (RAM): ~ 700MB
+%
+% Tested with
+% - openEMS v0.0.33
+% - Matlab 7.12.0 (R2011a)
+%
+% (C) 2013-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+
+close all
+clear
+clc
+
+% simulation setup
+f0 = 128e6;
+excite.f_0 = 75e6; % excite gaussian pulse center frequency
+excite.f_c = 75e6; % excite gaussian pulse cutoff frequency
+
+postproc_only = 0; % set to 1 to perform only post processing
+GeomPlot = 1; % set to 0 to skip geometry viewer
+
+% bore setup
+Bore.rad = 320;
+Bore.length = 1600;
+
+% birdcage setup
+BC.N_rungs = 8;
+BC.rad = 120;
+BC.stripwidth = 10;
+BC.portwidth = BC.stripwidth/2;
+BC.portlength = BC.stripwidth/2;
+BC.length = 250;
+BC.cap = 2.6e-12;
+
+% feed amplitude and phase at given rungs
+BC.feed_pos = [1 3];
+BC.feed_amp = [1 -1j];
+
+%% define the human body model (virtual family)
+% set file name for human body model to create with "Convert_VF_DiscMaterial"
+% the file name should contain a full path
+body_model_file = [pwd '/Ella_centered_' num2str(f0/1e6) 'MHz.h5'];
+
+% convert only part of the model (head/shoulder section)
+body_model_range = {[],[],[-0.85 0]};
+
+body_mesh_res = 2.5; % should be something like: BC.stripwidth/4
+
+% paths to virtual family voxel models (VFVM), adept to your install!
+VF_raw_filesuffix = '/tmp/Ella_26y_V2_1mm';
+VF_mat_db_file = '/tmp/DB_h5_20120711_SEMCADv14.8.h5';
+
+% delete(body_model_file); % uncomment to delete old model if something changed
+
+% convert model (if it does not exist)
+Convert_VF_DiscMaterial(VF_raw_filesuffix, VF_mat_db_file, body_model_file, ...
+ 'Frequency', f0, 'Center', 1, ...
+ 'Range', body_model_range);
+
+% rotate model to face the nose in +y-dir, and translate
+body_model_transform = {'Rotate_X',pi,'Rotate_Z',pi, ...
+ 'Translate',[0,5,-720]};
+
+%% some internal parameter
+physical_constants % load important physical constans
+end_crit = 1e-5; %abort simulation at -50dB energy drop
+unit = 1e-3; %drawing unit used
+
+%capacity footprint is 4mm x 4mm
+lambda_min = c0/(excite.f_0+excite.f_c);
+
+% meshing options
+% desired mesh resolution
+mesh_res([1 3]) = min(15,lambda_min/20/unit);
+mesh_res(2) = body_mesh_res / BC.rad;
+
+%% setup FDTD parameter & excitation function
+FDTD = InitFDTD('CoordSystem', 1, ... %init a cylindrical FDTD setup
+ 'EndCriteria', 1e-4, ... % with an end criteria of -40dB (1e-4)
+ 'MultiGrid', '10,20',... % add two cylindrical sub-grids at a radius of 10 and 20 mm
+ 'CellConstantMaterial', 1); % assume a material is constant inside
+ % a cell (material probing in cell center)
+
+% define the excitation time-signal (unmodulated gaussian pulse)
+FDTD = SetGaussExcite(FDTD,excite.f_0,excite.f_c);
+
+% define & set boundary conditions
+% - pml in +/- z-direction
+% - boundaries in -r and +/- alpha direction disabled (full cylindrical mesh)
+% - PEC boundary in +r-direction to model bore RF shield
+FDTD = SetBoundaryCond(FDTD, [0 0 0 0 3 3]);
+
+
+%% setup CSXCAD geometry & mesh (cylindrical)
+CSX = InitCSX('CoordSystem',1);
+
+% init empty mesh structure
+mesh.r = [];
+mesh.a = [];
+mesh.z = [];
+
+%% Create metal bird cage and rung capacities
+CSX = AddMetal(CSX,'metal');
+CSX = AddLumpedElement(CSX,'caps','z','C',BC.cap);
+
+da_Strip = BC.stripwidth/BC.rad; % width of a strip in radiant
+da_Caps = BC.portwidth/BC.rad; % width of a cap/port in radiant
+da_Segs = 2*pi/BC.N_rungs; % width of a rung in radiant
+
+a_start = -pi-da_Segs/2; % starting angle
+
+w0 = 2*pi*f0;
+T0 = 1/f0;
+
+% port counter
+port_Nr = 1;
+
+a0 = a_start;
+
+for n=1:BC.N_rungs
+ start = [BC.rad a0+da_Segs/2-da_Caps/2 -0.5*BC.portlength];
+ stop = [BC.rad a0+da_Segs/2+da_Caps/2 +0.5*BC.portlength];
+ CSX = AddBox(CSX,'caps',1, start, stop);
+
+ start = [BC.rad a0+da_Segs/2-da_Caps/2 0.5*BC.length-BC.stripwidth/2-BC.portlength];
+ stop = [BC.rad a0+da_Segs/2+da_Caps/2 0.5*BC.length-BC.stripwidth/2];
+ if (~isempty(intersect(n, BC.feed_pos)) && (BC.feed_amp(port_Nr)~=0)) % active port
+ exc_amp = abs(BC.feed_amp(port_Nr));
+
+ % calculate time delay to achieve a given phase shift at f0
+ T = -angle(BC.feed_amp(port_Nr)) / w0;
+ if T<0
+ T = T + T0;
+ end
+ [CSX port{port_Nr}] = AddLumpedPort(CSX, 100, port_Nr, 50, start, stop, [0 0 1]*exc_amp, true,'Delay',T);
+
+ %increase port count
+ port_Nr = port_Nr+1;
+
+ start = [BC.rad a0+da_Segs/2-da_Strip/2 0.5*BC.length-BC.stripwidth/2-BC.portlength];
+ elseif ~isempty(intersect(n, BC.feed_pos)) % passive port
+ [CSX port{port_Nr}] = AddLumpedPort(CSX, 100, port_Nr, 50, start, stop, [0 0 1], false);
+
+ %increase port count
+ port_Nr = port_Nr+1;
+
+ start = [BC.rad a0+da_Segs/2-da_Strip/2 0.5*BC.length-BC.stripwidth/2-BC.portlength];
+ else
+ start = [BC.rad a0+da_Segs/2-da_Strip/2 0.5*BC.length];
+ end
+
+ % the start z-coordinate depends on the port (see above)
+ stop = [BC.rad a0+da_Segs/2+da_Strip/2 0.5*BC.portlength];
+ CSX = AddBox(CSX,'metal',1, start, stop);
+
+ start = [BC.rad a0+da_Segs/2-da_Strip/2 -0.5*BC.length];
+ stop = [BC.rad a0+da_Segs/2+da_Strip/2 -0.5*BC.portlength];
+ CSX = AddBox(CSX,'metal',1, start, stop);
+
+ % some additonal mesh lines
+ mesh.a = [mesh.a a0+da_Segs/2];
+
+ a0 = a0 + da_Segs;
+end
+
+% create metal top ring
+start = [BC.rad a_start -(BC.length-BC.stripwidth)/2];
+stop = [BC.rad a_start+2*pi -(BC.length+BC.stripwidth)/2];
+CSX = AddBox(CSX,'metal',1, start, stop);
+
+% create metal bottom ring
+start = [BC.rad a_start (BC.length-BC.stripwidth)/2];
+stop = [BC.rad a_start+2*pi (BC.length+BC.stripwidth)/2];
+CSX = AddBox(CSX,'metal',1, start, stop);
+
+%% create smooth mesh
+mesh = DetectEdges(CSX, mesh);
+mesh.r = [0 SmoothMeshLines([body_mesh_res*1.5 mesh.r], body_mesh_res)];
+mesh.z = SmoothMeshLines(mesh.z, body_mesh_res);
+
+mesh.r = [mesh.r Bore.rad]; %mesh lines in radial direction
+mesh.z = [-Bore.length/2 mesh.z Bore.length/2]; %mesh lines in z-direction
+
+mesh = SmoothMesh(mesh, mesh_res, 1.5);
+
+%% check the cell limit
+numCells = numel(mesh.r)*numel(mesh.a)*numel(mesh.z);
+
+%% define human body model
+CSX = AddDiscMaterial(CSX, 'body_model', 'File', body_model_file, 'Scale', 1/unit, 'Transform', body_model_transform);
+start = [mesh.r(1) mesh.a(1) mesh.z(1)];
+stop = [mesh.r(end) mesh.a(end) mesh.z(end)];
+CSX = AddBox(CSX, 'body_model', 0, start, stop);
+
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start = [0 mesh.a(1) -BC.length/2];
+stop = [BC.rad mesh.a(end) +BC.length/2];
+
+CSX = AddDump(CSX,'Ef','FileType',1,'DumpType',10,'DumpMode',2,'Frequency',f0);
+CSX = AddBox(CSX,'Ef',0 , start,stop);
+
+CSX = AddDump(CSX,'Hf','FileType',1,'DumpType',11,'DumpMode',2,'Frequency',f0);
+CSX = AddBox(CSX,'Hf',0 , start,stop);
+
+CSX = AddDump(CSX,'SAR','FileType',1,'DumpType',20,'DumpMode',2,'Frequency',f0);
+CSX = AddBox(CSX,'SAR',0 , start,stop);
+
+start = [0 mesh.a(1) 0];
+stop = [BC.rad mesh.a(end) 0];
+CSX = AddDump(CSX,'Ht','FileType',1,'DumpType',1,'DumpMode',2);
+CSX = AddBox(CSX,'Ht',0 , start,stop);
+
+%% finalize mesh
+% add some lines for the pml in +/- z- direction
+mesh = AddPML(mesh, [0 0 0 0 10 10], 1);
+
+% define the mesh
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%% Write file & run openEMS
+Sim_Path = ['tmp_' mfilename];
+
+if (postproc_only==0)
+ [status, message, messageid] = rmdir(Sim_Path,'s'); %delete old results
+ [status, message, messageid] = mkdir(Sim_Path); %create folder
+
+ WriteOpenEMS([Sim_Path '/BirdCage.xml'],FDTD,CSX);
+end
+
+if (GeomPlot==1)
+ CSXGeomPlot( [Sim_Path '/BirdCage.xml'] , ['--export-polydata-vtk=' Sim_Path ' --RenderDiscMaterial -v']);
+end
+
+if (postproc_only==0)
+ RunOpenEMS(Sim_Path, 'BirdCage.xml');
+end
+
+%%
+freq = linspace(excite.f_0-excite.f_c,excite.f_0+excite.f_c,201);
+port = calcPort(port, Sim_Path, freq);
+
+close all
+s11 = port{1}.uf.ref./port{1}.uf.inc;
+s22 = port{2}.uf.ref./port{2}.uf.inc;
+
+% the s-parameter may be larger than 1 (0dB) since all ports are excited
+% and do not have a perfect port isolation
+plot(freq*1e-6,20*log10(abs(s11)),'Linewidth',2)
+hold on
+grid on
+plot(freq*1e-6,20*log10(abs(s22)),'r--','Linewidth',2)
+legend('s11','s22');
+
+%% read SAR values on a xy-plane (range)
+[SAR SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR.h5'],'Range',{[],[],0},'CloseAlpha',1);
+SAR = SAR.FD.values{1};
+
+% SAR plot
+figure()
+[R A] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{2});
+X = R.*cos(A);Y = R.*sin(A);
+colormap('hot');
+h = pcolor(X,Y,(squeeze(SAR)));
+% h = pcolor(X,Y,log10(squeeze(SAR)));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('y -->');
+title('local SAR');
+axis equal tight
+
+%% plot B1+/- on an xy-plane
+[H_field H_mesh] = ReadHDF5Dump([Sim_Path '/Hf.h5'],'Range',{[0 0.1],[],0},'CloseAlpha',1);
+% create a 2D grid to plot on
+[R A] = ndgrid(H_mesh.lines{1},H_mesh.lines{2});
+X = R.*cos(A);
+Y = R.*sin(A);
+
+% calc Bx,By (from Br and Ba), B1p, B1m
+Bx = MUE0*(H_field.FD.values{1}(:,:,:,1).*cos(A) - H_field.FD.values{1}(:,:,:,2).*sin(A));
+By = MUE0*(H_field.FD.values{1}(:,:,:,1).*sin(A) + H_field.FD.values{1}(:,:,:,2).*cos(A));
+B1p = 0.5*(Bx+1j*By);
+B1m = 0.5*(Bx-1j*By);
+
+Dump2VTK([Sim_Path '/B1p_xy.vtk'], abs(B1p), H_mesh, 'B-Field');
+Dump2VTK([Sim_Path '/B1m_xy.vtk'], abs(B1m), H_mesh, 'B-Field');
+
+maxB1 = max([abs(B1p(:)); abs(B1m(:))]);
+
+% B1+ plot
+figure()
+subplot(1,2,1);
+h = pcolor(X,Y,abs(B1p));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('y -->');
+title('B_1^+ field (dB)');
+caxis([0 maxB1]);
+axis equal tight
+
+% B1- plot
+subplot(1,2,2);
+h = pcolor(X,Y,abs(B1m));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('y -->');
+title('B_1^- field (dB)');
+caxis([0 maxB1]);
+axis equal tight
+
+%%
+ConvertHDF5_VTK([Sim_Path '/Hf.h5'],[Sim_Path '/Hf_xy'],'Range',{[],[],0},'CloseAlpha',1)
+ConvertHDF5_VTK([Sim_Path '/SAR.h5'],[Sim_Path '/SAR_xy'],'Range',{[],[],0},'CloseAlpha',1)
diff --git a/openEMS/matlab/Tutorials/MRI_Loop_Coil.m b/openEMS/matlab/Tutorials/MRI_Loop_Coil.m
new file mode 100644
index 0000000..088f8f3
--- /dev/null
+++ b/openEMS/matlab/Tutorials/MRI_Loop_Coil.m
@@ -0,0 +1,334 @@
+%
+% Tutorials / 7T MRI Loop Coil
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_MRI_Loop_Coil
+%
+% Tested with
+% - openEMS v0.0.33
+% - Matlab 7.12.0 (R2011a)
+%
+% (C) 2013-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants; %get some physical constants like c0 and MUE0
+unit = 1e-3; % all length in mm
+
+% Loop-Coil parameter
+loop.length = 80; % length of the loop (in z-direction)
+loop.width = 60; % width of the loop (in y-direction)
+loop.strip_width = 5; % metal strip width
+loop.strip_N_cells = 3; % number of cells over the strip length
+loop.air_gap = loop.strip_width/3; % air gap width for lumped capacitors
+loop.pos_x = -130; % position of loop
+loop.C_gap = 5.4e-12; % lumped cap value
+loop.port_R = 10; % feeding port resistance
+
+%% define the human body model (virtual family)
+% set file name for human body model to create with "Convert_VF_DiscMaterial"
+% the file name should contain a full path
+body_model_file = [pwd '/Ella_centered_298MHz.h5'];
+
+% convert only part of the model (head/shoulder section)
+body_model_range = {[],[],[-0.85 -0.4]};
+
+% paths to virtual family voxel models (VFVM), adept to your install!
+VF_raw_filesuffix = '/tmp/Ella_26y_V2_1mm';
+VF_mat_db_file = '/tmp/DB_h5_20120711_SEMCADv14.8.h5';
+
+% delete(body_model_file); % uncomment to delete old model if something changed
+
+% convert model (if it does not exist)
+Convert_VF_DiscMaterial(VF_raw_filesuffix, VF_mat_db_file, body_model_file, ...
+ 'Frequency', 298e6, 'Center', 1, ...
+ 'Range', body_model_range);
+
+% rotate model to face the nose in x-dir, and translate
+body_model_transform = {'Rotate_X',pi,'Rotate_Z',pi/2, ...
+ 'Translate',[0,5,-720]};
+
+% the head should + part of shoulder should fit this box
+body_box.start = [-120 -150 -200];
+body_box.stop = [+100 +150 +130];
+
+% box with high res mesh
+mesh_box.start = [-120 -80 -120];
+mesh_box.stop = [+100 +80 +120];
+mesh_box.resolution = 2;
+
+%% some mesh parameter
+Air_Box = 150; % size of the surrounding air box (150mm)
+
+%% setup FDTD parameter & excitation function
+% init FDTD structure
+FDTD = InitFDTD( 'EndCriteria', 1e-4, 'CellConstantMaterial', 0);
+
+% define gaussian pulse excitation signal
+f0 = 298e6; % center frequency
+fc = 300e6; % 20 dB corner frequency
+FDTD = SetGaussExcite( FDTD, f0, fc );
+
+% setup boundary conditions
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+CSX = InitCSX();
+
+%% create loop
+% setup all properties needed
+CSX = AddMetal( CSX, 'loop' );
+CSX = AddLumpedElement( CSX, 'caps_y', 1, 'C', loop.C_gap);
+CSX = AddLumpedElement( CSX, 'caps_z', 2, 'C', loop.C_gap);
+
+% horizontal (y-direction) strips
+start = [loop.pos_x -loop.width/2 -loop.length/2];
+stop = [loop.pos_x -loop.air_gap/2 -loop.length/2+loop.strip_width];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+start = [loop.pos_x -loop.width/2 loop.length/2 ];
+stop = [loop.pos_x -loop.air_gap/2 loop.length/2-loop.strip_width];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+start = [loop.pos_x loop.width/2 -loop.length/2];
+stop = [loop.pos_x loop.air_gap/2 -loop.length/2+loop.strip_width];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+start = [loop.pos_x loop.width/2 loop.length/2 ];
+stop = [loop.pos_x loop.air_gap/2 loop.length/2-loop.strip_width];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+% vertical (z-direction) strips
+start = [loop.pos_x -loop.width/2 -loop.length/2+loop.strip_width];
+stop = [loop.pos_x -loop.width/2+loop.strip_width -loop.air_gap/2];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+start = [loop.pos_x -loop.width/2 loop.length/2-loop.strip_width];
+stop = [loop.pos_x -loop.width/2+loop.strip_width loop.air_gap/2];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+start = [loop.pos_x loop.width/2 -loop.length/2+loop.strip_width];
+stop = [loop.pos_x loop.width/2-loop.strip_width -loop.air_gap/2];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+start = [loop.pos_x loop.width/2 loop.length/2-loop.strip_width ];
+stop = [loop.pos_x loop.width/2-loop.strip_width loop.air_gap/2];
+CSX = AddBox(CSX,'loop',10,start,stop);
+
+% add the lumped capacities
+start = [loop.pos_x -loop.width/2+loop.strip_width/2-loop.air_gap/2 -loop.air_gap/2];
+stop = [loop.pos_x -loop.width/2+loop.strip_width/2+loop.air_gap/2 +loop.air_gap/2];
+CSX = AddBox(CSX,'caps_z',10,start,stop);
+
+start = [loop.pos_x loop.width/2-loop.strip_width/2-loop.air_gap/2 -loop.air_gap/2];
+stop = [loop.pos_x loop.width/2-loop.strip_width/2+loop.air_gap/2 +loop.air_gap/2];
+CSX = AddBox(CSX,'caps_z',10,start,stop);
+
+start = [loop.pos_x -loop.air_gap/2 loop.length/2-loop.strip_width/2-loop.air_gap/2];
+stop = [loop.pos_x +loop.air_gap/2 loop.length/2-loop.strip_width/2+loop.air_gap/2];
+CSX = AddBox(CSX,'caps_y',10,start,stop);
+
+% add a lumped port as excitation
+start = [loop.pos_x -loop.air_gap/2 -loop.length/2+loop.strip_width/2-loop.air_gap/2];
+stop = [loop.pos_x +loop.air_gap/2 -loop.length/2+loop.strip_width/2+loop.air_gap/2];
+[CSX port] = AddLumpedPort(CSX, 100, 1, loop.port_R, start, stop, [0 1 0], true);
+
+%% define human body model
+CSX = AddDiscMaterial(CSX, 'body_model', 'File', body_model_file, 'Scale', 1/unit, 'Transform', body_model_transform);
+CSX = AddBox(CSX, 'body_model', 0, body_box.start, body_box.stop);
+
+%% finalize mesh
+% create loop mesh
+mesh = DetectEdges(CSX);
+
+% add a dense homegeneous mesh inside the human body model
+mesh.x = [mesh.x mesh_box.start(1) mesh_box.stop(1)];
+mesh.y = [mesh.y mesh_box.start(2) mesh_box.stop(2)];
+mesh.z = [mesh.z mesh_box.start(3) mesh_box.stop(3)];
+
+% add lines in x-dir for the loop and a cell centered around 0
+mesh.x = [mesh.x loop.pos_x -mesh_box.resolution/2 mesh_box.resolution/2];
+
+% smooth the mesh for the loop & body
+mesh = SmoothMesh(mesh, mesh_box.resolution);
+
+% add air spacer
+mesh.x = [-Air_Box+mesh.x(1) mesh.x mesh.x(end)+Air_Box];
+mesh.y = [-Air_Box+mesh.y(1) mesh.y mesh.y(end)+Air_Box];
+mesh.z = [-Air_Box+mesh.z(1) mesh.z mesh.z(end)+Air_Box];
+
+mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 10, 1.5, 'algorithm', 1);
+
+%% Add Dump boxes (2D boxes) for H and SAR on xy- and xz-plane
+CSX = AddDump(CSX,'Hf_xy','DumpType',11,'FileType',1,'Frequency',f0);
+CSX = AddBox(CSX,'Hf_xy',0, body_box.start.*[1 1 0], body_box.stop.*[1 1 0]);
+CSX = AddDump(CSX,'SAR_xy','DumpType',20,'DumpMode',2,'FileType',1,'Frequency',f0);
+CSX = AddBox(CSX,'SAR_xy',0, body_box.start.*[1 1 0], body_box.stop.*[1 1 0]);
+
+CSX = AddDump(CSX,'Hf_xz','DumpType',11,'FileType',1,'Frequency',f0);
+CSX = AddBox(CSX,'Hf_xz',0, body_box.start.*[1 0 1], body_box.stop.*[1 0 1]);
+CSX = AddDump(CSX,'SAR_xz','DumpType',20,'DumpMode',2,'FileType',1,'Frequency',f0);
+CSX = AddBox(CSX,'SAR_xz',0, body_box.start.*[1 0 1], body_box.stop.*[1 0 1]);
+
+%% add 10 lines in all direction to make space for PML or MUR absorbing
+%% boundary conditions
+mesh = AddPML(mesh, 10);
+
+%% finaly define the FDTD mesh grid
+disp(['number of cells: ' num2str(1e-6*numel(mesh.x)*numel(mesh.y)*numel(mesh.z)) ' Mcells'])
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% prepare simulation folder
+Sim_Path = ['tmp_' mfilename];
+Sim_CSX = [mfilename '.xml'];
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure and export as vtk data automatically
+CSXGeomPlot( [Sim_Path '/' Sim_CSX] , ['--export-polydata-vtk=' Sim_Path ' --RenderDiscMaterial -v']);
+
+%% run openEMS
+RunOpenEMS( Sim_Path, Sim_CSX);
+
+%% postprocessing & do the plots
+freq = linspace( f0-fc, f0+fc, 501 );
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+
+% get the feeding power for frequency f0
+P0_in = interp1(freq, port.P_acc, f0);
+
+%%
+% plot reflection coefficient S11
+figure
+h = plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}| (dB)' );
+
+% plot feed point admittance
+figure
+h = plot( freq/1e6, real(1./Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(1./Zin), 'r--', 'Linewidth', 2 );
+title( 'feed port admittance' );
+xlabel( 'frequency f (MHz)' );
+ylabel( 'admittance Y_{in} (S)' );
+legend( 'real', 'imag' );
+
+%% read SAR values on a xy-plane (range)
+[SAR SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR_xy.h5']);
+SAR = SAR.FD.values{1}/P0_in;
+
+% SAR plot
+figure()
+subplot(1,2,1);
+[X Y] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{2});
+colormap('hot');
+h = pcolor(X,Y,(squeeze(SAR)));
+% h = pcolor(X,Y,log10(squeeze(SAR)));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('y -->');
+title('local SAR');
+axis equal tight
+
+%% read SAR values on a xz-plane (range)
+[SAR SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR_xz.h5']);
+SAR = SAR.FD.values{1}/P0_in;
+
+% SAR plot
+subplot(1,2,2);
+[X Z] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{3});
+colormap('hot');
+h = pcolor(X,Z,(squeeze(SAR)));
+% h = pcolor(X,Y,log10(squeeze(SAR)));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('z -->');
+title('local SAR');
+axis equal tight
+
+%% plot B1+/- on an xy-plane
+[H_field H_mesh] = ReadHDF5Dump([Sim_Path '/Hf_xy.h5']);
+% calc Bx,By, B1p, B1m normalize to the input-power
+Bx = MUE0*H_field.FD.values{1}(:,:,:,1)/sqrt(P0_in);
+By = MUE0*H_field.FD.values{1}(:,:,:,2)/sqrt(P0_in);
+B1p = 0.5*(Bx+1j*By);
+B1m = 0.5*(Bx-1j*By);
+% create a 2D grid to plot on
+[X Y] = ndgrid(H_mesh.lines{1},H_mesh.lines{2});
+
+Dump2VTK([Sim_Path '/B1p_xy.vtk'], abs(B1p), H_mesh, 'B-Field');
+Dump2VTK([Sim_Path '/B1m_xy.vtk'], abs(B1m), H_mesh, 'B-Field');
+
+% B1+ plot
+figure()
+subplot(1,2,1);
+h = pcolor(X,Y,log10(abs(B1p)));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('y -->');
+title('B_1^+ field (dB)');
+axis equal tight
+
+% B1- plot
+subplot(1,2,2);
+h = pcolor(X,Y,log10(abs(B1m)));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('y -->');
+title('B_1^- field (dB)');
+axis equal tight
+
+%% plot B1+/- on an xz-plane
+[H_field H_mesh] = ReadHDF5Dump([Sim_Path '/Hf_xz.h5']);
+% calc Bx,By, B1p, B1m normalize to the input-power
+Bx = MUE0*H_field.FD.values{1}(:,:,:,1)/sqrt(P0_in);
+By = MUE0*H_field.FD.values{1}(:,:,:,2)/sqrt(P0_in);
+B1p = 0.5*(Bx+1j*By);
+B1m = 0.5*(Bx-1j*By);
+% create a 2D grid to plot on
+[X Z] = ndgrid(H_mesh.lines{1},H_mesh.lines{3});
+
+Dump2VTK([Sim_Path '/B1p_xz.vtk'], abs(B1p), H_mesh, 'B-Field');
+Dump2VTK([Sim_Path '/B1m_xz.vtk'], abs(B1m), H_mesh, 'B-Field');
+
+% B1+ plot
+figure()
+subplot(1,2,1);
+h = pcolor(X,Z,log10(squeeze(abs(B1p))));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('z -->');
+title('B_1^+ field (dB)');
+axis equal tight
+
+% B1- plot
+subplot(1,2,2);
+h = pcolor(X,Z,log10(squeeze(abs(B1m))));
+set(h,'EdgeColor','none');
+xlabel('x -->');
+ylabel('z -->');
+title('B_1^- field (dB)');
+axis equal tight
+
+%% dump to vtk to view in Paraview
+ConvertHDF5_VTK([Sim_Path '/SAR_xy.h5'],[Sim_Path '/SAR_xy'], 'weight', 1/P0_in, 'FieldName', 'SAR');
+ConvertHDF5_VTK([Sim_Path '/SAR_xz.h5'],[Sim_Path '/SAR_xz'], 'weight', 1/P0_in, 'FieldName', 'SAR');
+
+%%
+ConvertHDF5_VTK([Sim_Path '/Hf_xy.h5'],[Sim_Path '/B1_xy'], 'weight', MUE0/sqrt(P0_in), 'FieldName', 'B1-field');
+ConvertHDF5_VTK([Sim_Path '/Hf_xz.h5'],[Sim_Path '/B1_xz'], 'weight', MUE0/sqrt(P0_in), 'FieldName', 'B1-field');
diff --git a/openEMS/matlab/Tutorials/MSL_NotchFilter.m b/openEMS/matlab/Tutorials/MSL_NotchFilter.m
new file mode 100644
index 0000000..612456c
--- /dev/null
+++ b/openEMS/matlab/Tutorials/MSL_NotchFilter.m
@@ -0,0 +1,92 @@
+%
+% Tutorials / MSL_NotchFilter
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Microstrip_Notch_Filter
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2011-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; % specify everything in um
+MSL_length = 50000;
+MSL_width = 600;
+substrate_thickness = 254;
+substrate_epr = 3.66;
+stub_length = 12e3;
+f_max = 7e9;
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD();
+FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 );
+BC = {'PML_8' 'PML_8' 'MUR' 'MUR' 'PEC' '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( [0 MSL_width/2+[2*resolution/3 -resolution/3]/4], resolution/4, 1.5 ,0 );
+mesh.x = SmoothMeshLines( [-MSL_length -mesh.x mesh.x MSL_length], resolution, 1.5 ,0 );
+mesh.y = SmoothMeshLines( [0 MSL_width/2+[-resolution/3 +resolution/3*2]/4], resolution/4 , 1.5 ,0);
+mesh.y = SmoothMeshLines( [-15*MSL_width -mesh.y mesh.y stub_length+[-resolution/3 +resolution/3*2]/4 15*MSL_width+stub_length], resolution, 1.3 ,0);
+mesh.z = SmoothMeshLines( [linspace(0,substrate_thickness,5) 10*substrate_thickness], resolution );
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% substrate
+CSX = AddMaterial( CSX, 'RO4350B' );
+CSX = SetMaterialProperty( CSX, 'RO4350B', 'Epsilon', substrate_epr );
+start = [mesh.x(1), mesh.y(1), 0];
+stop = [mesh.x(end), mesh.y(end), substrate_thickness];
+CSX = AddBox( CSX, 'RO4350B', 0, start, stop );
+
+%% MSL port
+CSX = AddMetal( CSX, 'PEC' );
+portstart = [ mesh.x(1), -MSL_width/2, substrate_thickness];
+portstop = [ 0, MSL_width/2, 0];
+[CSX,port{1}] = AddMSLPort( CSX, 999, 1, 'PEC', portstart, portstop, 0, [0 0 -1], 'ExcitePort', true, 'FeedShift', 10*resolution, 'MeasPlaneShift', MSL_length/3);
+
+portstart = [mesh.x(end), -MSL_width/2, substrate_thickness];
+portstop = [0 , MSL_width/2, 0];
+[CSX,port{2}] = AddMSLPort( CSX, 999, 2, 'PEC', portstart, portstop, 0, [0 0 -1], 'MeasPlaneShift', MSL_length/3 );
+
+%% Filter-stub
+start = [-MSL_width/2, MSL_width/2, substrate_thickness];
+stop = [ MSL_width/2, MSL_width/2+stub_length, substrate_thickness];
+CSX = AddBox( CSX, 'PEC', 999, start, stop );
+
+%% write/show/run the openEMS compatible xml-file
+Sim_Path = 'tmp';
+Sim_CSX = 'msl.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([-40 2]);
+
diff --git a/openEMS/matlab/Tutorials/Parallel_Plate_Waveguide.m b/openEMS/matlab/Tutorials/Parallel_Plate_Waveguide.m
new file mode 100644
index 0000000..cbf76c0
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Parallel_Plate_Waveguide.m
@@ -0,0 +1,51 @@
+%
+% Tutorials / Parallel_Plate_Waveguide
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Parallel_Plate_Waveguide
+%
+% Tested with
+% - Matlab 2011a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2011,2012 Sebastian Held <sebastian.held@gmx.de>
+% (C) 2011-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+% init and define FDTD parameter
+FDTD = InitFDTD(100,0,'OverSampling',50);
+FDTD = SetSinusExcite(FDTD,10e6);
+BC = {'PMC' 'PMC' 'PEC' 'PEC' 'MUR' 'MUR'};
+FDTD = SetBoundaryCond(FDTD,BC);
+
+% init and define FDTD mesh
+CSX = InitCSX();
+mesh.x = -10:10;
+mesh.y = -10:10;
+mesh.z = -10:30;
+CSX = DefineRectGrid(CSX, 1, mesh);
+
+% define the excitation
+CSX = AddExcitation(CSX,'excitation',0,[0 1 0]);
+CSX = AddBox(CSX,'excitation',0,[-10 -10 0],[10 10 0]);
+
+% define a time domain e-field dump box
+CSX = AddDump(CSX,'Et','DumpMode',0);
+CSX = AddBox(CSX,'Et',0,[-10 0 -10],[10 0 30]);
+
+% remove old simulation results (if exist)
+rmdir('tmp','s');mkdir('tmp');
+
+% write openEMS xml data file
+WriteOpenEMS('tmp/tmp.xml',FDTD,CSX);
+
+% view defined structure
+CSXGeomPlot( 'tmp/tmp.xml' );
+
+% run openEMS simulation
+RunOpenEMS('tmp','tmp.xml','');
+
+disp('use Paraview to visualize the FDTD result...');
diff --git a/openEMS/matlab/Tutorials/Patch_Antenna_Array.m b/openEMS/matlab/Tutorials/Patch_Antenna_Array.m
new file mode 100644
index 0000000..ed12c67
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Patch_Antenna_Array.m
@@ -0,0 +1,170 @@
+function [port nf2ff] = Patch_Antenna_Array(Sim_Path, postproc_only, show_structure, xpos, caps, resist, active )
+% [port nf2ff] = Patch_Antenna_Array(Sim_Path, postproc_only, show_structure, xpos, caps, resist, active )
+%
+% Script to setup the patch array as described in [1].
+% Run main script in Patch_Antenna_Phased_Array.m instead!
+%
+% Sim_Path: Simulation path
+% postproc_only: set to post process only 0/1
+% show_structure: show the strucuture in AppCSXCAD 0/1
+% xpos: the x-position for each antenna is defined
+% caps: the port capacity (will override active port)
+% resist: port resitance
+% active: switch port active
+%
+% References:
+% [1] Y. Yusuf and X. Gong, “A low-cost patch antenna phased array with
+% analog beam steering using mutual coupling and reactive loading,” IEEE
+% Antennas Wireless Propag. Lett., vol. 7, pp. 81–84, 2008.
+%
+% Tested with
+% - Matlab 2011a
+% - openEMS v0.0.31
+%
+% (C) 2013 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+% example
+% xpos = [-41 0 41];
+% caps = [0.2e-12 0 0.2e-12];
+% active = [0 1 0];
+% resist = [50 50 50];
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% patch geometry setup
+patch.W = 35; % width
+patch.L = 28.3; % length
+patch.Ws = 3.8; % width of feeding stub
+patch.Gs = 1; % width of feeding gab
+patch.l = 6; % length of feeding stub
+patch.y0 = 10; % depth of feeding stub into into patch
+
+% patch resonance frequency
+f0 = 3e9;
+
+%substrate setup
+substrate.name = 'Ro3003';
+substrate.epsR = 3;
+substrate.kappa = 0.0013 * 2*pi*f0 * EPS0*substrate.epsR;
+substrate.thickness = 1.524;
+substrate.cells = 4;
+
+substrate.width = patch.W + max(xpos) - min(xpos) + 4*patch.l;
+substrate.length = 3*patch.l + patch.L;
+
+% size of the simulation box
+AirSpacer = [50 50 30];
+
+edge_res = [-1/3 2/3]*1;
+
+%% setup FDTD parameter & excitation function
+fc = 2e9; % 20 dB corner frequency
+FDTD = InitFDTD( 'EndCriteria', 1e-4 );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = [1 1 1 1 1 1]*3;
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+CSX = InitCSX();
+
+mesh.x = [];
+mesh.y = [];
+mesh.z = [];
+
+%% create patch
+CSX = AddMetal( CSX, 'patch' ); % create a perfect electric conductor (PEC)
+
+for port_nr=1:numel(xpos)
+ start = [xpos(port_nr)-patch.W/2 patch.l substrate.thickness];
+ stop = [xpos(port_nr)-patch.Ws/2-patch.Gs patch.l+patch.L substrate.thickness];
+ CSX = AddBox(CSX,'patch',10, start, stop);
+ mesh.x = [mesh.x xpos(port_nr)-patch.W/2-edge_res];
+
+ start = [xpos(port_nr)+patch.W/2 patch.l substrate.thickness];
+ stop = [xpos(port_nr)+patch.Ws/2+patch.Gs patch.l+patch.L substrate.thickness];
+ CSX = AddBox(CSX,'patch',10, start, stop);
+ mesh.x = [mesh.x xpos(port_nr)+patch.W/2+edge_res];
+
+ mesh.y = [mesh.y patch.l-edge_res patch.l+patch.L+edge_res];
+
+ start = [xpos(port_nr)-patch.Ws/2-patch.Gs patch.l+patch.y0 substrate.thickness];
+ stop = [xpos(port_nr)+patch.Ws/2+patch.Gs patch.l+patch.L substrate.thickness];
+ CSX = AddBox(CSX,'patch',10, start, stop);
+
+ % feed line
+ start = [xpos(port_nr)-patch.Ws/2 patch.l+patch.y0 substrate.thickness];
+ stop = [xpos(port_nr)+patch.Ws/2 0 substrate.thickness];
+ CSX = AddBox(CSX,'patch',10, start, stop);
+
+ mesh.x = [mesh.x xpos(port_nr)+linspace(-patch.Ws/2-patch.Gs,-patch.Ws/2,3) xpos(port_nr)+linspace(patch.Ws/2,patch.Ws/2+patch.Gs,3)];
+
+ start = [xpos(port_nr)-patch.Ws/2 0 0];
+ stop = [xpos(port_nr)+patch.Ws/2 0 substrate.thickness];
+ if (caps(port_nr)>0)
+ CSX = AddLumpedElement(CSX, ['C_' num2str(port_nr)], 2, 'C', caps(port_nr));
+ CSX = AddBox(CSX,['C_' num2str(port_nr)],10, start, stop);
+
+ [CSX port{port_nr}] = AddLumpedPort(CSX, 5 ,port_nr ,inf, start, stop, [0 0 1], 0);
+ else
+ % feed port
+ [CSX port{port_nr}] = AddLumpedPort(CSX, 5 ,port_nr, resist(port_nr), start, stop, [0 0 1], active(port_nr));
+ end
+end
+
+%% create substrate
+CSX = AddMaterial( CSX, substrate.name );
+CSX = SetMaterialProperty( CSX, substrate.name, 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa );
+start = [-substrate.width/2 0 0];
+stop = [ substrate.width/2 substrate.length substrate.thickness];
+CSX = AddBox( CSX, substrate.name, 0, start, stop );
+
+mesh.x = [mesh.x start(1) stop(1)];
+mesh.y = [mesh.y start(2) stop(2)];
+
+% add extra cells to discretize the substrate thickness
+mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];
+
+%% create ground (same size as substrate)
+CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
+start(3)=0;
+stop(3) =0;
+CSX = AddBox(CSX,'gnd',10,start,stop);
+
+%% finalize the mesh
+% generate a smooth mesh with max. cell size: lambda_min / 20
+mesh = SmoothMesh(mesh, 2, 1.3);
+mesh.x = [mesh.x min(mesh.x)-AirSpacer(1) max(mesh.x)+AirSpacer(1)];
+mesh.y = [mesh.y min(mesh.y)-AirSpacer(2) max(mesh.y)+AirSpacer(2)];
+mesh.z = [mesh.z min(mesh.z)-AirSpacer(3) max(mesh.z)+2*AirSpacer(3)];
+
+mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20, 1.3);
+
+%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition
+start = [mesh.x(4) mesh.y(4) mesh.z(4)];
+stop = [mesh.x(end-3) mesh.y(end-3) mesh.z(end-3)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);
+
+mesh = AddPML(mesh,(BC==3)*8);
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%% prepare simulation folder
+Sim_CSX = 'patch_array.xml';
+
+if (postproc_only==0)
+ [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+ [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+ %% write openEMS compatible xml-file
+ WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+ %% show the structure
+ if (show_structure>0)
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+ end
+
+ %% run openEMS
+ RunOpenEMS( Sim_Path, Sim_CSX);
+end
+
diff --git a/openEMS/matlab/Tutorials/Patch_Antenna_Phased_Array.m b/openEMS/matlab/Tutorials/Patch_Antenna_Phased_Array.m
new file mode 100644
index 0000000..873f345
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Patch_Antenna_Phased_Array.m
@@ -0,0 +1,166 @@
+%
+% Tutorials / Patch Antenna Phased Array
+%
+% Describtion at:
+%
+% Tested with
+% - Matlab 2011a
+% - Octave 4.0
+% - openEMS v0.0.33
+%
+% References:
+% [1] Y. Yusuf and X. Gong, “A low-cost patch antenna phased array with
+% analog beam steering using mutual coupling and reactive loading,” IEEE
+% Antennas Wireless Propag. Lett., vol. 7, pp. 81–84, 2008.
+% [2] S. Otto, S. Held, A. Rennings, and K. Solbach,
+% "Array and multiport antenna farfield simulation using
+% EMPIRE, MATLAB and ADS," 39th European Microwave Conf. (EuMC 2009),
+% Sept. 29 – Oct. 1, Rome, Italy, pp. 1547-1550, 2009.
+% [3] K. Karlsson, J. Carlsson, I. Belov, G. Nilsson, and P.-S. Kildal,
+% “Optimization of antenna diversity gain by combining full-wave and
+% circuit simulations,” in Proc. Second European Conference on Antennas
+% and Propagation EuCAP 2007, 11–16 Nov. 2007, pp. 1–5.
+%
+% (C) 2013-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+
+close all
+clear
+clc
+
+% we need the "Cuircuit Toolbox"
+addpath('C:\CTB');
+% get the latest version from:
+% using git: https://github.com/thliebig/CTB
+% or zip: https://github.com/thliebig/CTB/archive/master.zip
+
+% set this to 0 to NOT run a reference simulation with the given C2 and C3
+% for comparison
+do_reference_simulation = 1;
+
+% set to 1 if you want to run AppCSXCAD to see the simulated structure
+show_structure = 1;
+
+% set this to 1, to force openEMS to run again even if the data already exist
+force_rerun = 0;
+
+% frequency range of interest
+f = linspace( 1e9, 5e9, 1601 );
+
+% resonant frequency for far-field calculations
+f0 = 3e9;
+
+% capacities for port 2 and 3 to shift the far-field pattern
+C2 = 0.2e-12;
+C3 = 0.2e-12;
+
+Sim_Path_Root = ['tmp_' mfilename];
+
+%% calculate the full S-parameter set for all 3 patch antennas running 3
+% individual openEMS simulations in which one antenna is active and the
+% other two a passive (50 Ohm load) respectively
+xpos = [0 -41 41]; % x-center position of the 3 antennas
+caps = [0 0 0];
+resist = [50 50 50];
+
+spara = [];
+color_code = {'k-','r--','m-.'};
+
+for n=1:3
+ active = [0 0 0];
+ active(n) = 1; % activate antenna n
+ Sim_Path = [Sim_Path_Root '_' num2str(n)]; % create an individual path
+ [port{n} nf2ff{n}] = Patch_Antenna_Array(Sim_Path, ((exist(Sim_Path,'dir')>0) && (force_rerun==0)), show_structure, xpos, caps, resist, active);
+ port{n} = calcPort( port{n}, Sim_Path, f, 'RefImpedance', 50);
+ nf2ff{n} = CalcNF2FF(nf2ff{n}, Sim_Path, f0, [-180:2:180]*pi/180, 0);
+
+ figure
+ hold on
+ grid on
+ for p=1:3
+ I(p,n) = interp1(f, port{n}{p}.if.tot,f0);
+ P_in(p) = 0.5*interp1(f, port{n}{n}.uf.inc,f0)*conj(interp1(f, port{n}{n}.if.inc,f0));
+ spara(p,n,:) = port{n}{p}.uf.ref./ port{n}{n}.uf.inc;
+ plot(f, squeeze(20*log10(abs(spara(p,n,:)))),color_code{p},'Linewidth',2);
+ end
+end
+
+%% export sparameter to touchstone file
+write_touchstone('s',f,spara,[Sim_Path_Root '.s3p']);
+
+% instructions for Qucs:
+% load the written touchstone file
+% attach C2 and C3 to port 2 and 3
+% attach a signal port to port 1
+% probe the currents going into port 1 to 3
+
+% example currents for ports 1 to 3 for C2 = 0.2pF and C3=0.2pF
+I_qucs(1,1) = 0.00398-0.000465j;
+I_qucs(2,1) = 2.92e-5-0.000914j;
+I_qucs(3,1) = 2.92e-5-0.000914j;
+
+disp(['I2/I1: Qucs: ' num2str(I_qucs(2)/I_qucs(1)) ' (defined manually)'])
+disp(['I3/I1: Qucs: ' num2str(I_qucs(3)/I_qucs(1)) ' (defined manually)'])
+
+%% Calculate the currents of port 1 to 3 using Matlab [1]
+z = s2z(spara);
+
+Z2 = 1/(1j*2*pi*f0*C2);
+Z3 = 1/(1j*2*pi*f0*C3);
+
+z23(1,1) = interp1(f,squeeze(z(2,2,:)),f0) + Z2;
+z23(1,2) = interp1(f,squeeze(z(2,3,:)),f0);
+z23(2,1) = interp1(f,squeeze(z(3,2,:)),f0);
+z23(2,2) = interp1(f,squeeze(z(3,3,:)),f0) + Z3;
+
+%set input/feeding current of port 1 to 1mA
+I_out(1,1) = 1e-3;
+% calc current for port 2 and 3
+I_out([2 3],1) = z23\[-interp1(f,squeeze(z(2,1,:)),f0);-interp1(f,squeeze(z(3,1,:)),f0)]*I_out(1);
+
+disp(['I2/I1: Matlab: ' num2str(I_out(2)/I_out(1))])
+disp(['I3/I1: Matlab: ' num2str(I_out(3)/I_out(1))])
+
+
+%% do a referenc simulation for the given C2/C3 values
+if (do_reference_simulation)
+ active = [1 0 0];
+ caps = [0 C2 C3];
+ resist = [50 inf inf];
+ Sim_Path = [Sim_Path_Root '_C2=' num2str(C2*1e12) '_C3=' num2str(C3*1e12)];
+ [port_ref nf2ff_ref] = Patch_Antenna_Array(Sim_Path, ((exist(Sim_Path,'dir')>0) && (force_rerun==0)), show_structure, xpos, caps, resist, active);
+ port_ref = calcPort( port_ref, Sim_Path, f, 'RefImpedance', 50);
+ nf2ff_ref = CalcNF2FF(nf2ff_ref, Sim_Path, f0, [-180:2:180]*pi/180, 0);
+
+ % extract currents from referenc simulation
+ for p=1:3
+ I_ref(p,1) = interp1(f, port_ref{p}.if.tot,f0);
+ end
+
+ disp(['I2/I1: openEMS: ' num2str(I_ref(2)/I_ref(1))])
+ disp(['I3/I1: openEMS: ' num2str(I_ref(3)/I_ref(1))])
+end
+
+%% calculate and apply weighting cooefficients [3]
+% calculate
+coeff = I\I_out;
+
+% apply
+E_ff_phi = 0*nf2ff{1}.E_phi{1};
+E_ff_theta = 0*nf2ff{1}.E_phi{1};
+for n=1:3
+ E_ff_phi = E_ff_phi + coeff(n)*nf2ff{n}.E_phi{1};
+ E_ff_theta = E_ff_theta + coeff(n)*nf2ff{n}.E_theta{1};
+end
+
+%% plot far-field patterns
+figure
+polar([-180:2:180]'*pi/180,abs(E_ff_phi(:))/max(abs(E_ff_phi(:))));
+hold on
+if (do_reference_simulation)
+ polar([-180:2:180]'*pi/180,abs(nf2ff_ref.E_norm{1}(:,1))/max(abs(nf2ff_ref.E_norm{1}(:,1))),'r--');
+end
+title('normalized far-field pattern','Interpreter', 'none')
+legend('calculated','reference')
+
+
diff --git a/openEMS/matlab/Tutorials/RCS_Sphere.m b/openEMS/matlab/Tutorials/RCS_Sphere.m
new file mode 100644
index 0000000..b8bb5bc
--- /dev/null
+++ b/openEMS/matlab/Tutorials/RCS_Sphere.m
@@ -0,0 +1,138 @@
+%
+% Tutorials / radar cross section of a metal sphere
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_RCS_Sphere
+%
+% Tested with
+% - Matlab 2013a / Octave 3.8.1
+% - openEMS v0.0.32
+%
+% (C) 2012-2014 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+sphere.rad = 200;
+
+inc_angle = 0 /180*pi; %incident angle (to x-axis) in rad
+
+% size of the simulation box
+SimBox = 1000;
+PW_Box = 750;
+
+%% setup FDTD parameter & excitation function
+f_start = 50e6; % start frequency
+f_stop = 1000e6; % stop frequency
+f0 = 500e6;
+
+FDTD = InitFDTD( );
+FDTD = SetGaussExcite( FDTD, 0.5*(f_start+f_stop), 0.5*(f_stop-f_start) );
+BC = [1 1 1 1 1 1]*3; % set boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+max_res = c0 / f_stop / unit / 20; % cell size: lambda/20
+CSX = InitCSX();
+
+%create mesh
+smooth_mesh = SmoothMeshLines([0 SimBox/2], max_res);
+mesh.x = unique([-smooth_mesh smooth_mesh]);
+mesh.y = mesh.x;
+mesh.z = mesh.x;
+
+%% create metal sphere
+CSX = AddMetal( CSX, 'sphere' ); % create a perfect electric conductor (PEC)
+CSX = AddSphere(CSX,'sphere',10,[0 0 0],sphere.rad);
+
+%% plane wave excitation
+k_dir = [cos(inc_angle) sin(inc_angle) 0]; % plane wave direction
+E_dir = [0 0 1]; % plane wave polarization --> E_z
+
+CSX = AddPlaneWaveExcite(CSX, 'plane_wave', k_dir, E_dir, f0);
+start = [-PW_Box/2 -PW_Box/2 -PW_Box/2];
+stop = -start;
+CSX = AddBox(CSX, 'plane_wave', 0, start, stop);
+
+%% dump boxes
+CSX = AddDump(CSX, 'Et');
+start = [mesh.x(1) mesh.y(1) 0];
+stop = [mesh.x(end) mesh.y(end) 0];
+CSX = AddBox(CSX, 'Et', 0, start, stop);
+
+%%nf2ff calc
+start = [mesh.x(1) mesh.y(1) mesh.z(1)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);
+
+% add 8 lines in all direction as pml spacing
+mesh = AddPML(mesh,8);
+
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% prepare simulation folder
+Sim_Path = 'Sphere_RCS';
+Sim_CSX = 'Sphere_RCS.xml';
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure
+CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+%% run openEMS
+RunOpenEMS( Sim_Path, Sim_CSX);
+
+%%
+disp('Use Paraview to display the elctric fields dumped by openEMS');
+
+%%
+EF = ReadUI( 'et', Sim_Path, f0 ); % time domain/freq domain voltage
+Pin = 0.5*norm(E_dir)^2/Z0 .* abs(EF.FD{1}.val).^2;
+
+%%
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, pi/2, [-180:2:180]*pi/180, 'Mode',1);
+RCS = 4*pi./Pin(1).*nf2ff.P_rad{1}(:);
+polar(nf2ff.phi,RCS);
+xlabel('x -->');
+ylabel('y -->');
+hold on
+grid on
+
+drawnow
+
+%%
+freq = linspace(f_start,f_stop,100);
+EF = ReadUI( 'et', Sim_Path, freq ); % time domain/freq domain voltage
+Pin = 0.5*norm(E_dir)^2/Z0 .* abs(EF.FD{1}.val).^2;
+
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, freq, pi/2, pi+inc_angle, 'Mode',1);
+for fn=1:numel(freq)
+ back_scat(fn) = 4*pi./Pin(fn).*nf2ff.P_rad{fn}(1);
+end
+
+%%
+figure
+plot(freq/1e6,back_scat,'Linewidth',2);
+grid on;
+xlabel('frequency (MHz) \rightarrow');
+ylabel('RCS (m^2) \rightarrow');
+title('radar cross section');
+
+%%
+figure
+lambda = c0./freq;
+semilogy(sphere.rad*unit./lambda,back_scat/(pi*sphere.rad*unit*sphere.rad*unit),'Linewidth',2);
+ylim([10^-2 10^1])
+grid on;
+xlabel('sphere radius / wavelength \rightarrow');
+ylabel('RCS / (\pi a^2) \rightarrow');
+title('normalized radar cross section');
diff --git a/openEMS/matlab/Tutorials/Rect_Waveguide.m b/openEMS/matlab/Tutorials/Rect_Waveguide.m
new file mode 100644
index 0000000..3b1a79a
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Rect_Waveguide.m
@@ -0,0 +1,121 @@
+%
+% Tutorials / Rect_Waveguide
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Rectangular_Waveguide
+%
+% Tested with
+% - Octave 4.0.0
+% - openEMS v0.0.33
+%
+% (C) 2010-2015 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; %drawing unit in um
+
+% waveguide dimensions
+% WR42
+a = 10700; %waveguide width
+b = 4300; %waveguide heigth
+length = 50000;
+
+% frequency range of interest
+f_start = 20e9;
+f_0 = 24e9;
+f_stop = 26e9;
+lambda0 = c0/f_0/unit;
+
+%waveguide TE-mode definition
+TE_mode = 'TE10';
+
+%targeted mesh resolution
+mesh_res = lambda0./[30 30 30];
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD('NrTS',1e4, 'OverSampling', 5);
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+
+% boundary conditions
+BC = [0 0 0 0 3 3]; %pml in pos. and neg. z-direction
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = SmoothMeshLines([0 a], mesh_res(1));
+mesh.y = SmoothMeshLines([0 b], mesh_res(2));
+mesh.z = SmoothMeshLines([0 length], mesh_res(3));
+CSX = DefineRectGrid(CSX, unit,mesh);
+
+%% apply the waveguide port %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start=[mesh.x(1) mesh.y(1) mesh.z(11)];
+stop =[mesh.x(end) mesh.y(end) mesh.z(15)];
+[CSX, port{1}] = AddRectWaveGuidePort( CSX, 0, 1, start, stop, 'z', a*unit, b*unit, TE_mode, 1);
+
+start=[mesh.x(1) mesh.y(1) mesh.z(end-13)];
+stop =[mesh.x(end) mesh.y(end) mesh.z(end-14)];
+[CSX, port{2}] = AddRectWaveGuidePort( CSX, 0, 2, start, stop, 'z', a*unit, b*unit, TE_mode);
+
+%% define dump box... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','2,2,2');
+start = [mesh.x(1) mesh.y(1) mesh.z(1)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
+CSX = AddBox(CSX,'Et',0 , start,stop);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Sim_Path = 'tmp_mod';
+Sim_CSX = 'rect_wg.xml';
+
+[status, message, messageid] = rmdir(Sim_Path,'s');
+[status, message, messageid] = mkdir(Sim_Path);
+
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+RunOpenEMS(Sim_Path, Sim_CSX)
+
+%% postproc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+freq = linspace(f_start,f_stop,201);
+port = calcPort(port, Sim_Path, freq);
+
+s11 = port{1}.uf.ref./ port{1}.uf.inc;
+s21 = port{2}.uf.ref./ port{1}.uf.inc;
+ZL = port{1}.uf.tot./port{1}.if.tot;
+ZL_a = port{1}.ZL; % analytic waveguide impedance
+
+%% plot s-parameter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+figure
+plot(freq*1e-6,20*log10(abs(s11)),'k-','Linewidth',2);
+xlim([freq(1) freq(end)]*1e-6);
+grid on;
+hold on;
+plot(freq*1e-6,20*log10(abs(s21)),'r--','Linewidth',2);
+l = legend('S_{11}','S_{21}','Location','Best');
+set(l,'FontSize',12);
+ylabel('S-Parameter (dB)','FontSize',12);
+xlabel('frequency (MHz) \rightarrow','FontSize',12);
+
+%% compare analytic and numerical wave-impedance %%%%%%%%%%%%%%%%%%%%%%%%%%
+figure
+plot(freq*1e-6,real(ZL),'Linewidth',2);
+hold on;
+grid on;
+plot(freq*1e-6,imag(ZL),'r--','Linewidth',2);
+plot(freq*1e-6,ZL_a,'g-.','Linewidth',2);
+ylabel('ZL (\Omega)','FontSize',12);
+xlabel('frequency (MHz) \rightarrow','FontSize',12);
+xlim([freq(1) freq(end)]*1e-6);
+l = legend('\Re(Z_L)','\Im(Z_L)','Z_L analytic','Location','Best');
+set(l,'FontSize',12);
+
+%% Plot the field dumps %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+figure
+dump_file = [Sim_Path '/Et.h5'];
+PlotArgs.slice = {a/2*unit b/2*unit 0};
+PlotArgs.pauseTime=0.01;
+PlotArgs.component=0;
+PlotArgs.Limit = 'auto';
+PlotHDF5FieldData(dump_file, PlotArgs)
diff --git a/openEMS/matlab/Tutorials/Simple_Patch_Antenna.m b/openEMS/matlab/Tutorials/Simple_Patch_Antenna.m
new file mode 100644
index 0000000..ee2a8f0
--- /dev/null
+++ b/openEMS/matlab/Tutorials/Simple_Patch_Antenna.m
@@ -0,0 +1,180 @@
+%
+% Tutorials / simple patch antenna
+%
+% Describtion at:
+% http://openems.de/index.php/Tutorial:_Simple_Patch_Antenna
+%
+% Tested with
+% - Matlab 2013a / Octave 4.0
+% - openEMS v0.0.33
+%
+% (C) 2010-2015 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% patch width in x-direction
+patch.width = 32; % resonant length
+% patch length in y-direction
+patch.length = 40;
+
+%substrate setup
+substrate.epsR = 3.38;
+substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
+substrate.width = 60;
+substrate.length = 60;
+substrate.thickness = 1.524;
+substrate.cells = 4;
+
+%setup feeding
+feed.pos = -6; %feeding position in x-direction
+feed.R = 50; %feed resistance
+
+% size of the simulation box
+SimBox = [200 200 150];
+
+%% setup FDTD parameter & excitation function
+f0 = 2e9; % center frequency
+fc = 1e9; % 20 dB corner frequency
+FDTD = InitFDTD( 'NrTs', 30000 );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+CSX = InitCSX();
+
+%initialize the mesh with the "air-box" dimensions
+mesh.x = [-SimBox(1)/2 SimBox(1)/2];
+mesh.y = [-SimBox(2)/2 SimBox(2)/2];
+mesh.z = [-SimBox(3)/3 SimBox(3)*2/3];
+
+%% create patch
+CSX = AddMetal( CSX, 'patch' ); % create a perfect electric conductor (PEC)
+start = [-patch.width/2 -patch.length/2 substrate.thickness];
+stop = [ patch.width/2 patch.length/2 substrate.thickness];
+CSX = AddBox(CSX,'patch',10,start,stop); % add a box-primitive to the metal property 'patch'
+
+%% create substrate
+CSX = AddMaterial( CSX, 'substrate' );
+CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa );
+start = [-substrate.width/2 -substrate.length/2 0];
+stop = [ substrate.width/2 substrate.length/2 substrate.thickness];
+CSX = AddBox( CSX, 'substrate', 0, start, stop );
+
+% add extra cells to discretize the substrate thickness
+mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];
+
+%% create ground (same size as substrate)
+CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
+start(3)=0;
+stop(3) =0;
+CSX = AddBox(CSX,'gnd',10,start,stop);
+
+%% apply the excitation & resist as a current source
+start = [feed.pos 0 0];
+stop = [feed.pos 0 substrate.thickness];
+[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 0 1], true);
+
+%% finalize the mesh
+% detect all edges except of the patch
+mesh = DetectEdges(CSX, mesh,'ExcludeProperty','patch');
+% detect and set a special 2D metal edge mesh for the patch
+mesh = DetectEdges(CSX, mesh,'SetProperty','patch','2D_Metal_Edge_Res', c0/(f0+fc)/unit/50);
+% generate a smooth mesh with max. cell size: lambda_min / 20
+mesh = SmoothMesh(mesh, c0/(f0+fc)/unit/20);
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition
+start = [mesh.x(4) mesh.y(4) mesh.z(4)];
+stop = [mesh.x(end-3) mesh.y(end-3) mesh.z(end-3)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);
+
+%% prepare simulation folder
+Sim_Path = 'tmp_Patch_Ant';
+Sim_CSX = 'patch_ant.xml';
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure
+CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+%% run openEMS
+RunOpenEMS( Sim_Path, Sim_CSX);
+
+%% postprocessing & do the plots
+freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+
+% plot feed point impedance
+figure
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+drawnow
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%find resonance frequncy from s11
+f_res_ind = find(s11==min(s11));
+f_res = freq(f_res_ind);
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+disp( 'calculating far field at phi=[0 90] deg...' );
+
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, [-180:2:180]*pi/180, [0 90]*pi/180);
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
+disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./port.P_inc(f_res_ind)) ' %']);
+
+% normalized directivity as polar plot
+figure
+polarFF(nf2ff,'xaxis','theta','param',[1 2],'normalize',1)
+
+% log-scale directivity plot
+figure
+plotFFdB(nf2ff,'xaxis','theta','param',[1 2])
+% conventional plot approach
+% plot( nf2ff.theta*180/pi, 20*log10(nf2ff.E_norm{1}/max(nf2ff.E_norm{1}(:)))+10*log10(nf2ff.Dmax));
+
+drawnow
+
+%%
+disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
+thetaRange = (0:2:180);
+phiRange = (0:2:360) - 180;
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5');
+
+figure
+plotFF3D(nf2ff,'logscale',-20);
+
+
+E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax;
+DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,'scale',1e-3);
diff --git a/openEMS/matlab/Tutorials/readme b/openEMS/matlab/Tutorials/readme
new file mode 100644
index 0000000..a80dfa6
--- /dev/null
+++ b/openEMS/matlab/Tutorials/readme
@@ -0,0 +1 @@
+* Find the tutorial describtions at http://openems.de/index.php/Tutorials
diff --git a/openEMS/matlab/WriteHDF5.m b/openEMS/matlab/WriteHDF5.m
new file mode 100644
index 0000000..df6a8d7
--- /dev/null
+++ b/openEMS/matlab/WriteHDF5.m
@@ -0,0 +1,73 @@
+function WriteHDF5(filename,hdf_fielddata,hdf_mesh)
+% function WriteHDF5(filename,hdf_fielddata,hdf_mesh)
+%
+% input:
+% hdf_fielddata.time
+% hdf_fielddata.names
+% hdf_fielddata.values
+% hdf_mesh.type
+% hdf_mesh.names
+% hdf_mesh.lines
+%
+% openEMS matlab interface
+% -----------------------
+% (C) 2010 Sebastian Held <sebastian.held@uni-due.de>
+% See also ReadHDF5FieldData ReadHDF5Mesh
+
+isOctave = exist('OCTAVE_VERSION','builtin') ~= 0;
+if isOctave
+ WriteHDF5_octave(filename,hdf_fielddata,hdf_mesh);
+ return
+end
+
+writemode = 'overwrite';
+if isfield( hdf_fielddata, 'TD' )
+ % this is a time domain data set
+ time = hdf_fielddata.TD.time;
+ for n=1:numel(time)
+ name = ['/FieldData/TD/' int2str(n)];
+ [details.Location, details.Name] = fileparts(name);
+ attribute_details.AttachedTo = name;
+ attribute_details.AttachType = 'dataset';
+ attribute_details.Name = 'time';
+ hdf5write( filename, details, hdf_fielddata.TD.values{n}, ...
+ attribute_details, time(n), ...
+ 'WriteMode', writemode );
+ writemode = 'append';
+ end
+end
+if isfield( hdf_fielddata, 'FD' )
+ % this is a frequency domain data set
+ freq = hdf_fielddata.FD.frequency;
+ for n=1:numel(freq)
+ name = ['/FieldData/FD/f' int2str(n-1) '_real'];
+ [details.Location, details.Name] = fileparts(name);
+ hdf5write( filename, details, real(hdf_fielddata.FD.values{n}), ...
+ 'WriteMode', writemode );
+ name = ['/FieldData/FD/f' int2str(n-1) '_imag'];
+ [details.Location, details.Name] = fileparts(name);
+ hdf5write( filename, details, imag(hdf_fielddata.FD.values{n}), ...
+ 'WriteMode', 'append' );
+ writemode = 'append';
+ end
+ name = '/FieldData/FD';
+ [details.Location, details.Name] = fileparts(name);
+ attribute_details.AttachedTo = name;
+ attribute_details.AttachType = 'group';
+ attribute_details.Name = 'frequency';
+ hdf5write( filename, attribute_details, freq, ...
+ 'WriteMode', 'append' );
+end
+
+names = hdf_mesh.names; % names is a cell array
+for n=1:numel(names)
+ [details.Location, details.Name, ext] = fileparts(names{n});
+ details.Name = [details.Name ext];
+ hdf5write( filename, details, hdf_mesh.lines{n}, ...
+ 'WriteMode', 'append' );
+end
+
+
+
+function WriteHDF5_octave(filename,hdf_fielddata,hdf_mesh)
+error 'not yet implemented'
diff --git a/openEMS/matlab/WriteOpenEMS.m b/openEMS/matlab/WriteOpenEMS.m
new file mode 100644
index 0000000..d7c9cbd
--- /dev/null
+++ b/openEMS/matlab/WriteOpenEMS.m
@@ -0,0 +1,19 @@
+function WriteOpenEMS(filename, FDTD, CSX)
+% function WriteOpenEMS(filename, FDTD, CSX)
+%
+% Write the FDTD and CSX structures to a file.
+%
+% example:
+% CSX = InitCSX();
+% FDTD = InitFDTD();
+% WriteOpenEMS('test.xml',FDTD,CSX)
+%
+% See also InitFDTD InitCSX CSXGeomPlot
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig
+
+openEMS.FDTD = FDTD;
+openEMS.ContinuousStructure = CSX;
+struct_2_xml(filename,openEMS,'openEMS'); \ No newline at end of file
diff --git a/openEMS/matlab/calcLumpedPort.m b/openEMS/matlab/calcLumpedPort.m
new file mode 100644
index 0000000..69dba69
--- /dev/null
+++ b/openEMS/matlab/calcLumpedPort.m
@@ -0,0 +1,107 @@
+function [port] = calcLumpedPort( port, SimDir, f, varargin)
+% [port] = calcLumpedPort( port, SimDir, f, varargin)
+%
+% Calculate voltages and currents of given lumped port.
+%
+% The port has to be created by e.g. AddLumpedPort().
+%
+% input:
+% port: return value of e.g. AddMSLPort()
+% SimDir: directory, where the simulation files are
+% f: frequency vector for DFT
+%
+% variable input:
+% 'RefImpedance': - use a given reference impedance to calculate inc and
+% ref voltages and currents
+% - default is given port or calculated line impedance
+% 'SwitchDirection': 0/1, switch assumed direction of propagation
+%
+% output:
+% % output signals/values in time domain (TD):
+% port.ut.tot total voltage (time-domain)
+% port.ut.time voltage time vector
+% port.it.tot total current (time-domain)
+% port.it.time current time vector
+%
+% % output signals/values in frequency domain (FD):
+% port.f the given frequency fector
+% port.uf.tot/inc/ref total, incoming and reflected voltage
+% port.if.tot/inc/ref total, incoming and reflected current
+%
+% example:
+% port{1} = calcLumpedPort( port{1}, Sim_Path, f, 'RefImpedance', 50);
+%
+% openEMS matlab interface
+% -----------------------
+% (C) 2012 Thorsten Liebig <thorsten.liebig@gmx.de>
+%
+% See also AddLumpedPort, calcPort
+
+if (iscell(port))
+ for n=1:numel(port)
+ port{n}=calcLumpedPort(port{n}, SimDir, f, varargin{:});
+ end
+ return;
+end
+
+if (strcmpi(port.type,'Lumped')~=1 && strcmpi(port.type,'Curve')~=1)
+ error('openEMS:calcLumpedPort','error, type is not a lumped port');
+end
+
+
+%% read optional arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%set defaults
+ref_ZL = port.Feed_R;
+switch_dir = 1;
+
+UI_args = {};
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'RefImpedance')==1);
+ ref_ZL = varargin{n+1};
+ elseif (strcmpi(varargin{n},'SwitchDirection')==1);
+ if (varargin{n+1})
+ switch_dir = -1;
+ end
+ else
+ UI_args(end+1) = varargin(n);
+ UI_args(end+1) = varargin(n+1);
+ end
+end
+
+port.ZL_ref = ref_ZL;
+
+% read time domain data
+U = ReadUI( port.U_filename, SimDir, f, UI_args{:} );
+I = ReadUI( port.I_filename, SimDir, f, UI_args{:} );
+
+% store the original frequency domain waveforms
+u_f = U.FD{1}.val;
+i_f = switch_dir*I.FD{1}.val;
+
+port.ut.time = U.TD{1}.t;
+port.ut.tot = U.TD{1}.val;
+
+port.it.time = I.TD{1}.t;
+port.it.tot = switch_dir*I.TD{1}.val;
+
+port.Zin = u_f./i_f;
+
+port.f = f;
+uf_inc = 0.5 * ( u_f + i_f .* ref_ZL );
+if_inc = 0.5 * ( i_f + u_f ./ ref_ZL );
+
+uf_ref = u_f - uf_inc;
+if_ref = if_inc - i_f;
+
+port.uf.tot = u_f;
+port.uf.inc = uf_inc;
+port.uf.ref = uf_ref;
+
+port.if.tot = i_f;
+port.if.inc = if_inc;
+port.if.ref = if_ref;
+
+port.raw.U = U;
+port.raw.I = I;
diff --git a/openEMS/matlab/calcPort.m b/openEMS/matlab/calcPort.m
new file mode 100644
index 0000000..9b56955
--- /dev/null
+++ b/openEMS/matlab/calcPort.m
@@ -0,0 +1,82 @@
+function [port] = calcPort( port, SimDir, f, varargin)
+% [port] = calcPort( port, SimDir, f, varargin)
+%
+% Calculate:
+% - voltages and currents
+% - the propagation constant and the characteristic impedance (if applicable)
+%
+% The port has to be created by e.g. AddMSLPort(), AddLumpedPort() or AddCurvePort
+%
+% input:
+% port: return value of AddMSLPort()
+% SimDir: directory, where the simulation files are
+% f: frequency vector for DFT
+%
+% variable input:
+% 'RefImpedance': - use a given reference impedance to calculate inc and
+% ref voltages and currents
+% - default is given port or calculated line impedance
+% 'RefPlaneShift': for transmission lines only, See also calcTLPort for
+% more details
+% 'SwitchDirection': 0/1, switch assumed direction of propagation
+% 'SignalType': 'pulse' (default) or 'periodic'
+%
+% output:
+% % output signals/values in time domain (TD):
+% port.ut.tot total voltage (time-domain)
+% port.ut.time voltage time vector
+% port.it.tot total current (time-domain)
+% port.it.time current time vector
+%
+% % output signals/values in frequency domain (FD):
+% port.f the given frequency fector
+% port.uf.tot/inc/ref total, incoming and reflected voltage
+% port.if.tot/inc/ref total, incoming and reflected current
+% port.ZL_ref used refernce impedance
+%
+% port.P_inc incoming power
+% port.P_ref reflected power
+% port.P_acc accepted power (incoming minus reflected,
+% may be negative for passive ports)
+%
+% if port is a transmission line port:
+% port.beta: propagation constant
+% port.ZL: characteristic line impedance
+%
+% example:
+% port = calcPort(port, Sim_Path, f, 'RefImpedance', 50);
+%
+% openEMS matlab interface
+% -----------------------
+% (C) 2012 Thorsten Liebig <thorsten.liebig@gmx.de>
+%
+% See also AddMSLPort, AddLumpedPort, AddCurvePort, calcTLPort, calcLumpedPort
+
+if (iscell(port))
+ for n=1:numel(port)
+ port{n}=calcPort(port{n}, SimDir, f, varargin{:});
+ end
+ return;
+end
+
+if isempty(port)
+ return;
+end
+
+if (strcmpi(port.type,'MSL') || strcmpi(port.type,'Coaxial') || strcmpi(port.type,'StripLine') || strcmpi(port.type,'CPW'))
+ port = calcTLPort( port, SimDir, f, varargin{:});
+elseif strcmpi(port.type,'WaveGuide')
+ port = calcWGPort( port, SimDir, f, varargin{:});
+elseif (strcmpi(port.type,'Lumped') || strcmpi(port.type,'Curve'))
+ port = calcLumpedPort( port, SimDir, f, varargin{:});
+else
+ error 'unknown port type'
+end
+
+% calc some more port parameter
+% incoming power
+port.P_inc = 0.5*real(port.uf.inc.*conj(port.if.inc));
+% reflected power
+port.P_ref = 0.5*real(port.uf.ref.*conj(port.if.ref));
+% accepted power (incoming - reflected)
+port.P_acc = 0.5*real(port.uf.tot.*conj(port.if.tot));
diff --git a/openEMS/matlab/calcTLPort.m b/openEMS/matlab/calcTLPort.m
new file mode 100644
index 0000000..3a631ba
--- /dev/null
+++ b/openEMS/matlab/calcTLPort.m
@@ -0,0 +1,173 @@
+function [port] = calcTLPort( port, SimDir, f, varargin)
+% [port] = calcTLPort( port, SimDir, f, varargin)
+%
+% Calculate voltages and currents, the propagation constant beta
+% and the characteristic impedance ZL of the given transmission line port.
+%
+% The port has to be created by e.g. AddMSLPort().
+%
+% input:
+% port: return value of e.g. AddMSLPort()
+% SimDir: directory, where the simulation files are
+% f: frequency vector for DFT
+%
+% variable input:
+% 'RefImpedance': - use a given reference impedance to calculate inc and
+% ref voltages and currents
+% - default is given port or calculated line impedance
+% 'RefPlaneShift': - use a given reference plane shift from port beginning
+% for a desired phase correction
+% - default is the measurement plane
+% - the plane shift has to be given in drawing units!
+% 'SwitchDirection': 0/1, switch assumed direction of propagation
+%
+% output:
+% % output signals/values in time domain (TD):
+% port.ut.tot total voltage (time-domain)
+% port.ut.time voltage time vector
+% port.it.tot total current (time-domain)
+% port.it.time current time vector
+%
+% % output signals/values in frequency domain (FD):
+% port.f the given frequency fector
+% port.uf.tot/inc/ref total, incoming and reflected voltage
+% port.if.tot/inc/ref total, incoming and reflected current
+% port.beta: propagation constant
+% port.ZL: characteristic line impedance
+% port.ZL_ref used refernce impedance
+%
+% example:
+% port{1} = calcTLPort( port{1}, Sim_Path, f, 'RefImpedance', 50);
+%
+% reference: W. K. Gwarek, "A Differential Method of Reflection Coefficient Extraction From FDTD Simulations",
+% IEEE Microwave and Guided Wave Letters, Vol. 6, No. 5, May 1996
+%
+% openEMS matlab interface
+% -----------------------
+% (C) 2010 Sebastian Held <sebastian.held@uni-due.de>
+%
+% See also AddMSLPort, calcPort
+
+if (iscell(port))
+ for n=1:numel(port)
+ port{n}=calcTLPort(port{n}, SimDir, f, varargin{:});
+ end
+ return;
+end
+
+if ((strcmpi(port.type,'MSL')~=1) && (strcmpi(port.type,'Coaxial')~=1) && (strcmpi(port.type,'StripLine')~=1) && (strcmpi(port.type,'CPW')~=1))
+ error('openEMS:calcTLPort','error, type is not a transmission line port');
+end
+
+% check
+if abs((port.v_delta(1) - port.v_delta(2)) / port.v_delta(1))>1e-6
+ warning( 'openEMS:calcPort:mesh', 'mesh is not equidistant; expect degraded accuracy' );
+end
+
+
+%% read optional arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%set defaults
+ref_ZL = -1;
+ref_shift = nan;
+switch_dir = 1;
+
+UI_args = {};
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'RefPlaneShift')==1);
+ ref_shift = varargin{n+1};
+ elseif (strcmp(varargin{n},'RefImpedance')==1);
+ ref_ZL = varargin{n+1};
+ elseif (strcmpi(varargin{n},'SwitchDirection')==1);
+ if (varargin{n+1})
+ switch_dir = -1;
+ end
+ else
+ UI_args(end+1) = varargin(n);
+ UI_args(end+1) = varargin(n+1);
+ end
+end
+
+if ((strcmpi(port.type,'StripLine')==1) || (strcmpi(port.type,'CPW')==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)
+I = ReadUI( port.I_filename, SimDir, f, UI_args{:} );
+
+% time domain signals
+port.ut.time = U.TD{2}.t;
+port.ut.tot = U.TD{2}.val;
+
+port.it.time = I.TD{1}.t;
+port.it.tot = switch_dir*(I.TD{1}.val + I.TD{2}.val) / 2; % interpolate to same position as v
+
+% store the original frequency domain waveforms
+u_f = U.FD{2}.val;
+i_f = switch_dir*(I.FD{1}.val + I.FD{2}.val) / 2; % shift to same position as v
+
+f = U.FD{2}.f;
+Et = U.FD{2}.val;
+dEt = (U.FD{3}.val - U.FD{1}.val) / (sum(abs(port.v_delta(1:2))) * port.drawingunit);
+Ht = (I.FD{1}.val + I.FD{2}.val)/2; % space averaging: Ht is now defined at the same pos as Et
+dHt = (I.FD{2}.val - I.FD{1}.val) / (abs(port.i_delta(1)) * port.drawingunit);
+
+beta = sqrt( - dEt .* dHt ./ (Ht .* Et) );
+beta(real(beta) < 0) = -beta(real(beta) < 0); % determine correct sign (unlike the paper)
+
+% determine ZL
+ZL = sqrt(Et .* dEt ./ (Ht .* dHt));
+
+% if (strcmpi(port.type,'Coaxial'))
+% port.ZL = Z0/2/pi/ref_index*log(port.r_o/port.r_i);
+% end
+
+% reference plane shift (lossless)
+if ~isnan(ref_shift)
+ ref_shift = ref_shift * port.LengthScale;
+ % shift to the beginning of MSL
+ ref_shift = ref_shift - port.measplanepos;
+ ref_shift = ref_shift * port.drawingunit;
+
+ % store the shifted frequency domain waveforms
+ phase = real(beta)*ref_shift;
+ U.FD{1}.val = u_f .* cos(-phase) + 1i * i_f.*ZL .* sin(-phase);
+ I.FD{1}.val = i_f .* cos(-phase) + 1i * u_f./ZL .* sin(-phase);
+
+ u_f = U.FD{1}.val;
+ i_f = I.FD{1}.val;
+end
+
+if (ref_ZL < 0)
+ ref_ZL = ZL;
+end
+
+port.ZL = ZL;
+port.beta = beta;
+port.ZL_ref = ref_ZL;
+
+port.f = f;
+uf_inc = 0.5 * ( u_f + i_f .* ref_ZL );
+if_inc = 0.5 * ( i_f + u_f ./ ref_ZL );
+
+uf_ref = u_f - uf_inc;
+if_ref = if_inc - i_f;
+
+port.uf.tot = u_f;
+port.uf.inc = uf_inc;
+port.uf.ref = uf_ref;
+
+port.if.tot = i_f;
+port.if.inc = if_inc;
+port.if.ref = if_ref;
+
+port.raw.U = U;
+port.raw.I = I;
diff --git a/openEMS/matlab/calcWGPort.m b/openEMS/matlab/calcWGPort.m
new file mode 100644
index 0000000..ba845af
--- /dev/null
+++ b/openEMS/matlab/calcWGPort.m
@@ -0,0 +1,145 @@
+function [port] = calcWGPort( port, SimDir, f, varargin)
+% [port] = calcWGPort( port, SimDir, f, varargin)
+%
+% Calculate voltages and currents, the propagation constant beta
+% and the characteristic impedance ZL of the given waveguide port.
+%
+% The port has to be created by e.g. AddWaveGuidePort().
+%
+% input:
+% port: return value of e.g. AddWaveGuidePort()
+% SimDir: directory, where the simulation files are
+% f: frequency vector for DFT
+%
+% variable input:
+% 'RefImpedance': - use a given reference impedance to calculate inc and
+% ref voltages and currents
+% - default is given port or calculated line impedance
+% 'RefPlaneShift': - use a given reference plane shift from port beginning
+% for a desired phase correction
+% - default is the measurement plane at the end of the
+% port
+% - the plane shift has to be given in drawing units!
+% 'RefractiveIndex': set a material refractive index
+% 'SwitchDirection': 0/1, switch assumed direction of propagation
+%
+% output:
+% % output signals/values in time domain (TD):
+% port.ut.tot total voltage (time-domain)
+% port.ut.time voltage time vector
+% port.it.tot total current (time-domain)
+% port.it.time current time vector
+%
+% % output signals/values in frequency domain (FD):
+% port.f the given frequency fector
+% port.uf.tot/inc/ref total, incoming and reflected voltage
+% port.if.tot/inc/ref total, incoming and reflected current
+% port.beta: propagation constant
+% port.ZL: characteristic line impedance
+% port.ZL_ref used reference impedance
+%
+% example:
+% port{1} = calcWGPort( port{1}, Sim_Path, f, 'RefImpedance', 50);
+%
+% openEMS matlab interface
+% -----------------------
+% (C) 2013 Thorsten Liebig (thorsten.liebig@gmx.de)
+%
+% See also AddWaveGuidePort, calcPort
+
+if (iscell(port))
+ for n=1:numel(port)
+ port{n}=calcWGPort(port{n}, SimDir, f, varargin{:});
+ end
+ return;
+end
+
+if (strcmpi(port.type,'WaveGuide')~=1)
+ error('openEMS:calcWGPort','error, type is not a waveguide port');
+end
+
+%set defaults
+ref_ZL = -1;
+ref_shift = nan;
+ref_index = 1;
+switch_dir = 1;
+
+UI_args = {};
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'RefPlaneShift')==1);
+ ref_shift = varargin{n+1};
+ elseif (strcmp(varargin{n},'RefImpedance')==1);
+ ref_ZL = varargin{n+1};
+ elseif (strcmp(varargin{n},'RefractiveIndex')==1);
+ ref_index = varargin{n+1};
+ elseif (strcmpi(varargin{n},'SwitchDirection')==1);
+ if (varargin{n+1})
+ switch_dir = -1;
+ end
+ else
+ UI_args(end+1) = varargin(n);
+ UI_args(end+1) = varargin(n+1);
+ end
+end
+
+% read time domain data
+U = ReadUI( port.U_filename, SimDir, f, UI_args{:} );
+I = ReadUI( port.I_filename, SimDir, f, UI_args{:} );
+
+% store the original frequency domain waveforms
+u_f = U.FD{1}.val;
+i_f = I.FD{1}.val * switch_dir;
+
+% time domain signal
+port.ut.time = U.TD{1}.t;
+port.ut.tot = U.TD{1}.val;
+
+port.it.time = I.TD{1}.t;
+port.it.tot = switch_dir*I.TD{1}.val;
+
+
+physical_constants
+k = 2*pi*f/C0*ref_index;
+fc = C0*port.kc/2/pi/ref_index;
+port.beta = sqrt(k.^2 - port.kc^2);
+port.ZL = k * Z0 ./ port.beta; %analytic waveguide impedance
+
+% reference plane shift (lossless)
+if ~isnan(ref_shift)
+ % shift relative to the beginning of the waveguide
+ ref_shift = ref_shift - port.measplanepos;
+ ref_shift = ref_shift * port.drawingunit;
+
+ % store the shifted frequency domain waveforms
+ phase = real(beta)*ref_shift;
+ u_f_shift = u_f .* cos(-phase) + 1i * i_f.*port.ZL .* sin(-phase);
+ i_f_shift = i_f .* cos(-phase) + 1i * u_f./port.ZL .* sin(-phase);
+
+ u_f = u_f_shift;
+ i_f = i_f_shift;
+end
+
+if (ref_ZL < 0)
+ ref_ZL = port.ZL;
+end
+
+port.ZL_ref = ref_ZL;
+
+port.f = f;
+uf_inc = 0.5 * ( u_f + i_f .* ref_ZL );
+if_inc = 0.5 * ( i_f + u_f ./ ref_ZL );
+
+uf_ref = u_f - uf_inc;
+if_ref = if_inc - i_f;
+
+port.uf.tot = u_f;
+port.uf.inc = uf_inc;
+port.uf.ref = uf_ref;
+
+port.if.tot = i_f;
+port.if.inc = if_inc;
+port.if.ref = if_ref;
+
+port.raw.U = U;
+port.raw.I = I;
diff --git a/openEMS/matlab/calc_ypar.m b/openEMS/matlab/calc_ypar.m
new file mode 100644
index 0000000..f6ae1bd
--- /dev/null
+++ b/openEMS/matlab/calc_ypar.m
@@ -0,0 +1,69 @@
+function Y = calc_ypar( f, ports, Sim_Path_Prefix )
+% Y = calc_ypar( f, ports, Sim_Path_Prefix )
+%
+% f: frequency vector (Hz)
+% ports: cell array of ports (see AddMSLPort() and AddLumpedPort())
+% Sim_Path_Prefix: prefix of the simulation dirs (will be postfixed by
+% excitation port number)
+%
+% This function calculates the Y-matrix representation of the ports
+%
+% It is assumed that each port (inside ports) is excited and the
+% corresponding simulation was carried out at Sim_Path + portnr (e.g. for
+% port 2: '/tmp/sim2')
+%
+% Sebastian Held <sebastian.held@uni-due.de>
+% Jun 9 2010
+%
+% See also AddMSLPort AddLumpedPort
+
+% sanitize input arguments
+f = reshape(f,1,[]); % make it a row vector
+
+% prepare result matrix
+maxportnr = max( cellfun(@(x) x.nr, ports) );
+Y = ones(maxportnr,maxportnr,numel(f)) * NaN;
+U = ones(maxportnr,maxportnr,numel(f)) * NaN;
+I = ones(maxportnr,maxportnr,numel(f)) * NaN;
+
+% read time domain simulation results
+for runnr = 1:numel(ports)
+ Sim_Path = [Sim_Path_Prefix num2str(ports{runnr}.nr)];
+ for pnr = 1:numel(ports)
+ if isfield( ports{pnr}, 'v_delta' )
+ % this is an MSLPort
+ temp_U = ReadUI( ['port_ut' num2str(ports{pnr}.nr) 'B'], Sim_Path );
+ temp = ReadUI( {['port_it' num2str(ports{pnr}.nr) 'A'],['port_it' num2str(ports{pnr}.nr) 'B']}, Sim_Path );
+ temp_I.TD{1}.t = temp.TD{1}.t;
+ temp_I.TD{1}.val = (temp.TD{1}.val + temp.TD{2}.val) / 2; % space averaging
+ else
+ % this is a lumped port
+ temp_U = ReadUI( ['port_ut' num2str(ports{pnr}.nr)], Sim_Path );
+ temp_I = ReadUI( ['port_it' num2str(ports{pnr}.nr)], Sim_Path );
+
+% % correct the orientation of the probes (FIXME to be done inside
+% % openEMS)
+% temp_U.TD{1}.val = temp_U.TD{1}.val * (-ports{pnr}.direction);
+ end
+
+% % correct the orientation of the probes (FIXME to be done inside
+% % openEMS)
+% temp_I.TD{1}.val = temp_I.TD{1}.val * ports{pnr}.direction;
+% if runnr == 5 % DEBUG
+% temp_I.TD{1}.val = temp_I.TD{1}.val * -1;
+% end
+
+ % time domain -> frequency domain
+ U(ports{pnr}.nr,ports{runnr}.nr,:) = DFT_time2freq( temp_U.TD{1}.t, temp_U.TD{1}.val, f );
+ I(ports{pnr}.nr,ports{runnr}.nr,:) = DFT_time2freq( temp_I.TD{1}.t, temp_I.TD{1}.val, f );
+
+ % compensate H-field time advance
+ delta_t_2 = temp_I.TD{1}.t(1) - temp_U.TD{1}.t(1); % half time-step (s)
+ I(ports{pnr}.nr,ports{runnr}.nr,:) = squeeze(I(ports{pnr}.nr,ports{runnr}.nr,:)).' .* exp(-1i*2*pi*f*delta_t_2);
+ end
+end
+
+% calc Y-parameters
+for a=1:numel(f)
+ Y(:,:,a) = I(:,:,a) / U(:,:,a);
+end
diff --git a/openEMS/matlab/examples/__deprecated__/MSL2.m b/openEMS/matlab/examples/__deprecated__/MSL2.m
new file mode 100644
index 0000000..31a2600
--- /dev/null
+++ b/openEMS/matlab/examples/__deprecated__/MSL2.m
@@ -0,0 +1,254 @@
+%
+% EXAMPLE / microstrip / MSL2
+%
+% This example shows how to use the MSL-port.
+% The MSL is excited at the center of the computational volume. The
+% boundary at xmin is an absorbing boundary (Mur) and at xmax an electric
+% wall. The reflection coefficient at this wall is S11 = -1.
+% Direction of propagation is x.
+%
+% This example demonstrates:
+% - simple microstrip geometry (made of PEC)
+% - MSL port
+% - MSL analysis
+%
+% You may modify the PEC boundary condition at xmax to become a MUR
+% boundary. This resembles a matched microstrip line.
+%
+% Tested with
+% - Matlab 2009b
+% - Octave 3.3.52
+% - openEMS v0.0.14
+%
+% (C) 2010 Sebastian Held <sebastian.held@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches
+postproc_only = 0;
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; % specify everything in um
+MSL_length = 10000;
+MSL_width = 1000;
+substrate_thickness = 254;
+substrate_epr = 3.66;
+
+% mesh_res = [200 0 0];
+
+%% prepare simulation folder
+Sim_Path = 'tmp';
+Sim_CSX = 'msl2.xml';
+if ~postproc_only
+ [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+ [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+end
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+max_timesteps = 20000;
+min_decrement = 1e-6;
+f_max = 7e9;
+FDTD = InitFDTD( max_timesteps, min_decrement, 'OverSampling', 10 );
+FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 );
+BC = {'MUR' 'MUR' 'PEC' 'PEC' 'PEC' 'PMC'};
+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( [-MSL_length MSL_length], resolution );
+mesh.y = SmoothMeshLines( [-4*MSL_width -MSL_width/2 MSL_width/2 4*MSL_width], resolution );
+mesh.z = SmoothMeshLines( [linspace(0,substrate_thickness,5) 10*substrate_thickness], resolution );
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% substrate
+CSX = AddMaterial( CSX, 'RO4350B' );
+CSX = SetMaterialProperty( CSX, 'RO4350B', 'Epsilon', substrate_epr );
+start = [mesh.x(1), mesh.y(1), 0];
+stop = [mesh.x(end), mesh.y(end), substrate_thickness];
+CSX = AddBox( CSX, 'RO4350B', 0, start, stop );
+
+%% MSL port
+CSX = AddMetal( CSX, 'PEC' );
+portstart = [ 0, -MSL_width/2, substrate_thickness];
+portstop = [ MSL_length, MSL_width/2, 0];
+[CSX,portstruct] = AddMSLPort( CSX, 999, 1, 'PEC', portstart, portstop, [1 0 0], [0 0 1], [], 'excite' );
+
+%% MSL
+start = [-MSL_length, -MSL_width/2, substrate_thickness];
+stop = [ 0, MSL_width/2, substrate_thickness];
+CSX = AddBox( CSX, 'PEC', 999, start, stop ); % priority needs to be higher than
+
+%% define dump boxes
+start = [mesh.x(1), mesh.y(1), substrate_thickness/2];
+stop = [mesh.x(end), mesh.y(end), substrate_thickness/2];
+CSX = AddDump( CSX, 'Et_', 'DumpType', 0,'DumpMode', 2 ); % cell interpolated
+CSX = AddBox( CSX, 'Et_', 0, start, stop );
+CSX = AddDump( CSX, 'Ht_', 'DumpType', 1,'DumpMode', 2 ); % cell interpolated
+CSX = AddBox( CSX, 'Ht_', 0, start, stop );
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure
+if ~postproc_only
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+end
+
+%% run openEMS
+openEMS_opts = '';
+openEMS_opts = [openEMS_opts ' --engine=fastest'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+% openEMS_opts = [openEMS_opts ' --debug-PEC'];
+if ~postproc_only
+ RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
+end
+
+
+%% postprocess
+f = linspace( 1e6, f_max, 1601 );
+U = ReadUI( {'port_ut1A','port_ut1B','port_ut1C','et'}, 'tmp/', f );
+I = ReadUI( {'port_it1A','port_it1B'}, 'tmp/', f );
+
+% Z = (U.FD{1}.val+U.FD{2}.val)/2 ./ I.FD{1}.val;
+% plot( f*1e-9, [real(Z);imag(Z)],'Linewidth',2);
+% xlabel('frequency (GHz)');
+% ylabel('impedance (Ohm)');
+% grid on;
+% legend( {'real','imaginary'}, 'location', 'northwest' )
+% title( 'line impedance (will fail in case of reflections!)' );
+
+figure
+ax = plotyy( U.TD{1}.t/1e-6, [U.TD{1}.val;U.TD{2}.val;U.TD{3}.val], U.TD{4}.t/1e-6, U.TD{4}.val );
+xlabel( 'time (us)' );
+ylabel( 'amplitude (V)' );
+grid on
+title( 'Time domain voltage probes and excitation signal' );
+legend( {'ut1A','ut1B','ut1C','excitation'} );
+% now make the y-axis symmetric to y=0 (align zeros of y1 and y2)
+y1 = ylim(ax(1));
+y2 = ylim(ax(2));
+ylim( ax(1), [-max(abs(y1)) max(abs(y1))] );
+ylim( ax(2), [-max(abs(y2)) max(abs(y2))] );
+
+figure
+plot( I.TD{1}.t/1e-6, [I.TD{1}.val;I.TD{2}.val] );
+xlabel( 'time (us)' );
+ylabel( 'amplitude (A)' );
+grid on
+title( 'Time domain current probes' );
+legend( {'it1A','it1B'} );
+
+figure
+ax = plotyy( U.FD{1}.f/1e9, abs([U.FD{1}.val;U.FD{2}.val;U.FD{3}.val]), U.FD{1}.f/1e9, angle([U.FD{1}.val;U.FD{2}.val;U.FD{3}.val])/pi*180 );
+xlabel( 'frequency (GHz)' );
+ylabel( ax(1), 'amplitude (A)' );
+ylabel( ax(2), 'phase (deg)' );
+grid on
+title( 'Frequency domain voltage probes' );
+legend( {'abs(uf1A)','abs(uf1B)','abs(uf1C)','angle(uf1A)','angle(uf1B)','angle(uf1C)'} );
+
+figure
+ax = plotyy( I.FD{1}.f/1e9, abs([I.FD{1}.val;I.FD{2}.val]), I.FD{1}.f/1e9, angle([I.FD{1}.val;I.FD{2}.val])/pi*180 );
+xlabel( 'frequency (GHz)' );
+ylabel( ax(1), 'amplitude (A)' );
+ylabel( ax(2), 'phase (deg)' );
+grid on
+title( 'Frequency domain current probes' );
+legend( {'abs(if1A)','abs(if1B)','angle(if1A)','angle(if1B)'} );
+
+%% port analysis
+[U,I,beta,ZL] = calcPort( portstruct, Sim_Path, f );
+%% attention! the reflection coefficient S11 is normalized to ZL!
+
+figure
+plot( sin(0:0.01:2*pi), cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+hold on
+plot( 0.5+0.5*sin(0:0.01:2*pi), 0.5*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+plot( [-1 1], [0 0], 'Color', [.7 .7 .7] );
+plot( S11, 'k' );
+plot( real(S11(1)), imag(S11(1)), '*r' );
+axis equal
+title( 'Reflection coefficient S11 at the measurement plane' );
+
+figure
+plot( sin(0:0.01:2*pi), cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+hold on
+plot( 0.5+0.5*sin(0:0.01:2*pi), 0.5*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+plot( [-1 1], [0 0], 'Color', [.7 .7 .7] );
+Z = vi.FD.v.val ./ vi.FD.i.val;
+S11_ = (Z-ZL) ./ (Z+ZL);
+plot( S11_, 'k' );
+plot( real(S11_(1)), imag(S11_(1)), '*r' );
+axis equal
+title( {'Reflection coefficient S11 at the measurement plane' 'calculated from voltages and currents'} );
+
+figure
+plot( f/1e9, [real(S11);imag(S11)], 'Linewidth',2 );
+legend( {'Re(S11)', 'Im(S11)'} );
+ylabel( 'amplitude' );
+xlabel( 'frequency (GHz)' );
+title( 'Reflection coefficient S11 at the measurement plane' );
+
+figure
+plotyy( f/1e9, 20*log10(abs(S11)), f/1e9, angle(S11)/pi*180 );
+legend( {'|S11|', 'angle(S11)'} );
+xlabel( 'frequency (GHz)' );
+ylabel( '|S11| (dB)' );
+title( 'Reflection coefficient S11 at the measurement plane' );
+
+figure
+plot( f/1e9, [real(beta);imag(beta)], 'Linewidth',2 );
+legend( 'Re(beta)', 'Im(beta)' );
+ylabel( 'propagation constant beta (1/m)' );
+xlabel( 'frequency (GHz)' );
+title( 'Propagation constant of the MSL' );
+
+figure
+plot( f/1e9, [real(ZL);imag(ZL)], 'Linewidth',2);
+xlabel('frequency (GHz)');
+ylabel('impedance (Ohm)');
+grid on;
+legend( {'real','imaginary'}, 'location', 'northeast' )
+title( 'Characteristic line impedance ZL' );
+
+%% reference plane shift (to the end of the port)
+ref_shift = abs(portstop(1) - portstart(1));
+[U, I,beta,ZL] = calcPort( portstruct, Sim_Path, f );
+%%
+
+figure
+plotyy( f/1e9, 20*log10(abs(S11)), f/1e9, angle(S11)/pi*180 );
+legend( {'abs(S11)', 'angle(S11)'} );
+xlabel( 'frequency (GHz)' );
+title( 'Reflection coefficient S11 at the reference plane (at the electric wall)' );
+
+figure
+plot( sin(0:0.01:2*pi), cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+hold on
+plot( 0.5+0.5*sin(0:0.01:2*pi), 0.5*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+plot( [-1 1], [0 0], 'Color', [.7 .7 .7] );
+plot( S11, 'k' );
+plot( real(S11(1)), imag(S11(1)), '*r' );
+axis equal
+title( 'Reflection coefficient S11 at the reference plane (at the electric wall)' );
+
+figure
+plot( sin(0:0.01:2*pi), cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+hold on
+plot( 0.5+0.5*sin(0:0.01:2*pi), 0.5*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+plot( [-1 1], [0 0], 'Color', [.7 .7 .7] );
+Z = vi.FD.v.val_shifted ./ vi.FD.i.val_shifted;
+S11_ = (Z-ZL) ./ (Z+ZL);
+plot( S11_, 'k' );
+plot( real(S11_(1)), imag(S11_(1)), '*r' );
+axis equal
+title( {'Reflection coefficient S11 at the reference plane (at the electric wall)' 'calculated from shifted voltages and currents'} );
+
+%% visualize electric and magnetic fields
+% you will find vtk dump files in the simulation folder (tmp/)
+% use paraview to visualize them
diff --git a/openEMS/matlab/examples/antennas/Bi_Quad_Antenna.m b/openEMS/matlab/examples/antennas/Bi_Quad_Antenna.m
new file mode 100644
index 0000000..80ae97f
--- /dev/null
+++ b/openEMS/matlab/examples/antennas/Bi_Quad_Antenna.m
@@ -0,0 +1,139 @@
+%
+% Tutorials / bi-quad antenna
+%
+% Tested with
+% - Octave 3.8.1
+% - openEMS v0.0.32
+%
+% (C) 2011-2014 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+quad_size = 110;
+port_length = 10;
+quad_mesh = 5;
+
+Feed_R = 75;
+
+% size of the simulation box
+SimBox = [800 800 400];
+
+% frequency range of interest
+f_start = 400e6;
+f_stop = 1000e6;
+
+% frequency of interest
+f0 = 700e6;
+freq = linspace(f_start,f_stop,201);
+
+%% setup FDTD parameter & excitation function
+FDTD = InitFDTD( 'endCriteria', 1e-4 );
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+CSX = InitCSX();
+
+%create fixed lines for the antenna outline and port
+mesh.x = [-quad_size*sqrt(2) -quad_size/sqrt(2) 0 quad_size/sqrt(2) quad_size*sqrt(2)];
+mesh.y = [-quad_size/sqrt(2) -port_length/2 0 port_length/2 quad_size/sqrt(2)];
+mesh.z = [0];
+
+mesh = SmoothMesh(mesh, quad_mesh, 1.3);
+
+% add air box
+mesh.x = [mesh.x -SimBox(1)/2 SimBox(1)/2];
+mesh.y = [mesh.y -SimBox(2)/2 SimBox(2)/2];
+mesh.z = [-SimBox(3)/2 0 SimBox(3)/2];
+
+max_res = c0 / (f_stop) / unit / 20; % cell size: lambda/20
+mesh = SmoothMesh(mesh, max_res, 1.4);
+
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create bi-quad
+points(1,1) = 0;
+points(2,1) = port_length/2;
+points(3,1) = 0;
+points(1,end+1) = quad_size/sqrt(2);
+points(2,end) = quad_size/sqrt(2);
+points(1,end+1) = quad_size*sqrt(2);
+points(2,end) = 0;
+points(1,end+1) = quad_size/sqrt(2);
+points(2,end) = -quad_size/sqrt(2);
+points(1,end+1) = 0;
+points(2,end) = -port_length/2;
+points(1,end+1) = -quad_size/sqrt(2);
+points(2,end) = -quad_size/sqrt(2);
+points(1,end+1) = -quad_size*sqrt(2);
+points(2,end) = 0;
+points(1,end+1) = -quad_size/sqrt(2);
+points(2,end) = quad_size/sqrt(2);
+points(1,end+1) = 0;
+points(2,end) = port_length/2;
+
+% create a thin metal wire...
+CSX = AddMetal(CSX,'metal'); %create PEC with propName 'metal'
+CSX = AddCurve(CSX,'metal',10, points);
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start = [0 -port_length/2 0];
+stop = [0 port_length/2 0];
+[CSX port] = AddLumpedPort(CSX,10,0,Feed_R,start,stop,[0 1 0], true);
+
+%% nf2ff calc
+start = [mesh.x(9) mesh.y(9) mesh.z(9)];
+stop = [mesh.x(end-8) mesh.y(end-8) mesh.z(end-8)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);
+
+%% prepare simulation folder
+Sim_Path = 'tmp';
+Sim_CSX = 'bi_quad_ant.xml';
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS([Sim_Path '/' Sim_CSX], FDTD, CSX);
+
+%% show the structure
+CSXGeomPlot([Sim_Path '/' Sim_CSX]);
+
+%% run openEMS
+RunOpenEMS(Sim_Path, Sim_CSX);
+
+%% postprocessing & do the plots
+port = calcPort(port, Sim_Path, freq);
+s11 = port.uf.ref ./ port.uf.inc;
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e9, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+ylim([-30 0]);
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / GHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+%% calculate 3D far field pattern
+phiRange = -180:2.5:180;
+thetaRange = 0:2.5:180;
+
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, thetaRange*pi/180, phiRange*pi/180);
+
+disp( ['directivity: Dmax = ' num2str(10*log10(nf2ff.Dmax)) ' dBi'] );
+
+% plot far-field pattern with Matlab
+figure
+plotFF3D(nf2ff, 'logscale', -20)
+
+%%
+disp( 'Dumping far-field pattern to vtk (use Paraview to visualize)...' );
+DumpFF2VTK('Bi_Quad_Pattern.vtk', nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax, thetaRange, phiRange, 'scale', 0.05);
diff --git a/openEMS/matlab/examples/antennas/Patch_Antenna.m b/openEMS/matlab/examples/antennas/Patch_Antenna.m
new file mode 100644
index 0000000..2011d6f
--- /dev/null
+++ b/openEMS/matlab/examples/antennas/Patch_Antenna.m
@@ -0,0 +1,218 @@
+%
+% EXAMPLE / antennas / patch antenna
+%
+% This example demonstrates how to:
+% - calculate the reflection coefficient of a patch antenna
+%
+%
+% Tested with
+% - Matlab 2009b
+% - Octave 3.3.52
+% - openEMS v0.0.23
+%
+% (C) 2010,2011 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+draw_3d_pattern = 0; % this may take a while...
+use_pml = 0; % use pml boundaries instead of mur
+openEMS_opts = '';
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% width in x-direction
+% length in y-direction
+% main radiation in z-direction
+patch.width = 32.86; % resonant length
+patch.length = 41.37;
+
+substrate.epsR = 3.38;
+substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
+substrate.width = 60;
+substrate.length = 60;
+substrate.thickness = 1.524;
+substrate.cells = 4;
+
+feed.pos = -5.5;
+feed.width = 2;
+feed.R = 50; % feed resistance
+
+% size of the simulation box
+SimBox = [100 100 25];
+
+%% prepare simulation folder
+Sim_Path = 'tmp';
+Sim_CSX = 'patch_ant.xml';
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+ [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+end
+
+%% setup FDTD parameter & excitation function
+max_timesteps = 30000;
+min_decrement = 1e-5; % equivalent to -50 dB
+f0 = 0e9; % center frequency
+fc = 3e9; % 20 dB corner frequency (in this case 0 Hz - 3e9 Hz)
+FDTD = InitFDTD( 'NrTS', max_timesteps, 'EndCriteria', min_decrement );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
+if (use_pml>0)
+ BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'}; % use pml instead of mur
+end
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+% currently, openEMS cannot automatically generate a mesh
+max_res = c0 / (f0+fc) / unit / 20; % cell size: lambda/20
+CSX = InitCSX();
+mesh.x = [-SimBox(1)/2 SimBox(1)/2 -substrate.width/2 substrate.width/2 feed.pos];
+% add patch mesh with 2/3 - 1/3 rule
+mesh.x = [mesh.x -patch.width/2-max_res/2*0.66 -patch.width/2+max_res/2*0.33 patch.width/2+max_res/2*0.66 patch.width/2-max_res/2*0.33];
+mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4); % create a smooth mesh between specified mesh lines
+mesh.y = [-SimBox(2)/2 SimBox(2)/2 -substrate.length/2 substrate.length/2 -feed.width/2 feed.width/2];
+% add patch mesh with 2/3 - 1/3 rule
+mesh.y = [mesh.y -patch.length/2-max_res/2*0.66 -patch.length/2+max_res/2*0.33 patch.length/2+max_res/2*0.66 patch.length/2-max_res/2*0.33];
+mesh.y = SmoothMeshLines( mesh.y, max_res, 1.4 );
+mesh.z = [-SimBox(3)/2 linspace(0,substrate.thickness,substrate.cells) SimBox(3) ];
+mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
+mesh = AddPML( mesh, [8 8 8 8 8 8] ); % add equidistant cells (air around the structure)
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create patch
+CSX = AddMetal( CSX, 'patch' ); % create a perfect electric conductor (PEC)
+start = [-patch.width/2 -patch.length/2 substrate.thickness];
+stop = [ patch.width/2 patch.length/2 substrate.thickness];
+CSX = AddBox(CSX,'patch',10,start,stop);
+
+%% create substrate
+CSX = AddMaterial( CSX, 'substrate' );
+CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa );
+start = [-substrate.width/2 -substrate.length/2 0];
+stop = [ substrate.width/2 substrate.length/2 substrate.thickness];
+CSX = AddBox( CSX, 'substrate', 0, start, stop );
+
+%% create ground (same size as substrate)
+CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
+start(3)=0;
+stop(3) =0;
+CSX = AddBox(CSX,'gnd',10,start,stop);
+
+%% apply the excitation & resist as a current source
+start = [feed.pos-.1 -feed.width/2 0];
+stop = [feed.pos+.1 +feed.width/2 substrate.thickness];
+[CSX] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 0 1], true);
+
+%% dump magnetic field over the patch antenna
+CSX = AddDump( CSX, 'Ht_', 'DumpType', 1, 'DumpMode', 2); % cell interpolated
+start = [-patch.width -patch.length substrate.thickness+1];
+stop = [ patch.width patch.length substrate.thickness+1];
+CSX = AddBox( CSX, 'Ht_', 0, start, stop );
+
+%%nf2ff calc
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', -SimBox/2, SimBox/2);
+
+if (postprocessing_only==0)
+ %% write openEMS compatible xml-file
+ WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+ %% show the structure
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+ %% run openEMS
+ RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
+end
+
+%% postprocessing & do the plots
+freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
+U = ReadUI( {'port_ut1','et'}, 'tmp/', freq ); % time domain/freq domain voltage
+I = ReadUI( 'port_it1', 'tmp/', freq ); % time domain/freq domain current (half time step is corrected)
+
+% plot time domain voltage
+figure
+[ax,h1,h2] = plotyy( U.TD{1}.t/1e-9, U.TD{1}.val, U.TD{2}.t/1e-9, U.TD{2}.val );
+set( h1, 'Linewidth', 2 );
+set( h1, 'Color', [1 0 0] );
+set( h2, 'Linewidth', 2 );
+set( h2, 'Color', [0 0 0] );
+grid on
+title( 'time domain voltage' );
+xlabel( 'time t / ns' );
+ylabel( ax(1), 'voltage ut1 / V' );
+ylabel( ax(2), 'voltage et / V' );
+% now make the y-axis symmetric to y=0 (align zeros of y1 and y2)
+y1 = ylim(ax(1));
+y2 = ylim(ax(2));
+ylim( ax(1), [-max(abs(y1)) max(abs(y1))] );
+ylim( ax(2), [-max(abs(y2)) max(abs(y2))] );
+
+% plot feed point impedance
+figure
+Zin = U.FD{1}.val ./ I.FD{1}.val;
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+uf_inc = 0.5*(U.FD{1}.val + I.FD{1}.val * 50);
+if_inc = 0.5*(I.FD{1}.val - U.FD{1}.val / 50);
+uf_ref = U.FD{1}.val - uf_inc;
+if_ref = I.FD{1}.val - if_inc;
+s11 = uf_ref ./ uf_inc;
+plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+P_in = 0.5*U.FD{1}.val .* conj( I.FD{1}.val );
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+f_res_ind = find(s11==min(s11));
+f_res = freq(f_res_ind);
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+thetaRange = (0:2:359) - 180;
+phiRange = [0 90];
+disp( 'calculating far field at phi=[0 90] deg...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180);
+
+Dlog=10*log10(nf2ff.Dmax);
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(Dlog) ' dBi'] );
+disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);
+
+% display phi
+figure
+plotFFdB(nf2ff,'xaxis','theta','param',[1 2]);
+drawnow
+
+if (draw_3d_pattern==0)
+ return
+end
+
+%% calculate 3D pattern
+phiRange = 0:2:360;
+thetaRange = 0:2:180;
+disp( 'calculating 3D far field...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180, 'Verbose',2,'Outfile','nf2ff_3D.h5');
+figure
+plotFF3D(nf2ff);
+
+
+%% visualize magnetic fields
+% you will find vtk dump files in the simulation folder (tmp/)
+% use paraview to visulaize them
diff --git a/openEMS/matlab/examples/antennas/Patch_Antenna_Array.m b/openEMS/matlab/examples/antennas/Patch_Antenna_Array.m
new file mode 100644
index 0000000..40b3b46
--- /dev/null
+++ b/openEMS/matlab/examples/antennas/Patch_Antenna_Array.m
@@ -0,0 +1,256 @@
+%
+% EXAMPLE / antennas / patch antenna array
+%
+% This example demonstrates how to:
+% - calculate the reflection coefficient of a patch antenna array
+%
+%
+% Tested with
+% - Matlab 2009b
+% - Octave 3.3.52
+% - openEMS v0.0.23
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+draw_3d_pattern = 0; % this may take a (very long) while...
+use_pml = 0; % use pml boundaries instead of mur
+openEMS_opts = '';
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% width in x-direction
+% length in y-direction
+% main radiation in z-direction
+patch.width = 32.86; % resonant length
+patch.length = 41.37;
+
+% define array size and dimensions
+array.xn = 4;
+array.yn = 4;
+array.x_spacing = patch.width * 3;
+array.y_spacing = patch.length * 3;
+
+substrate.epsR = 3.38;
+substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
+substrate.width = 60 + (array.xn-1) * array.x_spacing;
+substrate.length = 60 + (array.yn-1) * array.y_spacing;
+substrate.thickness = 1.524;
+substrate.cells = 4;
+
+feed.pos = -5.5;
+feed.width = 2;
+feed.R = 50; % feed resistance
+
+% size of the simulation box around the array
+SimBox = [50+substrate.width 50+substrate.length 25];
+
+%% prepare simulation folder
+Sim_Path = 'tmp';
+Sim_CSX = 'patch_array.xml';
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+ [status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+end
+
+%% setup FDTD parameter & excitation function
+max_timesteps = 30000;
+min_decrement = 1e-5; % equivalent to -50 dB
+f0 = 0e9; % center frequency
+fc = 3e9; % 10 dB corner frequency (in this case 0 Hz - 3e9 Hz)
+FDTD = InitFDTD( 'NrTS', max_timesteps, 'EndCriteria', min_decrement );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
+if (use_pml>0)
+ BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'}; % use pml instead of mur
+end
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+% currently, openEMS cannot automatically generate a mesh
+max_res = c0 / (f0+fc) / unit / 20; % cell size: lambda/20
+CSX = InitCSX();
+mesh.x = [-SimBox(1)/2 SimBox(1)/2 -substrate.width/2 substrate.width/2];
+mesh.y = [-SimBox(2)/2 SimBox(2)/2 -substrate.length/2 substrate.length/2];
+
+mesh.z = [-SimBox(3)/2 linspace(0,substrate.thickness,substrate.cells) SimBox(3) ];
+mesh.z = SmoothMeshLines( mesh.z, max_res, 1.4 );
+
+for xn=1:array.xn
+ for yn=1:array.yn
+ midX = (array.xn/2 - xn + 1/2) * array.x_spacing;
+ midY = (array.yn/2 - yn + 1/2) * array.y_spacing;
+
+ % feeding mesh
+ mesh.x = [mesh.x midX+feed.pos];
+ mesh.y = [mesh.y midY-feed.width/2 midY+feed.width/2];
+
+ % add patch mesh with 2/3 - 1/3 rule
+ mesh.x = [mesh.x midX-patch.width/2-max_res/2*0.66 midX-patch.width/2+max_res/2*0.33 midX+patch.width/2+max_res/2*0.66 midX+patch.width/2-max_res/2*0.33];
+ % add patch mesh with 2/3 - 1/3 rule
+ mesh.y = [mesh.y midY-patch.length/2-max_res/2*0.66 midY-patch.length/2+max_res/2*0.33 midY+patch.length/2+max_res/2*0.66 midY+patch.length/2-max_res/2*0.33];
+ end
+end
+mesh.x = SmoothMeshLines( mesh.x, max_res, 1.4); % create a smooth mesh between specified mesh lines
+mesh.y = SmoothMeshLines( mesh.y, max_res, 1.4 );
+
+mesh = AddPML( mesh, [8 8 8 8 8 8] ); % add equidistant cells (air around the structure)
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create substrate
+CSX = AddMaterial( CSX, 'substrate' );
+CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon', substrate.epsR, 'Kappa', substrate.kappa);
+start = [-substrate.width/2 -substrate.length/2 0];
+stop = [ substrate.width/2 substrate.length/2 substrate.thickness];
+CSX = AddBox( CSX, 'substrate', 0, start, stop );
+
+%% create ground (same size as substrate)
+CSX = AddMetal( CSX, 'gnd' ); % create a perfect electric conductor (PEC)
+start(3)=0;
+stop(3) =0;
+CSX = AddBox(CSX,'gnd',10,start,stop);
+%%
+CSX = AddMetal( CSX, 'patch' ); % create a perfect electric conductor (PEC)
+number = 1;
+for xn=1:array.xn
+ for yn=1:array.yn
+
+ midX = (array.xn/2 - xn + 1/2) * array.x_spacing;
+ midY = (array.yn/2 - yn + 1/2) * array.y_spacing;
+
+ % create patch
+ start = [midX-patch.width/2 midY-patch.length/2 substrate.thickness];
+ stop = [midX+patch.width/2 midY+patch.length/2 substrate.thickness];
+ CSX = AddBox(CSX,'patch',10,start,stop);
+
+ % apply the excitation & resist as a current source
+ start = [midX+feed.pos-feed.width/2 midY-feed.width/2 0];
+ stop = [midX+feed.pos+feed.width/2 midY+feed.width/2 substrate.thickness];
+ [CSX] = AddLumpedPort(CSX, 5, number,feed.R, start, stop,[0 0 1],true);
+ number=number+1;
+ end
+end
+
+%%nf2ff calc
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', -SimBox/2, SimBox/2);
+
+if (postprocessing_only==0)
+ %% write openEMS compatible xml-file
+ WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+ %% show the structure
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+ %% run openEMS
+ RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
+end
+
+%% postprocessing & do the plots
+freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
+U = ReadUI( {'port_ut1','et'}, 'tmp/', freq ); % time domain/freq domain voltage
+I = ReadUI( 'port_it1', 'tmp/', freq ); % time domain/freq domain current (half time step is corrected)
+
+% plot time domain voltage
+figure
+[ax,h1,h2] = plotyy( U.TD{1}.t/1e-9, U.TD{1}.val, U.TD{2}.t/1e-9, U.TD{2}.val );
+set( h1, 'Linewidth', 2 );
+set( h1, 'Color', [1 0 0] );
+set( h2, 'Linewidth', 2 );
+set( h2, 'Color', [0 0 0] );
+grid on
+title( 'time domain voltage' );
+xlabel( 'time t / ns' );
+ylabel( ax(1), 'voltage ut1 / V' );
+ylabel( ax(2), 'voltage et / V' );
+% now make the y-axis symmetric to y=0 (align zeros of y1 and y2)
+y1 = ylim(ax(1));
+y2 = ylim(ax(2));
+ylim( ax(1), [-max(abs(y1)) max(abs(y1))] );
+ylim( ax(2), [-max(abs(y2)) max(abs(y2))] );
+
+% plot feed point impedance
+figure
+Zin = U.FD{1}.val ./ I.FD{1}.val;
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+uf_inc = 0.5*(U.FD{1}.val + I.FD{1}.val * 50);
+if_inc = 0.5*(I.FD{1}.val - U.FD{1}.val / 50);
+uf_ref = U.FD{1}.val - uf_inc;
+if_ref = I.FD{1}.val - if_inc;
+s11 = uf_ref ./ uf_inc;
+plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+%%
+number = 1;
+P_in = 0;
+for xn=1:array.xn
+ for yn=1:array.yn
+
+ U = ReadUI( ['port_ut' int2str(number)], 'tmp/', freq ); % time domain/freq domain voltage
+ I = ReadUI( ['port_it' int2str(number)], 'tmp/', freq ); % time domain/freq domain current (half time step is corrected)
+
+ P_in = P_in + 0.5*U.FD{1}.val .* conj( I.FD{1}.val );
+ number=number+1;
+ end
+end
+
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+f_res_ind = find(s11==min(s11));
+f_res = freq(f_res_ind);
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+thetaRange = (0:2:359) - 180;
+phiRange = [0 90];
+r = 1; % evaluate fields at radius r
+disp( 'calculating far field at phi=[0 90] deg...' );
+
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180);
+
+Dlog=10*log10(nf2ff.Dmax);
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(Dlog) ' dBi'] );
+disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);
+
+% display phi
+figure
+plotFFdB(nf2ff,'xaxis','theta','param',[1 2]);
+drawnow
+
+if (draw_3d_pattern==0)
+ return
+end
+
+%% calculate 3D pattern
+phiRange = 0:3:360;
+thetaRange = unique([0:0.5:15 10:3:180]);
+disp( 'calculating 3D far field...' );
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180, 'Verbose',2,'Outfile','nf2ff_3D.h5');
+figure
+plotFF3D(nf2ff);
+
+%% visualize magnetic fields
+% you will find vtk dump files in the simulation folder (tmp/)
+% use paraview to visulaize them
diff --git a/openEMS/matlab/examples/antennas/infDipol.m b/openEMS/matlab/examples/antennas/infDipol.m
new file mode 100644
index 0000000..0a43bc8
--- /dev/null
+++ b/openEMS/matlab/examples/antennas/infDipol.m
@@ -0,0 +1,121 @@
+%
+% infinitesimal dipole example
+%
+
+close all
+clear
+clc
+
+postprocessing_only = 0;
+
+physical_constants
+
+% setup the simulation
+drawingunit = 1e-6; % specify everything in um
+Sim_Path = 'tmp';
+Sim_CSX = 'tmp.xml';
+
+f_max = 1e9;
+lambda = c0/f_max;
+
+% setup geometry values
+dipole_length = lambda/50 /drawingunit;
+
+
+dipole_orientation = 3; % 1,2,3: x,y,z
+
+
+CSX = InitCSX();
+
+% create an equidistant mesh
+mesh.x = -dipole_length*10:dipole_length/2:dipole_length*10;
+mesh.y = -dipole_length*10:dipole_length/2:dipole_length*10;
+mesh.z = -dipole_length*10:dipole_length/2:dipole_length*10;
+
+% excitation
+ex_vector = [0 0 0];
+ex_vector(dipole_orientation) = 1;
+start = ex_vector * -dipole_length/2;
+stop = ex_vector * dipole_length/2;
+CSX = AddExcitation( CSX, 'infDipole', 1, ex_vector );
+% enlarge the box to be sure that one mesh line is covered by it
+start = start - [0.1 0.1 0.1] * dipole_length/2;
+stop = stop + [0.1 0.1 0.1] * dipole_length/2;
+CSX = AddBox( CSX, 'infDipole', 1, start, stop );
+
+% NFFF contour
+start = [mesh.x(1) mesh.y(1) mesh.z(1) ];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end) ];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);
+
+% add space for PML
+mesh = AddPML( mesh, [8 8 8 8 8 8] );
+% define the mesh
+CSX = DefineRectGrid( CSX, drawingunit, mesh );
+
+if ~postprocessing_only
+ % setup FDTD parameters & excitation function
+ max_timesteps = 2000;
+ min_decrement = 1e-6;
+ FDTD = InitFDTD( 'NrTS', max_timesteps, 'EndCriteria', min_decrement, 'OverSampling',10 );
+ 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 );
+
+ % Write openEMS compatible xml-file
+ [~,~,~] = rmdir(Sim_Path,'s');
+ [~,~,~] = mkdir(Sim_Path);
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+ % take a view at the "structure"
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+ % define openEMS options and start simulation
+ openEMS_opts = '';
+ RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
+end
+
+%% post processing
+disp( ' ' );
+disp( ' ********************************************************** ' );
+disp( ' ' );
+
+% calculate the far field at phi=0 degrees and at phi=90 degrees
+thetaRange = 0:0.5:359;
+disp( 'calculating far field at phi=[0 90] deg..' );
+nf2ff = CalcNF2FF( nf2ff, Sim_Path, f_max, thetaRange/180*pi, [0 pi/2], 'Mode', 1 );
+Prad = nf2ff.Prad;
+Dmax = nf2ff.Dmax;
+
+theta_HPBW = interp1(nf2ff.E_norm{1}(find(thetaRange<90),1)/max(nf2ff.E_norm{1}(find(thetaRange<90),1)),thetaRange(find(thetaRange<90)),1/sqrt(2))*2;
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(Prad)] );
+disp( ['directivity: Dmax = ' num2str(Dmax)] );
+disp( ['theta_HPBW = ' num2str(theta_HPBW) ' °']);
+
+% display polar plot for the e-field magnitude for phi = 0 & 90 deg
+figure
+polarFF(nf2ff,'xaxis','theta','param',[1 2]);
+
+%% calculate the far field at theta=90 degrees
+phiRange = 0:2:359;
+disp( 'calculating far field at theta=90 deg..' );
+nf2ff = CalcNF2FF( nf2ff, Sim_Path, f_max, 90/180*pi, phiRange/180*pi, 'Mode', 1 );
+
+% display polar plot
+figure
+polarFF(nf2ff,'xaxis','phi','param',1);
+
+%% calculate 3D pattern
+phiRange = 0:5:360;
+thetaRange = 0:5:180;
+disp( 'calculating 3D far field...' );
+nf2ff = CalcNF2FF( nf2ff, Sim_Path, f_max, thetaRange/180*pi, phiRange/180*pi, 'Mode', 1 );
+figure
+plotFF3D(nf2ff)
+
+%%
+E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:));
+DumpFF2VTK([Sim_Path '/FF_pattern.vtk'],E_far_normalized, thetaRange, phiRange);
+disp(['view the farfield pattern "' Sim_Path '/FF_pattern.vtk" using paraview' ]);
diff --git a/openEMS/matlab/examples/antennas/inverted_f.m b/openEMS/matlab/examples/antennas/inverted_f.m
new file mode 100644
index 0000000..175f94c
--- /dev/null
+++ b/openEMS/matlab/examples/antennas/inverted_f.m
@@ -0,0 +1,205 @@
+%
+% EXAMPLE / antennas / inverted-f antenna (ifa) 2.4GHz
+%
+% This example demonstrates how to:
+% - calculate the reflection coefficient of an ifa
+% - calculate farfield of an ifa
+%
+% Tested with
+% - Octave 3.7.5
+% - openEMS v0.0.30+ (git 10.07.2013)
+%
+% (C) 2013 Stefan Mahr <dac922@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% substrate.width
+% _______________________________________________ __ substrate.
+% | A ifa.l |\ __ thickness
+% | |ifa.e __________________________ | |
+% | | | ___ _________________| w2 | |
+% | | ifa.h | | || | |
+% |_V_____________|___|___||______________________| |
+% | .w1 .wf\ | |
+% | |.fp| \ | |
+% | | feed point | |
+% | | | | substrate.length
+% |<- substrate.width/2 ->| | |
+% | | |
+% |_______________________________________________| |
+% \_______________________________________________\|
+%
+% Note: It's not checked whether your settings make sense, so check
+% graphical output carefully.
+%
+substrate.width = 80; % width of substrate
+substrate.length = 80; % length of substrate
+substrate.thickness = 1.5; % thickness of substrate
+substrate.cells = 4; % use 4 cells for meshing substrate
+
+ifa.h = 8; % height of short circuit stub
+ifa.l = 22.5; % length of radiating element
+ifa.w1 = 4; % width of short circuit stub
+ifa.w2 = 2.5; % width of radiating element
+ifa.wf = 1; % width of feed element
+ifa.fp = 4; % position of feed element relative to short
+ % circuit stub
+ifa.e = 10; % distance to edge
+
+
+% substrate setup
+substrate.epsR = 4.3;
+substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;
+
+%setup feeding
+feed.R = 50; %feed resistance
+
+%open AppCSXCAD and show ifa
+show = 1;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% size of the simulation box
+SimBox = [substrate.width*2 substrate.length*2 150];
+
+%% setup FDTD parameter & excitation function
+f0 = 2.5e9; % center frequency
+fc = 1e9; % 20 dB corner frequency
+
+FDTD = InitFDTD('NrTS', 60000 );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+CSX = InitCSX();
+
+%initialize the mesh with the "air-box" dimensions
+mesh.x = [-SimBox(1)/2 SimBox(1)/2];
+mesh.y = [-SimBox(2)/2 SimBox(2)/2];
+mesh.z = [-SimBox(3)/2 SimBox(3)/2];
+
+%% create substrate
+CSX = AddMaterial( CSX, 'substrate');
+CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon',substrate.epsR, 'Kappa', substrate.kappa);
+start = [-substrate.width/2 -substrate.length/2 0];
+stop = [ substrate.width/2 substrate.length/2 substrate.thickness];
+CSX = AddBox( CSX, 'substrate', 1, start, stop );
+% add extra cells to discretize the substrate thickness
+mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];
+
+%% create ground plane
+CSX = AddMetal( CSX, 'groundplane' ); % create a perfect electric conductor (PEC)
+start = [-substrate.width/2 -substrate.length/2 substrate.thickness];
+stop = [ substrate.width/2 substrate.length/2-ifa.e substrate.thickness];
+CSX = AddBox(CSX, 'groundplane', 10, start,stop);
+
+%% create ifa
+CSX = AddMetal( CSX, 'ifa' ); % create a perfect electric conductor (PEC)
+tl = [0,substrate.length/2-ifa.e,substrate.thickness]; % translate
+start = [0 0.5 0] + tl;
+stop = start + [ifa.wf ifa.h-0.5 0];
+CSX = AddBox( CSX, 'ifa', 10, start, stop); % feed element
+start = [-ifa.fp 0 0] + tl;
+stop = start + [-ifa.w1 ifa.h 0];
+CSX = AddBox( CSX, 'ifa', 10, start, stop); % short circuit stub
+start = [(-ifa.fp-ifa.w1) ifa.h 0] + tl;
+stop = start + [ifa.l -ifa.w2 0];
+CSX = AddBox( CSX, 'ifa', 10, start, stop); % radiating element
+
+ifa_mesh = DetectEdges(CSX, [], 'SetProperty','ifa');
+mesh.x = [mesh.x SmoothMeshLines(ifa_mesh.x, 0.5)];
+mesh.y = [mesh.y SmoothMeshLines(ifa_mesh.y, 0.5)];
+
+%% apply the excitation & resist as a current source
+start = [0 0 0] + tl;
+stop = start + [ifa.wf 0.5 0];
+[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 1 0], true);
+
+%% finalize the mesh
+% generate a smooth mesh with max. cell size: lambda_min / 20
+mesh = DetectEdges(CSX, mesh);
+mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20);
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition
+start = [mesh.x(4) mesh.y(4) mesh.z(4)];
+stop = [mesh.x(end-3) mesh.y(end-3) mesh.z(end-3)];
+[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);
+
+%% prepare simulation folder
+Sim_Path = 'tmp_IFA';
+Sim_CSX = 'IFA.xml';
+
+try confirm_recursive_rmdir(false,'local'); end
+
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure
+if (show == 1)
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+end
+
+
+%% run openEMS
+RunOpenEMS( Sim_Path, Sim_CSX); %RunOpenEMS( Sim_Path, Sim_CSX, '--debug-PEC -v');
+
+%% postprocessing & do the plots
+freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
+port = calcPort(port, Sim_Path, freq);
+
+Zin = port.uf.tot ./ port.if.tot;
+s11 = port.uf.ref ./ port.uf.inc;
+P_in = real(0.5 * port.uf.tot .* conj( port.if.tot )); % antenna feed power
+
+% plot feed point impedance
+figure
+plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
+title( 'feed point impedance' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'impedance Z_{in} / Ohm' );
+legend( 'real', 'imag' );
+
+% plot reflection coefficient S11
+figure
+plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
+grid on
+title( 'reflection coefficient S_{11}' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'reflection coefficient |S_{11}|' );
+
+drawnow
+
+%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%find resonance frequncy from s11
+f_res_ind = find(s11==min(s11));
+f_res = freq(f_res_ind);
+
+%%
+disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
+thetaRange = (0:2:180);
+phiRange = (0:2:360) - 180;
+nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5');
+
+plotFF3D(nf2ff)
+
+% display power and directivity
+disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
+disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
+disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);
+
+E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax;
+DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,1e-3);
diff --git a/openEMS/matlab/examples/optimizer/optimizer_asco.m b/openEMS/matlab/examples/optimizer/optimizer_asco.m
new file mode 100644
index 0000000..e405653
--- /dev/null
+++ b/openEMS/matlab/examples/optimizer/optimizer_asco.m
@@ -0,0 +1,36 @@
+%
+% asco optimizer example -- optimize the turn number of a coil
+%
+% You need asco from http://asco.sf.net
+% This is the main script.
+% - optimizer_simfun.m starts the simulator with a parameter set from
+% asco
+%
+% The goal is evaluated inside optimizer_simfun() to get as close to 2 uH.
+
+% clear
+clear
+close all
+clc
+
+% setup the parameters
+params = [];
+params(end+1).name = 'turns';
+params(end).range = [1 30];
+params(end).value = 4;
+params(end).step = 1;
+params(end).active = 1; % this parameter is to be optimized
+
+% setup the simulation function
+folder = fileparts( mfilename('fullpath') );
+options.simfun = [folder '/optimizer_simfun.m'];
+
+% additional options
+% options.octave_exe = 'octave'; % must be newer than 3.2.4 (3.3.54 works)
+options.clean = 1;
+
+% start the optimization
+[params_opt,result] = optimize( 'opttmp', params, options, 'asco' );
+
+% display best value
+disp( ['ASCO found the optimum turn number: ' num2str(params_opt(1).value) ' result: ' num2str(result)] );
diff --git a/openEMS/matlab/examples/optimizer/optimizer_simfun.m b/openEMS/matlab/examples/optimizer/optimizer_simfun.m
new file mode 100644
index 0000000..14152de
--- /dev/null
+++ b/openEMS/matlab/examples/optimizer/optimizer_simfun.m
@@ -0,0 +1,134 @@
+function result = optimizer_simfun( folder, params )
+%
+% simulation function
+%
+% the variable params contains the simulation parameters
+
+disp( [mfilename ': SIMULATING...'] );
+
+if nargin == 0
+ % visualize the structure if called without parameters
+ folder = 'tmp';
+ params.turns = 10;
+end
+
+oldpwd = pwd;
+[a,a,a] = mkdir( folder );
+cd( folder );
+
+% create the structure
+f_max = 50e6;
+structure( params, 'tmp.xml', f_max );
+
+if nargin == 0
+ % visualize the structure
+ CSXGeomPlot('tmp.xml');
+ return;
+end
+
+% start simulation
+RunOpenEMS( '.', 'tmp.xml', '--engine=fastest' );
+
+% postprocess the results
+L = postproc( 'tmp.xml', f_max );
+disp( ['DONE. L = ' num2str(L(1)/1e-6) ' uH'] );
+
+% calculate result
+goal = 2e-6; % specify the goal: 2 uH
+result = abs(goal - L(1)); % costs must not be negative
+
+% restore curent folder
+cd( oldpwd );
+
+
+
+
+% -------------------------------------------------------------------------
+% -------------------------------------------------------------------------
+
+function CSX = structure( params, filename, f_max )
+% CSX = structure( params, filename )
+
+unit = 1e-3; % specify length in mm
+lambda = 3e8/f_max;
+resolution = lambda/15/unit;
+mesh_size = 1.5;
+radius = 10;
+turns = params.turns;
+height = 4 * turns;
+feed_length = 10;
+
+CSX = InitCSX();
+
+%% create coil
+p1 = create_coil( radius, height, turns );
+p = p1(:,end) + [feed_length;0;0];
+p1 = [p1 p];
+p = p1(:,1) + [feed_length;0;0];
+p1 = [p p1];
+CSX = AddMetal(CSX,'PEC1');
+CSX = AddCurve(CSX, 'PEC1', 0, p1);
+
+%% create mesh
+extraspace = 5*radius;
+mesh.x = linspace(-radius,radius,ceil(2*radius/mesh_size));
+mesh.x = [mesh.x mesh.x(1)-extraspace mesh.x(end)+extraspace];
+mesh.x = [mesh.x p1(1,1) p1(1,1)-mesh_size p1(1,1)+mesh_size];
+mesh.x = SmoothMeshLines2( mesh.x, resolution );
+mesh.y = linspace(-radius,radius,ceil(2*radius/mesh_size));
+mesh.y = [mesh.y mesh.y(1)-extraspace mesh.y(end)+extraspace];
+mesh.y = SmoothMeshLines2( mesh.y, resolution );
+mesh.z = linspace(0,height,ceil(height/mesh_size));
+mesh.z = [mesh.z mesh.z(1)-extraspace mesh.z(end)+extraspace];
+% mesh.z = [mesh.z p1(3,1) p1(3,1)-mesh_size p1(3,1)+mesh_size];
+mesh.z = SmoothMeshLines2( mesh.z, resolution );
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+
+%% create port
+[CSX,port] = AddCurvePort( CSX, 10, 1, 50, p1(:,1), p1(:,end), 'excite' );
+
+if nargin > 1
+ max_timesteps = 100000;
+ min_decrement = 1e-5;
+ FDTD = InitFDTD( max_timesteps, min_decrement );
+ FDTD = SetGaussExcite( FDTD, 0, f_max );
+ BC = {'PEC' 'PEC' 'PEC' 'PEC' 'PMC' 'PMC'};
+ FDTD = SetBoundaryCond( FDTD, BC );
+
+ WriteOpenEMS( filename, FDTD, CSX );
+end
+
+
+function p = create_coil(coil_rad,coil_length,coil_turns,coil_res,winding_direction,direction,offset,angle_offset)
+if nargin < 8, angle_offset = 0; end
+if nargin < 7, offset = [0; 0; 0]; end
+if nargin < 6, direction = +1; end
+if nargin < 5, winding_direction = +1; end
+if nargin < 4, coil_res = 30; end
+dt = 1/coil_res;
+height = 0;
+
+p = [];
+while abs(height) < coil_length
+ angle = height / (coil_length/coil_turns) * 2*pi;
+ p(1,end+1) = coil_rad * cos(angle*winding_direction+angle_offset);
+ p(2,end) = coil_rad * sin(angle*winding_direction+angle_offset);
+ p(3,end) = height * direction;
+ p(:,end) = p(:,end) + offset;
+ height = height + coil_length/coil_turns * dt;
+end
+
+
+
+function L = postproc( filename, f_max )
+freq = linspace(0,f_max,201);
+freq(1) = []; % delete DC component
+
+folder = fileparts(filename);
+U = ReadUI( 'port_ut1', folder, freq );
+I = ReadUI( 'port_it1', folder, freq );
+Z = U.FD{1}.val ./ I.FD{1}.val;
+
+L = imag(Z) ./ (2*pi*freq);
+L = reshape( L, 1, [] ); % row vector
diff --git a/openEMS/matlab/examples/other/Helix.m b/openEMS/matlab/examples/other/Helix.m
new file mode 100644
index 0000000..18e97c9
--- /dev/null
+++ b/openEMS/matlab/examples/other/Helix.m
@@ -0,0 +1,154 @@
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+feed_length=10;
+wire_rad = sqrt(1.4/pi);
+mesh_size = wire_rad;
+coil_rad = 10;
+coil_length = 50;
+coil_turns = 8;
+coil_res = 10;
+port_length = mesh_size; %coil_length/2;
+port_resist = 1000;
+
+f_max = 100e6;
+f_excite = 300e6;
+
+%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+% openEMS_opts = [openEMS_opts ' --debug-operator'];
+
+openEMS_opts = [openEMS_opts ' --disable-dumps --engine=fastest'];
+% openEMS_opts = [openEMS_opts ' --engine=sse-compressed'];
+
+Sim_Path = 'tmp';
+Sim_CSX = 'helix.xml';
+
+[status, message, messageid] = rmdir(Sim_Path,'s');
+[status,message,messageid] = mkdir(Sim_Path);
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(30000,1e-6);
+FDTD = SetGaussExcite(FDTD,f_excite/2,f_excite/2);
+BC = [1 1 1 1 1 1];
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+add_Lines = mesh_size * 1.5.^(1:10);
+add_Lines = add_Lines(find(add_Lines<(3e8/f_excite)/10*1e3));
+
+CSX = InitCSX();
+mesh.x = -coil_rad-mesh_size : mesh_size : coil_rad+mesh_size+feed_length;
+mesh.x = [mesh.x(1)-add_Lines mesh.x mesh.x(end)+add_Lines ];
+mesh.y = -coil_rad-mesh_size : mesh_size : coil_rad+mesh_size;
+mesh.y = [mesh.y(1)-add_Lines mesh.y mesh.y(end)+add_Lines ];
+mesh.z = -mesh_size : mesh_size : coil_length+mesh_size;
+mesh.z = [mesh.z(1)-add_Lines mesh.z mesh.z(end)+add_Lines ];
+CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+%% build/define helix %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddMaterial(CSX,'copper');
+CSX = SetMaterialProperty(CSX,'copper','Kappa',56e6);
+
+dt = 1.0/coil_res;
+height=0;
+wire.Vertex = {};
+p(1,1) = coil_rad + feed_length;
+p(2,1) = 0;
+p(3,1) = 0.5*(coil_length-port_length);
+p(1,2) = coil_rad + feed_length;
+p(2,2) = 0;
+p(3,2) = 0;
+count=2;
+for n=0:coil_turns-1
+ for m=0:coil_res
+ count = count + 1;
+ p(1,count) = coil_rad * cos(2*pi*dt*m);
+ p(2,count) = coil_rad * sin(2*pi*dt*m);
+ p(3,count) = height + coil_length/coil_turns * dt*m;
+ end
+ height = height + coil_length/coil_turns;
+end
+p(1,count+1) = coil_rad + feed_length;
+p(2,count+1) = 0;
+p(3,count+1) = coil_length;
+p(1,count+2) = coil_rad + feed_length;
+p(2,count+2) = 0;
+p(3,count+2) = 0.5*(coil_length+port_length);
+CSX = AddWire(CSX, 'copper', 0, p, wire_rad);
+
+%% apply the excitation & resist as a current source%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddMaterial(CSX,'resist');
+kappa = port_length/port_resist/wire_rad^2/pi/1e-3;
+CSX = SetMaterialProperty(CSX,'resist','Kappa',kappa);
+
+start=[coil_rad+feed_length 0 (coil_length-port_length)/2];
+stop=[coil_rad+feed_length 0 (coil_length+port_length)/2];
+%start(3)=(coil_length-port_length)/2;stop(3)=(coil_length+port_length)/2;
+CSX = AddCylinder(CSX,'resist',5 ,start,stop,wire_rad);
+
+CSX = AddExcitation(CSX,'excite',0,[0 0 1]);
+CSX = AddCylinder(CSX,'excite', 0 ,start,stop,wire_rad);
+
+%% define voltage calc boxes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%voltage calc
+CSX = AddProbe(CSX,'ut1',0);
+CSX = AddBox(CSX,'ut1', 0 ,stop,start);
+
+%current calc
+CSX = AddProbe(CSX,'it1',1);
+start(3) = coil_length/2+mesh_size;stop(3) = coil_length/2+mesh_size;
+start(1) = start(1)-2;start(2) = start(2)-2;
+stop(1) = stop(1)+2;stop(2) = stop(2)+2;
+CSX = AddBox(CSX,'it1', 0 ,start,stop);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et_');
+start = [mesh.x(1) , 0 , mesh.z(1)];
+stop = [mesh.x(end) , 0 , mesh.z(end)];
+CSX = AddBox(CSX,'Et_',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht_','DumpType',1);
+start = [mesh.x(1) , 0 , mesh.z(1)];
+stop = [mesh.x(end) , 0 , mesh.z(end)];
+CSX = AddBox(CSX,'Ht_',0 , start,stop);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+%% run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+
+%% postproc & do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+U = ReadUI('ut1','tmp/');
+I = ReadUI('it1','tmp/');
+
+Z = U.FD{1}.val./I.FD{1}.val;
+f = U.FD{1}.f;
+L = imag(Z)./(f*2*pi);
+R = real(Z);
+ind = find(f<f_max);
+
+subplot(2,1,1);
+plot(f(ind)*1e-6,L(ind)*1e9,'Linewidth',2);
+xlabel('frequency (MHz)');
+ylabel('coil inductance (nH)');
+grid on;
+subplot(2,1,2);
+plot(f(ind)*1e-6,R(ind),'Linewidth',2);
+hold on
+plot(f(ind)*1e-6,imag(Z(ind)),'r','Linewidth',2);
+xlabel('frequency (MHz)');
+ylabel('resistance (Ohm)');
+grid on;
+legend( {'real','imaginary'}, 'location', 'northwest' )
+
+figure
+plot(U.TD{1}.t/1e-6,U.TD{1}.val,'Linewidth',2);
+xlabel('time (us)');
+ylabel('amplitude (V)');
+grid on;
diff --git a/openEMS/matlab/examples/other/LumpedElement.m b/openEMS/matlab/examples/other/LumpedElement.m
new file mode 100644
index 0000000..d44094c
--- /dev/null
+++ b/openEMS/matlab/examples/other/LumpedElement.m
@@ -0,0 +1,158 @@
+%
+% EXAMPLE / other / lumped elements
+%
+% This example demonstrates how to:
+% - use lumped elements
+%
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.21-3
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+f_max = 100e6;
+f_excite = 300e6;
+SimBox = 100;
+mesh_size = 2;
+
+Lumped.R = 1000;
+Lumped.C = 10e-12;
+
+% the parasitice inductance of the feeding has to be deduced with a R=0
+% simulation
+parasitic_L = 63e-9;
+
+%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+% openEMS_opts = [openEMS_opts ' --debug-operator'];
+
+Sim_Path = 'tmp';
+Sim_CSX = 'lumped.xml';
+
+[status, message, messageid] = rmdir(Sim_Path,'s');
+[status,message,messageid] = mkdir(Sim_Path);
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(30000,1e-6);
+FDTD = SetGaussExcite(FDTD,f_excite/2,f_excite/2);
+BC = [1 1 1 1 1 1];
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = SmoothMeshLines([-SimBox/2,+SimBox/2],mesh_size);
+mesh.y = SmoothMeshLines([-SimBox/2,+SimBox/2],mesh_size);
+mesh.z = SmoothMeshLines([-SimBox/2,+SimBox/2],mesh_size);
+CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+
+%% create structure
+% insert curve port
+start = [ 10 -10 0];
+stop = [ 10 10 0];
+CSX = AddCurvePort(CSX,0,1,100,start,stop,'excite');
+
+% insert lumped element
+CSX = AddLumpedElement( CSX, 'Capacitor', 1, 'C', Lumped.C, 'R', Lumped.R);
+start = [ -14 -4 -4];
+stop = [ -6 4 4];
+CSX = AddBox( CSX, 'Capacitor', 0, start, stop );
+
+% insert feeding wire
+CSX = AddMetal(CSX,'metal');
+%first point
+points(1,1) = -10;
+points(2,1) = 4;
+points(3,1) = 0;
+%second point
+points(1,2) = -10;
+points(2,2) = 15;
+points(3,2) = 0;
+%3 point
+points(1,end+1) = 10;
+points(2,end) = 15;
+points(3,end) = 0;
+%4 point
+points(1,end+1) = 10;
+points(2,end) = 10;
+points(3,end) = 0;
+CSX = AddCurve(CSX,'metal', 10, points);
+
+points(2,:) = -1*points(2,:);
+CSX = AddCurve(CSX,'metal', 10, points);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+% CSXGeomPlot([Sim_Path '/' Sim_CSX]);
+
+%% run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+
+%% postproc & do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+f = linspace(1e6,f_max,1001);
+w = 2*pi*f;
+% read currents and voltages
+U = ReadUI('port_ut1','tmp/',f);
+I = ReadUI('port_it1','tmp/',f);
+
+% calculate analytic impedance
+if (Lumped.R>=0)
+ Z_a = Lumped.R*(1-1i*w*Lumped.C*Lumped.R)./(1+(w*Lumped.C*Lumped.R).^2);
+else
+ Z_a = -1i./(w*Lumped.C);
+end
+
+% calculate numerical impedance
+Z = U.FD{1}.val./I.FD{1}.val;
+
+% remove parasitic feeding effects
+Z = Z - 1i*w*parasitic_L;
+
+L = imag(Z)./w;
+C = -1./(w.*imag(Z));
+C(find(C<0)) = nan;
+L(find(L<0)) = nan;
+R = real(Z);
+
+subplot(2,1,1);
+plot(f*1e-6,C*1e12,'Linewidth',2);
+xlabel('frequency (MHz)');
+ylabel('capacitance (pF)');
+grid on;
+subplot(2,1,2);
+plot(f*1e-6,L*1e9,'Linewidth',2);
+xlabel('frequency (MHz)');
+ylabel('inductance (nH)');
+grid on;
+
+figure();
+plot(f*1e-6,R,'Linewidth',2);
+hold on
+plot(f*1e-6,imag(Z),'r--','Linewidth',2);
+
+plot(f*1e-6,real(Z_a),'g-.','Linewidth',1);
+plot(f*1e-6,imag(Z_a),'m--','Linewidth',1);
+
+xlabel('frequency (MHz)');
+ylabel('resistance (Ohm)');
+grid on;
+legend( '\Re\{Z\}','\Im\{Z\}','\Re\{Z_{analytisch}\}','\Im\{Z_{analytisch}\}', 'location', 'northeast' )
+
+figure();
+errorR = (R-real(Z_a))./R*100;
+errorX = (imag(Z)-imag(Z_a))./imag(Z)*100;
+plot(f*1e-6,errorR,'Linewidth',2);
+hold on
+grid on;
+plot(f*1e-6,errorX,'r--','Linewidth',2);
+xlabel('frequency (MHz)');
+ylabel('error (%)');
diff --git a/openEMS/matlab/examples/other/Metamaterial_PlaneWave_Drude.m b/openEMS/matlab/examples/other/Metamaterial_PlaneWave_Drude.m
new file mode 100644
index 0000000..db72b3e
--- /dev/null
+++ b/openEMS/matlab/examples/other/Metamaterial_PlaneWave_Drude.m
@@ -0,0 +1,147 @@
+%%%%%%%%%%%%%%%%%%%%%%%
+% example demonstrating double drude meta-material
+%
+% tested with openEMS v0.0.28
+%
+% author: Thorsten Liebig @ 2010,2012
+%%%%%%%%%%%%%%%%%%%%%%%
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+postproc_only = 0; %set to 1 if the simulation is already done
+
+Settings = [];
+Settings.LogFile = 'openEMS.log';
+
+pic_size = round([1400 1400/4]); %define the animation picture size
+
+%simulation domain setup (in mm)
+length = 500;
+width = 10;
+mesh_res = 0.5; % mesh resolution
+height = 3*mesh_res; % hight is ony 3 lines with PEC (top/bottom) --> quasi 2D
+
+%FDTD setup
+f0 = 5e9; %center frequency
+f_BW = f0/sqrt(2); %bandwidth
+MTM.eps_R = 1;
+MTM.mue_R = 1;
+MTM.f0 = f0; %plasma frequency of the drude material
+MTM.relaxTime = 5e-9; %relaxation time (smaller number results in greater losses, set to 0 to disable)
+MTM.length = 250; %length of the metamaterial
+N_TS = 5e4; %number of timesteps
+endCriteria = 1e-5; %stop simulation if signal is at -50dB
+
+%constants
+physical_constants
+
+%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '-vvv';
+
+Sim_Path = 'MTM_PW_Drude';
+Sim_CSX = 'MTM_PW_Drude.xml';
+
+if (postproc_only==0)
+
+ if (exist(Sim_Path,'dir'))
+ rmdir(Sim_Path,'s');
+ end
+ mkdir(Sim_Path);
+
+ %% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ FDTD = InitFDTD(N_TS,endCriteria,'OverSampling',10);
+ FDTD = SetGaussExcite(FDTD,0,2*f0);
+ BC = [1 1 0 0 2 2];
+ FDTD = SetBoundaryCond(FDTD,BC);
+
+ %% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ CSX = InitCSX();
+ mesh.x = -width/2 : mesh_res : width/2;
+ mesh.y = -height/2 : mesh_res : height/2;
+ mesh.z = -length/2 : mesh_res : length/2;
+ CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+ %% apply the plane wave excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ start=[-width/2 -height/2 ,mesh.z(3)];
+ stop=[width/2 height/2 mesh.z(3)];
+ CSX = AddExcitation(CSX,'excite',0,[0 1 0]); % excite E_y
+ CSX = AddBox(CSX,'excite',0 ,start,stop);
+
+ %% apply drude material %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ CSX = AddLorentzMaterial(CSX,'drude');
+ CSX = SetMaterialProperty(CSX,'drude','Epsilon',MTM.eps_R,'EpsilonPlasmaFrequency',MTM.f0,'EpsilonRelaxTime',MTM.relaxTime);
+ CSX = SetMaterialProperty(CSX,'drude','Mue',MTM.mue_R,'MuePlasmaFrequency',MTM.f0,'MueRelaxTime',MTM.relaxTime);
+ start=[mesh.x(1) mesh.y(1) -MTM.length/2];
+ stop =[mesh.x(end) mesh.y(end) MTM.length/2];
+ CSX = AddBox(CSX,'drude', 10 ,start,stop);
+
+ %% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','10,10,1');
+ start = [mesh.x(2) ,0 , mesh.z(1)];
+ stop = [mesh.x(end-1) , 0 , mesh.z(end)];
+ CSX = AddBox(CSX,'Et',0 , start,stop);
+
+ %% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+ %% run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts, Settings);
+
+end
+
+%% plot the drude type material dependency
+f = linspace(0.1*f0,2*f0,501);
+w = 2*pi*f;
+epsr = MTM.eps_R * (1 - (2*pi*MTM.f0)^2./( w.^2 - 1j*w./MTM.relaxTime ));
+muer = MTM.mue_R * (1 - (2*pi*MTM.f0)^2./( w.^2 - 1j*w./MTM.relaxTime ));
+plot(f,real(epsr),'Linewidth',2);
+hold on
+grid on
+plot(f,imag(epsr),'r--','Linewidth',2);
+plot(f,real(muer),'c-.','Linewidth',2);
+plot(f,imag(muer),'m-.','Linewidth',2);
+ylim([-10 MTM.eps_R])
+% l=legend('\Re \epsilon_r','\Im \epsilon_r','\Re \mue_r','\Im \mue_r');
+l=legend('$\Re\{\varepsilon_r\}$','$\Im\{\varepsilon_r\}$','$\Re\{\mu_r\}$','$\Im\{\mu_r\}$');
+set(l,'Interpreter','latex','Fontsize',12)
+
+%% plot E-fields
+freq = [f0/sqrt(2) f0 f0*sqrt(2)];
+field = ReadHDF5FieldData([Sim_Path '/Et.h5']);
+mesh_h5 = ReadHDF5Mesh([Sim_Path '/Et.h5']);
+
+ET = ReadUI('et',Sim_Path);
+ef = DFT_time2freq(ET.TD{1}.t,ET.TD{1}.val,freq);
+
+field_FD = GetField_TD2FD(field, freq);
+
+mesh.x = linspace(-500,500,numel(mesh_h5.lines{1})); %make animation wider...
+mesh.y = mesh_h5.lines{2};
+mesh.z = mesh_h5.lines{3};
+
+[X Z] = meshgrid(mesh.x,mesh.z);
+X = X';
+Z = Z';
+
+for n=1:numel(field_FD.FD.values)
+ Ec{n} = squeeze(field_FD.FD.values{n}/ef(n));
+end
+
+%%
+figure('Position',[10 100 pic_size(1) pic_size(2)]);
+phase = linspace(0,2*pi,21);
+disp('press CTRL+C to stop animation');
+while (1)
+ for ph = phase(1:end-1)
+ for n=1:numel(Ec)
+ subplot(1,numel(Ec),n)
+ E = real(Ec{n}.*exp(1j*ph));
+ surf(X,Z,E(:,:,2));
+ title(['f_0 = ' num2str(freq(n)*1e-9) ' GHz'])
+ end
+ pause(0.1);
+ end
+end
diff --git a/openEMS/matlab/examples/other/PML_reflection_analysis.m b/openEMS/matlab/examples/other/PML_reflection_analysis.m
new file mode 100644
index 0000000..f243a83
--- /dev/null
+++ b/openEMS/matlab/examples/other/PML_reflection_analysis.m
@@ -0,0 +1,196 @@
+%
+% fake-PML parallel plate waveguide example
+%
+% this example analyzes the reflection coefficient of a vacuum-pml
+% interface
+%
+
+%
+% currently this example uses a normal material with a certain conductivity
+% profile and not a pml
+%
+
+close all
+% clear
+clc
+
+physical_constants
+
+
+postprocessing_only = 0;
+
+
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+drawingunit = 1e-6; % specify everything in um
+
+length = 10000;
+epr = 1;
+
+mesh_res = [200 200 200];
+max_timesteps = 100000;
+min_decrement = 1e-6;
+f_max = 8e9;
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD( max_timesteps, min_decrement );
+FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 );
+BC = [0 0 1 1 0 0];
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% mesh grading
+N_pml = 8;
+pml_delta = cumsum(mesh_res(1) * 1.0 .^ (1:N_pml));
+% pml_delta = cumsum([200 200 200 200 200]);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = 0 : mesh_res(1) : length;
+mesh.x = [mesh.x(1) - fliplr(pml_delta), mesh.x];
+mesh.y = -2*mesh_res(2) : mesh_res(2) : 2*mesh_res(2);
+mesh.z = 0 : mesh_res(3) : 4*mesh_res(3);
+CSX = DefineRectGrid( CSX, drawingunit, mesh );
+
+%% fake pml %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+g = 2; % 2..3
+R0 = 1e-6; % requested analytical reflection coefficient
+Zm = sqrt(MUE0/(EPS0*epr)); % calculate reflection for substrate/pml interface
+delta = pml_delta(end) * drawingunit;
+deltal = mean(diff(pml_delta)) * drawingunit;
+kappa0 = -log(R0)*log(g)/( 2*Zm*deltal*(g^(delta/deltal)-1) );
+
+% kappa0 = 1.05;
+CSX = AddMaterial( CSX, 'pml_xmin' );
+CSX = SetMaterialProperty( CSX, 'pml_xmin', 'Epsilon', epr );
+CSX = SetMaterialProperty( CSX, 'pml_xmin', 'Kappa', kappa0 );
+CSX = SetMaterialProperty( CSX, 'pml_xmin', 'Sigma', kappa0 * MUE0/(EPS0*epr) );
+CSX = SetMaterialWeight( CSX, 'pml_xmin', 'Kappa', [num2str(g) '^((abs(x-100)-' num2str(abs(mesh.x(N_pml+1))) ')/(' num2str(deltal) '/' num2str(drawingunit) '))'] ); % g^(rho/deltal)*kappa0
+CSX = SetMaterialWeight( CSX, 'pml_xmin', 'Sigma', [num2str(g) '^((abs(x-100)-' num2str(abs(mesh.x(N_pml+1))) ')/(' num2str(deltal) '/' num2str(drawingunit) '))'] );
+start = [mesh.x(1), mesh.y(1), mesh.z(1)];
+stop = [100, mesh.y(end), mesh.z(end)];
+CSX = AddBox( CSX, 'pml_xmin', 1, start, stop );
+
+figure
+x = [-fliplr(pml_delta) 50];
+plot( x, kappa0 * g.^((abs(x-50)-abs(mesh.x(N_pml+1)))./(deltal/drawingunit)) ,'x-');
+xlabel( 'x / m' );
+ylabel( 'kappa' );
+figure
+title( 'conductivity profile inside the material' );
+
+%% excitation
+CSX = AddExcitation( CSX, 'excitation1', 0, [0 0 1]);
+idx = interp1( mesh.x, 1:numel(mesh.x), length*2/3, 'nearest' );
+start = [mesh.x(idx), mesh.y(1), mesh.z(1)];
+stop = [mesh.x(idx), mesh.y(end), mesh.z(end)];
+CSX = AddBox( CSX, 'excitation1', 0, start, stop );
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump( CSX, 'Et_', 'DumpMode', 2 );
+start = [mesh.x(1), mesh.y(1), mesh.z(3)];
+stop = [mesh.x(end), mesh.y(end), mesh.z(3)];
+CSX = AddBox( CSX, 'Et_', 0, start, stop );
+
+CSX = AddDump( CSX, 'Ht_', 'DumpType', 1, 'DumpMode', 2 );
+CSX = AddBox( CSX, 'Ht_', 0, start, stop );
+
+% hdf5 file
+CSX = AddDump( CSX, 'E', 'DumpType', 0, 'DumpMode', 2, 'FileType', 1 );
+idx = interp1( mesh.x, 1:numel(mesh.x), length*1/3, 'nearest' );
+start = [mesh.x(idx), mesh.y(3), mesh.z(1)];
+stop = [mesh.x(idx), mesh.y(3), mesh.z(end)];
+CSX = AddBox( CSX, 'E', 0, start, stop );
+
+% hdf5 file
+CSX = AddDump( CSX, 'H', 'DumpType', 1, 'DumpMode', 2, 'FileType', 1 );
+idx = interp1( mesh.x, 1:numel(mesh.x), length*1/3, 'nearest' );
+start = [mesh.x(idx), mesh.y(1), mesh.z(3)];
+stop = [mesh.x(idx), mesh.y(end), mesh.z(3)];
+CSX = AddBox( CSX, 'H', 0, start, stop );
+
+%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-operator'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+% openEMS_opts = [openEMS_opts ' --showProbeDiscretization'];
+openEMS_opts = [openEMS_opts ' --engine=fastest'];
+
+Sim_Path = 'tmp';
+Sim_CSX = 'PML_reflection_analysis.xml';
+
+if ~postprocessing_only
+ [~,~,~] = rmdir(Sim_Path,'s');
+ [~,~,~] = mkdir(Sim_Path);
+end
+
+%% Write openEMS compatible xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+%% cd to working dir and run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if ~postprocessing_only
+ savePath = pwd;
+ cd(Sim_Path); %cd to working dir
+ args = [Sim_CSX ' ' openEMS_opts];
+ invoke_openEMS(args);
+ cd(savePath)
+end
+
+
+%% postproc & do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% E_coords = ReadHDF5Mesh( [Sim_Path '/E.h5'] );
+% H_coords = ReadHDF5Mesh( [Sim_Path '/H.h5'] );
+E = ReadHDF5FieldData( [Sim_Path '/E.h5'] );
+H = ReadHDF5FieldData( [Sim_Path '/H.h5'] );
+E_val = cellfun( @(x) squeeze(x(1,1,:,3)), E.values, 'UniformOutput', false );
+H_val = cellfun( @(x) squeeze(x(1,:,1,2)), H.values, 'UniformOutput', false );
+E_val = cell2mat(E_val);
+H_val = cell2mat(H_val.');
+
+% pick center point
+Et = E_val(3,:);
+Ht = H_val(:,3).';
+
+delta_t_2 = H.time(1) - E.time(1); % half time-step (s)
+
+% create finer frequency resolution
+f = linspace( 0, f_max, 1601 );
+Ef = DFT_time2freq( E.time, Et, f );
+Hf = DFT_time2freq( H.time, Ht, f );
+Hf = Hf .* exp(-1i*2*pi*f*delta_t_2); % compensate half time-step advance of H-field
+
+% H is now time interpolated, but the position is not corrected with
+% respect to E
+
+% figure
+% plot( E.time/1e-6, Et );
+% xlabel('time (us)');
+% ylabel('amplitude (V)');
+% grid on;
+% title( 'Time domain voltage probe' );
+%
+% figure
+% plot( H.time/1e-6, Ht );
+% xlabel('time (us)');
+% ylabel('amplitude (A)');
+% grid on;
+% title( 'Time domain current probe' );
+
+
+Z0 = sqrt(MUE0/EPS0); % line impedance
+Z = Ef ./ Hf; % impedance at measurement plane
+gamma = (Z - Z0) ./ (Z + Z0);
+
+plot( f/1e9, 20*log10(abs(gamma)),'Linewidth',2);
+xlabel('frequency (GHz)');
+ylabel('reflection coefficient gamma (dB)');
+grid on;
+title( 'Reflection Coefficient' );
+
+if exist('ref_1','var')
+ hold on
+ plot( f/1e9, ref_1,'--','Linewidth',2, 'Color', [1 0 0]);
+ hold off
+end
+ref_1 = 20*log10(abs(gamma));
diff --git a/openEMS/matlab/examples/other/PlaneWave.m b/openEMS/matlab/examples/other/PlaneWave.m
new file mode 100644
index 0000000..5e0d3e8
--- /dev/null
+++ b/openEMS/matlab/examples/other/PlaneWave.m
@@ -0,0 +1,69 @@
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+length = 5000;
+width = 300;
+height = 200;
+mesh_res = 15;
+abs_length = mesh_res*10;
+
+EPS0 = 8.85418781762e-12;
+MUE0 = 1.256637062e-6;
+
+%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+openEMS_opts = [openEMS_opts ' --engine=fastest'];
+
+Sim_Path = 'tmp';
+Sim_CSX = 'plane_wave.xml';
+
+if (exist(Sim_Path,'dir'))
+ rmdir(Sim_Path,'s');
+end
+mkdir(Sim_Path);
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(5000,1e-5,'OverSampling',10);
+FDTD = SetGaussExcite(FDTD,0.5e9,0.5e9);
+BC = [1 1 0 0 2 2];
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = -width/2 : mesh_res : width/2;
+mesh.y = -height/2 : mesh_res : height/2;
+mesh.z = 0 : mesh_res : length;
+CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start=[-width/2 -height/2 mesh.z(3)];
+stop =[ width/2 height/2 mesh.z(3)];
+CSX = AddExcitation(CSX,'excite',0,[0 1 0]);
+CSX = AddBox(CSX,'excite',0 ,start,stop);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','4,4,4');
+start = [mesh.x(1) , mesh.y(1) , mesh.z(1)];
+stop = [mesh.x(end) , mesh.y(end) , mesh.z(end)];
+CSX = AddBox(CSX,'Et',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht','DumpType',1,'FileType',1,'SubSampling','4,4,4','DumpMode',2);
+CSX = AddBox(CSX,'Ht',0,start,stop);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+%% run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+
+%% do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+PlotArgs.slice = {mesh.x(round(end/2)) mesh.y(round(end/2)) mesh.z(round(end/2))};
+PlotArgs.pauseTime=0.01;
+PlotArgs.component=1;
+PlotArgs.Limit = 'auto';
+
+PlotHDF5FieldData('tmp/Ht.h5',PlotArgs)
diff --git a/openEMS/matlab/examples/other/gauss_excitation_test.m b/openEMS/matlab/examples/other/gauss_excitation_test.m
new file mode 100644
index 0000000..a7e166e
--- /dev/null
+++ b/openEMS/matlab/examples/other/gauss_excitation_test.m
@@ -0,0 +1,72 @@
+%
+% this script evaluates the same gaussian excitation function, as openEMS does
+%
+
+clear
+close all
+clc
+
+f0 = 0e9;
+fc = 10e9;
+dT = 1e-12; % sample time-step
+
+
+sigma = 1/sqrt(8/9)/pi/fc;
+t0 = sqrt(18)/sqrt(8/9)/pi/fc;
+
+len = 2 * 9/(2*pi*fc) / dT; % gauss length
+
+for n=1:len
+ t_(n) = (n-1)*dT;
+ ex(n) = cos(2*pi*f0*((n-1)*dT - 9/(2*pi*fc))) .* exp(-((t_(n)-t0)/sigma)^2/2);
+end
+
+plot(t_/1e-9,ex)
+xlabel( 'time (ns)' );
+ylabel( 'amplitude' );
+
+
+disp( ['Amplitude at t=0: ' num2str(20*log10(abs(ex(1))/1)) ' dB'] );
+
+val = DFT_time2freq( t_, ex, [f0-fc f0 f0+fc] );
+disp( ['Amplitude at f=f0-fc: ' num2str(20*log10(abs(val(1))/abs(val(2)))) ' dB'] );
+disp( ['Amplitude at f=f0+fc: ' num2str(20*log10(abs(val(3))/abs(val(2)))) ' dB'] );
+
+% calculate frequency domain via slow DFT
+freq = linspace(f0-fc,f0+fc,1000);
+val = DFT_time2freq( t_, ex, freq );
+figure
+plot( freq/1e9, abs(val) )
+
+% overlay the FFT result
+[f,val_fft] = FFT_time2freq( t_, ex );
+val_fft = val_fft((f0-fc<=f) & (f<=f0+fc));
+f = f((f0-fc<=f) & (f<=f0+fc));
+hold on
+plot( f/1e9, abs(val_fft), 'r' )
+hold on
+
+if (f0==0)
+ Fw = sigma*sqrt(2*pi)*exp(-0.5*(sigma*2*pi*f).^2);
+ plot( f/1e9, 2*abs(Fw), 'g--' )
+ legend('dft','fft','analytic')
+else
+ legend('dft','fft')
+end
+
+xlim([0 max(f)/1e9])
+
+xlabel( 'frequency (GHz)' );
+ylabel( 'amplitude' );
+
+
+% dB
+figure
+val = val(freq>=0);
+freq = freq(freq>=0);
+plot( freq/1e9, 20*log10(abs(val)/max(abs(val))), 'r' )
+xlabel( 'frequency (GHz)' );
+ylabel( 'amplitude (dB)' );
+
+
+
diff --git a/openEMS/matlab/examples/other/resistance_sheet.m b/openEMS/matlab/examples/other/resistance_sheet.m
new file mode 100644
index 0000000..b63c00e
--- /dev/null
+++ b/openEMS/matlab/examples/other/resistance_sheet.m
@@ -0,0 +1,207 @@
+%
+% resistance "sheet" example
+%
+% this example calculates the reflection coefficient of a sheet resistance
+% at the end of a parallel plate wave guide
+%
+% play around with the R and epr values
+%
+
+close all
+clear
+clc
+
+physical_constants
+
+
+postprocessing_only = 0;
+
+
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+epr = 1; % relative permittivity of the material inside the parallel plate waveguide
+
+% define the resistance
+R = sqrt(MUE0/(EPS0*epr)); % matched load (no reflections) (vacuum: approx. 377 Ohm)
+% R = 1e-10; % short circuit (reflection coefficient = -1)
+% R = 1e10; % open circuit (reflection coefficient = 1)
+
+
+drawingunit = 1e-6; % specify everything in um
+length = 10000;
+mesh_res = [200 200 200];
+max_timesteps = 100000;
+min_decrement = 1e-6;
+f_max = 1e9;
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD( max_timesteps, min_decrement );
+FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 );
+BC = [1 2 1 1 0 0]; % 0:PEC 1:PMC 2:MUR-ABC
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = 0 : mesh_res(1) : length;
+mesh.y = -2*mesh_res(2) : mesh_res(2) : 2*mesh_res(2);
+mesh.z = 0 : mesh_res(3) : 4*mesh_res(3);
+CSX = DefineRectGrid( CSX, drawingunit, mesh );
+
+%% measurement plane & reference plane
+meas_plane_xidx = interp1( mesh.x, 1:numel(mesh.x), length*1/3, 'nearest' );
+ref_plane_xidx = 3;
+
+%% fill the parallel plate waveguide with material
+CSX = AddMaterial( CSX, 'm1' );
+CSX = SetMaterialProperty( CSX, 'm1', 'Epsilon', epr );
+start = [mesh.x(1), mesh.y(1), mesh.z(1)];
+stop = [mesh.x(end), mesh.y(end), mesh.z(end)];
+CSX = AddBox( CSX, 'm1', -1, start, stop );
+
+%% excitation
+CSX = AddExcitation( CSX, 'excitation1', 0, [0 0 1]);
+idx = interp1( mesh.x, 1:numel(mesh.x), length*2/3, 'nearest' );
+start = [mesh.x(idx), mesh.y(1), mesh.z(1)];
+stop = [mesh.x(idx), mesh.y(end), mesh.z(end)];
+CSX = AddBox( CSX, 'excitation1', 0, start, stop );
+
+%% define the sheet resistance
+start = [mesh.x(ref_plane_xidx-1), mesh.y(1), mesh.z(1)];
+stop = [mesh.x(ref_plane_xidx), mesh.y(end), mesh.z(end)];
+l = abs(mesh.z(end) - mesh.z(1)) * drawingunit; % length of the "sheet"
+A = abs(start(1) - stop(1)) * abs(mesh.y(end) - mesh.y(1)) * drawingunit^2; % area of the "sheet"
+kappa = l/A / R; % [kappa] = S/m
+CSX = AddMaterial( CSX, 'sheet_resistance' );
+CSX = SetMaterialProperty( CSX, 'sheet_resistance', 'Kappa', kappa );
+CSX = AddBox( CSX, 'sheet_resistance', 0, start, stop );
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump( CSX, 'Et_', 'DumpMode', 2 );
+start = [mesh.x(1), mesh.y(1), mesh.z(3)];
+stop = [mesh.x(end), mesh.y(end), mesh.z(3)];
+CSX = AddBox( CSX, 'Et_', 0, start, stop );
+
+CSX = AddDump( CSX, 'Ht_', 'DumpType', 1, 'DumpMode', 2 );
+CSX = AddBox( CSX, 'Ht_', 0, start, stop );
+
+% hdf5 file
+CSX = AddDump( CSX, 'E', 'DumpType', 0, 'DumpMode', 2, 'FileType', 1 );
+start = [mesh.x(meas_plane_xidx), mesh.y(3), mesh.z(1)];
+stop = [mesh.x(meas_plane_xidx), mesh.y(3), mesh.z(end)];
+CSX = AddBox( CSX, 'E', 0, start, stop );
+
+% hdf5 file
+CSX = AddDump( CSX, 'H', 'DumpType', 1, 'DumpMode', 2, 'FileType', 1 );
+start = [mesh.x(meas_plane_xidx), mesh.y(1), mesh.z(3)];
+stop = [mesh.x(meas_plane_xidx), mesh.y(end), mesh.z(3)];
+CSX = AddBox( CSX, 'H', 0, start, stop );
+
+%% define openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-operator'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+% openEMS_opts = [openEMS_opts ' --showProbeDiscretization'];
+openEMS_opts = [openEMS_opts ' --engine=fastest'];
+
+Sim_Path = 'tmp';
+Sim_CSX = 'tmp.xml';
+
+if ~postprocessing_only
+ [~,~,~] = rmdir(Sim_Path,'s');
+ [~,~,~] = mkdir(Sim_Path);
+end
+
+%% Write openEMS compatible xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+%% cd to working dir and run openEMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if ~postprocessing_only
+ savePath = pwd;
+ cd(Sim_Path); %cd to working dir
+ args = [Sim_CSX ' ' openEMS_opts];
+ invoke_openEMS(args);
+ cd(savePath)
+end
+
+
+%% postproc & do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% E_coords = ReadHDF5Mesh( [Sim_Path '/E.h5'] );
+% H_coords = ReadHDF5Mesh( [Sim_Path '/H.h5'] );
+E = ReadHDF5FieldData( [Sim_Path '/E.h5'] );
+H = ReadHDF5FieldData( [Sim_Path '/H.h5'] );
+E_val = cellfun( @(x) squeeze(x(1,1,:,3)), E.values, 'UniformOutput', false );
+H_val = cellfun( @(x) squeeze(x(1,:,1,2)), H.values, 'UniformOutput', false );
+E_val = cell2mat(E_val);
+H_val = cell2mat(H_val.');
+
+% pick center point
+Et = E_val(3,:);
+Ht = H_val(:,3).';
+
+delta_t_2 = H.time(1) - E.time(1); % half time-step (s)
+
+% create finer frequency resolution
+f = linspace( 0, f_max, 201 );
+Ef = DFT_time2freq( E.time, Et, f );
+Hf = DFT_time2freq( H.time, Ht, f );
+Hf = Hf .* exp(-1i*2*pi*f*delta_t_2); % compensate half time-step advance of H-field
+
+% H is now time interpolated, but the position is not corrected with
+% respect to E
+
+% figure
+% plot( E.time/1e-6, Et );
+% xlabel('time (us)');
+% ylabel('amplitude (V)');
+% grid on;
+% title( 'Time domain voltage probe' );
+%
+% figure
+% plot( H.time/1e-6, Ht );
+% xlabel('time (us)');
+% ylabel('amplitude (A)');
+% grid on;
+% title( 'Time domain current probe' );
+
+
+Z0 = sqrt(MUE0/(EPS0*epr)); % line impedance
+Z = Ef ./ Hf; % impedance at measurement plane
+gamma = (Z - Z0) ./ (Z + Z0);
+
+% reference plane shift
+beta = 2*pi*f * sqrt(MUE0*(EPS0*epr)); % TEM wave
+meas_plane_x = mesh.x(meas_plane_xidx);
+ref_plane_x = mesh.x(ref_plane_xidx);
+gamma_refplane = gamma .* exp(2i*beta* (meas_plane_x-ref_plane_x)*drawingunit);
+Z_refplane = Z0 * (1+gamma_refplane)./(1-gamma_refplane);
+
+% smith chart
+figure
+if exist( 'smith', 'file' )
+ % smith chart
+ % www.ece.rutgers.edu/~orfanidi/ewa
+ % or cmt toolbox from git.ate.uni-duisburg.de
+ smith
+else
+ % poor man smith chart
+ plot( sin(0:0.01:2*pi), cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+ hold on
+% plot( 0.25+0.75*sin(0:0.01:2*pi), 0.75*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+ plot( 0.5+0.5*sin(0:0.01:2*pi), 0.5*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+% plot( 0.75+0.25*sin(0:0.01:2*pi), 0.25*cos(0:0.01:2*pi), 'Color', [.7 .7 .7] );
+ plot( [-1 1], [0 0], 'Color', [.7 .7 .7] );
+ axis equal
+end
+plot( real(gamma_refplane), imag(gamma_refplane), 'r*' );
+% plot( real(gamma), imag(gamma), 'k*' );
+title( 'reflection coefficient S11 at reference plane' )
+
+figure
+plot( f/1e9, [real(Z_refplane);imag(Z_refplane)],'Linewidth',2);
+xlabel('frequency (GHz)');
+ylabel('impedance (Ohm)');
+grid on;
+title( 'Impedance at reference plane' );
+legend( {'real','imag'} );
diff --git a/openEMS/matlab/examples/transmission_lines/CPW_Line.m b/openEMS/matlab/examples/transmission_lines/CPW_Line.m
new file mode 100644
index 0000000..6dac636
--- /dev/null
+++ b/openEMS/matlab/examples/transmission_lines/CPW_Line.m
@@ -0,0 +1,125 @@
+%
+% Tutorials / CPW_Line
+%
+% Describtion at:
+%
+% Tested with
+% - Octave 3.8.1
+% - openEMS v0.0.32
+%
+% (C) 2014 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; % specify everything in um
+CPW_length = 40000;
+CPW_port_length = 10000;
+CPW_width = 1000;
+CPW_gap = 140;
+substrate_thickness = 512;
+substrate_width = 5000
+substrate_epr = 3.66;
+f_max = 10e9;
+air_spacing = 7000
+
+% use a finite line CPW waveguide
+if 1
+ feed_R = 50;
+ pml_add_cells = [8 8 8 8 8 8];
+ feed_shift_cells = 0;
+ x_spacing = air_spacing;
+else % or use a waveguide with start/end in a pml
+ feed_R = inf; % CPW ends in a pml --> disable termination resitance
+ feed_shift_cells = 10; % CPW ends in an 8 cells thick pml --> shift feed 10 cells
+ pml_add_cells = [0 0 8 8 8 8]; % do not add air-space in x-direction
+ x_spacing = 0; % do not add air-space in x-direction
+end
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD('EndCriteria', 1e-4);
+FDTD = SetGaussExcite( FDTD, f_max/2, f_max/2 );
+BC = [2 2 2 2 2 2];
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+resolution = c0/(f_max*sqrt(substrate_epr))/unit /30; % resolution of lambda/50
+edge_res = 40;
+mesh.x = SmoothMeshLines( [0 CPW_length/2 CPW_length/2+x_spacing], resolution, 1.5 ,0 );
+mesh.x = unique(sort([-mesh.x mesh.x]));
+mesh.y = SmoothMeshLines( [CPW_width/2+[-edge_res/3 +edge_res/3*2] CPW_gap+CPW_width/2+[-edge_res/3*2 +edge_res/3]], edge_res , 1.5 ,0);
+mesh.y = SmoothMeshLines( [0 mesh.y], edge_res*2, 1.3 ,0);
+mesh.y = SmoothMeshLines( [0 mesh.y substrate_width/2 substrate_width/2+air_spacing], resolution, 1.3 ,0);
+mesh.y = unique(sort([-mesh.y mesh.y]));
+mesh.z = SmoothMeshLines( [-air_spacing linspace(0,substrate_thickness,5) substrate_thickness+air_spacing], resolution );
+
+mesh = AddPML(mesh, pml_add_cells);
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% substrate
+CSX = AddMaterial( CSX, 'RO4350B' );
+CSX = SetMaterialProperty( CSX, 'RO4350B', 'Epsilon', substrate_epr );
+start = [-CPW_length/2, -substrate_width/2, 0];
+stop = [+CPW_length/2, +substrate_width/2, substrate_thickness];
+CSX = AddBox( CSX, 'RO4350B', 0, start, stop );
+
+%%
+CSX = AddMetal( CSX, 'CPW_PORT' );
+
+%% CPW port, with the measurement plane at the end of each port
+portstart = [ -CPW_length/2 , -CPW_width/2, substrate_thickness];
+portstop = [ -CPW_length/2+CPW_port_length, CPW_width/2, substrate_thickness];
+[CSX,port{1}] = AddCPWPort( CSX, 999, 1, 'CPW_PORT', portstart, portstop, CPW_gap, 'x', [0 1 0], 'ExcitePort', true, 'FeedShift', feed_shift_cells*resolution, 'MeasPlaneShift', CPW_port_length, 'Feed_R', feed_R);
+
+portstart = [ CPW_length/2 , -CPW_width/2, substrate_thickness];
+portstop = [ CPW_length/2-CPW_port_length, CPW_width/2, substrate_thickness];
+[CSX,port{2}] = AddCPWPort( CSX, 999, 2, 'CPW_PORT', portstart, portstop, CPW_gap, 'x', [0 1 0], 'MeasPlaneShift', CPW_port_length, 'Feed_R', feed_R);
+
+%% CPW
+CSX = AddMetal( CSX, 'CPW');
+start = [ -CPW_length/2+CPW_port_length, -CPW_width/2, substrate_thickness];
+stop = [ +CPW_length/2-CPW_port_length, CPW_width/2, substrate_thickness];
+CSX = AddBox(CSX, 'CPW', 999, start, stop);
+
+%% CPW grounds
+CSX = AddMetal( CSX, 'GND' );
+start = [-CPW_length/2, -CPW_width/2-CPW_gap, substrate_thickness];
+stop = [+CPW_length/2, -substrate_width/2 , substrate_thickness];
+CSX = AddBox(CSX, 'GND', 999, start, stop);
+
+start = [-CPW_length/2, +CPW_width/2+CPW_gap, substrate_thickness];
+stop = [+CPW_length/2, +substrate_width/2 , substrate_thickness];
+CSX = AddBox(CSX, 'GND', 999, start, stop);
+
+%% write/show/run the openEMS compatible xml-file
+Sim_Path = 'tmp';
+Sim_CSX = 'CPW.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);
+
+
diff --git a/openEMS/matlab/examples/transmission_lines/Finite_Stripline.m b/openEMS/matlab/examples/transmission_lines/Finite_Stripline.m
new file mode 100644
index 0000000..da2b4a3
--- /dev/null
+++ b/openEMS/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/openEMS/matlab/examples/transmission_lines/MSL.m b/openEMS/matlab/examples/transmission_lines/MSL.m
new file mode 100644
index 0000000..b6ec0b3
--- /dev/null
+++ b/openEMS/matlab/examples/transmission_lines/MSL.m
@@ -0,0 +1,185 @@
+%
+% EXAMPLE / microstrip / MSL
+%
+% Microstrip line on air "substrate" in z-direction.
+%
+% This example demonstrates:
+% - simple microstrip geometry
+% - characteristic impedance
+% - material grading function
+% - geometric priority concept
+%
+%
+% Tested with
+% - Matlab 2009b
+% - Octave 3.3.52
+% - openEMS v0.0.14
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% setup the simulation
+physical_constants;
+unit = 1e-3; % all length in mm
+
+% geometry
+abs_length = 100; % absorber length
+length = 600;
+width = 400;
+height = 200;
+MSL_width = 50;
+MSL_height = 10;
+
+%% prepare simulation folder
+Sim_Path = 'tmp';
+Sim_CSX = 'msl.xml';
+[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
+[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+max_timesteps = 2000;
+min_decrement = 1e-5; % equivalent to -50 dB
+f0 = 2e9; % center frequency
+fc = 1e9; % 10 dB corner frequency (in this case 1e9 Hz - 3e9 Hz)
+FDTD = InitFDTD( max_timesteps, min_decrement );
+FDTD = SetGaussExcite( FDTD, f0, fc );
+BC = {'PMC' 'PMC' 'PEC' 'PMC' 'PEC' 'PEC'};
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh
+% very simple mesh
+CSX = InitCSX();
+resolution = c0/(f0+fc)/unit /15; % resolution of lambda/15
+mesh.x = SmoothMeshLines( [-width/2, width/2, -MSL_width/2, MSL_width/2], resolution ); % create smooth lines from fixed lines
+mesh.y = SmoothMeshLines( [linspace(0,MSL_height,5) MSL_height+1 height], resolution );
+mesh.z = SmoothMeshLines( [0 length], resolution );
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% create MSL
+% attention! the skin effect is not simulated, because the MSL is
+% discretized with only one cell!
+CSX = AddMaterial( CSX, 'copper' );
+CSX = SetMaterialProperty( CSX, 'copper', 'Kappa', 56e6 );
+start = [-MSL_width/2, MSL_height, 0];
+stop = [ MSL_width/2, MSL_height+1, length];
+priority = 100; % the geometric priority is set to 100
+CSX = AddBox( CSX, 'copper', priority, start, stop );
+
+%% add excitation below the strip
+start = [-MSL_width/2, 0 , mesh.z(1)];
+stop = [ MSL_width/2, MSL_height, mesh.z(1)];
+CSX = AddExcitation( CSX, 'excite', 0, [0 -1 0] );
+CSX = AddBox( CSX, 'excite', 0, start, stop );
+
+%% fake pml
+% this "pml" is a normal material with graded losses
+% electric and magnetic losses are related to give low reflection
+% for normally incident TEM waves
+finalKappa = 1/abs_length^2;
+finalSigma = finalKappa*MUE0/EPS0;
+CSX = AddMaterial( CSX, 'fakepml' );
+CSX = SetMaterialProperty( CSX, 'fakepml', 'Kappa', finalKappa );
+CSX = SetMaterialProperty( CSX, 'fakepml', 'Sigma', finalSigma );
+CSX = SetMaterialWeight( CSX, 'fakepml', 'Kappa', ['pow(z-' num2str(length-abs_length) ',2)'] );
+CSX = SetMaterialWeight( CSX, 'fakepml', 'Sigma', ['pow(z-' num2str(length-abs_length) ',2)'] );
+start = [mesh.x(1) mesh.y(1) length-abs_length];
+stop = [mesh.x(end) mesh.y(end) length];
+% the geometric priority is set to 0, which is lower than the priority
+% of the MSL, thus the MSL (copper) has precendence
+priority = 0;
+CSX = AddBox( CSX, 'fakepml', priority, start, stop );
+
+%% define dump boxes
+start = [mesh.x(1), MSL_height/2, mesh.z(1)];
+stop = [mesh.x(end), MSL_height/2, mesh.z(end)];
+CSX = AddDump( CSX, 'Et_', 'DumpMode', 2 ); % cell interpolated
+CSX = AddBox( CSX, 'Et_', 0, start, stop );
+CSX = AddDump( CSX, 'Ht_', 'DumpType', 1, 'DumpMode', 2 ); % cell interpolated
+CSX = AddBox( CSX, 'Ht_', 0, start, stop );
+
+%% define voltage calc box
+% voltage calc boxes will automatically snap to the next mesh-line
+CSX = AddProbe( CSX, 'ut1', 0 );
+zidx = interp1( mesh.z, 1:numel(mesh.z), length/2, 'nearest' );
+start = [0 MSL_height mesh.z(zidx)];
+stop = [0 0 mesh.z(zidx)];
+CSX = AddBox( CSX, 'ut1', 0, start, stop );
+% add a second voltage probe to compensate space offset between voltage and
+% current
+CSX = AddProbe( CSX, 'ut2', 0 );
+start = [0 MSL_height mesh.z(zidx+1)];
+stop = [0 0 mesh.z(zidx+1)];
+CSX = AddBox( CSX, 'ut2', 0, start, stop );
+
+%% define current calc box
+% current calc boxes will automatically snap to the next dual mesh-line
+CSX = AddProbe( CSX, 'it1', 1 );
+xidx1 = interp1( mesh.x, 1:numel(mesh.x), -MSL_width/2, 'nearest' );
+xidx2 = interp1( mesh.x, 1:numel(mesh.x), MSL_width/2, 'nearest' );
+xdelta = diff(mesh.x);
+yidx1 = interp1( mesh.y, 1:numel(mesh.y), MSL_height, 'nearest' );
+yidx2 = interp1( mesh.y, 1:numel(mesh.y), MSL_height+1, 'nearest' );
+ydelta = diff(mesh.y);
+zdelta = diff(mesh.z);
+start = [mesh.x(xidx1)-xdelta(xidx1-1)/2, mesh.y(yidx1)-ydelta(yidx1-1)/2, mesh.z(zidx)+zdelta(zidx)/2];
+stop = [mesh.x(xidx2)+xdelta(xidx2)/2, mesh.y(yidx2)+ydelta(yidx2)/2, mesh.z(zidx)+zdelta(zidx)/2];
+CSX = AddBox( CSX, 'it1', 0, start, stop );
+
+%% write openEMS compatible xml-file
+WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
+
+%% show the structure
+CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+
+%% run openEMS
+openEMS_opts = '';
+openEMS_opts = [openEMS_opts ' --engine=fastest'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
+
+%% postprocess
+freq = linspace( f0-fc, f0+fc, 501 );
+U = ReadUI( {'ut1','ut2','et'}, 'tmp/', freq ); % time domain/freq domain voltage
+I = ReadUI( 'it1', 'tmp/', freq ); % time domain/freq domain current (half time step offset is corrected)
+
+% plot time domain voltage
+figure
+[ax,h1,h2] = plotyy( U.TD{1}.t/1e-9, U.TD{1}.val, U.TD{3}.t/1e-9, U.TD{3}.val );
+set( h1, 'Linewidth', 2 );
+set( h1, 'Color', [1 0 0] );
+set( h2, 'Linewidth', 2 );
+set( h2, 'Color', [0 0 0] );
+grid on
+title( 'time domain voltage' );
+xlabel( 'time t / ns' );
+ylabel( ax(1), 'voltage ut1 / V' );
+ylabel( ax(2), 'voltage et / V' );
+% now make the y-axis symmetric to y=0 (align zeros of y1 and y2)
+y1 = ylim(ax(1));
+y2 = ylim(ax(2));
+ylim( ax(1), [-max(abs(y1)) max(abs(y1))] );
+ylim( ax(2), [-max(abs(y2)) max(abs(y2))] );
+
+% calculate characteristic impedance
+% arithmetic mean of ut1 and ut2 -> voltage in the middle of ut1 and ut2
+U = (U.FD{1}.val + U.FD{2}.val) / 2;
+Z = U ./ I.FD{1}.val;
+
+% plot characteristic impedance
+figure
+plot( freq/1e6, real(Z), 'k-', 'Linewidth', 2 );
+hold on
+grid on
+plot( freq/1e6, imag(Z), 'r--', 'Linewidth', 2 );
+title( 'characteristic impedance of MSL' );
+xlabel( 'frequency f / MHz' );
+ylabel( 'characteristic impedance Z / Ohm' );
+legend( 'real', 'imag' );
+
+%% visualize electric and magnetic fields
+% you will find vtk dump files in the simulation folder (tmp/)
+% use paraview to visualize them
diff --git a/openEMS/matlab/examples/transmission_lines/MSL_Losses.m b/openEMS/matlab/examples/transmission_lines/MSL_Losses.m
new file mode 100644
index 0000000..95cad7b
--- /dev/null
+++ b/openEMS/matlab/examples/transmission_lines/MSL_Losses.m
@@ -0,0 +1,102 @@
+%
+% examples / microstrip / MSL_Losses
+%
+% This example demonstrates how to model sheet conductor losses
+%
+% Tested with
+% - Matlab 2013a / Octave 3.8.1+
+% - openEMS v0.0.32
+%
+% (C) 2012-2014 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-6; % specify everything in um
+MSL.length = 10000;
+MSL.port_dist = 5000;
+MSL.width = 225;
+MSL.conductivity = 41e6;
+MSL.thickness = 35e-6;
+
+substrate.thickness = 250;
+substrate.epr = 9.8;
+
+f_start = 0e9;
+f_stop = 25e9;
+
+lambda = c0/f_stop;
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD('endCriteria',1e-4);
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PEC' 'PML_8'};
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+resolution = c0/(f_stop*sqrt(substrate.epr))/unit /20;
+mesh.x = SmoothMeshLines( [-MSL.length*0.5-MSL.port_dist 0 MSL.length*0.5+MSL.port_dist], resolution, 1.3 ,0 );
+mesh.y = SmoothMeshLines2( [0 MSL.width/2], resolution/6 , 1.3);
+mesh.y = SmoothMeshLines( [-0.5*lambda/unit -mesh.y mesh.y 0.5*lambda/unit], resolution, 1.4);
+mesh.z = SmoothMeshLines( [linspace(0,substrate.thickness,10) 0.5*lambda/unit], resolution );
+CSX = DefineRectGrid( CSX, unit, mesh );
+
+%% substrate
+CSX = AddMaterial( CSX, 'RO4350B' );
+CSX = SetMaterialProperty( CSX, 'RO4350B', 'Epsilon', substrate.epr );
+start = [mesh.x(1), mesh.y(1), 0];
+stop = [mesh.x(end), mesh.y(end), substrate.thickness];
+CSX = AddBox( CSX, 'RO4350B', 0, start, stop );
+
+%% MSL ports and lossy line
+CSX = AddConductingSheet( CSX, 'gold', MSL.conductivity, MSL.thickness );
+portstart = [ mesh.x(1), -MSL.width/2, substrate.thickness];
+portstop = [ mesh.x(1)+MSL.port_dist, MSL.width/2, 0];
+[CSX, port{1}] = AddMSLPort( CSX, 999, 1, 'gold', portstart, portstop, 0, [0 0 -1], 'ExcitePort', true, 'FeedShift', 10*resolution, 'MeasPlaneShift', MSL.port_dist);
+
+portstart = [mesh.x(end), -MSL.width/2, substrate.thickness];
+portstop = [mesh.x(end)-MSL.port_dist, MSL.width/2, 0];
+[CSX, port{2}] = AddMSLPort( CSX, 999, 2, 'gold', portstart, portstop, 0, [0 0 -1], 'MeasPlaneShift', MSL.port_dist );
+
+start = [mesh.x(1)+MSL.port_dist, -MSL.width/2, substrate.thickness];
+stop = [mesh.x(end)-MSL.port_dist, MSL.width/2, substrate.thickness];
+CSX = AddBox(CSX,'gold',500,start,stop);
+
+%% write/show/run the openEMS compatible xml-file
+Sim_Path = 'tmp';
+Sim_CSX = 'msl.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( f_start, f_stop, 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(s21)),'r--','LineWidth',2);
+grid on;
+hold on;
+ylabel('-|S_21| (dB)','Interpreter','None');
+xlabel('frequency (GHz)');
+
+%% plot 35um thickness loss model curve
+% values extracted from http://wcalc.sourceforge.net/cgi-bin/microstrip.cgi
+model.f = [1 2 2.5 3 4 5 7.5 10 12.5 15 17.5 20 25 ]; % frequency in GHz
+model.loss = [3.0 4.2 4.7 5.2 5.9 6.6 8.1 9.38 10.5 11.5 12.4 13.2 14.65]; % loss in db/m
+
+plot(model.f, model.loss * MSL.length * unit ,'k-','LineWidth',1);
+legend('FDTD simulated attenuation','t=35um, loss model by E. Hammerstad & F. Bekkadal','Location','NorthWest');
+
+
diff --git a/openEMS/matlab/examples/transmission_lines/Stripline.m b/openEMS/matlab/examples/transmission_lines/Stripline.m
new file mode 100644
index 0000000..71fd774
--- /dev/null
+++ b/openEMS/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]);
+
diff --git a/openEMS/matlab/examples/transmission_lines/directional_coupler.m b/openEMS/matlab/examples/transmission_lines/directional_coupler.m
new file mode 100644
index 0000000..8ba86f2
--- /dev/null
+++ b/openEMS/matlab/examples/transmission_lines/directional_coupler.m
@@ -0,0 +1,261 @@
+function directional_coupler
+%
+% EXAMPLE / microstrip / directional_coupler
+%
+% Stacked directional coupler in microstrip technology.
+%
+% This example demonstrates:
+% - simple microstrip geometry
+% - S-parameter calculation using the ypar-method
+% - display of coupler parameters
+% - display of S11 (smith chart)
+%
+%
+% Tested with
+% - Matlab 2010b
+% - Octave 3.2.4
+% - openEMS v0.0.17
+%
+% (C) 2010 Sebastian Held <sebastian.held@gmx.de>
+
+clear
+close all
+clc
+
+% sim settings
+showStructure = 1;
+runSimulation = 1;
+
+for n=1:4
+ if n > 1, showStructure = 0; end
+ ports{n} = sim( n, showStructure, runSimulation );
+end
+postprocess( ports );
+
+
+
+
+function ports = sim( simnr, showStructure, runSimulation )
+physical_constants
+
+% setup the simulation
+drawingunit = 1e-6; % specify everything in um
+Sim_Path = ['tmp' int2str(simnr)];
+Sim_CSX = 'tmp.xml';
+f_max = 100e6;
+lambda = c0/f_max;
+
+% specify the coupler
+pcb1.w = 147000;
+pcb1.h = 54500;
+pcb1.t = 1524;
+pcb1.epr = 3;
+msl1.w = 135000;
+msl1.h = 2800;
+pcb2.w = 107000;
+pcb2.h = 14000;
+pcb2.t = 1524;
+pcb2.epr = 3;
+msl2.w = 95000;
+msl2.h = 4000;
+
+
+CSX = InitCSX();
+
+% create the mesh
+mesh.x = [-pcb1.w/2 pcb1.w/2 -pcb2.w/2 pcb2.w/2 -msl1.w/2 msl1.w/2 -msl2.w/2 msl2.w/2];
+mesh.x = [mesh.x linspace(-msl2.w/2,-msl2.w/2+msl2.h, 5) linspace(msl2.w/2,msl2.w/2-msl2.h, 5)];
+mesh.y = [-pcb1.h/2 pcb1.h/2 -pcb2.h/2 pcb2.h/2 -msl1.h/2 msl1.h/2 -msl2.h/2 msl2.h/2];
+mesh.z = [linspace(0,pcb1.t,5) linspace(pcb1.t,pcb1.t+pcb2.t,5)];
+mesh.z = [mesh.z mesh.z(end)+10*(mesh.z(end)-mesh.z(1))]; % add space above pcb
+res = lambda/sqrt(max([pcb1.epr,pcb2.epr])) / 20 / drawingunit;
+mesh.x = SmoothMeshLines2(mesh.x,res);
+mesh.y = SmoothMeshLines2(mesh.y,res);
+mesh.z = SmoothMeshLines2(mesh.z,res);
+mesh = AddPML( mesh, [8 8 8 8 8 8] ); % add space for PML
+CSX = DefineRectGrid( CSX, drawingunit, mesh );
+
+%% create the structure
+
+% microstrip
+CSX = AddMetal( CSX, 'PEC' );
+start = [-msl1.w/2, -msl1.h/2, pcb1.t];
+stop = [ msl1.w/2, msl1.h/2, pcb1.t];
+priority = 100; % the geometric priority is set to 100
+CSX = AddBox( CSX, 'PEC', priority, start, stop );
+
+% ground plane
+CSX = AddMetal( CSX, 'PEC_ground' );
+start = [-pcb1.w/2, -pcb1.h/2, 0];
+stop = [ pcb1.w/2, pcb1.h/2, 0];
+CSX = AddBox( CSX, 'PEC_ground', priority, start, stop );
+
+% substrate 1
+start = [-pcb1.w/2, -pcb1.h/2, 0];
+stop = [ pcb1.w/2, pcb1.h/2, pcb1.t];
+priority = 10;
+CSX = AddMaterial( CSX, 'substrate1' );
+CSX = SetMaterialProperty( CSX, 'substrate1', 'Epsilon', pcb1.epr );
+CSX = AddBox( CSX, 'substrate1', priority, start, stop );
+
+% substrate 2
+start = [-pcb2.w/2, -pcb2.h/2, pcb1.t];
+stop = [ pcb2.w/2, pcb2.h/2, pcb1.t+pcb2.t];
+priority = 10;
+CSX = AddMaterial( CSX, 'substrate2' );
+CSX = SetMaterialProperty( CSX, 'substrate2', 'Epsilon', pcb2.epr );
+CSX = AddBox( CSX, 'substrate2', priority, start, stop );
+
+% stripline
+start = [-msl2.w/2, -msl2.h/2, pcb1.t+pcb2.t];
+stop = [ msl2.w/2, msl2.h/2, pcb1.t+pcb2.t];
+priority = 100;
+CSX = AddBox( CSX, 'PEC', priority, start, stop );
+
+% connections
+start = [-msl2.w/2, -msl2.h/2, pcb1.t+pcb2.t];
+stop = [-msl2.w/2+msl2.h, -pcb2.h/2, pcb1.t+pcb2.t];
+priority = 100;
+CSX = AddBox( CSX, 'PEC', priority, start, stop );
+start = [ msl2.w/2, -msl2.h/2, pcb1.t+pcb2.t];
+stop = [ msl2.w/2-msl2.h, -pcb2.h/2, pcb1.t+pcb2.t];
+priority = 100;
+CSX = AddBox( CSX, 'PEC', priority, start, stop );
+
+%% ports
+% this project needs 4 simulations
+for n=1:4
+ portexcite{n} = [];
+end
+portexcite{simnr} = 'excite';
+
+% port 1: input port
+start = [-msl1.w/2, 0, pcb1.t];
+stop = [-msl1.w/2, 0, 0];
+[CSX ports{1}] = AddCurvePort( CSX, 999, 1, 50, start, stop, portexcite{1} );
+% port 2: output port
+start = [msl1.w/2, 0, pcb1.t];
+stop = [msl1.w/2, 0, 0];
+[CSX ports{2}] = AddCurvePort( CSX, 999, 2, 50, start, stop, portexcite{2} );
+% port 3: coupled port
+start = [-msl2.w/2+msl2.h/2, -pcb2.h/2, pcb1.t+pcb2.t];
+stop = [-msl2.w/2+msl2.h/2, -pcb2.h/2, 0];
+[CSX ports{3}] = AddCurvePort( CSX, 999, 3, 50, start, stop, portexcite{3} );
+% port 4: isolated port
+start = [msl2.w/2-msl2.h/2, -pcb2.h/2, pcb1.t+pcb2.t];
+stop = [msl2.w/2-msl2.h/2, -pcb2.h/2, 0];
+[CSX ports{4}] = AddCurvePort( CSX, 999, 4, 50, start, stop, portexcite{4} );
+
+%% setup FDTD parameters & excitation function
+max_timesteps = 50000;
+min_decrement = 1e-6;
+FDTD = InitFDTD( max_timesteps, min_decrement );
+FDTD = SetGaussExcite( FDTD, 0, f_max );
+BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'};
+BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % faster
+FDTD = SetBoundaryCond( FDTD, BC );
+
+%% Write openEMS compatible xml-file
+if runSimulation
+ [dummy,dummy,dummy] = rmdir(Sim_Path,'s');
+end
+[dummy,dummy,dummy] = mkdir(Sim_Path);
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+if showStructure
+ CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
+end
+
+%% run openEMS
+openEMS_opts = '';
+openEMS_opts = [openEMS_opts ' --engine=fastest'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --debug-boxes'];
+if runSimulation
+ RunOpenEMS( Sim_Path, Sim_CSX, openEMS_opts );
+end
+
+
+
+
+function postprocess( ports )
+f = linspace( 0, 100e6, 201 );
+Y = calc_ypar( f, ports{1}, 'tmp' );
+R = 50;
+S = y2s(Y,R);
+
+% insertion loss
+IL_dB = -20 * log10(abs(squeeze(S(2,1,:))));
+
+% coupling factor
+CF_dB = -20 * log10(abs(squeeze(S(3,1,:))));
+
+% isolation
+I_dB = -20 * log10(abs(squeeze(S(4,1,:))));
+
+% directivity
+D_dB = -20 * log10(abs(squeeze(S(4,1,:) ./ S(3,1,:))));
+
+figure
+plot( f, [IL_dB CF_dB I_dB D_dB] );
+legend( {'insertion loss','coupling factor','isolation','directivity'} );
+title( ['performance of the coupler for a termination resistance of R=' num2str(R)] );
+grid on
+
+smithchart
+S11 = squeeze(S(1,1,:));
+plot( real(S11), imag(S11) );
+legend( 'S_{11}' );
+title( ['performance of the coupler for a termination resistance of R=' num2str(R)] );
+axis( [-1 1 -1 1] );
+
+
+
+function smithchart
+% smith chart
+figure
+if exist( 'smith', 'file' )
+ % smith chart
+ % www.ece.rutgers.edu/~orfanidi/ewa
+ % or cmt toolbox from git.ate.uni-duisburg.de
+ smith
+else
+ % poor man smith chart
+ color = [.6 .6 .6];
+ h = plot( sin(0:0.01:2*pi), cos(0:0.01:2*pi), 'Color', color );
+ hg = hggroup;
+ set( h,'Parent',hg );
+ hold on
+ plot( hg, 0.25+0.75*sin(0:0.01:2*pi), 0.75*cos(0:0.01:2*pi), 'Color', color );
+ plot( hg, 0.5+0.5*sin(0:0.01:2*pi), 0.5*cos(0:0.01:2*pi), 'Color', color );
+ plot( hg, 0.75+0.25*sin(0:0.01:2*pi), 0.25*cos(0:0.01:2*pi), 'Color', color );
+ plot( hg, [-1 1], [0 0], 'Color', color );
+ axis equal
+ axis off
+end
+
+
+function s = y2s(y, ZL)
+% S = y2s(Y, ZL)
+%
+% Admittance to Scattering transformation
+% for square matrices at multiple frequencies
+%
+% ZL defaults to 50 Ohm
+
+if nargin < 2
+ ZL = 50;
+end
+
+if size(size(y),2) > 2
+ nF = size(y,3);
+else
+ nF = 1;
+end
+
+I = diag(ones(1, size(y,2)))/ZL;
+
+for i=1:nF
+ %s(:,:,i) = inv(I+y(:,:,i)) * (I-y(:,:,i));
+ s(:,:,i) = (I+y(:,:,i)) \ (I-y(:,:,i));
+end
diff --git a/openEMS/matlab/examples/waveguide/Circ_Waveguide.m b/openEMS/matlab/examples/waveguide/Circ_Waveguide.m
new file mode 100644
index 0000000..9ee860e
--- /dev/null
+++ b/openEMS/matlab/examples/waveguide/Circ_Waveguide.m
@@ -0,0 +1,207 @@
+%
+% EXAMPLE / waveguide / circular waveguide
+%
+% This example demonstrates how to:
+% - setup a circular waveguide
+% - use analytic functions for waveguide excitations and voltage/current
+% calculations
+%
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.17
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+use_pml = 0; % use pml boundaries instead of mur
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+numTS = 1e5; %number of timesteps
+length = 1000; %length of the waveguide
+unit = 1e-3; %drawing unit used
+rad = 300; %radius of the circular waveguide
+mesh_res = [10 10 15]; %desired mesh resolution
+
+%excitation
+f0 = 350e6; %center frequency
+f0_BW = 25e6; %bandwidth: 10dB cut-off frequency
+
+physical_constants
+
+%% TE11 mode definitions (Pozar 3rd edition)
+p11 = 1.841;
+kc = p11 / rad /unit;
+k = 2*pi*f0/C0;
+fc = C0*kc/2/pi;
+beta = sqrt(k^2 - kc^2);
+n_eff = (beta/k);
+
+kc = kc*unit; %functions must be defined in drawing units
+func_Er = [ num2str(-1/kc^2) '/rho*cos(a)*j1(' num2str(kc) '*rho)'];
+func_Ea = [ num2str(1/kc) '*sin(a)*0.5*(j0(' num2str(kc) '*rho)-jn(2,' num2str(kc) '*rho))'];
+func_Ex = ['(' func_Er '*cos(a) - ' func_Ea '*sin(a) )*(rho<' num2str(rad) ')'];
+func_Ey = ['(' func_Er '*sin(a) + ' func_Ea '*cos(a) )*(rho<' num2str(rad) ')'];
+
+func_Ha = [ num2str(-1/kc^2,'%14.13f') '/rho*cos(a)*j1(' num2str(kc,'%14.13f') '*rho)'];
+func_Hr = [ '-1*' num2str(1/kc,'%14.13f') '*sin(a)*0.5*(j0(' num2str(kc,'%14.13f') '*rho)-jn(2,' num2str(kc,'%14.13f') '*rho))'];
+func_Hx = ['(' func_Hr '*cos(a) - ' func_Ha '*sin(a) )*(rho<' num2str(rad) ')'];
+func_Hy = ['(' func_Hr '*sin(a) + ' func_Ha '*cos(a) )*(rho<' num2str(rad) ')'];
+
+%% define files and path %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Sim_Path = 'tmp';
+Sim_CSX = 'Circ_WG.xml';
+
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir(Sim_Path,'s');
+ [status, message, messageid] = mkdir(Sim_Path);
+end
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(numTS,1e-6,'OverSampling',5);
+FDTD = SetGaussExcite(FDTD,f0,f0_BW);
+BC = {'PEC','PEC','PEC','PEC','PEC','MUR'};
+if (use_pml>0)
+ BC = {'PEC','PEC','PEC','PEC','PEC','PML_8'};
+end
+FDTD = SetBoundaryCond(FDTD,BC,'MUR_PhaseVelocity',C0 / n_eff);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = -mesh_res(1)/2-rad:mesh_res(1):rad+mesh_res(1)/2;
+mesh.y = -mesh_res(2)/2-rad:mesh_res(2):rad+mesh_res(2)/2;
+mesh.z = 0 : mesh_res(3) : length;
+CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+start = [0,0,0];
+stop = [0,0,length];
+
+%%% fill everything with copper, priority 0
+CSX = AddMetal(CSX,'copper');
+% CSX = SetMaterialProperty(CSX,'copper','Kappa',56e6);
+CSX = AddBox(CSX,'copper',0,[mesh.x(1) mesh.y(1) mesh.z(1)],[mesh.x(end) mesh.y(end) mesh.z(end)]);
+
+%%% cut out an air cylinder as circular waveguide... priority 5
+CSX = AddMaterial(CSX,'air');
+CSX = SetMaterialProperty(CSX,'air','Epsilon',1);
+CSX = AddCylinder(CSX,'air', 5 ,start,stop,rad);
+
+CSX = AddExcitation(CSX,'excite',0,[1 1 0]);
+weight{1} = func_Ex;
+weight{2} = func_Ey;
+weight{3} = 0;
+CSX = SetExcitationWeight(CSX, 'excite', weight );
+CSX = AddCylinder(CSX,'excite', 5 ,[0 0 -0.1],[0 0 0.1],rad);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et_','SubSampling','2,2,2','FileType',0,'DumpMode',2);
+start = [mesh.x(1) , 0 , mesh.z(1)];
+stop = [mesh.x(end), 0 , mesh.z(end)];
+CSX = AddBox(CSX,'Et_',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht_','SubSampling','2,2,2','DumpType',1,'FileType',0,'DumpMode',2);
+CSX = AddBox(CSX,'Ht_',0,start,stop);
+
+%% define voltage calc boxes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%voltage calc
+start = [mesh.x(1) mesh.y(1) mesh.z(10)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(10)];
+CSX = AddProbe(CSX, 'ut1', 10, 1, [], 'ModeFunction',{func_Ex,func_Ey,0});
+CSX = AddBox(CSX, 'ut1', 0 ,start,stop);
+CSX = AddProbe(CSX,'it1', 11, 1, [], 'ModeFunction',{func_Hx,func_Hy,0});
+CSX = AddBox(CSX,'it1', 0 ,start,stop);
+
+start = [mesh.x(1) mesh.y(1) mesh.z(end-10)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end-10)];
+CSX = AddProbe(CSX, 'ut2', 10, 1, [], 'ModeFunction',{func_Ex,func_Ey,0});
+CSX = AddBox(CSX, 'ut2', 0 ,start,stop);
+CSX = AddProbe(CSX,'it2', 11, 1, [], 'ModeFunction',{func_Hx,func_Hy,0});
+CSX = AddBox(CSX,'it2', 0 ,start,stop);
+
+port_dist = mesh.z(end-10) - mesh.z(10);
+
+%% Write openEMS
+if (postprocessing_only==0)
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+ RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+end
+
+%% do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+freq = linspace(f0-f0_BW,f0+f0_BW,201);
+U = ReadUI({'ut1','ut2'},[Sim_Path '/'],freq);
+I = ReadUI({'it1','it2'},[Sim_Path '/'],freq);
+Exc = ReadUI('et',Sim_Path,freq);
+
+k = 2*pi*freq/C0;
+kc = p11 / rad /unit;
+beta = sqrt(k.^2 - kc^2);
+
+ZL_a = Z0*k./beta ;
+
+uf1 = U.FD{1}.val./Exc.FD{1}.val;
+uf2 = U.FD{2}.val./Exc.FD{1}.val;
+if1 = I.FD{1}.val./Exc.FD{1}.val;
+if2 = I.FD{2}.val./Exc.FD{1}.val;
+
+uf1_inc = 0.5 * ( uf1 + if1 .* ZL_a );
+if1_inc = 0.5 * ( if1 + uf1 ./ ZL_a );
+uf2_inc = 0.5 * ( uf2 + if2 .* ZL_a );
+if2_inc = 0.5 * ( if2 + uf2 ./ ZL_a );
+
+uf1_ref = uf1 - uf1_inc;
+if1_ref = if1 - if1_inc;
+uf2_ref = uf2 - uf2_inc;
+if2_ref = if2 - if2_inc;
+
+% plot s-parameter
+figure
+s11 = uf1_ref./uf1_inc;
+s21 = uf2_inc./uf1_inc;
+plot(freq,20*log10(abs(s11)),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('s-para (dB)');
+% ylim([-40 5]);
+grid on;
+hold on;
+plot(freq,20*log10(abs(s21)),'r','Linewidth',2);
+legend('s11','s21','Location','SouthEast');
+
+% plot line-impedance comparison
+figure()
+ZL = uf1./if1;
+plot(freq,real(ZL),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('line-impedance (\Omega)');
+grid on;
+hold on;
+plot(freq,imag(ZL),'r--','Linewidth',2);
+plot(freq,ZL_a,'g-.','Linewidth',2);
+legend('\Re\{ZL\}','\Im\{ZL\}','ZL-analytic','Location','Best');
+
+% beta compare
+figure()
+da = angle(uf1_inc)-angle(uf2_inc);
+da = mod(da,2*pi);
+beta_12 = (da)/port_dist/unit;
+plot(freq,beta_12,'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)');
+ylabel('\beta (m^{-1})');
+grid on;
+hold on;
+plot(freq,beta,'g--','Linewidth',2);
+legend('\beta-FDTD','\beta-analytic','Location','Best');
+
+%% visualize electric & magnetic fields
+disp('you will find vtk dump files in the simulation folder (tmp/)')
+disp('use paraview to visulaize them');
diff --git a/openEMS/matlab/examples/waveguide/Circ_Waveguide_CylinderCoords.m b/openEMS/matlab/examples/waveguide/Circ_Waveguide_CylinderCoords.m
new file mode 100644
index 0000000..a767c0a
--- /dev/null
+++ b/openEMS/matlab/examples/waveguide/Circ_Waveguide_CylinderCoords.m
@@ -0,0 +1,204 @@
+%
+% EXAMPLE / waveguide / circular waveguide cylindrical coordinates
+%
+% This example demonstrates how to:
+% - use cylindrical coordinates
+% - setup a circular waveguide defined by the boundary conditions of the
+% cylindrical coordinate system
+% - use analytic functions for waveguide excitations and voltage/current
+% calculations
+%
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.17
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+use_pml = 0; % use pml boundaries instead of mur
+use_MultiGrid = 1; % disable multi-grid for this example
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+numTS = 1e5; %number of timesteps
+length = 1000; %length of the waveguide
+unit = 1e-3; %drawing unit used
+rad = 300; %radius of the circular waveguide
+mesh_res = [10 nan 15]; %desired mesh resolution
+N_alpha = 50; %mesh lines in azimuth direction
+
+MultiGrid_Level = [50]; % define multigrid radii (if enabled)
+
+%excitation
+f0 = 350e6; %center frequency
+f0_BW = 25e6; %bandwidth: 10dB cut-off frequency
+
+physical_constants
+
+%% TE11 mode definitions (Pozar 3rd edition)
+p11 = 1.841;
+kc = p11 / rad /unit;
+k = 2*pi*f0/C0;
+fc = C0*kc/2/pi;
+beta = sqrt(k^2 - kc^2);
+n_eff = (beta/k);
+
+kc = kc*unit; %functions must be defined in drawing units
+func_Er = [ num2str(-1/kc^2,15) '/rho*cos(a)*j1(' num2str(kc,15) '*rho)'];
+func_Ea = [ num2str(1/kc,15) '*sin(a)*0.5*(j0(' num2str(kc,15) '*rho)-jn(2,' num2str(kc,15) '*rho))'];
+func_Ha = [ num2str(-1/kc^2,'%14.13f') '/rho*cos(a)*j1(' num2str(kc,'%14.13f') '*rho)'];
+func_Hr = [ '-1*' num2str(1/kc,'%14.13f') '*sin(a)*0.5*(j0(' num2str(kc,'%14.13f') '*rho)-jn(2,' num2str(kc,'%14.13f') '*rho))'];
+
+%% define files and path %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Sim_Path = 'tmp';
+Sim_CSX = 'Circ_WG_CC.xml';
+
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir(Sim_Path,'s');
+ [status, message, messageid] = mkdir(Sim_Path);
+end
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if (use_MultiGrid==0)
+ FDTD = InitCylindricalFDTD(numTS,1e-5,'OverSampling',10);
+else
+ mg_str = num2str(MultiGrid_Level,'%d,'); %create comma-separated string
+ N_alpha = round(N_alpha * 2^numel(MultiGrid_Level));
+ FDTD = InitCylindricalFDTD(numTS,1e-5,'OverSampling',10,'MultiGrid',mg_str(1:end-1));
+end
+FDTD = SetGaussExcite(FDTD,f0,f0_BW);
+BC = {'PEC','PEC','PEC','PEC','PEC','MUR'};
+if (use_pml>0)
+ BC = {'PEC','PEC','PEC','PEC','PEC','PML_8'};
+end
+FDTD = SetBoundaryCond(FDTD,BC,'MUR_PhaseVelocity',C0 / n_eff);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX('CoordSystem',1);
+mesh.x = 0:mesh_res(1):rad;
+%define an odd number of lines in alpha-direction
+mesh.y = linspace(-pi,pi,N_alpha+mod(N_alpha+1,2))+pi/2;
+mesh.z = 0 : mesh_res(3) : length;
+CSX = DefineRectGrid(CSX, unit,mesh);
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddExcitation(CSX,'excite',0,[1 1 0]);
+weight{1} = func_Er;
+weight{2} = func_Ea;
+weight{3} = 0;
+CSX = SetExcitationWeight(CSX, 'excite', weight );
+start = [mesh.x(1) mesh.y(1) mesh.z(1)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(1)];
+CSX = AddBox(CSX,'excite', 5 ,start,stop);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et_','FileType',0,'DumpMode',2,'SubSampling','2,2,2');
+start = [mesh.x(1) , 0 , mesh.z(1)];
+stop = [mesh.x(end), 0 , mesh.z(end)];
+CSX = AddBox(CSX,'Et_',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht','FileType',0,'DumpType',1,'DumpMode',2,'SubSampling','2,2,2');
+CSX = AddBox(CSX,'Ht',0 , start,stop);
+
+%% define voltage calc boxes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start = [mesh.x(1) mesh.y(1) mesh.z(10)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(10)];
+CSX = AddProbe(CSX, 'ut1', 10, 1, [], 'ModeFunction',{func_Er,func_Ea,0});
+CSX = AddBox(CSX, 'ut1', 0 ,start,stop);
+CSX = AddProbe(CSX,'it1', 11, 1, [], 'ModeFunction',{func_Hr,func_Ha,0});
+CSX = AddBox(CSX,'it1', 0 ,start,stop);
+
+start = [mesh.x(1) mesh.y(1) mesh.z(end-10)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end-10)];
+CSX = AddProbe(CSX, 'ut2', 10, 1, [], 'ModeFunction',{func_Er,func_Ea,0});
+CSX = AddBox(CSX, 'ut2', 0 ,start,stop);
+CSX = AddProbe(CSX,'it2', 11, 1, [], 'ModeFunction',{func_Hr,func_Ha,0});
+CSX = AddBox(CSX,'it2', 0 ,start,stop);
+
+port_dist = mesh.z(end-10) - mesh.z(10);
+
+%% Write openEMS
+if (postprocessing_only==0)
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+ RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+end
+
+%% do the plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+freq = linspace(f0-f0_BW,f0+f0_BW,201);
+U = ReadUI({'ut1','ut2'},[Sim_Path '/'],freq);
+I = ReadUI({'it1','it2'},[Sim_Path '/'],freq);
+Exc = ReadUI('et',Sim_Path,freq);
+
+k = 2*pi*freq/C0;
+kc = p11 / rad /unit;
+beta = sqrt(k.^2 - kc^2);
+
+ZL_a = Z0*k./beta ;
+
+uf1 = U.FD{1}.val./Exc.FD{1}.val;
+uf2 = U.FD{2}.val./Exc.FD{1}.val;
+if1 = I.FD{1}.val./Exc.FD{1}.val;
+if2 = I.FD{2}.val./Exc.FD{1}.val;
+
+uf1_inc = 0.5 * ( uf1 + if1 .* ZL_a );
+if1_inc = 0.5 * ( if1 + uf1 ./ ZL_a );
+uf2_inc = 0.5 * ( uf2 + if2 .* ZL_a );
+if2_inc = 0.5 * ( if2 + uf2 ./ ZL_a );
+
+uf1_ref = uf1 - uf1_inc;
+if1_ref = if1 - if1_inc;
+uf2_ref = uf2 - uf2_inc;
+if2_ref = if2 - if2_inc;
+
+% plot s-parameter
+figure
+s11 = uf1_ref./uf1_inc;
+s21 = uf2_inc./uf1_inc;
+plot(freq,20*log10(abs(s11)),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('s-para (dB)');
+% ylim([-40 5]);
+grid on;
+hold on;
+plot(freq,20*log10(abs(s21)),'r','Linewidth',2);
+legend('s11','s21','Location','SouthEast');
+
+% plot line-impedance comparison
+figure()
+ZL = uf1./if1;
+plot(freq,real(ZL),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('line-impedance (\Omega)');
+grid on;
+hold on;
+plot(freq,imag(ZL),'r--','Linewidth',2);
+plot(freq,ZL_a,'g-.','Linewidth',2);
+legend('\Re\{ZL\}','\Im\{ZL\}','ZL-analytic','Location','Best');
+
+%% beta compare
+figure()
+da = angle(uf1_inc)-angle(uf2_inc);
+da = mod(da,2*pi);
+beta_12 = (da)/port_dist/unit;
+plot(freq,beta_12,'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)');
+ylabel('\beta (m^{-1})');
+grid on;
+hold on;
+plot(freq,beta,'g--','Linewidth',2);
+legend('\beta-FDTD','\beta-analytic','Location','Best');
+
+%% visualize electric & magnetic fields
+disp('you will find vtk dump files in the simulation folder (tmp/)')
+disp('use paraview to visulaize them');
diff --git a/openEMS/matlab/examples/waveguide/Coax.m b/openEMS/matlab/examples/waveguide/Coax.m
new file mode 100644
index 0000000..3db4d6a
--- /dev/null
+++ b/openEMS/matlab/examples/waveguide/Coax.m
@@ -0,0 +1,120 @@
+%
+% EXAMPLE / waveguide / coaxial cable
+%
+% This example demonstrates how to:
+% - setup a coaxial waveguide
+% - use analytic functions for waveguide excitations and voltage/current
+% calculations
+%
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.17
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+use_pml = 0; % use pml boundaries instead of mur
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+numTS = 5000; %number of timesteps
+length = 1000; %length of the waveguide
+unit = 1e-3; %drawing unit used
+coax_rad_i = 100; %inner radius
+coax_rad_ai = 230; %inner radius of outer cladding
+coax_rad_aa = 240; %outer radius of outer cladding
+mesh_res = [5 5 5]; %desired mesh resolution
+
+physical_constants;
+
+%excitation
+f0 = 0.5e9;
+epsR = 1;
+
+%% create sim path %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Sim_Path = 'tmp';
+Sim_CSX = 'coax.xml';
+
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir(Sim_Path,'s');
+ [status, message, messageid] = mkdir(Sim_Path);
+end
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(numTS,1e-5);
+FDTD = SetGaussExcite(FDTD,f0,f0);
+BC = {'PEC','PEC','PEC','PEC','MUR','MUR'};
+if (use_pml>0)
+ BC = {'PEC','PEC','PEC','PEC','PML_8','PML_8'};
+end
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = -coax_rad_aa : mesh_res(1) : coax_rad_aa;
+mesh.y = mesh.x;
+mesh.z = SmoothMeshLines([0 length], mesh_res(3));
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%%% coax
+CSX = AddMetal(CSX,'copper');
+start = [0,0,0];
+stop = [0,0,length/2];
+[CSX,port{1}] = AddCoaxialPort( CSX, 10, 1, 'copper', '', start, stop, 'z', coax_rad_i, coax_rad_ai, coax_rad_aa, 'ExciteAmp', 1,'FeedShift', 10*mesh_res(1) );
+
+start = [0,0,length/2];
+stop = [0,0,length];
+[CSX,port{2}] = AddCoaxialPort( CSX, 10, 2, 'copper', '', start, stop, 'z', coax_rad_i, coax_rad_ai, coax_rad_aa );
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et_','DumpMode',2);
+start = [mesh.x(1) , 0 , mesh.z(1)];
+stop = [mesh.x(end) , 0 , mesh.z(end)];
+CSX = AddBox(CSX,'Et_',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht_','DumpType',1,'DumpMode',2);
+CSX = AddBox(CSX,'Ht_',0,start,stop);
+
+%% Write openEMS
+if (postprocessing_only==0)
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+ CSXGeomPlot([Sim_Path '/' Sim_CSX]);
+ RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+end
+
+%%
+freq = linspace(0,2*f0,201);
+port = calcPort(port, Sim_Path, freq);
+
+%% plot s-parameter
+figure
+s11 = port{1}.uf.ref./port{1}.uf.inc;
+s21 = port{2}.uf.inc./port{1}.uf.inc;
+plot(freq,20*log10(abs(s11)),'Linewidth',2);
+hold on
+grid on
+plot(freq,20*log10(abs(s21)),'r--','Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('s-para (dB)');
+
+%% plot line-impedance comparison
+figure()
+ZL_a = ones(size(freq))*Z0/2/pi/sqrt(epsR)*log(coax_rad_ai/coax_rad_i); %analytic line-impedance of a coax
+ZL = port{2}.uf.tot./port{2}.if.tot;
+plot(freq,real(port{1}.ZL),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('line-impedance (\Omega)');
+grid on;
+hold on;
+plot(freq,imag(port{1}.ZL),'r--','Linewidth',2);
+plot(freq,ZL_a,'g-.','Linewidth',2);
+legend('\Re\{ZL\}','\Im\{ZL\}','ZL-analytic','Location','Best');
diff --git a/openEMS/matlab/examples/waveguide/Coax_CylinderCoords.m b/openEMS/matlab/examples/waveguide/Coax_CylinderCoords.m
new file mode 100644
index 0000000..5e4606c
--- /dev/null
+++ b/openEMS/matlab/examples/waveguide/Coax_CylinderCoords.m
@@ -0,0 +1,190 @@
+%
+% EXAMPLE / waveguide / coaxial cable using cylindrical coordinates
+%
+% This example demonstrates how to:
+% - use cylindrical coordinates
+% - setup a coaxial waveguide
+% - use analytic functions for waveguide excitations and voltage/current
+% calculations
+%
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.17
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+close all
+clear
+clc
+
+%% switches & options...
+postprocessing_only = 0;
+use_pml = 0; % use pml boundaries instead of mur
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+numTS = 1e5; %number of timesteps
+length = 1000; %length of the waveguide
+unit = 1e-3; %drawing unit used
+coax_rad_i = 100; %inner radius
+coax_rad_a = 230; %outer radius
+mesh_res = [10 nan 10]; %desired mesh resolution
+N_alpha = 71; %mesh lines in azimuth direction
+
+physical_constants;
+
+%excitation
+f0 = 0.5e9;
+epsR = 1;
+
+%% create sim path %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Sim_Path = 'tmp';
+Sim_CSX = 'coax.xml';
+
+if (postprocessing_only==0)
+ [status, message, messageid] = rmdir(Sim_Path,'s');
+ [status, message, messageid] = mkdir(Sim_Path);
+end
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitCylindricalFDTD(numTS,1e-5);
+FDTD = SetGaussExcite(FDTD,f0,f0);
+BC = {'PEC','PEC','PEC','PEC','PEC','MUR'};
+if (use_pml>0)
+ BC = {'PEC','PEC','PEC','PEC','PEC','PML_8'};
+end
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX('CoordSystem',1);
+mesh.x = coax_rad_i : mesh_res(1) : coax_rad_a;
+mesh.y = linspace(0,2*pi,N_alpha);
+mesh.z = 0 : mesh_res(3) : length;
+CSX = DefineRectGrid(CSX, unit, mesh);
+
+%% material
+CSX = AddMaterial(CSX,'fill');
+CSX = SetMaterialProperty(CSX,'fill','Epsilon',epsR);
+start = [mesh.x(1) mesh.y(1) 0];
+stop = [mesh.x(end) mesh.y(end) length];
+CSX = AddBox(CSX,'fill',0 ,start,stop);
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddExcitation(CSX,'excite',0,[1 0 0]);
+weight{1} = '1/rho';
+weight{2} = 0;
+weight{3} = 0;
+CSX = SetExcitationWeight(CSX, 'excite', weight );
+start = [coax_rad_i mesh.y(1) 0];
+stop = [coax_rad_a mesh.y(end) 0];
+CSX = AddBox(CSX,'excite',0 ,start,stop);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et_','DumpMode',0);
+start = [mesh.x(1) , 0 , mesh.z(1)];
+stop = [mesh.x(end) , 0 , mesh.z(end)];
+CSX = AddBox(CSX,'Et_',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht_','DumpType',1,'DumpMode',0);
+CSX = AddBox(CSX,'Ht_',0,start,stop);
+
+%% define voltage calc boxes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%voltage calc
+CSX = AddProbe(CSX,'ut1',0);
+start = [ coax_rad_i 0 mesh.z(10) ];
+stop = [ coax_rad_a 0 mesh.z(10) ];
+CSX = AddBox(CSX,'ut1', 0 ,start,stop);
+CSX = AddProbe(CSX,'ut2',0);
+start = [ coax_rad_i 0 mesh.z(end-10)];
+stop = [ coax_rad_a 0 mesh.z(end-10)];
+CSX = AddBox(CSX,'ut2', 0 ,start,stop);
+
+%current calc, for each position there are two currents, which will get
+%averaged to match the voltage position in between (!Yee grid!)
+CSX = AddProbe(CSX,'it1a',1);
+mid = 0.5*(coax_rad_i+coax_rad_a);
+start = [ 0 mesh.z(1) mesh.z(9) ];
+stop = [ mid mesh.z(end) mesh.z(9) ];
+CSX = AddBox(CSX,'it1a', 0 ,start,stop);
+CSX = AddProbe(CSX,'it1b',1);
+start = [ 0 mesh.z(1) mesh.z(10) ];
+stop = [ mid mesh.z(end) mesh.z(10) ];
+CSX = AddBox(CSX,'it1b', 0 ,start,stop);
+
+CSX = AddProbe(CSX,'it2a',1);
+start = [ 0 mesh.z(1) mesh.z(end-11) ];
+stop = [ mid mesh.z(end) mesh.z(end-11) ];
+CSX = AddBox(CSX,'it2a', 0 ,start,stop);
+CSX = AddProbe(CSX,'it2b',1);
+start = [ 0 mesh.z(1) mesh.z(end-10) ];
+stop = [ mid mesh.z(end) mesh.z(end-10) ];
+CSX = AddBox(CSX,'it2b', 0 ,start,stop);
+
+%% Write openEMS
+if (postprocessing_only==0)
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+ RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts);
+end
+
+%%
+freq = linspace(0,2*f0,201);
+U = ReadUI({'ut1','ut2'},[Sim_Path '/'],freq);
+I = ReadUI({'it1a','it1b','it2a','it2b'},[Sim_Path '/'],freq);
+Exc = ReadUI('et',Sim_Path,freq);
+
+%% plot voltages
+figure
+plot(U.TD{1}.t, U.TD{1}.val,'Linewidth',2);
+hold on;
+grid on;
+plot(U.TD{2}.t, U.TD{2}.val,'r--','Linewidth',2);
+xlabel('time (s)')
+ylabel('voltage (V)')
+legend('u_1(t)','u_2(t)')
+
+%% calculate incoming and reflected voltages & currents
+ZL_a = ones(size(freq))*Z0/2/pi/sqrt(epsR)*log(coax_rad_a/coax_rad_i); %analytic line-impedance of a coax
+
+uf1 = U.FD{1}.val./Exc.FD{1}.val;
+uf2 = U.FD{2}.val./Exc.FD{1}.val;
+if1 = 0.5*(I.FD{1}.val+I.FD{2}.val)./Exc.FD{1}.val;
+if2 = 0.5*(I.FD{3}.val+I.FD{4}.val)./Exc.FD{1}.val;
+
+uf1_inc = 0.5 * ( uf1 + if1 .* ZL_a );
+if1_inc = 0.5 * ( if1 + uf1 ./ ZL_a );
+uf2_inc = 0.5 * ( uf2 + if2 .* ZL_a );
+if2_inc = 0.5 * ( if2 + uf2 ./ ZL_a );
+
+uf1_ref = uf1 - uf1_inc;
+if1_ref = if1 - if1_inc;
+uf2_ref = uf2 - uf2_inc;
+if2_ref = if2 - if2_inc;
+
+% plot s-parameter
+figure
+s11 = uf1_ref./uf1_inc;
+s21 = uf2_inc./uf1_inc;
+plot(freq,20*log10(abs(s11)),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('s-para (dB)');
+% ylim([-40 5]);
+grid on;
+hold on;
+plot(freq,20*log10(abs(s21)),'r','Linewidth',2);
+legend('s11','s21','Location','SouthEast');
+
+% plot line-impedance comparison
+figure()
+ZL = uf1./if1;
+plot(freq,real(ZL),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)')
+ylabel('line-impedance (\Omega)');
+grid on;
+hold on;
+plot(freq,imag(ZL),'r--','Linewidth',2);
+plot(freq,ZL_a,'g-.','Linewidth',2);
+legend('\Re\{ZL\}','\Im\{ZL\}','ZL-analytic','Location','Best');
diff --git a/openEMS/matlab/examples/waveguide/Coax_Cylindrical_MG.m b/openEMS/matlab/examples/waveguide/Coax_Cylindrical_MG.m
new file mode 100644
index 0000000..84a1668
--- /dev/null
+++ b/openEMS/matlab/examples/waveguide/Coax_Cylindrical_MG.m
@@ -0,0 +1,155 @@
+close all
+clear
+clc
+
+%example for an cylindrical mesh, modeling a coaxial cable
+% this example is using a multi-grid approach
+
+
+%% setup %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Settings = [];
+Settings.LogFile = 'openEMS.log';
+
+physical_constants
+
+f0 = 0.5e9;
+epsR = 1; %material filling
+
+length = 1000;
+port_dist = length/2;
+rad_i = 10; %inner radius
+rad_a = 200; %outer radius
+partial = 0.5; %e.g. 0.5 means only one half of a coax, should be <1 or change boundary cond.
+max_mesh = 10 / sqrt(epsR);
+max_alpha = max_mesh;
+N_alpha = ceil(rad_a * 2*pi * partial / max_alpha);
+
+%make it even...
+N_alpha = N_alpha + mod(N_alpha,2);
+%make sure it is multiple of 4, needed for 2 multi-grid steps
+N_alpha = ceil((N_alpha)/4) *4 + 1;
+
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --numThreads=1'];
+
+def_refSimu = 0; % do a reference simulation without the multi-grid
+
+%% setup done %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+if (def_refSimu>0)
+ Sim_Path = 'tmp_ref';
+else
+ Sim_Path = 'tmp';
+end
+Sim_CSX = 'coax.xml';
+
+if (exist(Sim_Path,'dir'))
+ rmdir(Sim_Path,'s');
+end
+mkdir(Sim_Path);
+
+%setup FDTD parameter
+if (def_refSimu>0)
+ FDTD = InitCylindricalFDTD(1e5,1e-5,'OverSampling',5 );
+else
+ FDTD = InitCylindricalFDTD(1e5,1e-5,'OverSampling',5 ,'MultiGrid','60,120');
+end
+FDTD = SetGaussExcite(FDTD,f0,f0);
+BC = [0 0 1 1 2 2];
+FDTD = SetBoundaryCond(FDTD,BC);
+
+mesh_res = [max_mesh 2*pi*partial/N_alpha max_mesh];
+
+%setup CSXCAD geometry
+CSX = InitCSX();
+mesh.x = SmoothMeshLines([rad_i rad_a],mesh_res(1));
+mesh.y = linspace(-pi*partial,pi*partial,N_alpha);
+mesh.z = SmoothMeshLines([0 port_dist length],mesh_res(3));
+CSX = DefineRectGrid(CSX, 1e-3,mesh);
+
+start = [rad_i mesh.y(1) mesh.z(3)];
+stop = [rad_a mesh.y(end) mesh.z(3)];
+
+CSX = AddExcitation(CSX,'excite',0,[1 0 0]);
+weight{1} = '1/rho';
+weight{2} = 0;
+weight{3} = 0;
+CSX = SetExcitationWeight(CSX, 'excite', weight );
+CSX = AddBox(CSX,'excite',0 ,start,stop);
+
+
+start = [mesh.x(1) mesh.y(1) mesh.z(1)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
+CSX = AddMaterial(CSX,'material');
+CSX = SetMaterialProperty(CSX,'material','Epsilon',epsR);
+CSX = AddBox(CSX,'material',0 ,start,stop);
+
+%dump
+CSX = AddDump(CSX,'Et_rz_','DumpMode',0);
+start = [mesh.x(1) 0 mesh.z(1)];
+stop = [mesh.x(end) 0 mesh.z(end)];
+CSX = AddBox(CSX,'Et_rz_',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht_rz_','DumpType',1,'DumpMode',0);
+CSX = AddBox(CSX,'Ht_rz_',0 , start,stop);
+
+CSX = AddDump(CSX,'Et_','DumpType',0,'DumpMode',0);
+start = [mesh.x(1) mesh.y(1) length/2];
+stop = [mesh.x(end) mesh.y(end) length/2];
+CSX = AddBox(CSX,'Et_',0,start,stop);
+
+CSX = AddDump(CSX,'Ht_','DumpType',1,'DumpMode',0);
+start = [mesh.x(1) mesh.y(1) length/2];
+stop = [mesh.x(end) mesh.y(end) length/2];
+CSX = AddBox(CSX,'Ht_',0,start,stop);
+
+% voltage calc (take a voltage average to be at the same spot as the
+% current calculation)
+CSX = AddProbe(CSX,'ut1_1',0);
+start = [ rad_i 0 port_dist ];stop = [ rad_a 0 port_dist ];
+CSX = AddBox(CSX,'ut1_1', 0 ,start,stop);
+CSX = AddProbe(CSX,'ut1_2',0);
+start = [ rad_i 0 port_dist+mesh_res(3) ];stop = [ rad_a 0 port_dist+mesh_res(3) ];
+CSX = AddBox(CSX,'ut1_2', 0 ,start,stop);
+
+% current calc
+CSX = AddProbe(CSX,'it1',1);
+mid = 75;
+start = [ 0 mesh.y(1) port_dist+mesh_res(3)/2 ];stop = [ mid mesh.y(end) port_dist+mesh_res(3)/2 ];
+CSX = AddBox(CSX,'it1', 0 ,start,stop);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts, Settings)
+
+%%
+close all
+freq = linspace(0,2*f0,201);
+UI = ReadUI({'ut1_1','ut1_2','it1'},Sim_Path,freq);
+u_f = (UI.FD{1}.val + UI.FD{2}.val)/2; %averaging voltages to fit current
+i_f = UI.FD{3}.val / partial;
+
+% plot(UI.TD{1}.t,UI.TD{1}.val);
+% grid on;
+%
+% figure
+% plot(UI.TD{3}.t,UI.TD{3}.val);
+% grid on;
+
+%plot Z_L compare
+figure
+ZL = Z0/2/pi/sqrt(epsR)*log(rad_a/rad_i); %analytic line-impedance of a coax
+plot(UI.FD{1}.f,ZL*ones(size(u_f)),'g','Linewidth',3);
+hold on;
+grid on;
+Z = u_f./i_f;
+plot(UI.FD{1}.f,real(Z),'k--','Linewidth',2);
+plot(UI.FD{1}.f,imag(Z),'r-','Linewidth',2);
+xlim([0 2*f0]);
+legend('Z_L - analytic','\Re\{Z\} - FDTD','\Im\{Z\} - FDTD','Location','Best');
+
+
diff --git a/openEMS/matlab/examples/waveguide/Rect_Waveguide.m b/openEMS/matlab/examples/waveguide/Rect_Waveguide.m
new file mode 100644
index 0000000..a9601ad
--- /dev/null
+++ b/openEMS/matlab/examples/waveguide/Rect_Waveguide.m
@@ -0,0 +1,240 @@
+%
+% EXAMPLE / waveguide / Rect_Waveguide
+%
+% This example demonstrates:
+% - waveguide mode excitation
+% - waveguide mode matching
+% - pml absorbing boundaries
+%
+%
+% Tested with
+% - Matlab 2009b
+% - openEMS v0.0.17
+%
+% (C) 2010 Thorsten Liebig <thorsten.liebig@gmx.de>
+
+close all
+clear
+clc
+
+%% switches
+postproc_only = 0;
+
+%% setup the simulation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+physical_constants;
+unit = 1e-3; %drawing unit in mm
+numTS = 50000; %max. number of timesteps
+
+% waveguide dimensions
+length = 1000;
+a = 1000; %waveguide width
+b = 600; %waveguide heigth
+
+%waveguide TE-mode definition
+m = 1;
+n = 0;
+
+mesh_res = [10 10 10];
+
+%% setup FDTD parameters & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+f_start = 175e6;
+f_stop = 500e6;
+
+% dump special frequencies to vtk, use paraview (www.paraview.org) to
+% animate this dumps over phase
+vtk_dump_freq = [200e6 300e6 500e6];
+
+freq = linspace(f_start,f_stop,201);
+
+k = 2*pi*freq/c0;
+kc = sqrt((m*pi/a/unit)^2 + (n*pi/b/unit)^2);
+fc = c0*kc/2/pi; %cut-off frequency
+beta = sqrt(k.^2 - kc^2); %waveguide phase-constant
+ZL_a = k * Z0 ./ beta; %analytic waveguide impedance
+
+disp([' Cutoff frequencies for this mode and wavguide is: ' num2str(fc/1e6) ' MHz']);
+
+if (f_start<fc)
+ warning('openEMS:example','f_start is smaller than the cutoff-frequency, this may result in a long simulation... ');
+end
+
+%% mode functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% by David M. Pozar, Microwave Engineering, third edition, page 113
+func_Ex = [num2str( n/b/unit) '*cos(' num2str(m*pi/a) '*x)*sin(' num2str(n*pi/b) '*y)'];
+func_Ey = [num2str(-m/a/unit) '*sin(' num2str(m*pi/a) '*x)*cos(' num2str(n*pi/b) '*y)'];
+
+func_Hx = [num2str(m/a/unit) '*sin(' num2str(m*pi/a) '*x)*cos(' num2str(n*pi/b) '*y)'];
+func_Hy = [num2str(n/b/unit) '*cos(' num2str(m*pi/a) '*x)*sin(' num2str(n*pi/b) '*y)'];
+
+%% define and openEMS options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+openEMS_opts = '';
+% openEMS_opts = [openEMS_opts ' --disable-dumps'];
+% openEMS_opts = [openEMS_opts ' --debug-material'];
+% openEMS_opts = [openEMS_opts ' --engine=basic'];
+
+Settings = [];
+Settings.LogFile = 'openEMS.log';
+
+Sim_Path = 'tmp';
+Sim_CSX = 'rect_wg.xml';
+
+if (postproc_only==0)
+ [status, message, messageid] = rmdir(Sim_Path,'s');
+ [status, message, messageid] = mkdir(Sim_Path);
+end
+
+%% setup FDTD parameter & excitation function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FDTD = InitFDTD(numTS,1e-5,'OverSampling',6);
+FDTD = SetGaussExcite(FDTD,0.5*(f_start+f_stop),0.5*(f_stop-f_start));
+BC = [0 0 0 0 0 3];
+FDTD = SetBoundaryCond(FDTD,BC);
+
+%% setup CSXCAD geometry & mesh %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = InitCSX();
+mesh.x = SmoothMeshLines([0 a], mesh_res(1));
+mesh.y = SmoothMeshLines([0 b], mesh_res(2));
+mesh.z = SmoothMeshLines([0 length], mesh_res(3));
+CSX = DefineRectGrid(CSX, unit,mesh);
+
+%% apply the excitation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+start=[mesh.x(1) mesh.y(1) mesh.z(1) ];
+stop =[mesh.x(end) mesh.y(end) mesh.z(1) ];
+CSX = AddExcitation(CSX,'excite',0,[1 1 0]);
+weight{1} = func_Ex;
+weight{2} = func_Ey;
+weight{3} = 0;
+CSX = SetExcitationWeight(CSX,'excite',weight);
+CSX = AddBox(CSX,'excite',0 ,start,stop);
+
+%% voltage and current definitions using the mode matching probes %%%%%%%%%
+%port 1
+start = [mesh.x(1) mesh.y(1) mesh.z(15)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(15)];
+CSX = AddProbe(CSX, 'ut1', 10, 1, [], 'ModeFunction',{func_Ex,func_Ey,0});
+CSX = AddBox(CSX, 'ut1', 0 ,start,stop);
+CSX = AddProbe(CSX,'it1', 11, 1, [], 'ModeFunction',{func_Hx,func_Hy,0});
+CSX = AddBox(CSX,'it1', 0 ,start,stop);
+
+%port 2
+start = [mesh.x(1) mesh.y(1) mesh.z(end-15)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end-15)];
+CSX = AddProbe(CSX, 'ut2', 10, 1, [], 'ModeFunction',{func_Ex,func_Ey,0});
+CSX = AddBox(CSX, 'ut2', 0 ,start,stop);
+CSX = AddProbe(CSX,'it2', 11, 1, [], 'ModeFunction',{func_Hx,func_Hy,0});
+CSX = AddBox(CSX,'it2', 0 ,start,stop);
+
+port_dist = mesh.z(end-15) - mesh.z(15);
+
+%% define dump boxes... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','4,4,2');
+start = [mesh.x(1) mesh.y(1) mesh.z(1)];
+stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
+CSX = AddBox(CSX,'Et',0 , start,stop);
+
+CSX = AddDump(CSX,'Ht','DumpType',1,'FileType',1,'SubSampling','4,4,2');
+CSX = AddBox(CSX,'Ht',0,start,stop);
+
+%% Write openEMS compatoble xml-file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if (postproc_only==0)
+ WriteOpenEMS([Sim_Path '/' Sim_CSX],FDTD,CSX);
+
+ RunOpenEMS(Sim_Path, Sim_CSX, openEMS_opts, Settings)
+end
+
+%% postproc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+U = ReadUI({'ut1','ut2'},[Sim_Path '/'],freq);
+I = ReadUI({'it1','it2'},[Sim_Path '/'],freq);
+Exc = ReadUI('et',Sim_Path,freq);
+
+uf1 = U.FD{1}.val./Exc.FD{1}.val;
+uf2 = U.FD{2}.val./Exc.FD{1}.val;
+if1 = I.FD{1}.val./Exc.FD{1}.val;
+if2 = I.FD{2}.val./Exc.FD{1}.val;
+
+uf1_inc = 0.5 * ( uf1 + if1 .* ZL_a );
+if1_inc = 0.5 * ( if1 + uf1 ./ ZL_a );
+uf2_inc = 0.5 * ( uf2 + if2 .* ZL_a );
+if2_inc = 0.5 * ( if2 + uf2 ./ ZL_a );
+
+uf1_ref = uf1 - uf1_inc;
+if1_ref = if1 - if1_inc;
+uf2_ref = uf2 - uf2_inc;
+if2_ref = if2 - if2_inc;
+
+%% plot s-parameter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+figure
+s11 = uf1_ref./uf1_inc;
+s21 = uf2_inc./uf1_inc;
+plot(freq,20*log10(abs(s11)),'Linewidth',2);
+xlim([freq(1) freq(end)]);
+% ylim([-40 5]);
+grid on;
+hold on;
+plot(freq,20*log10(abs(s21)),'r','Linewidth',2);
+legend('s11','s21','Location','SouthEast');
+ylabel('s-para (dB)');
+xlabel('freq (Hz)');
+
+%% compare analytic and numerical wave-impedance %%%%%%%%%%%%%%%%%%%%%%%%%%
+ZL = uf1./if1;
+figure()
+plot(freq,real(ZL),'Linewidth',2);
+hold on;
+grid on;
+plot(freq,imag(ZL),'r--','Linewidth',2);
+plot(freq,ZL_a,'g-.','Linewidth',2);
+ylabel('ZL (\Omega)');
+xlabel('freq (Hz)');
+xlim([freq(1) freq(end)]);
+legend('\Re(Z_L)','\Im(Z_L)','Z_L analytic','Location','Best');
+
+%% beta compare
+figure()
+da = unwrap(angle(uf1_inc./uf2_inc)) ;
+% da = mod(da,2*pi);
+beta_12 = (da)/port_dist/unit;
+plot(freq,beta_12,'Linewidth',2);
+xlim([freq(1) freq(end)]);
+xlabel('frequency (Hz)');
+ylabel('\beta (m^{-1})');
+grid on;
+hold on;
+plot(freq,beta,'g--','Linewidth',2);
+legend('\beta-FDTD','\beta-analytic','Location','Best');
+
+%% Plot the field dumps %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+dump_file = [Sim_Path '/Et.h5'];
+figure()
+PlotArgs.slice = {a/2*unit b/2*unit 0};
+PlotArgs.pauseTime=0.01;
+PlotArgs.component=0;
+PlotArgs.Limit = 'auto';
+PlotHDF5FieldData(dump_file, PlotArgs)
+
+%% dump frequency to vtk %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% cleanup and create dump folder
+vtk_path = [Sim_Path '/vtk'];
+[status, message, messageid] = rmdir(vtk_path,'s');
+[status, message, messageid] = mkdir(vtk_path);
+
+disp('Dumping to vtk files... this may take a minute...')
+% define interpolation mesh
+mesh_interp{1}=mesh.x * unit;
+mesh_interp{2}=b/2 * unit;
+mesh_interp{3}=mesh.z * unit;
+[field mesh_FD] = ReadHDF5Dump(dump_file,'Interpolation',mesh_interp,'Frequency',vtk_dump_freq);
+
+% dump animated phase to vtk
+for n=1:numel(vtk_dump_freq)
+ phase = linspace(0,360,21);
+ phase = phase(1:end-1);
+ for ph = phase
+ filename = [vtk_path '/E_xz_f=' num2str(vtk_dump_freq(n)) '_p' num2str(ph) '.vtk'];
+ Dump2VTK(filename,real(field.FD.values{n}.*exp(1j*ph/180*pi)),mesh_FD,'E-Field');
+ end
+
+ filename = [vtk_path '/E_xz_f=' num2str(vtk_dump_freq(n)) '_mag.vtk'];
+ Dump2VTK(filename,abs(field.FD.values{n}),mesh_FD,'E-Field');
+end
+
+disp('done... you can open and visualize the vtk-files using Paraview (www.paraview.org)!')
diff --git a/openEMS/matlab/h5readatt_octave.cc b/openEMS/matlab/h5readatt_octave.cc
new file mode 100755
index 0000000..8bd58d0
--- /dev/null
+++ b/openEMS/matlab/h5readatt_octave.cc
@@ -0,0 +1,135 @@
+#include <octave/oct.h>
+#include <octave/ov-struct.h>
+#include "hdf5.h"
+
+// this special treatment is necessary because Win32-Octave ships with a very old hdf5 version (1.6.10)
+void CloseH5Object(hid_t obj)
+{
+#if ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR == 6))
+ // try group close, than Dataset close
+ if (H5Gclose(obj)<0)
+ H5Dclose(obj);
+#else
+ H5Oclose(obj);
+#endif
+}
+
+DEFUN_DLD (h5readatt_octave, args, nargout, "h5readatt_octave(<File_Name>,<DataSet_Name>,<Attribute_Name>)")
+{
+ octave_value retval;
+ int nargin = args.length();
+ if (nargin != 3)
+ {
+ print_usage();
+ return retval;
+ }
+ if ((args(0).is_string()==false) || (args(1).is_string()==false) || (args(2).is_string()==false))
+ {
+ print_usage();
+ return retval;
+ }
+
+ //suppress hdf5 error output
+ H5Eset_auto1(NULL, NULL);
+
+ hid_t file = H5Fopen( args(0).string_value().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT );
+ if (file==-1)
+ {
+ error("h5readatt_octave: opening the given File failed");
+ return retval;
+ }
+
+#if ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR == 6))
+ // this special treatment is necessary because Win32-Octave ships with a very old hdf5 version (1.6.10)
+ hid_t obj = -1;
+ //try opening the group
+ obj = H5Gopen(file, args(1).string_value().c_str());
+ //try opening the dataset if group failed
+ if (obj==-1)
+ obj = H5Dopen(file, args(1).string_value().c_str());
+#else
+ hid_t obj = H5Oopen(file, args(1).string_value().c_str(), H5P_DEFAULT);
+#endif
+
+ if (obj==-1)
+ {
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: opening the given Object failed");
+ return retval;
+ }
+
+ hid_t attr = H5Aopen_name(obj, args(2).string_value().c_str());
+ if (attr==-1)
+ {
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: opening the given Attribute failed");
+ return retval;
+ }
+
+ hid_t type = H5Aget_type(attr);
+ if (type<0)
+ {
+ H5Aclose(attr);
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: dataset type error");
+ return retval;
+ }
+
+ if (H5Tget_class(type)!=H5T_FLOAT)
+ {
+ H5Aclose(attr);
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: attribute type not supported");
+ return retval;
+ }
+
+ size_t numVal = H5Aget_storage_size(attr)/H5Tget_size(type);
+ double value[numVal];
+ if (H5Tget_size(type)==sizeof(float))
+ {
+ float f_value[numVal];
+ if (H5Aread(attr, H5T_NATIVE_FLOAT, f_value)<0)
+ {
+ H5Aclose(attr);
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: reading the given Attribute failed");
+ return retval;
+ }
+ for (size_t n=0;n<numVal;++n)
+ value[n] = f_value[n];
+ }
+ else if (H5Tget_size(type)==sizeof(double))
+ {
+ if (H5Aread(attr, H5T_NATIVE_DOUBLE, value)<0)
+ {
+ H5Aclose(attr);
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: reading the given Attribute failed");
+ return retval;
+ }
+ }
+ else
+ {
+ H5Aclose(attr);
+ CloseH5Object(obj);
+ H5Fclose(file);
+ error("h5readatt_octave: reading the given Attribute failed: unknown type");
+ return retval;
+ }
+
+ H5Aclose(attr);
+ CloseH5Object(obj);
+ H5Fclose(file);
+ Matrix mat(numVal,1);
+ for (size_t n=0;n<numVal;++n)
+ mat(n)=value[n];
+ retval = octave_value(mat);
+ return retval;
+}
+
diff --git a/openEMS/matlab/harminv.m b/openEMS/matlab/harminv.m
new file mode 100644
index 0000000..a5d0c77
--- /dev/null
+++ b/openEMS/matlab/harminv.m
@@ -0,0 +1,77 @@
+function [f,decay,Q,amp,phase,err]=harminv( timeseries, timestep, start_freq, stop_freq )
+% [f,decay,Q,amp,phase,err]=harminv( timeseries, timestep, start_freq, stop_freq )
+%
+% reconstruct time signal with:
+% real(amp(n) * exp(-1i*(2*pi*freq(n)*t-phase(n))-decay(n)*t)));
+%
+% example:
+% t = linspace(0,(1/0.3e9)*5,1000);
+% u = 0.8 * sin(2*pi*0.7e9 * t + 0/180*pi);
+% u = u + 0.3 * sin(2*pi*0.3e9 * t + 0/180*pi);
+% [freq,decay,Q,amp,phase,err]=harminv( u, t(2)-t(1), 0, 1e9 );
+%
+% -----------------------
+% Sebastian Held <sebastian.held@gmx.de>
+
+if isunix
+ harminv_exe = 'export LD_LIBRARY_PATH=; harminv';
+elseif ispc
+ m_filename = mfilename('fullpath');
+ dir = fileparts( m_filename );
+ harminv_exe = [ '"' dir '\..\harminv.exe"'];
+else
+ error('openEMS:harminv','unknown/unsupported operating system...');
+end
+
+options = ['-t ' num2str(timestep)];
+tmpfile = tempname;
+
+% convert to column vector
+if size(timeseries,2) > size(timeseries,1)
+ timeseries = timeseries.';
+end
+
+% harminv hangs if timeseries is zero only
+if all(timeseries == 0)
+ disp( 'timeseries is 0' );
+ return
+end
+
+% write timeseries to temporary file
+dlmwrite( tmpfile, timeseries );
+
+command = [harminv_exe ' ' options ' '...
+ num2str(start_freq) '-' num2str(stop_freq) ' < "' tmpfile '"'];
+[status,result] = system( command );
+if status ~= 0
+ disp( 'error executing harminv:' );
+ disp( command );
+ disp( ['exit status: ' num2str(status)] );
+ disp( ['output: ' result] );
+ return
+end
+
+%disp( command )
+%disp( result )
+
+f = [];
+decay = [];
+Q = [];
+amp = [];
+phase = [];
+err = [];
+
+lines = textscan( result, '%s', 'Delimiter', '\n');
+
+for n=2:numel(lines{1})
+ [C] = textscan( lines{1}{n}, '%f', 6, 'Delimiter', ',');
+ if isempty(C{1}), break; end
+ if C{1}(1) >= 0
+ f = [f C{1}(1)];
+ decay = [decay C{1}(2)];
+ Q = [Q C{1}(3)];
+ amp = [amp 2*C{1}(4)]; % neglecting negative frequencies => amplitude doubles
+ phase = [phase C{1}(5)];
+ err = [err C{1}(6)];
+ end
+end
diff --git a/openEMS/matlab/optimize.m b/openEMS/matlab/optimize.m
new file mode 100644
index 0000000..78ef497
--- /dev/null
+++ b/openEMS/matlab/optimize.m
@@ -0,0 +1,203 @@
+function [params,result] = optimize( optimdir, params, options, algorithm )
+%params = optimize( optimdir, params, options, algorithm )
+%
+% input:
+% optimdir: folder where to optimize
+% params: array of structures with parameters to optimize
+% .name char string parameter name (e.g. 'length1')
+% .value number
+% .step number discretization of .value
+% .range row vector range of .value (e.g. [1 10])
+% .active (0/1) 1=optimize this parameter
+% options: structure
+% .folder_matlabstart set the startup folder for matlab or octave
+% .simfun char string with the simulation function name
+% .octave_exe if this field is present, octave is used
+% .clean clean the optimization folder before optimization start
+% algorithm: 'asco' or 'simplex-downhill'
+%
+% output:
+% params: optimal values
+% result: optimization criterion for optimal values
+%
+% example:
+% see openEMS/matlab/examples/optimizer
+%
+% notes:
+% Create a file named 'STOP_OPTIMIZATION' in the optimdir folder to stop
+% the optimization process (or press Ctrl+C).
+%
+% (C) 2010 Sebastian Held <sebastian.held@gmx.de>
+
+error( nargchk(3,4,nargin) );
+
+% default to simplex-downhill
+if nargin < 4
+ algorithm = 'simplex-downhill';
+end
+if ~strcmp( algorithm, 'asco' )
+ algorithm = 'simplex-downhill';
+end
+
+optimdir = absolutepath( optimdir );
+if isfield(options,'clean') && (options.clean == 1)
+ [a,a,a] = rmdir( optimdir, 's' );
+end
+[a,a,a] = mkdir( optimdir );
+oldfolder = cd( optimdir );
+
+if strcmp( algorithm, 'asco' )
+ % ---------------------------------------------------------------------
+ % selected algorithm: ASCO
+ % http://asco.sourceforge.net/
+
+% if ~exist( 'asco', 'file' ) && ~exist( 'asco.exe', 'file' )
+% error 'asco was not found in PATH. Download from http://asco.sf.net/'
+% end
+
+ % create asco config file
+ fid = fopen( 'asco.cfg', 'wt' );
+ fprintf( fid, '* asco configuration file\n' );
+ fprintf( fid, '* http://asco.sourceforge.net/\n' );
+ fprintf( fid, '* \n' );
+ fprintf( fid, '* Optimization for openEMS\n\n' );
+ fprintf( fid, '#Optimization Flow#\n' );
+ fprintf( fid, 'Alter:no $do we want to do corner analysis?\n' );
+ fprintf( fid, 'MonteCarlo:no $do we want to do MonteCarlo analysis?\n' );
+ fprintf( fid, 'AlterMC cost:0.00 $point below which ALTER and/or MONTECARLO can start\n' );
+ fprintf( fid, 'ExecuteRF:no $Execute or no the RF module to add RF parasitics?\n' );
+ fprintf( fid, '#\n\n' );
+ fprintf( fid, '#DE#\n' );
+ fprintf( fid, 'choice of method:3\n' );
+ fprintf( fid, 'maximum no. of iterations:50\n' );
+ fprintf( fid, 'Output refresh cycle:2\n' );
+ fprintf( fid, 'No. of parents NP:10\n' );
+ fprintf( fid, 'Constant F:0.85\n' );
+ fprintf( fid, 'Crossing Over factor CR:1\n' );
+ fprintf( fid, 'Seed for pseudo random number generator:3\n' );
+ fprintf( fid, 'Minimum Cost Variance:1e-6\n' );
+ fprintf( fid, 'Cost objectives:10\n' );
+ fprintf( fid, 'Cost constraints:100\n' );
+ fprintf( fid, '#\n\n' );
+
+ fprintf( fid, '# Parameters #\n' );
+ for n=1:numel(params)
+ if params(n).active == 1
+ active = 'OPT';
+ else
+ active = '---';
+ end
+ value = params(n).value / params(n).step;
+ range = params(n).range / params(n).step;
+ fprintf( fid, 'description:#%s#:%i:%i:%i:LIN_INT:%s\n', params(n).name, value, range(1), range(2), active );
+ end
+ fprintf( fid, '#\n\n' );
+
+ fprintf( fid, '# Measurements #\n' );
+ fprintf( fid, 'value:---:MIN:0\n' );
+ fprintf( fid, '#\n\n' );
+ fclose(fid);
+
+ % create extract file
+ [a,a,a]=mkdir( 'extract' );
+ fid = fopen( 'extract/value', 'wt' );
+ fprintf( fid, '# Info #\n' );
+ fprintf( fid, 'Name:value\n' );
+ fprintf( fid, 'Symbol:value\n' );
+ fprintf( fid, '#\n\n' );
+ fprintf( fid, '# Commands #\n' );
+ fprintf( fid, '#\n\n' );
+ fprintf( fid, '# Post Processing #\n' );
+ fprintf( fid, 'MEASURE_VAR: #SYMBOL#: SEARCH_FOR:''value=''\n' );
+ fprintf( fid, '#\n' );
+ fclose(fid);
+
+ % create matlab parameter file
+ fid = fopen( 'asco.txt', 'wt' );
+ fprintf( fid, '%% this file is processed by asco and variables enclosed in ## are substituted\n' );
+ fprintf( fid, 'params = [];\n' );
+ for n=1:numel(params)
+ fprintf( fid, 'params.%s = #%s# * %i;\n', params(n).name, params(n).name, params(n).step );
+ end
+ fclose(fid);
+
+ % create shell script
+ folder_asco_helper = fileparts( mfilename('fullpath') );
+ asco_sim_helper = 'optimizer_asco_sim';
+ fid = fopen( 'general.sh', 'wt' );
+ fprintf( fid, '#!/bin/sh\n' );
+ fprintf( fid, 'rm "$2.out" 2> /dev/null\n' );
+ fprintf( fid, 'mv "$1.txt" "$1.m"\n' );
+ fprintf( fid, 'if [ -f STOP_OPTIMIZATION ]; then\n' );
+ fprintf( fid, ' exit\n' );
+ fprintf( fid, 'fi\n' );
+ fprintf( fid, 'oldpwd=$PWD\n' );
+ if isfield(options,'folder_matlabstart')
+ % this allows to start the new matlab process in a specific folder
+ % => startup.m is picked up here
+ fprintf( fid, 'cd "%s"\n', functions.folder_matlabstart );
+ end
+ if ~isfield(options,'octave_exe')
+ % matlab
+ fprintf( fid, '%s/bin/matlab -nodesktop -nosplash -r "cd ''%s''; %s(''%s'',''$1'',''$2.out'',''%s''); exit"\n', matlabroot, folder_asco_helper, asco_sim_helper, optimdir, options.simfun );
+ else
+ % octave
+ fprintf( fid, 'export LD_LIBRARY_PATH=\n' );
+ fprintf( fid, '%s --silent --eval "cd ''%s''; %s(''%s'',''$1'',''$2.out'',''%s'');"\n', options.octave_exe, folder_asco_helper, asco_sim_helper, optimdir, options.simfun );
+ end
+ fprintf( fid, 'cd "$oldpwd"\n' );
+ fclose(fid);
+ fileattrib( 'general.sh', '+x' ); % make it executable
+
+ % clean up old data
+ if exist( './best_result.mat', 'file' ), delete( 'best_result.mat' ); end
+ if exist( './STOP_OPTIMIZATION', 'file' ), delete( 'STOP_OPTIMIZATION' ); end
+
+ % start asco
+ [status,result] = unix( 'asco -general asco.txt', '-echo' );
+
+ % get best result
+ best = load( 'best_result.mat' );
+ best = best.best;
+ result = best.result;
+ for n=1:numel(params)
+ name = params(n).name;
+ if isfield(best.params,name)
+ params(n).value = best.params.(name);
+ end
+ end
+
+elseif strcmp( algorithm, 'simplex-downhill' )
+ % ---------------------------------------------------------------------
+ % selected algorithm: simplex-downhill
+ % Thorsten Liebig <thorsten.liebig@uni-due.de>
+
+ error( 'not implemented yet' );
+end
+
+cd( oldfolder );
+
+
+
+
+
+function folder = absolutepath( folder )
+%folder = absolutepath( folder )
+% make the path absolute
+if isunix
+ % Unix
+ if folder(1) == '/'
+ return
+ end
+ folder = fullfile( pwd, folder );
+else
+ % Windows
+ folder = strrep( folder, '\', '/' );
+ if strcmp( folder(2:3), ':/' ) || strcmp( folder(1:2), '//' ) || (folder(1) == '/')
+ return
+ end
+ if (folder(2) == ':') && (folder(3) ~= '/')
+ error( 'relative paths with drive specifier are not supported' );
+ end
+ folder = fullfile( pwd, folder );
+end
diff --git a/openEMS/matlab/optimizer_asco_sim.m b/openEMS/matlab/optimizer_asco_sim.m
new file mode 100644
index 0000000..6f62ebf
--- /dev/null
+++ b/openEMS/matlab/optimizer_asco_sim.m
@@ -0,0 +1,88 @@
+function optimizer_asco_sim( optimdir, inputfile, outputfile, simfun )
+%optimizer_asco_sim( optimdir, inputfile, outputfile, simfun )
+%
+% This function is called from general.sh. Do not call it yourself.
+%
+% tasks:
+% - set correct matlab path
+% - evaluate inputfile
+% - start simulation or get result from cache
+% - postprocess simulation results
+% - create output file (important: needs single \n at the first line and double \n at the last line!)
+
+error( nargchk(4,4,nargin) );
+
+% add CSXCAD and openEMS to the matlab path
+folder = fileparts( mfilename('fullpath') );
+addpath( folder );
+addpath( [folder '/../../CSXCAD/matlab'] );
+
+% change to optimdir
+olddir = pwd;
+cd( optimdir );
+
+% read parameters set by asco
+if ~isempty( strfind(inputfile,'-') )
+ % matlab cannot execute a file with dashes...
+ inputfile2 = strrep( inputfile,'-','_' );
+ movefile( [inputfile '.m'], [inputfile2 '.m'] );
+ run( inputfile2 );
+ movefile( [inputfile2 '.m'], [inputfile '.m'] );
+end
+% now a structure named 'params' is available
+
+% check cache
+folder = create_folder_name( params );
+if exist( ['./' folder], 'dir' ) && exist( ['./' folder '/result.mat'], 'file' )
+ % read cache
+ disp( 'CACHE HIT' );
+ result = load( [folder '/result.mat'], 'result' );
+ result = result.result;
+else
+ % start simulation in folder <folder>
+ disp( ['starting simulation function ' simfun] );
+ disp( [' simulation folder ' folder] );
+ [simfun_folder,simfun] = fileparts(simfun);
+ oldpath = path;
+ addpath( simfun_folder );
+ fhandle = str2func(simfun); % does not work for octave-3.2.4!
+ path( oldpath );
+ mkdir( folder );
+ result = fhandle(folder,params);
+ save( [folder '/result.mat'], 'result', '-mat' );
+end
+
+% write results for asco
+fid = fopen( outputfile, 'wt' );
+fprintf( fid, '\nvalue= %e\n\n', result );
+fclose( fid );
+
+% update best result
+best = [];
+best.result = result;
+best.params = params;
+if exist( [pwd '/best_result.mat'], 'file' )
+ old = load( 'best_result.mat', 'best' );
+ if old.best.result > best.result
+ save( 'best_result.mat', 'best', '-mat' );
+ end
+else
+ save( 'best_result.mat', 'best', '-mat' );
+end
+
+% restore old folder
+cd( olddir );
+
+
+
+
+
+
+
+function folder = create_folder_name( params )
+params = orderfields( params );
+folder = 'opt';
+fnames = fieldnames(params);
+for n=1:numel(fnames)
+ folder = [folder '_' fnames{n} '=' num2str(params.(fnames{n}))];
+end
diff --git a/openEMS/matlab/physical_constants.m b/openEMS/matlab/physical_constants.m
new file mode 100644
index 0000000..cbb333e
--- /dev/null
+++ b/openEMS/matlab/physical_constants.m
@@ -0,0 +1,12 @@
+%
+% physical constants
+%
+
+% Bronstein 3rd ed., 1997, pp. 945-946
+C0 = 299792458; % m/s
+c0 = C0; %constans in capital letters, c0 for legacy support
+MUE0 = 4e-7*pi; % N/A^2
+EPS0 = 1/(MUE0*C0^2); % F/m
+
+% free space wave impedance
+Z0 = sqrt(MUE0/EPS0); % Ohm
diff --git a/openEMS/matlab/plotFF3D.m b/openEMS/matlab/plotFF3D.m
new file mode 100644
index 0000000..45950c8
--- /dev/null
+++ b/openEMS/matlab/plotFF3D.m
@@ -0,0 +1,91 @@
+function h = plotFF3D(nf2ff,varargin)
+% h = plotFF3D(nf2ff,varargin)
+%
+% plot normalized 3D far field pattern
+%
+% input:
+% nf2ff: output of CalcNF2FF
+%
+% variable input:
+% 'freq_index': - use the given frequency index, see nf2ff.freq
+% - default is 1
+% 'logscale': - if set, show farfield with logarithmic scale
+% - set the dB value for point of origin
+% - values below will be clamped
+% 'normalize': - true/false, normalize linear plot
+% - default is false, log-plot is always normalized!
+%
+% example:
+% plotFF3D(nf2ff, 'freq_index', 2, 'logscale', -20)
+%
+% see examples/antennas/infDipol.m
+%
+% See also CalcNF2FF, plotFFdB, polarFF
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig, Stefan Mahr
+
+% defaults
+logscale = [];
+freq_index = 1;
+normalize = 0;
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'logscale')==1);
+ logscale = varargin{n+1};
+ elseif (strcmp(varargin{n},'freq_index')==1);
+ freq_index = varargin{n+1};
+ elseif (strcmp(varargin{n},'normalize')==1);
+ normalize = varargin{n+1};
+ else
+ warning('openEMS:plotFF3D',['unknown argument key: ''' varargin{n} '''']);
+ end
+end
+
+if ((normalize~=0) || ~isempty(logscale))
+ E_far = nf2ff.E_norm{freq_index} / max(nf2ff.E_norm{freq_index}(:));
+else
+ E_far = nf2ff.E_norm{freq_index};
+end;
+
+if ~isempty(logscale)
+ E_far = 20*log10(E_far)/-logscale + 1;
+ E_far = E_far .* ( E_far > 0 );
+ titletext = sprintf('electrical far field [dB] @ f = %e Hz',nf2ff.freq(freq_index));
+elseif (normalize==0)
+ titletext = sprintf('electrical far field [V/m] @ f = %e Hz',nf2ff.freq(freq_index));
+else
+ titletext = sprintf('normalized electrical far field @ f = %e Hz',nf2ff.freq(freq_index));
+end
+
+[theta,phi] = ndgrid(nf2ff.theta,nf2ff.phi);
+x = E_far .* sin(theta) .* cos(phi);
+y = E_far .* sin(theta) .* sin(phi);
+z = E_far .* cos(theta);
+%figure
+h = surf( x,y,z, E_far );
+set(h,'EdgeColor','none');
+axis equal
+axis off
+
+try
+ if (isOctave && (strcmp(graphics_toolkit,'gnuplot')==1))
+ warning('openEMS:plotFF3D','Colorbar doesn''t work properly with octave and gnuplot. On problems, try ''colorbar off''');
+ end
+end
+
+if ~isempty(logscale)
+ colorbar('YTick', linspace(0,max(E_far(:)),9), ...
+ 'YTickLabel',num2str(linspace(logscale, 10*log10(nf2ff.Dmax(freq_index)),9)'));
+else
+ colorbar;
+end
+
+title( titletext );
+
+if (nargout == 0)
+ clear h;
+end
+
+end
diff --git a/openEMS/matlab/plotFFdB.m b/openEMS/matlab/plotFFdB.m
new file mode 100644
index 0000000..07e96e3
--- /dev/null
+++ b/openEMS/matlab/plotFFdB.m
@@ -0,0 +1,78 @@
+function h = plotFFdB(nf2ff,varargin)
+% h = plotFFdB(nf2ff,varargin)
+%
+% plot far field pattern in dBi
+%
+% input:
+% nf2ff: output of CalcNF2FF
+%
+% variable input:
+% 'freq_index': - use the given frequency index, see nf2ff.freq
+% - default is 1
+% 'xaxis': - 'phi' (default) or 'theta'
+% 'param': - array positions of parametric plot
+% - if xaxis='phi', theta is parameter, and vice versa
+% - default is 1
+%
+% example:
+% plotFFdB(nf2ff, 'freq_index', 2, ...
+% 'xaxis', 'phi', 'param', [1 46 91])
+%
+% see examples/NF2FF/infDipol.m
+%
+% See also CalcNF2FF, plotFF3D, polarFF
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig, Stefan Mahr
+
+% defaults
+freq_index = 1;
+xaxis = 'phi';
+param = 1;
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'freq_index')==1);
+ freq_index = varargin{n+1};
+ elseif (strcmp(varargin{n},'xaxis')==1);
+ xaxis = varargin{n+1};
+ elseif (strcmp(varargin{n},'param')==1);
+ param = varargin{n+1};
+ else
+ warning('openEMS:plotFFdB',['unknown argument key: ''' varargin{n} '''']);
+ end
+end
+
+D_log = nf2ff.E_norm{freq_index} / max(nf2ff.E_norm{freq_index}(:));
+D_log = 20*log10(D_log) + 10*log10(nf2ff.Dmax(freq_index));
+
+if (strcmp(xaxis,'theta')==1);
+ xax = nf2ff.theta;
+ yax = D_log(:,param);
+ parval = nf2ff.phi(param);
+ param = 'phi';
+elseif (strcmp(xaxis,'phi')==1);
+ xax = nf2ff.phi;
+ yax = D_log(param,:);
+ parval = nf2ff.theta(param);
+ param = 'theta';
+else
+ error('openEMS:plotFFdB','unknown parameter to ''xaxis''');
+end
+
+%figure
+h = plot( xax / pi * 180 , yax );
+xlabel( sprintf('%s (deg)',xaxis ));
+ylabel( 'directivity (dBi)');
+
+createlegend = @(d)sprintf('%s = %3.1f',param,d / pi * 180);
+legendtext = arrayfun(createlegend,parval,'UniformOutput',0);
+legend( legendtext );
+title( sprintf('far field pattern @ f = %e Hz',nf2ff.freq(freq_index)) );
+grid on;
+
+if (nargout == 0)
+ clear h;
+end
+
+end
diff --git a/openEMS/matlab/polarFF.m b/openEMS/matlab/polarFF.m
new file mode 100644
index 0000000..96b97da
--- /dev/null
+++ b/openEMS/matlab/polarFF.m
@@ -0,0 +1,172 @@
+function h = polarFF(nf2ff,varargin)
+% h = polarFF(nf2ff,varargin)
+%
+% plot polar far field pattern
+%
+% input:
+% nf2ff: output of CalcNF2FF
+%
+% variable input:
+% 'freq_index': - use the given frequency index, see nf2ff.freq
+% - default is 1
+% 'xaxis': - 'phi' (default) or 'theta'
+% 'param': - array positions of parametric plot
+% - if xaxis='phi', theta is parameter, and vice versa
+% - default is 1
+% 'normalize': - true/false, normalize linear plot
+% - default is false, log-plot is always normalized!
+% 'logscale': - if set, plot logarithmic polar
+% - set the dB value for point of origin if scalar
+% - set point of origin and maximum if 2-element array
+% - values below minimum will be clamped
+% - default is -20
+% 'xtics': - set the number of tics for polar grid
+% - default is 5
+%
+% example:
+% polarFF(nf2ff, 'freq_index', 2, ...
+% 'xaxis', 'phi', 'param', [1 46 91] );
+%
+% polarFF(..., 'normalize', true );
+% polarFF(..., 'logscale', -30 );
+% polarFF(..., 'logscale', [-30 10]);
+%
+% polarFF(..., 'xtics', 10);
+%
+% see examples/antenna/infDipol.m
+%
+% See also CalcNF2FF, plotFFdB, plotFF3D
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig, Stefan Mahr
+
+% defaults
+freq_index = 1;
+xaxis = 'phi';
+param = 1;
+logscale = [];
+xtics = 5;
+normalize = 0;
+
+for n=1:2:numel(varargin)
+ if (strcmp(varargin{n},'freq_index')==1);
+ freq_index = varargin{n+1};
+ elseif (strcmp(varargin{n},'xaxis')==1);
+ xaxis = varargin{n+1};
+ elseif (strcmp(varargin{n},'param')==1);
+ param = varargin{n+1};
+ elseif (strcmp(varargin{n},'normalize')==1);
+ normalize = varargin{n+1};
+ elseif (strcmp(varargin{n},'logscale')==1);
+ logscale = varargin{n+1};
+ elseif (strcmp(varargin{n},'xtics')==1);
+ xtics = varargin{n+1};
+ else
+ warning('openEMS:polarFF',['unknown argument key: ''' varargin{n} '''']);
+ end
+end
+
+E_far_max = max(nf2ff.E_norm{freq_index}(:));
+if ~isempty(logscale)
+ gridmin = logscale(1);
+
+ Dmax = 10*log10(nf2ff.Dmax(freq_index));
+ E_far_scale = Dmax - gridmin;
+ E_far = 20*log10(nf2ff.E_norm{freq_index}) - 20*log10(E_far_max) + E_far_scale;
+ E_far = E_far .* ( E_far > 0 );
+ E_far = E_far ./ E_far_scale;
+
+ titletext = sprintf('electrical far field [dBi] @ f = %e Hz',nf2ff.freq(freq_index));
+
+ if numel(logscale) == 2 % normalize to maximum grid
+ gridmax = logscale(2);
+ E_far = E_far .* E_far_scale/(gridmax-gridmin);
+ else
+ gridmax = Dmax;
+ end
+elseif (normalize==0)
+ E_far = nf2ff.E_norm{freq_index};
+
+ titletext = sprintf('electrical far field [V/m] @ f = %e Hz',nf2ff.freq(freq_index));
+
+ gridmin = 0;
+ gridmax = E_far_max;
+else % normalize == 1
+ E_far = nf2ff.E_norm{freq_index} / E_far_max;
+
+ titletext = sprintf('normalized electrical far field @ f = %e Hz',nf2ff.freq(freq_index));
+
+ gridmin = 0;
+ gridmax = 1;
+end
+
+
+if (strcmp(xaxis,'theta')==1);
+ xax = nf2ff.theta(:);
+ yax = E_far(:,param);
+ parval = nf2ff.phi(param);
+ param = 'phi';
+elseif (strcmp(xaxis,'phi')==1);
+ xax = nf2ff.phi(:);
+ yax = E_far(param,:)';
+ parval = nf2ff.theta(param);
+ param = 'theta';
+else
+ error('openEMS:polarFF','unknown parameter to ''xaxis''');
+end
+
+if ~isempty(logscale)
+ scalegrid = 1;
+else
+ scalegrid = gridmax;
+end
+
+% workaround for polar plot
+gridcolor = [0.85 0.85 0.85];
+% plot xtics circles
+a=linspace(0,2*pi,60);
+b=linspace(0,scalegrid,xtics+1);
+b=repmat(b(2:end),numel(a),1)';
+a=repmat(a,size(b,1),1);
+[x,y] = pol2cart(a,b);
+h = plot(x',y');
+%h=polar(a,b,'-k');
+set(h,'Color',gridcolor);
+set(h(end),'Color',gridcolor*0.8);
+hold on;
+% plot degree lines
+a=bsxfun(@plus,[0:pi/6:pi-pi/6],[0 pi]');
+b=scalegrid.*ones(size(a));
+h=polar(a,b,'-k');
+set(h,'Color',gridcolor);
+set(h([1 4]),'Color',gridcolor*0.8);
+text(scalegrid*0.05,scalegrid*0.05,num2str(gridmin))
+text(scalegrid*1.05,scalegrid*0.05,num2str(gridmax))
+
+
+% draw far field
+xax = repmat(xax,1,size(yax,2));
+[x,y] = pol2cart(xax,yax);
+h = plot(x,y);
+%h = polar( xax, yax );
+
+% legend
+ylabel( sprintf('%s / deg', xaxis) );
+title( titletext );
+createlegend = @(d)sprintf('%s = %3.1f',param,d / pi * 180);
+legendtext = arrayfun(createlegend,parval,'UniformOutput',0);
+legend( h, legendtext ,'location','southeast');
+
+% workaround for polar plot
+axis equal tight
+axis ([-scalegrid scalegrid -scalegrid scalegrid]);
+axis off
+hold off
+set(gcf,'Color','white');
+
+if (nargout == 0)
+ clear h;
+end
+
+end
diff --git a/openEMS/matlab/private/ReadNF2FF.m b/openEMS/matlab/private/ReadNF2FF.m
new file mode 100644
index 0000000..55f67f9
--- /dev/null
+++ b/openEMS/matlab/private/ReadNF2FF.m
@@ -0,0 +1,82 @@
+function nf2ff = ReadNF2FF(nf2ff)
+% function nf2ff = ReadNF2FF(nf2ff)
+%
+% internal function to read calculated nf2ff data, use CalcNF2FF to read
+% existing nf2ff data
+%
+% See also: CalcNF2FF, CreateNF2FFBox
+%
+% openEMS matlab interface
+% -----------------------
+% author: Thorsten Liebig, 2012
+
+file = nf2ff.hdf5;
+
+hdf_mesh = ReadHDF5Mesh(file);
+
+nf2ff.r = double(hdf_mesh.lines{1});
+nf2ff.theta = double(hdf_mesh.lines{2});
+nf2ff.phi = double(hdf_mesh.lines{3});
+
+% read attributes
+nf2ff.freq = ReadHDF5Attribute(file,'/nf2ff','Frequency');
+nf2ff.Prad = ReadHDF5Attribute(file,'/nf2ff','Prad');
+nf2ff.Dmax = ReadHDF5Attribute(file,'/nf2ff','Dmax');
+
+try
+ nf2ff.Eps_r = ReadHDF5Attribute(file,'/nf2ff','Eps_r');
+catch
+ nf2ff.Eps_r = ones(size(nf2ff.freq));
+end
+try
+ nf2ff.Mue_r = ReadHDF5Attribute(file,'/nf2ff','Mue_r');
+catch
+ nf2ff.Mue_r = ones(size(nf2ff.freq));
+end
+
+if isOctave
+ hdf = load( '-hdf5', file );
+ for n=1:numel(nf2ff.freq)
+ nf2ff.E_theta{n} = double(hdf.nf2ff.E_theta.FD.(['f' int2str(n-1) '_real']) +1i*hdf.nf2ff.E_theta.FD.(['f' int2str(n-1) '_imag']) );
+ nf2ff.E_phi{n} = double(hdf.nf2ff.E_phi.FD.(['f' int2str(n-1) '_real']) +1i*hdf.nf2ff.E_phi.FD.(['f' int2str(n-1) '_imag']) );
+ nf2ff.E_norm{n} = double(sqrt(abs(nf2ff.E_theta{n}).^2+abs(nf2ff.E_phi{n}).^2));
+ nf2ff.P_rad{n} = double(hdf.nf2ff.P_rad.FD.(['f' int2str(n-1)]));
+ end
+else
+ % matlab compatibility to older versions
+ if verLessThan('matlab','7.12')
+ % read data
+ for n=1:numel(nf2ff.freq)
+ nf2ff.E_theta{n} = double(hdf5read(file,['/nf2ff/E_theta/FD/f' int2str(n-1) '_real']) + 1i*hdf5read(file,['/nf2ff/E_theta/FD/f' int2str(n-1) '_imag']));
+ nf2ff.E_phi{n} = double(hdf5read(file,['/nf2ff/E_phi/FD/f' int2str(n-1) '_real']) + 1i*hdf5read(file,['/nf2ff/E_phi/FD/f' int2str(n-1) '_imag']));
+ nf2ff.E_norm{n} = double(sqrt(abs(nf2ff.E_theta{n}).^2+abs(nf2ff.E_phi{n}).^2));
+ nf2ff.P_rad{n} = double(hdf5read(file,['/nf2ff/P_rad/FD/f' int2str(n-1)]));
+ end
+ else
+ % read data
+ for n=1:numel(nf2ff.freq)
+ nf2ff.E_theta{n} = double(h5read(file,['/nf2ff/E_theta/FD/f' int2str(n-1) '_real']) + 1i*h5read(file,['/nf2ff/E_theta/FD/f' int2str(n-1) '_imag']));
+ nf2ff.E_phi{n} = double(h5read(file,['/nf2ff/E_phi/FD/f' int2str(n-1) '_real']) + 1i*h5read(file,['/nf2ff/E_phi/FD/f' int2str(n-1) '_imag']));
+ nf2ff.E_norm{n} = double(sqrt(abs(nf2ff.E_theta{n}).^2+abs(nf2ff.E_phi{n}).^2));
+ nf2ff.P_rad{n} = double(h5read(file,['/nf2ff/P_rad/FD/f' int2str(n-1)]));
+ end
+ end
+end
+
+% Calculation of right- and left-handed circular polarization
+% adopted from
+% 2012, Tim Pegg <teepegg@gmail.com>
+
+% cleanup (if exist)
+nf2ff.E_cprh = [];
+nf2ff.E_cplh = [];
+
+% Setup vectors for converting to LHCP and RHCP polarization senses
+[THETHA PHI] = ndgrid(nf2ff.theta,nf2ff.phi);
+cosphi = cos(PHI);
+sinphi = sin(PHI);
+
+for f=1:numel(nf2ff.freq)
+ nf2ff.E_cprh{f} = (cosphi+1i*sinphi) .* (nf2ff.E_theta{f}+1i*nf2ff.E_phi{f})/sqrt(2);
+ nf2ff.E_cplh{f} = (cosphi-1i*sinphi) .* (nf2ff.E_theta{f}-1i*nf2ff.E_phi{f})/sqrt(2);
+end
diff --git a/openEMS/matlab/private/invoke_openEMS.m b/openEMS/matlab/private/invoke_openEMS.m
new file mode 100644
index 0000000..afb2b46
--- /dev/null
+++ b/openEMS/matlab/private/invoke_openEMS.m
@@ -0,0 +1,47 @@
+function invoke_openEMS( opts, logfile, silent )
+% function invoke_openEMS( opts, logfile, silent )
+%
+% internal method to invoke openEMS, use RunOpenEMS instead
+%
+% See also RunOpenEMS
+%
+% openEMS matlab interface
+% -----------------------
+% author: Sebastian Held, Thorsten Liebig
+
+if nargin < 1
+ error 'specify the xml file to simulate'
+end
+if nargin < 3
+ silent = 0;
+end
+if (nargin < 2) || isempty(logfile)
+ if isunix
+ logfile = '/dev/null';
+ else
+ logfile = 'nul:';
+ end
+end
+
+filename = mfilename('fullpath');
+dir = fileparts( filename );
+
+if isunix
+ openEMS_bin = searchBinary('openEMS.sh', ...
+ {[dir filesep '..' filesep '..' filesep], ... % try devel path
+ [dir filesep '..' filesep '..' filesep '..' filesep '..' filesep 'bin' filesep]}); % try (default) install path
+else % assume windows
+ openEMS_bin = searchBinary('openEMS.exe', [dir filesep '..' filesep '..' filesep]);
+end
+
+command = [openEMS_bin ' ' opts];
+
+if ~silent
+ if (isunix && nargin>1)
+ command = [command ' 2>&1 | tee ' logfile];
+ end
+else
+ command = [command ' > ' logfile ' 2>&1'];
+end
+
+system(command);
diff --git a/openEMS/matlab/queue_addProcess.m b/openEMS/matlab/queue_addProcess.m
new file mode 100644
index 0000000..73d4e14
--- /dev/null
+++ b/openEMS/matlab/queue_addProcess.m
@@ -0,0 +1,22 @@
+function [pid,filenames] = queue_addProcess( command )
+% [pid,filenames] = queue_addProcess( command )
+%
+% Sebastian Held <sebastian.held@uni-due.de>
+% 12.5.2010
+
+if ~isunix
+ error 'your OS is not supported (Unix only)'
+end
+
+if nargout > 1
+ filenames.stdout = tempname;
+ filenames.stderr = tempname;
+else
+ filenames.stdout = '/dev/null';
+ filenames.stderr = '/dev/null';
+end
+
+cmd = ['(' command ') >' filenames.stdout ' 2>' filenames.stderr ' & echo $!' ];
+[~,result] = unix( cmd );
+
+pid = str2double(result);
diff --git a/openEMS/matlab/queue_checkProcess.m b/openEMS/matlab/queue_checkProcess.m
new file mode 100644
index 0000000..878165a
--- /dev/null
+++ b/openEMS/matlab/queue_checkProcess.m
@@ -0,0 +1,25 @@
+function [alive,stdout,stderr] = queue_checkProcess( pid, filenames )
+% [alive,stdout,stderr] = queue_checkProcess( pid )
+%
+% Sebastian Held <sebastian.held@uni-due.de>
+% 12.5.2010
+
+if ~isunix
+ error 'your OS is not supported (Unix only)'
+end
+
+if nargout > 1
+ fid = fopen( filenames.stdout );
+ stdout = fread(fid, '*char')';
+ fclose(fid);
+end
+if nargout > 2
+ fid = fopen( filenames.stderr );
+ stderr = fread(fid, '*char')';
+ fclose(fid);
+end
+
+cmd = ['ps --no-headers -p' num2str(pid) ];
+[status,~] = unix( cmd );
+
+alive = (status == 0);
diff --git a/openEMS/matlab/queue_delProcess.m b/openEMS/matlab/queue_delProcess.m
new file mode 100644
index 0000000..39ab45c
--- /dev/null
+++ b/openEMS/matlab/queue_delProcess.m
@@ -0,0 +1,40 @@
+function [stdout,stderr] = queue_delProcess( pid, filenames )
+% [stdout,stderr] = queue_delProcess( pid, filenames )
+%
+% if pid == 0, do not kill a process, but clean up files
+%
+% Sebastian Held <sebastian.held@uni-due.de>
+% 12.5.2010
+
+if ~isunix
+ error 'your OS is not supported (Unix only)'
+end
+
+if pid ~= 0
+ alive = queue_checkProcess( pid );
+
+ if alive
+ unix( ['kill ' num2str(pid)] );
+ alive = queue_checkProcess( pid );
+ end
+ if alive
+ pause(1)
+ unix( ['kill ' num2str(pid)] );
+ alive = queue_checkProcess( pid );
+ end
+ if alive
+ unix( ['kill -KILL ' num2str(pid)] );
+ end
+end
+
+if nargin > 1
+ if nargout == 1
+ [~,stdout] = queue_checkProcess( pid, filenames );
+ end
+ if nargout == 2
+ [~,stdout,stderr] = queue_checkProcess( pid, filenames );
+ end
+
+ delete( filenames.stdout );
+ delete( filenames.stderr );
+end
diff --git a/openEMS/matlab/setup.m b/openEMS/matlab/setup.m
new file mode 100644
index 0000000..df56b25
--- /dev/null
+++ b/openEMS/matlab/setup.m
@@ -0,0 +1,36 @@
+function setup()
+% function setup()
+%
+% setup openEMS Matlab/octave interface
+%
+% openEMS matlab/octave interface
+% -----------------------
+% author: Thorsten Liebig (2011)
+
+disp('setting up openEMS matlab/octave interface')
+
+% cd to directory of this file and restore current path at the end
+current_path = pwd;
+dir = fileparts( mfilename('fullpath') );
+cd(dir);
+
+if isOctave()
+ disp('compiling oct files')
+ fflush(stdout)
+ if isunix
+ [res, fn] = unix('find /usr/lib -name libhdf5.so');
+ if length(fn)>0
+ [hdf5lib_dir, hdf5lib_fn] = fileparts(fn);
+ disp(["HDF5 library path found at: " hdf5lib_dir])
+ mkoctfile(["-L" hdf5lib_dir ],"-lhdf5 -DH5_USE_16_API", "h5readatt_octave.cc")
+ else
+ mkoctfile -lhdf5 -DH5_USE_16_API h5readatt_octave.cc
+ end
+ else
+ mkoctfile -lhdf5 -DH5_USE_16_API h5readatt_octave.cc
+ end
+else
+ disp('Matlab does not need this function. It is Octave only.')
+end
+
+cd(current_path);