fix: Fortran engine use_marker/alpha header passthrough + case04 Moon orbit fix

- engines/fortran/main.f90:
  - 新增 use_marker 和 alpha_str 的读取、传递、写入 display.txt header
  - 新增 json_get_alpha 函数兼容 JSON 单值或 6 元数组
- engines/release/: 引擎校准缓存 & fortran.json 参数
- examples/case04/: 修正月球位置 (11.5→10.5) 和速度 (526→647),
  地月距缩至希尔半径以内 (0.5 < 1.0), 新增希尔半径验证说明
- examples/Readme.html: case04/case09 描述更新
This commit is contained in:
2026-06-19 08:05:05 +08:00
parent c8d12e7f45
commit 6c06c00f4b
8 changed files with 158 additions and 35 deletions
+70 -7
View File
@@ -21,6 +21,8 @@ program dynamics_f90
integer :: driving_force
double precision :: gravity_strength
character(len=32) :: method
integer :: use_marker
character(len=512) :: alpha_str
double precision :: t0, t1, elapsed, tw
! 原子数据
@@ -71,7 +73,8 @@ program dynamics_f90
! 读取 param.json
call read_params(param_path, box_a, NT, DT, NSTEP, warmup_steps, method, G, B, &
gravity_field, gravity_interaction, &
elastic_force, damping_force, gravity_strength, driving_force)
elastic_force, damping_force, gravity_strength, driving_force, &
use_marker, alpha_str)
! 读取 coord.txt
call read_coord(input_dir, n_atoms, atom_ids, masses, radii, pos_0, vel_0, fixed)
@@ -201,7 +204,8 @@ program dynamics_f90
traj_x, traj_y, traj_z, traj_vx, traj_vy, traj_vz, &
NT, DT, NSTEP, warmup_steps, method, G, B, &
n_bonds, gravity_field, elastic_force, damping_force, &
driving_force, box_a, gravity_strength)
driving_force, box_a, gravity_strength, &
use_marker, alpha_str)
call cpu_time(t1)
elapsed = t1 - t0
@@ -228,15 +232,17 @@ contains
! ========================================================================
subroutine read_params(path, box_a, NT, DT, NSTEP, warmup_steps, method, G, B, &
gravity_field, gravity_interaction, &
elastic_force, damping_force, gravity_strength, driving_force)
elastic_force, damping_force, gravity_strength, driving_force, &
use_marker, alpha_str)
character(len=*), intent(in) :: path
double precision, intent(out) :: box_a, DT, G(3), B(3), gravity_strength
integer, intent(out) :: NT, NSTEP, warmup_steps
integer, intent(out) :: gravity_field, gravity_interaction, elastic_force, damping_force, driving_force
character(len=*), intent(out) :: method
integer, intent(out) :: use_marker
character(len=*), intent(out) :: method, alpha_str
character(len=8096) :: buf
character(len=256) :: line
integer :: u, ios
integer :: u, ios, i
box_a = 10.0d0; NT = 10000; DT = 0.001d0; NSTEP = 100; warmup_steps = 0
method = 'leapfrog'
@@ -244,6 +250,8 @@ subroutine read_params(path, box_a, NT, DT, NSTEP, warmup_steps, method, G, B, &
gravity_field = 1; gravity_interaction = 0
elastic_force = 1; damping_force = 0; gravity_strength = 1.0d0
driving_force = 0
use_marker = 0
alpha_str = '0.2'
open(newunit=u, file=trim(path), status='old', action='read', iostat=ios)
if (ios /= 0) then
@@ -274,6 +282,8 @@ subroutine read_params(path, box_a, NT, DT, NSTEP, warmup_steps, method, G, B, &
damping_force = json_get_int(buf, 'damping_force', 0)
gravity_strength = json_get_double(buf, 'gravity_strength', 1.0d0)
driving_force = json_get_int(buf, 'driving_force', 0)
use_marker = json_get_int(buf, 'use_marker', 0)
call json_get_alpha(buf, 'alpha', alpha_str)
end subroutine read_params
! ========================================================================
@@ -323,6 +333,55 @@ subroutine json_get_double3(buf, key, vals)
end do
end subroutine json_get_double3
! 读取 alpha:兼容单值 (0.2) 或 6 元数组 [0.0,0.0,0.0,0.0,0.0,0.0]
! 输出为逗号分隔字符串,与 draw.py 的解析格式一致
subroutine json_get_alpha(buf, key, val)
character(len=*), intent(in) :: buf, key
character(len=*), intent(out) :: val
double precision :: d6(6)
integer :: p, i, ios
character(len=32) :: tmp
val = '0.2'
p = index(buf, '"' // key // '"')
if (p == 0) return
p = index(buf(p:), ':') + p
! skip whitespace
do while (p <= len(buf) .and. (buf(p:p) == ':' .or. buf(p:p) == ' ' &
.or. buf(p:p) == char(9) .or. buf(p:p) == char(10)))
p = p + 1
end do
if (buf(p:p) == '[') then
! 6 元数组
d6 = 0.2d0
p = p + 1
do i = 1, 6
do while (p <= len(buf) .and. (buf(p:p) == ' ' .or. buf(p:p) == ',' &
.or. buf(p:p) == char(9) .or. buf(p:p) == char(10)))
p = p + 1
end do
if (p > len(buf) .or. buf(p:p) == ']') exit
read(buf(p:), *, iostat=ios) d6(i)
if (ios /= 0) exit
do while (p <= len(buf) .and. buf(p:p) /= ',' .and. buf(p:p) /= ']')
p = p + 1
end do
end do
val = ''
do i = 1, 6
write(tmp, '(f0.6)') d6(i)
if (i > 1) val = trim(val) // ','
val = trim(val) // trim(tmp)
end do
else
! 单值标量
read(buf(p:), *, iostat=ios) d6(1)
if (ios == 0) then
write(tmp, '(f0.6)') d6(1)
val = trim(tmp)
end if
end if
end subroutine json_get_alpha
! 从 JSON 中读取字符串值
subroutine json_get_string(buf, key, val)
character(len=*), intent(in) :: buf, key
@@ -999,10 +1058,12 @@ subroutine write_display_txt(outdir, n_frames, nat, aid, &
tx, ty, tz, tvx, tvy, tvz, &
NT, DT, NSTEP, warmup, method, G, B, &
nb, gravity_field, elastic_force, damping_force, &
driving_force, box_a, gravity_strength)
character(len=*), intent(in) :: outdir, method
driving_force, box_a, gravity_strength, &
use_marker, alpha_str)
character(len=*), intent(in) :: outdir, method, alpha_str
integer, intent(in) :: n_frames, nat, NT, NSTEP, warmup, nb
integer, intent(in) :: gravity_field, elastic_force, damping_force, driving_force
integer, intent(in) :: use_marker
integer, intent(in) :: aid(nat)
double precision, intent(in) :: tx(n_frames, nat), ty(n_frames, nat), tz(n_frames, nat)
double precision, intent(in) :: tvx(n_frames, nat), tvy(n_frames, nat), tvz(n_frames, nat)
@@ -1051,6 +1112,8 @@ subroutine write_display_txt(outdir, n_frames, nat, aid, &
write(buf, '("Y_MAX: ", g0)') box_a; write(u, '(a)') trim(buf)
write(buf, '("Z_MIN: ", g0)') -box_a; write(u, '(a)') trim(buf)
write(buf, '("Z_MAX: ", g0)') box_a; write(u, '(a)') trim(buf)
write(u, '("use_marker: ", i0)') use_marker
write(u, '("alpha: ", a)') trim(alpha_str)
! ── frame data ────────────────────────────────────────────────────────
do f = 1, n_frames