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; } }
void calc_listed(const t_commrec *cr, const gmx_multisim_t *ms, struct gmx_wallcycle *wcycle, const t_idef *idef, const rvec x[], history_t *hist, rvec f[], gmx::ForceWithVirial *forceWithVirial, const 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, const real *lambda, const t_mdatoms *md, t_fcdata *fcd, int *global_atom_index, int force_flags) { gmx_bool bCalcEnerVir; const t_pbc *pbc_null; bonded_threading_t *bt = fr->bondedThreading; bCalcEnerVir = ((force_flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY)) != 0); if (fr->bMolPBC) { pbc_null = pbc; } else { pbc_null = nullptr; } if ((idef->il[F_POSRES].nr > 0) || (idef->il[F_FBPOSRES].nr > 0) || fcd->orires.nr > 0 || fcd->disres.nres > 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, forceWithVirial); } if (idef->il[F_FBPOSRES].nr > 0) { fbposres_wrapper(nrnb, idef, pbc_full, x, enerd, fr, forceWithVirial); } /* Do pre force calculation stuff which might require communication */ if (fcd->orires.nr > 0) { /* This assertion is to ensure we have whole molecules. * Unfortunately we do not have an mdrun state variable that tells * us if molecules in x are not broken over PBC, so we have to make * do with checking graph!=nullptr, which should tell us if we made * molecules whole before calling the current function. */ GMX_RELEASE_ASSERT(fr->ePBC == epbcNONE || g != nullptr, "With orientation restraints molecules should be whole"); 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 (fcd->disres.nres > 0) { calc_disres_R_6(cr, ms, idef->il[F_DISRES].nr, idef->il[F_DISRES].iatoms, x, pbc_null, fcd, hist); } wallcycle_sub_stop(wcycle, ewcsRESTRAINTS); } if (bt->haveBondeds) { wallcycle_sub_start(wcycle, ewcsLISTED); /* 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 */ real dvdl[efptNR] = {0}; calcBondedForces(idef, x, fr, pbc_null, g, enerd, nrnb, lambda, dvdl, md, fcd, bCalcEnerVir, global_atom_index); wallcycle_sub_stop(wcycle, ewcsLISTED); wallcycle_sub_start(wcycle, ewcsLISTED_BUF_OPS); reduce_thread_output(fr->natoms_force, f, fr->fshift, enerd->term, &enerd->grpp, dvdl, bt, bCalcEnerVir, (force_flags & GMX_FORCE_DHDL) != 0); if (force_flags & GMX_FORCE_DHDL) { for (int i = 0; i < efptNR; i++) { enerd->dvdl_nonlin[i] += dvdl[i]; } } wallcycle_sub_stop(wcycle, ewcsLISTED_BUF_OPS); } /* Copy the sum of violations for the distance restraints from fcd */ if (fcd) { enerd->term[F_DISRESVIOL] = fcd->disres.sumviol; } }