top of page

example 1.1

ZIP with MATLAB scripts and note:

Small tag OK.jpg

 example 1.1 notes:

Small tag OK.jpg
pozar_01_example_01_question.jpg
001-1 plane wave equations.jpg
001-2 plane wave parameters table.jpg

All necessary scripts, working and ready to run are available in the Dropbox link top right corner of this page.

These notes are also available in Adobe format from the Adobe icon just below the Dropbox link.

For each example and exercise there are 2 support functions load_question.m and load_results_if_available.m that load each question that is not shown in the answer notes. One could argue what's the point to read an answer if one doesn't know the question. However why did go for the answer before reading the question I'd reply.

Some scripts consume some time in calculations so once the solution has been stored in a .mat file in same folder the support functions offer option to retrieve previously solution.

c0=299795856;   % [m/s]

etha0=120*pi;    % [ohm]

f0=5e9

 

% probably out of direct measurement, wavelength is provided

 

lambda=.03

kz=2*pi/lambda   % propagation constant

 

vp=lambda*f0        % phase velocity

 

er=(c0/vp)^2        % relative permittivity

 

etha=etha0/er^.5   % wave impedance

 

 

f0 =

     5.000000000000000e+09

 

lambda =

   0.030000000000000

 

kz =

     2.094395102393196e+02

vp =

   150000000

er =

   3.994558012212122

etha =

     1.886239140163974e+02

One could argue that while solving [POZAR] exercises and examples a hand held calculator suffices, as regretfully some Universities still put through students, not only at fresh year but at postgraduate level. In a more than ever competitive engineering jobs market, applying the right tool is more important than ever, and MATLAB offers the capacity yet relative simplicity to simulate the kind of electromagnetic problems detailed in [POZAR].

 

The point of solving [POZAR] with MATLAB is to enhance solving capabilities with MATLAB & Simulink hereon, just MATLAB.

 

In order to work with Electric and Magnetic fields efficiently, any seasoned engineer knows that either you work with spectrum analysers and tools of the kind, with real measurements and real signals, or one can go for an edged and purpose-built simulator, a wide range commercially available.

 

In any case, regarding electromagnetic simulation, pick and shovel (the hand held calculator) means one can barely cope with the amounts of data to process, or for the case, with most of the real world complex structures beyond the few simple examples that until computers were available to every one, were the only solvable problems with 'pen and paper'. The 'barely' is because there are simple solutions that cleverly exploit symmetries and particular circumstances, that may fool readers to consider that the hand held calculator is enough to work with electromagnetic simulations.

 

Make no mistake on this point, the more tools you have in your arsenal the more chances to get a good job. 

 

So when it comes to for instance drilling why limit CV skills to pick and shovel, when one can include JCB motorised shovel?

To such purpose, in between tools to work with real signals and purpose built simulators literature references [ED] and [TXEP] focus on developing functions that can be used to solve [POZAR] with MATLAB.

  

The [ED] suggested script to start 1D wave simulation is appended at the end of these notes, and also attached in .zip named Appendix_A:

modifying [ED] Appendix A script to simulate the following [TXEP] suggested 1D circuits:

In the above slide readers see 6 scenarios, yet when reaching [TXEP] 2D slide containing 2D proposed start exercises, the periodic BC case may also be relevant.

002.jpg
002-2.jpg

So, a good start simulating electromagnetic waves has to do with implementing the following 7 points:

 

1.- Basic FDTD 1D loop. [ED] supplies a starter, slow and with diffraction (1), but let's take it from here.

2.- Control source location, place source on one side.

3.- Absorbing boundaries instead of perfect reflectors.

4.- Add one way source. The general wave solution pings a pulse both ways.

         With a temporary reflector, just standing behind the source for the duration of the pulse,

         then one can 'beam' the source towards  just one boundary.

5.- Cyclic space, aka periodic BC: Folding the transmission line under test onto smaller identical

     space consecutive cells.

         Whatever pulse leaving rightwards automatically re-enters from the left side.

6.- How to calculate transmittance and reflectance when boundaries are not perfect (conductor / absorber).

7.- Add arbitrary device and measure.

 

In this example the 4 initial points are solved

Since nx is amount of cells, I have renamed number_of_time_steps to nt  .

 

When setting the space to simulate, one cannot simply double or halve for instance domain_source , or make the cavity larger or smaller without the simulation potentially suffering dispersion.

 

When attempting to change [ED] Appendix A script space and frequency parameters the output may show heavy numerical dispersion. Because the script may be too slow, the amount of time per iteration may be so large that not even the 1st bouncing may show up.

 

