Python 我的nbody轨道代码哪里出错了?(数学方面的东西?)

Python 我的nbody轨道代码哪里出错了?(数学方面的东西?),python,arrays,python-3.x,numpy,Python,Arrays,Python 3.x,Numpy,在fortran中,我的nbody代码工作得完美无缺。当我把它翻译成python时,我在某个地方搞砸了。代码仍然成功地读入了一个.txt文件中的物体,并且仍然打印出一个.txt文件,该文件记录了物体在每个时间步上的位置和速度。然而,我所有的身体似乎都被抛向了未知的世界。我知道这一点,因为当比较这些图(使用mathematica)时,我注意到我的fortran Jupiter生成的图(下面的第一幅图)是完全椭圆形的,并保持在木星预期的给定距离内,而我的python生成的图(下面的第二幅图)一直到1

在fortran中,我的nbody代码工作得完美无缺。当我把它翻译成python时,我在某个地方搞砸了。代码仍然成功地读入了一个.txt文件中的物体,并且仍然打印出一个.txt文件,该文件记录了物体在每个时间步上的位置和速度。然而,我所有的身体似乎都被抛向了未知的世界。我知道这一点,因为当比较这些图(使用mathematica)时,我注意到我的fortran Jupiter生成的图(下面的第一幅图)是完全椭圆形的,并保持在木星预期的给定距离内,而我的python生成的图(下面的第二幅图)一直到10^15的量级,这是荒谬的。我假设这是一个简单的数学修正案,但我似乎无法理解

import numpy as np
import pandas as pd
import os
import math as mt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

nbodies = int(input("Input the number of bodies:  "))
dt = int(input("Input the number of timesteps:  "))
ntimesteps = int(input("Max timestep:  "))
G = 6.6743E-11

def getFile():
    path = os.getcwd()
    global fileName
    fileName = input("What file?  ")
    inputFile = open(path + "\\" + str(fileName),"r")
    return(inputFile)

def hasNumbers(inputString):
    for char in inputString:
        if(char == '-'):
            return True
        try:
            float(char)
            return True
        except:
            return False
        
def readFile(inputFile):
    newdata = []
    data = []
    while True:
        line = inputFile.readline()
        #if the end of the file is reached
        if not line:
            break;
        rawdata = line.split(" ")
        for i in rawdata:
            if hasNumbers(i) == True:
                i = i.rstrip()
                newdata.append(i)
        if newdata:
            data.append(newdata)
        newdata = []
    inputFile.close()
    return(data)    

def emptyFile(fileName, datatype):
    path = os.getcwd()
    outfile = open(path + "\\" + fileName[:-4] + "_" + datatype + ".txt", "w")
    return(outfile)
           
inputFile = getFile()
Orbital = emptyFile(fileName, "Orbital")
nData = readFile(inputFile)
m = []
x = []
y = []
z = []
vx = []
vy = [] 
vz = []
for i in nData:
    if hasNumbers(i) == True:
        m.append(float(i[0]))
        x.append(float(i[1]))
        y.append(float(i[2]))
        z.append(float(i[3]))
        vx.append(float(i[4]))
        vy.append(float(i[5]))
        vz.append(float(i[6]))
mass = np.array(m)
xpos = np.array(x)
ypos = np.array(y)
zpos = np.array(z)
xvel = np.array(vx)
yvel = np.array(vy)
zvel = np.array(vz)
        

Fx = np.zeros(nbodies)
Fy = np.zeros(nbodies)
Fz = np.zeros(nbodies)


def CalcForce(axnew, aynew, aznew):
    axnew = np.zeros(nbodies)
    aynew = np.zeros(nbodies)
    aznew = np.zeros(nbodies)
    for i in range(nbodies):
        for j in range(nbodies): 
            if i!=j:
                xdiff = x[j] - x[i]
                ydiff = y[j] - y[i]
                zdiff = z[j] - z[i]
                r2 = (xdiff**2)+(ydiff**2)+(zdiff**2)
                C = (G*m[j]*m[i])/((r2)**(1.5))
                Fx[i] = Fx[i]+C*(xdiff)
                Fx[j] = Fx[j]-C*(xdiff)
                Fy[i] = Fy[i]+C*(ydiff)
                Fy[j] = Fy[j]-C*(ydiff)
                Fz[i] = Fz[i]+C*(zdiff)
                Fz[j] = Fz[j]-C*(zdiff)
                axnew[i] = np.divide(Fx[i],m[i])
                axnew[j] = np.divide(Fx[j],m[j])
                aynew[i] = np.divide(Fy[i],m[i])
                aynew[j] = np.divide(Fy[j],m[j])
                aznew[i] = np.divide(Fz[i],m[i])
                aznew[j] = np.divide(Fz[j],m[j])
            else:
                continue
    return axnew, aynew, aznew

axnew, aynew, aznew = CalcForce(axnew, aynew, aznew)

for k in range(ntimesteps):
    xpos = xpos + xvel * dt + 0.5 * axnew * dt**2
    ypos = ypos + yvel * dt + 0.5 * aynew * dt**2
    zpos = zpos + zvel * dt + 0.5 * aznew * dt**2
    axold = axnew
    ayold = aynew
    azold = aznew
    xvel = xvel + 0.5 * (axold + axnew) * dt
    yvel = yvel + 0.5 * (ayold + aynew) * dt
    zvel = zvel + 0.5 * (azold + aznew) * dt
    
    
    np.savetxt(Orbital, np.transpose([np.arange(1, nbodies+1), np.full(nbodies, k*dt), xpos, ypos, zpos]),fmt="%2i %20i %15.5E %15.5E %15.5E")

