我的编程空间,编程开发者的网络收藏夹
学习永远不晚

基于Python实现模拟三体运动的示例代码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

基于Python实现模拟三体运动的示例代码

温馨提示,只想看图的画直接跳到最后一节

拉格朗日方程

此前所做的一切三体和太阳系的动画,都是基于牛顿力学的,而且直接对微分进行差分化,从而精度非常感人,用不了几年就得撞一起去。

为了给三体人提供一个更加有价值的推导,这次通过求解拉格朗日方程的数值解来实现。

首先假设三个质点的质量分别为m1, m2,m3,坐标为x1​,x2​,x3,​质点速度可以表示为x → ˙.假设三体在二维平面上运动,则第i个质点的动能为

引力势能为

其中G为万有引力常量,rij为质点i,j之间的距离,则系统的拉格朗日量为

有了拉格朗日量,将其带入拉格朗日方程

就可以得到拉格朗日方程组。

推导方程组

对于三体系统而言,总计有3个粒子,每个粒子有x,y两个自由度,也就是说最后会得到6组方程。考虑到公式推导过程中可能会出现错误,所以下面采用sympy来进行公式推导。

首先定义符号变量

from sympy import symbols
from sympy.physics.mechanics import dynamicsymbols
m = symbols('m1:4')
x = dynamicsymbols('x1:4')
y = dynamicsymbols('y1:4')

接下来,需要构造系统的拉格朗日量L,其实质是系统的动能减去势能,对于上面构建的三体系统而言,动能和势能可分别表示为

计算每个质点的动能和势能。动能是由速度决定的,而速度是由位置对时间的导数决定的。我们可以用 sympy 的 diff 函数来求导:

from sympy import diff
# 此为速度的平方
v2 = [diff(x[i],t)**2 + diff(y[i])**2 for i in range(3)]
T = 0
for i in range(3):
    T += m[i]*v2[i]/2

势能是由万有引力决定的,而万有引力是由两个质点之间的距离决定的。我们可以用 sympy 的 sqrt 函数来求距离:

from sympy import sqrt,cos
G = symbols('G') # 引力常数
ijs = [(0,1), (0,2),(1,2)]
dij = [sqrt((x[i]-x[j])**2+(y[i]-y[j])**2) for i,j in ijs]
U = 0
for k in range(3):
    i,j = ijs[k]
    U -= G*m[i]*m[j]/dij[k]

有了动能和势能,就可以愉快地求拉格朗日量了,有了拉格朗日量,就可以列拉格朗日方程了

三个粒子的每一个坐标维度,都可以列出一组拉格朗日方程,所以总共有6个拉格朗日方程组

from sympy import solve
L = T - U
eqLag = lambda x : diff(L, x)-diff(diff(L, diff(x, t)), t)
# 拉格朗日方程组
eqs = [eqLag(xi) for xi in x+y]

记xij=xi−xj,yij=yi−yj ,则

微分方程算法化

接下来就要调用Python的odeint来计算这个微分方程组的数值解,odeint的调用方法大致为odeint(func, y, t, args),其中func是一个函数,这个函数必须为func(y,t,...),且返回值为dy/dt.

为此,需要将上述方程组再行拆分,以消去其中的二次导数,以x1为例,令u1=dx1/dt ,则此方程变为方程组

由于三体系统中有3个粒子,共6个独立变量,所以要列12个方程。记

odeint输入的y的形式为

从而func的具体形式为

import numpy as np
dxy = lambda x,y : np.sqrt(x**2+y**2)**(3/2)
def triSys(Y, t, m, G):
    jk = [(1,2),(0,2),(0,1)]
    x,y = Y[:3], Y[3:6]
    u,v = Y[6:9], Y[9:]
    du, dv = [], []
    for i in range(3):
        j, k = jk[i]
        xji, xki = x[j]-x[i], x[k]-x[i]
        yji, yki = y[j]-y[i], y[k]-y[i]
        dji, dki = dxy(xji, yji), dxy(yji, yki)
        mji, mki = G*m[i]*m[j], G*m[i]*m[k]
        du.append(mji*xji/dji + mki*xki/dki)
        dv.append(mji*yji/dji + mki*yki/dki)
    dydt = [*u, *v, *du, *dv]
    return dydt

求解+画图

接下来就是见证奇迹的时刻,首先创建一个随机的起点,作为三体运动的初值,然后带入开整就完事儿了

