void testSerialization() { // Create a Force. NonbondedForce force; force.setNonbondedMethod(NonbondedForce::CutoffPeriodic); force.setCutoffDistance(2.0); force.setEwaldErrorTolerance(1e-3); force.setReactionFieldDielectric(50.0); force.setUseDispersionCorrection(false); force.addParticle(1, 0.1, 0.01); force.addParticle(0.5, 0.2, 0.02); force.addParticle(-0.5, 0.3, 0.03); force.addException(0, 1, 2, 0.5, 0.1); force.addException(1, 2, 0.2, 0.4, 0.2); // Serialize and then deserialize it. stringstream buffer; XmlSerializer::serialize<NonbondedForce>(&force, "Force", buffer); NonbondedForce* copy = XmlSerializer::deserialize<NonbondedForce>(buffer); // Compare the two forces to see if they are identical. NonbondedForce& force2 = *copy; ASSERT_EQUAL(force.getNonbondedMethod(), force2.getNonbondedMethod()); ASSERT_EQUAL(force.getCutoffDistance(), force2.getCutoffDistance()); ASSERT_EQUAL(force.getEwaldErrorTolerance(), force2.getEwaldErrorTolerance()); ASSERT_EQUAL(force.getReactionFieldDielectric(), force2.getReactionFieldDielectric()); ASSERT_EQUAL(force.getUseDispersionCorrection(), force2.getUseDispersionCorrection()); ASSERT_EQUAL(force.getNumParticles(), force2.getNumParticles()); for (int i = 0; i < force.getNumParticles(); i++) { double charge1, sigma1, epsilon1; double charge2, sigma2, epsilon2; force.getParticleParameters(i, charge1, sigma1, epsilon1); force2.getParticleParameters(i, charge2, sigma2, epsilon2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(epsilon1, epsilon2); } ASSERT_EQUAL(force.getNumExceptions(), force2.getNumExceptions()); for (int i = 0; i < force.getNumExceptions(); i++) { int a1, a2, b1, b2; double charge1, sigma1, epsilon1; double charge2, sigma2, epsilon2; force.getExceptionParameters(i, a1, b1, charge1, sigma1, epsilon1); force2.getExceptionParameters(i, a2, b2, charge2, sigma2, epsilon2); ASSERT_EQUAL(a1, a2); ASSERT_EQUAL(b1, b2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(epsilon1, epsilon2); } }
void ValidateOpenMM::writeNonbondedForce( FILE* filePtr, const NonbondedForce & nonbondedForce ) const { // charge and vdw parameters (void) fprintf( filePtr, "NonbondedForce %d\n", nonbondedForce.getNumParticles() ); for(int ii = 0; ii < nonbondedForce.getNumParticles(); ii++ ){ double charge, sigma, epsilon; nonbondedForce.getParticleParameters( ii, charge, sigma, epsilon ); (void) fprintf( filePtr, "%8d %14.7e %14.7e %14.7e\n", ii, charge, sigma, epsilon ); } // cutoff, dielectric, Ewald tolerance (void) fprintf( filePtr, "CutoffDistance %14.7e\n", nonbondedForce.getCutoffDistance() ); (void) fprintf( filePtr, "RFDielectric %14.7e\n", nonbondedForce.getReactionFieldDielectric() ); (void) fprintf( filePtr, "EwaldRTolerance %14.7e\n", nonbondedForce.getEwaldErrorTolerance() ); // cutoff mode std::string nonbondedForceMethod; switch( nonbondedForce.getNonbondedMethod() ){ case NonbondedForce::NoCutoff: nonbondedForceMethod = "NoCutoff"; break; case NonbondedForce::CutoffNonPeriodic: nonbondedForceMethod = "CutoffNonPeriodic"; break; case NonbondedForce::CutoffPeriodic: nonbondedForceMethod = "CutoffPeriodic"; break; case NonbondedForce::Ewald: nonbondedForceMethod = "Ewald"; break; case NonbondedForce::PME: nonbondedForceMethod = "PME"; break; default: nonbondedForceMethod = "Unknown"; } (void) fprintf( filePtr, "NonbondedForceMethod %s\n", nonbondedForceMethod.c_str() ); (void) fprintf( filePtr, "NonbondedForceExceptions %d\n", nonbondedForce.getNumExceptions() ); for(int ii = 0; ii < nonbondedForce.getNumExceptions(); ii++ ){ int particle1, particle2; double chargeProd, sigma, epsilon; nonbondedForce.getExceptionParameters( ii, particle1, particle2, chargeProd, sigma, epsilon ); (void) fprintf( filePtr, "%8d %8d %8d %14.7e %14.7e %14.7e\n", ii, particle1, particle2, chargeProd, sigma, epsilon ); } }
void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const NonbondedForce& force) { if (force.getNumParticles() != numParticles) throw OpenMMException("updateParametersInContext: The number of particles has changed"); vector<int> nb14s; for (int i = 0; i < force.getNumExceptions(); i++) { int particle1, particle2; double chargeProd, sigma, epsilon; force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); if (chargeProd != 0.0 || epsilon != 0.0) nb14s.push_back(i); } if (nb14s.size() != num14) throw OpenMMException("updateParametersInContext: The number of non-excluded exceptions has changed"); // Record the values. double sumSquaredCharges = 0.0; for (int i = 0; i < numParticles; ++i) { double charge, radius, depth; force.getParticleParameters(i, charge, radius, depth); data.posq[4*i+3] = (float) charge; particleParams[i] = make_pair((float) (0.5*radius), (float) (2.0*sqrt(depth))); sumSquaredCharges += charge*charge; } if (nonbondedMethod == Ewald || nonbondedMethod == PME) ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI); else ewaldSelfEnergy = 0.0; for (int i = 0; i < num14; ++i) { int particle1, particle2; double charge, radius, depth; force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth); bonded14IndexArray[i][0] = particle1; bonded14IndexArray[i][1] = particle2; bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius); bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth); bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge); } // Recompute the coefficient for the dispersion correction. NonbondedForce::NonbondedMethod method = force.getNonbondedMethod(); if (force.getUseDispersionCorrection() && (method == NonbondedForce::CutoffPeriodic || method == NonbondedForce::Ewald || method == NonbondedForce::PME)) dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(context.getSystem(), force); }
void CpuCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force) { // Identify which exceptions are 1-4 interactions. numParticles = force.getNumParticles(); exclusions.resize(numParticles); vector<int> nb14s; for (int i = 0; i < force.getNumExceptions(); i++) { int particle1, particle2; double chargeProd, sigma, epsilon; force.getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); exclusions[particle1].insert(particle2); exclusions[particle2].insert(particle1); if (chargeProd != 0.0 || epsilon != 0.0) nb14s.push_back(i); } // Record the particle parameters. num14 = nb14s.size(); bonded14IndexArray = new int*[num14]; for (int i = 0; i < num14; i++) bonded14IndexArray[i] = new int[2]; bonded14ParamArray = new double*[num14]; for (int i = 0; i < num14; i++) bonded14ParamArray[i] = new double[3]; particleParams.resize(numParticles); double sumSquaredCharges = 0.0; for (int i = 0; i < numParticles; ++i) { double charge, radius, depth; force.getParticleParameters(i, charge, radius, depth); data.posq[4*i+3] = (float) charge; particleParams[i] = make_pair((float) (0.5*radius), (float) (2.0*sqrt(depth))); sumSquaredCharges += charge*charge; } // Recorded exception parameters. for (int i = 0; i < num14; ++i) { int particle1, particle2; double charge, radius, depth; force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth); bonded14IndexArray[i][0] = particle1; bonded14IndexArray[i][1] = particle2; bonded14ParamArray[i][0] = static_cast<RealOpenMM>(radius); bonded14ParamArray[i][1] = static_cast<RealOpenMM>(4.0*depth); bonded14ParamArray[i][2] = static_cast<RealOpenMM>(charge); } // Record other parameters. nonbondedMethod = CalcNonbondedForceKernel::NonbondedMethod(force.getNonbondedMethod()); nonbondedCutoff = force.getCutoffDistance(); if (nonbondedMethod == NoCutoff) useSwitchingFunction = false; else { useSwitchingFunction = force.getUseSwitchingFunction(); switchingDistance = force.getSwitchingDistance(); } if (nonbondedMethod == Ewald) { double alpha; NonbondedForceImpl::calcEwaldParameters(system, force, alpha, kmax[0], kmax[1], kmax[2]); ewaldAlpha = alpha; } else if (nonbondedMethod == PME) { double alpha; NonbondedForceImpl::calcPMEParameters(system, force, alpha, gridSize[0], gridSize[1], gridSize[2]); ewaldAlpha = alpha; } if (nonbondedMethod == Ewald || nonbondedMethod == PME) ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI); else ewaldSelfEnergy = 0.0; rfDielectric = force.getReactionFieldDielectric(); if (force.getUseDispersionCorrection()) dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(system, force); else dispersionCoefficient = 0.0; lastPositions.resize(numParticles, Vec3(1e10, 1e10, 1e10)); data.isPeriodic = (nonbondedMethod == CutoffPeriodic || nonbondedMethod == Ewald || nonbondedMethod == PME); }
void testSerialization() { // Create a Force. NonbondedForce force; force.setForceGroup(3); force.setNonbondedMethod(NonbondedForce::CutoffPeriodic); force.setSwitchingDistance(1.5); force.setUseSwitchingFunction(true); force.setCutoffDistance(2.0); force.setEwaldErrorTolerance(1e-3); force.setReactionFieldDielectric(50.0); force.setUseDispersionCorrection(false); double alpha = 0.5; int nx = 3, ny = 5, nz = 7; force.setPMEParameters(alpha, nx, ny, nz); double dalpha = 0.8; int dnx = 4, dny = 6, dnz = 7; force.setLJPMEParameters(dalpha, dnx, dny, dnz); force.addParticle(1, 0.1, 0.01); force.addParticle(0.5, 0.2, 0.02); force.addParticle(-0.5, 0.3, 0.03); force.addException(0, 1, 2, 0.5, 0.1); force.addException(1, 2, 0.2, 0.4, 0.2); force.addGlobalParameter("scale1", 1.0); force.addGlobalParameter("scale2", 2.0); force.addParticleParameterOffset("scale1", 2, 1.5, 2.0, 2.5); force.addExceptionParameterOffset("scale2", 1, -0.1, -0.2, -0.3); // Serialize and then deserialize it. stringstream buffer; XmlSerializer::serialize<NonbondedForce>(&force, "Force", buffer); NonbondedForce* copy = XmlSerializer::deserialize<NonbondedForce>(buffer); // Compare the two forces to see if they are identical. NonbondedForce& force2 = *copy; ASSERT_EQUAL(force.getForceGroup(), force2.getForceGroup()); ASSERT_EQUAL(force.getNonbondedMethod(), force2.getNonbondedMethod()); ASSERT_EQUAL(force.getSwitchingDistance(), force2.getSwitchingDistance()); ASSERT_EQUAL(force.getUseSwitchingFunction(), force2.getUseSwitchingFunction()); ASSERT_EQUAL(force.getCutoffDistance(), force2.getCutoffDistance()); ASSERT_EQUAL(force.getEwaldErrorTolerance(), force2.getEwaldErrorTolerance()); ASSERT_EQUAL(force.getReactionFieldDielectric(), force2.getReactionFieldDielectric()); ASSERT_EQUAL(force.getUseDispersionCorrection(), force2.getUseDispersionCorrection()); ASSERT_EQUAL(force.getNumParticles(), force2.getNumParticles()); ASSERT_EQUAL(force.getNumExceptions(), force2.getNumExceptions()); ASSERT_EQUAL(force.getNumGlobalParameters(), force2.getNumGlobalParameters()); ASSERT_EQUAL(force.getNumParticleParameterOffsets(), force2.getNumParticleParameterOffsets()); ASSERT_EQUAL(force.getNumExceptionParameterOffsets(), force2.getNumExceptionParameterOffsets()); double alpha2; int nx2, ny2, nz2; force2.getPMEParameters(alpha2, nx2, ny2, nz2); ASSERT_EQUAL(alpha, alpha2); ASSERT_EQUAL(nx, nx2); ASSERT_EQUAL(ny, ny2); ASSERT_EQUAL(nz, nz2); double dalpha2; int dnx2, dny2, dnz2; force2.getLJPMEParameters(dalpha2, dnx2, dny2, dnz2); ASSERT_EQUAL(dalpha, dalpha2); ASSERT_EQUAL(dnx, dnx2); ASSERT_EQUAL(dny, dny2); ASSERT_EQUAL(dnz, dnz2); for (int i = 0; i < force.getNumGlobalParameters(); i++) { ASSERT_EQUAL(force.getGlobalParameterName(i), force2.getGlobalParameterName(i)); ASSERT_EQUAL(force.getGlobalParameterDefaultValue(i), force2.getGlobalParameterDefaultValue(i)); } for (int i = 0; i < force.getNumParticleParameterOffsets(); i++) { int index1, index2; string param1, param2; double charge1, sigma1, epsilon1; double charge2, sigma2, epsilon2; force.getParticleParameterOffset(i, param1, index1, charge1, sigma1, epsilon1); force2.getParticleParameterOffset(i, param2, index2, charge2, sigma2, epsilon2); ASSERT_EQUAL(index1, index1); ASSERT_EQUAL(param1, param2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(epsilon1, epsilon2); } for (int i = 0; i < force.getNumExceptionParameterOffsets(); i++) { int index1, index2; string param1, param2; double charge1, sigma1, epsilon1; double charge2, sigma2, epsilon2; force.getExceptionParameterOffset(i, param1, index1, charge1, sigma1, epsilon1); force2.getExceptionParameterOffset(i, param2, index2, charge2, sigma2, epsilon2); ASSERT_EQUAL(index1, index1); ASSERT_EQUAL(param1, param2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(epsilon1, epsilon2); } for (int i = 0; i < force.getNumParticles(); i++) { double charge1, sigma1, epsilon1; double charge2, sigma2, epsilon2; force.getParticleParameters(i, charge1, sigma1, epsilon1); force2.getParticleParameters(i, charge2, sigma2, epsilon2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(epsilon1, epsilon2); } ASSERT_EQUAL(force.getNumExceptions(), force2.getNumExceptions()); for (int i = 0; i < force.getNumExceptions(); i++) { int a1, a2, b1, b2; double charge1, sigma1, epsilon1; double charge2, sigma2, epsilon2; force.getExceptionParameters(i, a1, b1, charge1, sigma1, epsilon1); force2.getExceptionParameters(i, a2, b2, charge2, sigma2, epsilon2); ASSERT_EQUAL(a1, a2); ASSERT_EQUAL(b1, b2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(sigma1, sigma2); ASSERT_EQUAL(epsilon1, epsilon2); } }
void testCutoff14() { System system; VerletIntegrator integrator(0.01); NonbondedForce* nonbonded = new NonbondedForce(); nonbonded->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic); for (int i = 0; i < 5; ++i) { system.addParticle(1.0); nonbonded->addParticle(0, 1.5, 0); } const double cutoff = 3.5; nonbonded->setCutoffDistance(cutoff); const double eps = 30.0; nonbonded->setReactionFieldDielectric(eps); vector<pair<int, int> > bonds; bonds.push_back(pair<int, int>(0, 1)); bonds.push_back(pair<int, int>(1, 2)); bonds.push_back(pair<int, int>(2, 3)); bonds.push_back(pair<int, int>(3, 4)); nonbonded->createExceptionsFromBonds(bonds, 0.0, 0.0); int first14, second14; for (int i = 0; i < nonbonded->getNumExceptions(); i++) { int particle1, particle2; double chargeProd, sigma, epsilon; nonbonded->getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); if ((particle1 == 0 && particle2 == 3) || (particle1 == 3 && particle2 == 0)) first14 = i; if ((particle1 == 1 && particle2 == 4) || (particle1 == 4 && particle2 == 1)) second14 = i; } system.addForce(nonbonded); Context context(system, integrator, platform); vector<Vec3> positions(5); positions[0] = Vec3(0, 0, 0); positions[1] = Vec3(1, 0, 0); positions[2] = Vec3(2, 0, 0); positions[3] = Vec3(3, 0, 0); positions[4] = Vec3(4, 0, 0); for (int i = 1; i < 5; ++i) { // Test LJ forces nonbonded->setParticleParameters(0, 0, 1.5, 1); for (int j = 1; j < 5; ++j) nonbonded->setParticleParameters(j, 0, 1.5, 0); nonbonded->setParticleParameters(i, 0, 1.5, 1); nonbonded->setExceptionParameters(first14, 0, 3, 0, 1.5, i == 3 ? 0.5 : 0.0); nonbonded->setExceptionParameters(second14, 1, 4, 0, 1.5, 0.0); context.reinitialize(); context.setPositions(positions); State state = context.getState(State::Forces | State::Energy); const vector<Vec3>& forces = state.getForces(); double r = positions[i][0]; double x = 1.5/r; double e = 1.0; double force = 4.0*e*(12*std::pow(x, 12.0)-6*std::pow(x, 6.0))/r; double energy = 4.0*e*(std::pow(x, 12.0)-std::pow(x, 6.0)); if (i == 3) { force *= 0.5; energy *= 0.5; } if (i < 3 || r > cutoff) { force = 0; energy = 0; } ASSERT_EQUAL_VEC(Vec3(-force, 0, 0), forces[0], TOL); ASSERT_EQUAL_VEC(Vec3(force, 0, 0), forces[i], TOL); ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL); // Test Coulomb forces const double q = 0.7; nonbonded->setParticleParameters(0, q, 1.5, 0); nonbonded->setParticleParameters(i, q, 1.5, 0); nonbonded->setExceptionParameters(first14, 0, 3, i == 3 ? q*q/1.2 : 0, 1.5, 0); nonbonded->setExceptionParameters(second14, 1, 4, 0, 1.5, 0); context.reinitialize(); context.setPositions(positions); state = context.getState(State::Forces | State::Energy); const vector<Vec3>& forces2 = state.getForces(); force = ONE_4PI_EPS0*q*q/(r*r); energy = ONE_4PI_EPS0*q*q/r; if (i == 3) { force /= 1.2; energy /= 1.2; } if (i < 3 || r > cutoff) { force = 0; energy = 0; } ASSERT_EQUAL_VEC(Vec3(-force, 0, 0), forces2[0], TOL); ASSERT_EQUAL_VEC(Vec3(force, 0, 0), forces2[i], TOL); ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL); } }
void testExclusionsAnd14() { System system; NonbondedForce* nonbonded = new NonbondedForce(); for (int i = 0; i < 5; ++i) { system.addParticle(1.0); nonbonded->addParticle(0, 1.5, 0); } vector<pair<int, int> > bonds; bonds.push_back(pair<int, int>(0, 1)); bonds.push_back(pair<int, int>(1, 2)); bonds.push_back(pair<int, int>(2, 3)); bonds.push_back(pair<int, int>(3, 4)); nonbonded->createExceptionsFromBonds(bonds, 0.0, 0.0); int first14, second14; for (int i = 0; i < nonbonded->getNumExceptions(); i++) { int particle1, particle2; double chargeProd, sigma, epsilon; nonbonded->getExceptionParameters(i, particle1, particle2, chargeProd, sigma, epsilon); if ((particle1 == 0 && particle2 == 3) || (particle1 == 3 && particle2 == 0)) first14 = i; if ((particle1 == 1 && particle2 == 4) || (particle1 == 4 && particle2 == 1)) second14 = i; } system.addForce(nonbonded); VerletIntegrator integrator(0.01); Context context(system, integrator, platform); for (int i = 1; i < 5; ++i) { // Test LJ forces vector<Vec3> positions(5); const double r = 1.0; for (int j = 0; j < 5; ++j) { nonbonded->setParticleParameters(j, 0, 1.5, 0); positions[j] = Vec3(0, j, 0); } nonbonded->setParticleParameters(0, 0, 1.5, 1); nonbonded->setParticleParameters(i, 0, 1.5, 1); nonbonded->setExceptionParameters(first14, 0, 3, 0, 1.5, i == 3 ? 0.5 : 0.0); nonbonded->setExceptionParameters(second14, 1, 4, 0, 1.5, 0.0); positions[i] = Vec3(r, 0, 0); context.reinitialize(); context.setPositions(positions); State state = context.getState(State::Forces | State::Energy); const vector<Vec3>& forces = state.getForces(); double x = 1.5/r; double eps = 1.0; double force = 4.0*eps*(12*std::pow(x, 12.0)-6*std::pow(x, 6.0))/r; double energy = 4.0*eps*(std::pow(x, 12.0)-std::pow(x, 6.0)); if (i == 3) { force *= 0.5; energy *= 0.5; } if (i < 3) { force = 0; energy = 0; } ASSERT_EQUAL_VEC(Vec3(-force, 0, 0), forces[0], TOL); ASSERT_EQUAL_VEC(Vec3(force, 0, 0), forces[i], TOL); ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL); // Test Coulomb forces nonbonded->setParticleParameters(0, 2, 1.5, 0); nonbonded->setParticleParameters(i, 2, 1.5, 0); nonbonded->setExceptionParameters(first14, 0, 3, i == 3 ? 4/1.2 : 0, 1.5, 0); nonbonded->setExceptionParameters(second14, 1, 4, 0, 1.5, 0); context.reinitialize(); context.setPositions(positions); state = context.getState(State::Forces | State::Energy); const vector<Vec3>& forces2 = state.getForces(); force = ONE_4PI_EPS0*4/(r*r); energy = ONE_4PI_EPS0*4/r; if (i == 3) { force /= 1.2; energy /= 1.2; } if (i < 3) { force = 0; energy = 0; } ASSERT_EQUAL_VEC(Vec3(-force, 0, 0), forces2[0], TOL); ASSERT_EQUAL_VEC(Vec3(force, 0, 0), forces2[i], TOL); ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL); } }