feat: 真蛙跳法重构(Python/C/C++/Fortran 四引擎统一)
- 新增 compute_accel_conservative / accel_conservative: 保守力加速度(弹簧+重力+原子间引力),不含阻尼,供蛙跳专用 - 重写 leapfrog_step / leapfrog_full: - 无阻尼:纯辛积分器,每步 1 次力计算(原 Velocity-Verlet 需 2 次) - 有阻尼:半隐式处理 v(t+dt/2)=[v(t-dt/2)*(1-α)+a_c*dt]/(1+α),无条件稳定 - 主循环加初始化反向半步 v(-dt/2)=v(0)-0.5*a_c(0)*dt - 修复 C/C++ number of frames 字段写采样帧数而非总积分步数的 bug - Python 引擎:新增 display.npz 二进制格式,draw.py/plot_wave.py 优先读取 - 编译参数统一为 -O3 -march=native -ffast-math
This commit is contained in:
@@ -30,16 +30,21 @@ else:
|
||||
output_dir = compute.get_output_dir(script_dir)
|
||||
os.environ["DYNAMICS_OUTPUT_DIR"] = output_dir
|
||||
disp_path = os.path.join(output_dir, "display.txt")
|
||||
npz_path = os.path.join(output_dir, "display.npz")
|
||||
|
||||
if not os.path.exists(disp_path):
|
||||
if not os.path.exists(npz_path) and not os.path.exists(disp_path):
|
||||
raise FileNotFoundError(
|
||||
f"找不到 display.txt!\n"
|
||||
f"期望路径: {disp_path}\n"
|
||||
f"找不到 display.npz 或 display.txt!\n"
|
||||
f"期望路径: {output_dir}\n"
|
||||
f"请先运行 compute.py 计算轨迹,再运行 sample.py 生成显示数组。\n"
|
||||
f"用法: python draw.py [案例输出目录]"
|
||||
)
|
||||
|
||||
disp_data = compute.load_display_txt(disp_path)
|
||||
# 优先读二进制 npz(加载速度约快 5-10x)
|
||||
if os.path.exists(npz_path):
|
||||
disp_data = compute.load_display_npz(npz_path)
|
||||
else:
|
||||
disp_data = compute.load_display_txt(disp_path)
|
||||
h = disp_data["header_fields"]
|
||||
|
||||
# 全原子帧数据
|
||||
@@ -94,7 +99,7 @@ try:
|
||||
alpha_list = [float(x) for x in raw_alpha.split(",")]
|
||||
if len(alpha_list) != 6:
|
||||
alpha_list = alpha_list * 6
|
||||
except:
|
||||
except (ValueError, AttributeError):
|
||||
alpha_list = [float(raw_alpha)] * 6
|
||||
|
||||
# 绘图参数
|
||||
@@ -514,8 +519,9 @@ def handle_mouse_press(event):
|
||||
def _update_atom_positions(f_idx):
|
||||
"""更新所有原子到第 f_idx 帧的位置。"""
|
||||
if USE_MARKER:
|
||||
for i in range(N_ATOMS):
|
||||
marker_pos[i] = [DISP_ALL_X[f_idx, i], DISP_ALL_Y[f_idx, i], DISP_ALL_Z[f_idx, i]]
|
||||
marker_pos[:, 0] = DISP_ALL_X[f_idx]
|
||||
marker_pos[:, 1] = DISP_ALL_Y[f_idx]
|
||||
marker_pos[:, 2] = DISP_ALL_Z[f_idx]
|
||||
balls.set_data(pos=marker_pos)
|
||||
else:
|
||||
for i in range(N_ATOMS):
|
||||
|
||||
Reference in New Issue
Block a user