全文共7726字,预计学习时长15分钟或更长

图片来自flickr, 凯文·吉尔

中国作家刘慈欣的科幻小说《三体》中描绘了存在于被三颗恒星环绕的“三体”星球上的一种虚构外星文明。能想象这种文明的存在因三颗恒星而和我们的文明大不相同吗?炫目的阳光?持续的夏日?事实证明,情况要糟糕很多。

生活在仅有一颗主要恒星的太阳系是值得庆幸的,因为这使得这颗恒星(太阳)的轨道有可预测性。即使增加一颗恒星,这个系统仍能保持稳定。该系统有个被称为分析解的解法,即描绘解方程式,并得到可以精确提供该系统从一秒到百万年时间演变的函数。

然而,当加入第三体时,就会发生特殊情况。系统会变得混乱而不可预测。没有分析解法(除了少数特定情况),并且只能在计算机上用数字解方程式。它们会突然从稳定变到不稳定,或者从不稳定变到稳定。在如此混乱的世界中,三体人进化出了在“混乱时代”自我“脱水”并休眠,而在“稳定时代”温和地复苏并生活的能力。

书中对恒星系统有趣的形象化描述激发了我们对万有引力中n体类问题以及解决这类问题的数值算法的研究。此文涉及一些理解问题必要的万有引力核心概念,以及描绘系统解方程式必要的数值算法的核心概念。

此文将讲述以下工具和概念的实施方法:

· 使用Scipy模型中的odeint函数解Python中的微分方程

· 无量纲化方程式

· 在Matploylib中进行3D绘制

万有引力概要

1. 牛顿的万有引力定律

牛顿的万有引力定律提出,任何两个质点之间都存在相互吸引力(称之为万有引力),其大小与它们质量的乘积直接成正比,与它们之间距离的平方成反比。以下方程式以向量的形式表示了这条定律:

在这里,G为万有引力常数,m₁和 m₂为两物体的质量,r为物体间的距离。单位向量从m₁指向 m₂ 并且力的作用方向也是相同的。

2. 运动方程

根据牛顿第二运动定律,物体上的合力造成了物体动量的净变化——简而言之,力就是质量乘以加速度。因此,将上述方程式应用到质量m₁ 的物体中,就可以得到以下运动微分方程。

这里要注意的是,单位向量r被分解成向量r除以其大小|r|,因此要增加分母中r项的幂到3.

现在得到一个二阶微分方程,它描绘了两个物体间因重力而存在的相互作用。为简化解法,可以将其分解成两个一阶微分方程。

物体的加速度是物体速率随时间的变化,因此速率的一阶微分可以替代位置的二阶微分。类似地,速率可表示为位置的一阶微分。

指数i 表示要计算位置和速率的物体,而指数j表示和物体i相互作用的其他物体。因此,对一个二体系统来说,就要解两组方程式。

3. 质心

另一个值得记下来的实用概念是系统的质心。质心是一个点,在这个点上系统的所有质量矩总和为零——简而言之,可以将其想象成整个系统质量平衡的点。

有个简单的公式可以找到系统的质心和速率,该公式包括位置和速率向量的质量加权平均值。

在三体系统建模之前,先来为一个二体系统建模,观测其行为然后将代码延伸应用到三体系统中。

二体模型

1. 半人马座α星恒星系统

一个著名的二体系统实例或许就是半人马座α星恒星系统。它包括三颗恒星——半人马座α星A,半人马座α星B,半人马座α星C(通常称之为比邻星)。然而,由于和其他两颗恒星相比,比邻星的质量小到可以忽视,半人马座α星也被视作双星系统。这儿有个需注意的要的点是,n体系统中考虑到的物体都有相似的质量。因此,日-地-月不是一个三体系统,因为它们没有同等的质量,并且地球和月球对太阳的轨迹影响不大。

约翰·科洛西莫在智利的帕洛马天文台捕捉到的半人马座α星双星系统

2. 无量纲化

在解方程式之前,需要先对方程式进行无量纲化。这意味着什么?把方程式中(如位置、速率、质量等)所有具有维数(如分别为m, m/s, kg)的量转换成大小接近单位的无因次量。这样做的原因是:

· 在微分方程中,不同项有不同的数量级(从0.1到10³⁰)。如此巨大的差异可能导致数值算法收敛变得缓慢。

