Commit 9bdab7b6 authored by peastman's avatar peastman
Browse files

Fixed error using interaction groups with parameter derivatives

parent 8d7234e5
...@@ -778,7 +778,7 @@ private: ...@@ -778,7 +778,7 @@ private:
std::vector<CudaArray*> tabulatedFunctions; std::vector<CudaArray*> tabulatedFunctions;
double longRangeCoefficient; double longRangeCoefficient;
std::vector<double> longRangeCoefficientDerivs; std::vector<double> longRangeCoefficientDerivs;
bool hasInitializedLongRangeCorrection, hasInitializedKernel; bool hasInitializedLongRangeCorrection, hasInitializedKernel, hasParamDerivs;
int numGroupThreadBlocks; int numGroupThreadBlocks;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
const System& system; const System& system;
......
...@@ -2664,6 +2664,7 @@ void CudaCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNonbo ...@@ -2664,6 +2664,7 @@ void CudaCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNonbo
// Create the kernel. // Create the kernel.
hasParamDerivs = (force.getNumEnergyParameterDerivatives() > 0);
map<string, string> replacements; map<string, string> replacements;
replacements["COMPUTE_INTERACTION"] = interactionSource; replacements["COMPUTE_INTERACTION"] = interactionSource;
const string suffixes[] = {"x", "y", "z", "w"}; const string suffixes[] = {"x", "y", "z", "w"};
...@@ -2687,6 +2688,8 @@ void CudaCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNonbo ...@@ -2687,6 +2688,8 @@ void CudaCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNonbo
args << ", const " << tableTypes[i]<< "* __restrict__ table" << i; args << ", const " << tableTypes[i]<< "* __restrict__ table" << i;
if (globals != NULL) if (globals != NULL)
args<<", const float* __restrict__ globals"; args<<", const float* __restrict__ globals";
if (hasParamDerivs)
args << ", mixed* __restrict__ energyParamDerivs";
replacements["PARAMETER_ARGUMENTS"] = args.str(); replacements["PARAMETER_ARGUMENTS"] = args.str();
stringstream load1; stringstream load1;
for (int i = 0; i < (int) buffers.size(); i++) for (int i = 0; i < (int) buffers.size(); i++)
...@@ -2718,6 +2721,19 @@ void CudaCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNonbo ...@@ -2718,6 +2721,19 @@ void CudaCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNonbo
} }
} }
replacements["LOAD_ATOM2_PARAMETERS"] = load2.str(); replacements["LOAD_ATOM2_PARAMETERS"] = load2.str();
stringstream initDerivs, saveDerivs;
const vector<string>& allParamDerivNames = cu.getEnergyParamDerivNames();
int numDerivs = allParamDerivNames.size();
for (int i = 0; i < force.getNumEnergyParameterDerivatives(); i++) {
string paramName = force.getEnergyParameterDerivativeName(i);
string derivVariable = cu.getNonbondedUtilities().addEnergyParameterDerivative(paramName);
initDerivs<<"mixed "<<derivVariable<<" = 0;\n";
for (int index = 0; index < numDerivs; index++)
if (allParamDerivNames[index] == paramName)
saveDerivs<<"energyParamDerivs[(blockIdx.x*blockDim.x+threadIdx.x)*"<<numDerivs<<"+"<<index<<"] += "<<derivVariable<<";\n";
}
replacements["INIT_DERIVATIVES"] = initDerivs.str();
replacements["SAVE_DERIVATIVES"] = saveDerivs.str();
map<string, string> defines; map<string, string> defines;
if (force.getNonbondedMethod() != CustomNonbondedForce::NoCutoff) if (force.getNonbondedMethod() != CustomNonbondedForce::NoCutoff)
defines["USE_CUTOFF"] = "1"; defines["USE_CUTOFF"] = "1";
...@@ -2779,6 +2795,8 @@ double CudaCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool in ...@@ -2779,6 +2795,8 @@ double CudaCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool in
interactionGroupArgs.push_back(&function->getDevicePointer()); interactionGroupArgs.push_back(&function->getDevicePointer());
if (globals != NULL) if (globals != NULL)
interactionGroupArgs.push_back(&globals->getDevicePointer()); interactionGroupArgs.push_back(&globals->getDevicePointer());
if (hasParamDerivs)
interactionGroupArgs.push_back(&cu.getEnergyParamDerivBuffer().getDevicePointer());
} }
int forceThreadBlockSize = cu.getNonbondedUtilities().getForceThreadBlockSize(); int forceThreadBlockSize = cu.getNonbondedUtilities().getForceThreadBlockSize();
cu.executeKernel(interactionGroupKernel, &interactionGroupArgs[0], numGroupThreadBlocks*forceThreadBlockSize, forceThreadBlockSize); cu.executeKernel(interactionGroupKernel, &interactionGroupArgs[0], numGroupThreadBlocks*forceThreadBlockSize, forceThreadBlockSize);
......
...@@ -17,6 +17,7 @@ extern "C" __global__ void computeInteractionGroups( ...@@ -17,6 +17,7 @@ extern "C" __global__ void computeInteractionGroups(
const unsigned int tgx = threadIdx.x & (TILE_SIZE-1); // index within the warp const unsigned int tgx = threadIdx.x & (TILE_SIZE-1); // index within the warp
const unsigned int tbx = threadIdx.x - tgx; // block warpIndex const unsigned int tbx = threadIdx.x - tgx; // block warpIndex
mixed energy = 0; mixed energy = 0;
INIT_DERIVATIVES
__shared__ AtomData localData[LOCAL_MEMORY_SIZE]; __shared__ AtomData localData[LOCAL_MEMORY_SIZE];
const unsigned int startTile = FIRST_TILE+warp*(LAST_TILE-FIRST_TILE)/totalWarps; const unsigned int startTile = FIRST_TILE+warp*(LAST_TILE-FIRST_TILE)/totalWarps;
...@@ -58,6 +59,7 @@ extern "C" __global__ void computeInteractionGroups( ...@@ -58,6 +59,7 @@ extern "C" __global__ void computeInteractionGroups(
LOAD_ATOM2_PARAMETERS LOAD_ATOM2_PARAMETERS
real dEdR = 0.0f; real dEdR = 0.0f;
real tempEnergy = 0.0f; real tempEnergy = 0.0f;
const real interactionScale = 1.0f;
COMPUTE_INTERACTION COMPUTE_INTERACTION
energy += tempEnergy; energy += tempEnergy;
delta *= dEdR; delta *= dEdR;
...@@ -82,4 +84,5 @@ extern "C" __global__ void computeInteractionGroups( ...@@ -82,4 +84,5 @@ extern "C" __global__ void computeInteractionGroups(
atomicAdd(&forceBuffers[atom2+2*PADDED_NUM_ATOMS], static_cast<unsigned long long>((long long) (localData[threadIdx.x].fz*0x100000000))); atomicAdd(&forceBuffers[atom2+2*PADDED_NUM_ATOMS], static_cast<unsigned long long>((long long) (localData[threadIdx.x].fz*0x100000000)));
} }
energyBuffer[blockIdx.x*blockDim.x+threadIdx.x] += energy; energyBuffer[blockIdx.x*blockDim.x+threadIdx.x] += energy;
SAVE_DERIVATIVES
} }
...@@ -758,7 +758,7 @@ private: ...@@ -758,7 +758,7 @@ private:
std::vector<OpenCLArray*> tabulatedFunctions; std::vector<OpenCLArray*> tabulatedFunctions;
double longRangeCoefficient; double longRangeCoefficient;
std::vector<double> longRangeCoefficientDerivs; std::vector<double> longRangeCoefficientDerivs;
bool hasInitializedLongRangeCorrection, hasInitializedKernel; bool hasInitializedLongRangeCorrection, hasInitializedKernel, hasParamDerivs;
int numGroupThreadBlocks; int numGroupThreadBlocks;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
const System& system; const System& system;
......
...@@ -2789,6 +2789,7 @@ void OpenCLCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNon ...@@ -2789,6 +2789,7 @@ void OpenCLCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNon
// Create the kernel. // Create the kernel.
hasParamDerivs = (force.getNumEnergyParameterDerivatives() > 0);
map<string, string> replacements; map<string, string> replacements;
replacements["COMPUTE_INTERACTION"] = interactionSource; replacements["COMPUTE_INTERACTION"] = interactionSource;
const string suffixes[] = {"x", "y", "z", "w"}; const string suffixes[] = {"x", "y", "z", "w"};
...@@ -2812,6 +2813,8 @@ void OpenCLCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNon ...@@ -2812,6 +2813,8 @@ void OpenCLCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNon
args << ", __global const " << tableTypes[i]<< "* restrict table" << i; args << ", __global const " << tableTypes[i]<< "* restrict table" << i;
if (globals != NULL) if (globals != NULL)
args<<", __global const float* restrict globals"; args<<", __global const float* restrict globals";
if (hasParamDerivs)
args << ", __global mixed* restrict energyParamDerivs";
replacements["PARAMETER_ARGUMENTS"] = args.str(); replacements["PARAMETER_ARGUMENTS"] = args.str();
stringstream load1; stringstream load1;
for (int i = 0; i < (int) buffers.size(); i++) for (int i = 0; i < (int) buffers.size(); i++)
...@@ -2843,6 +2846,19 @@ void OpenCLCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNon ...@@ -2843,6 +2846,19 @@ void OpenCLCalcCustomNonbondedForceKernel::initInteractionGroups(const CustomNon
} }
} }
replacements["LOAD_ATOM2_PARAMETERS"] = load2.str(); replacements["LOAD_ATOM2_PARAMETERS"] = load2.str();
stringstream initDerivs, saveDerivs;
const vector<string>& allParamDerivNames = cl.getEnergyParamDerivNames();
int numDerivs = allParamDerivNames.size();
for (int i = 0; i < force.getNumEnergyParameterDerivatives(); i++) {
string paramName = force.getEnergyParameterDerivativeName(i);
string derivVariable = cl.getNonbondedUtilities().addEnergyParameterDerivative(paramName);
initDerivs<<"mixed "<<derivVariable<<" = 0;\n";
for (int index = 0; index < numDerivs; index++)
if (allParamDerivNames[index] == paramName)
saveDerivs<<"energyParamDerivs[get_global_id(0)*"<<numDerivs<<"+"<<index<<"] += "<<derivVariable<<";\n";
}
replacements["INIT_DERIVATIVES"] = initDerivs.str();
replacements["SAVE_DERIVATIVES"] = saveDerivs.str();
map<string, string> defines; map<string, string> defines;
if (force.getNonbondedMethod() != CustomNonbondedForce::NoCutoff) if (force.getNonbondedMethod() != CustomNonbondedForce::NoCutoff)
defines["USE_CUTOFF"] = "1"; defines["USE_CUTOFF"] = "1";
...@@ -2902,6 +2918,8 @@ double OpenCLCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool ...@@ -2902,6 +2918,8 @@ double OpenCLCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool
interactionGroupKernel.setArg<cl::Memory>(index++, function->getDeviceBuffer()); interactionGroupKernel.setArg<cl::Memory>(index++, function->getDeviceBuffer());
if (globals != NULL) if (globals != NULL)
interactionGroupKernel.setArg<cl::Buffer>(index++, globals->getDeviceBuffer()); interactionGroupKernel.setArg<cl::Buffer>(index++, globals->getDeviceBuffer());
if (hasParamDerivs)
interactionGroupKernel.setArg<cl::Memory>(index++, cl.getEnergyParamDerivBuffer().getDeviceBuffer());
} }
setPeriodicBoxArgs(cl, interactionGroupKernel, 4); setPeriodicBoxArgs(cl, interactionGroupKernel, 4);
int forceThreadBlockSize = max(32, cl.getNonbondedUtilities().getForceThreadBlockSize()); int forceThreadBlockSize = max(32, cl.getNonbondedUtilities().getForceThreadBlockSize());
......
...@@ -50,6 +50,7 @@ __kernel void computeInteractionGroups( ...@@ -50,6 +50,7 @@ __kernel void computeInteractionGroups(
const unsigned int tgx = get_local_id(0) & (TILE_SIZE-1); // index within the warp const unsigned int tgx = get_local_id(0) & (TILE_SIZE-1); // index within the warp
const unsigned int tbx = get_local_id(0) - tgx; // block warpIndex const unsigned int tbx = get_local_id(0) - tgx; // block warpIndex
mixed energy = 0; mixed energy = 0;
INIT_DERIVATIVES
__local AtomData localData[LOCAL_MEMORY_SIZE]; __local AtomData localData[LOCAL_MEMORY_SIZE];
const unsigned int startTile = FIRST_TILE+warp*(LAST_TILE-FIRST_TILE)/totalWarps; const unsigned int startTile = FIRST_TILE+warp*(LAST_TILE-FIRST_TILE)/totalWarps;
...@@ -93,6 +94,7 @@ __kernel void computeInteractionGroups( ...@@ -93,6 +94,7 @@ __kernel void computeInteractionGroups(
LOAD_ATOM2_PARAMETERS LOAD_ATOM2_PARAMETERS
real dEdR = 0.0f; real dEdR = 0.0f;
real tempEnergy = 0.0f; real tempEnergy = 0.0f;
const real interactionScale = 1.0f;
COMPUTE_INTERACTION COMPUTE_INTERACTION
energy += tempEnergy; energy += tempEnergy;
delta *= dEdR; delta *= dEdR;
...@@ -125,4 +127,5 @@ __kernel void computeInteractionGroups( ...@@ -125,4 +127,5 @@ __kernel void computeInteractionGroups(
#endif #endif
} }
energyBuffer[get_global_id(0)] += energy; energyBuffer[get_global_id(0)] += energy;
SAVE_DERIVATIVES
} }
...@@ -1188,6 +1188,47 @@ void testEnergyParameterDerivatives2() { ...@@ -1188,6 +1188,47 @@ void testEnergyParameterDerivatives2() {
ASSERT_EQUAL_TOL((energy1-energy2)/(2*delta), derivs["a"], 1e-4); ASSERT_EQUAL_TOL((energy1-energy2)/(2*delta), derivs["a"], 1e-4);
} }
void testEnergyParameterDerivativesWithGroups() {
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
VerletIntegrator integrator(0.01);
CustomNonbondedForce* nonbonded = new CustomNonbondedForce("k*(r-r0)^2");
nonbonded->addGlobalParameter("r0", 0.0);
nonbonded->addGlobalParameter("k", 0.0);
nonbonded->addEnergyParameterDerivative("k");
nonbonded->addEnergyParameterDerivative("r0");
vector<double> parameters;
nonbonded->addParticle(parameters);
nonbonded->addParticle(parameters);
nonbonded->addParticle(parameters);
set<int> set1, set2;
set1.insert(1);
set2.insert(0);
set2.insert(2);
nonbonded->addInteractionGroup(set1, set2);
system.addForce(nonbonded);
Context context(system, integrator, platform);
vector<Vec3> positions(3);
positions[0] = Vec3(0, 2, 0);
positions[1] = Vec3(0, 0, 0);
positions[2] = Vec3(1, 0, 0);
context.setPositions(positions);
for (int i = 0; i < 10; i++) {
double r0 = 0.1*i;
double k = 10-i;
context.setParameter("r0", r0);
context.setParameter("k", k);
State state = context.getState(State::ParameterDerivatives);
map<string, double> derivs = state.getEnergyParameterDerivatives();
double dEdr0 = -2*k*((2-r0)+(1-r0));
double dEdk = (2-r0)*(2-r0) + (1-r0)*(1-r0);
ASSERT_EQUAL_TOL(dEdr0, derivs["r0"], 1e-5);
ASSERT_EQUAL_TOL(dEdk, derivs["k"], 1e-5);
}
}
void runPlatformTests(); void runPlatformTests();
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
...@@ -1217,6 +1258,7 @@ int main(int argc, char* argv[]) { ...@@ -1217,6 +1258,7 @@ int main(int argc, char* argv[]) {
testIllegalVariable(); testIllegalVariable();
testEnergyParameterDerivatives(); testEnergyParameterDerivatives();
testEnergyParameterDerivatives2(); testEnergyParameterDerivatives2();
testEnergyParameterDerivativesWithGroups();
runPlatformTests(); runPlatformTests();
} }
catch(const exception& e) { catch(const exception& e) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment