fix: driven atoms now oscillate around their initial equilibrium position
Previously, apply_driving_force set absolute position to A*cos(2π f t + φ), ignoring the atom's initial coordinates. For atoms not at the origin (e.g., atom 120 at x=119), this incorrectly forced them back toward the origin each step, causing severe distortion and numerical explosion. Fix: store each driven atom's initial position as eq_pos/eq_x/eq_y/eq_z at load time; position is now eq + A*cos(2π f t + φ) in all four engines (Python, C, C++, Fortran). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+12
-4
@@ -84,6 +84,7 @@ typedef struct {
|
||||
double *phi_x, *phi_y, *phi_z; /* radians */
|
||||
int *has_period; /* 0=all, 1=limited cycles */
|
||||
double *period_cycles; /* number of cycles */
|
||||
double *eq_x, *eq_y, *eq_z; /* 平衡位置(初始坐标) */
|
||||
double *freeze_x, *freeze_y, *freeze_z;
|
||||
} DriverData;
|
||||
|
||||
@@ -129,12 +130,16 @@ static DriverData read_driver(const char *input_dir, const AtomData *atoms) {
|
||||
d.phi_z = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.has_period = (int*)xmalloc(n_lines * sizeof(int));
|
||||
d.period_cycles = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.eq_x = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.eq_y = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.eq_z = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.freeze_x = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.freeze_y = (double*)xmalloc(n_lines * sizeof(double));
|
||||
d.freeze_z = (double*)xmalloc(n_lines * sizeof(double));
|
||||
|
||||
/* 初始化 freeze 数组 */
|
||||
/* 初始化 freeze/eq 数组 */
|
||||
for (int i = 0; i < n_lines; i++) {
|
||||
d.eq_x[i] = d.eq_y[i] = d.eq_z[i] = 0.0;
|
||||
d.freeze_x[i] = d.freeze_y[i] = d.freeze_z[i] = 0.0;
|
||||
}
|
||||
|
||||
@@ -177,6 +182,9 @@ static DriverData read_driver(const char *input_dir, const AtomData *atoms) {
|
||||
if (ii < 0) continue;
|
||||
|
||||
d.atom_idx[idx] = ii;
|
||||
d.eq_x[idx] = atoms->pos_0[ii*3+0];
|
||||
d.eq_y[idx] = atoms->pos_0[ii*3+1];
|
||||
d.eq_z[idx] = atoms->pos_0[ii*3+2];
|
||||
d.amp_x[idx] = amp_x;
|
||||
d.amp_y[idx] = amp_y;
|
||||
d.amp_z[idx] = amp_z;
|
||||
@@ -738,9 +746,9 @@ static void apply_driving_force(
|
||||
}
|
||||
}
|
||||
|
||||
double px = drivers->amp_x[d] * cos(2*M_PI*drivers->freq_x[d]*t + drivers->phi_x[d]);
|
||||
double py = drivers->amp_y[d] * cos(2*M_PI*drivers->freq_y[d]*t + drivers->phi_y[d]);
|
||||
double pz = drivers->amp_z[d] * cos(2*M_PI*drivers->freq_z[d]*t + drivers->phi_z[d]);
|
||||
double px = drivers->eq_x[d] + drivers->amp_x[d] * cos(2*M_PI*drivers->freq_x[d]*t + drivers->phi_x[d]);
|
||||
double py = drivers->eq_y[d] + drivers->amp_y[d] * cos(2*M_PI*drivers->freq_y[d]*t + drivers->phi_y[d]);
|
||||
double pz = drivers->eq_z[d] + drivers->amp_z[d] * cos(2*M_PI*drivers->freq_z[d]*t + drivers->phi_z[d]);
|
||||
double vpx = -drivers->amp_x[d]*2*M_PI*drivers->freq_x[d]*sin(2*M_PI*drivers->freq_x[d]*t + drivers->phi_x[d]);
|
||||
double vpy = -drivers->amp_y[d]*2*M_PI*drivers->freq_y[d]*sin(2*M_PI*drivers->freq_y[d]*t + drivers->phi_y[d]);
|
||||
double vpz = -drivers->amp_z[d]*2*M_PI*drivers->freq_z[d]*sin(2*M_PI*drivers->freq_z[d]*t + drivers->phi_z[d]);
|
||||
|
||||
Reference in New Issue
Block a user