void calc_listed(const struct gmx_multisim_t *ms, struct 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) { struct bonded_threading_t *bt; gmx_bool bCalcEnerVir; int i; /* 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]; const t_pbc *pbc_null; int thread; bt = fr->bonded_threading; assert(bt->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(bt->nthreads) schedule(static) for (thread = 0; thread < bt->nthreads; thread++) { try { 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_output(bt, thread); ft = bt->f_t[thread].f; 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, 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; } wallcycle_sub_stop(wcycle, ewcsLISTED); if (bt->nthreads > 1) { 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); 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; } }