MultiValue& ActionWithInputMatrix::getInputDerivatives( const unsigned& ind, const bool& normed, const multicolvar::AtomValuePack& myatoms ) const {
  if( (mymatrix->function)->mybasemulticolvars.size()==0  ) {
    MultiValue& myder=mymatrix->getTemporyMultiValue(0);
    if( myder.getNumberOfValues()!=2 || myder.getNumberOfDerivatives()!=(mymatrix->function)->getNumberOfDerivatives() ) {
      myder.resize( 2, (mymatrix->function)->getNumberOfDerivatives() );
    }
    myder.clearAll();
    MultiValue myvals( (mymatrix->function)->getNumberOfQuantities(), (mymatrix->function)->getNumberOfDerivatives() );
    for(unsigned i=0; i<mymatrix->getNumberOfColumns(); ++i) {
      if( mymatrix->undirectedGraph() && ind==i ) continue;
      addConnectionDerivatives( ind, i, myvals, myder );
    }
    myder.updateDynamicList(); return myder;
  }
  return (mymatrix->function)->getInputDerivatives( ind, normed, myatoms );
}
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");
}