LCOV - code coverage report
Current view: top level - tools - Communicator.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 100 118 84.7 %
Date: 2019-08-13 10:15:31 Functions: 30 35 85.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2019 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             : #include "Communicator.h"
      23             : #include "Exception.h"
      24             : #include "AtomNumber.h"
      25             : #include <cstdlib>
      26             : #include <cstring>
      27             : 
      28             : using namespace std;
      29             : 
      30             : namespace PLMD {
      31             : 
      32       11858 : Communicator::Communicator()
      33             : #ifdef __PLUMED_HAS_MPI
      34       11858 :   : communicator(MPI_COMM_SELF)
      35             : #endif
      36             : {
      37       11858 : }
      38             : 
      39           0 : Communicator::Communicator(const Communicator&pc) {
      40           0 :   Set_comm(pc.communicator);
      41           0 : }
      42             : 
      43             : Communicator::Status Communicator::StatusIgnore;
      44             : 
      45           0 : Communicator& Communicator::operator=(const Communicator&pc) {
      46           0 :   if (this != &pc) {
      47           0 :     Set_comm(pc.communicator);
      48             :   }
      49           0 :   return *this;
      50             : }
      51             : 
      52     6244618 : int Communicator::Get_rank()const {
      53     6244618 :   int r=0;
      54             : #ifdef __PLUMED_HAS_MPI
      55     6244618 :   if(initialized()) MPI_Comm_rank(communicator,&r);
      56             : #endif
      57     6244618 :   return r;
      58             : }
      59             : 
      60     2364828 : int Communicator::Get_size()const {
      61     2364828 :   int s=1;
      62             : #ifdef __PLUMED_HAS_MPI
      63     2364828 :   if(initialized()) MPI_Comm_size(communicator,&s);
      64             : #endif
      65     2364828 :   return s;
      66             : }
      67             : 
      68        1942 : void Communicator::Set_comm(MPI_Comm c) {
      69             : #ifdef __PLUMED_HAS_MPI
      70        1942 :   if(initialized()) {
      71        1587 :     if(communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator);
      72        1587 :     if(c!=MPI_COMM_SELF) MPI_Comm_dup(c,&communicator);
      73             :   }
      74             : #else
      75             :   (void) c;
      76             : #endif
      77        1942 : }
      78             : 
      79       19621 : Communicator::~Communicator() {
      80             : #ifdef __PLUMED_HAS_MPI
      81       11858 :   if(initialized() && communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator);
      82             : #endif
      83       19621 : }
      84             : 
      85        1186 : void Communicator::Set_comm(void*val) {
      86             : #ifdef __PLUMED_HAS_MPI
      87        1186 :   plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
      88        1186 :   if(val) Set_comm(*(MPI_Comm*)val);
      89             : #else
      90             :   (void) val;
      91             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
      92             : #endif
      93        1186 : }
      94             : 
      95           0 : void Communicator::Set_fcomm(void*val) {
      96             : #ifdef __PLUMED_HAS_MPI
      97           0 :   plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
      98           0 :   if(val) {
      99           0 :     MPI_Comm comm=MPI_Comm_f2c(*(MPI_Fint*)val);
     100           0 :     Set_comm(comm);
     101             :   }
     102             : #else
     103             :   (void) val;
     104             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
     105             : #endif
     106           0 : }
     107             : 
     108           0 : void Communicator::Abort(int errorcode) {
     109             : #ifdef __PLUMED_HAS_MPI
     110           0 :   if(initialized()) {
     111           0 :     MPI_Abort(communicator,errorcode);
     112             :   }
     113           0 :   std::exit(errorcode);
     114             : #else
     115             :   std::exit(errorcode);
     116             : #endif
     117             : }
     118             : 
     119     4204752 : void Communicator::Bcast(Data data,int root) {
     120             : #if defined(__PLUMED_HAS_MPI)
     121     4204752 :   if(initialized()) MPI_Bcast(data.pointer,data.size,data.type,root,communicator);
     122             : #else
     123             :   (void) data;
     124             :   (void) root;
     125             : #endif
     126     4204752 : }
     127             : 
     128     4232447 : void Communicator::Sum(Data data) {
     129             : #if defined(__PLUMED_HAS_MPI)
     130     4232447 :   if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_SUM,communicator);
     131             : #else
     132             :   (void) data;
     133             : #endif
     134     4232447 : }
     135             : 
     136           3 : void Communicator::Prod(Data data) {
     137             : #if defined(__PLUMED_HAS_MPI)
     138           3 :   if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_PROD,communicator);
     139             : #else
     140             :   (void) data;
     141             : #endif
     142           3 : }
     143             : 
     144           3 : void Communicator::Max(Data data) {
     145             : #if defined(__PLUMED_HAS_MPI)
     146           3 :   if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_MAX,communicator);
     147             : #else
     148             :   (void) data;
     149             : #endif
     150           3 : }
     151             : 
     152           3 : void Communicator::Min(Data data) {
     153             : #if defined(__PLUMED_HAS_MPI)
     154           3 :   if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_MIN,communicator);
     155             : #else
     156             :   (void) data;
     157             : #endif
     158           3 : }
     159             : 
     160       15206 : Communicator::Request Communicator::Isend(ConstData data,int source,int tag) {
     161             :   Request req;
     162             : #ifdef __PLUMED_HAS_MPI
     163       15206 :   plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
     164       15206 :   void*s=const_cast<void*>((const void*)data.pointer);
     165       15206 :   MPI_Isend(s,data.size,data.type,source,tag,communicator,&req.r);
     166             : #else
     167             :   (void) data;
     168             :   (void) source;
     169             :   (void) tag;
     170             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
     171             : #endif
     172       15206 :   return req;
     173             : }
     174             : 
     175       16805 : void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs) {
     176       16805 :   void*s=const_cast<void*>((const void*)in.pointer);
     177       16805 :   void*r=const_cast<void*>((const void*)out.pointer);
     178             :   int*rc=const_cast<int*>(recvcounts);
     179             :   int*di=const_cast<int*>(displs);
     180             : #if defined(__PLUMED_HAS_MPI)
     181       16805 :   if(initialized()) {
     182       16804 :     if(s==NULL)s=MPI_IN_PLACE;
     183       16804 :     MPI_Allgatherv(s,in.size,in.type,r,rc,di,out.type,communicator);
     184             :   } else {
     185           1 :     plumed_assert(in.nbytes==out.nbytes);
     186           1 :     plumed_assert(in.size==out.size);
     187           1 :     plumed_assert(rc);
     188           1 :     plumed_assert(rc[0]==in.size);
     189           1 :     plumed_assert(di);
     190           1 :     if(s) std::memcpy(static_cast<char*>(r)+displs[0]*in.nbytes,s,in.size*in.nbytes);
     191             :   }
     192             : #else
     193             :   plumed_assert(in.nbytes==out.nbytes);
     194             :   plumed_assert(in.size==out.size);
     195             :   plumed_assert(rc);
     196             :   plumed_assert(rc[0]==in.size);
     197             :   plumed_assert(di);
     198             :   if(s) std::memcpy(static_cast<char*>(r)+displs[0]*in.nbytes,s,in.size*in.nbytes);
     199             : #endif
     200       16805 : }
     201             : 
     202        4836 : void Communicator::Allgather(ConstData in,Data out) {
     203        4836 :   void*s=const_cast<void*>((const void*)in.pointer);
     204        4836 :   void*r=const_cast<void*>((const void*)out.pointer);
     205             : #if defined(__PLUMED_HAS_MPI)
     206        4836 :   if(initialized()) {
     207        4835 :     if(s==NULL)s=MPI_IN_PLACE;
     208        4835 :     MPI_Allgather(s,in.size,in.type,r,out.size/Get_size(),out.type,communicator);
     209             :   } else {
     210           1 :     plumed_assert(in.nbytes==out.nbytes);
     211           1 :     plumed_assert(in.size==out.size);
     212           1 :     if(s) std::memcpy(r,s,in.size*in.nbytes);
     213             :   }
     214             : #else
     215             :   plumed_assert(in.nbytes==out.nbytes);
     216             :   plumed_assert(in.size==out.size);
     217             :   if(s) std::memcpy(r,s,in.size*in.nbytes);
     218             : #endif
     219        4836 : }
     220             : 
     221       15206 : void Communicator::Recv(Data data,int source,int tag,Status&status) {
     222             : #ifdef __PLUMED_HAS_MPI
     223       15206 :   plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
     224       15206 :   if(&status==&StatusIgnore) MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,MPI_STATUS_IGNORE);
     225        7541 :   else                       MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,&status.s);
     226             : #else
     227             :   (void) data;
     228             :   (void) source;
     229             :   (void) tag;
     230             :   (void) status;
     231             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
     232             : #endif
     233       15206 : }
     234             : 
     235             : 
     236             : 
     237             : 
     238             : 
     239     4100598 : void Communicator::Barrier()const {
     240             : #ifdef __PLUMED_HAS_MPI
     241     4100598 :   if(initialized()) MPI_Barrier(communicator);
     242             : #endif
     243     4100598 : }
     244             : 
     245        1376 : MPI_Comm & Communicator::Get_comm() {
     246        1376 :   return communicator;
     247             : }
     248             : 
     249    21238130 : bool Communicator::initialized() {
     250             : #if defined(__PLUMED_HAS_MPI)
     251    21238130 :   int flag=0;
     252    21238130 :   MPI_Initialized(&flag);
     253    21238130 :   if(flag) return true;
     254    12672035 :   else return false;
     255             : #endif
     256             :   return false;
     257             : }
     258             : 
     259       14814 : void Communicator::Request::wait(Status&s) {
     260             : #ifdef __PLUMED_HAS_MPI
     261       14814 :   plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
     262       14814 :   if(&s==&StatusIgnore) MPI_Wait(&r,MPI_STATUS_IGNORE);
     263           1 :   else MPI_Wait(&r,&s.s);
     264             : #else
     265             :   (void) s;
     266             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
     267             : #endif
     268       14814 : }
     269             : 
     270             : #ifdef __PLUMED_HAS_MPI
     271           0 : template<> MPI_Datatype Communicator::getMPIType<float>() { return MPI_FLOAT;}
     272     4334308 : template<> MPI_Datatype Communicator::getMPIType<double>() { return MPI_DOUBLE;}
     273       47947 : template<> MPI_Datatype Communicator::getMPIType<int>()   { return MPI_INT;}
     274         234 : template<> MPI_Datatype Communicator::getMPIType<char>()   { return MPI_CHAR;}
     275       39953 : template<> MPI_Datatype Communicator::getMPIType<unsigned>()   { return MPI_UNSIGNED;}
     276           8 : template<> MPI_Datatype Communicator::getMPIType<AtomNumber>()   { return MPI_UNSIGNED;}
     277     4095993 : template<> MPI_Datatype Communicator::getMPIType<long unsigned>()   { return MPI_UNSIGNED_LONG;}
     278             : #else
     279             : template<> MPI_Datatype Communicator::getMPIType<float>() { return MPI_Datatype();}
     280             : template<> MPI_Datatype Communicator::getMPIType<double>() { return MPI_Datatype();}
     281             : template<> MPI_Datatype Communicator::getMPIType<int>() { return MPI_Datatype();}
     282             : template<> MPI_Datatype Communicator::getMPIType<char>() { return MPI_Datatype();}
     283             : template<> MPI_Datatype Communicator::getMPIType<unsigned>() { return MPI_Datatype();}
     284             : template<> MPI_Datatype Communicator::getMPIType<AtomNumber>()   { return MPI_Datatype();}
     285             : template<> MPI_Datatype Communicator::getMPIType<long unsigned>() { return MPI_Datatype();}
     286             : #endif
     287             : 
     288             : 
     289         370 : void Communicator::Split(int color,int key,Communicator&pc)const {
     290             : #ifdef __PLUMED_HAS_MPI
     291         370 :   MPI_Comm_split(communicator,color,key,&pc.communicator);
     292             : #else
     293             :   (void) color;
     294             :   (void) key;
     295             :   (void) pc;
     296             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
     297             : #endif
     298         370 : }
     299             : 
     300        7541 : int Communicator::Status::Get_count(MPI_Datatype type)const {
     301             :   int i;
     302             : #ifdef __PLUMED_HAS_MPI
     303        7541 :   plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
     304        7541 :   MPI_Get_count(const_cast<MPI_Status*>(&s),type,&i);
     305             : #else
     306             :   i=0;
     307             :   plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
     308             : #endif
     309        7541 :   return i;
     310             : }
     311             : 
     312        5874 : }
     313             : 

Generated by: LCOV version 1.14