/* current coordinates from efp struct are used */ void compute_energy(struct state *state, bool do_grad) { struct efp_atom *atoms; struct efp_energy efp_energy; double xyz[3], xyzabc[6], *grad; size_t ifrag, nfrag, iatom, natom; int itotal; /* EFP part */ check_fail(efp_compute(state->efp, do_grad)); check_fail(efp_get_energy(state->efp, &efp_energy)); check_fail(efp_get_frag_count(state->efp, &nfrag)); if (do_grad) { check_fail(efp_get_gradient(state->efp, state->grad)); check_fail(efp_get_point_charge_gradient(state->efp, state->grad + 6 * nfrag)); } state->energy = efp_energy.total; /* constraints */ for (ifrag = 0; ifrag < nfrag; ifrag++) { const struct frag *frag = state->sys->frags + ifrag; check_fail(efp_get_frag_xyzabc(state->efp, ifrag, xyzabc)); if (frag->constraint_enable) { double dr2, drx, dry, drz; drx = xyzabc[0] - frag->constraint_xyz.x; dry = xyzabc[1] - frag->constraint_xyz.y; drz = xyzabc[2] - frag->constraint_xyz.z; dr2 = drx * drx + dry * dry + drz * drz; state->energy += 0.5 * frag->constraint_k * dr2; if (do_grad) { grad = state->grad + 6 * ifrag; grad[0] += frag->constraint_k * drx; grad[1] += frag->constraint_k * dry; grad[2] += frag->constraint_k * drz; } } } /* MM force field part */ if (state->ff == NULL) return; for (ifrag = 0, itotal = 0; ifrag < nfrag; ifrag++) { check_fail(efp_get_frag_atom_count(state->efp, ifrag, &natom)); atoms = malloc(natom * sizeof(struct efp_atom)); check_fail(efp_get_frag_atoms(state->efp, ifrag, natom, atoms)); for (iatom = 0; iatom < natom; iatom++, itotal++) ff_set_atom_xyz(state->ff, itotal, &atoms[iatom].x); free(atoms); } ff_compute(state->ff, do_grad); if (do_grad) { for (ifrag = 0, itotal = 0, grad = state->grad; ifrag < nfrag; ifrag++, grad += 6) { check_fail(efp_get_frag_xyzabc(state->efp, ifrag, xyzabc)); check_fail(efp_get_frag_atom_count(state->efp, ifrag, &natom)); atoms = malloc(natom * sizeof(struct efp_atom)); check_fail(efp_get_frag_atoms(state->efp, ifrag, natom, atoms)); for (iatom = 0; iatom < natom; iatom++, itotal++) { ff_get_atom_gradient(state->ff, itotal, xyz); grad[0] += xyz[0]; grad[1] += xyz[1]; grad[2] += xyz[2]; grad[3] += (atoms[iatom].y - xyzabc[1]) * xyz[2] - (atoms[iatom].z - xyzabc[2]) * xyz[1]; grad[4] += (atoms[iatom].z - xyzabc[2]) * xyz[0] - (atoms[iatom].x - xyzabc[0]) * xyz[2]; grad[5] += (atoms[iatom].x - xyzabc[0]) * xyz[1] - (atoms[iatom].y - xyzabc[1]) * xyz[0]; } free(atoms); } } state->energy += ff_get_energy(state->ff); }
/* current coordinates from efp struct are used */ void compute_energy(struct state *state, bool do_grad) { struct efp_atom *atoms; struct efp_energy efp_energy; double xyz[3], xyzabc[6], *grad; size_t ifrag, nfrag, iatom, natom; int itotal; check_fail(efp_compute(state->efp, do_grad)); check_fail(efp_get_energy(state->efp, &efp_energy)); check_fail(efp_get_frag_count(state->efp, &nfrag)); if (do_grad) { check_fail(efp_get_gradient(state->efp, state->grad)); check_fail(efp_get_point_charge_gradient(state->efp, state->grad + 6 * nfrag)); } state->energy = efp_energy.total; if (state->ff == NULL) return; for (ifrag = 0, itotal = 0; ifrag < nfrag; ifrag++) { check_fail(efp_get_frag_atom_count(state->efp, ifrag, &natom)); atoms = malloc(natom * sizeof(struct efp_atom)); check_fail(efp_get_frag_atoms(state->efp, ifrag, natom, atoms)); for (iatom = 0; iatom < natom; iatom++, itotal++) ff_set_atom_xyz(state->ff, itotal, &atoms[iatom].x); free(atoms); } ff_compute(state->ff, do_grad); if (do_grad) { for (ifrag = 0, itotal = 0, grad = state->grad; ifrag < nfrag; ifrag++, grad += 6) { check_fail(efp_get_frag_xyzabc(state->efp, ifrag, xyzabc)); check_fail(efp_get_frag_atom_count(state->efp, ifrag, &natom)); atoms = malloc(natom * sizeof(struct efp_atom)); check_fail(efp_get_frag_atoms(state->efp, ifrag, natom, atoms)); for (iatom = 0; iatom < natom; iatom++, itotal++) { ff_get_atom_gradient(state->ff, itotal, xyz); grad[0] += xyz[0]; grad[1] += xyz[1]; grad[2] += xyz[2]; grad[3] += (atoms[iatom].y - xyzabc[1]) * xyz[2] - (atoms[iatom].z - xyzabc[2]) * xyz[1]; grad[4] += (atoms[iatom].z - xyzabc[2]) * xyz[0] - (atoms[iatom].x - xyzabc[0]) * xyz[2]; grad[5] += (atoms[iatom].x - xyzabc[0]) * xyz[1] - (atoms[iatom].y - xyzabc[1]) * xyz[0]; } free(atoms); } } state->energy += ff_get_energy(state->ff); }