Ошибка Fortran: аргумент 'y' встроенного в (1) datan2 должен быть РЕАЛЬНЫМ - PullRequest
0 голосов
/ 20 декабря 2018

Я хочу вычислить значение 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

Но я не мог заставить его работать какниже ошибка.Я думаю, потому что я, J в датане (я, 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

1 Ответ

0 голосов
/ 21 декабря 2018

Вдохновленный комментариями @Rodrigo Rodrigues, @Ian Bush и @Richard, здесь предлагается переписать сегмент кода из @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 переменных i иj до real значений для использования их в вещественных функциях datan и dsqrt.
  • Использование общих имен для внутренних процедур, то есть sqrt вместо dsqrt, atanвместо datan и sin вместо dsin.Одним из преимуществ этого подхода является то, что тип рабочей точности wp можно изменить в одном месте, не требуя явных изменений в других местах кода.
  • Определение переменных kind из real и вызовэто wp.Расширенное обсуждение этой темы, ее последствий и последствий можно найти на этом сайте, например, здесь и здесь .Также @Steve Lionel имеет подробное сообщение в своем блоге , где его общий совет - использовать selected_real_kind.
  • Определение pi как parameter, вычисляющего его значение один раз,вместо того, чтобы повторно вычислять одно и то же значение внутри вложенных циклов for.
...