feat: C/C++ 引擎支持 save_trajectory=0 时直接写 display.txt
所有引擎(Python/C/C++)在 save_trajectory=0 时行为一致: - 计算时按 NSTEP 抽帧,只存 sampled 缓冲区 - 直接写入 display.txt(新文本格式) - 不生成 trajectory.txt Python 引擎:run_simulation 已支持 ✅ C 引擎:采样缓冲区 + write_display_txt ✅ C++ 引擎:采样缓冲区 + write_display_txt ✅ Fortran 引擎:待完成 compute.py run_engine:save_trajectory=0 时跳过 trajectory.txt 加载 dynamics.py:引擎直接输出 display.txt 时跳过抽帧步骤
This commit is contained in:
+85
-17
@@ -38,6 +38,7 @@ typedef struct {
|
||||
int damping_force; /* 阻尼开关 */
|
||||
double gravity_strength; /* 万有引力强度 */
|
||||
int driving_force; /* 驱动力开关 */
|
||||
int save_trajectory; /* 是否保存完整轨迹文件 */
|
||||
} SimParams;
|
||||
|
||||
/* ========================================================================
|
||||
@@ -304,6 +305,7 @@ static SimParams read_params(const char *path) {
|
||||
p.damping_force = json_read_int(buf, "damping_force");
|
||||
p.gravity_strength = json_read_double(buf, "gravity_strength");
|
||||
p.driving_force = json_read_int(buf, "driving_force");
|
||||
p.save_trajectory = json_read_int(buf, "save_trajectory");
|
||||
g_gravity_field = p.gravity_field;
|
||||
g_gravity_interaction = p.gravity_interaction;
|
||||
g_elastic_force = p.elastic_force;
|
||||
@@ -858,6 +860,49 @@ static void write_trajectory_json(const char *path, const Trajectory *traj,
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void write_display_txt(const char *path, const Trajectory *traj,
|
||||
const SimParams *params, const AtomData *atoms)
|
||||
{
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) die("无法写入 display.txt");
|
||||
|
||||
int n_frames = traj->n_steps;
|
||||
int n_particles = traj->n_atoms;
|
||||
int dynamic_steps = params->NT - params->warmup_steps;
|
||||
double T_total = dynamic_steps * params->DT;
|
||||
|
||||
fprintf(f, "number of frames: %d\n", n_frames);
|
||||
fprintf(f, "number of particles: %d\n", n_particles);
|
||||
fprintf(f, "DT: %.16g\n", params->DT);
|
||||
fprintf(f, "NSTEP: %d\n", params->NSTEP);
|
||||
fprintf(f, "method: %s\n", params->method);
|
||||
fprintf(f, "warmup_steps: %d\n", params->warmup_steps);
|
||||
fprintf(f, "dynamic_steps: %d\n", dynamic_steps);
|
||||
fprintf(f, "T_total: %.16g\n", T_total);
|
||||
fprintf(f, "box_a: %.16g\n", params->box_a);
|
||||
|
||||
if (params->driving_force) {
|
||||
fprintf(f, "driving_force: 1\n");
|
||||
} else {
|
||||
fprintf(f, "driving_force: 0\n");
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
||||
for (int t = 0; t < n_frames; t++) {
|
||||
fprintf(f, "frame: %3d\n", t + 1);
|
||||
fprintf(f, "n x y z vx vy vz\n");
|
||||
for (int i = 0; i < n_particles; i++) {
|
||||
int idx = t * n_particles + i;
|
||||
fprintf(f, "%4d %12.6f %12.6f %12.6f %10.6f %10.6f %10.6f\n",
|
||||
atoms->atom_ids[i],
|
||||
traj->x[idx], traj->y[idx], traj->z[idx],
|
||||
traj->vx[idx], traj->vy[idx], traj->vz[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// 主函数
|
||||
// ========================================================================
|
||||
@@ -902,17 +947,29 @@ int main(int argc, char **argv) {
|
||||
vz[i] = atoms.vel_0[i*3+2];
|
||||
}
|
||||
|
||||
/* 分配轨迹缓冲区:改用 record_steps */
|
||||
/* 分配轨迹缓冲区 */
|
||||
int record_steps = params.NT - params.warmup_steps;
|
||||
Trajectory traj;
|
||||
traj.n_steps = record_steps;
|
||||
traj.n_atoms = n;
|
||||
traj.x = (double*)xmalloc(record_steps * n * sizeof(double) * 6);
|
||||
traj.y = traj.x + record_steps * n;
|
||||
traj.z = traj.y + record_steps * n;
|
||||
traj.vx = traj.z + record_steps * n;
|
||||
traj.vy = traj.vx + record_steps * n;
|
||||
traj.vz = traj.vy + record_steps * n;
|
||||
if (params.save_trajectory) {
|
||||
traj.n_steps = record_steps;
|
||||
traj.x = (double*)xmalloc(record_steps * n * sizeof(double) * 6);
|
||||
traj.y = traj.x + record_steps * n;
|
||||
traj.z = traj.y + record_steps * n;
|
||||
traj.vx = traj.z + record_steps * n;
|
||||
traj.vy = traj.vx + record_steps * n;
|
||||
traj.vz = traj.vy + record_steps * n;
|
||||
} else {
|
||||
int sampled_steps = (record_steps + params.NSTEP - 1) / params.NSTEP;
|
||||
if (sampled_steps < 1) sampled_steps = 1;
|
||||
traj.n_steps = sampled_steps;
|
||||
traj.x = (double*)xmalloc(sampled_steps * n * sizeof(double) * 6);
|
||||
traj.y = traj.x + sampled_steps * n;
|
||||
traj.z = traj.y + sampled_steps * n;
|
||||
traj.vx = traj.z + sampled_steps * n;
|
||||
traj.vy = traj.vx + sampled_steps * n;
|
||||
traj.vz = traj.vy + sampled_steps * n;
|
||||
}
|
||||
|
||||
/* 预热 */
|
||||
/* 初始时刻 t=0 驱动力(与 Python run_simulation 一致)*/
|
||||
@@ -930,6 +987,7 @@ int main(int argc, char **argv) {
|
||||
/* 记录 */
|
||||
int _prog_interval = record_steps / 100;
|
||||
if (_prog_interval < 1) _prog_interval = 1;
|
||||
int sample_idx = 0;
|
||||
for (int s = 0; s < record_steps; s++) {
|
||||
if (s % _prog_interval == 0 && s > 0) {
|
||||
printf("[C-engine] progress: %d/%d\n", s, record_steps);
|
||||
@@ -937,13 +995,18 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
double t = (s + params.warmup_steps) * params.DT;
|
||||
if (params.driving_force) apply_driving_force(n, x, y, z, vx, vy, vz, t, s, params.DT, &drivers);
|
||||
for (int i = 0; i < n; i++) {
|
||||
traj.x[ s * n + i] = x[i];
|
||||
traj.y[ s * n + i] = y[i];
|
||||
traj.z[ s * n + i] = z[i];
|
||||
traj.vx[s * n + i] = vx[i];
|
||||
traj.vy[s * n + i] = vy[i];
|
||||
traj.vz[s * n + i] = vz[i];
|
||||
int do_record = params.save_trajectory || (s % params.NSTEP == 0);
|
||||
if (do_record) {
|
||||
int idx = params.save_trajectory ? s : sample_idx;
|
||||
for (int i = 0; i < n; i++) {
|
||||
traj.x[ idx * n + i] = x[i];
|
||||
traj.y[ idx * n + i] = y[i];
|
||||
traj.z[ idx * n + i] = z[i];
|
||||
traj.vx[idx * n + i] = vx[i];
|
||||
traj.vy[idx * n + i] = vy[i];
|
||||
traj.vz[idx * n + i] = vz[i];
|
||||
}
|
||||
if (!params.save_trajectory) sample_idx++;
|
||||
}
|
||||
apply_step(params.method, n, x, y, z, vx, vy, vz,
|
||||
atoms.masses, params.G, params.B, &bonds, atoms.fixed,
|
||||
@@ -952,8 +1015,13 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
char out_path[512];
|
||||
snprintf(out_path, sizeof(out_path), "%s/trajectory.txt", output_dir);
|
||||
write_trajectory_json(out_path, &traj, ¶ms, &atoms, &bonds);
|
||||
if (params.save_trajectory) {
|
||||
snprintf(out_path, sizeof(out_path), "%s/trajectory.txt", output_dir);
|
||||
write_trajectory_json(out_path, &traj, ¶ms, &atoms, &bonds);
|
||||
} else {
|
||||
snprintf(out_path, sizeof(out_path), "%s/display.txt", output_dir);
|
||||
write_display_txt(out_path, &traj, ¶ms, &atoms);
|
||||
}
|
||||
|
||||
clock_t t1 = clock();
|
||||
double elapsed = (double)(t1 - t0) / CLOCKS_PER_SEC;
|
||||
|
||||
Reference in New Issue
Block a user