Fortran NBody sim代码不会运行高年份值

Fortran NBody sim代码不会运行高年份值,fortran,Fortran,节目如下 当我尝试运行代码超过80年时,问题就出现了,此时代码显然会立即“运行”,生成一个空文本文件。对于较小的时间尺度,代码运行良好 PROGRAM NBody IMPLICIT NONE DOUBLE PRECISION:: m(1:10), deltaR(1:3) DOUBLE PRECISION:: G, r DOUBLE PRECISION, DIMENSION(10,3):: pos, v, a0, a1 !x, y, z INTEGER:: n,i,j,k,stepsize, y

节目如下

当我尝试运行代码超过80年时,问题就出现了,此时代码显然会立即“运行”,生成一个空文本文件。对于较小的时间尺度,代码运行良好

PROGRAM NBody
IMPLICIT NONE

DOUBLE PRECISION:: m(1:10), deltaR(1:3)
DOUBLE PRECISION:: G, r
DOUBLE PRECISION, DIMENSION(10,3):: pos, v, a0, a1 !x, y, z
INTEGER:: n,i,j,k,stepsize, year, zero, length
CHARACTER(len=13):: fname !xxxyrxxpl.txt
zero = 0

m(1) = 1988500e24    !sun
m(2) = 0.33e24    !mercury
m(3) = 4.87e24    !venus
m(4) = 5.97e24    !earth
m(5) = 0.642e24    !mars
m(6) = 1898e24    !jupiter
m(7) = 568e24    !saturn
m(8) = 86.8e24    !uranus
m(9) = 102e24    !!neptune
m(10) = 0.0146e24    !pluto

!Initial POS
pos = zero
pos(2,1) = 57.9e9
pos(3,1) = 108e9
pos(4,1) = 149e9
pos(5,1) = 227e9
pos(6,1) = 778e9
pos(7,1) = 1352.6e9
pos(8,1) = 2741.3e9
pos(9,1) = 4444.5e9
pos(10,1) = 4436.8e9
!FORTRAN works column,row: (particle,x/y/z)
!Momentum is initially non-zero due to planet and velocity starting points. Figure out a solution.

!Initial velocity
v = zero
v(2,2) = 47.4e3
v(3,2) = 35e3
v(4,2) = 29.8e3
v(5,2) = 24.1e3
v(6,2) = 13.1e3
v(7,2) = 9.7e3
v(8,2) = 6.8e3
v(9,2) = 5.4e3
v(10,2) = 4.7e3

g = 6.67e-11
stepsize = 1800 !3600 = 1 hour
year = 3.154e+7

!Calculate initial values
a0 = 0
a1 = 0
do i = 1,10
    do j = 1,10
    if(i==j) cycle
    deltaR(:) = (pos(i,:)-pos(j,:))
    r = -sqrt((pos(i,1)-pos(j,1))**2+(pos(i,2)-pos(j,2))**2+(pos(i,3)-pos(j,3))**2)
    a0(i,:) = a0(i,:) + g*M(j)*deltaR*r**(-3)
    END DO
END DO

write(6,*) "Specify length in years"
read (*,*) length
write(6,*) "Specify file name (xxxYRzzPL.txt)"
read(*,*) fname

!Just above is where I call for a length in the terminal, values of 40 will work, much higher do not. I don't know the exact cut-off.


open (unit = 2, file = fname)

!Do loop over time, planet and partners to step positions
do k=0, length*year,stepsize
    write(2,*) pos
    pos = pos + v*stepsize + 0.5*a0*stepsize**2
    do i = 1,10
        do j = 1,10
        if(i==j) cycle
        deltaR(:) = (pos(i,:)-pos(j,:))
        r = -sqrt((pos(i,1)-pos(j,1))**2+(pos(i,2)-pos(j,2))**2+(pos(i,3)-pos(j,3))**2)
        a1(i,:) = a1(i,:) + G*M(j)*deltaR/r**3
        END DO
    END DO
    v = v + 0.5*(a0+a1)*stepsize
    a0=a1
    a1=0

END DO

close (2)

END PROGRAM

我怀疑这可能是变量存储的问题,但我看不出有任何问题。

在@francescalus上展开,您可能需要将整数指定为8字节,而不是默认的4字节:

integer, parameter :: c_int8 = selected_int_kind (10)
integer(kind = c_int8) :: n,i,j,k,stepsize, year, zero, length

编辑我添加了一个参数来确定64位整数的正确值。

在@francescalus上展开,您可能需要将整数指定为8字节,而不是默认的4字节:

integer, parameter :: c_int8 = selected_int_kind (10)
integer(kind = c_int8) :: n,i,j,k,stepsize, year, zero, length

EDIT我添加了一个参数来确定64位整数的正确值。

使用这样的迭代器可能是可疑的。如果运行时间足够长,即使是8字节整数也会溢出。考虑到该代码是如何设置的,我会这样做:

do iYear = 1, length
   do k = 0, year, stepsize
   ....
   enddo
enddo
内部do循环超过一年。多年来,外部的do循环。如果你想等那么久的话,用4个字节的整数就可以达到这样的千兆年

我可能也会重命名你的变量以使其更有意义。这样看起来会更好:

do iYear = 1, nYears
   do k = 0, YearLength, stepsize
   ....
   enddo
enddo

使用这样的迭代器可能是可疑的。如果运行时间足够长,即使是8字节整数也会溢出。考虑到该代码是如何设置的,我会这样做:

do iYear = 1, length
   do k = 0, year, stepsize
   ....
   enddo
enddo
内部do循环超过一年。多年来,外部的do循环。如果你想等那么久的话,用4个字节的整数就可以达到这样的千兆年

我可能也会重命名你的变量以使其更有意义。这样看起来会更好:

do iYear = 1, nYears
   do k = 0, YearLength, stepsize
   ....
   enddo
enddo

80*3.154e+7是一个相当大的整数,所以它是一个数字太大的问题?如何解决这个问题我对fortranIf还是新手如果这是唯一的问题,那么你会发现在诸如.80*3.154e+7这样的问题中讨论整数溢出是一个相当大的整数。所以这是一个数字太大的问题?如何解决这个问题我对fortranIf还是新手,如果这是唯一的问题,那么你会在以下问题中找到整数溢出的讨论。注意。。实物中的8=8可能需要有所不同。。这就是为什么强烈不建议使用直接的文字数字,并且认为它很难看的原因。看看有没有更好的选择。特别是考虑到这里我们确实知道所需的支持值,我通常在一个模块中指定不同的类型,例如int4=4,然后kind=int4。我不知道你可以用内在函数做这个,所以谢谢你的链接!这似乎不起作用,但是@Dan_Sp解决方案工作得很好。编辑:我理解为什么它不起作用,这是我的错:我没有将计数变量k更改为int8,我更改了存储长度的变量,这从来都不是问题。请注意。。实物中的8=8可能需要有所不同。。这就是为什么强烈不建议使用直接的文字数字,并且认为它很难看的原因。看看有没有更好的选择。特别是考虑到这里我们确实知道所需的支持值,我通常在一个模块中指定不同的类型,例如int4=4,然后kind=int4。我不知道你可以用内在函数做这个,所以谢谢你的链接!这似乎不起作用,但是@Dan_Sp解决方案工作得很好。编辑:我理解为什么它不起作用,这是我的错:我没有将计数变量k更改为int8,我更改了存储长度的变量,这从来都不是问题所在。