void calc_listed_lambda(const t_idef *idef, const rvec x[], t_forcerec *fr, const struct t_pbc *pbc, const struct t_graph *g, gmx_grppairener_t *grpp, real *epot, t_nrnb *nrnb, real *lambda, const t_mdatoms *md, t_fcdata *fcd, int *global_atom_index) { int ftype, nr_nonperturbed, nr; real v; real dvdl_dum[efptNR] = {0}; rvec *f, *fshift; const t_pbc *pbc_null; t_idef idef_fe; if (fr->bMolPBC) { pbc_null = pbc; } else { pbc_null = NULL; } /* Copy the whole idef, so we can modify the contents locally */ idef_fe = *idef; idef_fe.nthreads = 1; snew(idef_fe.il_thread_division, F_NRE*(idef_fe.nthreads+1)); /* We already have the forces, so we use temp buffers here */ snew(f, fr->natoms_force); snew(fshift, SHIFTS); /* Loop over all bonded force types to calculate the bonded energies */ for (ftype = 0; (ftype < F_NRE); ftype++) { if (ftype_is_bonded_potential(ftype)) { /* Set the work range of thread 0 to the perturbed bondeds only */ nr_nonperturbed = idef->il[ftype].nr_nonperturbed; nr = idef->il[ftype].nr; idef_fe.il_thread_division[ftype*2+0] = nr_nonperturbed; idef_fe.il_thread_division[ftype*2+1] = nr; /* This is only to get the flop count correct */ idef_fe.il[ftype].nr = nr - nr_nonperturbed; if (nr - nr_nonperturbed > 0) { v = calc_one_bond(0, ftype, &idef_fe, x, f, fshift, fr, pbc_null, g, grpp, nrnb, lambda, dvdl_dum, md, fcd, TRUE, global_atom_index); epot[ftype] += v; } } } sfree(fshift); sfree(f); sfree(idef_fe.il_thread_division); }
void calc_listed_lambda(const t_idef *idef, const rvec x[], const t_forcerec *fr, const struct t_pbc *pbc, const struct t_graph *g, gmx_grppairener_t *grpp, real *epot, t_nrnb *nrnb, const real *lambda, const t_mdatoms *md, t_fcdata *fcd, int *global_atom_index) { real v; real dvdl_dum[efptNR] = {0}; rvec4 *f; rvec *fshift; const t_pbc *pbc_null; t_idef idef_fe; bonded_threading_t bondedThreading; if (fr->bMolPBC) { pbc_null = pbc; } else { pbc_null = nullptr; } /* Copy the whole idef, so we can modify the contents locally */ idef_fe = *idef; bondedThreading.nthreads = 1; snew(bondedThreading.il_thread_division, F_NRE*(bondedThreading.nthreads+1)); /* We already have the forces, so we use temp buffers here */ snew(f, fr->natoms_force); snew(fshift, SHIFTS); /* Loop over all bonded force types to calculate the bonded energies */ for (int ftype = 0; (ftype < F_NRE); ftype++) { if (ftype_is_bonded_potential(ftype)) { const t_ilist &ilist = idef->il[ftype]; /* Create a temporary t_ilist with only perturbed interactions */ t_ilist &ilist_fe = idef_fe.il[ftype]; ilist_fe.iatoms = ilist.iatoms + ilist.nr_nonperturbed; ilist_fe.nr_nonperturbed = 0; ilist_fe.nr = ilist.nr - ilist.nr_nonperturbed; /* Set the work range of thread 0 to the perturbed bondeds */ bondedThreading.il_thread_division[ftype*2 + 0] = 0; bondedThreading.il_thread_division[ftype*2 + 1] = ilist_fe.nr; if (ilist_fe.nr > 0) { v = calc_one_bond(0, ftype, &idef_fe, bondedThreading, x, f, fshift, fr, pbc_null, g, grpp, nrnb, lambda, dvdl_dum, md, fcd, TRUE, global_atom_index); epot[ftype] += v; } } } sfree(fshift); sfree(f); sfree(bondedThreading.il_thread_division); }
void calc_listed(const gmx_multisim_t *ms, gmx_wallcycle *wcycle, const t_idef *idef, const rvec x[], history_t *hist, rvec f[], t_forcerec *fr, const struct t_pbc *pbc, const struct t_pbc *pbc_full, const struct t_graph *g, gmx_enerdata_t *enerd, t_nrnb *nrnb, real *lambda, const t_mdatoms *md, t_fcdata *fcd, int *global_atom_index, int force_flags) { gmx_bool bCalcEnerVir; int i; real dvdl[efptNR]; /* The dummy array is to have a place to store the dhdl at other values of lambda, which will be thrown away in the end*/ const t_pbc *pbc_null; int thread; assert(fr->nthreads == idef->nthreads); bCalcEnerVir = (force_flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY)); for (i = 0; i < efptNR; i++) { dvdl[i] = 0.0; } if (fr->bMolPBC) { pbc_null = pbc; } else { pbc_null = NULL; } #ifdef DEBUG if (g && debug) { p_graph(debug, "Bondage is fun", g); } #endif if ((idef->il[F_POSRES].nr > 0) || (idef->il[F_FBPOSRES].nr > 0) || (idef->il[F_ORIRES].nr > 0) || (idef->il[F_DISRES].nr > 0)) { /* TODO Use of restraints triggers further function calls inside the loop over calc_one_bond(), but those are too awkward to account to this subtimer properly in the present code. We don't test / care much about performance with restraints, anyway. */ wallcycle_sub_start(wcycle, ewcsRESTRAINTS); if (idef->il[F_POSRES].nr > 0) { posres_wrapper(nrnb, idef, pbc_full, x, enerd, lambda, fr); } if (idef->il[F_FBPOSRES].nr > 0) { fbposres_wrapper(nrnb, idef, pbc_full, x, enerd, fr); } /* Do pre force calculation stuff which might require communication */ if (idef->il[F_ORIRES].nr > 0) { enerd->term[F_ORIRESDEV] = calc_orires_dev(ms, idef->il[F_ORIRES].nr, idef->il[F_ORIRES].iatoms, idef->iparams, md, x, pbc_null, fcd, hist); } if (idef->il[F_DISRES].nr) { calc_disres_R_6(idef->il[F_DISRES].nr, idef->il[F_DISRES].iatoms, idef->iparams, x, pbc_null, fcd, hist); #ifdef GMX_MPI if (fcd->disres.nsystems > 1) { gmx_sum_sim(2*fcd->disres.nres, fcd->disres.Rt_6, ms); } #endif } wallcycle_sub_stop(wcycle, ewcsRESTRAINTS); } wallcycle_sub_start(wcycle, ewcsLISTED); #pragma omp parallel for num_threads(fr->nthreads) schedule(static) for (thread = 0; thread < fr->nthreads; thread++) { int ftype; real *epot, v; /* thread stuff */ rvec *ft, *fshift; real *dvdlt; gmx_grppairener_t *grpp; if (thread == 0) { ft = f; fshift = fr->fshift; epot = enerd->term; grpp = &enerd->grpp; dvdlt = dvdl; } else { zero_thread_forces(&fr->f_t[thread], fr->natoms_force, fr->red_nblock, 1<<fr->red_ashift); ft = fr->f_t[thread].f; fshift = fr->f_t[thread].fshift; epot = fr->f_t[thread].ener; grpp = &fr->f_t[thread].grpp; dvdlt = fr->f_t[thread].dvdl; } /* Loop over all bonded force types to calculate the bonded forces */ for (ftype = 0; (ftype < F_NRE); ftype++) { if (idef->il[ftype].nr > 0 && ftype_is_bonded_potential(ftype)) { v = calc_one_bond(thread, ftype, idef, x, ft, fshift, fr, pbc_null, g, grpp, nrnb, lambda, dvdlt, md, fcd, bCalcEnerVir, global_atom_index); epot[ftype] += v; } } } wallcycle_sub_stop(wcycle, ewcsLISTED); if (fr->nthreads > 1) { wallcycle_sub_start(wcycle, ewcsLISTED_BUF_OPS); reduce_thread_forces(fr->natoms_force, f, fr->fshift, enerd->term, &enerd->grpp, dvdl, fr->nthreads, fr->f_t, fr->red_nblock, 1<<fr->red_ashift, bCalcEnerVir, force_flags & GMX_FORCE_DHDL); wallcycle_sub_stop(wcycle, ewcsLISTED_BUF_OPS); } /* Remaining code does not have enough flops to bother counting */ if (force_flags & GMX_FORCE_DHDL) { for (i = 0; i < efptNR; i++) { enerd->dvdl_nonlin[i] += dvdl[i]; } } /* Copy the sum of violations for the distance restraints from fcd */ if (fcd) { enerd->term[F_DISRESVIOL] = fcd->disres.sumviol; } }
/*! \brief Compute the bonded part of the listed forces, parallelized over threads */ static void calcBondedForces(const t_idef *idef, const rvec x[], const t_forcerec *fr, const t_pbc *pbc_null, const t_graph *g, gmx_enerdata_t *enerd, t_nrnb *nrnb, const real *lambda, real *dvdl, const t_mdatoms *md, t_fcdata *fcd, gmx_bool bCalcEnerVir, int *global_atom_index) { bonded_threading_t *bt = fr->bondedThreading; #pragma omp parallel for num_threads(bt->nthreads) schedule(static) for (int thread = 0; thread < bt->nthreads; thread++) { try { int ftype; real *epot, v; /* thread stuff */ rvec4 *ft; rvec *fshift; real *dvdlt; gmx_grppairener_t *grpp; zero_thread_output(bt, thread); ft = bt->f_t[thread].f; if (thread == 0) { fshift = fr->fshift; epot = enerd->term; grpp = &enerd->grpp; dvdlt = dvdl; } else { fshift = bt->f_t[thread].fshift; epot = bt->f_t[thread].ener; grpp = &bt->f_t[thread].grpp; dvdlt = bt->f_t[thread].dvdl; } /* Loop over all bonded force types to calculate the bonded forces */ for (ftype = 0; (ftype < F_NRE); ftype++) { if (idef->il[ftype].nr > 0 && ftype_is_bonded_potential(ftype)) { v = calc_one_bond(thread, ftype, idef, *fr->bondedThreading, x, ft, fshift, fr, pbc_null, g, grpp, nrnb, lambda, dvdlt, md, fcd, bCalcEnerVir, global_atom_index); epot[ftype] += v; } } } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; } }