本文介绍了Fortran错误:(1)固有的'datan2'的'y'参数必须为REAL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想像下面的代码那样,将x值作为x:-50〜50和y:-50〜50范围内的坐标来计算.
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
但是我无法使它像下面的错误一样工作.我认为是因为i,j在datan(i,j)中.我应该如何更改这些代码?
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
推荐答案
受@Rodrigo Rodrigues,@ Ian Bush和@Richard的评论的启发,这里建议重写@SW中的代码段.金
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:
- 对问题的最小更改:将
integer
变量i
和j
转换为real
值,以便在实值函数datan
和dsqrt
中使用它们. - 为内在过程使用通用名称,即
sqrt
代替dsqrt
,atan
代替datan
和sin
代替dsin
.这种方法的一个好处是,可以在一个地方更改工作精度wp
的类型,而无需在代码中的其他地方进行显式更改. - 定义
real
变量的kind
并将其命名为wp
.可以在此站点上找到对该主题及其含义和后果的详细讨论,例如,此处和此处. @Steve Lionel还在他的博客,他的一般建议是使用selected_real_kind
. - 将
pi
定义为parameter
一次,而不是在嵌套的for循环中重复计算相同的值.
- Minimum change to answer the question: casting
integer
variablesi
andj
toreal
values for using them in the real valued functionsdatan
anddsqrt
. - Using generic names for intrinsic procedures, i.e
sqrt
instead ofdsqrt
,atan
instead ofdatan
, andsin
instead ofdsin
. One benefit of this approach, is that the kind of working precisionwp
can be changed in one place, without requiring explicit changes elsewhere in the code. - Defining the
kind
ofreal
variables and calling itwp
. 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 useselected_real_kind
. - Defining
pi
as aparameter
calculating its value once, instead of calculating the same value repeatedly within the nested for loops.
这篇关于Fortran错误:(1)固有的'datan2'的'y'参数必须为REAL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!