If one does number_of_time_steps=25000  , enough to see travelling pulses a few times backward and forward, then numerical dispersion happens, sample on right hand side:

 

This is not even half way the total number_of_time_steps and just a couple bounces.

 

One way to reduce numerical dispersion is to change dx=1e-4; dt=1e-13;I0=15 so the time dispersion parameter equals the space dispersion, read [ED] chapter 2 and [TXEP].

I0 is the pulse amplitude, that has to be modified accordingly because the display box is static, doesn´t shrink or expand to meet the signals inside.

 

So this is [ED] suggested pulse, with the signal source located right in the middle of the 1D grid, in between perfect metal reflectors.

 

Since example 1.1 is about calculating wave parameters of a 5GHz plane wave travelling through lossless dielectric medium, electric field wave with expression

E0*cos(2*pi*f0*t-beta*z)

 

then replacing the Gaussian test pulse with single tone seems reasonable.

 

To measure numerical dispersion of the algorithm we need to have a look at lambda0 and kx so using a single frequency signal makes it easier to visually spot whether a simulation suffers dispersion.

Again, with the initial script parameters dx and dt the dispersion is again excessive for a burst of single frequency pulses.

 

Excessive numerical dispersion renders simulation efforts pointless because the signal eventually falls down to same signal levels as the dispersion.

Following, MATLAB to build a single frequency burst of pulses. Overlapped in red, the Gaussian pulse.


 

003-3.jpg
003-2.jpg
003-3.jpg

source_position = .125;                      % define source

source_position_index = round(nx*source_position/domain_size)+1;

 

I0=1

 

% gauss pulse; use gaussian pulse as reference only

t0=2e-10

% t0=0

tau0=5e-10

Jz_waveform_ref = I0*exp(-((time-t0)/tau0).^2)';  

 

% test pulse: sin burst

f0=2.5e9

Np=4   %       amount of cycles, 1 cycle = 2 (sin)^2 peaks

t_window=Np*1/f0

n0=floor(t_window/dt)

nt1=[0:1:2*n0];

Jz_waveform=…

[I0*sin(2*pi*f0*nt1*dt).^2 zeros(1,nt-2*n0-1)];

 

% figure;plot(time,Jz_waveform+Jz_waveform_ref)  

% inspect test signal against reference

figure;plot(time,Jz_waveform);grid on

hold all

plot(time,Jz_waveform_ref);title('test signal + reference')

close all

003-4.jpg
A parameter missing in [ED] Appendix A script is the ratio lambda/dx  .
 
On the right hand side, showing why, from [TXEP]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Effect of dx too small:

f0=1e8

I0=.3

 

domain_size=1.25

 

dx=1e-2

dt=1e-13

nt=75000

 

n3=1  % dx=n3*dx;dt=n3*dt

n2=3   % main loop time step

 

it's supposed to be single frequency pulse bouncing on perfect reflector.

004.jpg
005.jpg

After playing a bit with different values of dx and dt as shown in following fdtd_1d_4_1.m  [ED] Appendix A simulations starts going somewhere.

Free space defined in initialize_fields_and_materials_1.m

 

[ED] shows the good practice of building different small code modules instead of writing all code in same single file.

 

I have modified [ED] start script in Appendix A, into the fddtd_1d_4_1.m . All support functions to run fdtd_1d_4_1.m are:

 

check_cell2lambda.m

check_numerical_stability.m

E_display_loop.n

init_E_display_loop.m

initialize_fdtdt_coefficients.m

initialize_fields_and_materials_1.m

initialize_plotting_parameters.m

measure_numerical_dispersion.m

plot_fields_while_solving_fdtd.m

 

I have renamed the modified [ED] plot_fields.m to plot_fields_while_solving_fdtd.m

 

This highlights the point that it's not an efficient practice to nest plot inside for loops.

 

Even more considering that at each iteration electromagnetic fields coefficients are updated, that for relatively large models, there is where the computing capacity  has to go, not to repeating command plot every time fields are updated.

% fdtd_1d_4_1_1.m

 

close all;clc;clear all

 

eps_0=8.854187817e-12;        % permittivity of free space 

mu_0=4*pi*1e-7;                     % permeability of free space   

 

c0=1/sqrt(mu_0*eps_0);                                       % light speed

etha0=120*pi

 

n4=1/2

eps_0=n4*eps_0;

mu_0=n4*mu_0;

 

%% TIME SPACE YEE FRAME

 

domain_size = 20.25;         % 1D problem space length in meters

dx = 1e-2;                                            % space resolution  

nx = round(domain_size/(dx));      % number of space cells

x=[0:dx:domain_size]

 

