求解拉普拉斯方程的有限差分方案的实现
在这个例子中,我们将求解以下拉普拉斯方程
采用5点有限差分解方案。
创建网格
假设我们有兴趣在平面上以L形点组的形式定义的特定网格上解决问题。
In [ ]:
Pkg.add(["LinearAlgebra"])
In [ ]:
gr()
Out[0]:
首先,我们将创建一个简单的零矩阵,然后用一个填充必要的区域,还添加一个1元素的"边界"来设置Dirichlet边界条件。 功能 spy 从一组图 gr() 它非常适合可视化矩阵元素值非零的区域。
In [ ]:
10÷2
Out[0]:
In [ ]:
function lshape(N)
#N = round(Int, N/2) * 2 # убедимся, что входной параметр – четный
L = zeros(Int, N, N) # создаем массив из чисел типа Int со значением 0
# заполним нужную область единицами
L[2:N÷2, 2:N-1] .= 1
L[2:N-1, N÷2+1:N-1] .= 1
# ÷ обозначает целочисленное деление
# (! julia не позволяет индексировать векторы при помощи чисел типа Float)
# Вместо единиц, подставим номера значений в матрице
items = findall( !iszero, L )
L[items] = 1:length(items)
return L
end
G = lshape( 32 );
spy( G .> 0, markersize=3, markercolor=1 )
Out[0]:
如果我们需要对所有这些点进行编号,函数是如何做到的? numgrid 对于MATLAB平台,使用以下代码:
In [ ]:
g = lshape( 10 ) .> 10
Out[0]:
In [ ]:
g = lshape( 10 )
Out[0]:
您可以看到输入矩阵的哪些元素编号应该参与计算哪些结果。 对于5元素方案,元素1、2和5(相邻元素)参与元素1的计算。
拉普拉斯运营商
现在让我们在任意网格上加载一个定义拉普拉斯算子的函数,使用4连通域进行计算。
In [ ]:
using SparseArrays, LinearAlgebra
include( "delsq.jl" ); # Создание лапласиана
让我们使用该功能 spy 以更好地看到各个标记。
In [ ]:
L = lshape(9);
G = delsq(L);
spy( G .!= 0, colorbar=false, markersize=3, markercolor=1 )
Out[0]:
虽然稀疏矩阵的标准输出已经相当擅长显示不同值的区域。
In [ ]:
delsq( lshape(9) )
Out[0]:
而对于一个32*32的矩阵(我们将输出这个矩阵的一部分):
In [ ]:
G = lshape( 32 );
D = delsq( G );
spy( D .!= 0, colorbar=false, markersize=2, markershpe=:square, markercolor=1 )
Out[0]:
这个函数有多少个点(粗略地说,它设置了多少个计算):
In [ ]:
N = sum( G[:] .> 0 )
Out[0]:
用边界条件求解PDE
现在我们准备用Dirichlet边界条件(如果点在域内,则为1,如果在边界上,则为0)求解上述微分方程。 Julia轻松地允许您以稀疏矩阵的形式求解具有系数的线性方程组(使用[UMFPack]库(http://faculty.cse.tamu.edu/davis/suitesparse.html )-与MATLAB相同)。
In [ ]:
N = 60 # Зададим правую часть уравнения
L = lshape(N)
A = -delsq(L)
b = ones( size(A,1) ) / N^2
u = A \ b; # Решаем систему линейных уравнений
让我们绘制这个解决方案的等值线图。:
In [ ]:
U = zeros( size(L) )
U[findall(!iszero, L)] = u
contour( U, levels=8, xlimits=(0,N), ylimits=(0,N),
yflip=true, c=cgrad(:turbo, rev=true),
cbar=false, aspect_ratio=:equal )
Out[0]:
现在让我们将解输出为三维网格。:
In [ ]:
wireframe( U[1:3:end,1:3:end],
zflip=true, camera=(240,30),
fmt=:png, aspect_ratio=:equal )
Out[0]:
结论
我们在L形计算网格上求解了一个简单的方程,该方程是使用我们编写的函数设置的。 此外,由于我们使用稀疏矩阵,我们的任务应该比使用密集(常规)矩阵时更快地解决并且占用更少的内存,因此,理论上,我们有机会解决许多倍大的任务。