· 如果所有项的大小都十分接近单位,从计算方面上讲所有运算价格都将比数值大小不平衡时低廉。

· 将会得到一个有关大小的参考点。例如,如果给一个4×10³⁰ kg的量,可能无法衡量在宇宙尺度上它是大是小。然而,如果说是太阳质量的2倍,就很容易把握这个量的意义。

将每个量除以一个固定的参考量以对方程式进行无量纲化。例如,用质量项除以太阳的质量,半人马座α星系统中两星间距离的位置(或距离)项,半人马座α星轨道周期的时间项,以及地球绕日公转的相对速率。

当把每一项除以参考量的时候,也需要将其相乘以免改变方程式。所有这些量和G在一起就能变成一个常数,比如方程式1中的K₁和方程式2中的 K₂。因此,无量纲化的方程式即如下所示:

项上的横杠表示该项是无因次的。因此这就是要用在模拟中的最终方程式。

3. 代码

从为模拟输入所要求的模块开始。

#Import scipy

import scipy as sci

#Import matplotlib and associated modules for 3D andanimations
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animation

接下来,定义无量纲化方程式中用到的常数和参考量,以及净常数K₁ 和 K₂。

#Define universal gravitation constant
G=6.67408e-11 #N-m2/kg2

#Reference quantities
m_nd=1.989e+30 #kg #mass of the sun
r_nd=5.326e+12 #m #distance between stars in Alpha Centauri
v_nd=30000 #m/s #relative velocity of earth around the sun
t_nd=79.91*365*24*3600*0.51 #s #orbital period of Alpha Centauri

#Net constants
K1=G*t_nd*m_nd/(r_nd**2*v_nd)
K2=v_nd*t_nd/r_nd

现在要定义一些参数,需要模拟两颗恒星的质量、初始位置和初速度。需要注意的是这些参数是无因次的,所以定义半人马座α星A的质量为1.1(意味着其质量为参考量太阳质量的1.1倍)。任意定义速率,则没有物体能够逃脱彼此的引力。

#Define masses
m1=1.1 #Alpha Centauri A
m2=0.907 #Alpha Centauri B

#Define initial position vectors
r1=[-0.5,0,0] #m
r2=[0.5,0,0] #m

#Convert pos vectors to arrays
r1=sci.array(r1,dtype="float64")
r2=sci.array(r2,dtype="float64")

#Find Centre of Mass
r_com=(m1*r1+m2*r2)/(m1+m2)

#Define initial velocities
v1=[0.01,0.01,0] #m/s
v2=[-0.05,0,-0.1] #m/s

#Convert velocity vectors to arrays
v1=sci.array(v1,dtype="float64")
v2=sci.array(v2,dtype="float64")

#Find velocity of COM
v_com=(m1*v1+m2*v2)/(m1+m2)

现在已经定义了大多数主要的模拟要求的量。可以为解方程组在scipy中准备odeint 求解器了。

为了解常微分方程,需要有方程式(肯定的!),一组初始条件以及解方程所需的时间跨度。Odeint求解器也要求具备这三样基本要素。方程式通过函数的形式被定义。函数以其顺序接受包含所有因变量(此处为位置和速率)的数组和包含所有因变量(此处为时间)的数组,函数返回数组中所有微分的值。

#A function defining the equations of motion
def TwoBodyEquations(w,t,G,m1,m2):
    r1=w[:3]
    r2=w[3:6]
    v1=w[6:9]
    v2=w[9:12]

r=sci.linalg.norm(r2-r1) #Calculate magnitude or norm of vector

dv1bydt=K1*m2*(r2-r1)/r**3
    dv2bydt=K1*m1*(r1-r2)/r**3
    dr1bydt=K2*v1
    dr2bydt=K2*v2

r_derivs=sci.concatenate((dr1bydt,dr2bydt))
    derivs=sci.concatenate((r_derivs,dv1bydt,dv2bydt))
    return derivs

从这段代码中也许很容易区分出微分方程。那其他零碎的东西是什么?记得吗?现在在解三维方程,所以每一位置和速率向量都会有3个分量。考虑一下之前章节给出的双矢量微分方程,它们需要解向量的所有3个分量。因此,需要为一个物体解6标量的微分方程。同理,两个物体就要解12标量的微分方程。所以要制作一个大小为12,含两个物体的质量和速率的数组w。