nt = 75000;                           % number of main loop iterations

 

dt = 1e-11;                                            % time resolution

time  = dt*[0:nt-1].';           % define time reference vector

 

% GEOMETRY

 

Ndim=1     % Ndim may take values [1 2 3] 1D 2D or 3D problem

 

n3=1

% eps_0=n3*eps_0

% mu_0=n3*mu_0

domain_size=n3*domain_size

dx=n3*dx

dt=n3*dt

 

%  BAND

 

f0=5e7;

lambda0=c0/f0

 

check_numerical_stability

 

% SIGNAL SOURCE, current

 

source_position = .1 %25;             % define source position

source_position_index = round(nx*source_position/domain_size)+1;

 

I0=50                                                             % signal amplitude

 

% gauss pulse; here used as reference only,

% test carried out with burst of single freq sin cycles

% t0=2e-10

% % t0=0

% tau0=5e-10

% % Jz_waveform_ref = I0*exp(-((time-t0)/tau0).^2)';  

% Jz_waveform_ref = I0*exp(-((time-t0)/tau0))';  

 

% test pulse: sin^2 burst

 

Np=1;              % amount of cycles, 1 cycle = 2 (sin)^2 peaks

t_window=Np*1/f0;

n0=floor(t_window/dt);

nt1=[0:1:n0];

Jz_waveform=[I0*sin(2*pi*f0*nt1*dt).^2 zeros(1,nt-n0-1)];

 

% figure;plot(time,Jz_waveform);grid on                 % check pulse

% hold all

% plot(time,Jz_waveform_ref);title('test signal + reference')

% % close all

 

measure_numerical_dispersion

check_cell2lambda                           % Nlambda>10 at least

 

%% INIT CALCULATION LOOP

 

initialize_fields_and_materials_1  % free space

initialize_fdtd_coefficients

initialize_plotting_parameters;              

 

Hy_sim=zeros([nt size(Hy)]);

Ez_sim=zeros([nt size(Ez)]);

 

%% CALCULATION LOOP : calculate simulation

tic

n2=1                                                 % just for test purposes

for kt=1:n2:nt                 % FDTD loop,  kt: previous time_step  

 

        Jz(source_position_index) = Jz_waveform(kt);                        

        Hy(1:nx) =...  Chyh(1:nx).*Hy(1:nx)+Chyez(1:nx).*(Ez(2:nx+1)-...

Ez(1:nx))+Chym(1:nx).*My(1:nx);          

        Ez(2:nx) =...

 Ceze(2:nx).*Ez(2:nx)+Cezhy(2:nx).*(Hy(2:nx)-...

Hy(1:nx-1))+Cezj(2:nx).*Jz(2:nx);          

   

        Hy_sim(kt,:)=Hy;  % recording field values

        Ez_sim(kt,:)=Ez;

       

        if kt<=n0

            Ez(source_position_index-1)=0;                              

        end

   

        Ez(1) = 0;              % Apply PEC boundary condition at x = 0 m

        Ez(nx+1) = 0;    % Apply PEC boundary condition at x = domain_size

 

        plot_fields_while_solving_fdtd;                         

end

toc

 

%% INIT E DISPLAY LOOP

 

init_E_display_loop

 

%% INIT H DISPLAY LOOP

 

%% E DISPLAY LOOP

 

E_display_loop

 

%% H DISPLAY LOOP

006-1.jpg
006-2.jpg

% initialize_fields_and_materials_1.m

% support function for fdtd_1d_4_1.m

 

% free space

 

Ceze      = zeros(nx+1,1);

Cezhy     = zeros(nx+1,1);

Cezj      = zeros(nx+1,1);

Ez        = zeros(nx+1,1);

Jz        = zeros(nx+1,1);

eps_r_z   = ones(nx+1,1);                                                                % free space

sigma_e_z = zeros(nx+1,1);                                                             % free space

% sigma_e_z = 4.4e-4*ones(nx+1,1);                                            % Silicon

% sigma_e_z = 2e-4*ones(nx+1,1);                                               % distilled water

% sigma_e_z = 4*ones(nx+1,1);                                                     % sea water

 

% sigma_e_z=5.823e7  % Cu

% sigma_e_z=6.173e7  % Ag

% sigma_e_z=5   % sea water

% sigma_e_z=9.52e7 % Pt

 

Chyh      = zeros(nx,1);

Chyez     = zeros(nx,1);

Chym      = zeros(nx,1);

Hy        = zeros(nx,1);

My        = zeros(nx,1);

mu_r_y    = ones (nx,1);                                                                    % free space

sigma_m_y = zeros(nx,1);                                                                % free space

