三体问题详解

从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解析解。

🧭 问题设定:三体系统的基本假设

假设我们有三个质量分别为 m 1 , m 2 , m 3 m_1, m_2, m_3 m1,m2,m3 的天体,位置向量分别为:

  • r 1 ( t ) \mathbf{r}_1(t) r1(t)
  • r 2 ( t ) \mathbf{r}_2(t) r2(t)
  • r 3 ( t ) \mathbf{r}_3(t) r3(t)

在牛顿引力定律下,每个天体受到其余两个天体的引力,总加速度由牛顿第二定律( F = m a \mathbf{F} = m\mathbf{a} F=ma)给出。


📐 一般形式的运动方程(牛顿引力 + 牛顿第二定律)

对第一个天体 m 1 m_1 m1,其加速度为:

m 1 d 2 r 1 d t 2 = G m 1 m 2 ∣ r 2 − r 1 ∣ 3 ( r 2 − r 1 ) + G m 1 m 3 ∣ r 3 − r 1 ∣ 3 ( r 3 − r 1 ) m_1 \frac{d^2 \mathbf{r}_1}{dt^2} = G \frac{m_1 m_2}{|\mathbf{r}_2 - \mathbf{r}_1|^3} (\mathbf{r}_2 - \mathbf{r}_1) + G \frac{m_1 m_3}{|\mathbf{r}_3 - \mathbf{r}_1|^3} (\mathbf{r}_3 - \mathbf{r}_1) m1dt2d2r1=Gr2r13m1m2(r2r1)+Gr3r13m1m3(r3r1)

类似地,对 m 2 , m 3 m_2, m_3 m2,m3 分别有:

m 2 d 2 r 2 d t 2 = G m 2 m 1 ∣ r 1 − r 2 ∣ 3 ( r 1 − r 2 ) + G m 2 m 3 ∣ r 3 − r 2 ∣ 3 ( r 3 − r 2 ) m_2 \frac{d^2 \mathbf{r}_2}{dt^2} = G \frac{m_2 m_1}{|\mathbf{r}_1 - \mathbf{r}_2|^3} (\mathbf{r}_1 - \mathbf{r}_2) + G \frac{m_2 m_3}{|\mathbf{r}_3 - \mathbf{r}_2|^3} (\mathbf{r}_3 - \mathbf{r}_2) m2dt2d2r2=Gr1r23m2m1(r1r2)+Gr3r23m2m3(r3r2)

m 3 d 2 r 3 d t 2 = G m 3 m 1 ∣ r 1 − r 3 ∣ 3 ( r 1 − r 3 ) + G m 3 m 2 ∣ r 2 − r 3 ∣ 3 ( r 2 − r 3 ) m_3 \frac{d^2 \mathbf{r}_3}{dt^2} = G \frac{m_3 m_1}{|\mathbf{r}_1 - \mathbf{r}_3|^3} (\mathbf{r}_1 - \mathbf{r}_3) + G \frac{m_3 m_2}{|\mathbf{r}_2 - \mathbf{r}_3|^3} (\mathbf{r}_2 - \mathbf{r}_3) m3dt2d2r3=Gr1r33m3m1(r1r3)+Gr2r33m3m2(r2r3)


⚠️ 为什么不稳定?

1. 非线性耦合微分方程组

这三组式子彼此高度耦合:每个加速度都依赖于另外两个天体的位置,而且这种依赖是非线性(距离的三次方在分母)。

这是典型的非线性二阶常微分方程组,形式上如下:

d 2 r i d t 2 = ∑ j ≠ i G m j r j − r i ∣ r j − r i ∣ 3 , i = 1 , 2 , 3 \frac{d^2 \mathbf{r}_i}{dt^2} = \sum_{j \ne i} G m_j \frac{\mathbf{r}_j - \mathbf{r}_i}{|\mathbf{r}_j - \mathbf{r}_i|^3}, \quad i = 1,2,3 dt2d2ri=j=iGmjrjri3rjri,i=1,2,3