在函数的最后,连结或加入所有不同的导数并返回大小为12的derivs。

最难的部分已经做完了!剩下的就是把函数,初始条件和和时间跨度输入到odeint函数中去。

#Package initial parameters
init_params=sci.array([r1,r2,v1,v2]) #create array of initial params
init_params=init_params.flatten() #flatten array to make it 1D
time_span=sci.linspace(0,8,500) #8 orbital periods and 500 points

#Run the ODE solver
import scipy.integrate

two_body_sol=sci.integrate.odeint(TwoBodyEquations,init_params,time_span,args=(G,m1,m2))

变量two_body_sol 包含有关二体系统所有的信息,包括位置向量和速率向量。为了创建图和动画,只需要有能延伸到两个不同变量的位置向量就可以了。

r1_sol=two_body_sol[:,:3]
r2_sol=two_body_sol[:,3:6]

现在是绘图!在这要用到Matplotlib的3D标图功能。

#Create figure
fig=plt.figure(figsize=(15,15))

#Create 3D axes
ax=fig.add_subplot(111,projection="3d")

#Plot the orbits
ax.plot(r1_sol[:,0],r1_sol[:,1],r1_sol[:,2],color="darkblue")
ax.plot(r2_sol[:,0],r2_sol[:,1],r2_sol[:,2],color="tab:red")

#Plot the final positions of the stars
ax.scatter(r1_sol[-1,0],r1_sol[-1,1],r1_sol[-1,2],color="darkblue",marker="o",s=100,label="AlphaCentauri A")
ax.scatter(r2_sol[-1,0],r2_sol[-1,1],r2_sol[-1,2],color="tab:red",marker="o",s=100,label="AlphaCentauri B")

#Add a few more bells and whistles
ax.set_xlabel("x-coordinate",fontsize=14)
ax.set_ylabel("y-coordinate",fontsize=14)
ax.set_zlabel("z-coordinate",fontsize=14)
ax.set_title("Visualization of orbits of stars in a two-bodysystem\n",fontsize=14)
ax.legend(loc="upper left",fontsize=14)

最终的图像清晰表明,轨道遵循可预测的模式,正如二体问题算法所期望的那样。

显示两颗星球轨道时间演变的Matplotlib图像

这里有一个展示轨道一步步演变的动画。

Matplotlib中展示轨道一步步演变的动画

还可以再制作一个可视化图像,它来自质心的参考框架。上面的图像来自空间中任一平稳点,但如果观察来自质心系统的两个物体的移动,就可以看到一个更加形象的图案。

因此,先找到每一时间步上质心的位置,然后从两个物体的位置向量上减去其向量以找到它们相对应质心的位置。

#Find location of COM
rcom_sol=(m1*r1_sol+m2*r2_sol)/(m1+m2)

#Find location of Alpha Centauri A w.r.t COM
r1com_sol=r1_sol-rcom_sol

#Find location of Alpha Centauri B w.r.t COM
r2com_sol=r2_sol-rcom_sol

最后,可以使用更改变量后的绘制之前图像使用的代码,绘制以下图像。

来自COM的显示两颗星球轨道时间演变的Matplotlib图像

如果坐在COM观察两个物体,就可以看到以上轨道。从这个模拟来看它并不清晰,因为时间尺度非常小,然而即使是这些轨道也一直在轻微地旋转。

现在就很清楚了,两个物体严格遵循预测的路线,而且可以用函数——也许是个椭圆体方程——来描绘它们在空间中如二体系统所期望的移动。

三体模型

1. 代码

现在为了把之前的代码延伸到三体系统,需要给常数增加一些东西——增加第三体的质量、位置和速率向量。把第三恒星的质量视作和太阳的质量等同。

#Mass of the Third Star
m3=1.0 #Third Star

#Position of the Third Star
r3=[0,1,0] #m
r3=sci.array(r3,dtype="float64")

#Velocity of the Third Star
v3=[0,-0.01,0]
v3=sci.array(v3,dtype="float64")

需要更新代码中质心和质心速率的公式。

#Update COM formula
r_com=(m1*r1+m2*r2+m3*r3)/(m1+m2+m3)