I also tried scaling permittivity and permeability in [ED] Appendix A script but there was no reduction in processing time.

n41=.5                                                          % eps_0 scaling

n42=.5                                                          % mu_0 scaling

 

domain_size=1.25

dx=1e-4

nx=domain_size/dx

 

nt=7500000

dt=1e-13

 

n3=1                                                            

domain_size scaling

f0=5e7

 

I0 =1200                                                      % signal amplitude

 

n2=50                                                           % main loop time step

Yee stable

time dispersion

space dispersion

Nlambda   % not too large but >10

Also tried mu_0=1 and eps_0= eps_0/mu_0 to use [ED] Appendix A script directly but far worse; the wave doesn't start yet MATLAB busy.

So why the limited performance of [ED] Appendix A script? why cannot one just change key parameters like size and simulate at any frequency? or  combine multiple frequencies? with different materials?

 

It turned out that the bulk of the delay is caused by the plot function inside main for loop:

 

Applying tic toc with nt=7.5e6 and plot_fields.m suppressed, then it only takes 41 seconds to generate all data.

When attempting to store all simulated values the required size of the variables where storing simulated fields may exceed MATLAB default matrix roof size:

Hy_sim=zeros([size(Hy) nt]);

Ez_sim=zeros([size(Ez) nt]);

 

..

 

for kt=1:n2:nt

 

..

 

  Hy_sim(:,kt)=Hy;

  Ez_sim(:,kt)=Ez;

 

..

 

end

Error using zeros

Requested 12500x1x7500000 (698.5GB) array exceeds maximum array

size preference. Creation of arrays greater than this limit may

take a long time and cause MATLAB to become unresponsive. See

array size limit or preference panel for more information.

n2 only for test purposes. One cannot use n2 too high or the shape of the test signal is lost. Also, n2>1 in the time loop compresses the signal in space. The signal is still going to bounce back wherever a reflector is found, but then reducing domain_size may be the only way to get the signal getting to any boundary, for the same nt.

 

I found it useful to collect main parameters in Excel spread sheet fdtd_budget.xls and shift values up and down before applying them in the script:

fdtd_budget_screenshot.jpg

Splitting simulation and display calculations

One loop for simulation calculations, and the other one to display values, fdtd_1d_4_1_2.m

 

This approach allows to simulate fields with wait time a fraction only of that required to run [ED] Appendix A script. The pace of the simulation display can also be changed without having to recalculate every single time. On the right hand side the start pulse that correctly bounces on both side boundary perfect conductors.

007.jpg

At the cost of a few more data storage bytes, I have copied all necessary files to run fdtd_1d_4_2.m into a separate folder. This is another point that perhaps [ED] should consider in next edition, because while the abundance of working scripts helps read and understand a text, having to guess what files to reuse from previous chapters doesn't help.

 

Additional functions:

 

init_E_display_loop.m

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E_display_loop.m

                                           n20=5  % simulation display rate

                                           for kt=1:n20:nt/10

                                                Ez_disp=Ez_sim(kt,:);

                                                hp1=plot(hf2.CurrentAxes,Ez_disp); grid on;grid minor;

   

                                               axis(hf2.CurrentAxes,[0 nx+1 -1.1*Ez_peak 1.1*Ez_peak]);

                                               hf2.CurrentAxes.XTickLabel=cell_x_ruler;

   

                                               % the following 4 lines require n2 from 5 to 55 for similar signal rate

                                               % lg1=legend(hf2.CurrentAxes,'Ez','Location','northeastoutside')

                                               % title(lg1,['f0 = ' num2str(f0) ' Hz'])

                                               % text(hf2.CurrentAxes,2100,.01,['simulation loop: kt = ' num2str(kt) ])

                                               % text(hf2.CurrentAxes,2100,.008,['simulation time: t = ' num2str(kt*dt) ])

  

                                               if kt>1

                                                    E_frame(floor(kt/n20))=getframe; % ignore 1st frame

                                               end

                                               drawnow

                                          end

% support function for fdtd_4_1.m

Ez_peak=abs(max(max(Ez_sim)))                           % display very 1st trace
Ez_disp=Ez_sim(2000,:);
hf2=figure(2);
hf2.Name='Ez';


plot(Ez_disp);grid on;grid minor; title(hf2.CurrentAxes,'simulated Ez');
axis(hf2.CurrentAxes,[0 nx+1 -1.1*Ez_peak 1.1*Ez_peak]);

% replace display reference vector numerals with actual physical distance
dXTick=domain_size/numel(hf2.CurrentAxes.XTickLabel);   % capture XTick
x_ruler=[0:dXTick:domain_size]';
 