上面是我最新版本的python代码。当i没有If语句时,名为accelerations的“CalcForce.axnew”就起作用了=J现在没有了,我很天真为什么。当在定义之外调用时,删除它并返回尝试返回加速度只返回0

下面是复制到.txt文件的有用输入。它包括11个天体,从太阳到彗星(包括冥王星,我用它来比较时间)。这是在所有3个笛卡尔坐标系下完成的,基于每个物体的轨道倾角,总线性动量守恒

m         x         y       z     vx      vy      vz
1.988e30 -4.490e5  0.000  0.000  0.000 -1.600e1  -0.4247
3.285e23  5.790e10 0.000  0.000  0.000  4.701e4   5.772e3
4.867e24  1.080e11 0.000  0.000  0.000  3.496e4   2.077e3
5.972e24  1.494e11 0.000  0.000  0.000  2.980e4   0.000
6.390e23  2.280e11 0.000  0.000  0.000  2.399e4   0.775e3
1.898e27  7.783e11 0.000  0.000  0.000  1.306e4   0.299e3
5.683e26  1.434e12 0.000  0.000  0.000  9.671e3   0.421e3
8.681e25  2.871e12 0.000  0.000  0.000  6.799e3   0.091e3
1.024e26  4.495e12 0.000  0.000  0.000  5.427e3   0.168e3
1.309e22  7.376e12 0.000  0.000  0.000  4.532e3   1.399e3
2.200e14  5.300e12 0.000  0.000  0.000  0.951e3   0.309e3

我的fortran比较代码是

Module nbody
  integer, parameter:: n = 100
  integer:: nbodies, nTimesteps, i, k
  double precision:: m(n), x(n), y(n), z(n), vx(n), vy(n), vz(n)
  double precision:: axold(n), ayold(n), azold(n), axnew(n), aynew(n), aznew(n)
  double precision:: Fx(n), Fy(n), Fz(n)
  double precision:: dt, G = 6.6743D-11, r2, C, S = 1.989D30
  character:: infile*40, outfile*40
  character(len=20), parameter :: fmt0 = "(1X,I15)",fmt1 = "(1X,E30.10)",fmt2 = "(1X,E30.10,/)"
end module

Program Gravitas
  use nbody

  print*,'input the number of bodies'
  read*, nbodies
  print*, 'input filename'
  read*, infile
  print*, 'output filename'
  read*, outfile
  open(unit=42, file=infile, status='unknown')
  open(unit=43, file=outfile, status='unknown')

  
  read(42,*)
  Do i=1, nbodies
    read(42,*) m(i), x(i), y(i), z(i), vx(i), vy(i), vz(i)
  end do
  print*, 'input timestep(dt)'
  read*, dt
  print*, 'Tmax'
  read*, nTimesteps
  
  Do i=1, nbodies
    WRITE(43,fmt1,advance="no")real(k)*dt 
    WRITE(43,fmt0,advance="no")i 
    WRITE(43,fmt1,advance="no")x(i) 
    WRITE(43,fmt1,advance="no")y(i) 
    WRITE(43,fmt2,advance="no")z(i)   
  end do
  
  call calcforces
  
  Do k = 1, nTimesteps
    x = x + vx * dt + 0.5 * axnew * dt**2
    y = y + vy * dt + 0.5 * aynew * dt**2
    z = z + vz * dt + 0.5 * aznew * dt**2
    axold = axnew
    ayold = aynew
    azold = aznew
    call calcforces
    vx = vx + 0.5 * (axold + axnew) * dt
    vy = vy + 0.5 * (ayold + aynew) * dt
    vz = vz + 0.5 * (azold + aznew) * dt
    Do i = 1, nbodies
      WRITE(43,fmt1,advance="no")real(k)*dt 
      WRITE(43,fmt0,advance="no")i 
      WRITE(43,fmt1,advance="no")x(i) 
      WRITE(43,fmt1,advance="no")y(i) 
      WRITE(43,fmt2,advance="no")z(i) 
    end do

Subroutine calcforces
  use nbody
  Fx=0.0
  Fy=0.0
  Fz=0.0
  do i=1, nbodies
    do j=(i+1), (nbodies)
      xdiff = x(j)-x(i)
      ydiff = y(j)-y(i)
      zdiff = z(j)-z(i)
      r2 = (xdiff**2)+(ydiff**2)+(zdiff)**2
      C = (G*m(j)*m(i))/((r2)**1.5)
      Fx(i)=Fx(i)+C*(xdiff)
      Fx(j)=Fx(j)-C*(xdiff)
      Fy(i)=Fy(i)+C*(ydiff)
      Fy(j)=Fy(j)-C*(ydiff)
      Fz(i)=Fz(i)+C*(zdiff)
      Fz(j)=Fz(j)-C*(zdiff)
    end do
  end do

  axnew = Fx/m
  aynew = Fy/m
  aznew = Fz/m
end subroutine


在嵌套的for循环中,在
CalcForce
中,循环从
i+1
开始,因此每次迭代都“缺少”了
i
对象的交互力。是这样吗?你能在你的fortran代码中添加一个链接或粘贴一个块吗?@Charles从i开始,我得到一个力常数的浮点除零问题:C=(G*m[j]*m[i])/((r2)**(1.5))@kendfss当然。我将把它包括在我的帖子中。CalcForce并没有像你想象的那样改变accelXN、accelYN和accelZN。您不需要在列表和nParray之间进行如此多的转换。顺便说一下,
axnew=np.zeros(nbodies)
是生成零数组的一种更快的方法。