Exemplo n.º 1
0
double OrientationSphere::compute(){
   // Make sure derivatives for central atom are only calculated once
   VectorMultiColvar* vv = dynamic_cast<VectorMultiColvar*>( getBaseMultiColvar(0) );
   vv->firstcall=true;

   weightHasDerivatives=true;   // The weight has no derivatives really
   double sw, value=0, denom=0, dot, f_dot, dot_df, dfunc; Vector distance;

   getVectorForBaseTask(0, catom_orient );
   for(unsigned i=1;i<getNAtoms();++i){
      distance=getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(i) );
      sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc );
      if( sw>=getTolerance() ){    
         getVectorForBaseTask( i, this_orient );
         // Calculate the dot product wrt to this position 
         dot=0; for(unsigned k=0;k<catom_orient.size();++k) dot+=catom_orient[k]*this_orient[k];  
         f_dot = transformDotProduct( dot, dot_df ); 
         // N.B. We are assuming here that the imaginary part of the dot product is zero
         for(unsigned k=0;k<catom_orient.size();++k){
            this_orient[k]*=sw*dot_df; catom_der[k]=sw*dot_df*catom_orient[k];
         }  

         // Set the derivatives wrt of the numerator
         addOrientationDerivatives( 0, this_orient ); 
         addOrientationDerivatives( i, catom_der );  
         addCentralAtomsDerivatives( 0, 0, f_dot*(-dfunc)*distance );
         addCentralAtomsDerivatives( i, 0, f_dot*(dfunc)*distance );
         addBoxDerivatives( f_dot*(-dfunc)*Tensor(distance,distance) );
         value += sw*f_dot;
         // Set the derivatives wrt to the numerator
         addCentralAtomsDerivatives( 0, 1, (-dfunc)*distance );
         addCentralAtomsDerivatives( i, 1, (dfunc)*distance );
         addBoxDerivativesOfWeight( (-dfunc)*Tensor(distance,distance) );
         denom += sw;
      }
   }
   
   // Now divide everything
   unsigned nder = getNumberOfDerivatives();
   for(unsigned i=0;i<nder;++i){
      setElementDerivative( i, getElementDerivative(i)/denom - (value*getElementDerivative(nder+i))/(denom*denom) );  
      setElementDerivative( nder + i, 0.0 );
   }
   weightHasDerivatives=false;   // Weight has no derivatives we just use the holder for weight to store some stuff
   return value / denom;
}
Exemplo n.º 2
0
double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
   // Make sure derivatives for central atom are only calculated once
   VectorMultiColvar* vv = dynamic_cast<VectorMultiColvar*>( getBaseMultiColvar(0) );
   vv->firstcall=true;

   double d2, sw, value=0, denom=0, dot, f_dot, dot_df, dfunc; 
   unsigned ncomponents=getBaseMultiColvar(0)->getNumberOfQuantities();
   unsigned nder=myatoms.getNumberOfDerivatives();
   std::vector<double> catom_orient( ncomponents ), this_orient( ncomponents ), catom_der( ncomponents ); 

   Vector catom_pos = myatoms.getPosition(0);
   getVectorForTask( myatoms.getIndex(0), true, catom_orient );
   multicolvar::CatomPack atom0; MultiValue myder0(0,0), myder1(0,0); 
   if( !doNotCalculateDerivatives() ){
       myder0.resize( ncomponents,nder ); myder1.resize(ncomponents,nder); 
       atom0=getCentralAtomPackFromInput( myatoms.getIndex(0) );
       getVectorDerivatives( myatoms.getIndex(0), true, myder0 );
   }

   for(unsigned i=1;i<myatoms.getNumberOfAtoms();++i){
      Vector& distance=myatoms.getPosition(i);  
      if ( (d2=distance[0]*distance[0])<rcut2 &&
           (d2+=distance[1]*distance[1])<rcut2 &&
           (d2+=distance[2]*distance[2])<rcut2) {
 
         sw = switchingFunction.calculateSqr( d2, dfunc );  
 
         getVectorForTask( myatoms.getIndex(i), true, this_orient );
         // Calculate the dot product wrt to this position 
         dot=0; for(unsigned k=2;k<catom_orient.size();++k) dot+=catom_orient[k]*this_orient[k];  
         f_dot = transformDotProduct( dot, dot_df ); 

         if( !doNotCalculateDerivatives() ){
             // N.B. We are assuming here that the imaginary part of the dot product is zero
             for(unsigned k=2;k<catom_orient.size();++k){
                 this_orient[k]*=sw*dot_df; catom_der[k]=sw*dot_df*catom_orient[k];
             }
             getVectorDerivatives( myatoms.getIndex(i), true, myder1 );
             mergeVectorDerivatives( 1, 2, this_orient.size(), myatoms.getIndex(0), this_orient, myder0, myatoms );  
             mergeVectorDerivatives( 1, 2, catom_der.size(), myatoms.getIndex(i), catom_der, myder1, myatoms );
             myatoms.addComDerivatives( 1, f_dot*(-dfunc)*distance, atom0 );
             addAtomDerivatives( 1, i, f_dot*(dfunc)*distance, myatoms );
             myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) );
             myder1.clearAll();
              
             myatoms.addComDerivatives( -1, (-dfunc)*distance, atom0 );
             addAtomDerivatives( -1, i, (dfunc)*distance, myatoms );
             myatoms.addTemporyBoxDerivatives( (-dfunc)*Tensor(distance,distance) );

         }
         value += sw*f_dot;
         denom += sw;
      }
   }
   double rdenom, df2, pref=calculateCoordinationPrefactor( denom, df2 );
   if( fabs(denom)>epsilon ){ rdenom = 1.0 / denom; }
   else { plumed_assert(fabs(value)<epsilon); rdenom=1.0; } 
  
   // Now divide everything
   double rdenom2=rdenom*rdenom;
   updateActiveAtoms( myatoms ); MultiValue& myvals=myatoms.getUnderlyingMultiValue();
   for(unsigned i=0;i<myvals.getNumberActive();++i){
       unsigned ider=myvals.getActiveIndex(i);
       double  dgd=myvals.getTemporyDerivative(ider);
       myvals.setDerivative( 1, ider, rdenom*(pref*myvals.getDerivative(1,ider)+value*df2*dgd) - (value*pref*dgd)*rdenom2 );
   } 

   return pref*rdenom*value;
}