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

作者:微小冷 时间:2022-03-29 21:40:37 

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

拉格朗日方程

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

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

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

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

引力势能为

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

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

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

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

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

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

推导方程组

对于三体系统而言,总计有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]

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

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

三个粒子的每一个坐标维度,都可以列出一组拉格朗日方程,所以总共有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实现模拟三体运动的示例代码

微分方程算法化

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

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

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

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

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

odeint输入的y的形式为

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

从而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()

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

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

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

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()

结果为

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

动图绘制

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

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实现模拟三体运动的示例代码

来源:https://blog.csdn.net/m0_37816922/article/details/129430989

标签:Python,三体,运动
0
投稿

猜你喜欢

  • Python pandas的八个生命周期总结

    2023-02-08 17:01:04
  • 基于PHP读取csv文件内容的详解

    2023-11-16 04:17:48
  • Python对多个sheet表进行整合实例讲解

    2021-01-15 06:18:24
  • Python使用QQ邮箱发送邮件报错smtplib.SMTPAuthenticationError

    2023-07-07 06:58:52
  • python3实现飞机大战

    2023-03-03 00:36:18
  • python list 查询是否存在并且并返回下标的操作

    2023-06-20 12:05:43
  • Bootstrap每天必学之响应式导航、轮播图

    2023-08-15 03:29:45
  • apache集成php5.6方法分享

    2023-09-06 09:03:54
  • 如何进行MySQL数据库表的故障检测

    2009-02-10 10:34:00
  • asp数组去重复和数组排序

    2008-10-30 12:51:00
  • 详解python-图像处理(映射变换)

    2023-12-23 06:43:35
  • 一些关于SQL2005+ASP.NET2.0的问题

    2007-09-23 13:01:00
  • asp如何实现点击数的计算?

    2010-05-18 18:39:00
  • python中的Elasticsearch操作汇总

    2022-01-29 10:44:45
  • php错误级别的设置方法

    2023-11-24 10:30:35
  • 用Dreamweaver制作活动菜单条

    2009-07-10 13:15:00
  • Python实现简单的列表冒泡排序和反转列表操作示例

    2022-10-18 08:46:04
  • 教你利用python如何读取txt中的数据

    2023-04-03 14:52:36
  • 如何检测Oracle的ODBC是否连接成功?

    2009-11-24 20:31:00
  • 用自定义html标签让IE支持html 5新增元素

    2008-03-18 12:57:00
  • asp之家 网络编程 m.aspxhome.com