bool _computeForceRaw(Real3D& force12,
                              Real3D& force32,
                              const Real3D& r12,
                              const Real3D& r32, real _theta0) const {

        real dist12_sqr = r12.sqr();
        real dist32_sqr = r32.sqr();
        real dist12_magn = sqrt(dist12_sqr);
        real dist32_magn = sqrt(dist32_sqr);
        real dU_dtheta, a11, a12, a22;
        real inv_dist1232 = 1.0/(dist12_magn * dist32_magn);

        real cos_theta = r12 * r32 * inv_dist1232;
        if(cos_theta < -1.0) cos_theta = -1.0;
        else if(cos_theta >  1.0) cos_theta =  1.0;
        real sin_theta = sqrt(1.0 - cos_theta * cos_theta);

        dU_dtheta = - KpK * (acos(cos_theta) - _theta0) / sin_theta;

        a11 = dU_dtheta * cos_theta / dist12_sqr;
        a12 = -dU_dtheta * inv_dist1232;
        a22 = dU_dtheta * cos_theta / dist32_sqr;

        force12 = a11 * r12 + a12 * r32;
        force32 = a22 * r32 + a12 * r12;
        return true;
      }
 inline real
 AngularUniquePotentialTemplate< Derived >::
 computeEnergy(const Real3D& r12, const Real3D& r32, real theta0) const {
   real dist12Sqr = r12.sqr();
   real dist32Sqr = r32.sqr();
   real cos_theta = r12 * r32 / (sqrt(dist12Sqr) * sqrt(dist32Sqr));
   return computeEnergy(acos(cos_theta), theta0);
 }
 inline real
 AngularUniquePotentialTemplate< Derived >::
 _computeEnergy(const Real3D& r12, const Real3D& r32, real theta0) const {
   real dist12_sqr = r12.sqr();
   real dist32_sqr = r32.sqr();
   if (dist12_sqr >= cutoffSqr || dist32_sqr >= cutoffSqr )
     return 0.0;
   else{
     real cos_theta = r12 * r32 / (sqrt(dist12_sqr) * sqrt(dist32_sqr));
     return _computeEnergy(acos(cos_theta), theta0);
   }
 }
                bool _computeForce(Real3D& force, const Particle &p1,
                         const Particle &p2) const {
                    Real3D dist = p1.position() - p2.position();
                    real r2 = dist.sqr();
                    if (r2>rc2) return true;
                    real r = sqrt(r2);
                    real qq = p1.q()*p2.q();
                    real ffactor = prefactor*qq* (1.0/(r*r2) + B1);
                    force = dist * ffactor;
                    return true;

                }
 real _computeEnergyDeriv(const Particle& p1, const Particle& p2) const {
     Real3D dist = p1.position() - p2.position();
     real distSqr = dist.sqr();
     if (distSqr>rc2) return 0.0;
     if (checkTIpair(p1.id(),p2.id())) {
         real qq = p1.q()*p2.q();
         real dhdl = -1.0 * prefactor * qq * (1.0 / sqrt(distSqr) - B1_half*distSqr -crf);
         return dhdl;
     } else {
         return 0.0;
     }
 }
