/* -------------------------------------------------------------------------- * * 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) 2011-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 "CudaBondedUtilities.h" #include "CudaExpressionUtilities.h" #include "openmm/OpenMMException.h" #include "CudaNonbondedUtilities.h" #include using namespace OpenMM; using namespace std; CudaBondedUtilities::CudaBondedUtilities(CudaContext& context) : context(context), numForceBuffers(0), maxBonds(0), hasInitializedKernels(false) { } CudaBondedUtilities::~CudaBondedUtilities() { for (int i = 0; i < (int) atomIndices.size(); i++) for (int j = 0; j < (int) atomIndices[i].size(); j++) delete atomIndices[i][j]; } void CudaBondedUtilities::addInteraction(const vector >& atoms, const string& source, int group) { if (atoms.size() > 0) { forceAtoms.push_back(atoms); forceSource.push_back(source); forceGroup.push_back(group); } } std::string CudaBondedUtilities::addArgument(CUdeviceptr data, const string& type) { arguments.push_back(data); argTypes.push_back(type); return "customArg"+context.intToString(arguments.size()); } void CudaBondedUtilities::addPrefixCode(const string& source) { prefixCode.push_back(source); } void CudaBondedUtilities::initialize(const System& system) { int numForces = forceAtoms.size(); if (numForces == 0) return; // Build the lists of atom indices. atomIndices.resize(numForces); for (int i = 0; i < numForces; i++) { int numBonds = forceAtoms[i].size(); int numAtoms = forceAtoms[i][0].size(); int startAtom = 0; while (startAtom < numAtoms) { int width = max(numAtoms-startAtom, 4); if (width == 3) width = 4; vector indexVec(width*numBonds); for (int bond = 0; bond < numBonds; bond++) { for (int atom = 0; atom < width; atom++) indexVec[bond*width+atom] = forceAtoms[i][bond][startAtom+atom]; } CudaArray* indices = CudaArray::create(indexVec.size(), "bondedIndices"); indices->upload(indexVec); atomIndices[i].push_back(indices); startAtom += width; } } // Create the kernel. stringstream s; for (int i = 0; i < (int) prefixCode.size(); i++) s<getElementSize()/4; string indexType = "unsigned int"+(indexWidth == 1 ? "" : context.intToString(indexWidth)); s<<", const "< defines; defines["PADDED_NUM_ATOMS"] = context.intToString(context.getPaddedNumAtoms()); CUmodule module = context.createModule(s.str(), defines); kernel = context.getKernel(module, "computeBondedForces"); forceAtoms.clear(); forceSource.clear(); } string CudaBondedUtilities::createForceSource(int forceIndex, int numBonds, int numAtoms, int group, const string& computeForce) { maxBonds = max(maxBonds, numBonds); string suffix1[] = {""}; string suffix4[] = {".x", ".y", ".z", ".w"}; string* suffix; stringstream s; s<<"if ((groups&"<<(1<getElementSize()/4; suffix = (indexWidth == 1 ? suffix1 : suffix4); string indexType = "unsigned int"+(indexWidth == 1 ? "" : context.intToString(indexWidth)); s<<" "<(index++, context.getForceBuffers().getDeviceBuffer()); // kernel.setArg(index++, context.getEnergyBuffer().getDeviceBuffer()); // kernel.setArg(index++, context.getPosq().getDeviceBuffer()); // index++; // for (int j = 0; j < (int) forceSets[i].size(); j++) { // kernel.setArg(index++, atomIndices[forceSets[i][j]]->getDeviceBuffer()); // kernel.setArg(index++, bufferIndices[forceSets[i][j]]->getDeviceBuffer()); // } // for (int j = 0; j < (int) arguments.size(); j++) // kernel.setArg(index++, *arguments[j]); // } // } // for (int i = 0; i < (int) kernels.size(); i++) { // kernels[i].setArg(3, groups); // context.executeKernel(kernels[i], maxBonds); // } }