void testCutoff() { System system; system.addParticle(1.0); system.addParticle(1.0); system.addParticle(1.0); VerletIntegrator integrator(0.01); NonbondedForce* forceField = new NonbondedForce(); forceField->addParticle(1.0, 1, 0); forceField->addParticle(1.0, 1, 0); forceField->addParticle(1.0, 1, 0); forceField->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic); const double cutoff = 2.9; forceField->setCutoffDistance(cutoff); const double eps = 50.0; forceField->setReactionFieldDielectric(eps); system.addForce(forceField); Context context(system, integrator, platform); vector<Vec3> positions(3); positions[0] = Vec3(0, 0, 0); positions[1] = Vec3(0, 2, 0); positions[2] = Vec3(0, 3, 0); context.setPositions(positions); State state = context.getState(State::Forces | State::Energy); const vector<Vec3>& forces = state.getForces(); const double krf = (1.0/(cutoff*cutoff*cutoff))*(eps-1.0)/(2.0*eps+1.0); const double crf = (1.0/cutoff)*(3.0*eps)/(2.0*eps+1.0); const double force1 = ONE_4PI_EPS0*(1.0)*(0.25-2.0*krf*2.0); const double force2 = ONE_4PI_EPS0*(1.0)*(1.0-2.0*krf*1.0); ASSERT_EQUAL_VEC(Vec3(0, -force1, 0), forces[0], TOL); ASSERT_EQUAL_VEC(Vec3(0, force1-force2, 0), forces[1], TOL); ASSERT_EQUAL_VEC(Vec3(0, force2, 0), forces[2], TOL); const double energy1 = ONE_4PI_EPS0*(1.0)*(0.5+krf*4.0-crf); const double energy2 = ONE_4PI_EPS0*(1.0)*(1.0+krf*1.0-crf); ASSERT_EQUAL_TOL(energy1+energy2, state.getPotentialEnergy(), TOL); }
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 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 test_water2_dpme_energies_forces_no_exclusions() { const double cutoff = 7.0*OpenMM::NmPerAngstrom; const double dalpha = 4.0124063605; const int grid = 32; NonbondedForce* forceField = new NonbondedForce(); vector<Vec3> positions; vector<double> epsvals; vector<double> sigvals; vector<pair<int, int> > bonds; System system; const int NATOMS = 6; double boxEdgeLength = 25*OpenMM::NmPerAngstrom; make_waterbox(NATOMS, boxEdgeLength, forceField, positions, epsvals, sigvals, bonds, system, false); forceField->setNonbondedMethod(OpenMM::NonbondedForce::LJPME); forceField->setPMEParameters(0.0f, grid, grid, grid); forceField->setReciprocalSpaceForceGroup(1); forceField->setLJPMEParameters(dalpha, grid, grid, grid); forceField->setCutoffDistance(cutoff); forceField->setReactionFieldDielectric(1.0); system.addForce(forceField); // Reference calculation VerletIntegrator integrator(0.01); Platform& platform = Platform::getPlatformByName("Reference"); Context context(system, integrator, platform); context.setPositions(positions); State state = context.getState(State::Forces | State::Energy, false, 1<<1); double refenergy = state.getPotentialEnergy(); const vector<Vec3>& refforces = state.getForces(); // Optimized CPU calculation CpuCalcDispersionPmeReciprocalForceKernel pme(CalcPmeReciprocalForceKernel::Name(), platform); IO io; double selfEwaldEnergy = 0; double dalpha6 = pow(dalpha, 6.0); for (int i = 0; i < NATOMS; i++) { io.posq.push_back((float)positions[i][0]); io.posq.push_back((float)positions[i][1]); io.posq.push_back((float)positions[i][2]); double c6 = 8.0f * pow(sigvals[i], 3) * epsvals[i]; io.posq.push_back(c6); selfEwaldEnergy += dalpha6 * c6 * c6 / 12.0; } pme.initialize(grid, grid, grid, NATOMS, dalpha, false); Vec3 boxVectors[3]; system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]); pme.beginComputation(io, boxVectors, true); double recenergy = pme.finishComputation(io); ASSERT_EQUAL_TOL(recenergy, -2.179629087, 5e-3); ASSERT_EQUAL_TOL(selfEwaldEnergy, 1.731404285, 1e-5); std::vector<Vec3> knownforces(6); knownforces[0] = Vec3( -1.890360546, -1.890723915, -1.879662698); knownforces[1] = Vec3( -0.003161352455, -0.000922244929, -0.005391616425); knownforces[2] = Vec3( 0.0009199035545, -0.001453894176, -0.006188087146); knownforces[3] = Vec3( 1.887108856, 1.887241446, 1.89644647); knownforces[4] = Vec3( 0.0008242336483, 0.003778910089, -0.002116131106); knownforces[5] = Vec3( 0.004912763044, 0.002324059399, -0.002844482646); for (int i = 0; i < NATOMS; i++) ASSERT_EQUAL_VEC(refforces[i], knownforces[i], 5e-3); recenergy += selfEwaldEnergy; // See if they match. ASSERT_EQUAL_TOL(refenergy, recenergy, 1e-3); for (int i = 0; i < NATOMS; i++) ASSERT_EQUAL_VEC(refforces[i], Vec3(io.force[4*i], io.force[4*i+1], io.force[4*i+2]), 5e-3); }
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); } }