Fortran 是否有LU分解的命令或子例程?
在MatLab中,命令lu(A)将两个矩阵L和U作为输出,即A的lu分解。我想知道Fortran中是否有一些命令执行完全相同的操作。我到处都找不到它。我发现了很多LAPACK的子程序,它们首先通过执行LU分解来求解线性系统,但出于我的目的,我需要专门执行LU分解并存储L和U矩阵Fortran 是否有LU分解的命令或子例程?,fortran,lapack,Fortran,Lapack,在MatLab中,命令lu(A)将两个矩阵L和U作为输出,即A的lu分解。我想知道Fortran中是否有一些命令执行完全相同的操作。我到处都找不到它。我发现了很多LAPACK的子程序,它们首先通过执行LU分解来求解线性系统,但出于我的目的,我需要专门执行LU分解并存储L和U矩阵 是否有一个命令或子例程以平方矩阵a作为输入,以LU分解的矩阵L和U作为输出?在Matlab中没有对应于LU的内置命令,但我们可以在LAPACK中为dgetrf编写一个简单的包装器,以便接口类似于LU,例如 module
是否有一个命令或子例程以平方矩阵a作为输入,以LU分解的矩阵L和U作为输出?在Matlab中没有对应于
LU
的内置命令,但我们可以在LAPACK中为dgetrf
编写一个简单的包装器,以便接口类似于LU
,例如
module linalg
implicit none
integer, parameter :: dp = kind(0.0d0)
contains
subroutine lufact( A, L, U, P )
!... P * A = L * U
!... http://www.netlib.org/lapack/explore-3.1.1-html/dgetrf.f.html
!... (note that the definition of P is opposite to that of the above page)
real(dp), intent(in) :: A(:,:)
real(dp), allocatable, dimension(:,:) :: L, U, P
integer, allocatable :: ipiv(:)
real(dp), allocatable :: row(:)
integer :: i, n, info
n = size( A, 1 )
allocate( L( n, n ), U( n, n ), P( n, n ), ipiv( n ), row( n ) )
L = A
call DGETRF( n, n, L, n, ipiv, info )
if ( info /= 0 ) stop "lufact: info /= 0"
U = 0.0d0
P = 0.0d0
do i = 1, n
U( i, i:n ) = L( i, i:n )
L( i, i:n ) = 0.0d0
L( i, i ) = 1.0d0
P( i, i ) = 1.0d0
enddo
!... Assuming that P = P[ipiv(n),n] * ... * P[ipiv(1),1]
!... where P[i,j] is a permutation matrix for i- and j-th rows.
do i = 1, n
row = P( i, : )
P( i, : ) = P( ipiv(i), : )
P( ipiv(i), : ) = row
enddo
endsubroutine
end module
然后,我们可以使用lu()的Matlab页面中显示的3x3矩阵测试例程:
这里请注意,
p
的逆是由它的转置(即,inv(p)=p'=转置(p)
)给出的,因为p
是(基本)置换矩阵的乘积。我添加了一种使用DOLITTLE方法计算LU的方法。MATLAB使用它来计算LU,以便更快地计算更大矩阵。算法如下。要执行该算法,必须提供以下格式的输入文件。由于该算法是一个子例程,因此可以将其添加到代码中,并在需要时调用它。算法、输入文件、输出文件如下
PROGRAM DOLITTLE
IMPLICIT NONE
INTEGER :: n
!**********************************************************
! READS THE NUMBER OF EQUATIONS TO BE SOLVED.
OPEN(UNIT=1,FILE='input.dat',ACTION='READ',STATUS='OLD')
READ(1,*) n
CLOSE(1)
!**********************************************************
CALL LU(n)
END PROGRAM
!==========================================================
! SUBROUTINES TO MAIN PROGRAM
SUBROUTINE LU(n)
IMPLICIT NONE
INTEGER :: i,j,k,p,n,z,ii,itr = 500000
REAL(KIND=8) :: temporary,s1,s2
REAL(KIND=8),DIMENSION(1:n) :: x,b,y
REAL(KIND=8),DIMENSION(1:n,1:n) :: A,U,L,TEMP
REAL(KIND=8),DIMENSION(1:n,1:n+1) :: AB
! READING THE SYSTEM OF EQUATIONS
OPEN(UNIT=2,FILE='input.dat',ACTION='READ',STATUS='OLD')
READ(2,*)
DO I=1,N
READ(2,*) A(I,:)
END DO
DO I=1,N
READ(2,*) B(I)
END DO
CLOSE(2)
DO z=1,itr
U(:,:) = 0
L(:,:) = 0
DO j = 1,n
L(j,j) = 1.0d0
END DO
DO j = 1,n
U(1,j) = A(1,j)
END DO
DO i=2,n
DO j=1,n
DO k=1,i1
s1=0
if (k==1)then
s1=0
else
DO p=1,k1
s1=s1+L(i,p)*U(p,k)
end DO
endif
L(i,k)=(A(i,k)-s1)/U(k,k)
END DO
DO k=i,n
s2=0
DO p=1,i-1
s2=s2+l(i,p)*u(p,k)
END DO
U(i,k)=A(i,k)*s2
END DO
END DO
END DO
IF(z.eq.1)THEN
OPEN(UNIT=3,FILE='output.dat',ACTION='write')
WRITE(3,*) ''
WRITE(3,*) '********** SOLUTIONS *********************'
WRITE(3,*) ''
WRITE(3,*) ''
WRITE(3,*) 'UPPER TRIANGULAR MATRIX'
DO I=1,N
WRITE(3,*) U(I,:)
END DO
WRITE(3,*) ''
WRITE(3,*) ''
WRITE(3,*) 'LOWER TRIANGULAR MATRIX'
DO I=1,N
WRITE(3,*) L(I,:)
END DO
END SUBROUTINE
这里是系统Ax=B的输入文件格式。第一行是方程的数量,接下来的三行是A矩阵元素,接下来的三行是B向量
3
10 8 3
3 20 1
4 5 15
18
23
9
输出结果如下所示:
********** SOLUTIONS *********************
UPPER TRIANGULAR MATRIX
10.000000000000000 8.0000000000000000 3.0000000000000000
0.0000000000000000 17.600000000000001 0.1000000000000009
0.0000000000000000 0.0000000000000000 13.789772727272727
LOWER TRIANGULAR MATRIX
1.0000000000000000 0.0000000000000000 0.0000000000000000
0.2999999999999999 1.0000000000000000 0.0000000000000000
0.4000000000000002 0.1022727272727273 1.0000000000000000
您可以尝试“fortran 77中的数字配方”,
有一个LU分解子程序
有许多有用的子程序,如linalg、stasistics等。您的问题是什么?为什么LAPACK的DGBTRF不合适?我的问题是:是否有一个命令或子例程,其输入为平方矩阵a,输出为LU分解的矩阵L和U?我不知道DGBTRF。我会试着用它。不过,对于我的紫色房子来说,这有点牵强。像MatLab的[L,U]=lu(A)这样简单的东西会更好,不是吗?我不认为将矩阵L和U存储在同一个数组中是一个优势(根据我刚刚查阅的文档,这就是我们所做的),这是一个优势,因为可以节省大量内存。顺便说一句,通过谷歌搜索“LAPACK LU”找到DGBTRF花了我不到一分钟的时间。@Qwertuy:一旦在单个矩阵中进行了LU分解,就可以通过其他LAPACK例程进一步单独处理三角形部分。这些例程只使用其中一个三角形部分,不访问dgbtrf输出的“二合一矩阵”的其余部分。您可以为dgetrf()或dgbtrf()编写一个类似Matlab的包装例程。实际上,我正试图写这样一个例子,但现在在ipiv(:)方面遇到了问题。。。XD每次有人写
real(kind=8)
上帝杀死一只小猫。也不要使用单位1、2、3。低数字往往用于特殊目的。通常为0、5和6,但这不是保证。
3
10 8 3
3 20 1
4 5 15
18
23
9
********** SOLUTIONS *********************
UPPER TRIANGULAR MATRIX
10.000000000000000 8.0000000000000000 3.0000000000000000
0.0000000000000000 17.600000000000001 0.1000000000000009
0.0000000000000000 0.0000000000000000 13.789772727272727
LOWER TRIANGULAR MATRIX
1.0000000000000000 0.0000000000000000 0.0000000000000000
0.2999999999999999 1.0000000000000000 0.0000000000000000
0.4000000000000002 0.1022727272727273 1.0000000000000000