Recursion 用Fortran语言模拟地球、月球和太阳的轨道

Recursion 用Fortran语言模拟地球、月球和太阳的轨道,recursion,fortran,orbital-mechanics,Recursion,Fortran,Orbital Mechanics,这已经折磨了我好几个小时了。我会尽力解释的。我知道这段代码非常糟糕,但我是Fortran新手,提高效率对我来说并不容易 我试图模拟我在标题中指定的天体运动。在移动到同向运动的坐标系之前,我将得到太阳在坐标原点,地球在x=14959787d+3米之外(我相信太阳到地球的平均距离),y=0。对于月球,我把它放在从月球到地球的距离(384400d+3米)加上从地球到太阳的距离上,因此我们基本上有一种情况,即所有行星都位于y=0线上,地球在x轴上有一个天文单位,月球离地球的距离等于地球和月球之间的距离

这已经折磨了我好几个小时了。我会尽力解释的。我知道这段代码非常糟糕,但我是Fortran新手,提高效率对我来说并不容易

我试图模拟我在标题中指定的天体运动。在移动到同向运动的坐标系之前,我将得到太阳在坐标原点,地球在x=
14959787d+3
米之外(我相信太阳到地球的平均距离),y=0。对于月球,我把它放在从月球到地球的距离(
384400d+3
米)加上从地球到太阳的距离上,因此我们基本上有一种情况,即所有行星都位于y=0线上,地球在x轴上有一个天文单位,月球离地球的距离等于地球和月球之间的距离

我试图在下面两幅图中说明这种情况以及自由体图

从那里,我定义了一个12维数组,
sol
,它保存每个物体的x和y位置和速度,使sol=(x1,y1,x2,y2,x3,y3,dx1/dt,dy1/dt,dx2/dt,dy2/dt,dx3/dt)。然后我初始化了阵列:太阳没有初始速度,地球的初始y速度等于它绕太阳的平均轨道速度,没有初始x速度,月球的初始y速度等于它绕地球的平均轨道速度,没有初始x速度

 inits(1:2) = 0d0
 inits(3) = distE
 inits(4) = 0d0
 inits(5) = distE+distM
 inits(6:9) = 0d0
 inits(10) = vE
 inits(11) = 0d0
 inits(12) = vM
 sol = inits
然后,我尝试根据以下等式将所有内容放到一个共同移动的帧中:

然后,我使用一个不同的时间步长,根据方程式进行计算:

综上所述,我使用前向Euler方法,并使用子程序从y0=y0+hf计算函数f:

subroutine q8RHS(sol)
use importants, ONLY: mSun, mEarth,mMoon, F, G
implicit none
real*8 :: distEtoS,distEtoM,distStoM
real*8,dimension(12) :: sol
integer :: i
distEtoS = SQRT((sol(3)-sol(1))**2 + (sol(4)-sol(2))**2)**3
distEtoM = SQRT((sol(5)-sol(3))**2 + (sol(6)-sol(4))**2)**3
distStoM = SQRT((sol(5)-sol(1))**2 + (sol(6)-sol(2))**2)**3
do i = 1,12    
    if (i < 7) then
        F(i) = sol(i+6)
    elseif (i < 9) then
        F(i) = G * (mEarth * (sol(i-4) - sol(i-6))/distEtoS + mMoon * (sol(i-2) - sol(i-6))/distStoM)

    elseif (i < 11) then
        F(i) =  G * mSun * (sol(i-6) - sol(i-8))/distEtoS - mMoon * G *(sol(i-4) - sol(i-6))/distEtoM
    else
        F(i) =  -G * mSun * (sol(i-6) - sol(i-10))/distStoM -G*mEarth * (sol(i-6) - sol(i-8))/distEtoM

    endif
enddo
end subroutine  
我知道有很多变量没有在这里使用,但用于其他子程序,因为这是我编写的一个有点笨拙的程序。我只知道前面的子程序和所有相关变量都运行得很好,我对它们没有异议,它们也不会干扰我所想的代码

