Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Abstract

284 visualizaciones

Publicado el

Publicado en: Educación
  • Inicia sesión para ver los comentarios

  • Sé el primero en recomendar esto

Abstract

  1. 1. Differential Reduction to the Pole of Iran aeromagnetic anomalies Master's Thesis Vahid Ghobadian Supervisors: Dr.Abdoreza Ghods Dr.Mahnaz Rezaeian September 2012 1
  2. 2. Abstract In this work, The aeromagnetic map of Iran wich reprocessed by Saleh (2008), performed by Arkani Hamed (1988)method called differential reduction to the pole(DRTP). The variations in direction are treated as perturbations about mean directions and the problem is solved iteratively.The DRTP operator used the Taylor series expansion approach in the frequency domain provided a uniformly leveled aeromagnetic map of Iran. DRTP reduces magnetic anomalies to the pole more effectively than the space-domain algorithm. It takes the anomaly, as measured at any latitude, and transforms it into which would have been measured if the body had been laid at the magnetic pole i.e. the area where the field inclination is vertical and the anomalies from symmetrical bodies are symmetrical. The technique is applied to the magnetic anomalies of three semiintinite dipoles, which arc inductively magnetized and locatcd at high, mid, and low latitudes in a region where the inclination of the ambient field changes from 25 to 42 degrees. We also apply the technique to the aeromagnetic anomalies of Iran. The revised DRTP map of Iran, where the inclination varies from 37° to 42°, is the most important output of this work. This aeromagnetic anomaly map of Iran clearly delineate distinctive anomaly pattern for Zagros and Alborz fold and thrust belts, Sanandaj-Sirjan metamorphic and Uromiyeh-Dokhtar volcanic zones, Lut block, Makran accretionary prism and Daruneh fault. Using the new DRTP map, a good correlation between geological structures and magnetic anomaly has been verified. For example after the algorithm reduced magnetic anomalies to the north, magnetic anomaly map boundaries delineate Sabalan and Damavand volcanic zones and Jazmurian district. 2
  3. 3. Appendix 1 - Matlab programs used for Standard RTP calculations % *********************************************************** % Tested using Matlab 7.6 Release 2008b under Windows XP % *********************************************************** % AUTHOR % Vahid Ghobadian %M.Sc. Student of Geophysics %Earth Science Department % Institute of Advanced Studies in Basic Sciences (IASBS) % Zanjan, Iran % vghobadian@iasbs.ac.ir % *********************************************************** % Function : RTP % Calculates reduction to pole % *********************************************************** function out = RTP(TR,Inc,Dec,dx,dy) I=Inc; D=Dec; TR = TR'; [nx,ny] = size(TR); nmax=max([nx ny]); npts=2^nextpow2(nmax); cdiff=floor((npts-ny)/2); rdiff=floor((npts-nx)/2); data=taper2d(TR,npts,nx,ny,rdiff,cdiff); TR1 = data; nyqx=(1/(2*dx)); nyqy=(1/(2*dy)); kx=linspace(-nyqx,nyqx,npts); ky=linspace(-nyqy,nyqy,npts); L=cos(I)*cos(D); l=cos(I)*cos(D); R=cos(I)*sin(D); r=cos(I)*sin(D); Q=sin(I); q=sin(I); [KX KY]=meshgrid(kx,ky); Kx=KX.*KX; Ky=KY.*KY; 3
  4. 4. for m= 1:npts for n= 1:npts RTP(m,n) = (Kx(m,n)+Ky(m,n))/(((i*L*KX(m,n))+(i*R*KY(m,n))+(Q*((Kx(m,n)+Ky(m,n)). ^0.5))).*((i*l*KX(m,n))+(i*r*KY(m,n))+(q*((Kx(m,n)+Ky(m,n)).^0.5)))); end end RTP=fftshift(RTP); filtR_dat1=(ifft2(fft2(TR1).*RTP)); out=real(filtR_dat1(1+rdiff:nx+rdiff,1+cdiff:ny+cdiff)); out = out'; function gt=taper2d(g,npts,nr,nc,rdiff,cdiff) % Merge edges to the value opposite using a cubic spline gt=zeros(npts); gt(rdiff+1:rdiff+nr,cdiff+1:cdiff+nc)=g; gp=g(:,1:3); [gpx1,junk]=gradient(gp); % sides gp=g(:,nc-2:nc); [gpx2,junk]=gradient(gp); x1=0; x2=(2*cdiff)+1; x=[1 1 0 0;x1 x2 1 1; x1^2 x2^2 2*x1 2*x2; x1^3 x2^3 3*x1^2 3*x2^2]; for I=1:nr; y=[g(I,nc) g(I,1) gpx2(I,3) gpx1(I,1)]; c=y/x; for J=1:cdiff; gt(I+rdiff,J)=c(1)+(J+cdiff)*c(2)+c(3)*(J+cdiff)^2+c(4)*(J+cdiff)^3; gt(I+rdiff,J+nc+cdiff)=c(1)+J*c(2)+c(3)*J^2+c(4)*J^3; end; end; gp=g(1:3,:); [junk,gpx1]=gradient(gp); % top and bottom gp=g(nr-2:nr,:); [junk,gpx2]=gradient(gp); x1=0; x2=(2*rdiff)+1; x=[1 1 0 0;x1 x2 1 1; x1^2 x2^2 2*x1 2*x2; x1^3 x2^3 3*x1^2 3*x2^2]; for J=1:nc; y=[g(nr,J) g(1,J) gpx2(3,J) gpx1(1,J)]; c=y/x; for I=1:rdiff; gt(I,J+cdiff)=c(1)+(I+rdiff)*c(2)+c(3)*(I+rdiff)^2+c(4)*(I+rdiff)^3; gt(I+rdiff+nr,J+cdiff)=c(1)+I*c(2)+c(3)*I^2+c(4)*I^3; end; end; for I=rdiff+nr+1:npts; % Corners for J=cdiff+nc+1:npts; if (I-nr-rdiff)>(J-nc-cdiff); gt(I,J)=gt(I,nc+cdiff); else gt(I,J)=gt(nr+rdiff,J); end; end; end; for I=1:rdiff; 4
  5. 5. for J=1:cdiff; if I>J; gt(I,J)=gt(rdiff+1,J); else gt(I,J)=gt(I,cdiff+1); end; end; end; for I=1:rdiff; % bottom right for J=cdiff+nc+1:npts; if I>(npts-J); gt(I,J)=gt(rdiff+1,J); else gt(I,J)=gt(I,cdiff+nc); end; end; end; for I=rdiff+nr+1:npts; % top left for J=1:cdiff; if (npts-I)>J; gt(I,J)=gt(rdiff+nr,J); else gt(I,J)=gt(I,cdiff+1); end; end; end; Appendix 2 - The program generates a magnetic field model (uniform magnetic sphere center in x0, y0-depth z0 and radius r0) function [XI,YI,L,N,Bx,By,Bz,T] = s3d2(incl,x0,y0) clc d2rad=pi/180; incl=incl*d2rad; decl=0; z0=50;rs=20;nx=201;ny=nx;azm=0*d2rad; %f=msphere3(incl,decl,M,dz,rs,nx,dx,ix,iy); F=50000; % Strength of Earth''s field (nT) chi=0.1; % Susceptibility of sphere (SI) vol = (4*pi*rs.^3)./3; cm=1e-7; mu_0 = 4*pi*cm; M=vol*chi*F/(mu_0) ; % Magnetization of sphere m0=M ; % Magnetic moment of sphere lx=600 ;ly=600;%length of grid (m) dx=lx./(nx-1);dy=ly./(nx-1); x=linspace(-lx/2,lx/2,nx); y=linspace(-ly/2,ly/2,ny); Mx=cos(incl).*cos(decl-azm); My=cos(incl).*sin(decl-azm); Mz=sin(incl); rx=(x-x0); 5
  6. 6. ry=(y-y0); rz=0-(z0)*ones(1,nx); for i=1:nx for j=1:ny r2(i,j)=rx(i)^2+ry(j)^2+rz(i)^2; r(i,j)=sqrt(r2(i,j)); dot(i,j)=rx(i)*Mx+ry(j)*My+rz(i)*Mz; % z0=z0.*ones(101,101); r5(i,j)=r(i,j)^5; Bx(i,j)=m0*cm*(3*dot(i,j)*rx(i)-(r2(i,j)*Mx))/r5(i,j); By(i,j)=m0*cm*(3*dot(i,j)*ry(j)-(r2(i,j)*My))/r5(i,j); Bz(i,j)=m0*cm*(3*dot(i,j)*rz(i)-(r2(i,j)*Mz))/r5(i,j); IB(i,j)=atan(Bz(i,j)/sqrt((Bx(i,j)^2)+(By(i,j))^2)); DB(i,j)=acos(Bx(i,j)/sqrt((Bx(i,j)^2)+(By(i,j))^2)); DB(i,j)=decl; IB(i,j)=incl; B(i,j)=(Bx(i,j)*cos(DB(i,j))*cos(IB(i,j))+By(i,j)*sin(DB(i, j))*cos(IB(i,j)))+Bz(i,j)*sin(IB(i,j)); end end N=401; xi=linspace(min(x),max(x),N); yi=linspace(min(y),max(y),N); L=max(xi)-min(yi); [XI,YI] = meshgrid(xi,yi); T = griddata(x,y,B,XI,YI,'linear'); Bx = griddata(x,y,Bx,XI,YI,'linear'); By = griddata(x,y,By,XI,YI,'linear'); Bz = griddata(x,y,Bz,XI,YI,'linear'); 6
  7. 7. Appendix 3 -Matlab program used to calculate differential reduction to pole (DRTP)correction %********(Differential Reduction to pole DRTP) % Reduction to Pole with variable geomagnetic parameters % *** Uses a perturbation method in the frequency domain % drtp Reduce a magnetic field anomaly map to the pole % using Fourier transform and specifying variation of inclination and % declination of the magnetic field and magnetization % Please notice that north is along X axis % Z is positive beyond horizontal % PC-MATLAB % AUTHOR % Vahid Ghobadian-IASBS-Department of Earth Sciences - March 5 2012 clear all clc load c.mat format short g ; deltaT=data(:,1);%input =data(x,y,T) x=(data(:,3)); y=(data(:,2)); x1=min(x):1.25:max(x); y1=min(y):1.25:max(y); [XI,YI]=meshgrid(x1,y1); dx=XI(1,2)-XI(1,1);dy=YI(2,1)-YI(1,1); %Define sample interval in x,y direction clear XI;clear YI; deltaT=gridfit(x,y,deltaT,x1,y1); %creation grid data decl=data(:,4); incl=data(:,5); 7
  8. 8. d2rad=pi/180; %converting degrees to radians [nx,ny]=size(deltaT); %Define demension of input 2-D data in x-y direction cm=1e-7; %constant value calculation in SI img=sqrt(-1); %imaginary number clear data; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Constructing the external feild incv =gridfit(x,y,incl,x1,y1)*d2rad; % inclination matrix %incv=incv'; declv =gridfit(x,y,decl,x1,y1)*d2rad; % inclination matrix %declv=declv'; %clear XI;clear YI; inc=incv(ceil(nx/2),ceil(ny/2)); % inclination at centre of grid dec=declv(ceil(nx/2),ceil(ny/2)); fx=(cos(incv).*cos(declv)); % vector of external feild in x fy=cos(incv) .* sin(declv); % vector of external feild in y fz=(sin(incv)); % vector of external feild in z clear incv; clear declv; % Defining components of external field at the center of our study region, f0_x=fx(floor(nx/2),floor(ny/2)); %fx in center of Iran f0_y=fy(floor(nx/2),floor(ny/2)); %fy in center of Iran f0_z=fz(floor(nx/2),floor(ny/2)); %fz in center of Iran % Calculating delta_f deltafx=(fx-f0_x); %perturbation about uniform vector f0_x deltafy=(fy-f0_y); %perturbation about uniform vector f0_x deltafz=(fz-f0_z); %perturbation about uniform vector f0_x Mx=fx; My=fy; Mz=0; clear fx; clear fy; clear fz; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% % Defining wave number kx=kvalue(nx,dx); ky=(kvalue(ny,dy)); kx=(kx'*ones(1,ny)); ky=(ky'*ones(1,nx));ky=(ky'); k=(sqrt(kx.*kx+ky.*ky));kx=img.*kx;ky=img.*ky;kz=abs(k); kdotf0=f0_x.*kx+f0_y.*ky+f0_z.*kz; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%% %furier transform of the Total field anomaly fdT=(fft2(deltaT)); 8
  9. 9. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% % calculating gradient of V, Gv fv= zeros(nx,ny); fv_old=fv; epsilon=1e-2; iter=0; error =1000; while error > epsilon Gv1= real(ifft2(kx .* (fv))); Gv2= real(ifft2(ky .* (fv))); Gv3= real(ifft2(kz .* (fv))); nl=(deltafx.*Gv1+deltafy.*Gv2+deltafz.*Gv3); clear Gv1;clear Gv2;clear Gv3; % Calculating potential field V for i=1:nx for j=1:ny if (kdotf0(i,j) ~= 0) fv(i,j)=-(fdT(i,j)+fft2(nl(i,j)))/kdotf0(i,j); else kdotf0(i,j)=1; end; end; end; error = sqrt(sum(sum( (real(fv - fv_old)).^2))); fv_old =fv; error iter=iter+1; iter if iter > 10 , break; end end disp('fv converged!'); clear nl; kdotM0=kdotf0; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% M0x=f0_x; M0y=f0_y; M0z=f0_z; 9
  10. 10. % Calculating magnetization of the equvalant layer fM=zeros(nx,ny); M=zeros(nx,ny); fM_old= fM; epsilon2=1e-3; iter2=0; error2 =1000; while error2 > epsilon2 M=real(ifft2(fM)); deltamx=Mx-M0x; deltamy=My-M0y; deltamz=0; fMdm_x=(fft2(M.*deltamx)); fMdm_y=(fft2(M.*deltamy)); fMdm_z=(fft2(M.*deltamz)); clear deltamx; clear deltamy; clear deltamz; kdotfMdm=kx.*fMdm_x+ky.*fMdm_y+kz.*fMdm_z; for i=1:nx for j=1:ny if (kdotM0(i,j) ~= 0) fM(i,j)=- ((fv(i,j)*k(i,j))/(2*pi*cm)+(kdotfMdm(i,j)))/kdotM0(i,j); else kdotM0(i,j)=1; end; end; end; error2 = sqrt(sum(sum( (real(fM - fM_old)).^2))); fM_old = fM; error2 iter2=iter2+1; iter2 if iter2 > 20 , break; end end disp ('fm converged!'); fTp=2*pi*cm*(kz.*fM); Tp=(real(ifft2(fTp))); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10
  11. 11. %load iranmagfull.mat [XI,YI]=meshgrid(x1,y1); n=1; for i=1:ny; for j=1:nx; xx(n)=XI(j,i); yy(n)=YI(j,i); Tpp(n)=Tp(j,i); n=n+1; end end yy=yy';xx=xx';Tpp=Tpp'; output =[yy,xx ,(Tpp)]; save Tpfull.txt output -ascii;%save output in Tpout.txt %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [zgrid,xgrid,ygrid] = gridfit(x,y,z,xnodes,ynodes,varargin) % usage #1: zgrid = gridfit(x,y,z,xnodes,ynodes); % usage #2: [zgrid,xgrid,ygrid] = gridfit(x,y,z,xnodes,ynodes); % usage #3: zgrid = gridfit(x,y,z,xnodes,ynodes,prop,val,prop,val,...); % set defaults params.smoothness = 1; params.interp = 'triangle'; params.regularizer = 'gradient'; params.solver = 'backslash'; params.maxiter = []; params.extend = 'warning'; params.tilesize = inf; params.overlap = 0.20; params.mask = []; params.autoscale = 'on'; params.xscale = 1; params.yscale = 1; % was the params struct supplied? if ~isempty(varargin) if isstruct(varargin{1}) % params is only supplied if its a call from tiled_gridfit params = varargin{1}; if length(varargin)>1 % check for any overrides params = parse_pv_pairs(params,varargin{2:end}); end else % check for any overrides of the defaults params = parse_pv_pairs(params,varargin); end end % check the parameters for acceptability params = check_params(params); % ensure all of x,y,z,xnodes,ynodes are column vectors, % also drop any NaN data 11
  12. 12. x=x(:); y=y(:); z=z(:); k = isnan(x) | isnan(y) | isnan(z); if any(k) x(k)=[]; y(k)=[]; z(k)=[]; end xmin = min(x); xmax = max(x); ymin = min(y); ymax = max(y); % did they supply a scalar for the nodes? if length(xnodes)==1 xnodes = linspace(xmin,xmax,xnodes)'; xnodes(end) = xmax; % make sure it hits the max end if length(ynodes)==1 ynodes = linspace(ymin,ymax,ynodes)'; ynodes(end) = ymax; % make sure it hits the max end xnodes=xnodes(:); ynodes=ynodes(:); dx = diff(xnodes); dy = diff(ynodes); nx = length(xnodes); ny = length(ynodes); ngrid = nx*ny; % set the scaling if autoscale was on if strcmpi(params.autoscale,'on') params.xscale = mean(dx); params.yscale = mean(dy); params.autoscale = 'off'; end % check to see if any tiling is necessary if (params.tilesize < max(nx,ny)) % split it into smaller tiles. compute zgrid and ygrid % at the very end if requested zgrid = tiled_gridfit(x,y,z,xnodes,ynodes,params); else % its a single tile. % mask must be either an empty array, or a boolean % aray of the same size as the final grid. nmask = size(params.mask); if ~isempty(params.mask) && ((nmask(2)~=nx) || (nmask(1)~=ny)) if ((nmask(2)==ny) || (nmask(1)==nx)) error 'Mask array is probably transposed from proper orientation.' else 12
  13. 13. error 'Mask array must be the same size as the final grid.' end end if ~isempty(params.mask) params.maskflag = 1; else params.maskflag = 0; end % default for maxiter? if isempty(params.maxiter) params.maxiter = min(10000,nx*ny); end % check lengths of the data n = length(x); if (length(y)~=n) || (length(z)~=n) error 'Data vectors are incompatible in size.' end if n<3 error 'Insufficient data for surface estimation.' end % verify the nodes are distinct if any(diff(xnodes)<=0) || any(diff(ynodes)<=0) error 'xnodes and ynodes must be monotone increasing' end % do we need to tweak the first or last node in x or y? if xmin<xnodes(1) switch params.extend case 'always' xnodes(1) = xmin; case 'warning' warning('GRIDFIT:extend',['xnodes(1) was decreased by: ',num2str(xnodes(1)-xmin),', new node = ',num2str(xmin)]) xnodes(1) = xmin; case 'never' error(['Some x (',num2str(xmin),') falls below xnodes(1) by: ',num2str(xnodes(1)-xmin)]) end end if xmax>xnodes(end) switch params.extend case 'always' xnodes(end) = xmax; case 'warning' warning('GRIDFIT:extend',['xnodes(end) was increased by: ',num2str(xmax-xnodes(end)),', new node = ',num2str(xmax)]) xnodes(end) = xmax; case 'never' error(['Some x (',num2str(xmax),') falls above xnodes(end) by: ',num2str(xmax-xnodes(end))]) end end 13
  14. 14. if ymin<ynodes(1) switch params.extend case 'always' ynodes(1) = ymin; case 'warning' warning('GRIDFIT:extend',['ynodes(1) was decreased by: ',num2str(ynodes(1)-ymin),', new node = ',num2str(ymin)]) ynodes(1) = ymin; case 'never' error(['Some y (',num2str(ymin),') falls below ynodes(1) by: ',num2str(ynodes(1)-ymin)]) end end if ymax>ynodes(end) switch params.extend case 'always' ynodes(end) = ymax; case 'warning' warning('GRIDFIT:extend',['ynodes(end) was increased by: ',num2str(ymax-ynodes(end)),', new node = ',num2str(ymax)]) ynodes(end) = ymax; case 'never' error(['Some y (',num2str(ymax),') falls above ynodes(end) by: ',num2str(ymax-ynodes(end))]) end end % determine which cell in the array each point lies in [junk,indx] = histc(x,xnodes); %#ok [junk,indy] = histc(y,ynodes); %#ok % any point falling at the last node is taken to be % inside the last cell in x or y. k=(indx==nx); indx(k)=indx(k)-1; k=(indy==ny); indy(k)=indy(k)-1; ind = indy + ny*(indx-1); % Do we have a mask to apply? if params.maskflag % if we do, then we need to ensure that every % cell with at least one data point also has at % least all of its corners unmasked. params.mask(ind) = 1; params.mask(ind+1) = 1; params.mask(ind+ny) = 1; params.mask(ind+ny+1) = 1; end % interpolation equations for each point tx = min(1,max(0,(x - xnodes(indx))./dx(indx))); ty = min(1,max(0,(y - ynodes(indy))./dy(indy))); % Future enhancement: add cubic interpolant switch params.interp case 'triangle' 14
  15. 15. % linear interpolation inside each triangle k = (tx > ty); L = ones(n,1); L(k) = ny; t1 = min(tx,ty); t2 = max(tx,ty); A = sparse(repmat((1:n)',1,3),[ind,ind+ny+1,ind+L], ... [1-t2,t1,t2-t1],n,ngrid); case 'nearest' % nearest neighbor interpolation in a cell k = round(1-ty) + round(1-tx)*ny; A = sparse((1:n)',ind+k,ones(n,1),n,ngrid); case 'bilinear' % bilinear interpolation in a cell A = sparse(repmat((1:n)',1,4),[ind,ind+1,ind+ny,ind+ny+1], ... [(1-tx).*(1-ty), (1-tx).*ty, tx.*(1-ty), tx.*ty], ... n,ngrid); end rhs = z; % do we have relative smoothing parameters? if numel(params.smoothness) == 1 % it was scalar, so treat both dimensions equally smoothparam = params.smoothness; xyRelativeStiffness = [1;1]; else % It was a vector, so anisotropy reigns. % I've already checked that the vector was of length 2 smoothparam = sqrt(prod(params.smoothness)); xyRelativeStiffness = params.smoothness(:)./smoothparam; end % Build regularizer. Add del^4 regularizer one day. switch params.regularizer case 'springs' % zero "rest length" springs [i,j] = meshgrid(1:nx,1:(ny-1)); ind = j(:) + ny*(i(:)-1); m = nx*(ny-1); stiffness = 1./(dy/params.yscale); Areg = sparse(repmat((1:m)',1,2),[ind,ind+1], ... xyRelativeStiffness(2)*stiffness(j(:))*[-1 1], ... m,ngrid); [i,j] = meshgrid(1:(nx-1),1:ny); ind = j(:) + ny*(i(:)-1); m = (nx-1)*ny; stiffness = 1./(dx/params.xscale); Areg = [Areg;sparse(repmat((1:m)',1,2),[ind,ind+ny], ... xyRelativeStiffness(1)*stiffness(i(:))*[-1 1],m,ngrid)]; 15
  16. 16. [i,j] = meshgrid(1:(nx-1),1:(ny-1)); ind = j(:) + ny*(i(:)-1); m = (nx-1)*(ny-1); stiffness = 1./sqrt((dx(i(:))/params.xscale/xyRelativeStiffness(1)).^2 + ... (dy(j(:))/params.yscale/xyRelativeStiffness(2)).^2); Areg = [Areg;sparse(repmat((1:m)',1,2),[ind,ind+ny+1], ... stiffness*[-1 1],m,ngrid)]; Areg = [Areg;sparse(repmat((1:m)',1,2),[ind+1,ind+ny], ... stiffness*[-1 1],m,ngrid)]; case {'diffusion' 'laplacian'} % thermal diffusion using Laplacian (del^2) [i,j] = meshgrid(1:nx,2:(ny-1)); ind = j(:) + ny*(i(:)-1); dy1 = dy(j(:)-1)/params.yscale; dy2 = dy(j(:))/params.yscale; Areg = sparse(repmat(ind,1,3),[ind-1,ind,ind+1], ... xyRelativeStiffness(2)*[-2./(dy1.*(dy1+dy2)), ... 2./(dy1.*dy2), -2./(dy2.*(dy1+dy2))],ngrid,ngrid); [i,j] = meshgrid(2:(nx-1),1:ny); ind = j(:) + ny*(i(:)-1); dx1 = dx(i(:)-1)/params.xscale; dx2 = dx(i(:))/params.xscale; Areg = Areg + sparse(repmat(ind,1,3),[ind-ny,ind,ind+ny], ... xyRelativeStiffness(1)*[-2./(dx1.*(dx1+dx2)), ... 2./(dx1.*dx2), -2./(dx2.*(dx1+dx2))],ngrid,ngrid); case 'gradient' % Subtly different from the Laplacian. A point for future % enhancement is to do it better for the triangle interpolation % case. [i,j] = meshgrid(1:nx,2:(ny-1)); ind = j(:) + ny*(i(:)-1); dy1 = dy(j(:)-1)/params.yscale; dy2 = dy(j(:))/params.yscale; Areg = sparse(repmat(ind,1,3),[ind-1,ind,ind+1], ... xyRelativeStiffness(2)*[-2./(dy1.*(dy1+dy2)), ... 2./(dy1.*dy2), -2./(dy2.*(dy1+dy2))],ngrid,ngrid); [i,j] = meshgrid(2:(nx-1),1:ny); ind = j(:) + ny*(i(:)-1); dx1 = dx(i(:)-1)/params.xscale; dx2 = dx(i(:))/params.xscale; Areg = [Areg;sparse(repmat(ind,1,3),[ind-ny,ind,ind+ny], ... xyRelativeStiffness(1)*[-2./(dx1.*(dx1+dx2)), ... 2./(dx1.*dx2), -2./(dx2.*(dx1+dx2))],ngrid,ngrid)]; 16
  17. 17. end nreg = size(Areg,1); % Append the regularizer to the interpolation equations, % scaling the problem first. Use the 1-norm for speed. NA = norm(A,1); NR = norm(Areg,1); A = [A;Areg*(smoothparam*NA/NR)]; rhs = [rhs;zeros(nreg,1)]; % do we have a mask to apply? if params.maskflag unmasked = find(params.mask); end % solve the full system, with regularizer attached switch params.solver case {'' 'backslash'} if params.maskflag % there is a mask to use zgrid=nan(ny,nx); zgrid(unmasked) = A(:,unmasked)rhs; else % no mask zgrid = reshape(Arhs,ny,nx); end case 'normal' % The normal equations, solved with . Can be faster % for huge numbers of data points, but reasonably % sized grids. The regularizer makes A well conditioned % so the normal equations are not a terribly bad thing % here. if params.maskflag % there is a mask to use Aunmasked = A(:,unmasked); zgrid=nan(ny,nx); zgrid(unmasked) = (Aunmasked'*Aunmasked)(Aunmasked'*rhs); else zgrid = reshape((A'*A)(A'*rhs),ny,nx); end case 'symmlq' % iterative solver - symmlq - requires a symmetric matrix, % so use it to solve the normal equations. No preconditioner. tol = abs(max(z)-min(z))*1.e-13; if params.maskflag % there is a mask to use zgrid=nan(ny,nx); [zgrid(unmasked),flag] = symmlq(A(:,unmasked)'*A(:,unmasked), ... A(:,unmasked)'*rhs,tol,params.maxiter); else [zgrid,flag] = symmlq(A'*A,A'*rhs,tol,params.maxiter); zgrid = reshape(zgrid,ny,nx); end % display a warning if convergence problems 17
  18. 18. switch flag case 0 % no problems with convergence case 1 % SYMMLQ iterated MAXIT times but did not converge. warning('GRIDFIT:solver',['Symmlq performed ',num2str(params.maxiter), ... ' iterations but did not converge.']) case 3 % SYMMLQ stagnated, successive iterates were the same warning('GRIDFIT:solver','Symmlq stagnated without apparent convergence.') otherwise warning('GRIDFIT:solver',['One of the scalar quantities calculated in',... ' symmlq was too small or too large to continue computing.']) end case 'lsqr' % iterative solver - lsqr. No preconditioner here. tol = abs(max(z)-min(z))*1.e-13; if params.maskflag % there is a mask to use zgrid=nan(ny,nx); [zgrid(unmasked),flag] = lsqr(A(:,unmasked),rhs,tol,params.maxiter); else [zgrid,flag] = lsqr(A,rhs,tol,params.maxiter); zgrid = reshape(zgrid,ny,nx); end % display a warning if convergence problems switch flag case 0 case 1 warning('GRIDFIT:solver',['Lsqr performed ', ... num2str(params.maxiter),' iterations but did not converge.']) case 3 % lsqr stagnated, successive iterates were the same warning('GRIDFIT:solver','Lsqr stagnated without apparent convergence.') case 4 warning('GRIDFIT:solver',['One of the scalar quantities calculated in',... ' LSQR was too small or too large to continue computing.']) end end % switch params.solver end % if params.tilesize... 18
  19. 19. % only generate xgrid and ygrid if requested. if nargout>1 [xgrid,ygrid]=meshgrid(xnodes,ynodes); end % subfunction - parse_pv_pairs % ============================================ function params=parse_pv_pairs(params,pv_pairs) % usage: params=parse_pv_pairs(default_params,pv_pairs) npv = length(pv_pairs); n = npv/2; if n~=floor(n) error 'Property/value pairs must come in PAIRS.' end if n<=0 % just return the defaults return end if ~isstruct(params) error 'No structure for defaults was supplied' end % there was at least one pv pair. process any supplied propnames = fieldnames(params); lpropnames = lower(propnames); for i=1:n p_i = lower(pv_pairs{2*i-1}); v_i = pv_pairs{2*i}; ind = strmatch(p_i,lpropnames,'exact'); if isempty(ind) ind = find(strncmp(p_i,lpropnames,length(p_i))); if isempty(ind) error(['No matching property found for: ',pv_pairs{2*i-1}]) elseif length(ind)>1 error(['Ambiguous property name: ',pv_pairs{2*i-1}]) end end p_i = propnames{ind}; % override the corresponding default in params params = setfield(params,p_i,v_i); %#ok end % ============================================ % subfunction - check_params % ============================================ function params = check_params(params) if isempty(params.smoothness) params.smoothness = 1; else 19
  20. 20. if (numel(params.smoothness)>2) || any(params.smoothness<=0) error 'Smoothness must be scalar (or length 2 vector), real, finite, and positive.' end end % regularizer - must be one of 4 options - the second and % third are actually synonyms. valid = {'springs', 'diffusion', 'laplacian', 'gradient'}; if isempty(params.regularizer) params.regularizer = 'diffusion'; end ind = find(strncmpi(params.regularizer,valid,length(params.regularizer))); if (length(ind)==1) params.regularizer = valid{ind}; else error(['Invalid regularization method: ',params.regularizer]) end % interp must be one of: % 'bilinear', 'nearest', or 'triangle' % but accept any shortening thereof. valid = {'bilinear', 'nearest', 'triangle'}; if isempty(params.interp) params.interp = 'triangle'; end ind = find(strncmpi(params.interp,valid,length(params.interp))); if (length(ind)==1) params.interp = valid{ind}; else error(['Invalid interpolation method: ',params.interp]) end % solver must be one of: % 'backslash', '', 'symmlq', 'lsqr', or 'normal' % but accept any shortening thereof. valid = {'backslash', '', 'symmlq', 'lsqr', 'normal'}; if isempty(params.solver) params.solver = ''; end ind = find(strncmpi(params.solver,valid,length(params.solver))); if (length(ind)==1) params.solver = valid{ind}; else error(['Invalid solver option: ',params.solver]) end % extend must be one of: % 'never', 'warning', 'always' % but accept any shortening thereof. valid = {'never', 'warning', 'always'}; if isempty(params.extend) params.extend = 'warning'; end 20
  21. 21. ind = find(strncmpi(params.extend,valid,length(params.extend))); if (length(ind)==1) params.extend = valid{ind}; else error(['Invalid extend option: ',params.extend]) end % tilesize == inf by default if isempty(params.tilesize) params.tilesize = inf; elseif (length(params.tilesize)>1) || (params.tilesize<3) error 'Tilesize must be scalar and > 0.' end % overlap == 0.20 by default if isempty(params.overlap) params.overlap = 0.20; elseif (length(params.overlap)>1) || (params.overlap<0) || (params.overlap>0.5) error 'Overlap must be scalar and 0 < overlap < 1.' end % ============================================ % subfunction - tiled_gridfit % ============================================ function zgrid=tiled_gridfit(x,y,z,xnodes,ynodes,params) % usage: [zgrid,xgrid,ygrid]=tiled_gridfit(x,y,z,xnodes,ynodes,params) tilesize = params.tilesize; overlap = max(2,floor(tilesize*params.overlap)); Tparams = params; Tparams.tilesize = inf; nx = length(xnodes); ny = length(ynodes); zgrid = zeros(ny,nx); % linear ramp for the bilinear interpolation rampfun = inline('(t-t(1))/(t(end)-t(1))','t'); % loop over each tile in the grid h = waitbar(0,'Relax and have a cup of JAVA. Its my treat.'); warncount = 0; xtind = 1:min(nx,tilesize); while ~isempty(xtind) && (xtind(1)<=nx) xinterp = ones(1,length(xtind)); if (xtind(1) ~= 1) xinterp(1:overlap) = rampfun(xnodes(xtind(1:overlap))); end if (xtind(end) ~= nx) xinterp((end-overlap+1):end) = 1-rampfun(xnodes(xtind((end- overlap+1):end))); end ytind = 1:min(ny,tilesize); 21
  22. 22. while ~isempty(ytind) && (ytind(1)<=ny) % update the waitbar waitbar((xtind(end)-tilesize)/nx + tilesize*ytind(end)/ny/nx) yinterp = ones(length(ytind),1); if (ytind(1) ~= 1) yinterp(1:overlap) = rampfun(ynodes(ytind(1:overlap))); end if (ytind(end) ~= ny) yinterp((end-overlap+1):end) = 1-rampfun(ynodes(ytind((end- overlap+1):end))); end % was a mask supplied? if ~isempty(params.mask) submask = params.mask(ytind,xtind); Tparams.mask = submask; end % extract data that lies in this grid tile k = (x>=xnodes(xtind(1))) & (x<=xnodes(xtind(end))) & ... (y>=ynodes(ytind(1))) & (y<=ynodes(ytind(end))); k = find(k); if length(k)<4 if warncount == 0 warning('GRIDFIT:tiling','A tile was too underpopulated to model. Filled with NaNs.') end warncount = warncount + 1; % fill this part of the grid with NaNs zgrid(ytind,xtind) = NaN; else % build this tile zgtile = gridfit(x(k),y(k),z(k),xnodes(xtind),ynodes(ytind),Tparams); % bilinear interpolation (using an outer product) interp_coef = yinterp*xinterp; % accumulate the tile into the complete grid zgrid(ytind,xtind) = zgrid(ytind,xtind) + zgtile.*interp_coef; end % step to the next tile in y if ytind(end)<ny ytind = ytind + tilesize - overlap; % are we within overlap elements of the edge of the grid? if (ytind(end)+max(3,overlap))>=ny % extend this tile to the edge ytind = ytind(1):ny; end 22
  23. 23. else ytind = ny+1; end end % while loop over y % step to the next tile in x if xtind(end)<nx xtind = xtind + tilesize - overlap; % are we within overlap elements of the edge of the grid? if (xtind(end)+max(3,overlap))>=nx % extend this tile to the edge xtind = xtind(1):nx; end else xtind = nx+1; end end % while loop over x % close down the waitbar close(h) if warncount>0 warning('GRIDFIT:tiling',[num2str(warncount),' tiles were underpopulated & filled with NaNs']) end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function kx=kvalue(nn,dx) % KVALUE compute wavenumber coordinate % Usage: % kx=kvalue(nn,dx); % nn2=nn/2; n2plus=nn2+1; dkx=2*pi/(nn*dx); % make wave number array kx=(-nn2:nn2-1).*dkx; kx=fftshift(kx); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function gt=taper2d(g,npts,nr,nc,rdiff,cdiff) % Merge edges to the value opposite using a cubic spline gt=zeros(npts); gt(rdiff+1:rdiff+nr,cdiff+1:cdiff+nc)=g; gp=g(:,1:3); [gpx1,junk]=gradient(gp); % sides gp=g(:,nc-2:nc); [gpx2,junk]=gradient(gp); x1=0; x2=(2*cdiff)+1; x=[1 1 0 0;x1 x2 1 1; x1^2 x2^2 2*x1 2*x2; x1^3 x2^3 3*x1^2 3*x2^2]; for I=1:nr; y=[g(I,nc) g(I,1) gpx2(I,3) gpx1(I,1)]; c=y/x; for J=1:cdiff; gt(I+rdiff,J)=c(1)+(J+cdiff)*c(2)+c(3)*(J+cdiff)^2+c(4)*(J+cdiff)^3; gt(I+rdiff,J+nc+cdiff)=c(1)+J*c(2)+c(3)*J^2+c(4)*J^3; end; 23
  24. 24. end; gp=g(1:3,:); [junk,gpx1]=gradient(gp); % top and bottom gp=g(nr-2:nr,:); [junk,gpx2]=gradient(gp); x1=0; x2=(2*rdiff)+1; x=[1 1 0 0;x1 x2 1 1; x1^2 x2^2 2*x1 2*x2; x1^3 x2^3 3*x1^2 3*x2^2]; for J=1:nc; y=[g(nr,J) g(1,J) gpx2(3,J) gpx1(1,J)]; c=y/x; for I=1:rdiff; gt(I,J+cdiff)=c(1)+(I+rdiff)*c(2)+c(3)*(I+rdiff)^2+c(4)*(I+rdiff)^3; gt(I+rdiff+nr,J+cdiff)=c(1)+I*c(2)+c(3)*I^2+c(4)*I^3; end; end; for I=rdiff+nr+1:npts; % Corners for J=cdiff+nc+1:npts; if (I-nr-rdiff)>(J-nc-cdiff); gt(I,J)=gt(I,nc+cdiff); else gt(I,J)=gt(nr+rdiff,J); end; end; end; for I=1:rdiff; for J=1:cdiff; if I>J; gt(I,J)=gt(rdiff+1,J); else gt(I,J)=gt(I,cdiff+1); end; end; end; for I=1:rdiff; % bottom right for J=cdiff+nc+1:npts; if I>(npts-J); gt(I,J)=gt(rdiff+1,J); else gt(I,J)=gt(I,cdiff+nc); end; end; end; for I=rdiff+nr+1:npts; % top left for J=1:cdiff; if (npts-I)>J; gt(I,J)=gt(rdiff+nr,J); else gt(I,J)=gt(I,cdiff+1); end; end; end; 24
  25. 25. 25

×