反转奇异矩阵(拉普拉斯算子反拉普拉斯算子)

时间:2017-06-21 12:32:49

标签: matlab matrix fortran octave lapack

我正在将用Octave / Matlab编写的二维CFD代码移植到fortran。域是周期性的,因此该方案基于FT。以下矩阵,'laplacian':

  

0 -1 -4 -9 -4 -1

     

-1 -2 -5 -10 -5 -2

     

-4 -5 -8 -13 -8 -5

     

-9 -10 -13 -18 -13 -10

     

-4 -5 -8 -13 -8 -5

     

-1 -2 -5 -10 -5 -2

代表6乘6网格上FT的拉普拉斯算子。我想要逆矩阵,即使拉普拉斯算子是奇异的。在matlab / octave中,'inv(laplacian)'返回所有'Inf',但是'1./laplacian'返回正确的答案(尽管是(1,1)元素,返回为Inf,必须设置为零)。

问题是如何使用LAPACK翻译第二个表单。我通常的矩阵求逆序列'DGETRF / DGETRI'失败,信息= 4,毫不奇怪。还有其他二十个DxxTRF。有谁知道什么可能有机会做Octave的工作?

1 个答案:

答案 0 :(得分:2)

如果你正在做我认为你的事情,那么你想要用不同的系数乘以傅立叶变换的不同波数,这些系数是从拉普拉斯算子的特征值导出的。

这样的东西
lambda(kx, ky, kz) = (kx**2 + ky**2 + kz**2)

注意“矩阵”中的1,4和9。它们是这些正方形kx**2

这不是矩阵求逆,实际上只是将1.0除以以表格形式写入的数字。该表看起来像一个矩阵,因为您的代码是2D,因此您只有lambda(kx, ky)

拉普拉斯算子的整个实际矩阵将非常大(N倍N,其中N = nx*ny在2D中,N = nx*ny*nz在3D中)并且将具有lambda s在对角线上,其他地方都是零。逆矩阵在对角线上具有1./labda s。所以你的操作在某种意义上是矩阵求逆,但与你想的不同。

你做的是

FT(kx,ky,kz) = FT(kx,ky,kz) / (kx**2 + ky**2 + kz**2)

也可以写成

FT = FT * inv_laplacian

,其中

inv_laplacian = 1. / laplacian

其中laplacian是系数(特征值)数组。

这不是矩阵求逆,它只是将数字除以1.0。

现在,用0特征值做什么?如果你没有启用浮点异常捕获,我建议你不要启用它们,那么你只需执行:

 FT = FT * inv_laplacian

因为inv_laplacian(0,0,0)为0,所以FT(0,0,0)除以0并且未定义(NaN或类似)。您可以将其设置为您想要的任何内容。 FT(0,0,0)的含义是你的字段的平均值,它是任意的。只做

 FT(0,0,0) = 0 !or any number you want

就是这样。

BTW我在现实世界的科学代码中看到了极端的做法,例如:

for i =0, nkx-1
  for j =0, nkx-1
    for k =0, nkx-1
      FT(i, j, k) = FT(i, j, k) / (cos(i*ax) + cos(j*ay) + cos(k*az)
    end 
  end
end

需要AGES来计算。它与你的情况非常相似,你的特征值不是余弦而是正方形。

关键是系数在时间上是恒定的并且是可分离的。

可以计算一次:

lambdax(i) = i**2 !or cos(ax*i)
lambday(i) = j**2 !or cos(ay*j)
lambdaz(i) = k**2 !or cos(az*k)

然后再做

FT(kx,ky,kz) = FT(kx,ky,kz) / (lambdax(kx) + lambday(ky) + lambdaz(kz))

您可以查看我的快速泊松求解器PoisFFT的源代码,以查看示例https://github.com/LadaF/PoisFFT/blob/master/src/poisfft-solvers-inc.f90并找到合适的边界条件。您的案例可能是第152行的PoisFFT_Solver2D_FullPeriodic。