All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Communicator.h
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 The plumed team
3  (see the PEOPLE file at the root of the distribution for a list of names)
4 
5  See http://www.plumed-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
8 
9  plumed is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  plumed is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #ifndef __PLUMED_tools_Communicator_h
23 #define __PLUMED_tools_Communicator_h
24 #ifdef __PLUMED_MPI
25 #include <mpi.h>
26 #endif
27 #include <cstdlib>
28 #include "Exception.h"
29 
30 namespace PLMD{
31 
32 #ifndef __PLUMED_MPI
33 /// Surrogate of MPI types when MPI library is not available
34  class MPI_Comm {
35  int dummy;
36  public:
37  MPI_Comm():dummy(0){};
38  };
39 #endif
40 
41 /// \ingroup TOOLBOX
42 /// Class containing wrappers to MPI.
43 /// All the MPI related stuff is relegated here.
45 /// Communicator
47 #ifdef __PLUMED_MPI
48  template <class T>
49  static MPI_Datatype getMPIType();
50 #endif
51 public:
52  class Status{
53  public:
54 #ifdef __PLUMED_MPI
55  MPI_Status s;
56 #endif
57  template <class T>
58  int Get_count()const;
59  };
60  class Request{
61  public:
62 #ifdef __PLUMED_MPI
63  MPI_Request r;
64 #endif
65  void wait();
66  void wait(Status&);
67  };
68 /// Default constructor
69  Communicator();
70 /// Copy constructor.
71 /// It effectively "clones" the communicator, providing a new one acting on the same group
72  Communicator(const Communicator&);
73 /// Assignment operator.
74 /// It effectively "clones" the communicator, providing a new one acting on the same group
76 /// Destructor
77  virtual ~Communicator();
78 /// Obtain the rank of the present process
79  int Get_rank()const;
80 /// Obtain the number of processes
81  int Get_size()const;
82 /// Set from a real MPI communicator
83  void Set_comm(MPI_Comm);
84 /// Reference to MPI communicator
85  MPI_Comm & Get_comm();
86 /// Set from a pointer to a real MPI communicator (C)
87 /// \param comm Pointer to a C MPI communicator
88  void Set_comm(void*comm);
89 /// Set from a pointer to a real MPI communicator (FORTRAN)
90 /// \param comm Pointer to a FORTRAN MPI communicator (INTEGER)
91  void Set_fcomm(void*comm);
92 /// Wrapper to MPI_Abort
93  void Abort(int);
94 /// Wrapper to MPI_Barrier
95  void Barrier()const;
96 /// Tests if MPI library is initialized
97  static bool initialized();
98 
99 /// Returns MPI_COMM_WORLD if MPI is initialized, otherwise the default communicator
100  static Communicator & Get_world();
101 
102 /// Wrapper for MPI_Allreduce with MPI_SUM
103  template <class T>
104  void Sum(T*,int);
105 /// Wrapper for MPI_Allgatherv
106  template <class T>
107  void Allgatherv(const T*,int,T*,const int*,const int*);
108  template <class T>
109  void Allgather(const T*,int,T*,int);
110  template <class T>
111  Request Isend(const T*,int,int,int);
112  template <class T>
113  void Recv(T*,int,int,int,Status&);
114  template <class T>
115  void Recv(T*,int,int,int);
116  template <class T>
117  void Bcast(T*,int,int);
118 
119 /// Wrapper to MPI_Comm_split
120  void Split(int,int,Communicator&)const;
121 };
122 
123 template<class T>
124 void Communicator::Sum(T*b,int count){
125 #if defined(__PLUMED_MPI)
126  if(initialized()) MPI_Allreduce(MPI_IN_PLACE,b,count,getMPIType<T>(),MPI_SUM,communicator);
127 #else
128  (void) b;
129  (void) count;
130 #endif
131 }
132 
133 template<class T>
134 void Communicator::Bcast(T*b,int count,int root){
135 #if defined(__PLUMED_MPI)
136  if(initialized()) MPI_Bcast(b,count,getMPIType<T>(),root,communicator);
137 #else
138  (void) b;
139  (void) count;
140  (void) root;
141 #endif
142 }
143 
144 
145 template<class T>
146 void Communicator::Allgatherv(const T*sendbuf,int sendcount,T*recvbuf,const int*recvcounts,const int*displs){
147 #if defined(__PLUMED_MPI)
148  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
149  void*s=const_cast<void*>((const void*)sendbuf);
150  void*r=const_cast<void*>((const void*)recvbuf);
151  int*rc=const_cast<int*>(recvcounts);
152  int*di=const_cast<int*>(displs);
153  if(s==NULL)s=MPI_IN_PLACE;
154  MPI_Allgatherv(s,sendcount,getMPIType<T>(),r,rc,di,getMPIType<T>(),communicator);
155 #else
156  (void) sendbuf;
157  (void) sendcount;
158  (void) recvbuf;
159  (void) recvcounts;
160  (void) displs;
161  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
162 #endif
163 }
164 
165 template<class T>
166 void Communicator::Allgather(const T*sendbuf,int sendcount,T*recvbuf,int recvcount){
167 #if defined(__PLUMED_MPI)
168  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
169  void*s=const_cast<void*>((const void*)sendbuf);
170  void*r=const_cast<void*>((const void*)recvbuf);
171  if(s==NULL)s=MPI_IN_PLACE;
172  MPI_Allgather(s,sendcount,getMPIType<T>(),r,recvcount,getMPIType<T>(),communicator);
173 #else
174  (void) sendbuf;
175  (void) sendcount;
176  (void) recvbuf;
177  (void) recvcount;
178  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
179 #endif
180 }
181 
182 template <class T>
183 Communicator::Request Communicator::Isend(const T*buf,int count,int source,int tag){
184  Request req;
185 #ifdef __PLUMED_MPI
186  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
187  void*s=const_cast<void*>((const void*)buf);
188  MPI_Isend(s,count,getMPIType<T>(),source,tag,communicator,&req.r);
189 #else
190  (void) buf;
191  (void) count;
192  (void) source;
193  (void) tag;
194  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
195 #endif
196  return req;
197 }
198 
199 template <class T>
200 void Communicator::Recv(T*buf,int count,int source,int tag,Status&status){
201 #ifdef __PLUMED_MPI
202  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
203  MPI_Recv(buf,count,getMPIType<T>(),source,tag,communicator,&status.s);
204 #else
205  (void) buf;
206  (void) count;
207  (void) source;
208  (void) tag;
209  (void) status;
210  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
211 #endif
212 }
213 
214 template <class T>
215 void Communicator::Recv(T*buf,int count,int source,int tag){
216 #ifdef __PLUMED_MPI
217  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
218  MPI_Recv(buf,count,getMPIType<T>(),source,tag,communicator,MPI_STATUS_IGNORE);
219 #else
220  (void) buf;
221  (void) count;
222  (void) source;
223  (void) tag;
224  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
225 #endif
226 }
227 
228 template<class T>
230  int i;
231 #ifdef __PLUMED_MPI
232  plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
233  MPI_Get_count(const_cast<MPI_Status*>(&s),getMPIType<T>(),&i);
234 #else
235  i=0;
236  plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
237 #endif
238  return i;
239 }
240 
241 
242 
243 }
244 
245 #endif
void Split(int, int, Communicator &) const
Wrapper to MPI_Comm_split.
static bool initialized()
Tests if MPI library is initialized.
virtual ~Communicator()
Destructor.
void Bcast(T *, int, int)
Definition: Communicator.h:134
MPI_Comm & Get_comm()
Reference to MPI communicator.
Class containing wrappers to MPI.
Definition: Communicator.h:44
void Allgather(const T *, int, T *, int)
Definition: Communicator.h:166
int Get_rank() const
Obtain the rank of the present process.
static Communicator & Get_world()
Returns MPI_COMM_WORLD if MPI is initialized, otherwise the default communicator. ...
void Recv(T *, int, int, int, Status &)
Definition: Communicator.h:200
Communicator & operator=(const Communicator &)
Assignment operator.
void Barrier() const
Wrapper to MPI_Barrier.
void Set_comm(MPI_Comm)
Set from a real MPI communicator.
Surrogate of MPI types when MPI library is not available.
Definition: Communicator.h:34
int Get_size() const
Obtain the number of processes.
void Set_fcomm(void *comm)
Set from a pointer to a real MPI communicator (FORTRAN)
void Allgatherv(const T *, int, T *, const int *, const int *)
Wrapper for MPI_Allgatherv.
Definition: Communicator.h:146
void Sum(T *, int)
Wrapper for MPI_Allreduce with MPI_SUM.
Definition: Communicator.h:124
Communicator()
Default constructor.
Request Isend(const T *, int, int, int)
Definition: Communicator.h:183
void Abort(int)
Wrapper to MPI_Abort.
MPI_Comm communicator
Communicator.
Definition: Communicator.h:46