cell_x_ruler=mat2cell(num2str(x_ruler),ones(1,size(num2str(x_ruler),1)),size(num2str(x_ruler),2));

 

for sk3=1:1:numel(cell_x_ruler)                        % limit XTickLabel to just 2 decimals
     L1=cell_x_ruler{sk3};                                       
     L1(L1==' ')=[];                                                 
% remove ' ' from XTickLabel
     loc_dot=find(L1=='.');                                    % take 2 decimals only
     if ~isempty(loc_dot)
        dloc_dot=length(L1)-loc_dot
        switch dloc_dot
            case dloc_dot<2
                L1=L1([1:find(L1=='.')+length(L1)-loc_dot]);
            case dloc_dot>=2  
                L1=L1([1:find(L1=='.')+2]);
            otherwise  
        end
     end

   cell_x_ruler{sk3}=L1;
end


hf2.CurrentAxes.XTickLabel=cell_x_ruler;
title(hf2.CurrentAxes,'simulated Ez')

 

Propagation through lossy materials:

In fdtd_1d_4_3.m as requested in one of [ED] exercises, a lossy material simulation is implemented

 

In initialize_fields_and_materials.m instead of using ideal material, use real conductivities.

 

sima_e_z=zeros(nx+1,1)  has been replaced with for instance, Silicon conductivity:

 

sigma_e_z = 4.4e-4*ones(nx+1,1)

 

the pulse correctly shifts forward only (rightwards) and bounces back correctly on both sides until simulation time steps exhausted.

008.jpg

Saving and retrieving simulated E H

The main purpose of including fields simulation in the very 1st example of [POZAR] solved with MATLAB is to build tools needed when simulating electromagnetic fields. While some electromagnetic modelling may require dedicated processing capacity (for instance a GPU), [ED] may be a basic start point may be function save_load_fields.m appended at the end of this note.

 

Why recalculate it all every time? here I briefly attempted adding storage support function for calculated fields, including clause to choose whether use stored fields, if in same folder, or just recalculate.

 

With

dx =   0.010000000000000

dt =    9.999999999999999e-12

f0 =    50000000

nt =    75000

nx =   2025

 

then

 

nt*nx

 

 

 

 

 

 

 

 

 

=

   151875000

Yet stored field in file size, for different parameters used, for just Ez_sim that exceeds 2GB.

 

I also checked whether getframe would somehow save disk space for same simulated field size.

command movie can be used to reproduce simulation directly from workspace, with movie(E_frame)

save E_frame.mat E_frame

 

save('E_frame.mat','E_frame')

 

to load  stored field

 

filename=E_frame.mat

load(filename)

 

or

 

load('E_frame.mat')

However, it's a back-to-square-one effort: using getframe and movie doesn't save file size. There is no data compression because E_frame.mat and E_sim_field.mat have same size.

 

Saving 1st derivative dE/dt, instead of E halves the size of the .mat file, but given the large amount of zeros, there has to be a far more efficient way to save simulated fields data.

 

Edot_sim=diff(Ez_sim);

save Edot_sim.mat 'Edot_sim'

 

 

 

 

 

Also tried the following

zip('Edot_sim.zip','Edot_sim.mat')

 

tic;tar('Edot_sim.tar','Edot_sim.mat');toc

 

dir('E*field*')

 

L3=dir('E*field*')

 

 

 

 

 

 

 

 

L3.bytes

Elapsed time is 61.876906 seconds.

 

E_01_01_field.mat  E_01_01_field.tar 

 

L3 =

  2×1 struct array with fields:

    name

    folder

    date

    bytes

    isdir

    datenum

 

=

     1.112588546000000e+09

=

     1.112596480000000e+09

.mat to .zip or .tar compressed files all have same size.

 

I used save_load_fields.m right after the simulation loop:

n1_save='1';    % E field descriptors

n2_save='1';  

str_save_e=['Ez_' n1_save n2_save]

[str150_vars_file,num123,rload]=save_load_fields(Ez_sim,'Ez_sim',n1_save,n2_save,1)

 

n3_save='1';    % H field descriptors

n4_save='1';  

str_save_e=['Hy_' n3_save n4_save]

[str150_vars_file,num123,rload]=save_load_fields(Ez_sim,'Hy_sim',n1_save,n2_save,1)

Efficiently compressing fields data is one of the many benchmarks of commercial electromagnetic simulators. No further time will be spent on this point.

Absorbing materials on boundaries

