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:
@@ -86,6 +86,7 @@ struct DriverData {
|
||||
std::vector<double> phi_x, phi_y, phi_z; // radians
|
||||
std::vector<int> has_period; // 0=all, 1=limited
|
||||
std::vector<double> period_cycles;
|
||||
std::vector<double> eq_x, eq_y, eq_z; // 平衡位置(初始坐标)
|
||||
std::vector<double> freeze_x, freeze_y, freeze_z;
|
||||
};
|
||||
|
||||
@@ -314,6 +315,9 @@ static DriverData read_driver(const std::string &input_dir, const AtomData &atom
|
||||
continue;
|
||||
}
|
||||
d.atom_idx.push_back(idx);
|
||||
d.eq_x.push_back(atoms.pos_0[idx*3+0]);
|
||||
d.eq_y.push_back(atoms.pos_0[idx*3+1]);
|
||||
d.eq_z.push_back(atoms.pos_0[idx*3+2]);
|
||||
d.amp_x.push_back(ax); d.amp_y.push_back(ay); d.amp_z.push_back(az);
|
||||
d.freq_x.push_back(fx); d.freq_y.push_back(fy); d.freq_z.push_back(fz);
|
||||
// Convert degrees to radians
|
||||
@@ -700,9 +704,9 @@ static void apply_driving_force(
|
||||
}
|
||||
|
||||
const double TWO_PI = 2.0 * M_PI;
|
||||
double px = drivers.amp_x[d] * std::cos(TWO_PI * drivers.freq_x[d] * t + drivers.phi_x[d]);
|
||||
double py = drivers.amp_y[d] * std::cos(TWO_PI * drivers.freq_y[d] * t + drivers.phi_y[d]);
|
||||
double pz = drivers.amp_z[d] * std::cos(TWO_PI * drivers.freq_z[d] * t + drivers.phi_z[d]);
|
||||
double px = drivers.eq_x[d] + drivers.amp_x[d] * std::cos(TWO_PI * drivers.freq_x[d] * t + drivers.phi_x[d]);
|
||||
double py = drivers.eq_y[d] + drivers.amp_y[d] * std::cos(TWO_PI * drivers.freq_y[d] * t + drivers.phi_y[d]);
|
||||
double pz = drivers.eq_z[d] + drivers.amp_z[d] * std::cos(TWO_PI * drivers.freq_z[d] * t + drivers.phi_z[d]);
|
||||
double vpx = -drivers.amp_x[d] * TWO_PI * drivers.freq_x[d] * std::sin(TWO_PI * drivers.freq_x[d] * t + drivers.phi_x[d]);
|
||||
double vpy = -drivers.amp_y[d] * TWO_PI * drivers.freq_y[d] * std::sin(TWO_PI * drivers.freq_y[d] * t + drivers.phi_y[d]);
|
||||
double vpz = -drivers.amp_z[d] * TWO_PI * drivers.freq_z[d] * std::sin(TWO_PI * drivers.freq_z[d] * t + drivers.phi_z[d]);
|
||||
|
||||
Reference in New Issue
Block a user