Exemplo n.º 6
0
      python::list MeanSquareInternalDist::compute() const{
                         
      python::list pyli;
      
      System& system = getSystemRef();
            
      //creating vector which stores particleIDs for each CPU
      vector<longint> localIDs; // localIDs is a vector with PID of particles in each CPU and it contains whole chains
      for (map<size_t,int>::const_iterator itr=idToCpu.begin(); itr!=idToCpu.end(); ++itr) {
        size_t i = itr->first;
        int whichCPU = itr->second;
        if(system.comm->rank()==whichCPU){
          localIDs.push_back(i); 
        }
      }
      sort(localIDs.begin(), localIDs.end()); //sorts entries from low to high - should not be necessary as long as the above iterator iterates in ascending order according to the keys
                
      // MSID calculation
      
      int M = getListSize(); //number of snapshots/configurations
                 
      real intdist_sum = 0;
                  
      int N_chains = localIDs.size() / chainlength; // N_chains is number of chains in this cpu and chainlength is a global variable from ConfigsParticleDecomp.hpp

      for (int n=1; n<chainlength;n++){ // loop over chainlength

          real intdist = 0.0;
      
          for (int j=0; j<N_chains;j++){
              
              real sumdistsq = 0.0 ;
                                    
              for (int i=j*chainlength; i<(j*chainlength)+chainlength-n;i++){
                  Real3D pos1 = getConf(M-1)->getCoordinates(localIDs[i]);   // compute the MSID of the last added snapshot
                  Real3D pos2 = getConf(M-1)->getCoordinates(localIDs[i+n]); // compute the MSID of the last added snapshot                                                     
                  Real3D delta = pos2 - pos1;   //vector with the distances from i to chainlength-n
                  sumdistsq += delta.sqr();// dx*dx+dy*dy+dz*dz
              }
              
              intdist += sumdistsq/real(chainlength-n);  //sum of the internal distances (chainlength-n) of the chains in this cpu
          }
                    
          boost::mpi::reduce(*system.comm, intdist, intdist_sum, std::plus<real>(), 0);
          
          if (system.comm->rank() == 0) { 
              int chains_total = num_of_part / chainlength;
              pyli.append( intdist_sum / real(chains_total)); 
          }          
      } 
      return pyli;
    }
                real _computeEnergy(const Particle& p1, const Particle& p2) const {
                    Real3D dist = p1.position() - p2.position();
                    real distSqr = dist.sqr();
                    if (distSqr>rc2) return 0.0;
                    real qq = p1.q()*p2.q();
                    /* Note: this implementation counts minus integral of the force as energy
                         which is not the same as the full electrostatic energy
                         See the original paper Tironi et al J.Chem.Phys 102, 13, 1995
                         for details*/

                    real energy = prefactor*qq * (1.0 / sqrt(distSqr) - B1_half*distSqr -crf);     
                    return energy;
                }
                bool _computeForce(Real3D& force, const Particle &p1,
                         const Particle &p2) const {
                    Real3D dist = p1.position() - p2.position();
                    real r2 = dist.sqr();
                    if (r2>rc2) return true;
                    real r = sqrt(r2);
                    real qq = p1.q()*p2.q();
                    if (checkTIpair(p1.id(),p2.id())) {
                      qq *= complLambdaTI; //(1-lambda)*qAi*qAj
                    }
                    real ffactor = prefactor*qq* (1.0/(r*r2) + B1);
                    force = dist * ffactor;
                    return true;

                }
                real _computeEnergy(const Particle& p1, const Particle& p2) const {
                    Real3D dist = p1.position() - p2.position();
                    real distSqr = dist.sqr();
                    if (distSqr>rc2) return 0.0;
                    real qq = p1.q()*p2.q();
                    if (checkTIpair(p1.id(),p2.id())) {
                      qq *= complLambdaTI; //(1-lambda)*qAi*qAj
                    }
                    /* Note: this implementation counts minus integral of the force as energy
                         which is not the same as the full electrostatic energy
                         See the original paper Tironi et al, J. Chem. Phys. 102 , 5451 (1995) 
                         for details*/

                    real energy = prefactor*qq * (1.0 / sqrt(distSqr) - B1_half*distSqr -crf);     
                    return energy;
                }
 void _computeForceRaw(Real3D& force1,
                       Real3D& force2,
                       Real3D& force3,
                       Real3D& force4,
                       const Real3D& r21,
                       const Real3D& r32,
                       const Real3D& r43, const real _phi0) const {
   
   Real3D retF[4];
   
   Real3D rijjk = r21.cross(r32); // [r21 x r32]
   Real3D rjkkn = r32.cross(r43); // [r32 x r43]
   
   real rijjk_sqr = rijjk.sqr();
   real rjkkn_sqr = rjkkn.sqr();
   
   real rijjk_abs = sqrt(rijjk_sqr);
   real rjkkn_abs = sqrt(rjkkn_sqr);
   
   real inv_rijjk = 1.0 / rijjk_abs;
   real inv_rjkkn = 1.0 / rjkkn_abs;
   
   // cosine between planes
   real cos_phi = (rijjk * rjkkn) * (inv_rijjk * inv_rjkkn);
   if (cos_phi > 1.0) cos_phi = 1.0;
   else if (cos_phi < -1.0) cos_phi = -1.0;
   
   real coef1 = (-2.0) * K * (cos_phi - cos(_phi0));
   
   real A1 = inv_rijjk * inv_rjkkn;
   real A2 = inv_rijjk * inv_rijjk;
   real A3 = inv_rjkkn * inv_rjkkn;
   
   Real3D p3232 ( prod(r32,r32) );
   Real3D p3243 ( prod(r32,r43) );
   Real3D p2132 ( prod(r21,r32) );
   Real3D p2143 ( prod(r21,r43) );
   Real3D p2121 ( prod(r21,r21) );
   Real3D p4343 ( prod(r43,r43) );
   
   // we have 4 particles 1,2,3,4
   for(int l=0; l<4; l++){
     Real3D B1, B2, B3;
     
     for(int i=0; i<3; i++){
       B1[i]= r21[i] * ( p3232[i] * (d(l,2)-d(l,3)) + p3243[i] * (d(l,2)-d(l,1)) ) +
              r32[i] * ( p2132[i] * (d(l,3)-d(l,2)) + p3243[i] * (d(l,1)-d(l,0)) ) +
              r43[i] * ( p2132[i] * (d(l,2)-d(l,1)) + p3232[i] * (d(l,0)-d(l,1)) ) +
              2.0 * r32[i] * p2143[i] * (d(l,1)-d(l,2));
     
       B2[i]= 2.0 * r21[i] * ( p3232[i] * (d(l,1)-d(l,0)) + p2132[i] * (d(l,1)-d(l,2)) ) +
              2.0 * r32[i] * ( p2121[i] * (d(l,2)-d(l,1)) + p2132[i] * (d(l,0)-d(l,1)));
     
       B3[i]= 2.0 * r43[i] * ( p3232[i] * (d(l,3)-d(l,2)) + p3243[i] * (d(l,1)-d(l,2)) ) +
              2.0 * r32[i] * ( p4343[i] * (d(l,2)-d(l,1)) + p3243[i] * (d(l,2)-d(l,3)));
     }
     
     retF[l] = coef1 * ( A1*B1 - 0.5*cos_phi*(A2*B2 + A3*B3) );
   }
   
   force1 = retF[0];
   force2 = retF[1];
   force3 = retF[2];
   force4 = retF[3];
 }
