Example #1
0
void ModifierRattle::doExecute(Integrator *i) {
  // estimate the current error in all velocity constraints
  Real error = calcError();

  // delta_t
  Real dt = i->getTimestep() / Constant::TIMEFACTOR;

  int iter = 0;
  while (error > myEpsilon) {
    for (unsigned int i = 0; i < myListOfConstraints->size(); i++) {
      // find the ID#s of the two atoms in the current constraint
      int a1 = (*myListOfConstraints)[i].atom1;
      int a2 = (*myListOfConstraints)[i].atom2;

      // reciprocal atomic masses
      Real rM1 = 1 / app->topology->atoms[a1].scaledMass;
      Real rM2 = 1 / app->topology->atoms[a2].scaledMass;

      // now lets compute the lambdas.
      // compute the current bond vector
      Vector3D rab = app->positions[a1] - app->positions[a2];
      Real rabsq = rab.normSquared();

      // compute the current velocity vector
      Vector3D vab = app->velocities[a1] - app->velocities[a2];

      // dot product of distance and velocity vectors
      Real rvab = rab * vab;

      // compute the change in lambda
      Real gab = -rvab / (dt * (rM1 + rM2) * rabsq);
      Vector3D dp = rab * gab;

      // move the velocities based upon the multiplier
      app->velocities[a1] += dp * dt * rM1;
      app->velocities[a2] -= dp * dt * rM2;

      // the constraint adds a force to each atom since their positions
      // had to be changed.  This constraint force therefore contributes
      // to the atomic virial.  Note that the molecular virial is independent of
      // any intramolecular constraint forces.
      if (app->energies.virial()) app->energies.addVirial(dp * 2, rab);
    }

    // compute the error in all the velocity constraints after this RATTLE
    // iteration
    error = calcError();
    iter++;
    if (iter > myMaxIter) {
      report << warning << "maxIter = " << myMaxIter
             << " reached, but still not converged ... error is " << error <<
      endr;
      break;
    }
  }
}
Example #2
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// find forces in block for 'small' numerical Hessian
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void BlockHessian::evaluateBlockForces( const unsigned int blockStart, const unsigned int blockEnd,
                            const Vector3DBlock *myPositions,
                                const GenericTopology *myTopo, Vector3DBlock *blockForces){

  //clear array
  for (unsigned int i = blockStart; i <= blockEnd; i++){
      (*blockForces)[i] = Vector3D(0.0, 0.0, 0.0);
  }

  //get boundary and dummy energies
  const VacuumBoundaryConditions &boundary =
            ((SemiGenericTopology<VacuumBoundaryConditions> &)(*myTopo)).boundaryConditions;
    
  ScalarStructure energies;
  energies.clear();

    //~~~~Bonds~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myBond){
    for (unsigned i = 0; i < myTopo->bonds.size(); i++) {
      const unsigned int a1 = myTopo->bonds[i].atom1;
      const unsigned int a2 = myTopo->bonds[i].atom2;

      //in this block?
      if( (a1 >= blockStart && a1 <= blockEnd) && (a2 >= blockStart && a2 <= blockEnd) ){

        //call force calculaton
        BondSystemForce<VacuumBoundaryConditions> bsf;

        bsf.calcBond(boundary,
                        myTopo->bonds[i], myPositions, blockForces, &energies);

      }
    }
  }

  //~~~~Angles~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myAngle){
    for (unsigned i = 0; i < myTopo->angles.size(); i++) {
      const unsigned int a1 = myTopo->angles[i].atom1;
      const unsigned int a2 = myTopo->angles[i].atom2;
      const unsigned int a3 = myTopo->angles[i].atom3;
      
      //in this block?
      if( (a1 >= blockStart && a1 <= blockEnd) &&
            (a2 >= blockStart && a2 <= blockEnd) &&
                (a3 >= blockStart && a3 <= blockEnd) ){
      
          AngleSystemForce<VacuumBoundaryConditions> asf;

          asf.calcAngle(boundary, myTopo->angles[i],
                        myPositions, blockForces, &energies);
          
      }
    }
  }

  //~~~~Impropers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myImproper) {
    for (unsigned int i = 0; i < myTopo->impropers.size(); i++) {
      const unsigned int a1 = myTopo->impropers[i].atom1;
      const unsigned int a2 = myTopo->impropers[i].atom2;
      const unsigned int a3 = myTopo->impropers[i].atom3;
      const unsigned int a4 = myTopo->impropers[i].atom4;

      //in this block?
      if( (a1 >= blockStart && a1 <= blockEnd) &&
            (a2 >= blockStart && a2 <= blockEnd) &&
                (a3 >= blockStart && a3 <= blockEnd) &&
                    (a4 >= blockStart && a4 <= blockEnd) ){
          ImproperSystemForce<VacuumBoundaryConditions> isf;

          isf.calcTorsion(boundary, myTopo->impropers[i], myPositions,
                            blockForces, (energies)[ScalarStructure::IMPROPER], &energies);
      }

    }
  }

  //~~~~Dihedrals~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myDihedral) {
    for (unsigned int i = 0; i < myTopo->dihedrals.size(); i++) {
      const unsigned int a1 = myTopo->dihedrals[i].atom1;
      const unsigned int a2 = myTopo->dihedrals[i].atom2;
      const unsigned int a3 = myTopo->dihedrals[i].atom3;
      const unsigned int a4 = myTopo->dihedrals[i].atom4;

      //in this block?
		if( (a1 >= blockStart && a1 <= blockEnd) &&
                (a2 >= blockStart && a2 <= blockEnd) &&
                    (a3 >= blockStart && a3 <= blockEnd) &&
                        (a4 >= blockStart && a4 <= blockEnd) ){
			DihedralSystemForce<VacuumBoundaryConditions> dsf;

          dsf.calcTorsion(boundary, myTopo->dihedrals[i], myPositions,
                            blockForces, (energies)[ScalarStructure::DIHEDRAL], &energies);
      }

    }
  }

  //~~~~RBDihedrals~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myRBDihedral) {
    for (unsigned int i = 0; i < myTopo->rb_dihedrals.size(); i++) {
      const unsigned int a1 = myTopo->rb_dihedrals[i].atom1;
      const unsigned int a2 = myTopo->rb_dihedrals[i].atom2;
      const unsigned int a3 = myTopo->rb_dihedrals[i].atom3;
      const unsigned int a4 = myTopo->rb_dihedrals[i].atom4;

      //in this block?
		if( (a1 >= blockStart && a1 <= blockEnd) &&
                (a2 >= blockStart && a2 <= blockEnd) &&
                    (a3 >= blockStart && a3 <= blockEnd) &&
                        (a4 >= blockStart && a4 <= blockEnd) ){
			RBDihedralSystemForce<VacuumBoundaryConditions> dsf;

          dsf.calcRBTorsion(boundary, myTopo->rb_dihedrals[i], myPositions,
                            blockForces, (energies)[ScalarStructure::OTHER], &energies);
      }

    }
  }

  //~~~~Lennard Jones~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myLennardJones) {
    //loop over all pairs in this block only
    for (unsigned int i = blockStart; i <= blockEnd; i++){
        for (unsigned int j = i + 1; j <= blockEnd; j++){

          //if not bonded/dihedral
          const ExclusionClass ec = myTopo->exclusions.check(i, j);
          
          if (ec != EXCLUSION_FULL) {

            Vector3D rij = myTopo->minimalDifference((*myPositions)[i], (*myPositions)[j]);

            const Real a = rij.normSquared();

            Real rawE = 0.0; Real rawForce = 0.0;

            LennardJonesForce jlf;

            jlf(rawE, rawForce, a, 1.0 / a, rij, myTopo, i, j, ec);

            // Add this force into the atom forces.
            Vector3D fij = -rij * rawForce;
            (*blockForces)[i] += fij;
            (*blockForces)[j] -= fij;

          }

        }
    }
  }

  //~~~~Coulomb~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (myCoulomb) {
    //loop over all pairs in this block only
    for (unsigned int i = blockStart; i <= blockEnd; i++){
        for (unsigned int j = i + 1; j <= blockEnd; j++){

          //if not bonded/dihedral
          const ExclusionClass ec = myTopo->exclusions.check(i, j);

          if (ec != EXCLUSION_FULL) {

            Vector3D rij = myTopo->minimalDifference((*myPositions)[i], (*myPositions)[j]);

            const Real a = rij.normSquared();

            Real rawE = 0.0; Real rawForce = 0.0;

            CoulombForce cf;

            cf(rawE, rawForce, a, 1.0 / a, rij, myTopo, i, j, ec);

            // Add this force into the atom forces.
            Vector3D fij = -rij * rawForce;
            (*blockForces)[i] += fij;
            (*blockForces)[j] -= fij;

          }

        }
    }

  }

  //~~~~End~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

}
  void ModifierNPTRattleDetails::doExecute(Integrator* myTheIntegrator){

    // estimate the current error in all velocity constraints
    Real error = calcError();

    // delta_t
    Real dt = myTheIntegrator->getTimestep() / Constant::TIMEFACTOR;

    // multiplicative constants for the box volume velocity and thermostat velocity
    const Real pVol_term = 0.5 * myTheIntegrator->getTimestep() * getEpsilonVel();
    const Real pEta_term = 0.5 * myTheIntegrator->getTimestep() * getEtaVel();
    const Real OneOverN_term = 1.0 + 1.0 / app->topology->atoms.size();

    int iter = 0;
    while(error > myEpsilon) {
      
      for(unsigned int i=0;i<myListOfConstraints->size();i++) {

        // find the ID#s of the two atoms in the current constraint
        int a1 = (*myListOfConstraints)[i].atom1;
        int a2 = (*myListOfConstraints)[i].atom2;

        // get the ID# of the molecule that this bond belongs to
        int Mol = app->topology->atoms[a1].molecule;

        // reciprocal atomic masses
        Real rM1 = 1/app->topology->atoms[a1].scaledMass;
        Real rM2 = 1/app->topology->atoms[a2].scaledMass;
        Real m1_over_M = 1 / (rM1 * app->topology->molecules[Mol].mass);
        Real m2_over_M = 1 / (rM2 * app->topology->molecules[Mol].mass);

        // multiplicative constants due to change in box volume
        // (for constant pressure simulations -- see Equation 56 of G. Kalibaeva,
        //  M. Ferrario, and G. Ciccotti, "Constant pressure-constant temperature molecular
        //  dynamics: a correct constrained NPT ensemble using the molecular virial", Mol. Phys.
        //  101(6), 2003, p. 765-778)
        Real Exp2_atom1 = (1 + pVol_term*OneOverN_term*m1_over_M) * exp( -pEta_term - pVol_term*OneOverN_term*m1_over_M);
        Real Exp2_atom2 = (1 + pVol_term*OneOverN_term*m2_over_M) * exp( -pEta_term - pVol_term*OneOverN_term*m2_over_M);
        
        // now lets compute the lambdas.
        // compute the current bond vector
        Vector3D rab = (app->positions)[a1] - (app->positions)[a2];
        Real rabsq = rab.normSquared();

        // compute the current velocity vector
        Vector3D vab = (app->velocities)[a1] - (app->velocities)[a2];   

        // dot product of distance and velocity vectors
        Real rvab = rab * vab;

        // compute the change in lambda
        Real gab = -rvab / (dt * (rM1 * Exp2_atom1 + rM2 * Exp2_atom2) * rabsq);
        Vector3D dp = rab * gab;

        // move the velocities based upon the multiplier
        (app->velocities)[a1] += dp * dt * rM1 * Exp2_atom1;
        (app->velocities)[a2] -= dp * dt * rM2 * Exp2_atom2;

        // the constraint adds a force to each atom since their positions
        // had to be changed.  This constraint force therefore contributes
        // to the atomic virial.  Note that the molecular virial is independent of
        // any intramolecular constraint forces.
        if (app->energies.virial()) app->energies.addVirial(dp*2,rab);
      }

      // compute the error in all the velocity constraints after this RATTLE iteration
      error = calcError();
      iter ++;
      if(iter > myMaxIter) {
        report << warning << "Rattle maxIter = " << myMaxIter
               << " reached, but still not converged ... error is "<<error<<endr;
        break;
      }
    }
  }
