当多个输出分配给主程序中的同一个变量时,Fortran 子例程 NaN 问题
Fortran subroutine NaN issue when multiple outputs are assigned to the same variable in the main program
我倾向于使用临时变量来“忽略”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
将同一个变量赋给子程序中可能改变的多个实参是非法的。这称为别名,在 Fortran 中是被禁止的。因为您的代码不符合标准,所以输出可以是任何内容。
每个参数使用不同的变量。
我倾向于使用临时变量来“忽略”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
将同一个变量赋给子程序中可能改变的多个实参是非法的。这称为别名,在 Fortran 中是被禁止的。因为您的代码不符合标准,所以输出可以是任何内容。
每个参数使用不同的变量。