【问题标题】:Fortran subroutine NaN issue when multiple outputs are assigned to the same variable in the main program将多个输出分配给主程序中的同一变量时的 Fortran 子例程 NaN 问题
【发布时间】:2020-07-19 16:50:47
【问题描述】:

我倾向于使用临时变量来“忽略” Fortran 中的一些子例程输出。由于 Fortran 在 Matlab 中没有波浪号 (~) 之类的命令,因此我必须从子例程中获取输出,但我将它们分配给具有正确大小的相同临时变量。我更喜欢让事情看起来更干净,没有实际目的。

到目前为止,多年来我没有遇到任何问题;今天,我遇到了问题。事实证明,当我将输出分配给同一个变量 (temp1) 时,C_DU 是一个全为零的矩阵,尽管它不应该如此。

我的问题是,将多个子程序输出分配给主代码中的同一个变量是不是很糟糕?为什么当我这样做时一切都突然变为零?感谢您的帮助。

下面是一个最小的工作示例:

program example
    implicit none

    real(kind=8) :: temp1(3,3)
    real(kind=8) :: temp2(3,3)
    real(kind=8) :: temp3(3,3)
    real(kind=8) :: temp4(3,3)
    real(kind=8) :: temp5(3,3)
    real(kind=8) :: r_PN_U(3)

    call r_calc(4.2d0, &
        0d0, 0d0, &
        0d0, 0d0, &
        0d0, 0d0, &
        0d0,      &
        0d0, 0d0, &
        0d0,      &
        0d0, 0d0, &
        0d0, 0d0, &
        r_PN_U, &
        temp1, temp1, temp1, temp1, temp1)

    call r_calc(4.2d0, &
        0d0, 0d0, &
        0d0, 0d0, &
        0d0, 0d0, &
        0d0,      &
        0d0, 0d0, &
        0d0,      &
        0d0, 0d0, &
        0d0, 0d0, &
        r_PN_U, &
        temp1, temp2, temp3, temp4, temp5)
end program example

subroutine r_calc(rin, &
    e,     ed,     &
    f,     fd,     &
    v,     vd,     &
    vp,            &
    w,     wd,     &
    wp,            &
    theta, thetad, &
    y_pos, z_pos, &
    r_PN_U, &
    C_DU_theta, C_DU_beta, C_DU_zeta, C_DU, C_UD)
    implicit none

    real(kind=8), intent(in) :: rin

    real(kind=8), intent(in) :: e,     ed
    real(kind=8), intent(in) :: f,     fd
    real(kind=8), intent(in) :: v,     vd
    real(kind=8), intent(in) :: vp
    real(kind=8), intent(in) :: w,     wd
    real(kind=8), intent(in) :: wp
    real(kind=8), intent(in) :: theta, thetad

    real(kind=8), intent(in) :: y_pos, z_pos

    real(kind=8), intent(out) :: r_PN_U(3)

    real(kind=8), intent(out) :: C_DU_theta(3,3)
    real(kind=8), intent(out) :: C_DU_beta (3,3)
    real(kind=8), intent(out) :: C_DU_zeta (3,3)
    real(kind=8), intent(out) :: C_DU      (3,3)
    real(kind=8), intent(out) :: C_UD      (3,3)

    real(kind=8) :: beta, zeta

    beta  = -atan(wp) ! [rad], flap down angle
    zeta  =  atan(vp) ! [rad], lead angle

    call angle2dcm(theta, beta, zeta, C_DU_theta, C_DU_beta, C_DU_zeta, C_DU)

    print *, C_DU ! gives all zero in the first call, correct values in the second call

    C_UD = transpose(C_DU)

    r_PN_U = [rin+e+f, v, w] + matmul(C_UD, [0d0, y_pos, z_pos])

end subroutine r_calc

subroutine angle2dcm(phi, theta, psi, C_phi, C_theta, C_psi, C_out)
    implicit none

    ! Calculates the direction cosine matrix in psi - theta - phi (3 - 2 - 1) order
    ! Difference from "angle2dcm" subroutine is the extra outputs

    real(kind=8), intent(in)  :: phi, theta, psi

    real(kind=8), intent(out) :: C_psi(3,3), C_theta(3,3), C_phi(3,3), C_out(3,3)

    C_phi(1,1:3) = [1d0,       0d0,      0d0]
    C_phi(2,1:3) = [0d0,  cos(phi), sin(phi)]
    C_phi(3,1:3) = [0d0, -sin(phi), cos(phi)]

    C_theta(1,1:3) = [cos(theta), 0d0, -sin(theta)]
    C_theta(2,1:3) = [       0d0, 1d0,         0d0]
    C_theta(3,1:3) = [sin(theta), 0d0,  cos(theta)]

    C_psi(1,1:3) = [ cos(psi),  sin(psi), 0d0]
    C_psi(2,1:3) = [-sin(psi),  cos(psi), 0d0]
    C_psi(3,1:3) = [      0d0,       0d0, 1d0]

    C_out = matmul(C_phi, matmul(C_theta,C_psi)) ! psi - theta - phi (3 - 2 - 1) order

end subroutine angle2dcm

【问题讨论】:

    标签: memory gfortran subroutine


    【解决方案1】:

    将同一个变量赋值为多个在子程序中可能改变的实际参数是非法的。它被称为别名,在 Fortran 中是被禁止的。因为你的代码不符合标准,所以输出可以是任何东西。

    为每个参数使用不同的变量。

    【讨论】:

    • 我不知道。谢谢您的回答。同样的情况对子程序的输入有效吗?我可以在主程序中为子程序的两个或多个不同输入使用相同的变量吗?
    • 可以,但不能更改这样的输入参数。可以使用目标和指针进行进一步控制。
    猜你喜欢
    • 1970-01-01
    • 2014-06-15
    • 2016-11-23
    • 2015-08-19
    • 2015-01-09
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多