#Update velocity of COM formula

v_com=(m1*v1+m2*v2+m3*v3)/(m1+m2+m3)

对一个三体系统来说,需要修改运动方程使之包括另一物体施加的额外引力。因此,需要在RHS上,对问题中每一对物体施加力的其他物体增加一个力项。在三体系统的情况下,一个物体会受到其余两个物体施加的力的影响并因此在RHS上出现两个力项。数学上可表示为:

为在代码中反映这些变化,需要为odeint求解器创建一个新函数。

def ThreeBodyEquations(w,t,G,m1,m2,m3):
    r1=w[:3]
    r2=w[3:6]
    r3=w[6:9]
    v1=w[9:12]
    v2=w[12:15]
    v3=w[15:18]

r12=sci.linalg.norm(r2-r1)
    r13=sci.linalg.norm(r3-r1)
    r23=sci.linalg.norm(r3-r2)
   
    dv1bydt=K1*m2*(r2-r1)/r12**3+K1*m3*(r3-r1)/r13**3
    dv2bydt=K1*m1*(r1-r2)/r12**3+K1*m3*(r3-r2)/r23**3
    dv3bydt=K1*m1*(r1-r3)/r13**3+K1*m2*(r2-r3)/r23**3
    dr1bydt=K2*v1
    dr2bydt=K2*v2
    dr3bydt=K2*v3

r12_derivs=sci.concatenate((dr1bydt,dr2bydt))
    r_derivs=sci.concatenate((r12_derivs,dr3bydt))
    v12_derivs=sci.concatenate((dv1bydt,dv2bydt))
    v_derivs=sci.concatenate((v12_derivs,dv3bydt))
    derivs=sci.concatenate((r_derivs,v_derivs))
    return derivs

最后,调用odeint函数并向其提供上述函数连同初始条件。

#Package initial parameters
init_params=sci.array([r1,r2,r3,v1,v2,v3]) #Initial parameters
init_params=init_params.flatten() #Flatten to make 1D array
time_span=sci.linspace(0,20,500) #20 orbital periods and 500 points

#Run the ODE solver
import scipy.integrate

three_body_sol=sci.integrate.odeint(ThreeBodyEquations,init_params,time_span,args=(G,m1,m2,m3))

正如二体模拟一样,需要提取所有三体的位置进行绘图。

r1_sol=three_body_sol[:,:3]
r2_sol=three_body_sol[:,3:6]
r3_sol=three_body_sol[:,6:9]

可以把上述章节给出的代码稍作修改后运用到最后的绘图上。正如下图呈现的混乱,这个轨道没有预期的图案。

显示三颗星球轨道时间演变的Matplotlib图像

动画会使这张混乱的图变得更容易理解。

Matplotlib中展示轨道一步步演变的动画

这里有另一个初始配置的解法,其中可以观察到,解法似乎在一开始是稳定的,但接着就突然变得不稳定了。

Matplotlib中展示轨道一步步演变的动画

可以试着玩玩这些初始条件,看看不同种类的解法。近年来,由于计算机能力的增强,人们已经发现了很多关于三体问题的有趣的解法,其中一些是周期性的——如figure-8解法,在这里三个物体全都在平面的figure-8路线上运动。

留言 点赞 发个朋友圈

我们一起分享AI学习与发展的干货

编译组:鲍歆祎、李林虹

相关链接:

https://towardsdatascience.com/modelling-the-three-body-problem-in-classical-mechanics-using-python-9dc270ad7767

如需转载,请后台留言,遵守转载规范

推荐文章阅读

ACL2018论文集50篇解读

EMNLP2017论文集28篇论文解读

2018年AI三大顶会中国学术成果全链接

ACL2017 论文集:34篇解读干货全在这里

10篇AAAI2017经典论文回顾

长按识别二维码可添加关注

读芯君爱你

