我用一侧诺依曼边界条件求解泊松方程的代码有什么问题?

计算科学 matlab 有限差分 泊松
2021-12-08 18:27:59

我编写了一个 Matlab 代码,用于在上求解二维泊松方程上具有诺伊曼边界条件, 并且其他边界条件是狄利克雷,我使用了有限差分方法。我的代码如下:uxx+uyy+f(x,y)=0[a,b]×[c,d]x=b

function [u,err] = poissonFDM(a,b,c,d,j1,j2,fun,g,typebound,bound,uex,nit)
dltx = (b - a)/(j1+1); dlty = (d - c)/(j2+1);
switch typebound 
    case 'Neumann'
        dim = (j1+1)*j2;
        D = speye(j1+1);
        T = ones(j1+1,1); 
        T = [T,-4*T,T]; T(j1,1) = 2*T(j1,1);
        T = spdiags(T,[-1;0;1],j1+1,j1+1);
        A1 = D;A = T;
        for i = 1 :((j2)- 2)
             A = blkdiag(A,T);
             A1 = blkdiag(A1,D);
        end
        A = blkdiag(A,T);
        A(1:(j1+1)*(j2-1),j1+2:(j1+1)*j2) = A(1:(j1+1)*(j2-1),j1+2:(j1+1)*j2) + A1;
        A(j1+2:(j1+1)*j2,1:(j1+1)*(j2-1)) = A(j1+2:(j1+1)*j2,1:(j1+1)*(j2-1)) + A1;
        h = max(dltx,dlty);
        xh = (a:dltx:b); yh = (c:dlty:d)';
        boundL = g(a,yh);
        boundB = g(xh,c);boundU = g(xh,d);
        gR = bound(b,yh);
        k = 1;
        v = zeros(dim,1);f = zeros(dim,1);Uex = zeros((j1+1)*j2,1);
        for s = 1:j2
             for r = 1:(j1+1)
             f(r,s) = fun(r*dltx + a,s*dlty + c);
                if(nargin == 12)
                    Uex(k) = uex(r*dltx+a,s*dlty+c);
                end
             v(k) = -(h^2)*f(r,s);   
             k = k + 1;
             end
        end
        %Bottom Border     
        v(1:j1) = v(1:j1) - boundB(2:j1+1)';
        v(j1+1) = v(j1+1) - gR(1);
        %Left Border
        v(1:j1:j1*j2 - j1 + 1) = v(1:j1:j1*j2 - j1 + 1) - boundL(2:j2+1);
        %Right Border
        v(j1+1:j1+1:(j1+1)*j2) = v(j1+1:j1+1:(j1+1)*j2) - 2*h*gR(2:j2+1);
        %Up Border
        v((j1+1)*j2-j1:(j1+1)*j2 -1) = v((j1+1)*j2-j1:(j1+1)*j2-1) - boundU(2:j1+1)';
        v((j1+1)*j2)= v((j1+1)*j2 ) - gR(j2+2);
        %solving linear system with conjugate gradiant
        %U = conjgrad(A,v);
        U = A\v;
        %err = U - Uex;
end 
end

我怀疑我的代码的准确性,我想。当我用这个测试我的代码时:u=sin(x+y)

u = poissonFDM(0,pi,0,pi,11,11,@(x,y)2*sin(x+y),@(x,y)sin(x+y),'Neumann',@(x,y)cos(x+y),@(x,y)sin(x+y));
surf(u)

所以图表将是这样的: 在此处输入图像描述

的图相去甚远我的代码有什么问题?关于我使用的方法,我应该说我用中心有限差分公式逼近所有导数!有人可以帮助我吗?u=sin(x+y)

2个回答

目前还不清楚问题是从什么开始的。为什么你怀疑你的解决方案的准确性?如果将数值结果代入控制方程,是否返回零残差?中央差异实现应该可以解决这个问题,当然边界除外。

尝试简化您的问题以找出错误:删除强制项以便求解拉普拉斯方程,简化边界条件(可能是所有边上的狄利克雷),减少阶数以便求解 1D问题,等等第四个。f(x,y)

你写下的问题非常令人费解。首先,在使用用于生成输出的相同命令的同时获取相同的代码并粘贴它会产生错误。

1 - 您指定 'u'(小写字母)作为函数输出,但它在您的代码中没有使用(您只使用 'U' - 大写字母)。

2 - 当我用 'u' 代替 'U' 时——正如人们所期望的那样——我得到一个向量。这意味着我无法像您那样通过“冲浪”重现输出。请同步您的问题,以便我们了解如何提供帮助。

3 - 出于好奇,“Uex”在最内层循环计算后的确切位置使用?

4 - 似乎根本没有使用其他一些变量,但是我认为这是为了简化问题而故意这样做的......

5 - 如果您使用更简化的功能(考虑到您期望边界如何反应)用于调试目的,会不会更容易?

6 - 为什么您的代码中没有注释。这是一个不好的编程习惯,即使是一个相对简单的功能,更不用说一个查询帖子了。

综上所述,考虑监控残差(每kth迭代?),简化您的输入函数并减少 Dirichlet 的边界。一个更有用的工具是在你的函数中插入一个断点,以进一步分解你的代码并有效地调试。如果这仍然不起作用,请考虑通过在我们这边重现您的问题来解决您的问题,请:评论

祝你好运 !