无论如何,一旦我运行程序,时间步长立即变得巨大,然后程序在一两次迭代中完成,因为时间步长函数中的分母很快变得很小。在展示我这里的代码之前,我首先注意到地球和月球没有相互作用,月球只是朝着太阳转,而地球正常地绕着太阳转。它看起来是这样的(注意,这是一个不同的RHS子例程,不是我列出的那个,只是为了上下文):

我试着用一个固定的时间步长来观察地球和月球本身。我最终让他们“相见”(以一种有意义的方式与他们的引力场相互作用),但当月球接近地球时,它就从地球上弹射回来(我想当月球刚刚经过地球时,它就几乎比地球离太阳更近了),并不断地向外发射。我试着使用不同的时间步长,但它的时间步长非常小,一旦月球离地球足够近,一切都会减慢到一半。这是使用一个只考虑月球和地球x位置的时间步长方程。然后我试着调整时间步长,让它看起来像我所列出的那样,盯着我所画的方程看得更长,这导致了我所讨论的大量时间步长。然后我放弃了,带回了太阳的存在,这就是我在这里列出的代码。我完全被难住了。下面是我现在使用的代码的轨迹:

我的代码有什么问题?我没有正确模拟轨道的是什么?我做错了什么

更新

在一位评论员的建议下,我把
alp
缩小了。结果如下:

还有一个更放大的版本

地球被完全排斥,月亮被抛向太阳

更新2

我认为我纠正了一个错误,因为我认为关于地球欧拉函数的
q8RHS
位的符号被翻转了

        elseif (i < 11) then
        F(i) =  -G * mSun * (sol(i-6) - sol(i-8))/distEtoS + mMoon * G *(sol(i-4) - sol(i-6))/distEtoM
elseif(i<11)那么
F(i)=-G*mSun*(溶胶(i-6)-溶胶(i-8))/distEtoS+mmon*G*(溶胶(i-4)-sol(i-6))/distEtoM
因为太阳的引力应该是负的,月球的引力应该是正的。这是最新的图片

更新3

我已经意识到我对月球的初始轨道速度是错误的——它必须是它绕月球的轨道速度加上地球绕太阳的轨道速度之和。我现在的动议是:

这显然让人更放心,但我不确定地球和月球在彼此之间是否表现正常。放大,月球似乎确实在太阳轨道的左右摆动,因此如果z轴是可见的,这可能更有意义,但也可能没有意义


月球路径向地球左右移动的行为不断重复,但我不确定这在物理上是否仍然合理

你的问题是什么?您选择了哪种时间集成方案?你从哪里得到你的时间步长方程的?@VladimirF我已经更新了我的问题。基本上,我想知道为什么我没有正确地模拟轨道。我已经尽力解释了我所做的一切,所以我希望有人能指出我做错了什么。@VladimirF我将继续使用我的完整方法进行更新。@VladimirF我添加了一个部分,解释了我是如何推导Euler方法中使用的函数的。Euler方法在这方面不是很好,我会选择f
subroutine q8RHS(sol)
use importants, ONLY: mSun, mEarth,mMoon, F, G
implicit none
real*8 :: distEtoS,distEtoM,distStoM
real*8,dimension(12) :: sol
integer :: i
distEtoS = SQRT((sol(3)-sol(1))**2 + (sol(4)-sol(2))**2)**3
distEtoM = SQRT((sol(5)-sol(3))**2 + (sol(6)-sol(4))**2)**3
distStoM = SQRT((sol(5)-sol(1))**2 + (sol(6)-sol(2))**2)**3
do i = 1,12    
    if (i < 7) then
        F(i) = sol(i+6)
    elseif (i < 9) then
        F(i) = G * (mEarth * (sol(i-4) - sol(i-6))/distEtoS + mMoon * (sol(i-2) - sol(i-6))/distStoM)

    elseif (i < 11) then
        F(i) =  G * mSun * (sol(i-6) - sol(i-8))/distEtoS - mMoon * G *(sol(i-4) - sol(i-6))/distEtoM
    else
        F(i) =  -G * mSun * (sol(i-6) - sol(i-10))/distStoM -G*mEarth * (sol(i-6) - sol(i-8))/distEtoM

    endif
