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:
2026-06-12 18:36:37 +08:00
parent e1ade53fff
commit e62e536cee
12 changed files with 627 additions and 355 deletions
+64 -39
View File
@@ -107,6 +107,24 @@ program dynamics_f90
allocate(traj_x(record_steps, n), traj_y(record_steps, n), traj_z(record_steps, n))
allocate(traj_vx(record_steps, n), traj_vy(record_steps, n), traj_vz(record_steps, n))
! 真蛙跳初始化:v(0) 反推 v(-dt/2) = v(0) - 0.5*a_c(0)*dt
if (trim(method) == 'leapfrog') then
block
double precision :: ax0(n), ay0(n), az0(n)
integer :: ii
call accel_conservative(n, x, y, z, masses, G, &
n_bonds, bond_pairs, bond_stiffness, bond_rest_lengths, &
gravity_field, gravity_interaction, &
elastic_force, gravity_strength, ax0, ay0, az0)
do ii = 1, n
if (fixed(ii,1) /= 0 .and. fixed(ii,2) /= 0 .and. fixed(ii,3) /= 0) cycle
vx(ii) = vx(ii) - 0.5d0 * ax0(ii) * DT
vy(ii) = vy(ii) - 0.5d0 * ay0(ii) * DT
vz(ii) = vz(ii) - 0.5d0 * az0(ii) * DT
end do
end block
end if
! 预热
! 初始时刻 t=0 驱动力(与 Python run_simulation 一致)
if (driving_force /= 0 .and. n_drivers > 0) then
@@ -524,6 +542,24 @@ pure subroutine accel(n, x, y, z, vx, vy, vz, m, G, B, &
end if
end subroutine accel
! 保守力加速度(不含阻尼),供真蛙跳法专用。
! 传入零速度、零 B 调用 accel,阻尼项 -B*v/m 自动为零。
subroutine accel_conservative(n, x, y, z, m, G, nb, bp, bk, br, &
gravity_field, gravity_interaction, &
elastic_force, gravity_strength, ax, ay, az)
integer, intent(in) :: n, nb, bp(nb, 2)
integer, intent(in) :: gravity_field, gravity_interaction, elastic_force
double precision, intent(in) :: x(n), y(n), z(n), m(n), G(3)
double precision, intent(in) :: bk(nb), br(nb), gravity_strength
double precision, intent(out) :: ax(n), ay(n), az(n)
double precision :: v0(n), B0(3)
v0 = 0.0d0
B0 = 0.0d0
call accel(n, x, y, z, v0, v0, v0, m, G, B0, nb, bp, bk, br, &
gravity_field, gravity_interaction, &
elastic_force, 0, gravity_strength, ax, ay, az)
end subroutine accel_conservative
! 边界条件:clamp 位置 + 速度反转
subroutine limit_in_box(pos, vel, lo, hi)
double precision, intent(inout) :: pos, vel
@@ -652,7 +688,13 @@ subroutine midpoint_step(n, x, y, z, vx, vy, vz, m, G, B, &
end do
end subroutine midpoint_step
! ── 蛙跳法(Velocity-Verlet)──
! 真蛙跳一步:x(t), v(t-dt/2) → x(t+dt), v(t+dt/2)
!
! 无阻尼:纯保守蛙跳,每步 1 次力计算,辛积分器。
! v(t+dt/2) = v(t-dt/2) + a_c(t)*dt
!
! 有阻尼:半隐式处理,仍 1 次力计算,对任意阻尼无条件稳定。
! v(t+dt/2) = [v(t-dt/2)*(1-α) + a_c(t)*dt] / (1+α),α = B*dt/(2m)
subroutine leapfrog_full(n, x, y, z, vx, vy, vz, m, G, B, &
nb, bp, bk, br, fixed, dt, &
gravity_field, gravity_interaction, &
@@ -662,53 +704,36 @@ subroutine leapfrog_full(n, x, y, z, vx, vy, vz, m, G, B, &
double precision, intent(inout) :: x(n), y(n), z(n), vx(n), vy(n), vz(n)
double precision, intent(in) :: m(n), G(3), B(3), bk(nb), br(nb), dt, gravity_strength
double precision :: ax(n), ay(n), az(n)
double precision :: dmp_vx(n), dmp_vy(n), dmp_vz(n)
double precision :: gx, gy, gz
double precision :: alphax, alphay, alphaz
logical :: has_damping
integer :: i
call accel(n, x, y, z, vx, vy, vz, m, G, B, nb, bp, bk, br, &
gravity_field, gravity_interaction, &
elastic_force, damping_force, gravity_strength, ax, ay, az)
! 1 次保守力计算(不含阻尼)
call accel_conservative(n, x, y, z, m, G, nb, bp, bk, br, &
gravity_field, gravity_interaction, &
elastic_force, gravity_strength, ax, ay, az)
has_damping = (damping_force /= 0) .and. &
(B(1) /= 0.0d0 .or. B(2) /= 0.0d0 .or. B(3) /= 0.0d0)
! 速度半步推
do i = 1, n
if (fixed(i,1) /= 0 .and. fixed(i,2) /= 0 .and. fixed(i,3) /= 0) cycle
vx(i) = vx(i) + ax(i) * dt * 0.5d0
vy(i) = vy(i) + ay(i) * dt * 0.5d0
vz(i) = vz(i) + az(i) * dt * 0.5d0
end do
! 全推位置(不含边界)
do i = 1, n
if (fixed(i,1) /= 0 .and. fixed(i,2) /= 0 .and. fixed(i,3) /= 0) cycle
if (has_damping) then
alphax = B(1) * dt / (2.0d0 * m(i))
alphay = B(2) * dt / (2.0d0 * m(i))
alphaz = B(3) * dt / (2.0d0 * m(i))
vx(i) = (vx(i) * (1.0d0 - alphax) + ax(i) * dt) / (1.0d0 + alphax)
vy(i) = (vy(i) * (1.0d0 - alphay) + ay(i) * dt) / (1.0d0 + alphay)
vz(i) = (vz(i) * (1.0d0 - alphaz) + az(i) * dt) / (1.0d0 + alphaz)
else
vx(i) = vx(i) + ax(i) * dt
vy(i) = vy(i) + ay(i) * dt
vz(i) = vz(i) + az(i) * dt
end if
x(i) = x(i) + vx(i) * dt
y(i) = y(i) + vy(i) * dt
z(i) = z(i) + vz(i) * dt
end do
! 隐式阻尼处理(用临时数组 dmp_v,不覆盖 vx/vy/vz
do i = 1, n
if (fixed(i,1) /= 0 .and. fixed(i,2) /= 0 .and. fixed(i,3) /= 0) then
dmp_vx(i) = 0; dmp_vy(i) = 0; dmp_vz(i) = 0; cycle
end if
gx = B(1) / m(i); gy = B(2) / m(i); gz = B(3) / m(i)
dmp_vx(i) = (vx(i) + 0.5d0 * G(1) * dt) / (1.0d0 + 0.5d0 * gx * dt)
dmp_vy(i) = (vy(i) + 0.5d0 * G(2) * dt) / (1.0d0 + 0.5d0 * gy * dt)
dmp_vz(i) = (vz(i) + 0.5d0 * G(3) * dt) / (1.0d0 + 0.5d0 * gz * dt)
end do
! 用新位置 + 阻尼速度重算加速度
call accel(n, x, y, z, dmp_vx, dmp_vy, dmp_vz, m, G, B, nb, bp, bk, br, &
gravity_field, gravity_interaction, &
elastic_force, damping_force, gravity_strength, ax, ay, az)
! 速度后半步:v = v_half + 0.5*a_next*dtvx 仍为 v_half
do i = 1, n
if (fixed(i,1) /= 0 .and. fixed(i,2) /= 0 .and. fixed(i,3) /= 0) cycle
vx(i) = vx(i) + ax(i) * dt * 0.5d0
vy(i) = vy(i) + ay(i) * dt * 0.5d0
vz(i) = vz(i) + az(i) * dt * 0.5d0
end do
end subroutine leapfrog_full
! ── 分发器 + 边界条件 + 自由度约束 ──