* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
* Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
- * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
errorReasons.emplace_back("a double-precision build");
}
- if (GMX_GPU == GMX_GPU_NONE)
+ if (!GMX_GPU)
{
errorReasons.emplace_back("a non-GPU build");
}
+ if (GMX_GPU_SYCL)
+ {
+ errorReasons.emplace_back("SYCL build"); // SYCL-TODO
+ }
return addMessageIfNotSupported(errorReasons, error);
}
{
std::list<std::string> errorReasons;
- if (GMX_GPU == GMX_GPU_OPENCL)
+ if (GMX_GPU_OPENCL)
{
#ifdef __APPLE__
errorReasons.emplace_back("Apple OS X operating system");
return addMessageIfNotSupported(errorReasons, error);
}
-bool pme_gpu_supports_input(const t_inputrec& ir, const gmx_mtop_t& mtop, std::string* error)
+bool pme_gpu_supports_input(const t_inputrec& ir, std::string* error)
{
std::list<std::string> errorReasons;
if (!EEL_PME(ir.coulombtype))
{
errorReasons.emplace_back("interpolation orders other than 4");
}
- if (ir.efep != efepNO)
- {
- if (gmx_mtop_has_perturbed_charges(mtop))
- {
- errorReasons.emplace_back(
- "free energy calculations with perturbed charges (multiple grids)");
- }
- }
if (EVDW_PME(ir.vdwtype))
{
errorReasons.emplace_back("Lennard-Jones PME");
}
if (!EI_DYNAMICS(ir.eI))
{
- errorReasons.emplace_back("not a dynamical integrator");
+ errorReasons.emplace_back(
+ "Cannot compute PME interactions on a GPU, because PME GPU requires a dynamical "
+ "integrator (md, sd, etc).");
+ }
+ return addMessageIfNotSupported(errorReasons, error);
+}
+
+bool pme_gpu_mixed_mode_supports_input(const t_inputrec& ir, std::string* error)
+{
+ std::list<std::string> errorReasons;
+ if (ir.efep != efepNO)
+ {
+ errorReasons.emplace_back("Free Energy Perturbation (in PME GPU mixed mode)");
}
return addMessageIfNotSupported(errorReasons, error);
}
{
errorReasons.emplace_back("interpolation orders other than 4");
}
- if (pme->bFEP)
- {
- errorReasons.emplace_back("free energy calculations (multiple grids)");
- }
if (pme->doLJ)
{
errorReasons.emplace_back("Lennard-Jones PME");
{
errorReasons.emplace_back("double precision");
}
- if (GMX_GPU == GMX_GPU_NONE)
+ if (!GMX_GPU)
{
errorReasons.emplace_back("non-GPU build of GROMACS");
}
-
+ if (GMX_GPU_SYCL)
+ {
+ errorReasons.emplace_back("SYCL build of GROMACS"); // SYCL-TODO
+ }
return addMessageIfNotSupported(errorReasons, error);
}
const DeviceContext* deviceContext,
const DeviceStream* deviceStream,
const PmeGpuProgram* pmeGpuProgram,
- const gmx::MDLogger& /*mdlog*/)
+ const gmx::MDLogger& mdlog)
{
int use_threads, sum_use_threads, i;
ivec ndata;
imbal = estimate_pme_load_imbalance(pme.get());
if (imbal >= 1.2 && pme->nodeid_major == 0 && pme->nodeid_minor == 0)
{
- fprintf(stderr,
- "\n"
- "NOTE: The load imbalance in PME FFT and solve is %d%%.\n"
- " For optimal PME load balancing\n"
- " PME grid_x (%d) and grid_y (%d) should be divisible by #PME_ranks_x "
- "(%d)\n"
- " and PME grid_y (%d) and grid_z (%d) should be divisible by #PME_ranks_y "
- "(%d)\n"
- "\n",
- gmx::roundToInt((imbal - 1) * 100), pme->nkx, pme->nky, pme->nnodes_major,
- pme->nky, pme->nkz, pme->nnodes_minor);
+ GMX_LOG(mdlog.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "NOTE: The load imbalance in PME FFT and solve is %d%%.\n"
+ " For optimal PME load balancing\n"
+ " PME grid_x (%d) and grid_y (%d) should be divisible by "
+ "#PME_ranks_x "
+ "(%d)\n"
+ " and PME grid_y (%d) and grid_z (%d) should be divisible by "
+ "#PME_ranks_y "
+ "(%d)",
+ gmx::roundToInt((imbal - 1) * 100), pme->nkx, pme->nky,
+ pme->nnodes_major, pme->nky, pme->nkz, pme->nnodes_minor);
}
}
try
{
+ // This is reinit. Any logging should have been done at first init.
+ // Here we should avoid writing notes for settings the user did not
+ // set directly.
const gmx::MDLogger dummyLogger;
- // This is reinit which is currently only changing grid size/coefficients,
- // so we don't expect the actual logging.
- // TODO: when PME is an object, it should take reference to mdlog on construction and save it.
GMX_ASSERT(pmedata, "Invalid PME pointer");
NumPmeDomains numPmeDomains = { pme_src->nnodes_major, pme_src->nnodes_minor };
*pmedata = gmx_pme_init(cr, numPmeDomains, &irc, pme_src->bFEP_q, pme_src->bFEP_lj, FALSE,
*/
if (!pme_src->gpu && pme_src->nnodes == 1)
{
- gmx_pme_reinit_atoms(*pmedata, pme_src->atc[0].numAtoms(), nullptr);
+ gmx_pme_reinit_atoms(*pmedata, pme_src->atc[0].numAtoms(), nullptr, nullptr);
}
// TODO this is mostly passing around current values
}
delete pme;
}
-void gmx_pme_reinit_atoms(gmx_pme_t* pme, const int numAtoms, const real* charges)
+void gmx_pme_reinit_atoms(gmx_pme_t* pme, const int numAtoms, const real* chargesA, const real* chargesB)
{
if (pme->gpu != nullptr)
{
- pme_gpu_reinit_atoms(pme->gpu, numAtoms, charges);
+ GMX_ASSERT(!(pme->bFEP_q && chargesB == nullptr),
+ "B state charges must be specified if running Coulomb FEP on the GPU");
+ pme_gpu_reinit_atoms(pme->gpu, numAtoms, chargesA, pme->bFEP_q ? chargesB : nullptr);
}
else
{