static void get_weight_factor(struct efp *efp, double *mass_fact, mat_t *inertia_fact) { size_t n_frags; check_fail(efp_get_frag_count(efp, &n_frags)); double xyzabc[6 * n_frags]; check_fail(efp_get_coordinates(efp, xyzabc)); for (size_t i = 0; i < n_frags; i++) { double mass; check_fail(efp_get_frag_mass(efp, i, &mass)); double inertia[3]; check_fail(efp_get_frag_inertia(efp, i, inertia)); double a = xyzabc[6 * i + 3]; double b = xyzabc[6 * i + 4]; double c = xyzabc[6 * i + 5]; mat_t rotmat; euler_to_matrix(a, b, c, &rotmat); mass_fact[i] = 1.0 / sqrt(mass); get_inertia_factor(inertia, &rotmat, inertia_fact + i); } }
static void compute_hessian(struct state *state, double *hess) { size_t n_frags, n_coord; double *xyzabc, *grad_f, *grad_b; bool central = cfg_get_bool(state->cfg, "hess_central"); check_fail(efp_get_frag_count(state->efp, &n_frags)); n_coord = 6 * n_frags; xyzabc = xmalloc(n_coord * sizeof(double)); grad_f = xmalloc(n_coord * sizeof(double)); grad_b = xmalloc(n_coord * sizeof(double)); check_fail(efp_get_coordinates(state->efp, xyzabc)); if (!central) { memcpy(grad_b, state->grad, n_frags * 6 * sizeof(double)); for (size_t i = 0; i < n_frags; i++) { const double *euler = xyzabc + 6 * i + 3; double *gradptr = grad_b + 6 * i + 3; efp_torque_to_derivative(euler, gradptr, gradptr); } } for (size_t i = 0; i < n_coord; i++) { double save = xyzabc[i]; double step = i % 6 < 3 ? cfg_get_double(state->cfg, "num_step_dist") : cfg_get_double(state->cfg, "num_step_angle"); show_progress(i + 1, n_coord, "FORWARD"); xyzabc[i] = save + step; compute_gradient(state, n_frags, xyzabc, grad_f); if (central) { show_progress(i + 1, n_coord, "BACKWARD"); xyzabc[i] = save - step; compute_gradient(state, n_frags, xyzabc, grad_b); } double delta = central ? 2.0 * step : step; for (size_t j = 0; j < n_coord; j++) hess[i * n_coord + j] = (grad_f[j] - grad_b[j]) / delta; xyzabc[i] = save; } /* restore original coordinates */ check_fail(efp_set_coordinates(state->efp, EFP_COORD_TYPE_XYZABC, xyzabc)); /* reduce error by computing the average of H(i,j) and H(j,i) */ for (size_t i = 0; i < n_coord; i++) { for (size_t j = i + 1; j < n_coord; j++) { double sum = hess[i * n_coord + j] + hess[j * n_coord + i]; hess[i * n_coord + j] = 0.5 * sum; hess[j * n_coord + i] = hess[i * n_coord + j]; } } free(xyzabc); free(grad_f); free(grad_b); msg("\n\n"); }
static struct md *md_create(struct state *state) { struct md *md = xcalloc(1, sizeof(struct md)); md->state = state; md->box = box_from_str(cfg_get_string(state->cfg, "periodic_box")); switch (cfg_get_enum(state->cfg, "ensemble")) { case ENSEMBLE_TYPE_NVE: md->get_invariant = get_invariant_nve; md->update_step = update_step_nve; break; case ENSEMBLE_TYPE_NVT: md->get_invariant = get_invariant_nvt; md->update_step = update_step_nvt; md->data = xcalloc(1, sizeof(struct nvt_data)); break; case ENSEMBLE_TYPE_NPT: md->get_invariant = get_invariant_npt; md->update_step = update_step_npt; md->data = xcalloc(1, sizeof(struct npt_data)); break; default: assert(0); } md->n_bodies = state->sys->n_frags; md->bodies = xcalloc(md->n_bodies, sizeof(struct body)); double coord[6 * md->n_bodies]; check_fail(efp_get_coordinates(state->efp, coord)); for (size_t i = 0; i < md->n_bodies; i++) { struct body *body = md->bodies + i; body->pos.x = coord[6 * i + 0]; body->pos.y = coord[6 * i + 1]; body->pos.z = coord[6 * i + 2]; double a = coord[6 * i + 3]; double b = coord[6 * i + 4]; double c = coord[6 * i + 5]; euler_to_matrix(a, b, c, &body->rotmat); body->vel.x = md->state->sys->frags[i].vel[0]; body->vel.y = md->state->sys->frags[i].vel[1]; body->vel.z = md->state->sys->frags[i].vel[2]; set_body_mass_and_inertia(state->efp, i, body); body->angmom.x = md->state->sys->frags[i].vel[3] * body->inertia.x; body->angmom.y = md->state->sys->frags[i].vel[4] * body->inertia.y; body->angmom.z = md->state->sys->frags[i].vel[5] * body->inertia.z; md->n_freedom += 3; if (body->inertia.x > EPSILON) md->n_freedom++; if (body->inertia.y > EPSILON) md->n_freedom++; if (body->inertia.z > EPSILON) md->n_freedom++; } return (md); }