这种系统存在如下三大特性:

  • 不可分解成单体运动 + 微扰项
  • 无法通过代数方法求出通解
  • 随时间演化会展现出对初始条件的极度敏感

2. 初始条件敏感性(混沌特征)

在数值模拟中,即使两个三体系统初始位置差异为 10 − 10 10^{-10} 1010 米,几十个周期后轨道会完全不同。

这是混沌系统的定义特征:

初始条件微小扰动会被放大,导致长期行为完全不可预测。


3. 守恒定律约束不足以稳定系统

虽然系统满足以下守恒定律:

  • 总动量守恒:

    ∑ i = 1 3 m i d r i d t = 常量 \sum_{i=1}^3 m_i \frac{d \mathbf{r}_i}{dt} = \text{常量} i=13midtdri=常量

  • 总能量守恒:

    E = ∑ i = 1 3 1 2 m i v i 2 − ∑ i < j G m i m j ∣ r i − r j ∣ E = \sum_{i=1}^3 \frac{1}{2} m_i v_i^2 - \sum_{i<j} \frac{G m_i m_j}{|\mathbf{r}_i - \mathbf{r}_j|} E=i=1321mivi2i<jrirjGmimj

但这些守恒量(常数)无法限制轨道在高维空间的发散演化,只是提供一些“整体约束”。

📉 所以为什么不能稳定运行?

从物理角度总结三点:

  1. 多体引力是非线性且时变的力学系统;
  2. 无解析解(除极少对称情况),必须数值求解;
  3. 即使数值解,也极度依赖初始条件,最终表现为混沌轨道;

🎯 实际结果是什么?

小说中三体行星文明面临的核心困境——无法预测三颗恒星的运动。正是这个真实的物理问题,使得三体文明的“乱纪元”和“恒纪元”交替成为必然,也解释了为什么他们需要寻找新的家园。数值模拟证实了这种不稳定性是三体系统的内在属性,而非外部干扰的结果。

三体运动的模拟动画

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib.patches as patches
from matplotlib.widgets import Button
from collections import deque

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


