Fortran NBody sim代码不会运行高年份值
节目如下 当我尝试运行代码超过80年时,问题就出现了,此时代码显然会立即“运行”,生成一个空文本文件。对于较小的时间尺度,代码运行良好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
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,我更改了存储长度的变量,这从来都不是问题所在。