function fd = div(Px,Py, options)

% div - divergence operator
%
%	fd = div(Px,Py, options);
%	fd = div(P, options);
%
%   options.bound = 'per' or 'sym'
%   options.order = 1 (backward differences)
%                 = 2 (centered differences)
%
%   Note that the div and grad operator are adjoint
%   of each other such that 
%       <grad(f),g>=<f,div(g)>
%
%   See also: grad.
%
%	Copyright (c) 2007 Gabriel Peyre

% retrieve number of dimensions
nbdims = 2;
if size(Px,1)==1 || size(Px,2)==1
    nbdims = 1;
end
if size(Px,3)>1
	if nargin>1
		options = Py;
        clear Py;
    end
    if size(Px,4)<=1
        Py = Px(:,:,2);
        Px = Px(:,:,1);
    else
        Pz = Px(:,:,:,3);
        Py = Px(:,:,:,2);
        Px = Px(:,:,:,1); 
        nbdims = 3;
    end
end

options.null = 0;
bound = getoptions(options, 'bound', 'sym');
order = getoptions(options, 'order', 1);

if strcmp(bound, 'sym')
    if order==1
        fx = Px-Px([1 1:end-1],:,:);         
        fx(1,:,:)   = Px(1,:,:);        % boundary
        fx(end,:,:) = -Px(end-1,:,:);        
        if nbdims>=2
            fy = Py-Py(:,[1 1:end-1],:);
            fy(:,1,:)   = Py(:,1,:);    % boundary
            fy(:,end,:) = -Py(:,end-1,:);
        end        
        if nbdims>=3
            fz = Pz-Pz(:,:,[1 1:end-1]);  
            fz(:,:,1)   = Pz(:,:,1);    % boundary
            fz(:,:,end) = -Pz(:,:,end-1);
        end
    else
        fx = (Px([2:end end],:,:)-Px([1 1:end-1],:,:))/2;
        fx(1,:,:)   = +Px(2,:,:)/2+Px(1,:,:);   % boundary
        fx(2,:,:)   = +Px(3,:,:)/2-Px(1,:,:);
        fx(end,:,:) = -Px(end,:,:)-Px(end-1,:,:)/2;
        fx(end-1,:,:) = Px(end,:,:)-Px(end-2,:,:)/2;
        if nbdims>=2
            fy = (Py(:,[2:end end],:)-Py(:,[1 1:end-1],:))/2;
            fy(:,1,:)   = +Py(:,2,:)/2+Py(:,1,:);
            fy(:,2,:)   = +Py(:,3,:)/2-Py(:,1,:);
            fy(:,end,:) = -Py(:,end,:)-Py(:,end-1,:)/2;
            fy(:,end-1,:) = Py(:,end,:)-Py(:,end-2,:)/2;
        end
        if nbdims>=3
            fz = (Pz(:,:,[2:end end])-Pz(:,:,[1 1:end-1]))/2;            
            fz(:,:,1)   = +Pz(:,:,2)/2+Pz(:,:,1);   % boundary
            fz(:,:,2)   = +Pz(:,:,3)/2-Pz(:,:,1);
            fz(:,:,end) = -Pz(:,:,end)-Pz(:,:,end-1)/2;
            fz(:,:,end-1) = Pz(:,:,end)-Pz(:,:,end-2)/2;
        end
    end 
else
    if order==1
        fx = Px-Px([end 1:end-1],:,:);
        if nbdims>=2
            fy = Py-Py(:,[end 1:end-1],:);
        end
        if nbdims>=3
            fz = Pz-Pz(:,:,[end 1:end-1]);
        end
    else
        fx = (Px([2:end 1],:,:)-Px([end 1:end-1],:,:))/2;
        if nbdims>=2
            fy = (Py(:,[2:end 1],:)-Py(:,[end 1:end-1],:))/2;
        end
        if nbdims>=3
            fz = (Pz(:,:,[2:end 1])-Pz(:,:,[end 1:end-1]))/2;
        end
    end
end

% gather result
if nbdims==3
    fd = fx+fy+fz;
elseif nbdims==2
    fd = fx+fy;
else
    fd = fx;
end