[POZAR] example 1.1 supplies lambda equal 3cm. Such measurement is carried out measuring consecutive field peaks. To measure consecutive peaks it's cheaper to use a stationary wave. Resonators hold propagating waves stationary within it's cavity. Another convenient way is to suppress return waves.

 

So suppress electromagnetic waves, there are commercial products readily available.

 

example real absorbing materials http://www.masttechnologies.com/rf-absorbers/

 

 

 

example different absorbers frequency response

 

https://leadertechinc.com/blog/different-types-rf-absorbers/

[ED] chapter 7 develops a support function for 2D perfectly matched layer. 3D PML matching conditions:

009-1.jpg
009-2.jpg
010-1.jpg

I tried the following to simulate the so called Perfect Matched Layer PML

 

Ez(nx+1)=-Ez(nx)

 

Doesn't work, just shifting electric field phase 180° does not behave as PML, it's just another way to implement a reflector.

[ED] chapter 7 2D implementation of a perfect PML layer requires PML layers to have certain thickness

010-2.jpg

However, a magnetic wall, although not exactly a PML, it approaches the equivalent wave impedance to that of free space, as if the boundary layer were RF 'transparent'.  To such purpose, replace

Ez(1) = 0;Ez(nx+1) = 0;                                           % perfect reflectors at x=0 m and x=domain_size

with

Ez(nx+1) = -Ez(nx);  

 Hy(1) = 0;

 Hy(nx+1) = 0;      

also the following has been added in initialize_fields_and_materials.m

Ez(nx+1)=Cezxe_border1*Ez(nx)+Cezxby_border1*(Hz(nx+1)-Hz(nx))

 

Cezxe_border1=1             

Cezxby_border1=dt/(eps_0*dx)

When using initialize_fields_and_materials_1.m lossless material, with a hold all right before calling E_display_loop.m the following s obtained:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

With initialize_fields_and_materials_4.m lossy material,

 

Appreciate that the green line showing the return is far lower than when

011-1.jpg
011-2.jpg

If just 'some' absorption is ok, 'some' as in how many dB do you need, then an approximation of matched layer for 1D absorber would be a magnetic wall:

 

This is not a thick PML, just an approximation of PML code solution provide in [ED] chapter 7, but sometimes combining a thin absorber with lossy material may be ok.

Measuring lambda and er

 

Now use fdtd_1d_4_5.m and support functions in same folder.

 

There's no need for absorber, or even to cut the transmission line at a specific length. Not even to know the exact value of the load, but the closer to a short the better to get as much  return as possible.

 

However, a far longer train of pulses is needed, otherwise only 2 peaks would show up when near reflection, and let's apply example 1.1 parameters.

In fdtd_1d_4_5.m the following FDTD parameters matching example 1.1 question are applied

 

domain_size = .25;                                            

dx = 1e-3;

nt = 175000;                                                          

dt = 1e-13;

f0=5e9;

source_position = .01

I0=1

Np=5

 

obtaining the simulation on the right hand side:

 

 

 

 

One can now manually measure lambda

(176-145)*dx

011-3.jpg
011-4.jpg

=

   0.031000000000000

Or directly processing the simulation

mean_Ez_sim=mean(Ez_sim,1);

 

figure;plot(x,mean_Ez_sim);grid on

xlabel('x');ylabel('Ez sim')

 

% solve odd samples around source

nsource_position=find(x==source_position)

mean_Ez_sim([nsource_position-1 nsource_position nsource_position+1])=0

 

% fold signal to include negative peaks

mean_Ez_sim=abs(mean_Ez_sim)

 

figure;plot(x,mean_Ez_sim);grid on

xlabel('x');ylabel('|Ez sim|')

title('stationary wave to measure \lambda')

 

[row,col,v]=findpeaks(mean_Ez_sim)

 

x_peaks=x(col)

 

 

hold all;plot(x(col),mean_Ez_sim(col),'ro')

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

% ignore peaks behind source position

x_peaks(x_peaks<source_position+.001)=[]

 

% now x_peaks samples behind or on source removed

x_peaks

lambda_measure2=mean(diff(x_peaks))

012-1.jpg

x_peaks =

     0.008   0.016   0.045   0.075  0.107   0.143   0.175   0.206  0.235

012-2.jpg

x_peaks =     0.016   0.045   0.075  0.107   0.143   0.175   0.206  0.235

 

lambda_measure2 =   0.031285714285714

Once lambda has been measured, then it's time to plug the initial lines calculate wave constant kz propagation velocity vp and relative permittivity er

When producing enough pulses against any load other than PML or a matched load, if watching long enough, then wave peaks are observable, similarly to [POZAR] example 2.4 supplied measurement

013.jpg