三体究竟有多可怕?用Python建模来深度了解相关推荐

  1. python可以实现哪些功能_Python学习究竟有多强大,Python代码能实现哪些功能

    Python究竟有多强大?Python代码能实现哪些功能?众所周知,Python入门简单.功能强大,是人工智能时代最佳的编程语言.但很多人好奇Python究竟有多强大,为什么那么受欢迎?下面就来给大家 ...

  2. 决策树python建模中的坑 :ValueError: Expected 2D array, got 1D array instead:

    决策树python建模中的坑 代码 #coding=utf-8 from sklearn.feature_extraction import DictVectorizerimport csvfrom ...

  3. python股票交易模型_如何用Python建模GGM模型并对股票估值?

    内容首发 乐学偶得(http://lexueoude.com) 公众号: 乐学Fintech 用代码理解分析解决金融问题 首先我们快速了解一下什么是GGM模型. GGM模型又叫做"戈登增长模 ...

  4. python建模 决策_决策树python建模中的坑 :ValueError: Expected 2D array, got 1D array instead:...

    决策树python建模中的坑 代码 #coding=utf-8 from sklearn.feature_extraction import DictVectorizer import csv fro ...

  5. 《利用Python进行数据分析·第2版》第13章 Python建模库介绍

    第1章 准备工作 第2章 Python语法基础,IPython和Jupyter 第3章 Python的数据结构.函数和文件 第4章 NumPy基础:数组和矢量计算 第5章 pandas入门 第6章 数 ...

  6. Python数据分析学习系列 十三 Python建模库介绍

    Python数据分析学习系列 十三 Python建模库介绍 资料转自(GitHub地址):https://github.com/wesm/pydata-book 有需要的朋友可以自行去github下载 ...

  7. 【利用Python进行数据分析】13 - Python建模库介绍

    第十三章 Python建模库介绍 1.pandas与模型代码的接口 2.用Patsy创建模型描述 2.1.Patsy创建模型设计矩阵 2.2.用Patsy公式进行数据转换 2.3.分类数据和Patsy ...

  8. 第十三篇 Python建模库介绍

    前面已经介绍了Python数据分析的编程基础.数据分析师和科学家总是在数据规整和准备上花费⼤量时间,前面部分的重点在于掌握这些功能. 开发模型选⽤什么库取决于应⽤本身.许多统计问题可以⽤简单⽅法解决, ...

  9. 第13章 Python建模库介绍--Python for Data Analysis 2nd

    本书中,我已经介绍了Python数据分析的编程基础.因为数据分析师和科学家总是在数据规整和准备上花费大量时间,这本书的重点在于掌握这些功能. 开发模型选用什么库取决于应用本身.许多统计问题可以用简单方 ...

最新文章

  1. httpClient多线程请求
  2. addhandler php5-script php,htaccess和AddType/Addhandler
  3. 这年头,机器翻译都会通过文字脑补画面了 | NAACL 2021
  4. 关于VM热备份的三种方法
  5. Servlet Cookie处理
  6. [转]项目经理面试指南
  7. uniapp 获取到js文件var一个变量怎么获取到这个变量值_浅析Js中const,let,var的区别及作用域...
  8. Visual Studio Online 的 FAQ:iPad 支持、自托管环境、Azure 账号等
  9. 33、JAVA_WEB开发基础之会话机制
  10. 工业以太网交换机选机攻略
  11. JAVA遇见HTML——JSP篇(JSP状态管理)
  12. RUNNOOB python练习题 28 递归 数列
  13. figtree如何编辑进化树_进化树的注释:ggtree
  14. POJ NOI MATH-7826 分苹果
  15. 7. COM编程——初始化并创建COM对象
  16. 前端视频播放初探总结,video标签-视频插件jwplayer
  17. 网易涉暴力裁员引众怒 5大争议背后是否违法?
  18. 阿里云商标优选怎么样上传商标挂售?
  19. redis的原理和源码-数据持久化方式AOF的介绍和源码解析
  20. C1驾照到期更换,驾照异地入迁,摩托驾驶证报名,记录

热门文章

  1. git安装问题解决方案
  2. centos8使用syncthing自启动的两种方式
  3. (98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
  4. MyBatis框架学习笔记01:初生牛犊
  5. 抛出异常和捕获异常_多捕获和最终重新抛出的异常处理
  6. CSS (二) 背景
  7. Lodash pick
  8. 期刊勘误、关注和撤稿:科研作者该知道的信息(转载)
  9. python运行窗口闪退_python+selenium自动化测试,IE浏览器运行过程中出现闪退
  10. Centos7超级无敌简单的PXE安装系统手动与自动化