我正在編寫一個程序來使用有限差分方法求解3D Schroedinger方程。我的代碼的1D和2D版本運行得很好,但在3D版本中,我發現矩陣的生成(對於那些知道QM的人,這是哈密爾頓矩陣;對於那些不知道的人,這並不重要)是最多的時間(典型的網格間隔爲幾分鐘,其他操作包括最小特徵值搜索!)。在有限差分求解器中高效地生成稀疏矩陣
我想知道是否有人對如何更有效地編寫矩陣生成有任何建議。我在下面包含了兩個版本的代碼:一個應該比較容易理解,然後是遵循MATLAB的文檔建議的第二個版本,我不應該在製作稀疏矩陣時直接對條目進行索引,而應該製作三個向量(行和列索引和它們各自的值)並從它們生成稀疏矩陣。不幸的是,後者並沒有幫助加快速度,因爲我仍然在使用一個愚蠢的三重嵌套循環,我想不出一個好辦法來避免它。
delta = 0.1e-9;
Lx = 2e-9;
x = 0:delta:Lx;
Nx = length(x);
Ly = 2e-9;
y = 0:delta:Ly;
Ny = length(y);
Lz = 2e-9;
z = 0:delta:Lz;
Nz = length(z);
map = inline('((idx_x-1) * Ny*Nz) + ((idx_y-1) * Nz) + idx_z','idx_x','idx_y','idx_z','Ny','Nz'); % define an inline helper function for mapping (x,y,z) indices to a linear index
Tsparse = sparse([],[],[],Nx*Ny*Nz, Nx*Ny*Nz, 7*(Nx-2)*(Ny-2)*(Nz-2)); % kinetic part of Hamiltonian matrix: (d^2/dx^2 + d^2/dy^2 + d^2/dz^2); NOTE: we'll have 7*(Nx-2)*(Ny-2)*(Nz-2) non-zero entries in this matrix, so we get the sparse() function to preallocate enough memory for this
for idx_x = 2:Nx-1
for idx_y = 2:Ny-1
for idx_z = 2:Nz-1
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y , idx_z , Ny, Nz)) = -6/delta^2;
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x+1,idx_y , idx_z , Ny, Nz)) = 1/delta^2;
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x-1,idx_y , idx_z , Ny, Nz)) = 1/delta^2;
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y+1, idx_z , Ny, Nz)) = 1/delta^2;
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y-1, idx_z , Ny, Nz)) = 1/delta^2;
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y , idx_z+1, Ny, Nz)) = 1/delta^2;
Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y , idx_z-1, Ny, Nz)) = 1/delta^2;
end
end
end
此代碼的矩陣僅具有非零項沿對角線7(而不是所有的在每個這些對角線的條目是非零的)。
這裏就是我嘗試的方式,是一個有點接近MATLAB的文檔如何建議創建的T矩陣代碼的版本我做:提前
delta = 0.1e-9;
Lx = 2e-9;
x = 0:delta:Lx;
Nx = length(x);
Ly = 2e-9;
y = 0:delta:Ly;
Ny = length(y);
Lz = 2e-9;
z = 0:delta:Lz;
Nz = length(z);
map = inline('((idx_x-1) * Ny*Nz) + ((idx_y-1) * Nz) + idx_z','idx_x','idx_y','idx_z','Ny','Nz'); % define an inline helper function for mapping (x,y,z) indices to a linear index
Iidx = zeros(7*(Nx-2)*(Ny-2)*(Nz-2),1); % matrix row indices
Jidx = zeros(7*(Nx-2)*(Ny-2)*(Nz-2),1); % matrix col indices
vals = zeros(7*(Nx-2)*(Ny-2)*(Nz-2),1); % matrix non-zero values, corresponding to (row,col)
cnt = 1;
for idx_x = 2:Nx-1
for idx_y = 2:Ny-1
for idx_z = 2:Nz-1
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y , idx_z , Ny, Nz)) = -6/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
vals(cnt) = -6/delta^2;
cnt = cnt + 1;
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x+1,idx_y , idx_z , Ny, Nz)) = 1/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x+1,idx_y,idx_z,Ny,Nz);
vals(cnt) = 1/delta^2;
cnt = cnt + 1;
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x-1,idx_y , idx_z , Ny, Nz)) = 1/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x-1,idx_y,idx_z,Ny,Nz);
vals(cnt) = 1/delta^2;
cnt = cnt + 1;
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y+1, idx_z , Ny, Nz)) = 1/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x,idx_y+1,idx_z,Ny,Nz);
vals(cnt) = 1/delta^2;
cnt = cnt + 1;
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y-1, idx_z , Ny, Nz)) = 1/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x,idx_y-1,idx_z,Ny,Nz);
vals(cnt) = 1/delta^2;
cnt = cnt + 1;
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y , idx_z+1, Ny, Nz)) = 1/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x,idx_y,idx_z+1,Ny,Nz);
vals(cnt) = 1/delta^2;
cnt = cnt + 1;
% Tsparse(map(idx_x,idx_y,idx_z,Ny,Nz) , map(idx_x ,idx_y , idx_z-1, Ny, Nz)) = 1/delta^2;
Iidx(cnt) = map(idx_x,idx_y,idx_z,Ny,Nz);
Jidx(cnt) = map(idx_x,idx_y,idx_z-1,Ny,Nz);
vals(cnt) = 1/delta^2;
cnt = cnt + 1;
end
end
end
Tsparse = sparse(Iidx, Jidx, vals, Nx*Ny*Nz, Nx*Ny*Nz);
感謝您的任何建議!
- dx.dy.dz
(附註:「地圖」功能用於從3D去座標系(X,Y,Z),以一維值假設我的特徵值問題H psi = E psi,其中H是哈密爾頓矩陣,而psi是矢量,E是標量。矩陣H = T + V(代碼樣本中未示出V,只有T是)被寫入例如,假設每個維度只有2個網格點,所以x = 1:1:2,y = 1:1:2,z = 1: 1:2,然後我的哈密爾頓函數以{psi(1,1,1),psi(1,1,2),psi(1,2,1),psi(1,2,2),psi (2,1,1),psi(2,1,2),psi(2,2,1),psi(2,2,2)},即它是一個8×8的矩陣,一個特徵向量psi eigs()求解器的輸出將是一個8分量矢量,然後我就可以解析了。高原肺水腫回,如果我想要一個2x2x2的矩陣)