22 #ifndef __PLUMED_tools_DynamicList_h
23 #define __PLUMED_tools_DynamicList_h
134 template <
typename T>
137 template <
typename U>
158 DynamicList():nactive(0),nprocessors(1),rank(0),allWereActivated(false) {}
161 plumed_dbg_assert( i<nactive );
162 return all[ active[i] ];
166 plumed_dbg_assert( i<all.size() );
176 bool isActive(
const unsigned& )
const;
203 unsigned linkIndex(
const unsigned& ii )
const ;
206 template <
typename T>
208 std::vector<T> this_active(nactive);
209 for(
unsigned k=0;k<nactive;++k) this_active[k]=all[ active[k] ];
213 template <
typename T>
215 all.resize(0); translator.resize(0);
216 onoff.resize(0); active.resize(0);
219 template <
typename T>
221 return (onoff[i]>0 && onoff[i]%nprocessors==0);
224 template <
typename T>
229 template <
typename T>
234 template <
typename T>
236 all.push_back(ii); active.resize( all.size() );
237 translator.push_back( all.size()-1 ); onoff.push_back(0);
240 template <
typename T>
245 template <
typename T>
247 plumed_dbg_massert(ii<all.size(),
"ii is out of bounds");
248 plumed_dbg_assert( allWereActivated );
249 if( onoff[ii]==0 || onoff[ii]%nprocessors!=0 ) return ;
250 if( rank==0 ) onoff[ii]=nprocessors-1;
251 else onoff[ii]=nprocessors-rank;
254 template <
typename T>
256 for(
unsigned i=0;i<nactive;++i) onoff[ active[i] ]= 0;
258 for(
unsigned i=0;i<onoff.size();++i) plumed_dbg_assert( onoff[i]==0 );
262 template <
typename T>
264 plumed_dbg_massert(ii<all.size(),
"ii is out of bounds");
265 plumed_dbg_assert( !allWereActivated );
266 onoff[ii]=nprocessors;
269 template <
typename T>
271 for(
unsigned i=0;i<onoff.size();++i) onoff[i]=nprocessors;
272 updateActiveMembers(); allWereActivated=
true;
275 template <
typename T>
277 plumed_massert( comm.
Get_size()==nprocessors,
"error missing a call to DynamicList::setupMPICommunication");
278 comm.
Sum(&onoff[0],onoff.size());
280 for(
unsigned i=0;i<all.size();++i)
if( onoff[i]>0 && onoff[i]%nprocessors==0 ){ onoff[i]=nprocessors; }
281 updateActiveMembers();
284 template <
typename T>
287 for(
unsigned i=0;i<all.size();++i){
288 if( onoff[i]>0 && onoff[i]%nprocessors==0 ){ translator[i]=kk; active[kk]=i; kk++; }
290 nactive=kk; allWereActivated=
false;
293 template <
typename T>
298 template <
typename T>
300 if( onoff[ii]>0 && onoff[ii]%nprocessors==0 ){
301 translator[nactive]=nactive; active[nactive]=ii; nactive++;
305 template <
typename T>
307 std::sort( active.begin(), active.begin()+nactive );
308 for(
unsigned i=0;i<nactive;++i) translator[ active[i] ]=i;
311 template <
typename T>
313 plumed_dbg_assert( onoff[ii]>0 && onoff[ii]%nprocessors==0 );
314 return translator[ii];
317 template <
typename U>
320 unsigned bufsize=0;
unsigned size=comm.
Get_size();
321 for(
unsigned i=0;i<ll.size();++i){
322 plumed_dbg_massert( ll[i].nprocessors==size,
"missing a call to DynamicList::setupMPICommunication" );
323 bufsize+=ll[i].onoff.size();
325 std::vector<unsigned> buffer( bufsize );
328 for(
unsigned i=0;i<ll.size();++i){
329 for(
unsigned j=0;j<ll[i].onoff.size();++j){ buffer[bufsize]=ll[i].onoff[j]; bufsize++; }
332 comm.
Sum(&buffer[0],buffer.size());
335 for(
unsigned i=0;i<ll.size();++i){
336 for(
unsigned j=0;j<ll[i].onoff.size();++j){
337 if( buffer[bufsize]>0 && buffer[bufsize]%size==0 ) ll[i].onoff[j]=size;
338 else ll[i].onoff[j]=size-1;
342 for(
unsigned i=0;i<ll.size();++i) ll[i].updateActiveMembers();
void setupMPICommunication(Communicator &comm)
Setup MPI communication if things are activated/deactivated on different nodes.
std::vector< T > all
This is the list of all the relevent members.
std::vector< int > translator
This translates a position from all to active.
void mpi_gatherActiveMembers(Communicator &comm, std::vector< DynamicList< U > > &ll)
std::vector< T > retrieveActiveList()
Retriee the list of active objects.
bool allWereActivated
This is a flag that is used internally to ensure that dynamic lists are being used properly...
void deactivate(const unsigned ii)
Make a particular element inactive.
T operator[](const unsigned &i) const
An operator that returns the element from the current active list.
A class for storing a list that changes which members are active as a function of time...
Class containing wrappers to MPI.
T operator()(const unsigned &i) const
An operator that returns the element from the full list (used in neighbour lists) ...
void activate(const unsigned ii)
Make something active.
void updateActiveMembers()
Get the list of active members.
DynamicList()
Constructor.
void sortActiveList()
This sorts the elements in the active list.
unsigned linkIndex(const unsigned &ii) const
Return the index of this atom.
void updateIndex(const unsigned &ii)
This can be used for a fast version of updateActiveMembers in which only a subset of the indexes are ...
void clear()
Clear the list.
int Get_rank() const
Obtain the rank of the present process.
void emptyActiveMembers()
Empty the list of active members.
unsigned nactive
The current number of active members.
void addIndexToList(const T &ii)
Add something to the active list.
bool isActive(const unsigned &) const
Find out if a member is active.
std::vector< unsigned > onoff
This tells us what members of all are on/off at any given time.
std::vector< unsigned > active
This is the list of active members.
friend void mpi_gatherActiveMembers(Communicator &, std::vector< DynamicList< U > > &)
This gathers data split across nodes list of Dynamic lists.
unsigned rank
The rank of the node we are on.
unsigned fullSize() const
Return the total number of elements in the list.
int Get_size() const
Obtain the number of processes.
void deactivateAll()
Make everything in the list inactive.
void activateAll()
Make everything in the list active.
void Sum(T *, int)
Wrapper for MPI_Allreduce with MPI_SUM.
unsigned getNumberActive() const
Return the number of elements that are currently active.
unsigned nprocessors
the number of processors the jobs in the Dynamic list are distributed across