from scipy.integrate import odeint
np.random.seed(42)
y0 = np.random.rand(12)
m = np.random.rand(3)
t = np.linspace(0, 20, 1001)
sol = odeint(triSys, y0, t, args=(m, 1))

然后绘制一下这三颗星的轨迹

import matplotlib.pyplot as plt
plt.plot(sol[:,0], sol[:,3])
plt.plot(sol[:,1], sol[:,4])
plt.plot(sol[:,2], sol[:,5])
plt.show()

光是看这个轨迹就十分惊险了有木有。

如果把其中的第一颗星作为坐标原点,那么另外两颗星的轨迹大致为

plt.plot(sol[:,1]-sol[:,0], sol[:,4]-sol[:,3])
plt.plot(sol[:,2]-sol[:,0], sol[:,5]-sol[:,3])
plt.scatter([0],[0], c='g', marker='*')
plt.show()

结果为

动图绘制

最后,以中间这颗星为原点,绘制一下另外两颗星运动的动态过程

import matplotlib.animation as animation 

fig = plt.figure(figsize=(9,4))
ax = fig.add_subplot(xlim=(-1.8,1.8),ylim=(-1.8,1.5))
ax.grid()

traces = [ax.plot([],[],'-',lw=0.5)[0] for _ in range(2)]
pts = [ax.plot([],[] ,marker='*')[0] for _ in range(2)]
ax.plot([0],[0], marker="*", c='r')

X1 = sol[:,1]-sol[:,0]
Y1 = sol[:,4]-sol[:,3]
X2 = sol[:,2]-sol[:,0]
Y2 = sol[:,5]-sol[:,3]

def animate(n):
    traces[0].set_data(X1[:n], Y1[:n])
    traces[1].set_data(X2[:n], Y2[:n])
    pts[0].set_data([X1[n], Y1[n]])
    pts[1].set_data([X2[n], Y2[n]])
    return traces + pts

ani = animation.FuncAnimation(fig, animate, 
    range(1000), interval=10, blit=True)
ani.save('tri.gif')

到此这篇关于基于Python实现模拟三体运动的示例代码的文章就介绍到这了,更多相关Python三体运动内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

基于Python实现模拟三体运动的示例代码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

基于Python实现模拟三体运动的示例代码

此前所做的一切三体和太阳系的动画,都是基于牛顿力学的,而且直接对微分进行差分化,从而精度非常感人,用不了几年就得撞一起去。所以本文来用Python重新模拟一下三体运动,感兴趣的可以了解一下
2023-03-10

基于Python如何实现模拟三体运动

本文小编为大家详细介绍“基于Python如何实现模拟三体运动”,内容详细,步骤清晰,细节处理妥当,希望这篇“基于Python如何实现模拟三体运动”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。拉格朗日方程此前所做的
2023-07-05

Python实现蒙特卡洛模拟的示例代码

这篇文章主要为大家详细介绍了如何利用Python实现蒙特卡洛模拟,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以了解一下
2023-03-13

基于Python实现录音功能的示例代码

今天我们来介绍一个好玩且实用的东西,我们使用python来实现一个录音的功能。文中的示例代码简洁易懂,感兴趣的小伙伴快跟随小编一起学习一下吧
2023-02-07

基于Python实现24点游戏的示例代码

这篇文章主要为大家详细介绍了如何利用Python实现24点游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2022-12-08

基于Python实现格斗小游戏的示例代码

格斗游戏,曾经是街机厅里最火爆的游戏之一,甚至可以把“之一”去掉,那个年代的格斗游戏就是街机游戏的王。本文就来用Python实现一个简单的格斗游戏,感兴趣的可以了解一下
2023-03-02

动态代理模拟实现aop的示例

AOP实现起来代码相当简单.主要核心是动态代理和反射.一.接口类:public interface MethodDao { public void sayHello(); }
2023-05-30

基于Python实现文件分类器的示例代码

这篇文章主要为大家详细介绍了如何基于Python实现文件分类器,目的主要是为了将办公过程中产生的各种格式的文件完成整理,感兴趣的可以了解一下
2023-05-14

基于Echarts实现绘制立体柱状图的示例代码

这篇文章主要为大家详细介绍了如何基于Echarts实现绘制立体柱状图的功能,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
2023-02-23

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录