Matrix 基本高斯消去法解算器产生错误结果
我是Fortran的新手,我需要写一个高斯消去码来解4x4矩阵。下面的代码返回了错误的结果,我无法调试该问题。如果你能帮助我,我将不胜感激Matrix 基本高斯消去法解算器产生错误结果,matrix,fortran,gaussian,solver,Matrix,Fortran,Gaussian,Solver,我是Fortran的新手,我需要写一个高斯消去码来解4x4矩阵。下面的代码返回了错误的结果,我无法调试该问题。如果你能帮助我,我将不胜感激 common /grid/ A(100,100), NEQ, C(100), X(100) open(10, file="NEQ.txt", status='unknown') read(10,*) NEQ close (10) open(12, file="C1.txt", status='u
common /grid/ A(100,100), NEQ, C(100), X(100)
open(10, file="NEQ.txt", status='unknown')
read(10,*) NEQ
close (10)
open(12, file="C1.txt", status='unknown')
do i=1,NEQ
read(12,*) C(i)
enddo
close (12)
open(11, file="A1.txt", status='unknown')
do i=1,NEQ
read(11,*) (A(i,k), k=1,NEQ)
enddo
close (11)
call SOL
open(13, file="X.txt", status='unknown')
do i=1,NEQ
write(13,*) X(i)
enddo
close (13)
stop
end
subroutine SOL
common /grid/ A(100,100), NEQ, C(100), X(100)
c Forward Reduction Phase:
do 10 K=2,NEQ
do 10 I=K,NEQ
R=A(I,K-1)/A(K-1,K-1)
C(I)=C(I)-R*C(K-1)
do 10 J=K-1,NEQ
10 A(I,J)=A(I,J)-R*A(K-1,J)
c Back Substitution Phase:
X(NEQ)=C(NEQ)/A(NEQ,NEQ)
do 30 K=NEQ-1,1,-1
X(K)=C(K)
do 20 J=K+1,NEQ
20 X(K)=X(K)-A(K,J)*X(J)
30 X(K)=X(K)/A(K,K)
return
end
在我的例子中,NEQ作为4从文本文件中读取 我的A1.txt是:
18, -6, -6, 0
-6, 12, 0, -6
-6, 0, 12, -6
0, -6, -6, 18
C1.txt是:
60
0
20
0
生成的X矩阵为:
8.3333330
6.6666665
8.3333321
4.9999995
而不是:
13.13
14.17
15.83
15.00
正如Vladimir F所评论的,如果您必须编写任何新代码,那么至少使用Fortran 90是非常有帮助的。它提供了比Fortran 77更好的选项来保持代码的结构化和组织性(以及可读性)。我想补充一点,
implicit none
也是减少错误的宝贵语句
也就是说,下面是一个例子,说明您的算法在Fortran 90中可能是什么样子的(我将其作为函数编写):
这只会让我想知道为什么您认为您的结果
X=[8.33,6.67,8.33,5.00]
不正确?这是正确的解决方案,您可以通过将矩阵A与之相乘来验证:matmul(A,X)
应该(几乎)等于C
正如Vladimir F所评论的,如果您必须编写任何新代码,至少使用Fortran 90是非常有用的。它提供了比Fortran 77更好的选项来保持代码的结构化和组织性(以及可读性)。我想补充一点,implicit none
也是减少错误的宝贵语句
也就是说,下面是一个例子,说明您的算法在Fortran 90中可能是什么样子的(我将其作为函数编写):
这只会让我想知道为什么您认为您的结果
X=[8.33,6.67,8.33,5.00]
不正确?这是正确的解决方案,您可以通过将矩阵A与之相乘来验证:matmul(A,X)
应该(几乎)等于C
如果您是新手,我真的建议您为现代Fortran风格找到一个很好的参考。忘记普通和数据,结束前的返回是多余的。使用“结束-做”和“不做”标签。即使在循环中使用标签,也应至少使用“继续”将其放置在直线上。学习为你的子程序和函数使用模块。如果你是新手,我真的建议你为现代Fortran风格找到一个好的参考。忘记普通和数据,结束前的返回是多余的。使用“结束-做”和“不做”标签。即使在循环中使用标签,也应至少使用“继续”将其放置在直线上。学习为子程序和函数使用模块。
function gaussian_elimination(A, C) result(X)
implicit none
real, intent(inout) :: C(:), A(size(C), size(C))
real :: X(size(C))
real :: R(size(C))
integer :: i, j, neq
neq = size(C)
! Forward reduction, only two loops since reduction is now row by row
do i = 1, neq
R = A(:,i)/A(i,i)
do j = i+1, neq
A(j,:) = A(j,:) - R(j)*A(i,:)
C(j) = C(j) - R(j)*C(i)
enddo
enddo
! Back substitution, only one loop
do i = neq, 1, -1
x(i) = (C(i) - sum(A(i, i+1:) * x(i+1:))) / A(i,i)
enddo
end function gaussian_elimination