+std::unique_ptr<nonbonded_verlet_t> createNbnxmGPU(const size_t numParticleTypes,
+ const NBKernelOptions& options,
+ const std::vector<real>& nonbondedParameters,
+ const interaction_const_t& interactionConst,
+ const gmx::DeviceStreamManager& deviceStreamManager)
+{
+ const auto pinPolicy = gmx::PinningPolicy::PinnedIfSupported;
+ const int combinationRule = static_cast<int>(options.ljCombinationRule);
+
+ Nbnxm::KernelSetup kernelSetup = createKernelSetupGPU(options.useTabulatedEwaldCorr);
+
+ PairlistParams pairlistParams(kernelSetup.kernelType, false, options.pairlistCutoff, false);
+
+
+ // nbnxn_atomdata is always initialized with 1 thread if the GPU is used
+ constexpr int numThreadsInit = 1;
+ // multiple energy groups are not supported on the GPU
+ constexpr int numEnergyGroups = 1;
+ auto atomData = std::make_unique<nbnxn_atomdata_t>(pinPolicy,
+ gmx::MDLogger(),
+ kernelSetup.kernelType,
+ combinationRule,
+ numParticleTypes,
+ nonbondedParameters,
+ numEnergyGroups,
+ numThreadsInit);
+
+ NbnxmGpu* nbnxmGpu = Nbnxm::gpu_init(
+ deviceStreamManager, &interactionConst, pairlistParams, atomData.get(), false);
+
+ // minimum iList count for GPU balancing
+ int iListCount = Nbnxm::gpu_min_ci_balanced(nbnxmGpu);
+
+ auto pairlistSets = std::make_unique<PairlistSets>(pairlistParams, false, iListCount);
+ auto pairSearch = std::make_unique<PairSearch>(
+ PbcType::Xyz, false, nullptr, nullptr, pairlistParams.pairlistType, false, options.numOpenMPThreads, pinPolicy);
+
+ // Put everything together
+ auto nbv = std::make_unique<nonbonded_verlet_t>(
+ std::move(pairlistSets), std::move(pairSearch), std::move(atomData), kernelSetup, nbnxmGpu, nullptr);
+
+ // Some paramters must be copied to NbnxmGpu to have a fully constructed nonbonded_verlet_t
+ Nbnxm::gpu_init_atomdata(nbv->gpu_nbv, nbv->nbat.get());
+
+ return nbv;
+}
+