//____ normVector3DOp
static bool normVector3DOp(const Vector3D &v1, const Vector3D &v2) {
  return v1.normSquared() < v2.normSquared();
}
Example #5
0
void ModifierShake::doExecute(Integrator *i) {
  // estimate the current error in all bond constraints
  Real error = calcError();

  // delta_t
  Real dt = i->getTimestep() / Constant::TIMEFACTOR;

  int iter = 0;
  while (error > myEpsilon) {
    for (unsigned int i = 0; i < myListOfConstraints->size(); i++) {
      // find the ID#s of the two atoms in the current constraint
      int a1 = (*myListOfConstraints)[i].atom1;
      int a2 = (*myListOfConstraints)[i].atom2;

      // get the target bond distance for this constraint
      Real restLength = (*myListOfConstraints)[i].restLength;

      // now lets compute the lambdas.
      Vector3D pab = app->positions[a1] - app->positions[a2];

      // compute the current bond vector
      Real pabsq = pab.normSquared();
      Real rabsq = restLength * restLength;

      // compute the difference between the target bond length and
      // the actual bond length
      Real diffsq = rabsq - pabsq;   //-g^k()

      // compute the bond vector from the previous timestep
      Vector3D rab = myLastPositions[a1] - myLastPositions[a2];
      Real rpab = rab * pab;

      // reciprocal atomic masses
      Real rM1 = 1 / app->topology->atoms[a1].scaledMass;
      Real rM2 = 1 / app->topology->atoms[a2].scaledMass;

      // calculate the constraint force, or multiplier
      Real gab = diffsq / (2 * (rM1 + rM2) * rpab);
      Vector3D dp = rab * gab;

      // move the positions based upon the multiplier
      app->positions[a1] += dp * rM1;
      app->positions[a2] -= dp * rM2;

      dp /= dt;

      // move the velocities based upon the multiplier
      app->velocities[a1] += dp * rM1;
      app->velocities[a2] -= dp * rM2;

      // the constraint adds a force to each atom since their positions
      // had to be changed.  This constraint force therefore contributes
      // to the atomic virial.  Note that the molecular virial is independent of
      // any intramolecular constraint forces.
      if (app->energies.virial()) {
        dp /= dt;
        app->energies.addVirial(dp * 2, rab);
      }
    }

    // compute the error in all the bond constraints after this SHAKE iteration
    error = calcError();
    iter++;
    if (iter > myMaxIter) {
      report << warning << "maxIter = " << myMaxIter
             << " reached, but still not converged ... error is "
             << error << endr;
      break;
    }
  }

  // store the old positions
  myLastPositions = app->positions;
}