enddo
end subroutine  
module importants
implicit none
integer,parameter::Ndim = 3
integer:: N,N2
real*8, parameter :: G = 6.67408e-11
integer,parameter :: Nbodies = 2
integer::specific_Nbodies = 2*Nbodies
real*8,dimension(12) :: inits,sol,F
real*8 :: d_j = 778.547200d+9
real*8 :: v_j = 13.1d+3
integer :: rank = Nbodies * Ndim * 2
real*8 :: mSun = 1.989d+30    
real*8, dimension(12) :: mf
real*8 :: mJup = 1.89819d+27
real*8, parameter :: pi= DACOS(-1.d0)
real*8 :: a,P,FF
real*8 :: pJ = 374080032d0
real*8, dimension(2) :: QEcompare,QLcompare,QPcompare
real*8 :: mEarth = 5.9722d+24
real*8 :: mMoon = 7.34767309d+22
real*8 :: distE = 149597870d+3 ! Dist from sun to earth
real*8 :: distM = 384400d+3 ! Dist from earth to moon
real*8 :: distMS = 152d+9
real*8 :: vE = 29.78d+3
real*8 :: vM = 1.022d+3
end module

program exercise3
use importants
implicit none
print*,'two'
!call solve()
!call q3()
!call q4()
!call q5()
!call q5circ()
!call q6ecc()
!call q6pt2()
!call q7()
call q8()
end program

subroutine q8()
 use importants
 implicit none
 !real*8,external :: Epot,Ekin, L
 real*8,external :: fun_tstepq8
 real*8 :: tstep,time,tracker,Mtot,t
 !real*8,dimension(2) :: Etot,L1,L2
 !real*8, dimension(3,2) :: r2  
 integer :: j,i
 print*, 'Starting Q8. -------------------------------------------------------'
 inits(1:2) = 0d0
 inits(3) = distE
 inits(4) = 0d0
 inits(5) = distE+distM
 inits(6:9) = 0d0
 inits(10) = vE
 inits(11) = 0d0
 inits(12) = vM
 sol = inits
 mf = 0
 Mtot = mSun + mEarth + mMoon
 mf(1:2) = mSun/(Mtot) * mf(1:2) + mEarth/(Mtot) * sol(3:4) + mMoon/(Mtot) * sol(5:6)
 mf(3:4) = mEarth/(Mtot) * mf(3:4) + mSun/(Mtot) * sol(1:2) + mMoon/(Mtot) * sol(5:6)
 mf(5:6) = mMoon/(Mtot) * mf(5:6) + mSun/(Mtot) * sol(1:2) + mEarth/(Mtot) * sol(3:4)
 mf(7:8) = mSun/(Mtot) * mf(7:8) + mEarth/(Mtot) * sol(9:10) +  mMoon/(Mtot) * sol(11:12)
 mf(9:10) = mEarth/(Mtot) * mf(9:10) + mSun/(Mtot) * sol(7:8) + mMoon/(Mtot) * sol(11:12)
 mf(11:12) = mMoon/(Mtot) * mf(11:12) + mSun/(Mtot) * sol(7:8) + mEarth/(Mtot) * sol(9:10)
 sol = inits - mf
 print*, '---------------------------------------------------------------------'
 print*, 'Beginning fixed t timestep. '
 t = 0d0
 P = 3.154d+7
 time=0
 tracker=0
 print*, 'P understood as :', P
 open(70,file='q8.dat')
 time=0
 tracker=0
 write(70,*) sol(1),sol(2),sol(3),sol(4),sol(5),sol(6)
 do while(time.le.P)
     call q8RHS(sol)
     tstep=fun_tstepq8(sol)
     time=time+tstep
     tracker=tracker+1
     print*, tstep
     do i=1,12
       sol(i) = sol(i) + tstep * F(i)
     enddo
 write(70,*) sol(1),sol(2),sol(3),sol(4),sol(5),sol(6)

 enddo

end subroutine 
        elseif (i < 11) then
        F(i) =  -G * mSun * (sol(i-6) - sol(i-8))/distEtoS + mMoon * G *(sol(i-4) - sol(i-6))/distEtoM