#ifndef OPENMM_CUDANONBONDEDUTILITIES_H_ #define OPENMM_CUDANONBONDEDUTILITIES_H_ /* -------------------------------------------------------------------------- * * OpenMM * * -------------------------------------------------------------------------- * * This is part of the OpenMM molecular simulation toolkit originating from * * Simbios, the NIH National Center for Physics-Based Simulation of * * Biological Structures at Stanford, funded under the NIH Roadmap for * * Medical Research, grant U54 GM072970. See https://simtk.org. * * * * Portions copyright (c) 2009-2012 Stanford University and the Authors. * * Authors: Peter Eastman * * Contributors: * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as published * * by the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * -------------------------------------------------------------------------- */ #include "CudaContext.h" #include "openmm/System.h" #include "CudaExpressionUtilities.h" #include #include #include namespace OpenMM { /** * This class provides a generic interface for calculating nonbonded interactions. It does this in two * ways. First, it can be used to create Kernels that evaluate nonbonded interactions. Clients * only need to provide the code for evaluating a single interaction and the list of parameters it depends on. * A complete kernel is then synthesized using an appropriate algorithm to evaluate all interactions on all * atoms. * * Second, this class itself creates and invokes a single "default" interaction kernel, allowing several * different forces to be evaluated at once for greater efficiency. Call addInteraction() and addParameter() * to add interactions to this default kernel. * * During each force or energy evaluation, the following sequence of steps takes place: * * 1. Data structures (e.g. neighbor lists) are calculated to allow nonbonded interactions to be evaluated * quickly. * * 2. calcForcesAndEnergy() is called on each ForceImpl in the System. * * 3. Finally, the default interaction kernel is invoked to calculate all interactions that were added * to it. * * This sequence means that the default interaction kernel may depend on quantities that were calculated * by ForceImpls during calcForcesAndEnergy(). */ class OPENMM_EXPORT CudaNonbondedUtilities { public: class ParameterInfo; // CudaNonbondedUtilities(CudaContext& context); // ~CudaNonbondedUtilities(); // /** // * Add a nonbonded interaction to be evaluated by the default interaction kernel. // * // * @param usesCutoff specifies whether a cutoff should be applied to this interaction // * @param usesPeriodic specifies whether periodic boundary conditions should be applied to this interaction // * @param usesExclusions specifies whether this interaction uses exclusions. If this is true, it must have identical exclusions to every other interaction. // * @param cutoffDistance the cutoff distance for this interaction (ignored if usesCutoff is false) // * @param exclusionList for each atom, specifies the list of other atoms whose interactions should be excluded // * @param kernel the code to evaluate the interaction // * @param forceGroup the force group in which the interaction should be calculated // */ // void addInteraction(bool usesCutoff, bool usesPeriodic, bool usesExclusions, double cutoffDistance, const std::vector >& exclusionList, const std::string& kernel, int forceGroup); // /** // * Add a per-atom parameter that the default interaction kernel may depend on. // */ // void addParameter(const ParameterInfo& parameter); // /** // * Add an array (other than a per-atom parameter) that should be passed as an argument to the default interaction kernel. // */ // void addArgument(const ParameterInfo& parameter); // /** // * Specify the list of exclusions that an interaction outside the default kernel will depend on. // * // * @param exclusionList for each atom, specifies the list of other atoms whose interactions should be excluded // */ // void requestExclusions(const std::vector >& exclusionList); // /** // * Initialize this object in preparation for a simulation. // */ // void initialize(const System& system); // /** // * Get the number of force buffers required for nonbonded forces. // */ // int getNumForceBuffers() { // return numForceBuffers; // } // /** // * Get the number of energy buffers required for nonbonded forces. // */ // int getNumEnergyBuffers() { // return numForceThreadBlocks*forceThreadBlockSize; // } // /** // * Get whether a cutoff is being used. // */ // bool getUseCutoff() { // return useCutoff; // } // /** // * Get whether periodic boundary conditions are being used. // */ // bool getUsePeriodic() { // return usePeriodic; // } // /** // * Get whether there is one force buffer per atom block. // */ // bool getForceBufferPerAtomBlock() { // return forceBufferPerAtomBlock; // } // /** // * Get the number of work groups used for computing nonbonded forces. // */ // int getNumForceThreadBlocks() { // return numForceThreadBlocks; // } // /** // * Get the size of each work group used for computing nonbonded forces. // */ // int getForceThreadBlockSize() { // return forceThreadBlockSize; // } // /** // * Get the cutoff distance. // */ // double getCutoffDistance() { // return cutoff; // } // /** // * Get whether any interactions have been added. // */ // bool getHasInteractions() { // return cutoff != -1.0; // } // /** // * Get the force group in which nonbonded interactions should be computed. // */ // int getForceGroup() { // return nonbondedForceGroup; // } // /** // * Prepare to compute interactions. This updates the neighbor list. // */ // void prepareInteractions(); // /** // * Compute the nonbonded interactions. // */ // void computeInteractions(); // /** // * Check to see if the neighbor list arrays are large enough, and make them bigger if necessary. // */ // void updateNeighborListSize(); // /** // * Get the array containing the center of each atom block. // */ // CudaArray& getBlockCenters() { // return *blockCenter; // } // /** // * Get the array containing the dimensions of each atom block. // */ // CudaArray& getBlockBoundingBoxes() { // return *blockBoundingBox; // } // /** // * Get the array whose first element contains the number of tiles with interactions. // */ // CudaArray& getInteractionCount() { // return *interactionCount; // } // /** // * Get the array containing tiles with interactions. // */ // CudaArray& getInteractingTiles() { // return *interactingTiles; // } // /** // * Get the array containing flags for tiles with interactions. // */ // CudaArray& getInteractionFlags() { // return *interactionFlags; // } // /** // * Get the array containing exclusion flags. // */ // CudaArray& getExclusions() { // return *exclusions; // } // /** // * Get the array containing the index into the exclusion array for each tile. // */ // CudaArray& getExclusionIndices() { // return *exclusionIndices; // } // /** // * Get the array listing where the exclusion data starts for each row. // */ // CudaArray& getExclusionRowIndices() { // return *exclusionRowIndices; // } // /** // * Get the index of the first tile this context is responsible for processing. // */ // int getStartTileIndex() const { // return startTileIndex; // } // /** // * Get the total number of tiles this context is responsible for processing. // */ // int getNumTiles() const { // return numTiles; // } // /** // * Set the range of tiles that should be processed by this context. // */ // void setTileRange(int startTileIndex, int numTiles); // /** // * Create a Kernel for evaluating a nonbonded interaction. Cutoffs and periodic boundary conditions // * are assumed to be the same as those for the default interaction Kernel, since this kernel will use // * the same neighbor list. // * // * @param source the source code for evaluating the force and energy // * @param params the per-atom parameters this kernel may depend on // * @param arguments arrays (other than per-atom parameters) that should be passed as arguments to the kernel // * @param useExclusions specifies whether exclusions are applied to this interaction // * @param isSymmetric specifies whether the interaction is symmetric // */ // cl::Kernel createInteractionKernel(const std::string& source, const std::vector& params, const std::vector& arguments, bool useExclusions, bool isSymmetric) const; private: // static int findExclusionIndex(int x, int y, const std::vector& exclusionIndices, const std::vector& exclusionRowIndices); // CudaContext& context; // cl::Kernel forceKernel; // cl::Kernel findBlockBoundsKernel; // cl::Kernel findInteractingBlocksKernel; // cl::Kernel findInteractionsWithinBlocksKernel; // CudaArray* exclusions; // CudaArray* exclusionIndices; // CudaArray* exclusionRowIndices; // CudaArray* interactingTiles; // CudaArray* interactionFlags; // CudaArray* interactionCount; // CudaArray* blockCenter; // CudaArray* blockBoundingBox; // std::vector > atomExclusions; // std::vector parameters; // std::vector arguments; // std::string kernelSource; // std::map kernelDefines; // double cutoff; // bool useCutoff, usePeriodic, forceBufferPerAtomBlock, deviceIsCpu, anyExclusions; // int numForceBuffers, startTileIndex, numTiles, numForceThreadBlocks, forceThreadBlockSize, nonbondedForceGroup; }; /** * This class stores information about a per-atom parameter that may be used in a nonbonded kernel. */ class CudaNonbondedUtilities::ParameterInfo { public: /** * Create a ParameterInfo object. * * @param name the name of the parameter * @param type the data type of the parameter's components * @param numComponents the number of components in the parameter * @param size the size of the parameter in bytes * @param memory the memory containing the parameter values */ ParameterInfo(const std::string& name, const std::string& componentType, int numComponents, int size, CUdeviceptr memory) : name(name), componentType(componentType), numComponents(numComponents), size(size), memory(memory) { if (numComponents == 1) type = componentType; else { std::stringstream s; s << componentType << numComponents; type = s.str(); } } const std::string& getName() const { return name; } const std::string& getComponentType() const { return componentType; } const std::string& getType() const { return type; } int getNumComponents() const { return numComponents; } int getSize() const { return size; } CUdeviceptr getMemory() const { return memory; } private: std::string name; std::string componentType; std::string type; int size, numComponents; CUdeviceptr memory; }; } // namespace OpenMM #endif /*OPENMM_CUDANONBONDEDUTILITIES_H_*/