void StoreDataVessel::storeDerivatives( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const { plumed_dbg_assert( vecsize>0 && getAction()->derivativesAreRequired() && myelem<getAction()->getFullNumberOfTasks() ); unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); if( getAction()->getFullNumberOfTasks()==getNumberOfStoredValues() ){ der_list[jelem]=myvals.getNumberActive(); unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); for(unsigned j=0;j<myvals.getNumberActive();++j){ der_list[kder] = myvals.getActiveIndex(j); kder++; } } else { // This ensures that active indices are gathered correctly if // we have multiple tasks contributing to a stored quantity unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); for(unsigned j=0;j<myvals.getNumberActive();++j){ bool found=false; unsigned jder = myvals.getActiveIndex(j); for(unsigned k=0;k<der_list[jelem];++k){ if( der_list[kder+k]==jder ){ found=true; break; } } if(!found){ der_list[kder+der_list[jelem]]=jder; der_list[jelem]++; } } } // Store the values of the components and the derivatives for(unsigned icomp=0;icomp<vecsize;++icomp){ unsigned ibuf = bufstart + jelem * ( vecsize*nspace ) + icomp*nspace + 1; for(unsigned j=0;j<myvals.getNumberActive();++j){ unsigned jder=myvals.getActiveIndex(j); buffer[ibuf] += myvals.getDerivative( icomp, jder ); ibuf++; } } }
void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ){ plumed_dbg_assert( myvals.getNumberOfValues()==vecsize && myvals.getNumberOfDerivatives()==getAction()->getNumberOfDerivatives() ); myvals.clearAll(); if( getAction()->lowmem ){ recalculateStoredQuantity( myelem, myvals ); if( normed ) getAction()->normalizeVectorDerivatives( myvals ); } else { unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); // Retrieve the derivatives for elements 0 and 1 - weight and norm for(unsigned icomp=0;icomp<vecsize;++icomp){ unsigned ibuf = jelem * ( vecsize*nspace ) + icomp*nspace + 1; unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); for(unsigned j=0;j<active_der[jelem];++j){ myvals.addDerivative( icomp, active_der[kder], local_buffer[ibuf] ); kder++; ibuf++; } } if( normed ) getAction()->normalizeVectorDerivatives( myvals ); // Now ensure appropriate parts of list are activated myvals.emptyActiveMembers(); unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); for(unsigned j=0;j<active_der[jelem];++j){ myvals.putIndexInActiveArray( active_der[kder] ); kder++; } myvals.sortActiveList(); } }
void StoreDataVessel::resize(){ vecsize=getAction()->getNumberOfQuantities(); plumed_dbg_assert( vecsize>0 ); if( getAction()->lowmem || !getAction()->derivativesAreRequired() ){ nspace = 1; active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); } else { nspace = 1 + getAction()->maxderivatives; active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); } resizeBuffer( getNumberOfStoredValues()*vecsize*nspace ); local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace ); }
void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector<double>& buffer ) const { plumed_dbg_assert( vecsize>0 ); unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); plumed_dbg_assert( jelem<getNumberOfStoredValues() ); unsigned ibuf = bufstart + jelem * vecsize * nspace; for(unsigned icomp=0;icomp<vecsize;++icomp){ buffer[ibuf] += myvals.get(icomp); ibuf+=nspace; } }
void TrigonometricPathVessel::finish( const std::vector<double>& buffer ) { // Store the data calculated during mpi loop StoreDataVessel::finish( buffer ); // Get current value of all arguments for(unsigned i=0; i<cargs.size(); ++i) cargs[i]=mymap->getArgument(i); // Determine closest and second closest point to current position double lambda=mymap->getLambda(); std::vector<double> dist( getNumberOfComponents() ), dist2( getNumberOfComponents() );; retrieveSequentialValue( 0, false, dist ); retrieveSequentialValue( 1, false, dist2 ); iclose1=getStoreIndex(0); iclose2=getStoreIndex(1); double mindist1=dist[0], mindist2=dist2[0]; if( lambda>0.0 ) { mindist1=-std::log( dist[0] ) / lambda; mindist2=-std::log( dist2[0] ) / lambda; } if( mindist2<mindist1 ) { double tmp=mindist1; mindist1=mindist2; mindist2=tmp; iclose1=getStoreIndex(1); iclose2=getStoreIndex(0); } for(unsigned i=2; i<getNumberOfStoredValues(); ++i) { retrieveSequentialValue( i, false, dist ); double ndist=dist[0]; if( lambda>0.0 ) ndist=-std::log( dist[0] ) / lambda; if( ndist<mindist1 ) { mindist2=mindist1; iclose2=iclose1; mindist1=ndist; iclose1=getStoreIndex(i); } else if( ndist<mindist2 ) { mindist2=ndist; iclose2=getStoreIndex(i); } } // And find third closest point int isign = iclose1 - iclose2; if( isign>1 ) isign=1; else if( isign<-1 ) isign=-1; int iclose3 = iclose1 + isign; double v2v2; // We now have to compute vectors connecting the three closest points to the // new point double v1v1 = (mymap->getReferenceConfiguration( iclose1 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack1, true ); double v3v3 = (mymap->getReferenceConfiguration( iclose2 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack3, true ); if( iclose3<0 || iclose3>=mymap->getFullNumberOfTasks() ) { ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); v2v2=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), conf2->getReferenceArguments(), mypack2, true ); (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), conf2->getReferenceArguments(), false, projdir ); } else { ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose3 ); v2v2=(mymap->getReferenceConfiguration( iclose1 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), conf2->getReferenceArguments(), mypack2, true ); (mymap->getReferenceConfiguration( iclose1 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), conf2->getReferenceArguments(), false, projdir ); } // Stash derivatives of v1v1 for(unsigned i=0; i<mymap->getNumberOfArguments(); ++i) mypack1_stashd_args[i]=mypack1.getArgumentDerivative(i); if( mymap->getNumberOfAtoms()>0 ) { ReferenceAtoms* at = dynamic_cast<ReferenceAtoms*>( mymap->getReferenceConfiguration( iclose1 ) ); const std::vector<double> & displace( at->getDisplace() ); for(unsigned i=0; i<mymap->getNumberOfAtoms(); ++i) { mypack1_stashd_atoms[i]=mypack1.getAtomDerivative(i); mypack1.getAtomsDisplacementVector()[i] /= displace[i]; } } // Calculate the dot product of v1 with v2 double v1v2 = (mymap->getReferenceConfiguration(iclose1))->projectDisplacementOnVector( projdir, mymap->getArguments(), cargs, mypack1 ); // This computes s value double spacing = mymap->getPropertyValue( iclose1, (mymap->property.begin())->first ) - mymap->getPropertyValue( iclose2, (mymap->property.begin())->first ); double root = sqrt( v1v2*v1v2 - v2v2 * ( v1v1 - v3v3) ); dx = 0.5 * ( (root + v1v2) / v2v2 - 1.); double path_s = mymap->getPropertyValue(iclose1, (mymap->property.begin())->first ) + spacing * dx; sp->set( path_s ); double fact = 0.25*spacing / v2v2; // Derivative of s wrt arguments for(unsigned i=0; i<mymap->getNumberOfArguments(); ++i) { sp->setDerivative( i, fact*( mypack2.getArgumentDerivative(i) + (v2v2 * (-mypack1_stashd_args[i] + mypack3.getArgumentDerivative(i)) + v1v2*mypack2.getArgumentDerivative(i) )/root ) ); } // Derivative of s wrt atoms unsigned narg=mymap->getNumberOfArguments(); Tensor vir; vir.zero(); fact = 0.5*spacing / v2v2; if( mymap->getNumberOfAtoms()>0 ) { for(unsigned i=0; i<mymap->getNumberOfAtoms(); ++i) { Vector ader = fact*(( v1v2*mypack1.getAtomDerivative(i) + 0.5*v2v2*(-mypack1_stashd_atoms[i] + mypack3.getAtomDerivative(i) ) )/root + mypack1.getAtomDerivative(i) ); for(unsigned k=0; k<3; ++k) sp->setDerivative( narg+3*i+k, ader[k] ); vir-=Tensor( mymap->getPosition(i), ader ); } // Set the virial unsigned nbase=narg+3*mymap->getNumberOfAtoms(); for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) sp->setDerivative( nbase+3*i+j, vir(i,j) ); } // Now compute z value ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); double v4v4=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), conf2->getReferenceArguments(), mypack2, true ); // Extract vector connecting frames (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), conf2->getReferenceArguments(), false, projdir ); // Calculate projection of vector on line connnecting frames double proj = (mymap->getReferenceConfiguration(iclose1))->projectDisplacementOnVector( projdir, mymap->getArguments(), cargs, mypack1 ); double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; // Derivatives for z path path_z = sqrt(path_z); zp->set( path_z ); vir.zero(); for(unsigned i=0; i<mymap->getNumberOfArguments(); ++i) zp->setDerivative( i, (mypack1_stashd_args[i] - 2*dx*mypack1.getArgumentDerivative(i))/(2.0*path_z) ); // Derivative wrt atoms if( mymap->getNumberOfAtoms()>0 ) { for(unsigned i=0; i<mymap->getNumberOfAtoms(); ++i) { Vector dxder; for(unsigned k=0; k<3; ++k) dxder[k] = ( 2*v4v4*dx - 2*proj )*spacing*sp->getDerivative( narg + 3*i+k ); Vector ader = ( mypack1_stashd_atoms[i] - 2.*dx*mypack1.getAtomDerivative(i) + dxder )/ (2.0*path_z); for(unsigned k=0; k<3; ++k) zp->setDerivative( narg+3*i+k, ader[k] ); vir-=Tensor( mymap->getPosition(i), ader ); } // Set the virial unsigned nbase=narg+3*mymap->getNumberOfAtoms(); for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) zp->setDerivative( nbase+3*i+j, vir(i,j) ); } }