【问题标题】:Fortran Error: 'y' argument of 'datan2' intrinsic at (1) must be REALFortran 错误:(1) 处固有的“datan2”的“y”参数必须为 REAL
【发布时间】:2018-12-20 05:21:02
【问题描述】:

我想计算 z 值作为 x:-50~50 和 y:-50~50 范围内的坐标,如下面的代码。

program test
implicit none
! --- [local entities]
      real*8            :: rrr,th,U0,amp,alp,Ndiv
      real*8            :: pi,alpR,NR,Rmin,Rmax,z
      integer           :: ir, i, j

do i=0, 50
  do j=0, 50
      th=datan2(i,j)
      pi=datan(1.d0)*4.d0
!
      Ndiv= 24.d0            !! Number of circumferential division
      alp = 90.d0/180.d0*pi  !! phase [rad]
      U0  = 11.4d0           !! average velocity
      amp = 0.5d0            !! amplitude of velocity
      Rmin = 10              !! [m] 
      Rmax = 50              !! [m]
      NR = 6.d0              !! Number of radial division
!
      rrr=dsqrt(i**2+j**2)
      ir=int((rrr-Rmin)/(Rmax-Rmin)*NR)
      alpR=2.d0*pi/dble(Ndiv)*dble(mod(ir,2))
      z=U0*(1.d0+amp*dsin(0.5d0*Ndiv*th+alp+alpR))

  write(*,*) 'i, j, z'
  write(*,*) i, j, z 
 end do
end do

stop
end program test

但我无法让它像下面的错误一样工作。我认为因为 i, j 在 datan(i,j) 中。我应该如何更改这些代码?

test.f90:10.16:

      th=datan2(i,j)
                1
Error: 'y' argument of 'datan2' intrinsic at (1) must be REAL
test.f90:21.16:

      rrr=dsqrt(i**2+j**2)
                1
Error: 'x' argument of 'dsqrt' intrinsic at (1) must be REAL

【问题讨论】:

  • 你必须弄清楚如何将整数转换为实数。
  • datan2(real(i, kind(0d0)), real(j, kind(0d0)))
  • 甚至更好 atan2(real(i, kind(0d0)), real(j, kind(0d0))) 几十年来不应该使用内部过程的特定名称 - 我希望没有人正在教这个。同样完全非标准的实数*8。
  • 我找不到合适的副本。这是一个相当琐碎的问题,我应该写一个正确的答案吗?你觉得@IanBush 怎么样?或者以某种方式标记它?
  • 如果您找不到重复的答案,请写下答案 - 如果某个地方已经隐藏了答案,则不会造成任何伤害

标签: fortran fortran90


【解决方案1】:

受@Rodrigo Rodrigues、@Ian Bush 和@Richard 的 cmets 的启发,这里建议重写来自@SW 的代码段。金

program test
    use, intrinsic :: iso_fortran_env, only : real64
    implicit none
    ! --- [local entities]
    ! Determine the kind of your real variables (select one):
    !   for specifying a given numerical precision
    integer, parameter  :: wp = selected_real_kind(15, 307)  !15 digits, 10**307 range
    !   for specifying a given number of bits
    ! integer, parameter  :: wp = real64

    real(kind=wp), parameter    :: pi = atan(1._wp)*4._wp
    real(kind=wp)               :: rrr, th, U0, amp, alp, Ndiv
    real(kind=wp)               :: alpR, NR, Rmin, Rmax, z
    integer                     :: ir, i, j

    do i = 0, 50
        do j = 0, 50
            th = atan2(real(i, kind=wp), real(j, kind=wp))
    !
            Ndiv= 24._wp             !! Number of circumferential division
            alp = 90._wp/180._wp*pi  !! phase [rad]
            U0  = 11.4_wp            !! average velocity
            amp = 0.5_wp             !! amplitude of velocity
            Rmin = 10                !! [m]
            Rmax = 50                !! [m]
            NR = 6._wp               !! Number of radial division
    !
            rrr = sqrt(real(i, kind=wp)**2 + real(j, kind=wp)**2)
            ir = int((rrr - Rmin) / (Rmax - Rmin) * NR)
            alpR = 2._wp * pi / Ndiv * mod(ir, 2)
            z = U0 * (1._wp + amp * sin(0.5_wp * Ndiv * th + alp + alpR))
    !
            write(*,*) 'i, j, z'
            write(*,*) i, j, z
        end do
    end do

    stop
end program test

具体来说,对发布的原始代码进行了以下更改:

  • 回答问题的最小改动:将integer 变量ij 转换为real 值,以便在实值函数datandsqrt 中使用它们。
  • 对内部过程使用通用名称,即sqrt 代替dsqrtatan 代替datan,以及sin 代替dsin。这种方法的一个好处是,wp 的工作精度可以在一个地方更改,而无需在代码的其他地方进行显式更改。
  • 定义real 变量的kind 并将其命名为wp。可以在此站点上找到有关该主题、其含义和后果的扩展讨论,例如 herehere。 @Steve Lionel 在他的 blog 上也有一篇深入的帖子,他的一般建议是使用 selected_real_kind
  • pi 定义为 parameter,计算其值一次,而不是在嵌套的 for 循环中重复计算相同的值。

【讨论】:

  • 狙击。好答案,+1。顺便说一句,在real(mod(ir, 2), kind=wp) 中,不需要对 real 的约定。
猜你喜欢
  • 1970-01-01
  • 2019-01-14
  • 2021-02-06
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多