将非线性源项添加到 2d 隐式 MATLAB 代码

计算科学 matlab 有限差分 扩散 隐式方法
2021-12-01 06:11:59

我的这段代码的时间不多了,所以任何帮助都将不胜感激。我目前正在 matlab 中编写 2D 热/扩散方程,但在添加源项时遇到问题。我的等式如下所示:

ut=αx2ux2+αy2uy2+Au(1uK)

我到处都在使用带有通量 = 0 的 Neumann bc。u 是人口数,A 是内在增长率,K 是承载能力。我正在使用的代码是我在此处找到的代码,我已对其进行编辑以使用隐式/BTCS 方法。

太感谢了。

%%
%Specifying parameters
nx=40;                           %Number of steps in space(x)
ny=50;                           %Number of steps in space(y)       
nt=50;                           %Number of time steps 
dt=0.01;                         %Width of each time step
dx=2/(nx-1);                     %Width of space step(x)
dy=2/(ny-1);                     %Width of space step(y)
x=0:dx:2;                        %Range of x(0,2) and specifying the grid points
y=0:dy:2;                        %Range of y(0,2) and specifying the grid points
u=zeros(nx,ny);                  %Preallocating u
un=zeros(nx,ny);                 %Preallocating un
visx = 2;                        %Diffusion coefficient/viscocity
visy = 2;                        %Diffusion coefficient/viscocity
% RepRateA = 0.3;                %Intrinsic Growth Rate of Population
% CarCapK = 1.7;                 %Carrying Capacity of Environment 

UnW=0;                           %x=0 Neumann B.C (du/dn=UnW)
UnE=0;                           %x=L Neumann B.C (du/dn=UnE)
UnS=0;                           %y=0 Neumann B.C (du/dn=UnS)
UnN=0;                           %y=L Neumann B.C (du/dn=UnN)

%%
%Initial Conditions
for i=1:nx
    for j=1:ny
        if ((0.5<=y(j))&&(y(j)<=1.5)&&(0.5<=x(i))&&(x(i)<=1.5))
            u(i,j)=2;
        else
            u(i,j)=0;
        end
    end
end

%%
%B.C vector
bc=zeros(nx-2,ny-2);

bc(1,:)=-UnW/dx;       %Neumann B.Cs
bc(nx-2,:)=UnE/dx;     %Neumann B.Cs
bc(:,1)=-UnS/dy;       %Neumann B.Cs
bc(:,nx-2)=UnN/dy;     %Neumann B.Cs

%B.Cs at the corners:
bc=visx*dt*bc+visy*dt*bc;

%Calculating the coefficient matrix for the implicit scheme
Ex=sparse(2:nx-2,1:nx-3,1,nx-2,nx-2);
% Ax=Ex+Ex'-2*speye(nx-2);
Ax(1,1)=-1; 
Ax(nx-2,nx-2)=-1;                 %Neumann B.Cs
Ey=sparse(2:ny-2,1:ny-3,1,ny-2,ny-2);
% Ay=Ey+Ey'-2*speye(ny-2);
Ay(1,1)=-1; 
Ay(ny-2,ny-2)=-1;                 %Neumann B.Cs
A=kron(Ay/dy^2,speye(nx-2))+kron(speye(ny-2),Ax/dx^2);
D=speye((nx-2)*(ny-2))-visx*dt*A-visy*dt*A;
%%
%Calculating the field variable for each time step
i=2:nx-1;
j=2:ny-1;

for it=0:nt
    un=u;
    h=surf(x,y,u','EdgeColor','none');       %plotting the field variable
    shading interp
    axis ([0 2 0 2 0 2])
    title({['2-D Diffusion with alphax = ',num2str(visx)];['2-D Diffusion with alphay = ',num2str(visy)];['time (\itt) = ',num2str(it*dt)]})
    xlabel('Spatial co-ordinate (x) \rightarrow')
    ylabel('{\leftarrow} Spatial co-ordinate (y)')
    zlabel('Transport property profile (u) \rightarrow')
    drawnow; 
    refreshdata(h)

    %Implicit method:
    U=un;
    U(1,:)=[];
    U(end,:)=[];
    U(:,1)=[];
    U(:,end)=[];
    U=reshape(U+bc,[],1);
    U=D\U;
    U=reshape(U,nx-2,ny-2);
    u(2:nx-1,2:ny-1)=U;
%Neumann:
    u(1,:)=RepRateA*u(2,:)*(1-u(2,:).'/CarCapK)-UnW*dx;
    u(nx,:)=RepRateA*u(nx-1,:)*(1-u(nx-1,:).'/CarCapK)+UnE*dx;
    u(:,1)=RepRateA*u(:,2).'*(1-u(:,2)/CarCapK)-UnS*dy;
    u(:,ny)=RepRateA*u(:,ny-1).'*(1-u(:,ny-1)/CarCapK)+UnN*dy;
end
1个回答

您可以通过两种方式解决您的问题:显式隐式

如果您想明确地解决您的系统,那么解决方案非常简单:您要解决的唯一术语是ui+1时间导数中的项。所有其他实例u是已知量(ui),这意味着它们可以放在 RHS 上——因为它们是已知的!为了确保数值稳定性,时间步长的大小应该足够小,使得uiui+1是小。在某些情况下,小的定义并非微不足道。大多数关于 PDE 的教科书将为您提供有关 PDE 显式求解器稳定意味着什么的更多信息。如果您真的想变得花哨,您可以及时将您的 PDE 设置为 ODE 系统,并使用 Matlab 提供的 ODE 求解器之一(例如ode45ode15等)。这具有使用自适应时间步长的额外好处,因为这些 Matlab 例程能够根据误差测量计算时间步长的大小。

如果你想隐式求解你的方程,那么你就会进入非线性PDE 的世界,这需要在每个时间步内都有一个非线性求解器。当使用相同大小的时间步时,这比显式求解器更昂贵然而,隐式求解器通常比显式求解器更稳定,有时可以保证使用更大的时间步来加速求解器。我注意到您在上面的代码中隐含地写道:如果您决定这样做,那么您需要为您的问题编写一个非线性求解器。


一个相当简单的非线性隐式求解器被称为Newton-Raphson 方法,它可能对您的问题有用。

如果您不想实现非线性隐式求解器,您可能会决定实现一种混合方法,其中隐式处理所有线性显式处理非线性什么最适合解决您的问题只能通过更仔细地查看有关该主题或实验的文献来确定。由于您已经在使用 BTCS 方法,我建议您通过将源术语明确包含到 RHS 中来扩展它。这将导致您的源术语在时间上出现“滞后”,但对于您的问题可能是合理的。