Appendices to Pozar example 1.1 Notes

 

                                 

save_load_fields.m

function [str150_vars_file,num123,rload]=save_load_fields(A,str_field_name,n1,n2,field_type)

%

% FILE NAME: load_results_if_available.m

%

% DESCRIPTION: Support function for fdtd_4_1_3.m

%

%

%

% MATLAB script author: John Bofarull.

% jgb2012@sky.com jgb2014@live.co.uk

 

num123(1)=n1;

num123(2)=n2;

num123(3)=field_type;

 

if n1<10 L_chap_n=[ '0' num2str(n1)]; end % generate .mat file name

if n1>=10 L_chap_n=num2str(n1); end

if n2<10 L_ex_n=[ '0' num2str(n2)]; end

if n2>=10 L_ex_n=num2str(n2); end

if field_type==1                                                                           % ex_type=1 then Electric field

    str150_vars_file=['E_' L_chap_n  '_' L_ex_n '_field.mat']

    str_field_type='E'

end

if field_type==0                                                                           % ex_type=0 then Magnetic field

    str150_vars_file=['H_' L_chap_n  '_' L_ex_n '_field.mat']

    str_field_type='H'

end

 

rload=0 % 0: no results stored or script told to recalculate regardless of possibly available results.

            % 1: results available, may reload and avoid recalculate.

 

Ldir=ls('*.mat');                                                     % assume already in right directory: get list .mat files within same directory.

s=0                                                                      % s: amount .mat files with file name matching str150_var_file

                                                                           % OS should have policy of unique file names in same folder active

k1=1

if size(Ldir,1)>0                                                      % Ldir not empty

  while s==0 && k1<=size(Ldir,1)

    Ldir1=Ldir(k1,:);

    if strcmp(str150_vars_file,Ldir1)                            % remove trailing heading possible blank characters in name.

        s=1;

        rload=1;

        k1=k1+1;

    else

        s=0;

        rload=0;

        k1=k1+1;

    end

  end

end

 

if s==0                                                                  % Ldir empty = list doesn't contain str150_vars_file, results not available.

   

    disp(['No previous ' str150_vars_file ' stored in folder, saving ' str_field_type ' field in .mat file.'])

   

    L2=['save ' str150_vars_file ' ' str_field_name]

    evalin('base',L2)

   

    save(str150_vars_file,A)

   

    rload=1;

   

   

    return

end

 

prompt='Results already stored. Do you want to recalculate? Y/N [Y]: ';   % list contains str150_vars_file, results available.

str150_input=input(prompt,'s');

if isempty(str150_input) || str150_input=='y' || str150_input=='Y'

    rload=1;

   

   return                                                                % recalculating

  

end

 

if str150_input=='n' || str150_input=='N'

  rload=0;

  hw=whos;

  Lvars={}

  for k2=1:1:size(hw,1)                                           % list with all .mat file names

     if ~isequal(hw(k2).name,'str150_vars_file')

          Lvars=[Lvars hw(k2).name];

     end

 end

 

  disp('Loading Results ...');

 

  str151=['load ' str150_vars_file];                           

  evalin('base',str151)      

 

  pause(2)

  disp('Stored results loaded.')                                  % exit to avoid recalculating just loaded results

 

  rload=0

  num123(1)=n1;

  num123(2)=n2;

  num123(3)=field_type;

 

end

 

end

[ED] original Appendix A 1D, wave moves way too slow when slightly varying simulation parameters.

 

fdtd_solve.m

% This program demonstrates a one-dimensional FDTD simulation.

% The problem geometry is composed of two PEC plates extending to

% infinity in y, and z dimensions, parallel to each other with 1 meter

% separation. The space between the PEC plates is filled with air.

% A sheet of current source paralle to the PEC plates is placed

% at the center of the problem space. The current source excites fields

% in the problem space due to a z-directed current density Jz,

% which has a Gaussian waveform in time.

 

% Define initial constants

 

eps_0 = 8.854187817e-12;          % permittivity of free space 

mu_0  = 4*pi*1e-7;                % permeability of free space   

c     = 1/sqrt(mu_0*eps_0);       % speed of light

 

% Define problem geometry and parameters

domain_size = 1;                  % 1D problem space length in meters

dx = 1e-3;                        % cell size in meters  

dt = 3e-12;                       % duration of time step in seconds 

number_of_time_steps = 2000;      % number of iterations

nx = round(domain_size/dx);       % number of cells in 1D problem space

source_position = 0.5;            % position of the current source Jz

 

% Initialize field and material arrays

Ceze      = zeros(nx+1,1);

Cezhy    = zeros(nx+1,1);

