void testSingleParticle() { ReferencePlatform platform; System system; system.addParticle(2.0); LangevinIntegrator integrator(0, 0.1, 0.01); GBVIForce* forceField = new GBVIForce(); double charge = -1.0; double radius = 0.15; double gamma = 1.0; forceField->addParticle(charge, radius, gamma); system.addForce(forceField); ASSERT(!forceField->usesPeriodicBoundaryConditions()); ASSERT(!system.usesPeriodicBoundaryConditions()); Context context(system, integrator, platform); vector<Vec3> positions(1); positions[0] = Vec3(0, 0, 0); context.setPositions(positions); State state = context.getState(State::Energy); double bornRadius = radius; double eps0 = EPSILON0; double tau = (1.0/forceField->getSoluteDielectric()-1.0/forceField->getSolventDielectric()); double bornEnergy = (-charge*charge/(8*PI_M*eps0))*tau/bornRadius; double nonpolarEnergy = -gamma*tau*std::pow(radius/bornRadius, 3.0); double expectedE = (bornEnergy+nonpolarEnergy); double obtainedE = state.getPotentialEnergy(); double diff = fabs((obtainedE - expectedE)/expectedE); ASSERT_EQUAL_TOL((bornEnergy+nonpolarEnergy), state.getPotentialEnergy(), 0.01); }
void ValidateOpenMM::writeGBVIForce( FILE* filePtr, const GBVIForce& gbviForce ) const { (void) fprintf( filePtr, "GBVIForce %d\n", gbviForce.getNumParticles() ); for(int ii = 0; ii < gbviForce.getNumParticles(); ii++ ){ double charge, radius, gamma; gbviForce.getParticleParameters( ii, charge, radius, gamma ); (void) fprintf( filePtr, "%8d %14.7e %14.7e %14.7e\n", ii, charge, radius, gamma ); } (void) fprintf( filePtr, "GBVIBonds %d\n", gbviForce.getNumBonds() ); for(int ii = 0; ii < gbviForce.getNumBonds(); ii++ ){ int atomI, atomJ; double bondLength; gbviForce.getBondParameters( ii, atomI, atomJ, bondLength ); (void) fprintf( filePtr, "%8d %8d %8d %14.7e\n", ii, atomI, atomJ, bondLength ); } (void) fprintf( filePtr, "SoluteDielectric %14.7e\n", gbviForce.getSoluteDielectric() ); (void) fprintf( filePtr, "SolventDielectric %14.7e\n", gbviForce.getSolventDielectric() ); }
void testEnergyEthane(int applyBornRadiiScaling) { ReferencePlatform platform; const int numParticles = 8; System system; LangevinIntegrator integrator(0, 0.1, 0.01); // harmonic bond double C_HBondDistance = 0.1097; double C_CBondDistance = 0.1504; HarmonicBondForce* bonds = new HarmonicBondForce(); bonds->addBond(0, 1, C_HBondDistance, 0.0); bonds->addBond(2, 1, C_HBondDistance, 0.0); bonds->addBond(3, 1, C_HBondDistance, 0.0); bonds->addBond(1, 4, C_CBondDistance, 0.0); bonds->addBond(5, 4, C_HBondDistance, 0.0); bonds->addBond(6, 4, C_HBondDistance, 0.0); bonds->addBond(7, 4, C_HBondDistance, 0.0); system.addForce(bonds); double C_radius, C_gamma, C_charge, H_radius, H_gamma, H_charge; int AM1_BCC = 1; H_charge = -0.053; C_charge = -3.0*H_charge; if (AM1_BCC) { C_radius = 0.180; C_gamma = -0.2863; H_radius = 0.125; H_gamma = 0.2437; } else { C_radius = 0.215; C_gamma = -1.1087; H_radius = 0.150; H_gamma = 0.1237; } NonbondedForce* nonbonded = new NonbondedForce(); nonbonded->setNonbondedMethod(NonbondedForce::NoCutoff); GBVIForce* forceField = new GBVIForce(); if (applyBornRadiiScaling) { forceField->setBornRadiusScalingMethod(GBVIForce::QuinticSpline); } else { forceField->setBornRadiusScalingMethod(GBVIForce::NoScaling); } for (int i = 0; i < numParticles; i++) { system.addParticle(1.0); forceField->addParticle(H_charge, H_radius, H_gamma); nonbonded->addParticle( H_charge, H_radius, 0.0); } forceField->setParticleParameters(1, C_charge, C_radius, C_gamma); forceField->setParticleParameters(4, C_charge, C_radius, C_gamma); nonbonded->setParticleParameters( 1, C_charge, C_radius, 0.0); nonbonded->setParticleParameters( 4, C_charge, C_radius, 0.0); forceField->addBond(0, 1, C_HBondDistance); forceField->addBond(2, 1, C_HBondDistance); forceField->addBond(3, 1, C_HBondDistance); forceField->addBond(1, 4, C_CBondDistance); forceField->addBond(5, 4, C_HBondDistance); forceField->addBond(6, 4, C_HBondDistance); forceField->addBond(7, 4, C_HBondDistance); std::vector<pair<int, int> > bondExceptions; std::vector<double> bondDistances; bondExceptions.push_back(pair<int, int>(0, 1)); bondDistances.push_back(C_HBondDistance); bondExceptions.push_back(pair<int, int>(2, 1)); bondDistances.push_back(C_HBondDistance); bondExceptions.push_back(pair<int, int>(3, 1)); bondDistances.push_back(C_HBondDistance); bondExceptions.push_back(pair<int, int>(1, 4)); bondDistances.push_back(C_CBondDistance); bondExceptions.push_back(pair<int, int>(5, 4)); bondDistances.push_back(C_HBondDistance); bondExceptions.push_back(pair<int, int>(6, 4)); bondDistances.push_back(C_HBondDistance); bondExceptions.push_back(pair<int, int>(7, 4)); bondDistances.push_back(C_HBondDistance); nonbonded->createExceptionsFromBonds(bondExceptions, 0.0, 0.0); system.addForce(forceField); system.addForce(nonbonded); Context context(system, integrator, platform); vector<Vec3> positions(numParticles); positions[0] = Vec3(0.5480, 1.7661, 0.0000); positions[1] = Vec3(0.7286, 0.8978, 0.6468); positions[2] = Vec3(0.4974, 0.0000, 0.0588); positions[3] = Vec3(0.0000, 0.9459, 1.4666); positions[4] = Vec3(2.1421, 0.8746, 1.1615); positions[5] = Vec3(2.3239, 0.0050, 1.8065); positions[6] = Vec3(2.8705, 0.8295, 0.3416); positions[7] = Vec3(2.3722, 1.7711, 1.7518); context.setPositions(positions); State state = context.getState(State::Forces | State::Energy); // Take a small step in the direction of the energy gradient. double norm = 0.0; double forceSum[3] = { 0.0, 0.0, 0.0 }; for (int i = 0; i < numParticles; ++i) { Vec3 f = state.getForces()[i]; norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2]; forceSum[0] += f[0]; forceSum[1] += f[1]; forceSum[2] += f[2]; } norm = std::sqrt(norm); const double delta = 1e-4; double step = delta/norm; for (int i = 0; i < numParticles; ++i) { Vec3 p = positions[i]; Vec3 f = state.getForces()[i]; positions[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step); } context.setPositions(positions); State state2 = context.getState(State::Energy); // See whether the potential energy changed by the expected amount. ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01) }
void testGBVI(GBVIForce::NonbondedMethod gbviMethod, CustomGBForce::NonbondedMethod customGbviMethod, std::string molecule) { const int numMolecules = 1; const double boxSize = 10.0; ReferencePlatform platform; GBVIForce* gbvi = new GBVIForce(); std::vector<Vec3> positions; // select molecule if( molecule == "Monomer" ){ buildMonomer( gbvi, positions ); } else if( molecule == "Dimer" ){ buildDimer( gbvi, positions ); } else { buildEthane( gbvi, positions ); } int numParticles = gbvi->getNumParticles(); System standardSystem; System customGbviSystem; for (int i = 0; i < numParticles; i++) { standardSystem.addParticle(1.0); customGbviSystem.addParticle(1.0); } standardSystem.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0.0, 0.0), Vec3(0.0, boxSize, 0.0), Vec3(0.0, 0.0, boxSize)); customGbviSystem.setDefaultPeriodicBoxVectors(Vec3(boxSize, 0.0, 0.0), Vec3(0.0, boxSize, 0.0), Vec3(0.0, 0.0, boxSize)); gbvi->setCutoffDistance(2.0); // create customGbviForce GBVI force CustomGBForce* customGbviForce = createCustomGBVI( gbvi->getSolventDielectric(), gbvi->getSoluteDielectric() ); customGbviForce->setCutoffDistance(2.0); // load parameters from gbvi to customGbviForce loadGbviParameters( gbvi, customGbviForce ); OpenMM_SFMT::SFMT sfmt; init_gen_rand(0, sfmt); vector<Vec3> velocities(numParticles); for (int ii = 0; ii < numParticles; ii++) { velocities[ii] = Vec3(genrand_real2(sfmt), genrand_real2(sfmt), genrand_real2(sfmt)); } gbvi->setNonbondedMethod(gbviMethod); customGbviForce->setNonbondedMethod(customGbviMethod); standardSystem.addForce(gbvi); customGbviSystem.addForce(customGbviForce); VerletIntegrator integrator1(0.01); VerletIntegrator integrator2(0.01); Context context1(standardSystem, integrator1, platform); context1.setPositions(positions); context1.setVelocities(velocities); State state1 = context1.getState(State::Forces | State::Energy); Context context2(customGbviSystem, integrator2, platform); context2.setPositions(positions); context2.setVelocities(velocities); State state2 = context2.getState(State::Forces | State::Energy); ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-4); for (int i = 0; i < numParticles; i++) { ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-4); } }
static void findScaledRadii( GBVIForce& gbviForce, std::vector<double> & scaledRadii) { int numberOfParticles = gbviForce.getNumParticles(); int numberOfBonds = gbviForce.getNumBonds(); // load 1-2 atom pairs along w/ bond distance using HarmonicBondForce & constraints // numberOfBonds < 1, indicating they were not set by the user if( numberOfBonds < 1 && numberOfParticles > 1 ){ (void) fprintf( stderr, "Warning: no covalent bonds set for GB/VI force!\n" ); } std::vector< std::vector<int> > bondIndices; bondIndices.resize( numberOfBonds ); std::vector<double> bondLengths; bondLengths.resize( numberOfBonds ); scaledRadii.resize(numberOfParticles); for (int i = 0; i < numberOfParticles; i++) { double charge, radius, gamma; gbviForce.getParticleParameters(i, charge, radius, gamma); scaledRadii[i] = radius; } for (int i = 0; i < numberOfBonds; i++) { int particle1, particle2; double bondLength; gbviForce.getBondParameters(i, particle1, particle2, bondLength); if (particle1 < 0 || particle1 >= gbviForce.getNumParticles()) { std::stringstream msg; msg << "GBVISoftcoreForce: Illegal particle index: "; msg << particle1; throw OpenMMException(msg.str()); } if (particle2 < 0 || particle2 >= gbviForce.getNumParticles()) { std::stringstream msg; msg << "GBVISoftcoreForce: Illegal particle index: "; msg << particle2; throw OpenMMException(msg.str()); } if (bondLength < 0 ) { std::stringstream msg; msg << "GBVISoftcoreForce: negative bondlength: "; msg << bondLength; throw OpenMMException(msg.str()); } bondIndices[i].push_back( particle1 ); bondIndices[i].push_back( particle2 ); bondLengths[i] = bondLength; } // load 1-2 indicies for each atom std::vector<std::vector<int> > bonded12(numberOfParticles); for (int i = 0; i < (int) bondIndices.size(); ++i) { bonded12[bondIndices[i][0]].push_back(i); bonded12[bondIndices[i][1]].push_back(i); } int errors = 0; // compute scaled radii (Eq. 5 of Labute paper [JCC 29 p. 1693-1698 2008]) for (int j = 0; j < (int) bonded12.size(); ++j){ double charge; double gamma; double radiusJ; double scaledRadiusJ; gbviForce.getParticleParameters(j, charge, radiusJ, gamma); if( bonded12[j].size() == 0 ){ if( numberOfParticles > 1 ){ (void) fprintf( stderr, "Warning GBVIForceImpl::findScaledRadii atom %d has no covalent bonds; using atomic radius=%.3f.\n", j, radiusJ ); } scaledRadiusJ = radiusJ; // errors++; } else { double rJ2 = radiusJ*radiusJ; // loop over bonded neighbors of atom j, applying Eq. 5 in Labute scaledRadiusJ = 0.0; for (int i = 0; i < (int) bonded12[j].size(); ++i){ int index = bonded12[j][i]; int bondedAtomIndex = (j == bondIndices[index][0]) ? bondIndices[index][1] : bondIndices[index][0]; double radiusI; gbviForce.getParticleParameters(bondedAtomIndex, charge, radiusI, gamma); double rI2 = radiusI*radiusI; double a_ij = (radiusI - bondLengths[index]); a_ij *= a_ij; a_ij = (rJ2 - a_ij)/(2.0*bondLengths[index]); double a_ji = radiusJ - bondLengths[index]; a_ji *= a_ji; a_ji = (rI2 - a_ji)/(2.0*bondLengths[index]); scaledRadiusJ += a_ij*a_ij*(3.0*radiusI - a_ij) + a_ji*a_ji*( 3.0*radiusJ - a_ji ); } scaledRadiusJ = (radiusJ*radiusJ*radiusJ) - 0.125*scaledRadiusJ; if( scaledRadiusJ > 0.0 ){ scaledRadiusJ = 0.95*pow( scaledRadiusJ, (1.0/3.0) ); } else { scaledRadiusJ = 0.0; } } //(void) fprintf( stderr, "scaledRadii %d %12.4f\n", j, scaledRadiusJ ); scaledRadii[j] = scaledRadiusJ; } // abort if errors if( errors ){ throw OpenMMException("GBVIForceImpl::findScaledRadii errors -- aborting"); } #if GBVIDebug (void) fprintf( stderr, " R q gamma scaled radii no. bnds\n" ); double totalQ = 0.0; for( int i = 0; i < (int) scaledRadii.size(); i++ ){ double charge; double gamma; double radiusI; gbviForce.getParticleParameters(i, charge, radiusI, gamma); totalQ += charge; (void) fprintf( stderr, "%4d %14.5e %14.5e %14.5e %14.5e %d\n", i, radiusI, charge, gamma, scaledRadii[i], (int) bonded12[i].size() ); } (void) fprintf( stderr, "Total charge=%e\n", totalQ ); (void) fflush( stderr ); #endif #undef GBVIDebug }
void testSerialization() { // Create a Force. GBVIForce force; force.setNonbondedMethod(GBVIForce::CutoffPeriodic); force.setBornRadiusScalingMethod(GBVIForce::QuinticSpline); force.setQuinticLowerLimitFactor(0.123); force.setQuinticUpperBornRadiusLimit(5.123); force.setCutoffDistance(2.0); force.setSoluteDielectric(5.1); force.setSolventDielectric(50.0); force.addParticle(1, 0.1, 0.01); force.addParticle(0.5, 0.2, 0.02); force.addParticle(-0.5, 0.3, 0.03); force.addBond(0, 1, 2.0); force.addBond(3, 5, 1.2); // Serialize and then deserialize it. stringstream buffer; XmlSerializer::serialize<GBVIForce>(&force, "Force", buffer); GBVIForce* copy = XmlSerializer::deserialize<GBVIForce>(buffer); // Compare the two forces to see if they are identical. GBVIForce& force2 = *copy; ASSERT_EQUAL(force.getNonbondedMethod(), force2.getNonbondedMethod()); ASSERT_EQUAL(force.getCutoffDistance(), force2.getCutoffDistance()); ASSERT_EQUAL(force.getSoluteDielectric(), force2.getSoluteDielectric()); ASSERT_EQUAL(force.getSolventDielectric(), force2.getSolventDielectric()); ASSERT_EQUAL(force.getNumParticles(), force2.getNumParticles()); ASSERT_EQUAL(force.getQuinticUpperBornRadiusLimit(), force2.getQuinticUpperBornRadiusLimit()); ASSERT_EQUAL(force.getQuinticLowerLimitFactor(), force2.getQuinticLowerLimitFactor()); ASSERT_EQUAL(force.getBornRadiusScalingMethod(), force2.getBornRadiusScalingMethod()); for (int i = 0; i < force.getNumParticles(); i++) { double charge1, radius1, scale1; double charge2, radius2, scale2; force.getParticleParameters(i, charge1, radius1, scale1); force2.getParticleParameters(i, charge2, radius2, scale2); ASSERT_EQUAL(charge1, charge2); ASSERT_EQUAL(radius1, radius2); ASSERT_EQUAL(scale1, scale2); } ASSERT_EQUAL(force.getNumBonds(), force2.getNumBonds()); for (int i = 0; i < force.getNumBonds(); i++) { int a1, a2, b1, b2; double da, db; force.getBondParameters(i, a1, a2, da); force2.getBondParameters(i, b1, b2, db); ASSERT_EQUAL(a1, b1); ASSERT_EQUAL(a2, b2); ASSERT_EQUAL(da, db); } }