我是Matlab的新手,如果这个问题很简单,请提前道歉。我有以下MatLab代码
function fdstencil(k,j)
% Compute stencil coefficients for finite difference approximation
% of k'th order derivative on a uniform grid. Print the stencil and
% dominant terms in the truncation error.
%
% j should be a vector of indices of grid points, values u(x0 + j*h)
% are used, where x0 is an arbitrary grid point and h the mesh spacing.
% This routine returns a vector c of length n=length(j) and the
% k'th derivative is approximated by
% 1/h^k * [c(1)*u(x0 + j(1)*h) + ... + c(n)*u(x0 + j(n)*h)].
% Typically j(1) <= 0 <= j(n) and the values in j are monotonically
% increasing, but neither of these conditions is required.
% The routine fdcoeffF is used to compute the coefficients.
%
% Example: fdstencil(2,-1:1);
% determines the 2nd order centered approximation of the 2nd derivative.
%
% From http://www.amath.washington.edu/~rjl/fdmbook/ (2007)
n = length(j);
if k>=n
error('*** length(j) must be larger than k')
end
c = fdcoeffF(k,0,j); % coefficients for k'th derivative
% print out stencil:
disp(' ')
disp(sprintf('The derivative u^(%i) of u at x0 is approximated by',k))
disp(' ')
disp(sprintf(' 1/h^%i * [',k))
for i=1:n-1
if j(i) < 0
disp(sprintf(' %22.15e * u(x0%i*h) + ',c(i),j(i)))
elseif j(i) == 0
disp(sprintf(' %22.15e * u(x0) + ',c(i)))
else
disp(sprintf(' %22.15e * u(x0+%i*h) + ',c(i),j(i)))
end
end
disp(sprintf(' %22.15e * u(x0+%i*h) ] ',c(n),j(n)))
% determine dominant terms in truncation error and print out:
err0 = c*(j(:).^n) / factorial(n);
err1 = c*(j(:).^(n+1)) / factorial(n+1);
if (abs(err0)) < 1e-14, err0 = 0; end % for centered approximations, expect
if (abs(err1)) < 1e-14, err1 = 0; end % one of these to be exactly 0.
disp(' ')
disp('For smooth u,')
disp(sprintf(' Error = %g * h^%i*u^(%i) + %g * h^%i*u^(%i) + ...',err0,n-k,n,err1,n-k+1,n+1))
disp(' ')
其中fdcoeffF.m定义为
function c = fdcoeffF(k,xbar,x)
% Compute coefficients for finite difference approximation for the
% derivative of order k at xbar based on grid values at points in x.
%
% This function returns a row vector c of dimension 1 by n, where n=length(x),
% containing coefficients to approximate u^{(k)}(xbar),
% the k'th derivative of u evaluated at xbar, based on n values
% of u at x(1), x(2), ... x(n).
%
% If U is a column vector containing u(x) at these n points, then
% c*U will give the approximation to u^{(k)}(xbar).
%
% Note for k=0 this can be used to evaluate the interpolating polynomial
% itself.
%
% Requires length(x) > k.
% Usually the elements x(i) are monotonically increasing
% and x(1) <= xbar <= x(n), but neither condition is required.
% The x values need not be equally spaced but must be distinct.
%
% This program should give the same results as fdcoeffV.m, but for large
% values of n is much more stable numerically.
%
% Based on the program "weights" in
% B. Fornberg, "Calculation of weights in finite difference formulas",
% SIAM Review 40 (1998), pp. 685-691.
%
% Note: Forberg's algorithm can be used to simultaneously compute the
% coefficients for derivatives of order 0, 1, ..., m where m <= n-1.
% This gives a coefficient matrix C(1:n,1:m) whose k'th column gives
% the coefficients for the k'th derivative.
%
% In this version we set m=k and only compute the coefficients for
% derivatives of order up to order k, and then return only the k'th column
% of the resulting C matrix (converted to a row vector).
% This routine is then compatible with fdcoeffV.
% It can be easily modified to return the whole array if desired.
%
% From http://www.amath.washington.edu/~rjl/fdmbook/ (2007)
n = length(x);
if k >= n
error('*** length(x) must be larger than k')
end
m = k; % change to m=n-1 if you want to compute coefficients for all
% possible derivatives. Then modify to output all of C.
c1 = 1;
c4 = x(1) - xbar;
C = zeros(n-1,m+1);
C(1,1) = 1;
for i=1:n-1
i1 = i+1;
mn = min(i,m);
c2 = 1;
c5 = c4;
c4 = x(i1) - xbar;
for j=0:i-1
j1 = j+1;
c3 = x(i1) - x(j1);
c2 = c2*c3;
if j==i-1
for s=mn:-1:1
s1 = s+1;
C(i1,s1) = c1*(s*C(i1-1,s1-1) - c5*C(i1-1,s1))/c2;
end
C(i1,1) = -c1*c5*C(i1-1,1)/c2;
end
for s=mn:-1:1
s1 = s+1;
C(j1,s1) = (c4*C(j1,s1) - s*C(j1,s1-1))/c3;
end
C(j1,1) = c4*C(j1,1)/c3;
end
c1 = c2;
end
c = C(:,end)'; % last column of c gives desired row vector
在命令窗口中,我已经定义了
j = [1 1 1 1 1; -2 -1 0 1 2; -2 -1/2 0 1/2 2; -4/3 -1/6 0 1/6 4/3; -2/3 -1/24 0 1/24 2/3]
当我参考时,
fdstencil(2,j)
(对矩阵j的二阶导数)
我收到以下错误消息 -
Error using *
Inner matrix dimensions must agree.
我不明白为什么5x5矩阵会返回此错误。我需要阅读更多教程吗?
答案 0 :(得分:1)
问题是j
以5x5开头,但它不用作此行err0 = c*(j(:).^n) / factorial(n);
中乘法的输入。术语j(:)
会将j
转换为大小为25 1
的列向量。同样,它下方的行err1 = c*(j(:).^(n+1)) / factorial(n+1);
包含相同的错误。
正确的命令是err0 = c * (j.^n) / factorial(n);
和err = c * (j.^(n+1)) / factorial(n + 1);
找到这样的问题的一个好方法是使用命令dbstop on error
停止执行任何错误并进入调试模式。