LCOV - code coverage report
Current view: top level - tools - Communicator.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 102 122 83.6 %
Date: 2024-10-18 14:00:25 Functions: 30 36 83.3 %

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

Generated by: LCOV version 1.16