LCOV - code coverage report
Current view: top level - src/mpiwrap - cp_mpi.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 51.4 % 290 149
Test Date: 2026-09-24 01:27:39 Functions: 87.5 % 32 28

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2026 CP2K developers group <https://cp2k.org>              */
       4              : /*                                                                            */
       5              : /*  SPDX-License-Identifier: BSD-3-Clause                                     */
       6              : /*----------------------------------------------------------------------------*/
       7              : #include "cp_mpi.h"
       8              : 
       9              : #include <assert.h>
      10              : #include <omp.h>
      11              : #include <stdio.h>
      12              : #include <stdlib.h>
      13              : #include <string.h>
      14              : 
      15              : #if defined(__parallel)
      16              : static bool mpi_initialized_by_cp2k = false;
      17              : static bool mpi_attached_by_cp2k = false;
      18              : 
      19              : /*******************************************************************************
      20              :  * \brief Check given MPI status and upon failure abort with a nice message.
      21              :  * \author Ole Schuett
      22              :  ******************************************************************************/
      23              : #define CHECK(CMD)                                                             \
      24              :   do {                                                                         \
      25              :     const int error = (CMD);                                                   \
      26              :     if (MPI_SUCCESS != error) {                                                \
      27              :       fprintf(stderr, "MPI error #%i in %s:%i\n", error, __FILE__, __LINE__);  \
      28              :       MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);                                 \
      29              :     }                                                                          \
      30              :   } while (0)
      31              : 
      32              : /*******************************************************************************
      33              :  * \brief Abort if an MPI lifecycle operation is called from a parallel region.
      34              :  ******************************************************************************/
      35      4908520 : static void assert_outside_parallel(const char *routine_name) {
      36      4908520 :   if (omp_in_parallel()) {
      37            0 :     fprintf(stderr, "%s must be called outside an OpenMP parallel region.\n",
      38              :             routine_name);
      39            0 :     abort();
      40              :   }
      41      4908520 : }
      42              : 
      43              : /*******************************************************************************
      44              :  * \brief Return a human-readable MPI thread-support level.
      45              :  ******************************************************************************/
      46            0 : static const char *thread_level_name(const int level) {
      47            0 :   switch (level) {
      48              :   case MPI_THREAD_SINGLE:
      49              :     return "MPI_THREAD_SINGLE";
      50            0 :   case MPI_THREAD_FUNNELED:
      51            0 :     return "MPI_THREAD_FUNNELED";
      52            0 :   case MPI_THREAD_SERIALIZED:
      53            0 :     return "MPI_THREAD_SERIALIZED";
      54            0 :   case MPI_THREAD_MULTIPLE:
      55            0 :     return "MPI_THREAD_MULTIPLE";
      56            0 :   default:
      57            0 :     return "unknown";
      58              :   }
      59              : }
      60              : 
      61              : /*******************************************************************************
      62              :  * \brief Abort unless MPI provides MPI_THREAD_MULTIPLE support.
      63              :  ******************************************************************************/
      64            0 : static void require_thread_multiple(const int provided) {
      65            0 :   if (provided < MPI_THREAD_MULTIPLE) {
      66            0 :     fprintf(stderr, "CP2K requires MPI_THREAD_MULTIPLE, but MPI provides %s.\n",
      67              :             thread_level_name(provided));
      68            0 :     MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
      69            0 :     abort();
      70              :   }
      71            0 : }
      72              : #endif
      73              : 
      74              : /*******************************************************************************
      75              :  * \brief Initialize MPI with MPI_THREAD_MULTIPLE or attach to an active MPI.
      76              :  * \author Ole Schuett
      77              :  ******************************************************************************/
      78            2 : void cp_mpi_init(int *argc, char ***argv) {
      79              : #if defined(__parallel)
      80            0 :   assert_outside_parallel("cp_mpi_init");
      81            0 :   if (mpi_attached_by_cp2k) {
      82            0 :     fprintf(stderr, "cp_mpi_init must only be called once per lifecycle.\n");
      83            0 :     abort();
      84              :   }
      85              : 
      86            0 :   int finalized, initialized, provided;
      87            0 :   CHECK(MPI_Finalized(&finalized));
      88            0 :   if (finalized) {
      89            0 :     fprintf(stderr, "cp_mpi_init cannot be called after MPI_Finalize.\n");
      90            0 :     abort();
      91              :   }
      92              : 
      93            0 :   CHECK(MPI_Initialized(&initialized));
      94            0 :   if (initialized) {
      95            0 :     CHECK(MPI_Query_thread(&provided));
      96              :   } else {
      97            0 :     CHECK(MPI_Init_thread(argc, argv, MPI_THREAD_MULTIPLE, &provided));
      98            0 :     mpi_initialized_by_cp2k = true;
      99              :   }
     100            0 :   require_thread_multiple(provided);
     101            0 :   mpi_attached_by_cp2k = true;
     102              : #else
     103            2 :   (void)argc; // mark used
     104            2 :   (void)argv;
     105              : #endif
     106            2 : }
     107              : 
     108              : /*******************************************************************************
     109              :  * \brief Detach from MPI and finalize it only if cp_mpi_init initialized it.
     110              :  * \author Ole Schuett
     111              :  ******************************************************************************/
     112            2 : void cp_mpi_finalize(void) {
     113              : #if defined(__parallel)
     114            0 :   assert_outside_parallel("cp_mpi_finalize");
     115            0 :   if (!mpi_attached_by_cp2k) {
     116            0 :     fprintf(stderr, "cp_mpi_finalize called without a matching cp_mpi_init.\n");
     117            0 :     abort();
     118              :   }
     119              : 
     120            0 :   int finalized;
     121            0 :   CHECK(MPI_Finalized(&finalized));
     122            0 :   if (finalized) {
     123            0 :     fprintf(stderr, "MPI was finalized before cp_mpi_finalize.\n");
     124            0 :     abort();
     125              :   }
     126            0 :   if (mpi_initialized_by_cp2k) {
     127            0 :     CHECK(MPI_Finalize());
     128            0 :     mpi_initialized_by_cp2k = false;
     129              :   }
     130            0 :   mpi_attached_by_cp2k = false;
     131              : #endif
     132            2 : }
     133              : 
     134              : /*******************************************************************************
     135              :  * \brief Returns MPI_COMM_WORLD.
     136              :  * \author Ole Schuett
     137              :  ******************************************************************************/
     138           10 : cp_mpi_comm_t cp_mpi_get_comm_world(void) {
     139              : #if defined(__parallel)
     140           10 :   return MPI_COMM_WORLD;
     141              : #else
     142            0 :   return -1;
     143              : #endif
     144              : }
     145              : 
     146              : /*******************************************************************************
     147              :  * \brief Wrapper around MPI_Comm_f2c.
     148              :  * \author Ole Schuett
     149              :  ******************************************************************************/
     150      1260426 : cp_mpi_comm_t cp_mpi_comm_f2c(const int fortran_comm) {
     151              : #if defined(__parallel)
     152              :   // Attempt to support "no MPI" if __parallel is defined (0 -> MPI_COMM_NULL).
     153      1260422 :   return 0 != fortran_comm ? MPI_Comm_f2c(fortran_comm) : MPI_COMM_NULL;
     154              : #else
     155            4 :   (void)fortran_comm; // mark used
     156            4 :   return -1;
     157              : #endif
     158              : }
     159              : 
     160              : /*******************************************************************************
     161              :  * \brief Wrapper around MPI_Comm_c2f.
     162              :  * \author Ole Schuett
     163              :  ******************************************************************************/
     164            2 : int cp_mpi_comm_c2f(const cp_mpi_comm_t comm) {
     165              : #if defined(__parallel)
     166            2 :   return MPI_Comm_c2f(comm);
     167              : #else
     168            0 :   (void)comm; // mark used
     169            0 :   return -1;
     170              : #endif
     171              : }
     172              : 
     173              : /*******************************************************************************
     174              :  * \brief Wrapper around MPI_Comm_rank.
     175              :  * \author Ole Schuett
     176              :  ******************************************************************************/
     177      3681392 : int cp_mpi_comm_rank(const cp_mpi_comm_t comm) {
     178              : #if defined(__parallel)
     179      3681392 :   int rank = 0;
     180      3681392 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     181      3681392 :     CHECK(MPI_Comm_rank(comm, &rank));
     182              :   }
     183      3681392 :   return rank;
     184              : #else
     185            0 :   (void)comm; // mark used
     186            0 :   return 0;
     187              : #endif
     188              : }
     189              : 
     190              : /*******************************************************************************
     191              :  * \brief Wrapper around MPI_Comm_size.
     192              :  * \author Ole Schuett
     193              :  ******************************************************************************/
     194      3681534 : int cp_mpi_comm_size(const cp_mpi_comm_t comm) {
     195              : #if defined(__parallel)
     196      3681534 :   int nranks = 1;
     197      3681534 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     198      3681534 :     CHECK(MPI_Comm_size(comm, &nranks));
     199              :   }
     200      3681534 :   return nranks;
     201              : #else
     202            0 :   (void)comm; // mark used
     203            0 :   return 1;
     204              : #endif
     205              : }
     206              : 
     207              : /*******************************************************************************
     208              :  * \brief Wrapper around MPI_Barrier; a null communicator is a no-op.
     209              :  ******************************************************************************/
     210            6 : void cp_mpi_barrier(const cp_mpi_comm_t comm) {
     211              : #if defined(__parallel)
     212            6 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     213            6 :     CHECK(MPI_Barrier(comm));
     214              :   }
     215              : #else
     216            0 :   (void)comm; // mark used
     217              : #endif
     218            6 : }
     219              : 
     220              : /*******************************************************************************
     221              :  * \brief Wrapper around MPI_Dims_create.
     222              :  * \author Ole Schuett
     223              :  ******************************************************************************/
     224            0 : void cp_mpi_dims_create(const int nnodes, const int ndims, int dims[]) {
     225              : #if defined(__parallel)
     226            0 :   CHECK(MPI_Dims_create(nnodes, ndims, dims));
     227              : #else
     228            0 :   dims[0] = nnodes;
     229            0 :   for (int i = 1; i < ndims; i++) {
     230            0 :     dims[i] = 1;
     231              :   }
     232              : #endif
     233            0 : }
     234              : 
     235              : /*******************************************************************************
     236              :  * \brief Wrapper around MPI_Cart_create.
     237              :  * \author Ole Schuett
     238              :  ******************************************************************************/
     239            0 : cp_mpi_comm_t cp_mpi_cart_create(const cp_mpi_comm_t comm_old, const int ndims,
     240              :                                  const int dims[], const int periods[],
     241              :                                  const int reorder) {
     242              : #if defined(__parallel)
     243            0 :   assert_outside_parallel("cp_mpi_cart_create");
     244            0 :   cp_mpi_comm_t comm_cart;
     245            0 :   CHECK(MPI_Cart_create(comm_old, ndims, dims, periods, reorder, &comm_cart));
     246            0 :   return comm_cart;
     247              : #else
     248            0 :   (void)comm_old; // mark used
     249            0 :   (void)ndims;
     250            0 :   (void)dims;
     251            0 :   (void)periods;
     252            0 :   (void)reorder;
     253            0 :   return -1;
     254              : #endif
     255              : }
     256              : 
     257              : /*******************************************************************************
     258              :  * \brief Wrapper around MPI_Cart_get.
     259              :  * \author Ole Schuett
     260              :  ******************************************************************************/
     261      2454260 : void cp_mpi_cart_get(const cp_mpi_comm_t comm, int maxdims, int dims[],
     262              :                      int periods[], int coords[]) {
     263              : #if defined(__parallel)
     264      2454260 :   CHECK(MPI_Cart_get(comm, maxdims, dims, periods, coords));
     265              : #else
     266            0 :   (void)comm; // mark used
     267            0 :   for (int i = 0; i < maxdims; i++) {
     268            0 :     dims[i] = 1;
     269            0 :     periods[i] = 1;
     270            0 :     coords[i] = 0;
     271              :   }
     272              : #endif
     273      2454260 : }
     274              : 
     275              : /*******************************************************************************
     276              :  * \brief Wrapper around MPI_Cart_rank.
     277              :  * \author Ole Schuett
     278              :  ******************************************************************************/
     279    119458824 : int cp_mpi_cart_rank(const cp_mpi_comm_t comm, const int coords[]) {
     280              : #if defined(__parallel)
     281    119458824 :   int rank;
     282    119458824 :   CHECK(MPI_Cart_rank(comm, coords, &rank));
     283    119458824 :   return rank;
     284              : #else
     285            0 :   (void)comm; // mark used
     286            0 :   (void)coords;
     287            0 :   return 0;
     288              : #endif
     289              : }
     290              : 
     291              : /*******************************************************************************
     292              :  * \brief Wrapper around MPI_Cart_sub.
     293              :  * \author Ole Schuett
     294              :  ******************************************************************************/
     295      2454260 : cp_mpi_comm_t cp_mpi_cart_sub(const cp_mpi_comm_t comm,
     296              :                               const int remain_dims[]) {
     297              : #if defined(__parallel)
     298      2454260 :   assert_outside_parallel("cp_mpi_cart_sub");
     299      2454260 :   cp_mpi_comm_t newcomm;
     300      2454260 :   CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
     301      2454260 :   return newcomm;
     302              : #else
     303            0 :   (void)comm; // mark used
     304            0 :   (void)remain_dims;
     305            0 :   return -1;
     306              : #endif
     307              : }
     308              : 
     309              : /*******************************************************************************
     310              :  * \brief Wrapper around MPI_Comm_free.
     311              :  * \author Ole Schuett
     312              :  ******************************************************************************/
     313      2454260 : void cp_mpi_comm_free(cp_mpi_comm_t *comm) {
     314              : #if defined(__parallel)
     315      2454260 :   assert_outside_parallel("cp_mpi_comm_free");
     316      2454260 :   CHECK(MPI_Comm_free(comm));
     317              : #else
     318            0 :   (void)comm; // mark used
     319              : #endif
     320      2454260 : }
     321              : 
     322              : /*******************************************************************************
     323              :  * \brief Wrapper around MPI_Comm_compare.
     324              :  * \author Ole Schuett
     325              :  ******************************************************************************/
     326       700188 : bool cp_mpi_comms_are_similar(const cp_mpi_comm_t comm1,
     327              :                               const cp_mpi_comm_t comm2) {
     328              : #if defined(__parallel)
     329       700188 :   int res;
     330       700188 :   CHECK(MPI_Comm_compare(comm1, comm2, &res));
     331       700188 :   return res == MPI_IDENT || res == MPI_CONGRUENT || res == MPI_SIMILAR;
     332              : #else
     333            0 :   (void)comm1; // mark used
     334            0 :   (void)comm2;
     335            0 :   return true;
     336              : #endif
     337              : }
     338              : 
     339              : /*******************************************************************************
     340              :  * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_INT.
     341              :  * \author Ole Schuett
     342              :  ******************************************************************************/
     343      1400088 : void cp_mpi_max_int(int *values, const int count, const cp_mpi_comm_t comm) {
     344              : #if defined(__parallel)
     345      1400088 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     346      1400088 :     int value = 0;
     347      1400088 :     void *recvbuf =
     348      1400088 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
     349      1400088 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
     350      1400088 :     memcpy(values, recvbuf, count * sizeof(int));
     351      1400088 :     if (1 < count) {
     352            0 :       cp_mpi_free_mem(recvbuf);
     353              :     }
     354              :   }
     355              : #else
     356            0 :   (void)comm; // mark used
     357            0 :   (void)values;
     358            0 :   (void)count;
     359              : #endif
     360      1400088 : }
     361              : 
     362              : /*******************************************************************************
     363              :  * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_UINT64_T.
     364              :  * \author Ole Schuett
     365              :  ******************************************************************************/
     366        32308 : void cp_mpi_max_uint64(uint64_t *values, const int count,
     367              :                        const cp_mpi_comm_t comm) {
     368              : #if defined(__parallel)
     369        32302 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     370        32302 :     uint64_t value = 0;
     371        32302 :     void *recvbuf =
     372        32302 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(uint64_t)) : &value);
     373        32302 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_UINT64_T, MPI_MAX, comm));
     374        32302 :     memcpy(values, recvbuf, count * sizeof(uint64_t));
     375        32302 :     if (1 < count) {
     376            0 :       cp_mpi_free_mem(recvbuf);
     377              :     }
     378              :   }
     379              : #else
     380            6 :   (void)comm; // mark used
     381            6 :   (void)values;
     382            6 :   (void)count;
     383              : #endif
     384        32308 : }
     385              : 
     386              : /*******************************************************************************
     387              :  * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_DOUBLE.
     388              :  * \author Ole Schuett
     389              :  ******************************************************************************/
     390           48 : void cp_mpi_max_double(double *values, const int count,
     391              :                        const cp_mpi_comm_t comm) {
     392              : #if defined(__parallel)
     393           48 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     394           48 :     double value = 0;
     395           48 :     void *recvbuf =
     396           48 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
     397           48 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_MAX, comm));
     398           48 :     memcpy(values, recvbuf, count * sizeof(double));
     399           48 :     if (1 < count) {
     400            0 :       cp_mpi_free_mem(recvbuf);
     401              :     }
     402              :   }
     403              : #else
     404            0 :   (void)comm; // mark used
     405            0 :   (void)values;
     406            0 :   (void)count;
     407              : #endif
     408           48 : }
     409              : 
     410              : /*******************************************************************************
     411              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT.
     412              :  * \author Ole Schuett
     413              :  ******************************************************************************/
     414       350022 : void cp_mpi_sum_int(int *values, const int count, const cp_mpi_comm_t comm) {
     415              : #if defined(__parallel)
     416       350022 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     417       350022 :     int value = 0;
     418       350022 :     void *recvbuf =
     419       350022 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
     420       350022 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
     421       350022 :     memcpy(values, recvbuf, count * sizeof(int));
     422       350022 :     if (1 < count) {
     423       347363 :       cp_mpi_free_mem(recvbuf);
     424              :     }
     425              :   }
     426              : #else
     427            0 :   (void)comm; // mark used
     428            0 :   (void)values;
     429            0 :   (void)count;
     430              : #endif
     431       350022 : }
     432              : 
     433              : /*******************************************************************************
     434              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_LONG.
     435              :  * \author Hans Pabst
     436              :  ******************************************************************************/
     437      4439200 : void cp_mpi_sum_long(long *values, const int count, const cp_mpi_comm_t comm) {
     438              : #if defined(__parallel)
     439      4438400 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     440      4438400 :     long value = 0;
     441      4438400 :     void *recvbuf =
     442      4438400 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(long)) : &value);
     443      4438400 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_LONG, MPI_SUM, comm));
     444      4438400 :     memcpy(values, recvbuf, count * sizeof(long));
     445      4438400 :     if (1 < count) {
     446            0 :       cp_mpi_free_mem(recvbuf);
     447              :     }
     448              :   }
     449              : #else
     450          800 :   (void)comm; // mark used
     451          800 :   (void)values;
     452          800 :   (void)count;
     453              : #endif
     454      4439200 : }
     455              : 
     456              : /*******************************************************************************
     457              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
     458              :  * \author Ole Schuett
     459              :  ******************************************************************************/
     460       710400 : void cp_mpi_sum_int64(int64_t *values, const int count,
     461              :                       const cp_mpi_comm_t comm) {
     462              : #if defined(__parallel)
     463       710400 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     464       710400 :     int64_t value = 0;
     465       710400 :     void *recvbuf =
     466       710400 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(int64_t)) : &value);
     467       710400 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
     468       710400 :     memcpy(values, recvbuf, count * sizeof(int64_t));
     469       710400 :     if (1 < count) {
     470            0 :       cp_mpi_free_mem(recvbuf);
     471              :     }
     472              :   }
     473              : #else
     474            0 :   (void)comm; // mark used
     475            0 :   (void)values;
     476            0 :   (void)count;
     477              : #endif
     478       710400 : }
     479              : 
     480              : /*******************************************************************************
     481              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_DOUBLE.
     482              :  * \author Ole Schuett
     483              :  ******************************************************************************/
     484          190 : void cp_mpi_sum_double(double *values, const int count,
     485              :                        const cp_mpi_comm_t comm) {
     486              : #if defined(__parallel)
     487          190 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     488          190 :     double value = 0;
     489          190 :     void *recvbuf =
     490          190 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
     491          190 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_SUM, comm));
     492          190 :     memcpy(values, recvbuf, count * sizeof(double));
     493          190 :     if (1 < count) {
     494            0 :       cp_mpi_free_mem(recvbuf);
     495              :     }
     496              :   }
     497              : #else
     498            0 :   (void)comm; // mark used
     499            0 :   (void)values;
     500            0 :   (void)count;
     501              : #endif
     502          190 : }
     503              : 
     504              : /*******************************************************************************
     505              :  * \brief Wrapper around MPI_Sendrecv for datatype MPI_BYTE.
     506              :  * \author Ole Schuett
     507              :  ******************************************************************************/
     508        33758 : int cp_mpi_sendrecv_byte(const void *sendbuf, const int sendcount,
     509              :                          const int dest, const int sendtag, void *recvbuf,
     510              :                          const int recvcount, const int source,
     511              :                          const int recvtag, const cp_mpi_comm_t comm) {
     512              : #if defined(__parallel)
     513        33758 :   MPI_Status status;
     514        33758 :   CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
     515              :                      recvcount, MPI_BYTE, source, recvtag, comm, &status));
     516        33758 :   int count_received = 0;
     517        33758 :   CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
     518        33758 :   return count_received;
     519              : #else
     520            0 :   (void)sendbuf; // mark used
     521            0 :   (void)sendcount;
     522            0 :   (void)dest;
     523            0 :   (void)sendtag;
     524            0 :   (void)recvbuf;
     525            0 :   (void)recvcount;
     526            0 :   (void)source;
     527            0 :   (void)recvtag;
     528            0 :   (void)comm;
     529            0 :   fprintf(stderr, "Error: cp_mpi_sendrecv_byte not available without MPI\n");
     530            0 :   abort();
     531              : #endif
     532              : }
     533              : 
     534              : /*******************************************************************************
     535              :  * \brief Wrapper around MPI_Sendrecv for datatype MPI_DOUBLE.
     536              :  * \author Ole Schuett
     537              :  ******************************************************************************/
     538        33758 : int cp_mpi_sendrecv_double(const double *sendbuf, const int sendcount,
     539              :                            const int dest, const int sendtag, double *recvbuf,
     540              :                            const int recvcount, const int source,
     541              :                            const int recvtag, const cp_mpi_comm_t comm) {
     542              : #if defined(__parallel)
     543        33758 :   MPI_Status status;
     544        33758 :   CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
     545              :                      recvcount, MPI_DOUBLE, source, recvtag, comm, &status));
     546        33758 :   int count_received;
     547        33758 :   CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
     548        33758 :   return count_received;
     549              : #else
     550            0 :   (void)sendbuf; // mark used
     551            0 :   (void)sendcount;
     552            0 :   (void)dest;
     553            0 :   (void)sendtag;
     554            0 :   (void)recvbuf;
     555            0 :   (void)recvcount;
     556            0 :   (void)source;
     557            0 :   (void)recvtag;
     558            0 :   (void)comm;
     559            0 :   fprintf(stderr, "Error: cp_mpi_sendrecv_double not available without MPI\n");
     560            0 :   abort();
     561              : #endif
     562              : }
     563              : 
     564              : /*******************************************************************************
     565              :  * \brief Wrapper around MPI_Alltoall for datatype MPI_INT.
     566              :  * \author Ole Schuett
     567              :  ******************************************************************************/
     568       733946 : void cp_mpi_alltoall_int(const int *sendbuf, const int sendcount, int *recvbuf,
     569              :                          const int recvcount, const cp_mpi_comm_t comm) {
     570              : #if defined(__parallel)
     571       733946 :   CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
     572              :                      comm));
     573              : #else
     574            0 :   (void)comm; // mark used
     575            0 :   assert(sendcount == recvcount);
     576            0 :   memcpy(recvbuf, sendbuf, sendcount * sizeof(int));
     577              : #endif
     578       733946 : }
     579              : 
     580              : /*******************************************************************************
     581              :  * \brief Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
     582              :  * \author Ole Schuett
     583              :  ******************************************************************************/
     584       733802 : void cp_mpi_alltoallv_byte(const void *sendbuf, const int *sendcounts,
     585              :                            const int *sdispls, void *recvbuf,
     586              :                            const int *recvcounts, const int *rdispls,
     587              :                            const cp_mpi_comm_t comm) {
     588              : #if defined(__parallel)
     589       733802 :   CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
     590              :                       recvcounts, rdispls, MPI_BYTE, comm));
     591              : #else
     592            0 :   (void)comm; // mark used
     593            0 :   assert(sendcounts[0] == recvcounts[0]);
     594            0 :   assert(sdispls[0] == 0 && rdispls[0] == 0);
     595            0 :   memcpy(recvbuf, sendbuf, sendcounts[0]);
     596              : #endif
     597       733802 : }
     598              : 
     599              : /*******************************************************************************
     600              :  * \brief Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
     601              :  * \author Ole Schuett
     602              :  ******************************************************************************/
     603       733946 : void cp_mpi_alltoallv_double(const double *sendbuf, const int *sendcounts,
     604              :                              const int *sdispls, double *recvbuf,
     605              :                              const int *recvcounts, const int *rdispls,
     606              :                              const cp_mpi_comm_t comm) {
     607              : #if defined(__parallel)
     608       733946 :   CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
     609              :                       recvcounts, rdispls, MPI_DOUBLE, comm));
     610              : #else
     611            0 :   (void)comm; // mark used
     612            0 :   assert(sendcounts[0] == recvcounts[0]);
     613            0 :   assert(sdispls[0] == 0 && rdispls[0] == 0);
     614            0 :   memcpy(recvbuf, sendbuf, sendcounts[0] * sizeof(double));
     615              : #endif
     616       733946 : }
     617              : 
     618              : /*******************************************************************************
     619              :  * \brief Wrapper around MPI_Alloc_mem.
     620              :  * \author Hans Pabst
     621              :  ******************************************************************************/
     622      3181585 : void *cp_mpi_alloc_mem(size_t size) {
     623      3181585 :   void *result = NULL;
     624              : #if DBM_ALLOC_MPI && defined(__parallel)
     625              :   CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
     626              : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
     627              :   result = omp_alloc(size, omp_null_allocator);
     628              : #else
     629      3181585 :   result = malloc(size);
     630              : #endif
     631      3181585 :   return result;
     632              : }
     633              : 
     634              : /*******************************************************************************
     635              :  * \brief Wrapper around MPI_Free_mem.
     636              :  * \author Hans Pabst
     637              :  ******************************************************************************/
     638      3181585 : void cp_mpi_free_mem(void *mem) {
     639              : #if DBM_ALLOC_MPI && defined(__parallel)
     640              :   CHECK(MPI_Free_mem(mem));
     641              : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
     642              :   omp_free(mem, omp_null_allocator);
     643              : #else
     644      3181585 :   free(mem);
     645              : #endif
     646      3181585 : }
     647              : 
     648              : // EOF
        

Generated by: LCOV version 2.0-1