pc-1
This commit is contained in:
dison0331-ThinkPad
2026-03-11 21:32:58 +08:00
commit 8c8ad9fe07
29 changed files with 4005 additions and 0 deletions

View File

@@ -0,0 +1,203 @@
"""
8字形轨道示例 - 著名的稳定三体轨道
"""
import numpy as np
import matplotlib.pyplot as plt
import sys
import os
# 添加父目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from three_body_problem import ThreeBodySolver, ThreeBodyConfig, ThreeBodyVisualizer
def run_figure8_example():
"""运行8字形轨道示例"""
print("=" * 60)
print("8字形轨道示例")
print("=" * 60)
# 创建8字形轨道配置
particles = ThreeBodyConfig.create_figure8_config()
# 打印配置摘要
ThreeBodyConfig.print_config_summary(particles)
# 创建求解器
dt = 0.001 # 时间步长(年)
solver = ThreeBodySolver(particles, dt=dt)
# 模拟10年
total_time = 10.0
print(f"\n开始模拟,总时间: {total_time}年,时间步长: {dt}")
solver.simulate(total_time=total_time, progress_interval=2000)
# 计算守恒误差
momentum_error, angular_momentum_error, energy_error = solver.get_conservation_errors()
print(f"\n守恒定律误差:")
print(f" 动量误差: {momentum_error:.6e}")
print(f" 角动量误差: {angular_momentum_error:.6e}")
print(f" 能量相对误差: {energy_error:.6e}")
# 可视化
print("\n生成可视化图形...")
visualizer = ThreeBodyVisualizer(figsize=(14, 10))
# 创建3D轨迹图
plt.figure(figsize=(14, 10))
# 3D轨迹
ax1 = plt.subplot(2, 2, 1, projection='3d')
trajectories = solver.get_trajectories()
colors = ['red', 'green', 'blue']
for i, (traj, particle) in enumerate(zip(trajectories, solver.particles)):
color = particle.color if particle.color else colors[i % len(colors)]
label = particle.name if particle.name else f"质点 {i+1}"
ax1.plot(traj[:, 0], traj[:, 1], traj[:, 2],
color=color, alpha=0.7, linewidth=1.5, label=label)
ax1.scatter(traj[-1, 0], traj[-1, 1], traj[-1, 2],
color=color, s=100, edgecolors='black', linewidth=1.5)
# 绘制质心
com = solver.get_center_of_mass()
ax1.scatter(com[0], com[1], com[2],
color='black', marker='x', s=200, label='质心', linewidth=2)
ax1.set_xlabel('X (AU)')
ax1.set_ylabel('Y (AU)')
ax1.set_zlabel('Z (AU)')
ax1.set_title('8字形轨道 - 3D视图')
ax1.legend()
ax1.grid(True, alpha=0.3)
# XY平面投影
ax2 = plt.subplot(2, 2, 2)
for i, (traj, particle) in enumerate(zip(trajectories, solver.particles)):
color = particle.color if particle.color else colors[i % len(colors)]
label = particle.name if particle.name else f"质点 {i+1}"
ax2.plot(traj[:, 0], traj[:, 1], color=color, alpha=0.7, linewidth=1.5, label=label)
ax2.scatter(traj[-1, 0], traj[-1, 1], color=color, s=100, edgecolors='black', linewidth=1.5)
ax2.scatter(com[0], com[1], color='black', marker='x', s=200, label='质心', linewidth=2)
ax2.set_xlabel('X (AU)')
ax2.set_ylabel('Y (AU)')
ax2.set_title('XY平面投影')
ax2.legend()
ax2.grid(True, alpha=0.3)
ax2.set_aspect('equal', adjustable='box')
# XZ平面投影
ax3 = plt.subplot(2, 2, 3)
for i, (traj, particle) in enumerate(zip(trajectories, solver.particles)):
color = particle.color if particle.color else colors[i % len(colors)]
label = particle.name if particle.name else f"质点 {i+1}"
ax3.plot(traj[:, 0], traj[:, 2], color=color, alpha=0.7, linewidth=1.5, label=label)
ax3.scatter(traj[-1, 0], traj[-1, 2], color=color, s=100, edgecolors='black', linewidth=1.5)
ax3.scatter(com[0], com[2], color='black', marker='x', s=200, label='质心', linewidth=2)
ax3.set_xlabel('X (AU)')
ax3.set_ylabel('Z (AU)')
ax3.set_title('XZ平面投影')
ax3.legend()
ax3.grid(True, alpha=0.3)
ax3.set_aspect('equal', adjustable='box')
# YZ平面投影
ax4 = plt.subplot(2, 2, 4)
for i, (traj, particle) in enumerate(zip(trajectories, solver.particles)):
color = particle.color if particle.color else colors[i % len(colors)]
label = particle.name if particle.name else f"质点 {i+1}"
ax4.plot(traj[:, 1], traj[:, 2], color=color, alpha=0.7, linewidth=1.5, label=label)
ax4.scatter(traj[-1, 1], traj[-1, 2], color=color, s=100, edgecolors='black', linewidth=1.5)
ax4.scatter(com[1], com[2], color='black', marker='x', s=200, label='质心', linewidth=2)
ax4.set_xlabel('Y (AU)')
ax4.set_ylabel('Z (AU)')
ax4.set_title('YZ平面投影')
ax4.legend()
ax4.grid(True, alpha=0.3)
ax4.set_aspect('equal', adjustable='box')
plt.suptitle('8字形三体轨道', fontsize=16, fontweight='bold')
plt.tight_layout()
# 保存图形
output_file = "figure8_orbit.png"
plt.savefig(output_file, dpi=300, bbox_inches='tight')
print(f"\n图形已保存到: {output_file}")
# 显示图形
plt.show()
return solver
def analyze_figure8_stability():
"""分析8字形轨道的稳定性"""
print("\n" + "=" * 60)
print("8字形轨道稳定性分析")
print("=" * 60)
# 创建8字形轨道配置
particles = ThreeBodyConfig.create_figure8_config()
# 测试不同时间步长
time_steps = [0.01, 0.005, 0.001, 0.0005]
total_time = 5.0
results = []
for dt in time_steps:
print(f"\n测试时间步长: {dt}")
solver = ThreeBodySolver([p.copy() for p in particles], dt=dt)
solver.simulate(total_time=total_time, progress_interval=10000)
# 计算守恒误差
momentum_error, angular_momentum_error, energy_error = solver.get_conservation_errors()
results.append({
'dt': dt,
'momentum_error': momentum_error,
'angular_momentum_error': angular_momentum_error,
'energy_error': energy_error
})
print(f" 能量相对误差: {energy_error:.6e}")
# 绘制误差随步长变化
plt.figure(figsize=(10, 6))
dts = [r['dt'] for r in results]
energy_errors = [r['energy_error'] for r in results]
plt.loglog(dts, energy_errors, 'o-', linewidth=2, markersize=8)
plt.xlabel('时间步长 (年)', fontsize=12)
plt.ylabel('能量相对误差', fontsize=12)
plt.title('8字形轨道数值误差分析', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, which='both')
# 添加参考线(四阶精度)
ref_dt = np.array(dts)
ref_error = 1e-4 * (ref_dt / 0.001)**4
plt.loglog(ref_dt, ref_error, 'r--', alpha=0.7, label='四阶精度参考线')
plt.legend()
plt.tight_layout()
output_file = "figure8_stability_analysis.png"
plt.savefig(output_file, dpi=300, bbox_inches='tight')
print(f"\n稳定性分析图形已保存到: {output_file}")
plt.show()
if __name__ == "__main__":
# 运行主示例
solver = run_figure8_example()
# 运行稳定性分析(可选)
# analyze_figure8_stability()