LCOV - code coverage report
Current view: top level - tools - Communicator.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 84 88 95.5 %
Date: 2026-11-05 10:19:04 Functions: 67 69 97.1 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 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.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       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_HAS_MPI
      25             : #include <mpi.h>
      26             : #endif
      27             : #include <cstdlib>
      28             : #include "Exception.h"
      29             : #include "TypesafePtr.h"
      30             : #include <vector>
      31             : #include <string>
      32             : #include "Vector.h"
      33             : #include "Tensor.h"
      34             : #include "Matrix.h"
      35             : 
      36             : namespace PLMD {
      37             : 
      38             : #ifndef  __PLUMED_HAS_MPI
      39             : /// Surrogate of MPI_Comm when MPI library is not available
      40             : class MPI_Comm {};
      41             : /// Surrogate of MPI_Datatype when MPI library is not available
      42             : class MPI_Datatype {};
      43             : /// Surrogate of MPI_Status when MPI library is not available
      44             : class MPI_Status {};
      45             : /// Surrogate of MPI_Request when MPI library is not available
      46             : class MPI_Request {};
      47             : #endif
      48             : 
      49             : /// \ingroup TOOLBOX
      50             : /// Class containing wrappers to MPI.
      51             : /// All the MPI related stuff is relegated here.
      52             : class Communicator {
      53             : /// Communicator
      54             :   MPI_Comm communicator;
      55             : /// True if this process holds the communicator only as a stand-in.
      56             : /// See setStandIn().
      57             :   bool standIn=false;
      58             : /// In debug builds, raise an error if this communicator is a stand-in.
      59             :   void checkNotStandIn()const;
      60             : /// Function returning the MPI type.
      61             : /// You can use it to access to the MPI type of a C++ type, e.g.
      62             : /// `MPI_Datatype type=getMPIType<double>();`
      63             :   template <class T>
      64             :   static MPI_Datatype getMPIType();
      65             : /// Structure defining a buffer for MPI.
      66             : /// It contains info on the pointed data and its type and size. It is useful to
      67             : /// allow wrapper of MPI functions where the triplet (buffer,type,size)
      68             : /// is grouped into a single object. It can be built starting from
      69             : /// different kinds of data. To implement compatibility of MPI wrappers
      70             : /// with e.g. vectors, add constructors here.
      71             :   struct Data {
      72             :     void*pointer;
      73             :     int size;
      74             :     int nbytes=0;
      75             :     MPI_Datatype type;
      76             : /// Init from pointer and size
      77     2954993 :     template <typename T> Data(T*p,int s): pointer(p), size(s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      78             : /// Init from reference
      79     4249088 :     template <typename T> explicit Data(T&p): pointer(&p), size(1), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      80             : /// Init from pointer to VectorGeneric
      81       11179 :     template <typename T, unsigned n> explicit Data(VectorTyped<T,n> *p,int s): pointer(p), size(n*s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      82             : /// Init from reference to VectorGeneric
      83             :     template <typename T, unsigned n> explicit Data(VectorTyped<T,n> &p): pointer(&p), size(n), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      84             : /// Init from pointer to TensorTyped
      85          16 :     template <typename T, unsigned n,unsigned m> explicit Data(TensorTyped<T,n,m> *p,int s): pointer(p), size(n*m*s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      86             : /// Init from reference to TensorTyped
      87       21142 :     template <typename T, unsigned n,unsigned m> explicit Data(TensorTyped<T,n,m> &p): pointer(&p), size(n*m), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      88             : /// Init from reference to std::vector
      89     2774381 :     template <typename T> explicit Data(std::vector<T>&v) {
      90     2763381 :       Data d(v.data(),v.size());
      91     2774576 :       pointer=d.pointer;
      92     2774576 :       size=d.size;
      93     2774576 :       type=d.type;
      94     2774370 :     }
      95             : /// Init from reference to PLMD::Matrix
      96             :     template <typename T> explicit Data(Matrix<T>&m ) {
      97             :       if(m.nrows()*m.ncols()>0) {
      98             :         Data d(&m(0,0),m.nrows()*m.ncols());
      99             :         pointer=d.pointer;
     100             :         size=d.size;
     101             :         type=d.type;
     102             :       } else {
     103             :         pointer=NULL;
     104             :         size=0;
     105             :       }
     106             :     }
     107             : /// Init from reference to std::string
     108         188 :     explicit Data(std::string&s) {
     109         188 :       if(s.size()>0) {
     110         188 :         Data d(&s[0],s.size());
     111         188 :         pointer=d.pointer;
     112         188 :         size=d.size;
     113         188 :         type=d.type;
     114             :       } else {
     115           0 :         pointer=NULL;
     116           0 :         size=0;
     117             :       }
     118         188 :     }
     119             :   };
     120             : /// Const version of Communicator::Data
     121             : /// See Communicator::Data documentation
     122             :   struct ConstData {
     123             :     const void*pointer;
     124             :     int size;
     125             :     int nbytes=0;
     126             :     MPI_Datatype type;
     127       10597 :     template <typename T> explicit ConstData(const T*p,int s): pointer(p), size(s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     128        2486 :     template <typename T> explicit ConstData(const T&p): pointer(&p), size(1), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     129             :     template <typename T,unsigned n> explicit ConstData(const VectorTyped<T,n> *p,int s): pointer(p), size(n*s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     130             :     template <typename T,unsigned n> explicit ConstData(const VectorTyped<T,n> &p): pointer(&p), size(n), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     131             :     template <typename T, unsigned n,unsigned m> explicit ConstData(const TensorTyped<T,n,m> *p,int s): pointer(p), size(n*m*s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     132             :     template <typename T, unsigned n,unsigned m> explicit ConstData(const TensorTyped<T,n,m> &p): pointer(&p), size(n*m), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     133        6349 :     template <typename T> explicit ConstData(const std::vector<T>&v) {
     134        6349 :       ConstData d(v.data(),v.size());
     135        6349 :       pointer=d.pointer;
     136        6349 :       size=d.size;
     137        6349 :       type=d.type;
     138        6349 :     }
     139             :     template <typename T> explicit ConstData(const Matrix<T>&m ) {
     140             :       if(m.nrows()*m.ncols()>0) {
     141             :         ConstData d(&m(0,0),m.nrows()*m.ncols());
     142             :         pointer=d.pointer;
     143             :         size=d.size;
     144             :         type=d.type;
     145             :       } else {
     146             :         pointer=NULL;
     147             :         size=0;
     148             :       }
     149             :     }
     150          69 :     explicit ConstData(const std::string&s) {
     151          69 :       if(s.size()>0) {
     152          69 :         ConstData d(&s[0],s.size());
     153          69 :         pointer=d.pointer;
     154          69 :         size=d.size;
     155          69 :         type=d.type;
     156             :       } else {
     157           0 :         pointer=NULL;
     158           0 :         size=0;
     159             :       }
     160          69 :     }
     161             :   };
     162             : public:
     163             :   ///Runtime acces to the __PLUMED_HAS_MPI definition
     164             :   static bool plumedHasMPI();
     165             : 
     166             : /// Wrapper class for MPI_Status
     167             :   class Status {
     168             :     int Get_count(MPI_Datatype)const;
     169             :   public:
     170             :     MPI_Status s;
     171             :     template <class T>
     172        8142 :     int Get_count()const {
     173        8142 :       return Get_count(getMPIType<T>());
     174             :     }
     175             :   };
     176             : /// Special status used when status should be ignored.
     177             : /// E.g. `Recv(a,0,1,Communicator::StatusIgnore);`
     178             : /// Notice that this is the default for Recv, so this is equivalent to
     179             : /// `Recv(a,0,1);`
     180             :   static Status StatusIgnore;
     181             : /// Wrapper class for MPI_Request
     182             :   class Request {
     183             :   public:
     184             :     MPI_Request r;
     185             :     void wait(Status&s=StatusIgnore);
     186             :   };
     187             : /// Default constructor
     188             :   Communicator();
     189             : /// Copy constructor.
     190             : /// It effectively "clones" the communicator, providing a new one acting on the same group
     191             :   Communicator(const Communicator&);
     192             : /// Assignment operator.
     193             : /// It effectively "clones" the communicator, providing a new one acting on the same group
     194             :   Communicator& operator=(const Communicator&);
     195             : /// Destructor
     196             :   virtual ~Communicator();
     197             : /// Obtain the rank of the present process
     198             :   int Get_rank()const;
     199             : /// Obtain the number of processes
     200             :   int Get_size()const;
     201             : /// Set from a real MPI communicator.
     202             : /// \param comm MPI communicator
     203             :   void Set_comm(MPI_Comm comm);
     204             : /// Reference to MPI communicator
     205             :   MPI_Comm & Get_comm();
     206             : /// Mark this communicator as a stand-in on this process.
     207             : /// A stand-in is a communicator that other processes were given but this
     208             : /// process was not, so it does not connect this process to the processes it
     209             : /// is meant to connect. This is the case of PLMD::Action::multi_sim_comm on
     210             : /// all the processes of a replica except the first one.
     211             : /// In debug builds, using a stand-in (asking its rank or size, or
     212             : /// communicating over it) raises an error. Set_comm() clears the mark.
     213             :   void setStandIn(bool s);
     214             : /// True if this communicator has been marked as a stand-in with setStandIn().
     215             :   bool isStandIn()const;
     216             : /// Set from a pointer to a real MPI communicator (C).
     217             : /// \param comm Pointer to a C MPI communicator
     218             :   void Set_comm(const TypesafePtr & comm);
     219             : /// Set from a pointer to a real MPI communicator (FORTRAN).
     220             : /// \param comm Pointer to a FORTRAN MPI communicator (INTEGER)
     221             :   void Set_fcomm(const TypesafePtr & comm);
     222             : /// Wrapper to MPI_Abort.
     223             : /// \param code Error code
     224             :   void Abort(int code);
     225             : /// Wrapper to MPI_Barrier
     226             :   void Barrier()const;
     227             : /// Tests if MPI library is initialized
     228             :   static bool initialized();
     229             : /// Wrapper for MPI_Allreduce with MPI_SUM (data struct)
     230             :   void Sum(Data);
     231             : /// Wrapper for MPI_Allreduce with MPI_SUM (pointer)
     232       75492 :   template <class T> void Sum(T*buf,int count) {
     233       75492 :     Sum(Data(buf,count));
     234       75492 :   }
     235             : /// Wrapper for MPI_Allreduce with MPI_SUM (reference)
     236     4490692 :   template <class T> void Sum(T&buf) {
     237     4490692 :     Sum(Data(buf));
     238     4490692 :   }
     239             : /// Wrapper for MPI_Allreduce with MPI_PROD (data struct)
     240             :   void Prod(Data);
     241             : /// Wrapper for MPI_Allreduce with MPI_PROD (pointer)
     242             :   template <class T> void Prod(T*buf,int count) {
     243             :     Prod(Data(buf,count));
     244             :   }
     245             : /// Wrapper for MPI_Allreduce with MPI_PROD (reference)
     246             :   template <class T> void Prod(T&buf) {
     247             :     Prod(Data(buf));
     248             :   }
     249             : /// Wrapper for MPI_Allreduce with MPI_MAX (data struct)
     250             :   void Max(Data);
     251             : /// Wrapper for MPI_Allreduce with MPI_MAX (pointer)
     252           4 :   template <class T> void Max(T*buf,int count) {
     253           4 :     Max(Data(buf,count));
     254           4 :   }
     255             : /// Wrapper for MPI_Allreduce with MPI_MAX (reference)
     256        6386 :   template <class T> void Max(T&buf) {
     257        6386 :     Max(Data(buf));
     258        6386 :   }
     259             : /// Wrapper for MPI_Allreduce with MPI_MIN (data struct)
     260             :   void Min(Data);
     261             : /// Wrapper for MPI_Allreduce with MPI_MIN (pointer)
     262             :   template <class T> void Min(T*buf,int count) {
     263             :     Min(Data(buf,count));
     264             :   }
     265             : /// Wrapper for MPI_Allreduce with MPI_MIN (reference)
     266         235 :   template <class T> void Min(T&buf) {
     267         235 :     Min(Data(buf));
     268         235 :   }
     269             : 
     270             : /// Wrapper for MPI_Bcast (data struct)
     271             :   void Bcast(Data,int);
     272             : /// Wrapper for MPI_Bcast (pointer)
     273          20 :   template <class T> void Bcast(T*buf,int count,int root) {
     274          20 :     Bcast(Data(buf,count),root);
     275          20 :   }
     276             : /// Wrapper for MPI_Bcast (reference)
     277      403800 :   template <class T> void Bcast(T&buf,int root) {
     278      403800 :     Bcast(Data(buf),root);
     279      403800 :   }
     280             : 
     281             : /// Wrapper for MPI_Scatter (data struct)
     282             :   void Scatter(ConstData sendbuf,int sendcount,Data recvbuf,int recvcount,int root);
     283             : /// Wrapper for MPI_Scatter (pointer)
     284           8 :   template <class T,class S> void Scatter(const T*sendbuf,int sendcount,S*recvbuf,int recvcount,int root) {
     285           8 :     Scatter(ConstData(sendbuf,sendcount*Get_size()),sendcount,Data(recvbuf,recvcount),recvcount,root);
     286           8 :   }
     287             : /// Wrapper for MPI_Scatter (reference)
     288             :   template <class T,class S> void Scatter(const T&sendbuf,int sendcount,S&recvbuf,int recvcount,int root) {
     289             :     Scatter(ConstData(sendbuf),sendcount,Data(recvbuf),recvcount,root);
     290             :   }
     291             : 
     292             : /// Wrapper for MPI_Gather (data struct)
     293             :   void Gather(ConstData sendbuf,int sendcount,Data recvbuf,int recvcount,int root);
     294             : /// Wrapper for MPI_Gather (pointer)
     295           8 :   template <class T,class S> void Gather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount,int root) {
     296          16 :     Gather(ConstData(sendbuf,sendcount),sendcount,Data(recvbuf,recvcount*Get_size()),recvcount,root);
     297           8 :   }
     298             : /// Wrapper for MPI_Gather (reference)
     299             :   template <class T,class S> void Gather(const T&sendbuf,int sendcount,S&recvbuf,int recvcount,int root) {
     300             :     Gather(ConstData(sendbuf),sendcount,Data(recvbuf),recvcount,root);
     301             :   }
     302             : 
     303             : /// Wrapper for MPI_Isend (data struct)
     304             :   Request Isend(ConstData,int,int);
     305             : /// Wrapper for MPI_Isend (pointer)
     306       16284 :   template <class T> Request Isend(const T*buf,int count,int source,int tag) {
     307       16284 :     return Isend(ConstData(buf,count),source,tag);
     308             :   }
     309             : /// Wrapper for MPI_Isend (reference)
     310         207 :   template <class T> Request Isend(const T&buf,int source,int tag) {
     311         207 :     return Isend(ConstData(buf),source,tag);
     312             :   }
     313             : 
     314             : /// Wrapper for MPI_Allgatherv (data struct)
     315             :   void Allgatherv(ConstData in,Data out,const int*,const int*);
     316             : /// Wrapper for MPI_Allgatherv (pointer)
     317        3967 :   template <class T,class S> void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs) {
     318        3967 :     Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs);
     319        3967 :   }
     320             : /// Wrapper for MPI_Allgatherv (reference)
     321         414 :   template <class T,class S> void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs) {
     322         414 :     Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs);
     323         414 :   }
     324             : 
     325             : /// Wrapper for MPI_Allgather (data struct)
     326             :   void Allgather(ConstData in,Data out);
     327             : /// Wrapper for MPI_Allgatherv (pointer)
     328         204 :   template <class T,class S> void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount) {
     329         408 :     Allgather(ConstData(sendbuf,sendcount),Data(recvbuf,recvcount*Get_size()));
     330         204 :   }
     331             : /// Wrapper for MPI_Allgatherv (reference)
     332        8145 :   template <class T,class S> void Allgather(const T&sendbuf,S&recvbuf) {
     333       10355 :     Allgather(ConstData(sendbuf),Data(recvbuf));
     334        8145 :   }
     335             : 
     336             : /// Wrapper for MPI_Recv (data struct)
     337             :   void Recv(Data,int,int,Status&s=StatusIgnore);
     338             : /// Wrapper for MPI_Recv (pointer)
     339       16284 :   template <class T> void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore) {
     340       16284 :     Recv(Data(buf,count),source,tag,s);
     341       16284 :   }
     342             : /// Wrapper for MPI_Recv (reference)
     343         207 :   template <class T> void Recv(T&buf,int source,int tag,Status&s=StatusIgnore) {
     344         207 :     Recv(Data(buf),source,tag,s);
     345         207 :   }
     346             : 
     347             : /// Wrapper to MPI_Comm_split
     348             :   void Split(int,int,Communicator&)const;
     349             : };
     350             : 
     351             : }
     352             : 
     353             : #endif

Generated by: LCOV version 1.16