sandbox/easystab/fourdif.m

    Fourier differentiation matrix

    function [x, DM] = fourdif(N,m)
    %
    % The function [x, DM] = fourdif(N,m) computes the m'th derivative Fourier 
    % spectral differentiation matrix on grid with N equispaced points in [0,2pi)
    % 
    %  Input:
    %  N:        Size of differentiation matrix.
    %  M:        Derivative required (non-negative integer)
    %
    %  Output:
    %  x:        Equispaced points 0, 2pi/N, 4pi/N, ... , (N-1)2pi/N
    %  DM:       m'th order differentiation matrix
    %
    % 
    %  Explicit formulas are used to compute the matrices for m=1 and 2. 
    %  A discrete Fouier approach is employed for m>2. The program 
    %  computes the first column and first row and then uses the 
    %  toeplitz command to create the matrix.
    
    %  For m=1 and 2 the code implements a "flipping trick" to
    %  improve accuracy suggested by W. Don and A. Solomonoff in 
    %  SIAM J. Sci. Comp. Vol. 6, pp. 1253--1268 (1994).
    %  The flipping trick is necesary since sin t can be computed to high
    %  relative precision when t is small whereas sin (pi-t) cannot.
    %
    %  S.C. Reddy, J.A.C. Weideman 1998.  Corrected for MATLAB R13 
    %  by JACW, April 2003.
     
    
        x=2*pi*(0:N-1)'/N;                       % gridpoints
        h=2*pi/N;                                % grid spacing
        zi=sqrt(-1);
        kk=(1:N-1)';
        n1=floor((N-1)/2); n2=ceil((N-1)/2);
        if m==0,                                 % compute first column
          col1=[1; zeros(N-1,1)];                % of zeroth derivative
          row1=col1;                             % matrix, which is identity
    
        elseif m==1,                             % compute first column
          if rem(N,2)==0                         % of 1st derivative matrix
    	topc=cot((1:n2)'*h/2);
            col1=[0; 0.5*((-1).^kk).*[topc; -flipud(topc(1:n1))]]; 
          else
    	topc=csc((1:n2)'*h/2);
            col1=[0; 0.5*((-1).^kk).*[topc; flipud(topc(1:n1))]];
          end;
          row1=-col1;                            % first row
    
        elseif m==2,                             % compute first column  
          if rem(N,2)==0                         % of 2nd derivative matrix
    	topc=csc((1:n2)'*h/2).^2;
            col1=[-pi^2/3/h^2-1/6; -0.5*((-1).^kk).*[topc; flipud(topc(1:n1))]];
          else
    	topc=csc((1:n2)'*h/2).*cot((1:n2)'*h/2);
            col1=[-pi^2/3/h^2+1/12; -0.5*((-1).^kk).*[topc; -flipud(topc(1:n1))]];
          end;
          row1=col1;                             % first row 
    
        else                                     % employ FFT to compute
          N1=floor((N-1)/2);                     % 1st column of matrix for m>2
          N2 = (-N/2)*rem(m+1,2)*ones(rem(N+1,2));  
          mwave=zi*[(0:N1) N2 (-N1:-1)];
          col1=real(ifft((mwave.^m).*fft([1 zeros(1,N-1)])));
          if rem(m,2)==0,
    	row1=col1;                           % first row even derivative
          else
    	col1=[0 col1(2:N)]'; 
    	row1=-col1;                          % first row odd derivative
          end;
        end;
        DM=toeplitz(col1,row1);