void turn_body(int direction, double length){ int a = current_step % 10; if(a < 5) move_body(0, length); else rotate_body(direction, length); }
static void update_step_nve(struct md *md) { double dt = cfg_get_double(md->state->cfg, "time_step"); for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->vel.x += 0.5 * body->force.x * dt / body->mass; body->vel.y += 0.5 * body->force.y * dt / body->mass; body->vel.z += 0.5 * body->force.z * dt / body->mass; body->angmom.x += 0.5 * body->torque.x * dt; body->angmom.y += 0.5 * body->torque.y * dt; body->angmom.z += 0.5 * body->torque.z * dt; body->pos.x += body->vel.x * dt; body->pos.y += body->vel.y * dt; body->pos.z += body->vel.z * dt; rotate_body(body, dt); } compute_forces(md); for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->vel.x += 0.5 * body->force.x * dt / body->mass; body->vel.y += 0.5 * body->force.y * dt / body->mass; body->vel.z += 0.5 * body->force.z * dt / body->mass; body->angmom.x += 0.5 * body->torque.x * dt; body->angmom.y += 0.5 * body->torque.y * dt; body->angmom.z += 0.5 * body->torque.z * dt; } }
/* * Reference * * Simone Melchionna, Giovanni Ciccotti, Brad Lee Holian * * Hoover NPT dynamics for systems varying in shape and size * * Mol. Phys. 78, 533 (1993) */ static void update_step_npt(struct md *md) { struct npt_data *data = (struct npt_data *)md->data; double dt = cfg_get_double(md->state->cfg, "time_step"); double t_tau = cfg_get_double(md->state->cfg, "thermostat_tau"); double t_target = cfg_get_double(md->state->cfg, "temperature"); double p_tau = cfg_get_double(md->state->cfg, "barostat_tau"); double p_target = cfg_get_double(md->state->cfg, "pressure"); double t_tau2 = t_tau * t_tau; double p_tau2 = p_tau * p_tau; double kbt = BOLTZMANN * t_target; double t0 = get_temperature(md); double p0 = get_pressure(md); double v0 = get_volume(md); for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->vel.x += 0.5 * dt * (body->force.x / body->mass - body->vel.x * (data->chi + data->eta)); body->vel.y += 0.5 * dt * (body->force.y / body->mass - body->vel.y * (data->chi + data->eta)); body->vel.z += 0.5 * dt * (body->force.z / body->mass - body->vel.z * (data->chi + data->eta)); body->angmom.x += 0.5 * dt * (body->torque.x - body->angmom.x * data->chi); body->angmom.y += 0.5 * dt * (body->torque.y - body->angmom.y * data->chi); body->angmom.z += 0.5 * dt * (body->torque.z - body->angmom.z * data->chi); rotate_body(body, dt); } data->chi += 0.5 * dt * (t0 / t_target - 1.0) / t_tau2; data->chi_dt += 0.5 * dt * data->chi; data->eta += 0.5 * dt * v0 * (p0 - p_target) / md->n_bodies / kbt / p_tau2; vec_t com = get_system_com(md); vec_t pos_init[md->n_bodies]; for (size_t i = 0; i < md->n_bodies; i++) pos_init[i] = md->bodies[i].pos; for (size_t iter = 1; iter <= MAX_ITER; iter++) { bool done = true; for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; vec_t pos = wrap(md, &body->pos); vec_t v = { data->eta * (pos.x - com.x), data->eta * (pos.y - com.y), data->eta * (pos.z - com.z) }; vec_t new_pos = { pos_init[i].x + dt * (body->vel.x + v.x), pos_init[i].y + dt * (body->vel.y + v.y), pos_init[i].z + dt * (body->vel.z + v.z) }; done = done && vec_dist(&body->pos, &new_pos) < EPSILON; body->pos = new_pos; } if (done) break; if (iter == MAX_ITER) msg("WARNING: NPT UPDATE DID NOT CONVERGE\n\n"); } vec_scale(&md->box, exp(dt * data->eta)); check_fail(efp_set_periodic_box(md->state->efp, md->box.x, md->box.y, md->box.z)); compute_forces(md); double chi_init = data->chi, eta_init = data->eta; vec_t angmom_init[md->n_bodies], vel_init[md->n_bodies]; for (size_t i = 0; i < md->n_bodies; i++) { angmom_init[i] = md->bodies[i].angmom; vel_init[i] = md->bodies[i].vel; } for (size_t iter = 1; iter <= MAX_ITER; iter++) { double chi_prev = data->chi; double eta_prev = data->eta; double t_cur = get_temperature(md); double p_cur = get_pressure(md); double v_cur = get_volume(md); data->chi = chi_init + 0.5 * dt * (t_cur / t_target - 1.0) / t_tau2; data->eta = eta_init + 0.5 * dt * v_cur * (p_cur - p_target) / md->n_bodies / kbt / p_tau2; for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->vel.x = vel_init[i].x + 0.5 * dt * (body->force.x / body->mass - vel_init[i].x * (data->chi + data->eta)); body->vel.y = vel_init[i].y + 0.5 * dt * (body->force.y / body->mass - vel_init[i].y * (data->chi + data->eta)); body->vel.z = vel_init[i].z + 0.5 * dt * (body->force.z / body->mass - vel_init[i].z * (data->chi + data->eta)); body->angmom.x = angmom_init[i].x + 0.5 * dt * (body->torque.x - angmom_init[i].x * data->chi); body->angmom.y = angmom_init[i].y + 0.5 * dt * (body->torque.y - angmom_init[i].y * data->chi); body->angmom.z = angmom_init[i].z + 0.5 * dt * (body->torque.z - angmom_init[i].z * data->chi); } if (fabs(data->chi - chi_prev) < EPSILON && fabs(data->eta - eta_prev) < EPSILON) break; if (iter == MAX_ITER) msg("WARNING: NPT UPDATE DID NOT CONVERGE\n\n"); } data->chi_dt += 0.5 * dt * data->chi; }
/* * NVT with Nose-Hoover thermostat: * * William G. Hoover * * Canonical dynamics: Equilibrium phase-space distributions * * Phys. Rev. A 31, 1695 (1985) */ static void update_step_nvt(struct md *md) { struct nvt_data *data = (struct nvt_data *)md->data; double dt = cfg_get_double(md->state->cfg, "time_step"); double target = cfg_get_double(md->state->cfg, "temperature"); double tau = cfg_get_double(md->state->cfg, "thermostat_tau"); double t0 = get_temperature(md); for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->vel.x += 0.5 * dt * (body->force.x / body->mass - body->vel.x * data->chi); body->vel.y += 0.5 * dt * (body->force.y / body->mass - body->vel.y * data->chi); body->vel.z += 0.5 * dt * (body->force.z / body->mass - body->vel.z * data->chi); body->angmom.x += 0.5 * dt * (body->torque.x - body->angmom.x * data->chi); body->angmom.y += 0.5 * dt * (body->torque.y - body->angmom.y * data->chi); body->angmom.z += 0.5 * dt * (body->torque.z - body->angmom.z * data->chi); body->pos.x += body->vel.x * dt; body->pos.y += body->vel.y * dt; body->pos.z += body->vel.z * dt; rotate_body(body, dt); } data->chi += 0.5 * dt * (t0 / target - 1.0) / tau / tau; data->chi_dt += 0.5 * dt * data->chi; compute_forces(md); double chi_init = data->chi; vec_t angmom_init[md->n_bodies], vel_init[md->n_bodies]; for (size_t i = 0; i < md->n_bodies; i++) { angmom_init[i] = md->bodies[i].angmom; vel_init[i] = md->bodies[i].vel; } for (size_t iter = 1; iter <= MAX_ITER; iter++) { double chi_prev = data->chi; double ratio = get_temperature(md) / target; data->chi = chi_init + 0.5 * dt * (ratio - 1.0) / tau / tau; for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->vel.x = vel_init[i].x + 0.5 * dt * (body->force.x / body->mass - vel_init[i].x * data->chi); body->vel.y = vel_init[i].y + 0.5 * dt * (body->force.y / body->mass - vel_init[i].y * data->chi); body->vel.z = vel_init[i].z + 0.5 * dt * (body->force.z / body->mass - vel_init[i].z * data->chi); body->angmom.x = angmom_init[i].x + 0.5 * dt * (body->torque.x - angmom_init[i].x * data->chi); body->angmom.y = angmom_init[i].y + 0.5 * dt * (body->torque.y - angmom_init[i].y * data->chi); body->angmom.z = angmom_init[i].z + 0.5 * dt * (body->torque.z - angmom_init[i].z * data->chi); } if (fabs(data->chi - chi_prev) < EPSILON) break; if (iter == MAX_ITER) msg("WARNING: NVT UPDATE DID NOT CONVERGE\n\n"); } data->chi_dt += 0.5 * dt * data->chi; }