void ActionWithVessel::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector<unsigned>& indices ){ indices[jstore]=getNumberOfDerivatives(); if( indices[jstore]>maxder ) error("too many derivatives to store. Run with LOWMEM"); unsigned kder = ntotal + jstore*getNumberOfDerivatives(); for(unsigned jder=0;jder<getNumberOfDerivatives();++jder){ indices[ kder ] = jder; kder++; } }
void VectorMultiColvar::addForcesOnAtoms( const std::vector<double>& inforces ){ plumed_dbg_assert( inforces.size()==getNumberOfDerivatives() ); std::vector<double> oldforces( getNumberOfDerivatives() ); getForcesFromVessels( oldforces ); for(unsigned i=0;i<getNumberOfDerivatives();++i) oldforces[i]+=inforces[i]; setForcesOnAtoms( oldforces ); }
void ActionWithVessel::readVesselKeywords(){ // Set maxderivatives if it is too big if( maxderivatives>getNumberOfDerivatives() ) maxderivatives=getNumberOfDerivatives(); // Loop over all keywords find the vessels and create appropriate functions for(unsigned i=0;i<keywords.size();++i){ std::string thiskey,input; thiskey=keywords.getKeyword(i); // Check if this is a key for a vessel if( vesselRegister().check(thiskey) ){ plumed_assert( keywords.style(thiskey,"vessel") ); bool dothis=false; parseFlag(thiskey,dothis); if(dothis) addVessel( thiskey, input ); parse(thiskey,input); if(input.size()!=0){ addVessel( thiskey, input ); } else { for(unsigned i=1;;++i){ if( !parseNumbered(thiskey,i,input) ) break; std::string ss; Tools::convert(i,ss); addVessel( thiskey, input, i ); input.clear(); } } } } // Make sure all vessels have had been resized at start if( functions.size()>0 ) resizeFunctions(); }
void BridgedMultiColvarFunction::clearDerivativesAfterTask( const unsigned& ider ){ unsigned vstart=getNumberOfDerivatives()*ider; if( derivativesAreRequired() ){ // Clear atom derivatives for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned iatom=vstart+3*atoms_with_derivatives[i]; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); } // Clear virial contribution unsigned nvir=vstart+3*mycolv->getNumberOfAtoms(); for(unsigned j=0;j<9;++j){ setElementDerivative( nvir, 0.0 ); nvir++; } // Clear derivatives of local atoms for(unsigned j=0;j<getNumberOfAtoms();++j){ setElementDerivative( nvir, 0.0 ); nvir++; setElementDerivative( nvir, 0.0 ); nvir++; setElementDerivative( nvir, 0.0 ); nvir++; } plumed_dbg_assert( (nvir-vstart)==getNumberOfDerivatives() ); } // Clear values thisval_wasset[ider]=false; setElementValue( ider, 0.0 ); thisval_wasset[ider]=false; }
void ActionWithVessel::resizeFunctions(){ unsigned bufsize=0; for(unsigned i=0;i<functions.size();++i){ functions[i]->bufstart=bufsize; functions[i]->resize(); bufsize+=functions[i]->bufsize; } thisval.resize( getNumberOfQuantities() ); thisval_wasset.resize( getNumberOfQuantities(), false ); derivatives.resize( getNumberOfQuantities()*getNumberOfDerivatives(), 0.0 ); buffer.resize( bufsize ); tmpforces.resize( getNumberOfDerivatives() ); }
void ActionWithVessel::chainRuleForElementDerivatives( const unsigned& iout, const unsigned& ider, const unsigned& stride, const unsigned& off, const double& df, Vessel* valout ){ plumed_dbg_assert( off<stride ); current_buffer_stride=stride; current_buffer_start=valout->bufstart + stride*(getNumberOfDerivatives()+1)*iout + stride + off; mergeDerivatives( ider, df ); }
Vector BridgedMultiColvarFunction::retrieveCentralAtomPos(){ if( atomsWithCatomDer.getNumberActive()==0 ){ Vector cvec = mycolv->retrieveCentralAtomPos(); // Copy the value and derivatives from the MultiColvar atomsWithCatomDer.emptyActiveMembers(); for(unsigned i=0;i<3;++i){ setElementValue( getCentralAtomElementIndex() + i, mycolv->getElementValue( mycolv->getCentralAtomElementIndex() + i ) ); unsigned nbase = ( getCentralAtomElementIndex() + i)*getNumberOfDerivatives(); unsigned nbas2 = ( mycolv->getCentralAtomElementIndex() + i )*mycolv->getNumberOfDerivatives(); for(unsigned j=0;j<mycolv->atomsWithCatomDer.getNumberActive();++j){ unsigned n=mycolv->atomsWithCatomDer[j], nx=3*n; atomsWithCatomDer.activate(n); addElementDerivative(nbase + nx + 0, mycolv->getElementDerivative(nbas2 + nx + 0) ); addElementDerivative(nbase + nx + 1, mycolv->getElementDerivative(nbas2 + nx + 1) ); addElementDerivative(nbase + nx + 2, mycolv->getElementDerivative(nbas2 + nx + 2) ); } } for(unsigned j=0;j<mycolv->atomsWithCatomDer.getNumberActive();++j) atomsWithCatomDer.updateIndex( mycolv->atomsWithCatomDer[j] ); atomsWithCatomDer.sortActiveList(); return cvec; } Vector cvec; for(unsigned i=0;i<3;++i) cvec[i]=getElementValue(1+i); return cvec; }
void Histogram::apply() { if( !myhist->wasForced() ) return ; in_apply=true; // Run the loop to calculate the forces runAllTasks(); finishAveraging(); // We now need to retrieve the buffer and set the forces on the atoms myhist->applyForce( forcesToApply ); // Now make the forces make sense for the virial unsigned fbase=0, tbase=0, vbase = getNumberOfDerivatives() - myvessels.size()*9; for(unsigned i=vbase; i<vbase+9; ++i) finalForces[i]=0.0; for(unsigned i=0; i<myvessels.size(); ++i) { for(unsigned j=0; j<myvessels[i]->getNumberOfDerivatives()-9; ++j) { finalForces[fbase + j] = forcesToApply[tbase + j]; } unsigned k=0; for(unsigned j=myvessels[i]->getNumberOfDerivatives()-9; j<myvessels[i]->getNumberOfDerivatives(); ++j) { finalForces[vbase + k] += forcesToApply[tbase + j]; k++; } fbase += myvessels[i]->getNumberOfDerivatives() - 9; tbase += myvessels[i]->getNumberOfDerivatives(); } // And set the final forces on the atoms setForcesOnAtoms( finalForces ); // Reset everything for next regular loop in_apply=false; }
void SecondaryStructureRMSD::readBackboneAtoms( const std::string& moltype, std::vector<unsigned>& chain_lengths ){ std::vector<SetupMolInfo*> moldat=plumed.getActionSet().select<SetupMolInfo*>(); if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); std::vector<std::string> resstrings; parseVector( "RESIDUES", resstrings ); if( !verbose_output ){ if(resstrings[0]=="all"){ log.printf(" examining all possible secondary structure combinations\n"); } else { log.printf(" examining secondary struture in residue poritions : %s \n",resstrings[0].c_str() ); for(unsigned i=1;i<resstrings.size();++i) log.printf(", %s",resstrings[i].c_str() ); log.printf("\n"); } } std::vector< std::vector<AtomNumber> > backatoms; moldat[0]->getBackbone( resstrings, moltype, backatoms ); chain_lengths.resize( backatoms.size() ); for(unsigned i=0;i<backatoms.size();++i){ chain_lengths[i]=backatoms[i].size(); for(unsigned j=0;j<backatoms[i].size();++j) all_atoms.push_back( backatoms[i][j] ); } ActionAtomistic::requestAtoms( all_atoms ); forcesToApply.resize( getNumberOfDerivatives() ); }
void MultiColvarBase::quotientRule( const unsigned& uder, const unsigned& vder, const unsigned& iout ){ unsigned ustart=uder*getNumberOfDerivatives(); unsigned vstart=vder*getNumberOfDerivatives(); unsigned istart=iout*getNumberOfDerivatives(); double weight = getElementValue( vder ), pref = getElementValue( uder ) / (weight*weight); if( !doNotCalculateDerivatives() ){ for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned n=3*atoms_with_derivatives[i], nx=n, ny=n+1, nz=n+2; setElementDerivative( istart + nx, getElementDerivative(ustart+nx) / weight - pref*getElementDerivative(vstart+nx) ); setElementDerivative( istart + ny, getElementDerivative(ustart+ny) / weight - pref*getElementDerivative(vstart+ny) ); setElementDerivative( istart + nz, getElementDerivative(ustart+nz) / weight - pref*getElementDerivative(vstart+nz) ); } unsigned vbase=3*getNumberOfAtoms(); for(unsigned i=0;i<9;++i){ setElementDerivative( istart + vbase + i, getElementDerivative(ustart+vbase+i) / weight - pref*getElementDerivative(vstart+vbase+i) ); } } thisval_wasset[iout]=false; setElementValue( iout, getElementValue(uder) / weight ); }
void ActionWithValue::turnOnDerivatives() { // Turn on the derivatives noderiv=false; // Resize the derivatives for(unsigned i=0; i<values.size(); ++i) values[i]->resizeDerivatives( getNumberOfDerivatives() ); // And turn on the derivatives in all actions on which we are dependent for(unsigned i=0; i<getDependencies().size(); ++i) { ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] ); if(vv) vv->turnOnDerivatives(); } }
bool ActionWithVessel::getForcesFromVessels( std::vector<double>& forcesToApply ){ plumed_dbg_assert( forcesToApply.size()==getNumberOfDerivatives() ); forcesToApply.assign( forcesToApply.size(),0.0 ); bool wasforced=false; for(unsigned i=0;i<getNumberOfVessels();++i){ if( (functions[i]->applyForce( tmpforces )) ){ wasforced=true; for(unsigned j=0;j<forcesToApply.size();++j) forcesToApply[j]+=tmpforces[j]; } } return wasforced; }
void MultiColvarBase::mergeDerivatives( const unsigned& ider, const double& df ){ unsigned vstart=getNumberOfDerivatives()*ider; for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned iatom=3*atoms_with_derivatives[i]; accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); iatom++; accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); iatom++; accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); } unsigned nvir=3*getNumberOfAtoms(); for(unsigned j=0;j<9;++j){ accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++; } }
void StoreCentralAtomsVessel::addAtomsDerivatives( const unsigned& iatom, const unsigned& jout, const unsigned& base_cv_no, const Vector& df, MultiColvarFunction* funcout ){ plumed_dbg_assert( mycolv->derivativesAreRequired() ); for(unsigned ider=0;ider<getNumberOfDerivatives(iatom);ider+=3){ for(unsigned i=0;i<3;++i) tmpdf[i]=df[0]; funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( iatom, ider+0 ), chainRule(iatom, ider+0, tmpdf) ); for(unsigned i=0;i<3;++i) tmpdf[i]=df[1]; funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( iatom, ider+1 ), chainRule(iatom, ider+1, tmpdf) ); for(unsigned i=0;i<3;++i) tmpdf[i]=df[2]; funcout->addStoredDerivative( jout, base_cv_no, getStoredIndex( iatom, ider+2 ), chainRule(iatom, ider+2, tmpdf) ); } }
void BridgedMultiColvarFunction::mergeDerivatives( const unsigned& ider, const double& df ){ unsigned vstart=getNumberOfDerivatives()*ider; // Merge atom derivatives for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned iatom=3*atoms_with_derivatives[i]; accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); iatom++; accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); iatom++; accumulateDerivative( iatom, df*getElementDerivative(vstart+iatom) ); } // Merge virial derivatives unsigned nvir=3*mycolv->getNumberOfAtoms(); for(unsigned j=0;j<9;++j){ accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++; } // Merge local atom derivatives for(unsigned j=0;j<getNumberOfAtoms();++j){ accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++; accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++; accumulateDerivative( nvir, df*getElementDerivative(vstart+nvir) ); nvir++; } plumed_dbg_assert( nvir==getNumberOfDerivatives() ); }
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; }
void MultiColvarBase::clearDerivativesAfterTask( const unsigned& ider ){ unsigned vstart=getNumberOfDerivatives()*ider; thisval_wasset[ider]=false; setElementValue( ider, 0.0 ); thisval_wasset[ider]=false; if( ider>1 && ider<5 && derivativesAreRequired() ){ for(unsigned i=0;i<atomsWithCatomDer.getNumberActive();++i){ unsigned iatom=vstart+3*atomsWithCatomDer[i]; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); } } else if( derivativesAreRequired() ) { for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned iatom=vstart+3*atoms_with_derivatives[i]; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); } unsigned nvir=vstart+3*getNumberOfAtoms(); for(unsigned j=0;j<9;++j){ setElementDerivative( nvir, 0.0 ); nvir++; } } }
void ActionWithVessel::runAllTasks(){ if( getExchangeStep() && nactive_tasks!=fullTaskList.size() ) error("contributors must be unlocked during exchange steps"); plumed_massert( functions.size()>0, "you must have a call to readVesselKeywords somewhere" ); unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); if(serial){ stride=1; rank=0; } // Make sure jobs are done if(timers) stopwatch.start("1 Prepare Tasks"); doJobsRequiredBeforeTaskList(); if(timers) stopwatch.stop("1 Prepare Tasks"); // Get number of threads for OpenMP unsigned nt=OpenMP::getNumThreads(); if( nt*stride*10>nactive_tasks) nt=nactive_tasks/stride/10; if( nt==0 ) nt=1; // Get size for buffer unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); // Clear buffer buffer.assign( buffer.size(), 0.0 ); // Switch off calculation of derivatives in main loop if( dertime_can_be_off ) dertime=false; // std::vector<unsigned> der_list; // if( mydata ) der_list.resize( mydata->getSizeOfDerivativeList(), 0 ); // Build storage stuff for loop // std::vector<double> buffer( bufsize, 0.0 ); if(timers) stopwatch.start("2 Loop over tasks"); #pragma omp parallel num_threads(nt) { std::vector<double> omp_buffer; if( nt>1 ) omp_buffer.resize( bufsize, 0.0 ); MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); myvals.clearAll(); bvals.clearAll(); #pragma omp for nowait for(unsigned i=rank;i<nactive_tasks;i+=stride){ // Calculate the stuff in the loop for this action performTask( indexOfTaskInFullList[i], partialTaskList[i], myvals ); // Weight should be between zero and one plumed_dbg_assert( myvals.get(0)>=0 && myvals.get(0)<=1.0 ); // Check for conditions that allow us to just to skip the calculation // the condition is that the weight of the contribution is low // N.B. Here weights are assumed to be between zero and one if( myvals.get(0)<tolerance ){ // Deactivate task if it is less than the neighbor list tolerance if( myvals.get(0)<nl_tolerance && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); // Clear the derivatives myvals.clearAll(); continue; } // Now calculate all the functions // If the contribution of this quantity is very small at neighbour list time ignore it // untill next neighbour list time if( nt>1 ){ if( !calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, omp_buffer, der_list ) && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); } else { if( !calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer, der_list ) && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); } // Clear the value myvals.clearAll(); } #pragma omp critical if(nt>1) for(unsigned i=0;i<bufsize;++i) buffer[i]+=omp_buffer[i]; } if(timers) stopwatch.stop("2 Loop over tasks"); // Turn back on derivative calculation dertime=true; if(timers) stopwatch.start("3 MPI gather"); // MPI Gather everything if( !serial && buffer.size()>0 ) comm.Sum( buffer ); // MPI Gather index stores if( mydata && !lowmem && !noderiv ){ comm.Sum( der_list ); mydata->setActiveValsAndDerivatives( der_list ); } // Update the elements that are makign contributions to the sum here // this causes problems if we do it in prepare if( !serial && contributorsAreUnlocked ) comm.Sum( taskFlags ); if(timers) stopwatch.stop("3 MPI gather"); if(timers) stopwatch.start("4 Finishing computations"); finishComputations( buffer ); if(timers) stopwatch.stop("4 Finishing computations"); }
void ActionWithVessel::clearDerivativesAfterTask( const unsigned& ider ){ unsigned kstart=ider*getNumberOfDerivatives(); thisval[ider]=0.0; thisval_wasset[ider]=false; for(unsigned j=0;j<getNumberOfDerivatives();++j) derivatives[ kstart+j ]=0.0; }
void MultiColvarBase::turnOnDerivatives(){ ActionWithValue::turnOnDerivatives(); needsDerivatives(); forcesToApply.resize( getNumberOfDerivatives() ); }
void ActionWithVessel::chainRuleForElementDerivatives( const unsigned& iout, const unsigned& ider, const double& df, Vessel* valout ){ current_buffer_stride=1; current_buffer_start=valout->bufstart + (getNumberOfDerivatives()+1)*iout + 1; mergeDerivatives( ider, df ); }
void ActionWithVessel::mergeDerivatives( const unsigned& ider, const double& df ){ unsigned nder=getNumberOfDerivatives(), vstart=nder*ider; for(unsigned i=0;i<getNumberOfDerivatives();++i){ accumulateDerivative( i, df*derivatives[vstart+i] ); } }