├── README.md ├── TE_model2d.m ├── TM_run_example.m ├── blackharrispulse.m ├── fdtd1dq.m ├── finddt.m ├── finddx.m ├── gridinterp.m └── padgrid.m /README.md: -------------------------------------------------------------------------------- 1 | # FDTD-algorithm-GPR 2 | matlab code for GPR simulation in 2-D. 3 | -------------------------------------------------------------------------------- /TE_model2d.m: -------------------------------------------------------------------------------- 1 | function [gather,tout,srcx,srcz,recx,recz] = TE_model2d(ep,mu,sig,xprop,zprop,srcloc,recloc,srcpulse,t,npml,outstep,plotopt) 2 | % TE_model2d.m 3 | % 4 | % This is a 2-D, TE-mode, FDTD modeling program for crosshole GPR and vertical radar profiling. 5 | % See TE_run_example.m for an example of how to use this code. 6 | % 7 | % Features: 8 | % - convolutional PML absorbing boundaries (Roden and Gedney, 2000) 9 | % - calculations in PML boundary regions have been separated from main modeling region for speed 10 | % - second-order accurate time derivatives, fourth-order-accurate spatial derivatives (O(2,4)) 11 | % 12 | % Syntax: [gather,tout,srcx,srcz,recx,recz] = TE_model2d(ep,mu,sig,xprop,zprop,srcloc,recloc,srcpulse,t,npml,outstep,plotopt) 13 | % 14 | % where gather = output data cube (common source gathers are stacked along the third index) 15 | % tout = output time vector corresponding to first index in gather matrix (s) 16 | % srcx = vector containing actual source x locations after discretization (m) 17 | % srcz = vector containing actual source z locations after discretization (m) 18 | % recx = vector containing actual receiver x locations after discretization (m) 19 | % recz = vector containing actual receiver z locations after discretization (m) 20 | % ep,mu,sig = electrical property matrices (rows = x, columns = z; need odd # of rows and columns; 21 | % already padded for PML boundaries; ep and mu are relative to free space; sig units are S/m) 22 | % xprop,zprop = position vectors corresponding to electrical property matrices (m) 23 | % srcloc = matrix containing source locations and type (rows are [x (m), z (m), type (1=Ex,2=Ez]) 24 | % recloc = matrix containing receiver locations (format same as above) 25 | % srcpulse = source pulse vector (length must be equal to the number of iterations) 26 | % t = time vector corresponding to srcpulse (used for determining time step and number of iterations) (s) 27 | % npml = number of PML absorbing boundary cells 28 | % outstep = write a sample to the output matrix every so many iterations (default=1) 29 | % plotopt = plot Ex or Ez wavefield during simulation? 30 | % (vector = [{0=no, 1=yes}, (1=Ex, 2=Ez) {output every # of iterations}, {colorbar threshold}]) 31 | % (default = [1 2 50 0.05]) 32 | % 33 | % Notes: 34 | % - all matrices in this code need to be transposed before plotting, as the first index always refers 35 | % to the horizontal direction, and the second index to the vertical direction 36 | % - locations in space are referred to using x and z 37 | % - indices in electric and magnetic field matrices are referred to using (i,j) [i=horizontal,j=vertical] 38 | % - indices in electrical property matrices are referred to using (k,l) [k=horizontal,l=vertical] 39 | % 40 | % by James Irving 41 | % July 2005 42 | 43 | % ------------------------------------------------------------------------------------------------ 44 | % SET DEFAULTS, AND TEST A FEW THINGS TO MAKE SURE ALL THE INPUTS ARE OK 45 | % ------------------------------------------------------------------------------------------------ 46 | 47 | if nargin==10; outstep=1; plotopt=[1 2 50 0.05]; end 48 | if nargin==11; plotopt=[1 2 50 0.05]; end 49 | 50 | if size(mu)~=size(ep) | size(sig)~=size(ep); disp('ep, mu, and sig matrices must be the same size'); return; end 51 | if [length(xprop),length(zprop)]~=size(ep); disp('xprop and zprop are inconsistent with ep, mu, and sig'); return; end 52 | if mod(size(ep,1),2)~=1 | mod(size(ep,2),2)~=1; disp('ep, mu, and sig must have an odd # of rows and columns'); return; end 53 | if size(srcloc,2)~=3 | size(recloc,2)~=3; disp('srcloc and recloc matrices must have 3 columns'); return; end 54 | if max(srcloc(:,1))>max(xprop) | min(srcloc(:,1))max(zprop)... 55 | | min(srcloc(:,2))max(xprop) | min(recloc(:,1))max(zprop)... 57 | | min(recloc(:,2))=length(xprop)/2 | npml>=length(zprop)/2; disp('too many PML boundary layers for grid'); return; end 60 | if length(plotopt)~=4; disp('plotopt must be a 4 component vector'); return; end 61 | 62 | 63 | % ------------------------------------------------------------------------------------------------ 64 | % DETERMINE SOME INITIAL PARAMETERS 65 | % ------------------------------------------------------------------------------------------------ 66 | 67 | % determine true permittivity and permeability matrices from supplied relative ones 68 | ep0 = 8.8541878176e-12; % dielectric permittivity of free space 69 | mu0 = 1.2566370614e-6; % magnetic permeability of free space 70 | ep = ep*ep0; % true permittivity matrix 71 | mu = mu*mu0; % true permeability matrix 72 | 73 | % determine number of field nodes and discretization interval 74 | nx = (length(xprop)+1)/2; % maximum number of field nodes in the x-direction 75 | nz = (length(zprop)+1)/2; % maximum number of field nodes in the z-direction 76 | dx = 2*(xprop(2)-xprop(1)); % electric and magnetic field spatial discretization in x (m) 77 | dz = 2*(zprop(2)-zprop(1)); % electric and magnetic field spatial discretization in z (m) 78 | 79 | % x and z position vectors corresponding to Ex, Ez, and Hy field matrices 80 | % (these field matrices are staggered in both space and time, and thus have different coordinates) 81 | xEx = xprop(2):dx:xprop(end-1); 82 | zEx = zprop(1):dz:zprop(end); 83 | xEz = xprop(1):dx:xprop(end); 84 | zEz = zprop(2):dz:zprop(end-1); 85 | xHy = xEx; 86 | zHy = zEz; 87 | 88 | % determine source and receiver (i,j) indices in Ex or Ez field matrices, 89 | % and true coordinates of sources and receivers in numerical model (after discretization) 90 | nsrc = size(srcloc,1); % number of sources 91 | nrec = size(recloc,1); % number of receivers 92 | for s=1:nsrc; 93 | if srcloc(s,3)==1 % in the case of an Ex source... 94 | [temp,srci(s)] = min(abs(xEx-srcloc(s,1))); % source x index in Ex field matrix 95 | [temp,srcj(s)] = min(abs(zEx-srcloc(s,2))); % source z index in Ex field matrix 96 | srcx(s) = xEx(srci(s)); % true source x location 97 | srcz(s) = zEx(srcj(s)); % true source z location 98 | elseif srcloc(s,3)==2 % in the case of an Ez source... 99 | [temp,srci(s)] = min(abs(xEz-srcloc(s,1))); % source x index in Ez field matrix 100 | [temp,srcj(s)] = min(abs(zEz-srcloc(s,2))); % source z index in Ez field matrix 101 | srcx(s) = xEz(srci(s)); % true source x location 102 | srcz(s) = zEz(srcj(s)); % true source z location 103 | end 104 | end 105 | for r=1:nrec; 106 | if recloc(r,3)==1 % in the case of an Ex receiver 107 | [temp,reci(r)] = min(abs(xEx-recloc(r,1))); % receiver x index in Ex field matrix 108 | [temp,recj(r)] = min(abs(zEx-recloc(r,2))); % receiver z index in Ex field matrix 109 | recx(r) = xEx(reci(r)); % true receiver x location 110 | recz(r) = zEx(recj(r)); % true receiver z location 111 | elseif recloc(r,3)==2 % in the case of an Ez receiver 112 | [temp,reci(r)] = min(abs(xEz-recloc(r,1))); % receiver x index in Ez field matrix 113 | [temp,recj(r)] = min(abs(zEz-recloc(r,2))); % receiver z index in Ez field matrix 114 | recx(r) = xEz(reci(r)); % true receiver x location 115 | recz(r) = zEz(recj(r)); % true receiver z location 116 | end 117 | end 118 | 119 | % determine time stepping parameters from supplied time vector 120 | dt = t(2)-t(1); % temporal discretization 121 | numit = length(t); % number of iterations 122 | 123 | 124 | % ------------------------------------------------------------------------------------------------ 125 | % COMPUTE FDTD UPDATE COEFFICIENTS FOR ENTIRE SIMULATION GRID 126 | % note: these matrices are twice as large as the field component matrices 127 | % (i.e., the same size as the electrical property matrices) 128 | % ------------------------------------------------------------------------------------------------ 129 | 130 | disp('Determining update coefficients for simulation region...') 131 | 132 | % set the basic PML parameters, keeping the following in mind... 133 | % - maximum sigma_x and sigma_z vary in heterogeneous media to damp waves most effiently 134 | % - Kmax = 1 is the original PML of Berenger (1994); Kmax > 1 can be used to damp evanescent waves 135 | % - keep alpha = 0 except for highly elongated domains (see Roden and Gedney (2000)) 136 | m = 4; % PML Exponent (should be between 3 and 4) 137 | Kxmax = 5; % maximum value for PML K_x parameter (must be >=1) 138 | Kzmax = 5; % maximum value for PML K_z parameter (must be >=1) 139 | sigxmax = (m+1)./(150*pi*sqrt(ep./ep0)*dx); % maximum value for PML sigma_x parameter 140 | sigzmax = (m+1)./(150*pi*sqrt(ep./ep0)*dz); % maximum value for PML sigma_z parameter 141 | alpha = 0; % alpha parameter for PML (CFS) 142 | 143 | % indices corresponding to edges of PML regions in electrical property grids 144 | kpmlLout = 1; % x index for outside of PML region on left-hand side 145 | kpmlLin = 2*npml+2; % x index for inside of PML region on left-hand side 146 | kpmlRin = length(xprop)-(2*npml+2)+1; % x index for inside of PML region on right-hand side 147 | kpmlRout = length(xprop); % x index for outside of PML region on right-hand side 148 | lpmlTout = 1; % z index for outside of PML region at the top 149 | lpmlTin = 2*npml+2; % z index for inside of PML region at the top 150 | lpmlBin = length(zprop)-(2*npml+2)+1; % z index for inside of PML region at the bottom 151 | lpmlBout = length(zprop); % z index for outside of PML region at the bottom 152 | 153 | % determine the ratio between the distance into the PML and the PML thickness in x and z directions 154 | % done for each point in electrical property grids; non-PML regions are set to zero 155 | xdel = zeros(length(xprop),length(zprop)); % initialize x direction matrix 156 | k = kpmlLout:kpmlLin; k = k(:); % left-hand PML layer 157 | xdel(k,:) = repmat(((kpmlLin-k)./(2*npml)),1,length(zprop)); 158 | k = kpmlRin:kpmlRout; k = k(:); % right-hand PML layer 159 | xdel(k,:) = repmat(((k-kpmlRin)./(2*npml)),1,length(zprop)); 160 | zdel = zeros(length(xprop),length(zprop)); % initialize z direction matrix 161 | l = lpmlTout:lpmlTin; % top PML layer 162 | zdel(:,l) = repmat(((lpmlTin-l)./(2*npml)),length(xprop),1); 163 | l = lpmlBin:lpmlBout; % bottom PML layer 164 | zdel(:,l) = repmat(((l-lpmlBin)./(2*npml)),length(xprop),1); 165 | 166 | % determine PML parameters at each point in the simulation grid 167 | % (scaled to increase from the inside to the outside of the PML region) 168 | % (interior non-PML nodes have sigx=sigz=0, Kx=Kz=1) 169 | sigx = sigxmax.*xdel.^m; 170 | sigz = sigzmax.*zdel.^m; 171 | Kx = 1 + (Kxmax-1)*xdel.^m; 172 | Kz = 1 + (Kzmax-1)*zdel.^m; 173 | 174 | % determine FDTD update coefficients 175 | Ca = (1-dt*sig./(2*ep))./(1+dt*sig./(2*ep)); 176 | Cbx = (dt./ep)./((1+dt*sig./(2*ep))*24*dx.*Kx); 177 | Cbz = (dt./ep)./((1+dt*sig./(2*ep))*24*dz.*Kz); 178 | Cc = (dt./ep)./(1+dt*sig./(2*ep)); 179 | Dbx = (dt./(mu.*Kx*24*dx)); 180 | Dbz = (dt./(mu.*Kz*24*dz)); 181 | Dc = dt./mu; 182 | Bx = exp(-(sigx./Kx + alpha)*(dt/ep0)); 183 | Bz = exp(-(sigz./Kz + alpha)*(dt/ep0)); 184 | Ax = (sigx./(sigx.*Kx + Kx.^2*alpha + 1e-20).*(Bx-1))./(24*dx); 185 | Az = (sigz./(sigz.*Kz + Kz.^2*alpha + 1e-20).*(Bz-1))./(24*dz); 186 | 187 | % clear unnecessary PML variables as they take up lots of memory 188 | clear sigxmax sigzmax xdel zdel Kx Kz sigx sigz 189 | 190 | 191 | % ------------------------------------------------------------------------------------------------ 192 | % RUN THE FDTD SIMULATION 193 | % ------------------------------------------------------------------------------------------------ 194 | 195 | disp('Beginning FDTD simulation...') 196 | 197 | % initialize gather matrix where data will be stored 198 | gather = zeros(fix((numit-1)/outstep)+1,nrec,nsrc); 199 | 200 | % loop over number of sources 201 | for s=1:nsrc 202 | 203 | % zero all field matrices 204 | Hy = zeros(nx-1,nz-1); % Hy component of magnetic field 205 | Ex = zeros(nx-1,nz); % Ex component of electric field 206 | Ez = zeros(nx,nz-1); % Ez component of electric field 207 | Hydiffx = zeros(nx,nz-1); % difference for dHy/dx 208 | Hydiffz = zeros(nx-1,nz); % difference for dHy/dz 209 | Exdiffz = zeros(nx-1,nz-1); % difference for dEx/dz 210 | Ezdiffx = zeros(nx-1,nz-1); % difference for dEz/dx 211 | PHyx = zeros(nx-1,nz-1); % psi_Hyx (for PML) 212 | PHyz = zeros(nx-1,nz-1); % psi_Hyz (for PML) 213 | PEx = zeros(nx-1,nz); % psi_Ex (for PML) 214 | PEz = zeros(nx,nz-1); % psi_Ez (for PML) 215 | 216 | % time stepping loop 217 | for it=1:numit 218 | 219 | % update Hy component... 220 | 221 | % determine indices for entire, PML, and interior regions in Hy and property grids 222 | i = 2:nx-2; j = 2:nz-2; % indices for all components in Hy matrix to update 223 | k = 2*i; l = 2*j; % corresponding indices in property grids 224 | kp = k((k<=kpmlLin | k>=kpmlRin)); % corresponding property indices in PML region 225 | lp = l((l<=lpmlTin | l>=lpmlBin)); 226 | ki = k((k>kpmlLin & klpmlTin & l=kpmlRin)); % corresponding property indices in PML region 251 | lp = l((l<=lpmlTin | l>=lpmlBin)); 252 | ki = k((k>kpmlLin & klpmlTin & l=kpmlRin)); % corresponding property indices in PML region 274 | lp = l((l<=lpmlTin | l>=lpmlBin)); 275 | ki = k((k>kpmlLin & klpmlTin & l=T) = 0; 25 | 26 | % for the pulse, approximate the window's derivative and normalize 27 | p = window(:)'; 28 | p = [window(2:end) 0] - window(1:end); 29 | p = p./max(abs(p)); 30 | -------------------------------------------------------------------------------- /fdtd1dq.m: -------------------------------------------------------------------------------- 1 | %fdtd analysis 2 | % 3 | % 4 | %fdtd engine 5 | close all; 6 | clc; 7 | clear all; 8 | 9 | %units 10 | meters = 1; 11 | centimeters = 1e-2 * meters; 12 | millimeters = 1e-3 * meters; 13 | inches = 2.54 * centimeters; 14 | feet = 12 * inches; 15 | 16 | seconds = 1; 17 | hertz = 1/seconds; 18 | kilohertz = 1e-3 * hertz; 19 | megahertz = 1e-6 * hertz; 20 | gigahertz = 1e-9 * hertz; 21 | 22 | %constant 23 | 24 | c0 = 299792458 * meters/seconds; 25 | e0 = 8.8541878176e-12 * 1/meters; 26 | u0 = 1.2566370614e-6 * 1/meters; 27 | 28 | %open a figure window 29 | figure('Color','w'); 30 | 31 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 32 | %%%dashboard 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | 35 | 36 | %Source parameters 37 | fmax = 5.0 * gigahertz; 38 | 39 | %grid parameters 40 | 41 | nmax = 1; 42 | NLAM = 10; 43 | NBUFZ = [100,100]; 44 | 45 | 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47 | %%% COMPUTE OPTIMISED GRID 48 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 49 | 50 | %NOMINAL RESOLUTION 51 | 52 | lam0 = c0/fmax; 53 | dz = lam0/nmax/NLAM; 54 | 55 | %compute grid size 56 | 57 | Nz = sum(NBUFZ) + 3; 58 | 59 | 60 | %COMPUTE GRID AXIS 61 | za = [0: Nz-1]*dz; 62 | 63 | %dz = 0.006 * meters; 64 | %Nz = 200; 65 | %dt =1e-11*seconds; 66 | %STEPS = 1000; 67 | 68 | 69 | % BUILD DEVICE ON THE GRID 70 | 71 | 72 | % INITIALIZE MATERIALS TO FREE SPACE 73 | 74 | ER = ones(1,Nz); 75 | UR = ones(1,Nz); 76 | 77 | 78 | 79 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80 | %%compute the source 81 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 82 | 83 | %compute the time step(dt) 84 | 85 | nbc = sqrt(ER(1)*UR(1)); 86 | dt = nbc*dz/(2*c0); 87 | 88 | 89 | %compute the source parameters 90 | 91 | tau = 0.5/fmax; 92 | t0 = 5* tau; 93 | 94 | 95 | %compute number of time steps 96 | 97 | tprop = nmax*Nz*dz/c0; 98 | t = 2*t0 + 3*tprop; 99 | STEPS = ceil(t/dt); 100 | 101 | 102 | % compute the source 103 | 104 | t = [0:STEPS-1]*dt; 105 | nz_src = round(Nz/2); 106 | Esrc = exp(-((t-t0)/tau).^2); 107 | 108 | %plot(t,Esrc); 109 | %break; 110 | 111 | 112 | 113 | 114 | %COMPUTE UPDATE COEFFICIENTS 115 | 116 | mEy = (c0*dt)./ER; 117 | mHx = (c0*dt)./UR; 118 | 119 | %initialize fields 120 | 121 | Ey = zeros(1,Nz); 122 | Hx = zeros(1,Nz); 123 | 124 | 125 | %initialize boundry conditions 126 | H1=0; H2=0; H3=0; 127 | E1=0; E2=0; E3=0; 128 | 129 | 130 | 131 | 132 | 133 | % PERFORM FDTD ANALYSIS 134 | 135 | for T = 1:STEPS 136 | 137 | %UPDTATE H FROM E 138 | 139 | for nz = 1 : Nz-1 140 | 141 | Hx(nz) = Hx(nz) + mHx(nz)*( Ey(nz+1)-Ey(nz) )/dz; 142 | end 143 | Hx(Nz) = Hx(Nz) + mHx(Nz)*( E3 -Ey(Nz) )/dz 144 | 145 | 146 | %REcord H-field at the boundry 147 | 148 | H3=H2; 149 | H2=H1; 150 | H1=Hx(1); 151 | 152 | 153 | % UPDATE E FROM H 154 | 155 | Ey(1) = Ey(1) + mEy(1)* ( Hx(1) - H3 )/dz; 156 | for nz = 2: Nz 157 | Ey(nz) = Ey(nz) + mEy(nz)*( Hx(nz) - Hx(nz-1) )/dz; 158 | end 159 | 160 | %RECORD EFFIELD AT THE BOUNDRY 161 | 162 | E3=E2; 163 | E2=E1; 164 | E1=Ey(Nz); 165 | 166 | 167 | end 168 | 169 | 170 | %inject Esource 171 | 172 | Ey(nz_src) = Ey(nz_src) + Esrc(T); 173 | 174 | 175 | 176 | % SHOW status 177 | if ~mod(T,1) 178 | 179 | %show fields 180 | draw1d(ER,Ey,Hx,dz); 181 | xlim([dz,Nz*dz]); 182 | xlabel('z'); 183 | title(['field at step' num2str(T) 'of' num2str(STEPS)']); 184 | 185 | 186 | % draw graphics 187 | drawnow; 188 | end 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /finddt.m: -------------------------------------------------------------------------------- 1 | function dtmax = finddt(epmin,mumin,dx,dz); 2 | % finddt.m 3 | % 4 | % This function finds the maximum time step that can be used in the 2-D 5 | % FDTD modeling codes TM_model2d.m and TE_model2d.m, such that they remain 6 | % numerically stable. Second-order-accurate time and fourth-order-accurate 7 | % spatial derivatives are assumed (i.e., O(2,4)). 8 | % 9 | % Syntax: dtmax = finddt(epmin,mumin,dx,dz) 10 | % 11 | % where dtmax = maximum time step for FDTD to be stable 12 | % epmin = minimum relative dielectric permittivity in grid 13 | % mumin = minimum relative magnetic permeability in grid 14 | % dx = spatial discretization in x-direction (m) 15 | % dz = spatial discretization in z-direction (m) 16 | % 17 | % by James Irving 18 | % July 2005 19 | 20 | % convert relative permittivity and permeability to true values 21 | mu0 = 1.2566370614e-6; 22 | ep0 = 8.8541878176e-12; 23 | epmin = epmin*ep0; 24 | mumin = mumin*mu0; 25 | 26 | % determine maximum allowable time step for numerical stability 27 | dtmax = 6/7*sqrt(epmin*mumin/(1/dx^2 + 1/dz^2)); -------------------------------------------------------------------------------- /finddx.m: -------------------------------------------------------------------------------- 1 | function [dxmax,wlmin,fmax] = finddx(epmax,mumax,srcpulse,t,thres); 2 | % finddx.m 3 | % 4 | % This function finds the maximum spatial discretization that can be used in the 5 | % 2-D FDTD modeling codes TM_model2d.m and TE_model2d.m, such that numerical 6 | % dispersion is avoided. Second-order accurate time and fourth-order-accurate 7 | % spatial derivatives are assumed (i.e., O(2,4)). Consequently, 5 field points 8 | % per minimum wavelength are required. 9 | % 10 | % Note: The dx value obtained with this program is needed to compute the maximum 11 | % time step (dt) that can be used to avoid numerical instability. However, the 12 | % time vector and source pulse are required in this code to determine the highest 13 | % frequency component in the source pulse. For this program, make sure to use a fine 14 | % temporal discretization for the source pulse, such that no frequency components 15 | % present in the pulse are aliased. 16 | % 17 | % Syntax: [dx,wlmin,fmax] = finddx(epmax,mumax,srcpulse,t,thres) 18 | % 19 | % where dxmax = maximum spatial discretization possible (m) 20 | % wlmin = minimum wavelength in the model (m) 21 | % fmax = maximum frequency contained in source pulse (Hz) 22 | % epmax = maximum relative dielectric permittivity in grid 23 | % mumax = maximum relative magnetic permeability in grid 24 | % srcpulse = source pulse for FDTD simulation 25 | % t = associated time vector (s) 26 | % thres = threshold to determine maximum frequency in source pulse 27 | % (default = 0.02) 28 | % 29 | % by James Irving 30 | % July 2005 31 | 32 | if nargin==4; thres=0.02; end 33 | 34 | % convert relative permittivity and permeability to true values 35 | mu0 = 1.2566370614e-6; 36 | ep0 = 8.8541878176e-12; 37 | epmax = epmax*ep0; 38 | mumax = mumax*mu0; 39 | 40 | % compute amplitude spectrum of source pulse and corresponding frequency vector 41 | n = 2^nextpow2(length(srcpulse)); 42 | W = abs(fftshift(fft(srcpulse,n))); 43 | W = W./max(W); 44 | fn = 0.5/(t(2)-t(1)); 45 | df = 2.*fn/n; 46 | f = -fn:df:fn-df; 47 | W = W(n/2+1:end); 48 | f = f(n/2+1:end); 49 | 50 | % determine the maximum allowable spatial disretization 51 | % (5 grid points per minimum wavelength are needed to avoid dispersion) 52 | fmax = f(max(find(W>=thres))); 53 | wlmin = 1/(fmax*sqrt(epmax*mumax)); 54 | dxmax = wlmin/5; -------------------------------------------------------------------------------- /gridinterp.m: -------------------------------------------------------------------------------- 1 | function A2 = gridinterp(A,x,z,x2,z2,method) 2 | % gridinterp.m 3 | % 4 | % This function interpolates the electrical property matrix A (having row and column position 5 | % vectors x and z, respectively) to form the matrix A2 (having row and column position vectors 6 | % x2 and z2, respectively). The interpolation method by default is nearest neighbour ('nearest'). 7 | % Otherwise the method can be specified as 'linear', 'cubic', or 'spline'. 8 | % 9 | % Syntax: A2 = gridinterp(A,x,z,x2,z2,method) 10 | % 11 | % by James Irving 12 | % July 2005 13 | 14 | if nargin==5; method = 'nearest'; end 15 | 16 | % transpose for interpolation 17 | A = A'; 18 | 19 | % transform position vectors into matrices for interp2 20 | [x,z] = meshgrid(x,z); 21 | [x2,z2] = meshgrid(x2,z2); 22 | 23 | % perform the interpolation 24 | A2 = interp2(x,z,A,x2,z2,method); 25 | 26 | % transpose back for output 27 | A2 = A2'; 28 | -------------------------------------------------------------------------------- /padgrid.m: -------------------------------------------------------------------------------- 1 | function [A2,x2,z2] = padgrid(A,x,z,n) 2 | % padgrid.m 3 | % 4 | % This function pads the electrical property matrix A (having row and column position vectors 5 | % x and z, respectively) with n elements around each side to create the matrix A2 (having row 6 | % and column position vectors x2 and z2, respectively). The properties in the padded regions 7 | % are simply the properties of the original matrix extended outwards. 8 | % 9 | % Syntax: [A2,x2,z2] = padgrid(A,x,z,n) 10 | % 11 | % by James Irving 12 | % July 2005 13 | 14 | % determine the new position vectors 15 | dx = x(2)-x(1); 16 | dz = z(2)-z(1); 17 | x2 = (x(1)-n*dx):dx:(x(end)+n*dx+1e-10); 18 | z2 = (z(1)-n*dz):dz:(z(end)+n*dz+1e-10); 19 | 20 | % pad the grid 21 | A2 = [repmat(A(:,1),1,n), A, repmat(A(:,end),1,n)]; 22 | A2 = [repmat(A2(1,:),n,1); A2; repmat(A2(end,:),n,1)]; 23 | --------------------------------------------------------------------------------