--- a
+++ b/del2.m
@@ -0,0 +1,115 @@
+## Copyright (C) 2000  Kai Habel
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{D} =} del2 (@var{M})
+## @deftypefnx {Function File} {@var{D} =}del2 (@var{M}, @var{dx}, @var{dy})
+##
+## @var{D} = del2 (@var{M}) calculates the Laplace Operator
+##
+## @example
+##       1    / d^2            d^2         \
+## D  = --- * | ---  M(x,y) +  ---  M(x,y) | 
+##       4    \ dx^2           dx^2        /
+## @end example
+##
+## Spacing values for x and y direction can be provided by the
+## @var{dx}, @var{dy} parameters, otherwise the spacing is set to 1.
+## A scalar value specifies an equidistant spacing.
+## A vector value can be used to specify a variable spacing. The length
+## must match the respective dimension of @var{M}.
+##
+## You need at least 3 data points for each dimension.
+## Boundary points are calculated with y0'' and y2'' respectively.
+## For interior point y1'' is taken. 
+##
+## @example
+## y0''(i) = 1/(dy^2) *(y(i)-2*y(i+1)+y(i+2)).
+## y1''(i) = 1/(dy^2) *(y(i-1)-2*y(i)+y(i+1)).
+## y2''(i) = 1/(dy^2) *(y(i-2)-2*y(i-1)+y(i)).
+## @end example
+##
+## @end deftypefn
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function D = del2 (M, dx, dy)
+  
+  if ((nargin < 1) || (nargin > 3))
+    usage ("del2(M,dx,dy)");
+  elseif (nargin == 1)
+    dx = dy = 1;
+  elseif (nargin == 2)
+    dy = 1;
+  endif
+
+  if (!is_matrix (M))
+    error ("first argument must be a matrix");
+  else
+    if is_scalar (dx)
+      dx = dx * ones (1, columns(M) - 1);
+    else
+      if !(length(dx) == columns(M))
+        error ("columns of M must match length of dx")
+      else
+        dx = diff (dx);
+      endif
+    endif
+
+    if (is_scalar (dy))
+      dy = dy * ones (rows (M) - 1, 1);
+    else
+      if !(length(dy) == rows(M))
+        error ("rows of M must match length of dy")
+      else
+        dy = diff (dy);
+      endif
+    endif
+  endif
+
+  [mr,mc] = size (M);
+  D = zeros (size (M));
+
+  if (mr >= 3)  
+    ## x direction
+    ## left and right boundary
+    D(:, 1) = (M(:, 1) .- 2 * M(:, 2) + M(:, 3)) / (dx(1) * dx(2));
+    D(:, mc) = (M(:, mc - 2) .- 2 * M(:, mc - 1) + M(:, mc))\
+      / (dx(mc - 2) * dx(mc - 1));
+
+    ## interior points
+    D(:, 2:mc - 1) = D(:, 2:mc - 1)\
+      + (M(:, 3:mc) .- 2 * M(:, 2:mc - 1) + M(:, 1:mc - 2))\
+      ./ kron (dx(1:mc -2 ) .* dx(2:mc - 1), ones (mr, 1));
+  endif
+
+  if (mc >= 3)
+    ## y direction
+    ## top and bottom boundary
+    D(1, :) = D(1,:)\
+      + (M(1, :) .- 2 * M(2, :) + M(3, :)) / (dy(1) * dy(2));
+    D(mr, :) = D(mr, :)\
+      + (M(mr - 2,:) .- 2 * M(mr - 1, :) + M(mr, :))\
+      / (dy(mr - 2) * dx(mr - 1));
+    
+    ## interior points
+    D(2:mr - 1, :) = D(2:mr - 1, :)\
+      + (M(3:mr, :) .- 2 * M(2:mr - 1, :) + M(1:mr - 2, :))\
+      ./ kron (dy(1:mr - 2) .* dy(2:mr - 1), ones (1, mc));
+  endif
+
+  D = D ./ 4;
+endfunction