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 ContactMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { if( !doNotCalculateDerivatives() ){ Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); addAtomDerivatives( 1, 0, (-dfunc)*distance, myatoms ); addAtomDerivatives( 1, 1, (+dfunc)*distance, myatoms ); myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); } double val=myatoms.getValue(0); myatoms.setValue(0,1.0); return val; }
double TopologyMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype ); // Initialise to zero density on all bins for(unsigned bin=0; bin<maxbins; ++bin) myatoms.setValue(bin+1,0); // Calculate whether or not atoms 1 and 2 are within cutoff (can use delta here as pbc are done in atom setup) Vector d1 = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double d1_len = d1.modulo(); d1 = d1 / d1_len; // Convert vector into director AtomNumber a1 = myatoms.getAbsoluteIndex( 0 ); AtomNumber a2 = myatoms.getAbsoluteIndex( 1 ); for(unsigned i=2; i<myatoms.getNumberOfAtoms(); ++i) { AtomNumber a3 = myatoms.getAbsoluteIndex( i ); if( a3!=a1 && a3!=a2 ) calculateForThreeAtoms( i, d1, d1_len, bead, myatoms ); } // std::vector<double> binvals( 1+maxbins ); for(unsigned i=1;i<maxbins;++i) binvals[i]=myatoms.getValue(i); // unsigned ii; double fdf; //std::cout<<"HELLO DENSITY "<<myatoms.getIndex(0)<<" "<<myatoms.getIndex(1)<<" "<<transformStoredValues( binvals, ii, fdf )<<std::endl; // Now find the element for which the density is maximal unsigned vout=2; double max=myatoms.getValue( 2 ); for(unsigned i=3; i<myatoms.getUnderlyingMultiValue().getNumberOfValues()-1; ++i) { if( myatoms.getValue(i)>max ) { max=myatoms.getValue(i); vout=i; } } // Calculate value and derivative of switching function between atoms 1 and 2 double dfuncl, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( d1_len, dfuncl ); // Transform the density double df, tsw = threshold_switch.calculate( max, df ); if( !doNotCalculateDerivatives() ) { // Factor of d1_len is required here because d1 is normalized d1 *= d1_len; addAtomDerivatives( 2+maxbins, 0, -dfuncl*d1, myatoms ); addAtomDerivatives( 2+maxbins, 1, dfuncl*d1, myatoms ); myatoms.addBoxDerivatives( 2+maxbins, (-dfuncl)*Tensor(d1,d1) ); // Update active atoms so that next bit works updateActiveAtoms( myatoms ); // Now finish caclulation of derivatives MultiValue& myvals=myatoms.getUnderlyingMultiValue(); for(unsigned jd=0; jd<myvals.getNumberActive(); ++jd) { unsigned ider=myvals.getActiveIndex(jd); myvals.addDerivative( 1, ider, sw*df*max*myvals.getDerivative( vout, ider ) + tsw*myvals.getDerivative( 2+maxbins, ider ) ); } } return sw*tsw; }
void ContactAlignedMatrix::calculateWeight( const unsigned& taskCode, multicolvar::AtomValuePack& myatoms ) const { 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 ); myatoms.setValue(0,sw); }