我正在开发一个Fortran应用程序,用于数值求解边界值问题的二阶ODE类型:-y''+ q(x)*y = r(x).在这个应用程序中,我使用高斯消除算法来求解线性方程组并将解决方案写入文件中.但对于解决方案向量,我收到了NaN.为什么会这样?这是一些代码.
subroutine gaussian_solve(s, c, error)
double precision, dimension(:,:), intent(in out) :: s
double precision, dimension(:), intent(in out) :: c
integer :: error
if(error == 0) then
call back_substitution(s, c)
end if
end subroutine gaussian_solve
!=========================================================================================
!================= Subroutine gaussian_ellimination ===============================
subroutine gaussion_ellimination(s, c, error)
double precision, dimension(:,:), intent(in out) :: s
double precision, dimension(:), intent(in out) :: c
integer, intent(out) :: error
real, dimension(size(s, 1)) :: temp_array
integer, dimension(1) :: ksave
integer :: i, j, k, n
real :: temp, m
n = size(s, 1)
if(n == 0) then
error = -1
return
end if
if(n /= size(s, 2)) then
error = -2
return
end if
if(n /= size(s, 2)) then
error = -3
return
end if
error = 0
do i = 1, n-1
ksave = maxloc(abs(s(i:n, i)))
k = ksave(1) + i - 1
if(s(k, i) == 0) then
error = -4
return
end if
if(k /= i) then
temp_array = s(i, :)
s(i, :) = s(k, :)
s(k, :) = temp_array
temp = c(i)
c(i) = c(k)
c(k) = temp
end if
do j = i + 1, n
m = s(j, i)/s(i, i)
s(j, :) = s(j, :) - m*s(i, :)
c(j) = c(j) - m*c(i)
end do
end do
end subroutine gaussion_ellimination
!==========================================================================================
!================= Subroutine back_substitution ========================================
subroutine back_substitution(s, c)
double precision, dimension(:,:), intent(in) :: s
double precision, dimension(:), intent(in out) :: c
real :: w
integer :: i, j, n
n = size(c)
do i = n, 1, -1
w = c(i)
do j = i + 1, n
w = w - s(i, j)*c(j)
end do
c(i) = w/s(i, i)
end do
end subroutine back_substitution
Run Code Online (Sandbox Code Playgroud)
其中s(i,j)是系统的系数矩阵,c(i)是解向量.
Jon*_*rsi 10
你永远不应该为高斯消除或类似的矩阵运算编写自己的例程.像LAPACK这样无处不在的软件包将拥有比您自己编写代码的更快,更准确的版本; 在LAPACK中,你会使用_getrf和_getrs的组合作为一般的matricies,但如果你有带状或sytrictric matricies,那么也有特殊的例程.您会发现很容易为您的系统找到并安装优化的线性代数包.(寻找像atlas或flame或gotoblas这样的包名).
在上面的代码,应该大概是call gaussion_ellimination(s, c, error)你开始接近gaussian_solve常规,你temp_array(和temp和m和w)也应该是双精度,以避免您的双精度矩阵失去精度,检查精确平等浮点零是一个危险的策略,我会检查你的输入矩阵 - 如果有任何线性退化,你将获得所有NaN(特别是如果它是最后一行与任何较早的那些线性退化的行向量).
如果这不能解决问题,你可以使用信令NaN来找出问题首先出现的地方 - 强迫gfortran首先停止程序NaN - 但你最好只使用现有的包来做这样的东西,它有多年来一直研究线性方程组数值解的人写的.
| 归档时间: |
|
| 查看次数: |
1866 次 |
| 最近记录: |