class ThreeBodySystem:
    def __init__(self, masses, positions, velocities, G=1.0):
        """
        三体系统
        masses: [m1, m2, m3] 三个天体的质量
        positions: [[x1,y1], [x2,y2], [x3,y3]] 初始位置
        velocities: [[vx1,vy1], [vx2,vy2], [vx3,vy3]] 初始速度
        G: 引力常数
        """
        self.masses = np.array(masses)
        self.positions = np.array(positions, dtype=float)
        self.velocities = np.array(velocities, dtype=float)
        self.G = G

        # 轨迹历史记录 - 为每个天体单独记录
        self.trail_length = 800
        self.trails = [deque(maxlen=self.trail_length) for _ in range(3)]

        # 初始化轨迹记录
        for i in range(3):
            self.trails[i].append([self.positions[i][0], self.positions[i][1]])

        self.dt = 0.005  # 基础时间步长
        self.speed_multiplier = 1.0  # 速度倍数
        self.time = 0

        # 天体属性
        self.colors = ['#FF6B35', '#004E89', '#00A86B']  # 橙色、深蓝、绿色
        self.names = ['恒星Alpha', '恒星Beta', '恒星Gamma']
        self.base_sizes = [300, 250, 280]

        # 统计数据记录
        self.energy_history = deque(maxlen=500)
        self.distance_history = {'AB': deque(maxlen=500),
                                 'AC': deque(maxlen=500),
                                 'BC': deque(maxlen=500)}

    def set_speed_multiplier(self, multiplier):
        """设置速度倍数"""
        self.speed_multiplier = max(0.1, min(10.0, multiplier))

    def compute_gravitational_forces(self):
        """计算每个天体受到的引力"""
        forces = np.zeros_like(self.positions)

        for i in range(3):
            for j in range(3):
                if i != j:
                    # 位置差矢量: 从i指向j
                    r_vec = self.positions[j] - self.positions[i]
                    r_magnitude = np.linalg.norm(r_vec)

                    # 避免数值奇点
                    if r_magnitude > 1e-8:
                        # 万有引力: F = G*m1*m2/r^2 * 单位矢量
                        force_magnitude = self.G * self.masses[i] * self.masses[j] / (r_magnitude ** 3)
                        forces[i] += force_magnitude * r_vec

        return forces

    def runge_kutta_4th_order(self):
        """四阶龙格-库塔法数值积分(带速度控制)"""
        effective_dt = self.dt * self.speed_multiplier

        # 当前状态
        pos = self.positions.copy()
        vel = self.velocities.copy()

        # k1 计算
        k1_vel = vel
        k1_acc = self.compute_gravitational_forces() / self.masses.reshape(-1, 1)

        # k2 计算
        pos_k2 = pos + 0.5 * effective_dt * k1_vel
        self.positions = pos_k2  # 临时更新位置用于力计算
        k2_vel = vel + 0.5 * effective_dt * k1_acc
        k2_acc = self.compute_gravitational_forces() / self.masses.reshape(-1, 1)

        # k3 计算
        pos_k3 = pos + 0.5 * effective_dt * k2_vel
        self.positions = pos_k3
        k3_vel = vel + 0.5 * effective_dt * k2_acc
        k3_acc = self.compute_gravitational_forces() / self.masses.reshape(-1, 1)

        # k4 计算
        pos_k4 = pos + effective_dt * k3_vel
        self.positions = pos_k4
        k4_vel = vel + effective_dt * k3_acc
        k4_acc = self.compute_gravitational_forces() / self.masses.reshape(-1, 1)

        # 最终更新
        self.positions = pos + effective_dt * (k1_vel + 2 * k2_vel + 2 * k3_vel + k4_vel) / 6
        self.velocities = vel + effective_dt * (k1_acc + 2 * k2_acc + 2 * k3_acc + k4_acc) / 6

        # 记录轨迹
        for i in range(3):
            self.trails[i].append([self.positions[i][0], self.positions[i][1]])

        self.time += effective_dt

    def calculate_total_energy(self):
        """计算系统总能量(动能+势能)"""
        # 动能
        kinetic_energy = 0
        for i in range(3):
            v_squared = np.sum(self.velocities[i] ** 2)
            kinetic_energy += 0.5 * self.masses[i] * v_squared

        # 引力势能
        potential_energy = 0
        for i in range(3):
            for j in range(i + 1, 3):
                r = np.linalg.norm(self.positions[i] - self.positions[j])
                if r > 1e-8:
                    potential_energy -= self.G * self.masses[i] * self.masses[j] / r

        return kinetic_energy + potential_energy

    def update_statistics(self):
        """更新统计数据"""
        # 总能量
        energy = self.calculate_total_energy()
        self.energy_history.append(energy)

        # 天体间距离
        r_AB = np.linalg.norm(self.positions[0] - self.positions[1])
        r_AC = np.linalg.norm(self.positions[0] - self.positions[2])
        r_BC = np.linalg.norm(self.positions[1] - self.positions[2])

        self.distance_history['AB'].append(r_AB)
        self.distance_history['AC'].append(r_AC)
        self.distance_history['BC'].append(r_BC)


