1

I want to calculate z value as the coordinate in range of x:-50~50 and y:-50~50 like below code.

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

But I couldn't make it work like below error. I think because i, j are in datan(i,j). How should I change these code?

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
SW. Kim
  • 21
  • 3
  • You've got to figure out how to **cast** integers to reals. – Richard Dec 20 '18 at 05:29
  • 1
    `datan2(real(i, kind(0d0)), real(j, kind(0d0)))` – Rodrigo Rodrigues Dec 20 '18 at 05:51
  • 5
    Even better atan2(real(i, kind(0d0)), real(j, kind(0d0))) Specific names of intrinsic procedures shouldn't have been used for decades - I hope no one is teaching this. Similarly the completely non-standard real*8. – Ian Bush Dec 20 '18 at 09:19
  • I couldn’t find a suitable duplicate. This is a rather trivial question, should I write a proper answer? What do you think @IanBush? Or flag it somehow? – Rodrigo Rodrigues Dec 20 '18 at 17:42
  • If you can't find a duplicate write an answer - no harm done if there is one already hidden somewhere – Ian Bush Dec 20 '18 at 18:14
  • If you can't find a duplicate with casual searching then though duplicates do not yet exist. I'd appreciate seeing an answer that explicitly addresses some of the points @Ian raises about old techniques. I've seen `real*8` frequently and didn't know it was antiquated. – Richard Dec 20 '18 at 20:12

1 Answers1

2

Inspired by the comments of @Rodrigo Rodrigues, @Ian Bush, and @Richard, here is a suggested rewrite of the code segment from @SW. Kim

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

Specifically, the following changes were made with respect to the original code posted:

  • Minimum change to answer the question: casting integer variables i and j to real values for using them in the real valued functions datan and dsqrt.
  • Using generic names for intrinsic procedures, i.e sqrt instead of dsqrt, atan instead of datan, and sin instead of dsin. One benefit of this approach, is that the kind of working precision wp can be changed in one place, without requiring explicit changes elsewhere in the code.
  • Defining the kind of real variables and calling it wp. Extended discussion of this topic, its implications and consequences can be found on this site, for example here and here. Also @Steve Lionel has an in depth post on his blog, where his general advice is to use selected_real_kind.
  • Defining pi as a parameter calculating its value once, instead of calculating the same value repeatedly within the nested for loops.
jbdv
  • 1,263
  • 1
  • 11
  • 18