Exemplo n.º 11
0
    void Rattle::applyPositionConstraints() {

      int iteration = 0;
      bool done = false;
      real dt = integrator->getTimeStep();
      System& system = getSystemRef();
      const bc::BC& bc = *getSystemRef().bc;  // boundary conditions

      boost::unordered_map<longint, Real3D> currPosition;
      boost::unordered_map<longint, Real3D> currVelocity;
      boost::unordered_map<longint, bool> movedLastTime; //was this particle moved last time?
      boost::unordered_map<longint, bool> movingThisTime; //is the particle being moved this time?

      if (oldPos.size() == 0) {return;} //no rigid bonds on this node

      //loop over bonds on this node
      OldPos::iterator it;
      for (it=oldPos.begin(); it != oldPos.end(); it++ ) { 
        longint pidHyd = it->first;
        longint pidHeavy = constrainedBonds[pidHyd].pidHeavy;
        //In the maps below, the values for each key pidHeavy may be initialised more than, if pidHeavy is involved in more than one constrained bond. This is not a problem
        movedLastTime[pidHyd] = true;
        movedLastTime[pidHeavy] = true;
        movingThisTime[pidHyd] = false;
        movingThisTime[pidHeavy] = false;
        currPosition[pidHyd] = system.storage->lookupAdrATParticle(pidHyd)->getPos();
        currPosition[pidHeavy] = system.storage->lookupAdrATParticle(pidHeavy)->getPos(); 
        currVelocity[pidHyd] = system.storage->lookupAdrATParticle(pidHyd)->getV();
        currVelocity[pidHeavy] = system.storage->lookupAdrATParticle(pidHeavy)->getV(); 
      }

      //constraint interations
      while (!done && iteration < maxit) {
        done = true;
        //loop over constrained bonds on this cpu
        for (it=oldPos.begin(); it != oldPos.end(); it++) {
          //get pids of the two particles in this bond
          longint a = it->first; //pidHyd
          longint b = constrainedBonds[a].pidHeavy;
          if (movedLastTime[a] || movedLastTime[b]) { 
            //compare current distance to desired constraint distance
            Real3D pab;
            bc.getMinimumImageVectorBox(pab,currPosition[a],currPosition[b]); //a-b, current positions which change during iterations
            real pabsq = pab.sqr();
            real constraint_absq = constrainedBonds[a].constraintDist2;
            real diffsq = pabsq - constraint_absq; 
            if (fabs(diffsq) > (constraint_absq*tol) ) {
              //get ab vector before unconstrained position update
              Real3D rab;
              bc.getMinimumImageVectorBox(rab,oldPos[a].second,oldPos[a].first); //pos at time t (end of last timestep), a-b;
              real rab_dot_pab = rab * pab; //r_ab(t) * r_ab,curr(t+dt)
              if (rab_dot_pab < (constraint_absq*rptol)) { //i.e. if angle is too large
                std::ostringstream msg;
                msg << "Constraint failure in RATTLE" << std::endl;
                throw std::runtime_error( msg.str() );
              }
              real rma = constrainedBonds[a].invmassHyd;
              real rmb = constrainedBonds[a].invmassHeavy;
              real gab = diffsq / (2.0 * (rma + rmb) * rab_dot_pab);
              //direct constraint along bond vector at end of previous timestep
              Real3D displ = gab * rab; 
              currPosition[a] -= rma * displ;
              currPosition[b] += rmb * displ;

              displ /= dt;
              currVelocity[a] -= rma * displ;
              currVelocity[b] += rmb * displ;

              movingThisTime[a] = true;
              movingThisTime[b] = true;
              done = false;
            }
          }
        }
        boost::unordered_map<longint, bool>::iterator it3;
        for (it3 = movedLastTime.begin(); it3 != movedLastTime.end(); it3++) {
          longint id = it3->first;
          movedLastTime[id] = movingThisTime[id];
          movingThisTime[id] = false;
        }

        iteration += 1;
      }

      if (!done) {
        std::ostringstream msg;
        msg << "Too many position constraint iterations in Rattle" << std::endl;
        throw std::runtime_error( msg.str() );
      }

      //store new values for positions
      boost::unordered_map<longint, Real3D>::iterator it2;
      for (it2 = currPosition.begin(); it2 != currPosition.end(); it2++) {
        longint id = it2->first;
        Particle* p = system.storage->lookupAdrATParticle(id);
        p->position() = currPosition[id];
        p->velocity() = currVelocity[id];
      }
    }