1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
## Copyright (C) 2000-2013 Kai Habel
## Copyright (C) 2007 David Bateman
##
## This file is part of Octave.
##
## Octave 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 3 of the License, or (at
## your option) any later version.
##
## Octave 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 Octave; see the file COPYING. If not, see
## <http://www.gnu.org/licenses/>.
## -*- texinfo -*-
## @deftypefn {Function File} {@var{d} =} del2 (@var{M})
## @deftypefnx {Function File} {@var{d} =} del2 (@var{M}, @var{h})
## @deftypefnx {Function File} {@var{d} =} del2 (@var{M}, @var{dx}, @var{dy}, @dots{})
##
## Calculate the discrete Laplace
## @tex
## operator $( \nabla^2 )$.
## @end tex
## @ifnottex
## operator.
## @end ifnottex
## For a 2-dimensional matrix @var{M} this is defined as
## @tex
## $$d = {1 \over 4} \left( {d^2 \over dx^2} M(x,y) + {d^2 \over dy^2} M(x,y) \right)$$
## @end tex
## @ifnottex
##
## @example
## @group
## 1 / d^2 d^2 \
## D = --- * | --- M(x,y) + --- M(x,y) |
## 4 \ dx^2 dy^2 /
## @end group
## @end example
##
## @end ifnottex
## For N-dimensional arrays the sum in parentheses is expanded to include second
## derivatives over the additional higher dimensions.
##
## The spacing between evaluation points may be defined by @var{h}, which is a
## scalar defining the equidistant spacing in all dimensions. Alternatively,
## the spacing in each dimension may be defined separately by @var{dx},
## @var{dy}, etc. A scalar spacing argument defines equidistant spacing,
## whereas a vector argument can be used to specify variable spacing. The
## length of the spacing vectors must match the respective dimension of
## @var{M}. The default spacing value is 1.
##
## At least 3 data points are needed for each dimension. Boundary points are
## calculated from the linear extrapolation of interior points.
##
## @seealso{gradient, diff}
## @end deftypefn
## Author: Kai Habel <kai.habel@gmx.de>
function D = del2 (M, varargin)
if (nargin < 1)
print_usage ();
endif
nd = ndims (M);
sz = size (M);
dx = cell (1, nd);
if (nargin == 2 || nargin == 1)
if (nargin == 1)
h = 1;
else
h = varargin{1};
endif
for i = 1 : nd
if (isscalar (h))
dx{i} = h * ones (sz (i), 1);
else
if (length (h) == sz (i))
dx{i} = diff (h)(:);
else
error ("del2: dimensionality mismatch in %d-th spacing vector", i);
endif
endif
endfor
elseif (nargin - 1 == nd)
## Reverse dx{1} and dx{2} as the X-dim is the 2nd dim of the ND array
tmp = varargin{1};
varargin{1} = varargin{2};
varargin{2} = tmp;
for i = 1 : nd
if (isscalar (varargin{i}))
dx{i} = varargin{i} * ones (sz (i), 1);
else
if (length (varargin{i}) == sz (i))
dx{i} = diff (varargin{i})(:);
else
error ("del2: dimensionality mismatch in %d-th spacing vector", i);
endif
endif
endfor
else
print_usage ();
endif
idx = cell (1, nd);
for i = 1: nd
idx{i} = ":";
endfor
D = zeros (sz);
for i = 1: nd
if (sz(i) >= 3)
DD = zeros (sz);
idx1 = idx2 = idx3 = idx;
## interior points
idx1{i} = 1 : sz(i) - 2;
idx2{i} = 2 : sz(i) - 1;
idx3{i} = 3 : sz(i);
szi = sz;
szi (i) = 1;
h1 = repmat (shiftdim (dx{i}(1 : sz(i) - 2), 1 - i), szi);
h2 = repmat (shiftdim (dx{i}(2 : sz(i) - 1), 1 - i), szi);
DD(idx2{:}) = ((M(idx1{:}) - M(idx2{:})) ./ h1 + ...
(M(idx3{:}) - M(idx2{:})) ./ h2) ./ (h1 + h2);
## left and right boundary
if (sz(i) == 3)
DD(idx1{:}) = DD(idx3{:}) = DD(idx2{:});
else
idx1{i} = 1;
idx2{i} = 2;
idx3{i} = 3;
DD(idx1{:}) = (dx{i}(1) + dx{i}(2)) / dx{i}(2) * DD (idx2{:}) - ...
dx{i}(1) / dx{i}(2) * DD (idx3{:});
idx1{i} = sz(i);
idx2{i} = sz(i) - 1;
idx3{i} = sz(i) - 2;
DD(idx1{:}) = (dx{i}(sz(i) - 1) + dx{i}(sz(i) - 2)) / ...
dx{i}(sz(i) - 2) * DD (idx2{:}) - ...
dx{i}(sz(i) - 1) / dx{i}(sz(i) - 2) * DD (idx3{:});
endif
D += DD;
endif
endfor
D = D ./ nd;
endfunction
|