Matlab 反转奇异矩阵(拉普拉斯矩阵到逆拉普拉斯矩阵)

Matlab 反转奇异矩阵(拉普拉斯矩阵到逆拉普拉斯矩阵),matlab,matrix,fortran,octave,lapack,Matlab,Matrix,Fortran,Octave,Lapack,我正在将一个用Octave/Matlab编写的2d CFD代码移植到fortran。该域是周期性的,因此该方案基于FT。以下矩阵为“拉普拉斯矩阵”: 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./lap

我正在将一个用Octave/Matlab编写的2d CFD代码移植到fortran。该域是周期性的,因此该方案基于FT。以下矩阵为“拉普拉斯矩阵”:

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”返回正确答案(尽管作为Inf返回的(1,1)元素必须设置为零)


问题是如何使用LAPACK翻译第二种形式。我通常的矩阵求逆序列'DGETRF/DGETRI'失败,info=4,这并不奇怪。还有大约二十个其他的DxxTRF。有人知道什么有可能达到八度音阶吗?

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

差不多

lambda(kx, ky, kz) = (kx**2 + ky**2 + kz**2)
注意“矩阵”中的1、4和9。它们是这些方块
kx**2

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

拉普拉斯算子的整个实际矩阵将非常大(N乘以N,其中2D中的N=
nx*ny
,3D中的N=
nx*ny*nz
),并且对角线上的λ和其他地方的零都将小于code>s。逆矩阵在对角线上有
1./labda
s。所以你们的运算在某种意义上是矩阵求逆,但和你们想象的不同

你要做的是

FT(kx,ky,kz) = FT(kx,ky,kz) / (kx**2 + ky**2 + kz**2)
也可以写成

FT = FT * inv_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
就这样


顺便说一句,我在现实世界的科学代码中甚至看到过极端的做法,例如:

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
计算起来花了好长时间。这和你的情况非常相似,你的特征值不是余弦而是平方

关键是这些系数在时间上是常数,并且是可分离的

我们可以只计算一次:

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))


您可以查看我的快速泊松解算器Poisson FFT的源代码,以查看示例并找到适当的边界条件。你的例子很可能是第152行的Poissfft\u Solver2D\u FullPeriodic。

如果你在做我认为你在做的事情,那么你需要将傅里叶变换的不同波数乘以从拉普拉斯算子特征值导出的不同系数

差不多

lambda(kx, ky, kz) = (kx**2 + ky**2 + kz**2)
注意“矩阵”中的1、4和9。它们是这些方块
kx**2

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

拉普拉斯算子的整个实际矩阵将非常大(N乘以N,其中2D中的N=
nx*ny
,3D中的N=
nx*ny*nz
),并且对角线上的λ和其他地方的零都将小于code>s。逆矩阵在对角线上有
1./labda
s。所以你们的运算在某种意义上是矩阵求逆,但和你们想象的不同

你要做的是

FT(kx,ky,kz) = FT(kx,ky,kz) / (kx**2 + ky**2 + kz**2)
也可以写成

FT = FT * inv_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
就这样


顺便说一句,我在现实世界的科学代码中甚至看到过极端的做法,例如:

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
计算起来花了好长时间。这和你的情况非常相似,你的特征值不是余弦而是平方

关键是这些系数在时间上是常数,并且是可分离的

我们可以只计算一次:

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))


您可以查看我的快速泊松解算器Poisson FFT的源代码,以查看示例并找到适当的边界条件。您的案例很可能是第152行的Poissfft\u Solver2D\u FullPeriodic。

在科学计算中,您很少想反转矩阵。即使您设法获得矩阵求逆,在计算后使用它也比使用LU分解慢。最后你想解一个线性系统,不是吗?你不需要矩阵求逆,我同意弗拉基米尔的观点。不仅逆矩阵是不必要的,而且它们在数值上往往是不稳定的——原始矩阵中的微小变化可能会产生逆矩阵中的较大变化,因此舍入误差会被放大。而L-U分解是一种更好的方法。在科学计算中,你很少想反转矩阵。即使你设法得到矩阵我