LCOV - code coverage report
Current view: top level - tools - Communicator.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 99 120 82.5 %
Date: 2024-10-11 08:09:47 Functions: 28 35 80.0 %

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

Generated by: LCOV version 1.15