예제 #1
0
int ReferenceLincsAlgorithm::apply( int numberOfAtoms, vector<RealVec>& atomCoordinates,
                                         vector<RealVec>& atomCoordinatesP,
                                         vector<RealOpenMM>& inverseMasses ){

   // ---------------------------------------------------------------------------------------

   static const char* methodName = "\nReferenceLincsAlgorithm::apply";

   static const RealOpenMM zero        =  0.0;
   static const RealOpenMM one         =  1.0;
   static const RealOpenMM two         =  2.0;

   // ---------------------------------------------------------------------------------------

   if (_numberOfConstraints == 0)
       return SimTKOpenMMCommon::DefaultReturn;

   if( !_hasInitialized )
       initialize(numberOfAtoms, inverseMasses);

   // Calculate the direction of each constraint, along with the initial RHS and solution vectors.

   for (int i = 0; i < _numberOfConstraints; i++) {
       int atom1 = _atomIndices[i][0];
       int atom2 = _atomIndices[i][1];
       _constraintDir[i] = RealVec(atomCoordinatesP[atom1][0]-atomCoordinatesP[atom2][0],
                                atomCoordinatesP[atom1][1]-atomCoordinatesP[atom2][1],
                                atomCoordinatesP[atom1][2]-atomCoordinatesP[atom2][2]);
       RealOpenMM invLength = (RealOpenMM)(1/SQRT((RealOpenMM)_constraintDir[i].dot(_constraintDir[i])));
       _constraintDir[i][0] *= invLength;
       _constraintDir[i][1] *= invLength;
       _constraintDir[i][2] *= invLength;
       _rhs1[i] = _solution[i] = _sMatrix[i]*(one/invLength-_distance[i]);
   }

   // Build the coupling matrix.

   for (int c1 = 0; c1 < (int)_couplingMatrix.size(); c1++) {
       RealVec& dir1 = _constraintDir[c1];
       for (int j = 0; j < (int)_couplingMatrix[c1].size(); j++) {
           int c2 = _linkedConstraints[c1][j];
           RealVec& dir2 = _constraintDir[c2];
           if (_atomIndices[c1][0] == _atomIndices[c2][0] || _atomIndices[c1][1] == _atomIndices[c2][1])
               _couplingMatrix[c1][j] = (RealOpenMM)(-inverseMasses[_atomIndices[c1][0]]*_sMatrix[c1]*dir1.dot(dir2)*_sMatrix[c2]);
           else
               _couplingMatrix[c1][j] = (RealOpenMM)(inverseMasses[_atomIndices[c1][1]]*_sMatrix[c1]*dir1.dot(dir2)*_sMatrix[c2]);
       }
   }

   // Solve the matrix equation and update the positions.

   solveMatrix();
   updateAtomPositions(numberOfAtoms, atomCoordinatesP, inverseMasses);

   // Correct for rotational lengthening.

   for (int i = 0; i < _numberOfConstraints; i++) {
       int atom1 = _atomIndices[i][0];
       int atom2 = _atomIndices[i][1];
       RealVec delta(atomCoordinatesP[atom1][0]-atomCoordinatesP[atom2][0],
                  atomCoordinatesP[atom1][1]-atomCoordinatesP[atom2][1],
                  atomCoordinatesP[atom1][2]-atomCoordinatesP[atom2][2]);
       RealOpenMM p2 = (RealOpenMM)(two*_distance[i]*_distance[i]-delta.dot(delta));
       if (p2 < zero)
           p2 = zero;
       _rhs1[i] = _solution[i] = _sMatrix[i]*(_distance[i]-SQRT(p2));
   }
   solveMatrix();
   updateAtomPositions(numberOfAtoms, atomCoordinatesP, inverseMasses);

   return SimTKOpenMMCommon::DefaultReturn;

}
예제 #2
0
// -----------------------------------------------------------------------------
//                      INITIALIZE OpenMM DATA STRUCTURES
// -----------------------------------------------------------------------------
// We take these actions here:
// (1) Load any available OpenMM plugins, e.g. Cuda and Brook.
// (2) Allocate a MyOpenMMData structure to hang on to OpenMM data structures
//     in a manner which is opaque to the caller.
// (3) Fill the OpenMM::System with the force field parameters we want to
//     use and the particular set of atoms to be simulated.
// (4) Create an Integrator and a Context associating the Integrator with
//     the System.
// (5) Select the OpenMM platform to be used.
// (6) Return the MyOpenMMData struct and the name of the Platform in use.
//
// Note that this function must understand the calling MD code's molecule and
// force field data structures so will need to be customized for each MD code.
static MyOpenMMData*
myInitializeOpenMM( int                 numWatersAlongEdge,
                    double              temperature,
                    double              frictionInPerPs,
                    double              stepSizeInFs,
                    std::string&        platformName)
{
    // Load all available OpenMM plugins from their default location.
    OpenMM::Platform::loadPluginsFromDirectory
       (OpenMM::Platform::getDefaultPluginsDirectory());

    // Allocate space to hold OpenMM objects while we're using them.
    MyOpenMMData* omm = new MyOpenMMData();

    // Create a System and Force objects within the System. Retain a reference
    // to each force object so we can fill in the forces. Note: the System owns
    // the force objects and will take care of deleting them; don't do it yourself!
    OpenMM::System&                 system      = *(omm->system = new OpenMM::System());

    OpenMM::NonbondedForce&         nonbond     = *new OpenMM::NonbondedForce();
    system.addForce(&nonbond);

    OpenMM::HarmonicBondForce&      bondStretch = *new OpenMM::HarmonicBondForce();
    system.addForce(&bondStretch);

    OpenMM::HarmonicAngleForce&     bondBend    = *new OpenMM::HarmonicAngleForce();
    system.addForce(&bondBend);

    OpenMM::AndersenThermostat&     thermostat  = *new OpenMM::AndersenThermostat(
            temperature,      // kelvins
            frictionInPerPs); // collision frequency in 1/picoseconds
    system.addForce(&thermostat);

    // Volume of one water is 30 Angstroms cubed;
    // Thus length in one dimension is cube-root of 30,
    // or 3.107 Angstroms or 0.3107 nanometers
    const double WaterSizeInNm = 0.3107; // edge of cube containing one water, in nanometers
    // Place water molecules one at a time in an NxNxN rectilinear grid
    const double boxEdgeLengthInNm = WaterSizeInNm * numWatersAlongEdge;

    // Create periodic box
    nonbond.setNonbondedMethod(OpenMM::NonbondedForce::PME);
    nonbond.setUseDispersionCorrection(true);
    nonbond.setCutoffDistance(CutoffDistanceInAng * OpenMM::NmPerAngstrom);
    nonbond.setSwitchingDistance(SwitchDistanceInAng * OpenMM::NmPerAngstrom);
    nonbond.setEwaldErrorTolerance(1e-6);
    system.setDefaultPeriodicBoxVectors(Vec3(boxEdgeLengthInNm,0,0),
                                  Vec3(0,boxEdgeLengthInNm,0),
                                  Vec3(0,0,boxEdgeLengthInNm));

    // Specify the atoms and their properties:
    //  (1) System needs to know the masses and constraints (if any).
    //  (2) NonbondedForce needs charges,van der Waals properties (in MD units!).
    //  (3) Collect starting positions for initializing the simulation later.

    // Create data structures to hold lists of initial positions and bonds
    std::vector<Vec3>                   initialPosInNm;
    std::vector< std::pair<int,int> >   bondPairs;

    // Add water molecules one at a time in the NxNxN cubic lattice
    for (int latticeX = 0; latticeX < numWatersAlongEdge; ++latticeX)
    for (int latticeY = 0; latticeY < numWatersAlongEdge; ++latticeY)
    for (int latticeZ = 0; latticeZ < numWatersAlongEdge; ++latticeZ)
    {
        // Add parameters for one water molecule

        // Add atom masses to system
        int  oIndex = system.addParticle(O_mass); // O
        int h1Index = system.addParticle(H_mass); // H1
        int h2Index = system.addParticle(H_mass); // H2

        // Add atom charge, sigma, and stiffness to nonbonded force
        nonbond.addParticle( // Oxygen
                O_charge,
                O_vdwRadInAng     * OpenMM::NmPerAngstrom * OpenMM::SigmaPerVdwRadius,
                O_vdwEnergyInKcal * OpenMM::KJPerKcal);
        nonbond.addParticle( // Hydrogen1
                H_charge,
                H_vdwRadInAng     * OpenMM::NmPerAngstrom * OpenMM::SigmaPerVdwRadius,
                H_vdwEnergyInKcal * OpenMM::KJPerKcal);
        nonbond.addParticle( // Hydrogen2
                H_charge,
                H_vdwRadInAng     * OpenMM::NmPerAngstrom * OpenMM::SigmaPerVdwRadius,
                H_vdwEnergyInKcal * OpenMM::KJPerKcal);

        // Constrain O-H bond lengths or use harmonic forces.
        if (UseConstraints) {
            system.addConstraint(oIndex, h1Index,
                             OH_nominalLengthInAng * OpenMM::NmPerAngstrom);
            system.addConstraint(oIndex, h2Index,
                             OH_nominalLengthInAng * OpenMM::NmPerAngstrom);
        } else {
            // Add stretch parameters for two covalent bonds
            // Note factor of 2 for stiffness below because Amber specifies the constant
            // as it is used in the harmonic energy term kx^2 with force 2kx; OpenMM wants
            // it as used in the force term kx, with energy kx^2/2.
            bondStretch.addBond(oIndex, h1Index,
                    OH_nominalLengthInAng     * OpenMM::NmPerAngstrom,
                    OH_stiffnessInKcalPerAng2 * 2 * OpenMM::KJPerKcal
                        * OpenMM::AngstromsPerNm * OpenMM::AngstromsPerNm);
            bondStretch.addBond(oIndex, h2Index,
                    OH_nominalLengthInAng     * OpenMM::NmPerAngstrom,
                    OH_stiffnessInKcalPerAng2 * 2 * OpenMM::KJPerKcal
                        * OpenMM::AngstromsPerNm * OpenMM::AngstromsPerNm);
        }

        // Store bonds for exclusion list
        bondPairs.push_back(std::make_pair(oIndex, h1Index));
        bondPairs.push_back(std::make_pair(oIndex, h2Index));

        // Add bond bend parameters for one angle.
        // See note under bond stretch above regarding the factor of 2 here.
        bondBend.addAngle(h1Index, oIndex, h2Index,
                HOH_nominalAngleInDeg      * OpenMM::RadiansPerDegree,
                HOH_stiffnessInKcalPerRad2 * 2 * OpenMM::KJPerKcal);

        // Location of this molecule in the lattice
        Vec3 latticeVec(WaterSizeInNm * latticeX,
                        WaterSizeInNm * latticeY,
                        WaterSizeInNm * latticeZ);

        // flip half the waters to prevent giant dipole
        int flip = (rand() % 100) > 49 ? 1 : -1;

        // place this water
        initialPosInNm.push_back(Vec3(0,0,0) + latticeVec); // O
        initialPosInNm.push_back(Vec3(0.09572*flip,0,0) + latticeVec); // H1
        initialPosInNm.push_back(Vec3(-0.02397*flip,0.09267*flip,0) + latticeVec); // H2
    }

    // Populate nonbonded exclusions
    nonbond.createExceptionsFromBonds(bondPairs, 1.0, 1.0);

    // Choose an Integrator for advancing time, and a Context connecting the
    // System with the Integrator for simulation. Let the Context choose the
    // best available Platform. Initialize the configuration from the default
    // positions we collected above. Initial velocities will be zero.
    omm->integrator = new OpenMM::VerletIntegrator(StepSizeInFs * OpenMM::PsPerFs);
    omm->context    = new OpenMM::Context(*omm->system, *omm->integrator);
    omm->context->setPositions(initialPosInNm);

    platformName = omm->context->getPlatform().getName();
    return omm;
}
MBPolReferenceDispersionForce::MBPolReferenceDispersionForce( ) : _nonbondedMethod(NoCutoff), _cutoff(1.0e+10) {

    _periodicBoxDimensions = RealVec( 0.0, 0.0, 0.0 );
}