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 ContactAlignedMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { double f_dot, dot_df; std::vector<double> orient0(ncomp), orient1(ncomp); getOrientationVector( myatoms.getIndex(0), true, orient0 ); getOrientationVector( myatoms.getIndex(1), true, orient1 ); double dot=0; for(unsigned k=2;k<orient0.size();++k) dot+=orient0[k]*orient1[k]; f_dot=0.5*( 1 + dot ); dot_df=0.5; // Retrieve the weight of the connection double weight = myatoms.getValue(0); myatoms.setValue(0,1.0); if( !doNotCalculateDerivatives() ){ Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( distance.modulo(), dfunc ); addAtomDerivatives( 1, 0, (-dfunc)*f_dot*distance, myatoms ); addAtomDerivatives( 1, 1, (+dfunc)*f_dot*distance, myatoms ); myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) ); // Add derivatives of orientation for(unsigned k=2;k<orient0.size();++k){ orient0[k]*=sw*dot_df; orient1[k]*=sw*dot_df; } addOrientationDerivatives( 1, 0, orient1, myatoms ); addOrientationDerivatives( 1, 1, orient0, myatoms ); } return weight*f_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; }