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,280 @@
"""
三体问题配置管理模块
"""
import numpy as np
from typing import List, Dict, Any, Optional
from .particle import Particle
class ThreeBodyConfig:
"""三体问题配置类"""
@staticmethod
def create_figure8_config() -> List[Particle]:
"""
创建8字形轨道配置著名的稳定三体轨道
返回:
三个质点的列表
"""
# 8字形轨道的初始条件等质量
m = 1.0 # 质量
# 位置 (Chenciner & Montgomery, 2000)
r1 = np.array([0.97000436, -0.24308753, 0.0])
r2 = np.array([-0.97000436, 0.24308753, 0.0])
r3 = np.array([0.0, 0.0, 0.0])
# 速度
v1 = np.array([0.466203685, 0.43236573, 0.0])
v2 = np.array([0.466203685, 0.43236573, 0.0])
v3 = np.array([-0.93240737, -0.86473146, 0.0])
particles = [
Particle(mass=m, position=r1, velocity=v1, name="Star A", color="red"),
Particle(mass=m, position=r2, velocity=v2, name="Star B", color="green"),
Particle(mass=m, position=r3, velocity=v3, name="Star C", color="blue")
]
return particles
@staticmethod
def create_lagrange_point_config(lagrange_point: int = 4) -> List[Particle]:
"""
创建拉格朗日点配置
参数:
lagrange_point: 拉格朗日点编号 (4=L4, 5=L5)
返回:
三个质点的列表
"""
if lagrange_point not in [4, 5]:
raise ValueError("lagrange_point 必须是 4 (L4) 或 5 (L5)")
# 大质量天体(类似太阳)
m_sun = 1.0
# 小质量天体(类似地球)
m_earth = 3e-6 # 地球质量/太阳质量
# 测试质点(类似小行星)
m_test = 1e-8
# 大质量天体在原点
r_sun = np.array([0.0, 0.0, 0.0])
v_sun = np.array([0.0, 0.0, 0.0])
# 小质量天体在圆形轨道上1 AU距离
r_earth = np.array([1.0, 0.0, 0.0])
# 圆形轨道速度v = sqrt(G*M/r)
v_earth = np.array([0.0, 2*np.pi, 0.0]) # 2π AU/年
# 拉格朗日点位置(等边三角形)
if lagrange_point == 4: # L4
r_test = np.array([0.5, np.sqrt(3)/2, 0.0])
else: # L5
r_test = np.array([0.5, -np.sqrt(3)/2, 0.0])
# 测试质点的速度(与地球相同角速度)
v_test = np.array([-np.sqrt(3)/2 * 2*np.pi, 0.5 * 2*np.pi, 0.0])
particles = [
Particle(mass=m_sun, position=r_sun, velocity=v_sun, name="Sun", color="yellow"),
Particle(mass=m_earth, position=r_earth, velocity=v_earth, name="Earth", color="blue"),
Particle(mass=m_test, position=r_test, velocity=v_test, name="Test", color="gray")
]
return particles
@staticmethod
def create_random_config(masses: Optional[List[float]] = None,
position_range: float = 2.0,
velocity_scale: float = 1.0) -> List[Particle]:
"""
创建随机初始条件配置
参数:
masses: 质量列表如果为None则使用随机质量
position_range: 位置范围±position_range
velocity_scale: 速度缩放因子
返回:
三个质点的列表
"""
if masses is None:
# 随机质量在0.5到2.0之间)
masses = np.random.uniform(0.5, 2.0, 3)
if len(masses) != 3:
raise ValueError("需要恰好3个质量值")
particles = []
colors = ['red', 'green', 'blue']
names = ['Star A', 'Star B', 'Star C']
for i in range(3):
# 随机位置
position = np.random.uniform(-position_range, position_range, 3)
# 随机速度(确保系统总动量接近零)
velocity = np.random.uniform(-velocity_scale, velocity_scale, 3)
particles.append(
Particle(mass=masses[i], position=position, velocity=velocity,
name=names[i], color=colors[i])
)
# 调整速度使系统总动量接近零
total_momentum = sum(p.mass * p.velocity for p in particles)
total_mass = sum(p.mass for p in particles)
for p in particles:
p.velocity -= total_momentum / total_mass
return particles
@staticmethod
def create_binary_star_config() -> List[Particle]:
"""
创建双星系统+测试质点配置
返回:
三个质点的列表
"""
# 双星质量
m1 = 1.0
m2 = 0.8
# 双星位置(在椭圆轨道上)
# 半长轴
a = 1.0
# 偏心率
e = 0.3
# 质心在原点
r1 = np.array([-m2/(m1+m2) * a * (1+e), 0.0, 0.0])
r2 = np.array([m1/(m1+m2) * a * (1+e), 0.0, 0.0])
# 计算轨道速度(简化圆形轨道近似)
# 对于椭圆轨道,速度更复杂,这里使用简化
orbital_speed = np.sqrt(4*np.pi**2 * (m1+m2) / (2*a))
v1 = np.array([0.0, orbital_speed * m2/(m1+m2), 0.0])
v2 = np.array([0.0, -orbital_speed * m1/(m1+m2), 0.0])
# 测试质点(小质量)
m_test = 0.01
r_test = np.array([0.0, 2.0, 0.0])
v_test = np.array([0.5, 0.0, 0.0])
particles = [
Particle(mass=m1, position=r1, velocity=v1, name="Primary", color="red"),
Particle(mass=m2, position=r2, velocity=v2, name="Secondary", color="green"),
Particle(mass=m_test, position=r_test, velocity=v_test, name="Test", color="blue")
]
return particles
@staticmethod
def create_custom_config(config_dict: Dict[str, Any]) -> List[Particle]:
"""
从字典创建自定义配置
参数:
config_dict: 包含配置信息的字典
返回:
三个质点的列表
"""
particles = []
for i in range(3):
key = f"particle_{i+1}"
if key not in config_dict:
raise ValueError(f"配置中缺少 {key}")
p_config = config_dict[key]
particle = Particle(
mass=p_config.get('mass', 1.0),
position=np.array(p_config.get('position', [0.0, 0.0, 0.0])),
velocity=np.array(p_config.get('velocity', [0.0, 0.0, 0.0])),
name=p_config.get('name', f"Particle {i+1}"),
color=p_config.get('color', None)
)
particles.append(particle)
return particles
@staticmethod
def save_config(particles: List[Particle], filename: str):
"""
保存配置到文件
参数:
particles: 质点列表
filename: 文件名
"""
config_dict = {}
for i, p in enumerate(particles):
config_dict[f"particle_{i+1}"] = {
'mass': float(p.mass),
'position': p.position.tolist(),
'velocity': p.velocity.tolist(),
'name': p.name,
'color': p.color
}
import json
with open(filename, 'w') as f:
json.dump(config_dict, f, indent=2)
print(f"配置已保存到: {filename}")
@staticmethod
def load_config(filename: str) -> List[Particle]:
"""
从文件加载配置
参数:
filename: 文件名
返回:
三个质点的列表
"""
import json
with open(filename, 'r') as f:
config_dict = json.load(f)
return ThreeBodyConfig.create_custom_config(config_dict)
@staticmethod
def print_config_summary(particles: List[Particle]):
"""打印配置摘要"""
print("=" * 60)
print("三体问题配置摘要")
print("=" * 60)
total_mass = 0.0
total_momentum = np.zeros(3)
total_angular_momentum = np.zeros(3)
for i, p in enumerate(particles):
print(f"\n质点 {i+1} ({p.name}):")
print(f" 质量: {p.mass:.6f} M_sun")
print(f" 位置: [{p.position[0]:.6f}, {p.position[1]:.6f}, {p.position[2]:.6f}] AU")
print(f" 速度: [{p.velocity[0]:.6f}, {p.velocity[1]:.6f}, {p.velocity[2]:.6f}] AU/yr")
total_mass += p.mass
total_momentum += p.mass * p.velocity
angular_momentum = np.cross(p.position, p.mass * p.velocity)
total_angular_momentum += angular_momentum
print("\n" + "=" * 60)
print("系统总质量: {:.6f} M_sun".format(total_mass))
print("系统总动量: [{:.6e}, {:.6e}, {:.6e}]".format(
total_momentum[0], total_momentum[1], total_momentum[2]))
print("系统总角动量: [{:.6e}, {:.6e}, {:.6e}]".format(
total_angular_momentum[0], total_angular_momentum[1], total_angular_momentum[2]))
print("=" * 60)