OpenMM::System* AmberParm::createSystem( OpenMM::NonbondedForce::NonbondedMethod nonbondedMethod, double nonbondedCutoff, std::string constraints, bool rigidWater, std::string implicitSolvent, double implicitSolventKappa, double implicitSolventSaltConc, double temperature, double soluteDielectric, double solventDielectric, bool removeCMMotion, double ewaldErrorTolerance, bool flexibleConstraints, bool useSASA) { OpenMM::System* system = new OpenMM::System(); // Make sure we have a legal choice for constraints and implicitSolvent if (constraints != "None" && constraints != "HBonds" && constraints != "AllBonds") { string msg = "constraints must be None, HBonds, or AllBonds; not " + constraints; throw AmberParmError(msg.c_str()); } if (implicitSolvent != "None" && implicitSolvent != "HCT" && implicitSolvent != "OBC1" && implicitSolvent != "OBC2" && implicitSolvent != "GBn" && implicitSolvent != "GBn2") { string msg = "implicitSolvent must be None, HCT, OBC1, OBC2, GBn, or " "GBn2; not " + implicitSolvent; throw AmberParmError(msg.c_str()); } if (rigidWater && (constraints != "HBonds" && constraints != "AllBonds")) { cerr << "rigidWater is incompatible with constraints=None; setting to " << "false" << endl; } // Catch illegal nonbonded choice for system if (isPeriodic()) { if (nonbondedMethod == OpenMM::NonbondedForce::CutoffNonPeriodic || nonbondedMethod == OpenMM::NonbondedForce::NoCutoff) throw AmberParmError("Illegal nonbondedForce choice for periodic system"); } else { if (nonbondedMethod == OpenMM::NonbondedForce::CutoffPeriodic || nonbondedMethod == OpenMM::NonbondedForce::PME || nonbondedMethod == OpenMM::NonbondedForce::Ewald) throw AmberParmError("Illegal nonbondedForce choice for non-periodic system"); } // Add all particles for (atom_iterator it = AtomBegin(); it != AtomEnd(); it++) { system->addParticle(it->getMass()); } // Add constraints bool hcons = constraints == "HBonds" || constraints == "AllBonds"; bool allcons = constraints == "AllBonds"; for (bond_iterator it = BondBegin(); it != BondEnd(); it++) { Atom a1 = atoms_[it->getAtomI()]; Atom a2 = atoms_[it->getAtomJ()]; if (hcons && (a1.getElement() == 1 || a2.getElement() == 1)) { system->addConstraint(it->getAtomI(), it->getAtomJ(), it->getEquilibriumDistance()*NANOMETER_PER_ANGSTROM); } else if (allcons) { system->addConstraint(it->getAtomI(), it->getAtomJ(), it->getEquilibriumDistance()*NANOMETER_PER_ANGSTROM); } } // Add all bonds if (!allcons || flexibleConstraints) { OpenMM::HarmonicBondForce *bond_force = new OpenMM::HarmonicBondForce(); bond_force->setForceGroup(BOND_FORCE_GROUP); double conv = ANGSTROM_PER_NANOMETER*ANGSTROM_PER_NANOMETER*JOULE_PER_CALORIE; for (bond_iterator it=BondBegin(); it != BondEnd(); it++) { // See if this bond needs to be skipped due to constraints Atom a1 = atoms_[it->getAtomI()]; Atom a2 = atoms_[it->getAtomJ()]; if (hcons && (a1.getElement() == 1 || a2.getElement() == 1) && !flexibleConstraints) continue; bond_force->addBond(it->getAtomI(), it->getAtomJ(), it->getEquilibriumDistance()*NANOMETER_PER_ANGSTROM, 2*it->getForceConstant()*conv); } system->addForce(bond_force); } // Add all angles OpenMM::HarmonicAngleForce *angle_force = new OpenMM::HarmonicAngleForce(); angle_force->setForceGroup(ANGLE_FORCE_GROUP); for (angle_iterator it = AngleBegin(); it != AngleEnd(); it++) { angle_force->addAngle(it->getAtomI(), it->getAtomJ(), it->getAtomK(), it->getEquilibriumAngle()*RADIAN_PER_DEGREE, 2*it->getForceConstant()*JOULE_PER_CALORIE); } system->addForce(angle_force); // Add all torsions OpenMM::PeriodicTorsionForce *dihedral_force = new OpenMM::PeriodicTorsionForce(); dihedral_force->setForceGroup(DIHEDRAL_FORCE_GROUP); for (dihedral_iterator it = DihedralBegin(); it != DihedralEnd(); it++) { dihedral_force->addTorsion(it->getAtomI(), it->getAtomJ(), it->getAtomK(), it->getAtomL(), it->getPeriodicity(), it->getPhase()*RADIAN_PER_DEGREE, it->getForceConstant()*JOULE_PER_CALORIE); } system->addForce(dihedral_force); // Add nonbonded force OpenMM::NonbondedForce *nonb_frc = new OpenMM::NonbondedForce(); nonb_frc->setForceGroup(NONBONDED_FORCE_GROUP); nonb_frc->setNonbondedMethod(nonbondedMethod); if (nonbondedMethod != OpenMM::NonbondedForce::NoCutoff) nonb_frc->setCutoffDistance(nonbondedCutoff*NANOMETER_PER_ANGSTROM); const double ONE_SIXTH = 1.0 / 6.0; const double SIGMA_SCALE = pow(2, -ONE_SIXTH) * 2 * NANOMETER_PER_ANGSTROM; for (atom_iterator it = AtomBegin(); it != AtomEnd(); it++) { nonb_frc->addParticle(it->getCharge(), it->getLJRadius()*SIGMA_SCALE, it->getLJEpsilon()*JOULE_PER_CALORIE); } // Now do exceptions const double SIGMA_SCALE2 = pow(2, -ONE_SIXTH) * NANOMETER_PER_ANGSTROM; for (dihedral_iterator it = DihedralBegin(); it != DihedralEnd(); it++) { if (it->ignoreEndGroups()) continue; Atom a1 = atoms_[it->getAtomI()]; Atom a2 = atoms_[it->getAtomL()]; double eps = sqrt(a1.getLJEpsilon() * a2.getLJEpsilon()) * JOULE_PER_CALORIE / it->getScnb(); double sig = (a1.getLJRadius() + a2.getLJRadius()) * SIGMA_SCALE2; nonb_frc->addException(it->getAtomI(), it->getAtomL(), a1.getCharge()*a2.getCharge()/it->getScee(), sig, eps); } // Now do exclusions for (int i = 0; i < atoms_.size(); i++) { if (exclusion_list_[i].size() == 0) continue; // No exclusions here for (set<int>::const_iterator it = exclusion_list_[i].begin(); it != exclusion_list_[i].end(); it++) { nonb_frc->addException(i, *it, 0.0, 1.0, 0.0); } } // Set the ewald error tolerance if (nonbondedMethod == OpenMM::NonbondedForce::PME || nonbondedMethod == OpenMM::NonbondedForce::Ewald) nonb_frc->setEwaldErrorTolerance(ewaldErrorTolerance); system->addForce(nonb_frc); // See about removing the center of mass motion if (removeCMMotion) system->addForce(new OpenMM::CMMotionRemover()); // Add a box if necessary if (isPeriodic()) system->setDefaultPeriodicBoxVectors(unit_cell_.getVectorA()/10, unit_cell_.getVectorB()/10, unit_cell_.getVectorC()/10); // If no implicit solvent, we can return system now if (implicitSolvent == "None") return system; // Otherwise, we need to add the GB force if (implicitSolventKappa <= 0 && implicitSolventSaltConc > 0) implicitSolventKappa = 50.33355 * 0.73 * sqrt(implicitSolventSaltConc/(solventDielectric*temperature)); OpenMM::CustomGBForce *gb_frc = 0; if (implicitSolvent == "HCT") { gb_frc = GB_HCT(*this, solventDielectric, soluteDielectric, useSASA, nonbondedCutoff, implicitSolventKappa); } else if (implicitSolvent == "OBC1") { gb_frc = GB_OBC1(*this, solventDielectric, soluteDielectric, useSASA, nonbondedCutoff, implicitSolventKappa); } else if (implicitSolvent == "OBC2") { gb_frc = GB_OBC2(*this, solventDielectric, soluteDielectric, useSASA, nonbondedCutoff, implicitSolventKappa); } else if (implicitSolvent == "GBn") { gb_frc = GB_GBn(*this, solventDielectric, soluteDielectric, useSASA, nonbondedCutoff, implicitSolventKappa); } else if (implicitSolvent == "GBn2") { gb_frc = GB_GBn2(*this, solventDielectric, soluteDielectric, useSASA, nonbondedCutoff, implicitSolventKappa); } else { stringstream iss; iss << "Should not be here; bad GB model " << implicitSolvent; throw InternalError(iss.str()); } if (nonbondedMethod == OpenMM::NonbondedForce::NoCutoff) gb_frc->setNonbondedMethod(OpenMM::CustomGBForce::NoCutoff); else if (nonbondedMethod == OpenMM::NonbondedForce::CutoffNonPeriodic) gb_frc->setNonbondedMethod(OpenMM::CustomGBForce::CutoffNonPeriodic); else // all remaining options are periodic cutoff... gb_frc->setNonbondedMethod(OpenMM::CustomGBForce::CutoffPeriodic); gb_frc->setForceGroup(NONBONDED_FORCE_GROUP); // Since we're using GB, we need to turn off the reaction field dielectric nonb_frc->setReactionFieldDielectric(1.0); system->addForce(gb_frc); return system; }
TEST(TestControlBerendsenBins,SingleBin){ std::ifstream file("../foam-1728.json"); if(!file.is_open()){ std::cout<<"File not found"<<std::endl; exit(0); } std::string jsonstr; std::string line; while (!file.eof()) { getline(file, line); jsonstr += line; } file.close(); rapidjson::Document document; if(document.Parse<0>(jsonstr.c_str()).HasParseError()){ std::cout<<"Parsing error "<<std::endl; exit(0); } const double stepSizeInFs = document["StepSizeInFs"].GetDouble(); const int numParticles = document["NumberAtoms"].GetInt(); std::string equationStr = document["Equation"].GetString(); const double rCut = document["rCut"].GetDouble(); const rapidjson::Value& b = document["Boxsize"]; double bx = b[(rapidjson::SizeType)0].GetDouble(); double by = b[(rapidjson::SizeType)1].GetDouble(); double bz = b[(rapidjson::SizeType)2].GetDouble(); int numSpecies = document["NumberSpecies"].GetInt(); std::vector<OpenMM::Vec3> posInNm; std::vector<OpenMM::Vec3> velInNm; OpenMM::Platform::loadPluginsFromDirectory( OpenMM::Platform::getDefaultPluginsDirectory()); OpenMM::System system; //add particles to the system by reading from json file system.setDefaultPeriodicBoxVectors(OpenMM::Vec3(bx,0,0),OpenMM::Vec3(0,by,0),OpenMM::Vec3(0,0,bz)); const rapidjson::Value& mass = document["masses"]; const rapidjson::Value& pos = document["Positions"]; const rapidjson::Value& vel = document["Velocities"]; posInNm.clear(); velInNm.clear(); for(rapidjson::SizeType m=0;m<mass.Size();m++){ double tm = mass[(rapidjson::SizeType) m].GetDouble(); system.addParticle(tm); posInNm.push_back(OpenMM::Vec3(pos[(rapidjson::SizeType) m]["0"].GetDouble(), pos[(rapidjson::SizeType) m]["1"].GetDouble(), pos[(rapidjson::SizeType) m]["2"].GetDouble() )); velInNm.push_back(OpenMM::Vec3(vel[(rapidjson::SizeType) m]["0"].GetDouble(), vel[(rapidjson::SizeType) m]["1"].GetDouble(), vel[(rapidjson::SizeType) m]["2"].GetDouble() )); } std::cout<<"Initialized System with "<<system.getNumParticles()<<" Particles."<<std::endl; OpenMM::CustomNonbondedForce* nonbonded = new OpenMM::CustomNonbondedForce(equationStr); nonbonded->setNonbondedMethod(OpenMM::CustomNonbondedForce::CutoffPeriodic); nonbonded->setCutoffDistance(rCut);// * OpenMM::NmPerAngstrom nonbonded->addPerParticleParameter("Ar");//later on collect it from json string based on OF for(int p=0;p<numParticles;p++){ std::vector<double> params(numSpecies); params[0] = (double) 1; nonbonded->addParticle(params); } system.addForce(nonbonded); std::vector<std::string> ctools(1); ctools[0] = "ControlBerendsenInBins"; OpenMM::Vec3 startPoint = OpenMM::Vec3((10*0.34),(0*0.34),(10*0.34)); OpenMM::Vec3 endPoint = OpenMM::Vec3((10*0.34),(20*0.34),(10*0.34)); OpenMM::ControlTools controls(ctools,(double)292,0.001, startPoint,endPoint); int num_plat = OpenMM::Platform::getNumPlatforms(); std::cout<<"Number of registered platforms: "<< num_plat <<std::endl; for(int i=0;i<num_plat;i++) { OpenMM::Platform& tempPlatform = OpenMM::Platform::getPlatform(i); std::string tempPlatformName = tempPlatform.getName(); std::cout<<"Platform "<<(i+1)<<" is "<<tempPlatformName.c_str()<<std::endl; } OpenMM::Platform& platform = OpenMM::Platform::getPlatformByName("OpenCL"); OpenMM::VelocityVerletIntegrator integrator(stepSizeInFs * OpenMM::PsPerFs); OpenMM::Context context(system,integrator,platform,controls); string Platformname = context.getPlatform().getName(); std::cout<<"Using OpenMM "<<Platformname.c_str()<<" Platform"<<std::endl; context.setPositions(posInNm); context.setVelocities(velInNm); int nbs = context.getControls().getNBins(); printf("Using %d bins for the system\n",nbs); //start the simulation loop integrator.step(1); printf("Finished initial integration\n"); int counter=0; std::cout<<"starting the loop\n"; for(int frame=1;frame<400;++frame){ // OpenMM::State state = context.getState(OpenMM::State::Velocities); // const double time = state.getTime(); double* mola = context.getControls().getBinTemperature(); // OpenMM::Vec3* tv = context.getControls().getTestVariable(); double gpuMol = 0.0; for(int k=0;k<nbs;k++){ gpuMol += mola[k]; } EXPECT_EQ((double) numParticles,gpuMol); integrator.step(1); } std::cout<<"Simulation completed with counter value "<<counter<<std::endl; }
void simulate(json &molinfo) { // Load any shared libraries containing GPU implementations. OpenMM::Platform::loadPluginsFromDirectory( OpenMM::Platform::getDefaultPluginsDirectory()); // force to use CPU platform that is better than CUDA in my simulation scale OpenMM::Platform& platform = OpenMM::Platform::getPlatformByName("CPU"); // force to use single thread platform.setPropertyDefaultValue("Threads", "1"); // Create a system with forces. OpenMM::System system; const int N_particles = molinfo["resSeq"].size(); std::cout << "# Number of Particles : " << N_particles << '\n'; // set MD paramters const double Temperature = molinfo["parameters"]["Temperature"]; const int SimulationSteps = molinfo["parameters"]["SimulationSteps"]; const double TimePerStepInPs = molinfo["parameters"]["TimePerStepInPs"]; const int NStepSave = molinfo["parameters"]["NStepSave"]; const int RandomSeed = molinfo["parameters"]["RandomSeed"]; // set other parameters const std::string filename = molinfo["output"]["filename"]; // Create Atoms std::vector<OpenMM::Vec3> initPosInNm(N_particles); // map from resSeq to particle index(0..N-1) for (int i=0; i<N_particles; ++i) { int resSeq = molinfo["resSeq"][i]; rs2pi.insert(std::pair<int,int>(resSeq, i)); } double x, y, z; for (int i=0; i<N_particles; ++i) { x = molinfo["position"][i]["position"][0]; y = molinfo["position"][i]["position"][1]; z = molinfo["position"][i]["position"][2]; initPosInNm[i] = OpenMM::Vec3(x, y, z) * OpenMM::NmPerAngstrom; system.addParticle(137.0); // average mass of amino acid residues } // add non-local repulsive force // This pair potential is excluded from bonded pairs OpenMM::CustomNonbondedForce& nonlocalRepulsion = *new OpenMM::CustomNonbondedForce("epsilon_repul*(d_exclusive/r)^12"); system.addForce(&nonlocalRepulsion); nonlocalRepulsion.setNonbondedMethod(OpenMM::CustomNonbondedForce::NonbondedMethod::CutoffNonPeriodic); nonlocalRepulsion.setCutoffDistance(D_ExclusionCutoffInNm); nonlocalRepulsion.addGlobalParameter("d_exclusive", D_ExclusiveInNm); nonlocalRepulsion.addGlobalParameter("epsilon_repul", E_ExclusionPair); for (int i=0; i<N_particles; ++i) { nonlocalRepulsion.addParticle(); } // add non-local Go contact for native contact pairs OpenMM::CustomBondForce& goContactForce = *new OpenMM::CustomBondForce("epsilon_ngo*(5*(r_native/r)^12 - 6*(r_native/r)^10)"); system.addForce(&goContactForce); goContactForce.addGlobalParameter("epsilon_ngo", E_GoContactPair); goContactForce.addPerBondParameter("r_native"); for (int i=0; i<molinfo["contact"].size(); ++i) { int p1 = rs2pi[molinfo["contact"][i]["resSeq"][0]]; int p2 = rs2pi[molinfo["contact"][i]["resSeq"][1]]; double r_native = molinfo["contact"][i]["length"]; std::vector<double> perBondParams = {r_native * OpenMM::NmPerAngstrom}; goContactForce.addBond(p1, p2, perBondParams); nonlocalRepulsion.addExclusion(p1, p2); } // add bonding force or constraints between two particles OpenMM::HarmonicBondForce& bondStretch = *new OpenMM::HarmonicBondForce(); system.addForce(&bondStretch); for (int i=0; i<molinfo["bond"].size(); ++i) { int p1 = rs2pi[molinfo["bond"][i]["resSeq"][0]]; int p2 = rs2pi[molinfo["bond"][i]["resSeq"][1]]; double length = molinfo["bond"][i]["length"]; if (UseConstraints) { system.addConstraint(p1, p2, length * OpenMM::NmPerAngstrom); } else { bondStretch.addBond(p1, p2, length * OpenMM::NmPerAngstrom, K_BondStretch); } nonlocalRepulsion.addExclusion(p1, p2); } // add angle force OpenMM::HarmonicAngleForce& bondBend = *new OpenMM::HarmonicAngleForce(); system.addForce(&bondBend); for (int i=0; i<molinfo["angle"].size(); ++i) { int p1 = rs2pi[molinfo["angle"][i]["resSeq"][0]]; int p2 = rs2pi[molinfo["angle"][i]["resSeq"][1]]; int p3 = rs2pi[molinfo["angle"][i]["resSeq"][2]]; double angle = molinfo["angle"][i]["angle"]; bondBend.addAngle(p1, p2, p3, angle * OpenMM::RadiansPerDegree, K_BondAngle); nonlocalRepulsion.addExclusion(p1, p3); } // add dihedral force OpenMM::PeriodicTorsionForce& bondTorsion = *new OpenMM::PeriodicTorsionForce(); system.addForce(&bondTorsion); for (int i=0; i<molinfo["dihedral"].size(); ++i) { int p1 = rs2pi[molinfo["dihedral"][i]["resSeq"][0]]; int p2 = rs2pi[molinfo["dihedral"][i]["resSeq"][1]]; int p3 = rs2pi[molinfo["dihedral"][i]["resSeq"][2]]; int p4 = rs2pi[molinfo["dihedral"][i]["resSeq"][3]]; double dihedral = molinfo["dihedral"][i]["dihedral"]; bondTorsion.addTorsion(p1, p2, p3, p4, 1, (dihedral+180.0) * OpenMM::RadiansPerDegree, K_BondTorsion1); bondTorsion.addTorsion(p1, p2, p3, p4, 3, (dihedral+180.0) * OpenMM::RadiansPerDegree, K_BondTorsion3); nonlocalRepulsion.addExclusion(p1, p4); } // set langevin integrator OpenMM::LangevinIntegrator integrator(Temperature, LangevinFrictionPerPs, TimePerStepInPs); integrator.setRandomNumberSeed(RandomSeed); // Let OpenMM Context choose best platform OpenMM::Context context(system, integrator, platform); std::cout << "# Using OpenMM Platform: "; std::cout << context.getPlatform().getName().c_str() << std::endl; // Set starting positions of the atoms. Leave time and velocity zero. context.setPositions(initPosInNm); // set initial velocity context.setVelocitiesToTemperature(Temperature, RandomSeed); // set output files std::ofstream opdb, ots; opdb.open(filename + ".pdb", std::ios::out); ots.open(filename + ".ts", std::ios::out); std::cout << "# PDB: " << filename + ".pdb\n"; std::cout << "# TimeSereis: " << filename + ".ts\n"; int infoMask = 0; infoMask = OpenMM::State::Positions; infoMask += OpenMM::State::Energy; for (int frameNum = 0;; ++frameNum) { // Output current state information OpenMM::State state = context.getState(infoMask); int steps = frameNum * NStepSave; double qscore = getQscore(state, molinfo); // write PDB frame writePDBFrame(frameNum, state, molinfo, opdb); writeTimeSeries(steps, state, ots, qscore); // show progress in stdout if (SilentMode == false) { std::cout << '\r'; std::cout << "Q=" << std::setw(5) << std::setprecision(3) << qscore; std::cout << "; T=" << std::setw(5) << integrator.getTemperature(); std::cout << "; E=" << std::setw(5) << state.getPotentialEnergy(); std::cout << std::setw(8) << steps << " steps / "; std::cout << std::setw(8) << SimulationSteps << std::flush; } if (frameNum * NStepSave >= SimulationSteps) break; integrator.step(NStepSave); } std::cout << std::endl; opdb.close(); ots.close(); }