Cezj      = zeros(nx+1,1);

Ez        = zeros(nx+1,1);

Jz        = zeros(nx+1,1);

eps_r_z   = ones (nx+1,1); % free space

sigma_e_z = zeros(nx+1,1); % free space

 

Chyh      = zeros(nx,1);

Chyez     = zeros(nx,1);

Chym      = zeros(nx,1);

Hy        = zeros(nx,1);

My        = zeros(nx,1);

mu_r_y    = ones (nx,1); % free space

sigma_m_y = zeros(nx,1); % free space

 

% Calculate FDTD updating coefficients

Ceze = (2 * eps_r_z * eps_0 - dt * sigma_e_z) ...

     ./(2 * eps_r_z * eps_0 + dt * sigma_e_z);

 

Cezhy = (2 * dt / dx) ...

     ./(2 * eps_r_z * eps_0 + dt * sigma_e_z);

 

Cezj  = (-2 * dt) ...

     ./(2 * eps_r_z * eps_0 + dt * sigma_e_z);

 

Chyh  = (2 * mu_r_y * mu_0 - dt * sigma_m_y) ...

     ./(2 * mu_r_y * mu_0 + dt * sigma_m_y);

 

Chyez = (2 * dt / dx) ...

     ./(2 * mu_r_y * mu_0 + dt * sigma_m_y);

 

Chym  = (-2 * dt) ...

     ./(2 * mu_r_y * mu_0 + dt * sigma_m_y);

 

% Define the Gaussian source waveform

time       = dt*[0:number_of_time_steps-1].';

Jz_waveform = exp(-((time-2e-10)/5e-11).^2);

source_position_index = round(nx*source_position/domain_size)+1;

 

% Subroutine to initialize plotting

initialize_plotting_parameters;

 

% FDTD loop

for time_step = 1:number_of_time_steps

 

    % Update Jz for the current time step

    Jz(source_position_index) = Jz_waveform(time_step);

   

    % Update magnetic field

    Hy(1:nx) =   Chyh(1:nx) .* Hy(1:nx) ...

         + Chyez(1:nx) .* (Ez(2:nx+1) - Ez(1:nx))  ...

         + Chym(1:nx) .* My(1:nx);

 

    % Update electric field

    Ez(2:nx) = Ceze (2:nx) .*  Ez(2:nx) ...

             + Cezhy(2:nx) .* (Hy(2:nx) - Hy(1:nx-1))  ...

             + Cezj(2:nx)  .*  Jz(2:nx);

 

    Ez(1)    = 0; % Apply PEC boundary condition at x = 0 m

    Ez(nx+1) = 0; % Apply PEC boundary condition at x = 1 m

 

    % Subroutine to plot the current state of the fields

    plot_fields;

end

 

initialize_plotting_parameters.m

 

% subroutine used to initialize 1D plot

 Ez_positions = [0:nx]*dx;

Hy_positions = ([0:nx-1]+0.5)*dx;

v = [0 -0.1 -0.1; 0 -0.1 0.1; 0 0.1 0.1; 0 0.1 -0.1; ...

     1 -0.1 -0.1; 1 -0.1 0.1; 1 0.1 0.1; 1 0.1 -0.1];

f = [1 2 3 4; 5 6 7 8];

axis([0 1 -0.2 0.2 -0.2 0.2]);

lez = line(Ez_positions,Ez*0,Ez,'Color','b','LineWidth',1.5);

lhy = line(Hy_positions,377*Hy,Hy*0,'Color','r', ...

    'LineWidth',1.5,'linestyle','-.');

set(gca,'fontsize',12,'FontWeight','bold');

axis square;

legend('E_{z}', 'H_{y} \times 377','Location','NorthEast');

xlabel('x [m]');

ylabel('[A/m]');

zlabel('[V/m]');

grid on;

p = patch('vertices', v, 'faces', f, 'facecolor', 'g', 'facealpha',0.2);

text(0,1,1.1,'PEC','horizontalalignment','center','fontweight','bold');

text(1,1,1.1,'PEC','horizontalalignment','center','fontweight','bold');

 

 

plot_fields.m

 

% subroutine used to plot 1D transient fields

delete(lez);

delete(lhy);

lez = line(Ez_positions,Ez*0,Ez,'Color','b','LineWidth',1.5);

lhy = line(Hy_positions,377*Hy,Hy*0,'Color','r', ...

    'LineWidth',1.5,'linestyle','-.');

ts = num2str(time_step);

ti = num2str(dt*time_step*1e9);

title(['time step = ' ts ', time = ' ti ' ns']);

drawnow;

bottom of page