class SpeedController:
    """速度控制器类"""

    def __init__(self, system):
        self.system = system
        self.speed_levels = [0.1, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0]
        self.current_level = 3  # 默认1.0倍速

    def speed_up(self, event=None):
        """加速"""
        if self.current_level < len(self.speed_levels) - 1:
            self.current_level += 1
            self.current_level = min(self.current_level, len(self.speed_levels)-1)
            self.system.set_speed_multiplier(self.speed_levels[self.current_level])

    def slow_down(self, event=None):
        """减速"""
        if self.current_level > 0:
            self.current_level -= 1
            self.current_level = max(self.current_level, 0)
            self.system.set_speed_multiplier(self.speed_levels[self.current_level])

    def reset_speed(self, event=None):
        """重置到正常速度"""
        self.current_level = 3
        self.system.set_speed_multiplier(self.speed_levels[self.current_level])

    def get_current_speed_text(self):
        """获取当前速度显示文本"""
        speed = self.speed_levels[self.current_level]
        return f"播放速度: {speed:.1f}x"


def create_three_body_animation():
    """创建带速度控制的三体运动动画"""

    # 初始化系统 - 选择一个展现混沌特性的配置
    masses = [1.5, 1.0, 1.2]  # 三个不同质量的恒星

    # 三角形初始配置,但有适当的速度产生复杂轨道
    positions = [
        [-2.0, 0.0],  # Alpha星
        [1.0, 1.732],  # Beta星
        [1.0, -1.732]  # Gamma星
    ]

    velocities = [
        [0.2, 0.8],  # Alpha星初始速度
        [-0.6, -0.2],  # Beta星初始速度
        [0.4, -0.6]  # Gamma星初始速度
    ]

    system = ThreeBodySystem(masses, positions, velocities, G=3.0)
    speed_controller = SpeedController(system)

    # 创建图形界面
    fig = plt.figure(figsize=(19, 12), facecolor='#0a0a0a')

    # 主动画区域 (左侧大图)
    ax_main = plt.subplot2grid((3, 5), (0, 0), colspan=3, rowspan=3, facecolor='#0a0a0a')

    # 监控面板 (右侧)
    ax_energy = plt.subplot2grid((3, 5), (0, 3), colspan=2, facecolor='#0a0a0a')
    ax_distances = plt.subplot2grid((3, 5), (1, 3), colspan=2, facecolor='#0a0a0a')
    ax_info = plt.subplot2grid((3, 5), (2, 3), colspan=2, facecolor='#0a0a0a')

    # 在底部为按钮留出空间
    plt.subplots_adjust(bottom=0.15)

    # 创建速度控制按钮
    button_height = 0.04
    button_width = 0.08
    button_y = 0.02

    # 减速按钮
    ax_slow = plt.axes([0.25, button_y, button_width, button_height])
    btn_slow = Button(ax_slow, '减速', color='#FF4444', hovercolor='#FF6666')
    btn_slow.label.set_color('white')
    btn_slow.label.set_fontweight('bold')

    # 重置按钮
    ax_reset = plt.axes([0.35, button_y, button_width, button_height])
    btn_reset = Button(ax_reset, '正常', color='#4CAF50', hovercolor='#6BCF7F')
    btn_reset.label.set_color('white')
    btn_reset.label.set_fontweight('bold')

    # 加速按钮
    ax_fast = plt.axes([0.45, button_y, button_width, button_height])
    btn_fast = Button(ax_fast, '加速', color='#2196F3', hovercolor='#42A5F5')
    btn_fast.label.set_color('white')
    btn_fast.label.set_fontweight('bold')

    # 暂停/继续按钮
    ax_pause = plt.axes([0.55, button_y, button_width, button_height])
    btn_pause = Button(ax_pause, '暂停', color='#FF9800', hovercolor='#FFB74D')
    btn_pause.label.set_color('white')
    btn_pause.label.set_fontweight('bold')

    # 速度显示文本
    speed_text = fig.text(0.65, button_y + button_height / 2,
                          speed_controller.get_current_speed_text(),
                          fontsize=12, color='white', va='center', weight='bold')

    # 设置主画布
    ax_main.set_xlim(-8, 8)
    ax_main.set_ylim(-8, 8)
    ax_main.set_aspect('equal')
    ax_main.set_facecolor('#0a0a0a')
    ax_main.tick_params(colors='white')
    ax_main.set_xlabel('X 坐标', color='white', fontsize=14)
    ax_main.set_ylabel('Y 坐标', color='white', fontsize=14)
    ax_main.set_title('三体问题:三颗恒星的混沌舞蹈', color='white', fontsize=16, pad=20)

    # 创建星空背景
    np.random.seed(123)
    star_x = np.random.uniform(-8, 8, 200)
    star_y = np.random.uniform(-8, 8, 200)
    star_sizes = np.random.uniform(0.5, 3, 200)
    ax_main.scatter(star_x, star_y, c='white', s=star_sizes, alpha=0.4)

    # 添加网格
    ax_main.grid(True, alpha=0.15, color='gray', linestyle='-', linewidth=0.5)

    # 初始化绘图元素
    # 1. 三个恒星天体
    stars = []
    for i in range(3):
        star = ax_main.scatter([], [], s=system.base_sizes[i],
                               c=system.colors[i], edgecolors='white',
                               linewidth=3, alpha=0.95, zorder=20)
        stars.append(star)

    # 2. 三条轨迹线
    orbit_trails = []
    for i in range(3):
        trail, = ax_main.plot([], [], color=system.colors[i],
                              linewidth=2.5, alpha=0.8, zorder=10)
        orbit_trails.append(trail)

    # 3. 引力连接线
    gravity_lines = []
    gravity_colors = ['yellow', 'orange', 'red']
    line_pairs = [(0, 1), (0, 2), (1, 2)]

    for i, (a, b) in enumerate(line_pairs):
        line, = ax_main.plot([], [], color=gravity_colors[i],
                             alpha=0.4, linewidth=2, linestyle='--', zorder=5)
        gravity_lines.append(line)

    # 4. 恒星标签
    star_labels = []
    for i in range(3):
        label = ax_main.text(0, 0, system.names[i], fontsize=12, color='white',
                             ha='center', va='center', weight='bold',
                             bbox=dict(boxstyle="round,pad=0.3", facecolor=system.colors[i], alpha=0.7))
        star_labels.append(label)

    # 5. 信息显示
    status_text = ax_main.text(0.02, 0.98, '', transform=ax_main.transAxes,
                               fontsize=12, color='white', verticalalignment='top',
                               bbox=dict(boxstyle="round,pad=0.5",
                                         facecolor="black", alpha=0.8))

    # 设置监控图表
    for ax in [ax_energy, ax_distances]:
        ax.set_facecolor('#0a0a0a')
        ax.tick_params(colors='white')
        ax.grid(True, alpha=0.3, color='gray')

    # 能量图
    ax_energy.set_title('系统总能量守恒', color='white', fontsize=12)
    ax_energy.set_ylabel('总能量', color='white')
    energy_line, = ax_energy.plot([], [], color='cyan', linewidth=2)

    # 距离图
    ax_distances.set_title('恒星间距离变化', color='white', fontsize=12)
    ax_distances.set_ylabel('距离', color='white')
    ax_distances.set_xlabel('时间步', color='white')

    dist_lines = {}
    dist_colors = ['red', 'blue', 'green']
    dist_labels = ['Alpha-Beta', 'Alpha-Gamma', 'Beta-Gamma']

    for i, key in enumerate(['AB', 'AC', 'BC']):
        line, = ax_distances.plot([], [], color=dist_colors[i],
                                  linewidth=2, label=dist_labels[i])
        dist_lines[key] = line
    ax_distances.legend(fontsize=10)

    # 信息面板
    ax_info.set_facecolor('#0a0a0a')
    ax_info.axis('off')
    info_display = ax_info.text(0.05, 0.95, '', transform=ax_info.transAxes,
                                fontsize=11, color='white', verticalalignment='top')

    # 动画状态控制
    animation_paused = [False]  # 使用列表以便在闭包中修改

    def toggle_pause(event):
        """切换暂停/继续"""
        animation_paused[0] = not animation_paused[0]
        btn_pause.label.set_text('继续' if animation_paused[0] else '暂停')

    def update_speed_display():
        """更新速度显示"""
        speed_text.set_text(speed_controller.get_current_speed_text())
        fig.canvas.draw_idle()

    def on_speed_up(event):
        speed_controller.speed_up()
        update_speed_display()

    def on_slow_down(event):
        speed_controller.slow_down()
        update_speed_display()

    def on_reset_speed(event):
        speed_controller.reset_speed()
        update_speed_display()

    # 连接按钮事件
    btn_fast.on_clicked(on_speed_up)
    btn_slow.on_clicked(on_slow_down)
    btn_reset.on_clicked(on_reset_speed)
    btn_pause.on_clicked(toggle_pause)

    def animate_frame(frame):
        # 如果暂停则不更新
        if animation_paused[0]:
            return (stars + orbit_trails + gravity_lines + star_labels +
                    [status_text, energy_line] + list(dist_lines.values()) + [info_display])

        # 执行物理计算 - 每帧多步提高精度
        steps_per_frame = max(1, int(3 / max(0.1, system.speed_multiplier)))
        for _ in range(steps_per_frame):
            system.runge_kutta_4th_order()
            system.update_statistics()

        # 更新三个恒星的位置
        for i in range(3):
            # 更新恒星位置
            current_pos = system.positions[i].reshape(1, -1)
            stars[i].set_offsets(current_pos)

            # 添加脉动效果
            pulse = 1 + 0.2 * np.sin(system.time * 4 + i * 2)
            stars[i].set_sizes([system.base_sizes[i] * pulse])

            # 更新标签位置
            star_labels[i].set_position((system.positions[i][0] + 0.5,
                                         system.positions[i][1] + 0.5))

        # 更新轨迹
        for i in range(3):
            if len(system.trails[i]) > 1:
                trail_array = np.array(list(system.trails[i]))
                orbit_trails[i].set_data(trail_array[:, 0], trail_array[:, 1])

        # 更新引力连接线
        for i, (a, b) in enumerate(line_pairs):
            pos_a = system.positions[a]
            pos_b = system.positions[b]
            gravity_lines[i].set_data([pos_a[0], pos_b[0]], [pos_a[1], pos_b[1]])

            # 根据距离调整线条粗细和透明度
            distance = np.linalg.norm(pos_a - pos_b)
            alpha = max(0.2, min(0.8, 5.0 / distance))
            linewidth = max(1, min(4, 8.0 / distance))
            gravity_lines[i].set_alpha(alpha)
            gravity_lines[i].set_linewidth(linewidth)

        # 更新状态信息
        current_energy = system.calculate_total_energy()
        max_velocity = max([np.linalg.norm(v) for v in system.velocities])

        status_info = (
            f"模拟时间: {system.time:.2f}\n"
            f"播放速度: {system.speed_multiplier:.1f}x\n"
            f"系统总能量: {current_energy:.4f}\n"
            f"最大速度: {max_velocity:.3f}\n"
            f"计算步数: {frame * steps_per_frame}\n"
            f"\n三体位置坐标:\n"
        )

        for i in range(3):
            pos = system.positions[i]
            vel_mag = np.linalg.norm(system.velocities[i])
            status_info += f"{system.names[i]}: ({pos[0]:.2f}, {pos[1]:.2f})\n"
            status_info += f"   速度: {vel_mag:.3f}\n"

        status_text.set_text(status_info)

        # 更新能量图
        if len(system.energy_history) > 1:
            time_points = list(range(len(system.energy_history)))
            energy_line.set_data(time_points, list(system.energy_history))
            ax_energy.relim()
            ax_energy.autoscale_view()

        # 更新距离图
        if len(system.distance_history['AB']) > 1:
            time_points = list(range(len(system.distance_history['AB'])))
            for key in ['AB', 'AC', 'BC']:
                dist_lines[key].set_data(time_points, list(system.distance_history[key]))
            ax_distances.relim()
            ax_distances.autoscale_view()

        # 更新信息面板
        min_dist = min([list(system.distance_history[key])[-1]
                        for key in system.distance_history.keys()
                        if len(system.distance_history[key]) > 0])

        info_text = (
            "=== 三体系统状态 ===\n\n"
            f"恒星质量:\n"
            f"  {system.names[0]}: {system.masses[0]:.1f}M☉\n"
            f"  {system.names[1]}: {system.masses[1]:.1f}M☉\n"
            f"  {system.names[2]}: {system.masses[2]:.1f}M☉\n\n"
            f"最近距离: {min_dist:.3f}\n"
            f"引力常数: {system.G:.1f}\n\n"
            "观察要点:\n"
            "*  轨道的不规则性\n"
            "*  近距离遭遇事件\n"
            "*  能量守恒定律\n"
            "*  混沌敏感依赖性\n\n"
            "控制说明:\n"
            "*  加速/减速按钮调节播放速度\n"
            "*  暂停按钮停止/继续动画\n"
            "*  正常按钮重置为1x速度"
        )

        info_display.set_text(info_text)

        return (stars + orbit_trails + gravity_lines + star_labels +
                [status_text, energy_line] + list(dist_lines.values()) + [info_display])

    # 创建动画对象
    anim = FuncAnimation(fig, animate_frame, frames=3000,
                         interval=30, blit=False, repeat=True, cache_frame_data=False)

    # 总标题
    fig.suptitle('三体问题数值模拟:混沌引力系统(速度可控)',
                 fontsize=18, color='white', y=0.96)

    # 底部说明
    fig.text(0.02, 0.085,
             '物理原理: 三个质量不等的恒星在万有引力作用下的非周期运动 | '
             '混沌特征: 轨道不可预测、对初始条件敏感、长期行为无法确定 | '
             '数值方法: 四阶龙格-库塔法求解牛顿引力方程组',
             fontsize=10, color='white',
             bbox=dict(boxstyle="round,pad=0.5", facecolor="#1a1a2e", alpha=0.9))

    plt.tight_layout()
    plt.subplots_adjust(top=0.92, bottom=0.18)
    plt.show()

    return anim


