#ifndef AMOEBA_OPENMM_CUDAKERNELS_H_ #define AMOEBA_OPENMM_CUDAKERNELS_H_ /* -------------------------------------------------------------------------- * * OpenMMAmoeba * * -------------------------------------------------------------------------- * * 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) 2008-2012 Stanford University and the Authors. * * Authors: Mark Friedrichs, 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 "openmm/amoebaKernels.h" #include "openmm/kernels.h" #include "openmm/System.h" #include "CudaArray.h" #include "CudaContext.h" #include "CudaSort.h" #include namespace OpenMM { /** * This kernel is invoked by AmoebaHarmonicBondForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaHarmonicBondForceKernel : public CalcAmoebaHarmonicBondForceKernel { public: CudaCalcAmoebaHarmonicBondForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaHarmonicBondForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaHarmonicBondForce this kernel will be used for */ void initialize(const System& system, const AmoebaHarmonicBondForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numBonds; CudaContext& cu; System& system; CudaArray* params; }; /** * This kernel is invoked by AmoebaUreyBradleyForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaUreyBradleyForceKernel : public CalcAmoebaUreyBradleyForceKernel { public: CudaCalcAmoebaUreyBradleyForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaUreyBradleyForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaUreyBradleyForce this kernel will be used for */ void initialize(const System& system, const AmoebaUreyBradleyForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numInteractions; CudaContext& cu; System& system; }; /** * This kernel is invoked by AmoebaHarmonicAngleForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaHarmonicAngleForceKernel : public CalcAmoebaHarmonicAngleForceKernel { public: CudaCalcAmoebaHarmonicAngleForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaHarmonicAngleForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaHarmonicAngleForce this kernel will be used for */ void initialize(const System& system, const AmoebaHarmonicAngleForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numAngles; CudaContext& cu; System& system; CudaArray* params; }; /** * This kernel is invoked by AmoebaHarmonicInPlaneAngleForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaHarmonicInPlaneAngleForceKernel : public CalcAmoebaHarmonicInPlaneAngleForceKernel { public: CudaCalcAmoebaHarmonicInPlaneAngleForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaHarmonicInPlaneAngleForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaHarmonicInPlaneAngleForce this kernel will be used for */ void initialize(const System& system, const AmoebaHarmonicInPlaneAngleForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numAngles; CudaContext& cu; System& system; CudaArray* params; }; /** * This kernel is invoked by AmoebaTorsionForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaTorsionForceKernel : public CalcAmoebaTorsionForceKernel { public: CudaCalcAmoebaTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaTorsionForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaTorsionForce this kernel will be used for */ void initialize(const System& system, const AmoebaTorsionForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numTorsions; CudaContext& cu; System& system; }; /** * This kernel is invoked by AmoebaPiTorsionForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaPiTorsionForceKernel : public CalcAmoebaPiTorsionForceKernel { public: CudaCalcAmoebaPiTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaPiTorsionForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaPiTorsionForce this kernel will be used for */ void initialize(const System& system, const AmoebaPiTorsionForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numPiTorsions; CudaContext& cu; System& system; CudaArray* params; }; /** * This kernel is invoked by AmoebaStretchBendForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaStretchBendForceKernel : public CalcAmoebaStretchBendForceKernel { public: CudaCalcAmoebaStretchBendForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaStretchBendForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaStretchBendForce this kernel will be used for */ void initialize(const System& system, const AmoebaStretchBendForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numStretchBends; CudaContext& cu; System& system; CudaArray* params; }; /** * This kernel is invoked by AmoebaOutOfPlaneBendForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaOutOfPlaneBendForceKernel : public CalcAmoebaOutOfPlaneBendForceKernel { public: CudaCalcAmoebaOutOfPlaneBendForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaOutOfPlaneBendForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaOutOfPlaneBendForce this kernel will be used for */ void initialize(const System& system, const AmoebaOutOfPlaneBendForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numOutOfPlaneBends; CudaContext& cu; System& system; CudaArray* params; }; /** * This kernel is invoked by AmoebaTorsionTorsionForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaTorsionTorsionForceKernel : public CalcAmoebaTorsionTorsionForceKernel { public: CudaCalcAmoebaTorsionTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaTorsionTorsionForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaTorsionTorsionForce this kernel will be used for */ void initialize(const System& system, const AmoebaTorsionTorsionForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; int numTorsionTorsions; int numTorsionTorsionGrids; CudaContext& cu; System& system; CudaArray* gridValues; CudaArray* gridParams; CudaArray* torsionParams; }; /** * This kernel is invoked by AmoebaMultipoleForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaMultipoleForceKernel : public CalcAmoebaMultipoleForceKernel { public: CudaCalcAmoebaMultipoleForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaMultipoleForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaMultipoleForce this kernel will be used for */ void initialize(const System& system, const AmoebaMultipoleForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); /** * Execute the kernel to calculate the electrostatic potential * * @param context the context in which to execute this kernel * @param inputGrid input grid coordinates * @param outputElectrostaticPotential output potential */ void getElectrostaticPotential(ContextImpl& context, const std::vector< Vec3 >& inputGrid, std::vector< double >& outputElectrostaticPotential ); /** * Get the system multipole moments * * @param origin origin * @param context context * @param outputMultipoleMoments (charge, * dipole_x, dipole_y, dipole_z, * quadrupole_xx, quadrupole_xy, quadrupole_xz, * quadrupole_yx, quadrupole_yy, quadrupole_yz, * quadrupole_zx, quadrupole_zy, quadrupole_zz ) */ void getSystemMultipoleMoments(ContextImpl& context, const Vec3& origin, std::vector& outputMultipoleMoments); private: class ForceInfo; class SortTrait : public CudaSort::SortTrait { int getDataSize() const {return 8;} int getKeySize() const {return 4;} const char* getDataType() const {return "int2";} const char* getKeyType() const {return "int";} const char* getMinKey() const {return "INT_MIN";} const char* getMaxKey() const {return "INT_MAX";} const char* getMaxValue() const {return "make_int2(INT_MAX, INT_MAX)";} const char* getSortKey() const {return "value.y";} }; void initializeScaleFactors(); template void computeSystemMultipoleMoments(ContextImpl& context, const Vec3& origin, std::vector& outputMultipoleMoments); int numMultipoles, maxInducedIterations; double inducedEpsilon; bool hasInitializedScaleFactors, hasInitializedFFT; CudaContext& cu; System& system; std::vector covalentFlagValues; std::vector polarizationFlagValues; CudaArray* multipoleParticles; CudaArray* molecularDipoles; CudaArray* molecularQuadrupoles; CudaArray* labFrameDipoles; CudaArray* labFrameQuadrupoles; CudaArray* field; CudaArray* fieldPolar; CudaArray* inducedField; CudaArray* inducedFieldPolar; CudaArray* torque; CudaArray* dampingAndThole; CudaArray* inducedDipole; CudaArray* inducedDipolePolar; CudaArray* inducedDipoleErrors; CudaArray* polarizability; CudaArray* covalentFlags; CudaArray* polarizationGroupFlags; CudaArray* pmeGrid; CudaArray* pmeBsplineModuliX; CudaArray* pmeBsplineModuliY; CudaArray* pmeBsplineModuliZ; CudaArray* pmeTheta1; CudaArray* pmeTheta2; CudaArray* pmeTheta3; CudaArray* pmeIgrid; CudaArray* pmePhi; CudaArray* pmePhid; CudaArray* pmePhip; CudaArray* pmePhidp; CudaArray* pmeAtomRange; CudaArray* pmeAtomGridIndex; CudaSort* sort; cufftHandle fft; CUfunction computeMomentsKernel, recordInducedDipolesKernel, computeFixedFieldKernel, computeInducedFieldKernel, updateInducedFieldKernel, electrostaticsKernel, mapTorqueKernel; CUfunction pmeUpdateBsplinesKernel, pmeAtomRangeKernel, pmeZIndexKernel, pmeSpreadFixedMultipolesKernel, pmeSpreadInducedDipolesKernel, pmeConvolutionKernel, pmeFixedPotentialKernel, pmeInducedPotentialKernel; CUfunction pmeFixedForceKernel, pmeInducedForceKernel, pmeRecordInducedFieldDipolesKernel, computePotentialKernel; static const int PmeOrder = 5; }; /** * This kernel is invoked by AmoebaMultipoleForce to calculate the forces acting on the system and the energy of the system. */ class CudaCalcAmoebaGeneralizedKirkwoodForceKernel : public CalcAmoebaGeneralizedKirkwoodForceKernel { public: CudaCalcAmoebaGeneralizedKirkwoodForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaGeneralizedKirkwoodForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaMultipoleForce this kernel will be used for */ void initialize(const System& system, const AmoebaGeneralizedKirkwoodForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; CudaContext& cu; System& system; }; /** * This kernel is invoked to calculate the vdw forces acting on the system and the energy of the system. */ class CudaCalcAmoebaVdwForceKernel : public CalcAmoebaVdwForceKernel { public: CudaCalcAmoebaVdwForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaVdwForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaMultipoleForce this kernel will be used for */ void initialize(const System& system, const AmoebaVdwForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; CudaContext& cu; System& system; bool hasInitializedNonbonded; double dispersionCoefficient; CudaArray* sigmaEpsilon; CudaArray* bondReductionAtoms; CudaArray* bondReductionFactors; CudaArray* tempPosq; CudaArray* tempForces; CudaNonbondedUtilities* nonbonded; CUfunction prepareKernel, spreadKernel; }; /** * This kernel is invoked to calculate the WCA dispersion forces acting on the system and the energy of the system. */ class CudaCalcAmoebaWcaDispersionForceKernel : public CalcAmoebaWcaDispersionForceKernel { public: CudaCalcAmoebaWcaDispersionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system); ~CudaCalcAmoebaWcaDispersionForceKernel(); /** * Initialize the kernel. * * @param system the System this kernel will be applied to * @param force the AmoebaMultipoleForce this kernel will be used for */ void initialize(const System& system, const AmoebaWcaDispersionForce& force); /** * Execute the kernel to calculate the forces and/or energy. * * @param context the context in which to execute this kernel * @param includeForces true if forces should be calculated * @param includeEnergy true if the energy should be calculated * @return the potential energy due to the force */ double execute(ContextImpl& context, bool includeForces, bool includeEnergy); private: class ForceInfo; CudaContext& cu; System& system; }; } // namespace OpenMM #endif /*AMOEBA_OPENMM_CUDAKERNELS_H*/