void VectorMultiColvar::addWeightedValueDerivatives( const unsigned& iatom, const unsigned& base_cv_no, const double& weight, multicolvar::MultiColvarFunction* func ){ if( usingLowMem() ){ vecs->recompute( iatom, 1 ); for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( 1, j, 5+j, base_cv_no, weight, func ); } else { for(unsigned j=0;j<getNumberOfQuantities()-5;++j) vecs->chainRuleForComponent( iatom, j, 5+j, base_cv_no, weight, func ); } }
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 HistogramOnGrid::getFinalForces( const std::vector<double>& buffer, std::vector<double>& finalForces ) { if( finalForces.size()!=getAction()->getNumberOfDerivatives() ) finalForces.resize( getAction()->getNumberOfDerivatives() ); // And the final force unsigned nder = getAction()->getNumberOfDerivatives(); // Derivatives due to normalization unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); for(unsigned i=0; i<finalForces.size(); ++i) finalForces[i] = buffer[ bufstart + gridbuf + i ]; // Derivatives due to normalization if( !noAverage() ) { unsigned wderstart = bufstart + gridbuf + nder; double pref=0; for(unsigned ipoint=0; ipoint<getNumberOfPoints(); ++ipoint) { pref += forces[ipoint]*buffer[ bufstart + ipoint*nper ] / buffer[wderstart]; } for(unsigned j=0; j<finalForces.size(); ++j) finalForces[j] -= pref*buffer[ wderstart + 1 + j ]; } }
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 HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const { if( addOneKernelAtATime ) { plumed_dbg_assert( myvals.getNumberOfValues()==2 && !wasforced ); std::vector<double> der( dimension ); for(unsigned i=0; i<dimension; ++i) der[i]=myvals.getDerivative( 1, i ); accumulate( getAction()->getPositionInCurrentTaskList(current), myvals.get(0), myvals.get(1), der, buffer ); } else { plumed_dbg_assert( myvals.getNumberOfValues()==dimension+2 ); std::vector<double> point( dimension ); double weight=myvals.get(0)*myvals.get( 1+dimension ); for(unsigned i=0; i<dimension; ++i) point[i]=myvals.get( 1+i ); // Get the kernel unsigned num_neigh; std::vector<unsigned> neighbors; std::vector<double> der( dimension ); KernelFunctions* kernel=getKernelAndNeighbors( point, num_neigh, neighbors ); // If no kernel normalize the vector so von misses distribution is calculated correctly if( !kernel ) { double norm=0; for(unsigned j=0; j<dimension; ++j) norm += point[j]*point[j]; norm=sqrt( norm ); for(unsigned j=0; j<dimension; ++j) point[j] = point[j] / norm; } if( !kernel && getType()=="flat" ) { plumed_dbg_assert( num_neigh==1 ); accumulate( neighbors[0], weight, 1.0, der, buffer ); } else { double totwforce=0.0; std::vector<double> intforce( 2*dimension, 0.0 ); std::vector<Value*> vv( getVectorOfValues() ); double newval; std::vector<double> xx( dimension ); for(unsigned i=0; i<num_neigh; ++i) { unsigned ineigh=neighbors[i]; if( inactive( ineigh ) ) continue ; getGridPointCoordinates( ineigh, xx ); for(unsigned j=0; j<dimension; ++j) vv[j]->set(xx[j]); if( kernel ) { newval = kernel->evaluate( vv, der, true ); } else { // Evalulate dot product double dot=0; for(unsigned j=0; j<dimension; ++j) { dot+=xx[j]*point[j]; der[j]=xx[j]; } // Von misses distribution for concentration parameter newval = von_misses_norm*exp( von_misses_concentration*dot ); // And final derivatives for(unsigned j=0; j<dimension; ++j) der[j] *= von_misses_concentration*newval; } accumulate( ineigh, weight, newval, der, buffer ); if( wasForced() ) { accumulateForce( ineigh, weight, der, intforce ); totwforce += myvals.get( 1+dimension )*newval*forces[ineigh]; } } if( wasForced() ) { unsigned nder = getAction()->getNumberOfDerivatives(); unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); for(unsigned j=0; j<dimension; ++j) { for(unsigned k=0; k<myvals.getNumberActive(); ++k) { // Minus sign here as we are taking derivative with respect to position of center of kernel NOT derivative wrt to // grid point unsigned kder=myvals.getActiveIndex(k); buffer[ bufstart + gridbuf + kder ] -= intforce[j]*myvals.getDerivative( j+1, kder ); } } // Accumulate the sum of all the weights buffer[ bufstart + gridbuf + nder ] += myvals.get(0); // Add the derivatives of the weights into the force -- this is separate loop as weights of all parts are considered together for(unsigned k=0; k<myvals.getNumberActive(); ++k) { unsigned kder=myvals.getActiveIndex(k); buffer[ bufstart + gridbuf + kder ] += totwforce*myvals.getDerivative( 0, kder ); buffer[ bufstart + gridbuf + nder + 1 + kder ] += myvals.getDerivative( 0, kder ); } } delete kernel; for(unsigned i=0; i<dimension; ++i) delete vv[i]; } } }