# 启动三体动画
print("🌟 启动三体恒星系统动态模拟(带速度控制)...")
print("\n系统配置:")
print("*  三颗质量不等的恒星: Alpha(1.5M☉), Beta(1.0M☉), Gamma(1.2M☉)")
print("*  初始三角形配置,赋予复杂初始速度")
print("*  高精度数值积分(RK4)确保长期稳定性")

print("\n可视化特征:")
print("✓ 三个不同颜色的恒星实时运动")
print("✓ 彩色轨迹显示历史路径")
print("✓ 虚线显示引力相互作用")
print("✓ 恒星大小脉动模拟真实效果")
print("✓ 实时监控能量守恒和距离变化")

print("\n新增速度控制功能:")
print("🎮 减速按钮: 降低播放速度(0.1x-8x)")
print("🎮 加速按钮: 提高播放速度(0.1x-8x)")
print("🎮 正常按钮: 重置为1x正常速度")
print("🎮 暂停按钮: 暂停/继续动画播放")
print("🎮 实时速度显示: 当前播放倍数")

print("\n观察重点:")
print("🔍 轨道的复杂性和不可预测性")
print("🔍 恒星间距离的剧烈变化")
print("🔍 近距离遭遇引起的轨道突变")
print("🔍 系统总能量的精确守恒")

print("\n操作提示:")
print("💡 使用加速功能快速观察长期行为")
print("💡 使用减速功能仔细研究细节变化")
print("💡 暂停功能方便截图和观察")

print("\n正在加载动画...")

# 运行动画
animation = create_three_body_animation()

print("🎬 三体动画已启动!使用底部按钮控制播放速度...")
___

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值