【问题标题】:Receiving NaN value in Fortran app在 Fortran 应用程序中接收 NaN 值
【发布时间】:2012-01-22 03:56:57
【问题描述】:

我正在开发一个 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

其中 s(i, j) 是系统的系数矩阵,c(i) 是解向量。

【问题讨论】:

    标签: fortran nan


    【解决方案1】:

    您应该永远编写自己的例程来进行高斯消除或类似的矩阵运算。像 LAPACK 这样无处不在的软件包将拥有比您自己编写的任何代码更快、更准确的版本;在 LAPACK 中,您可以将 _getrf_getrs 组合用于一般矩阵,但如果您有带状或对称矩阵,则也有特殊的例程。您应该会发现为您的系统找到并安装优化的线性代数包非常容易。 (查找包名称,例如 atlas、flame 或 gotoblas)。

    在上面的代码中,在gaussian_solve 例程的开头附近应该有一个call gaussion_ellimination(s, c, error),您的temp_array(以及tempmw)也应该是双精度的避免从双精度矩阵中丢失精度,检查是否与浮点零完全相等是一种冒险的策略,我会检查你的输入矩阵 - 如果有任何线性退化,你将得到所有的 NaN(特别是如果它是最后一行向量与之前的任何一个都是线性退化的)。

    如果这不能解决问题,你可以使用信号 NaN 来找出问题首先出现的位置 - Force gfortran to stop program at first NaN - 但你最好只使用现有的包来处理这样的东西,这些包已经写好了多年研究线性方程组数值解的人。

    【讨论】:

      猜你喜欢
      • 2018-07-08
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 1970-01-01
      • 2017-11-04
      • 2017-08-15
      • 2015-08-22
      相关资源
      最近更新 更多