Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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();

}