+namespace gmx
+{
+
+//! Returns whether there are any interactions suitable for a GPU.
+static bool someInteractionsCanRunOnGpu(const InteractionLists &ilists)
+{
+ for (int ftype : ftypesOnGpu)
+ {
+ if (!ilists[ftype].iatoms.empty())
+ {
+ // Perturbation is not implemented in the GPU bonded
+ // kernels. If all the interactions were actually
+ // perturbed, then that will be detected later on each
+ // domain, and work will never run on the GPU. This is
+ // very unlikely to occur, and has little run-time cost,
+ // so we don't complicate the code by catering for it
+ // here.
+ return true;
+ }
+ }
+ return false;
+}
+
+//! Returns whether there are any interactions suitable for a GPU.
+static bool bondedInteractionsCanRunOnGpu(const gmx_mtop_t &mtop)
+{
+ // Check the regular molecule types
+ for (const auto &moltype : mtop.moltype)
+ {
+ if (someInteractionsCanRunOnGpu(moltype.ilist))
+ {
+ return true;
+ }
+ }
+ // Check the inter-molecular interactions.
+ if (mtop.intermolecular_ilist)
+ {
+ if (someInteractionsCanRunOnGpu(*mtop.intermolecular_ilist))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*! \brief Help build a descriptive message in \c error if there are
+ * \c errorReasons why bondeds on a GPU are not supported.
+ *
+ * \returns Whether the lack of errorReasons indicate there is support. */
+static bool
+addMessageIfNotSupported(ArrayRef <const std::string> errorReasons,
+ std::string *error)
+{
+ bool isSupported = errorReasons.empty();
+ if (!isSupported && error)
+ {
+ *error = "Bonded interactions cannot run on GPUs: ";
+ *error += joinStrings(errorReasons, "; ") + ".";
+ }
+ return isSupported;
+}
+
+bool buildSupportsGpuBondeds(std::string *error)
+{
+ std::vector<std::string> errorReasons;
+ if (GMX_DOUBLE)
+ {
+ errorReasons.emplace_back("not supported with double precision");
+ }
+ if (GMX_GPU == GMX_GPU_OPENCL)
+ {
+ errorReasons.emplace_back("not supported with OpenCL build of GROMACS");
+ }
+ else if (GMX_GPU == GMX_GPU_NONE)
+ {
+ errorReasons.emplace_back("not supported with CPU-only build of GROMACS");
+ }
+ return addMessageIfNotSupported(errorReasons, error);
+}
+
+bool inputSupportsGpuBondeds(const t_inputrec &ir,
+ const gmx_mtop_t &mtop,
+ std::string *error)
+{
+ std::vector<std::string> errorReasons;
+
+ if (!bondedInteractionsCanRunOnGpu(mtop))
+ {
+ errorReasons.emplace_back("No supported bonded interactions are present");
+ }
+ if (ir.cutoff_scheme == ecutsGROUP)
+ {
+ errorReasons.emplace_back("group cutoff scheme");
+ }
+ if (!EI_DYNAMICS(ir.eI))
+ {
+ errorReasons.emplace_back("not a dynamical integrator");
+ }
+ return addMessageIfNotSupported(errorReasons, error);
+}
+
+} // namespace gmx
+