Exemple #1
0
double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
   if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; 

   unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities();

   std::vector<double> orient0( ncomp ), orient1( ncomp );
   getVectorForTask( myatoms.getIndex(0), true, orient0 ); 
   getVectorForTask( myatoms.getIndex(1), true, orient1 );

   double dot=0;
   for(unsigned k=2;k<orient0.size();++k){
       dot+=orient0[k]*orient1[k];
   }

   if( !doNotCalculateDerivatives() ){
     unsigned nder=myatoms.getNumberOfDerivatives();   //getNumberOfDerivatives();
     MultiValue myder0(ncomp,nder), myder1(ncomp,nder);
     getVectorDerivatives( myatoms.getIndex(0), true, myder0 );
     mergeVectorDerivatives( 1, 2, orient1.size(), myatoms.getIndex(0), orient1, myder0, myatoms );
     getVectorDerivatives( myatoms.getIndex(1), true, myder1 ); 
     mergeVectorDerivatives( 1, 2, orient0.size(), myatoms.getIndex(1), orient0, myder1, myatoms );
   }

   return dot;
}
double InterMolecularTorsions::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
  Vector v1, v2, dv1, dv2, dconn, conn = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );

  // Retrieve vectors
  std::vector<double> orient0( 5 ), orient1( 5 );
  getInputData( 0, true, myatoms, orient0 );
  getInputData( 1, true, myatoms, orient1 );
  for(unsigned i=0; i<3; ++i) { v1[i]=orient0[2+i]; v2[i]=orient1[2+i]; }
  if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0;

  // Evaluate angle
  Torsion t; double angle = t.compute( v1, conn, v2, dv1, dconn, dv2 );
  for(unsigned i=0; i<3; ++i) { orient0[i+2]=dv1[i]; orient1[i+2]=dv2[i]; }

  // And accumulate derivatives
  if( !doNotCalculateDerivatives() ) {
    MultiValue& myder0=getInputDerivatives( 0, true, myatoms );
    mergeInputDerivatives( 1, 2, orient1.size(), 0, orient0, myder0, myatoms );
    MultiValue& myder1=getInputDerivatives( 1, true, myatoms );
    mergeInputDerivatives( 1, 2, orient0.size(), 1, orient1, myder1, myatoms );
    addAtomDerivatives( 1, 0, -dconn, myatoms ); addAtomDerivatives( 1, 1, dconn, myatoms );
    myatoms.addBoxDerivatives( 1, -extProduct( conn, dconn ) );
  }

  return angle;
}
OrientationSphere::OrientationSphere(const ActionOptions&ao):
Action(ao),
MultiColvarFunction(ao)
{
  // Resize everything that stores a vector now that we know the 
  // number of components
  unsigned ncomponents=getBaseMultiColvar(0)->getNumberOfQuantities() - 5;
  catom_orient.resize( ncomponents ); 
  catom_der.resize( ncomponents );
  this_orient.resize( ncomponents ); 

  // Weight of this does not have derivatives
  weightHasDerivatives=false;
  // Read in the switching function
  std::string sw, errors; parse("SWITCH",sw);
  if(sw.length()>0){
     switchingFunction.set(sw,errors);
  } else { 
     double r_0=-1.0, d_0; int nn, mm;
     parse("NN",nn); parse("MM",mm);
     parse("R_0",r_0); parse("D_0",d_0);
     if( r_0<0.0 ) error("you must set a value for R_0");
     switchingFunction.set(nn,mm,r_0,d_0);
  }
  log.printf("  degree of overlap in orientation between central molecule and those within %s\n",( switchingFunction.description() ).c_str() );
  // Set the link cell cutoff
  setLinkCellCutoff( 2.*switchingFunction.inverse( getTolerance() ) );

  // Finish the setup of the object
  buildSymmetryFunctionLists();

  // And check everything has been read in correctly
  checkRead();
}
void ClusteringBase::turnOnDerivatives() {
  // Check base multicolvar isn't density probably other things shouldn't be allowed here as well
  if( (getAdjacencyVessel()->getMatrixAction())->getNumberOfBaseMultiColvars()>0 ) {
    if( getBaseMultiColvar(0)->isDensity() ) error("DFS clustering cannot be differentiated if base multicolvar is DENSITY");
  }

  // Ensure that derivatives are turned on in base classes
  ActionWithInputMatrix::turnOnDerivatives();
}
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;
}
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;
}