LCOV - code coverage report
Current view: top level - src/mpiwrap - cp_mpi.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 49.5 % 285 141
Test Date: 2026-09-03 07:32:15 Functions: 80.6 % 31 25

            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      4901992 : static void assert_outside_parallel(const char *routine_name) {
      36      4901992 :   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      4901992 : }
      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            0 : cp_mpi_comm_t cp_mpi_get_comm_world(void) {
     139              : #if defined(__parallel)
     140            0 :   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      1258410 : 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      1258406 :   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            0 : int cp_mpi_comm_c2f(const cp_mpi_comm_t comm) {
     165              : #if defined(__parallel)
     166            0 :   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      3676494 : int cp_mpi_comm_rank(const cp_mpi_comm_t comm) {
     178              : #if defined(__parallel)
     179      3676494 :   int rank = 0;
     180      3676494 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     181      3676494 :     CHECK(MPI_Comm_rank(comm, &rank));
     182              :   }
     183      3676494 :   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      3676638 : int cp_mpi_comm_size(const cp_mpi_comm_t comm) {
     195              : #if defined(__parallel)
     196      3676638 :   int nranks = 1;
     197      3676638 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     198      3676638 :     CHECK(MPI_Comm_size(comm, &nranks));
     199              :   }
     200      3676638 :   return nranks;
     201              : #else
     202            0 :   (void)comm; // mark used
     203            0 :   return 1;
     204              : #endif
     205              : }
     206              : 
     207              : /*******************************************************************************
     208              :  * \brief Wrapper around MPI_Dims_create.
     209              :  * \author Ole Schuett
     210              :  ******************************************************************************/
     211            0 : void cp_mpi_dims_create(const int nnodes, const int ndims, int dims[]) {
     212              : #if defined(__parallel)
     213            0 :   CHECK(MPI_Dims_create(nnodes, ndims, dims));
     214              : #else
     215            0 :   dims[0] = nnodes;
     216            0 :   for (int i = 1; i < ndims; i++) {
     217            0 :     dims[i] = 1;
     218              :   }
     219              : #endif
     220            0 : }
     221              : 
     222              : /*******************************************************************************
     223              :  * \brief Wrapper around MPI_Cart_create.
     224              :  * \author Ole Schuett
     225              :  ******************************************************************************/
     226            0 : cp_mpi_comm_t cp_mpi_cart_create(const cp_mpi_comm_t comm_old, const int ndims,
     227              :                                  const int dims[], const int periods[],
     228              :                                  const int reorder) {
     229              : #if defined(__parallel)
     230            0 :   assert_outside_parallel("cp_mpi_cart_create");
     231            0 :   cp_mpi_comm_t comm_cart;
     232            0 :   CHECK(MPI_Cart_create(comm_old, ndims, dims, periods, reorder, &comm_cart));
     233            0 :   return comm_cart;
     234              : #else
     235            0 :   (void)comm_old; // mark used
     236            0 :   (void)ndims;
     237            0 :   (void)dims;
     238            0 :   (void)periods;
     239            0 :   (void)reorder;
     240            0 :   return -1;
     241              : #endif
     242              : }
     243              : 
     244              : /*******************************************************************************
     245              :  * \brief Wrapper around MPI_Cart_get.
     246              :  * \author Ole Schuett
     247              :  ******************************************************************************/
     248      2450996 : void cp_mpi_cart_get(const cp_mpi_comm_t comm, int maxdims, int dims[],
     249              :                      int periods[], int coords[]) {
     250              : #if defined(__parallel)
     251      2450996 :   CHECK(MPI_Cart_get(comm, maxdims, dims, periods, coords));
     252              : #else
     253            0 :   (void)comm; // mark used
     254            0 :   for (int i = 0; i < maxdims; i++) {
     255            0 :     dims[i] = 1;
     256            0 :     periods[i] = 1;
     257            0 :     coords[i] = 0;
     258              :   }
     259              : #endif
     260      2450996 : }
     261              : 
     262              : /*******************************************************************************
     263              :  * \brief Wrapper around MPI_Cart_rank.
     264              :  * \author Ole Schuett
     265              :  ******************************************************************************/
     266    119420491 : int cp_mpi_cart_rank(const cp_mpi_comm_t comm, const int coords[]) {
     267              : #if defined(__parallel)
     268    119420491 :   int rank;
     269    119420491 :   CHECK(MPI_Cart_rank(comm, coords, &rank));
     270    119420491 :   return rank;
     271              : #else
     272            0 :   (void)comm; // mark used
     273            0 :   (void)coords;
     274            0 :   return 0;
     275              : #endif
     276              : }
     277              : 
     278              : /*******************************************************************************
     279              :  * \brief Wrapper around MPI_Cart_sub.
     280              :  * \author Ole Schuett
     281              :  ******************************************************************************/
     282      2450996 : cp_mpi_comm_t cp_mpi_cart_sub(const cp_mpi_comm_t comm,
     283              :                               const int remain_dims[]) {
     284              : #if defined(__parallel)
     285      2450996 :   assert_outside_parallel("cp_mpi_cart_sub");
     286      2450996 :   cp_mpi_comm_t newcomm;
     287      2450996 :   CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
     288      2450996 :   return newcomm;
     289              : #else
     290            0 :   (void)comm; // mark used
     291            0 :   (void)remain_dims;
     292            0 :   return -1;
     293              : #endif
     294              : }
     295              : 
     296              : /*******************************************************************************
     297              :  * \brief Wrapper around MPI_Comm_free.
     298              :  * \author Ole Schuett
     299              :  ******************************************************************************/
     300      2450996 : void cp_mpi_comm_free(cp_mpi_comm_t *comm) {
     301              : #if defined(__parallel)
     302      2450996 :   assert_outside_parallel("cp_mpi_comm_free");
     303      2450996 :   CHECK(MPI_Comm_free(comm));
     304              : #else
     305            0 :   (void)comm; // mark used
     306              : #endif
     307      2450996 : }
     308              : 
     309              : /*******************************************************************************
     310              :  * \brief Wrapper around MPI_Comm_compare.
     311              :  * \author Ole Schuett
     312              :  ******************************************************************************/
     313       698952 : bool cp_mpi_comms_are_similar(const cp_mpi_comm_t comm1,
     314              :                               const cp_mpi_comm_t comm2) {
     315              : #if defined(__parallel)
     316       698952 :   int res;
     317       698952 :   CHECK(MPI_Comm_compare(comm1, comm2, &res));
     318       698952 :   return res == MPI_IDENT || res == MPI_CONGRUENT || res == MPI_SIMILAR;
     319              : #else
     320            0 :   (void)comm1; // mark used
     321            0 :   (void)comm2;
     322            0 :   return true;
     323              : #endif
     324              : }
     325              : 
     326              : /*******************************************************************************
     327              :  * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_INT.
     328              :  * \author Ole Schuett
     329              :  ******************************************************************************/
     330      1397616 : void cp_mpi_max_int(int *values, const int count, const cp_mpi_comm_t comm) {
     331              : #if defined(__parallel)
     332      1397616 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     333      1397616 :     int value = 0;
     334      1397616 :     void *recvbuf =
     335      1397616 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
     336      1397616 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
     337      1397616 :     memcpy(values, recvbuf, count * sizeof(int));
     338      1397616 :     if (1 < count) {
     339            0 :       cp_mpi_free_mem(recvbuf);
     340              :     }
     341              :   }
     342              : #else
     343            0 :   (void)comm; // mark used
     344            0 :   (void)values;
     345            0 :   (void)count;
     346              : #endif
     347      1397616 : }
     348              : 
     349              : /*******************************************************************************
     350              :  * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_UINT64_T.
     351              :  * \author Ole Schuett
     352              :  ******************************************************************************/
     353        31524 : void cp_mpi_max_uint64(uint64_t *values, const int count,
     354              :                        const cp_mpi_comm_t comm) {
     355              : #if defined(__parallel)
     356        31518 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     357        31518 :     uint64_t value = 0;
     358        31518 :     void *recvbuf =
     359        31518 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(uint64_t)) : &value);
     360        31518 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_UINT64_T, MPI_MAX, comm));
     361        31518 :     memcpy(values, recvbuf, count * sizeof(uint64_t));
     362        31518 :     if (1 < count) {
     363            0 :       cp_mpi_free_mem(recvbuf);
     364              :     }
     365              :   }
     366              : #else
     367            6 :   (void)comm; // mark used
     368            6 :   (void)values;
     369            6 :   (void)count;
     370              : #endif
     371        31524 : }
     372              : 
     373              : /*******************************************************************************
     374              :  * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_DOUBLE.
     375              :  * \author Ole Schuett
     376              :  ******************************************************************************/
     377           48 : void cp_mpi_max_double(double *values, const int count,
     378              :                        const cp_mpi_comm_t comm) {
     379              : #if defined(__parallel)
     380           48 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     381           48 :     double value = 0;
     382           48 :     void *recvbuf =
     383           48 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
     384           48 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_MAX, comm));
     385           48 :     memcpy(values, recvbuf, count * sizeof(double));
     386           48 :     if (1 < count) {
     387            0 :       cp_mpi_free_mem(recvbuf);
     388              :     }
     389              :   }
     390              : #else
     391            0 :   (void)comm; // mark used
     392            0 :   (void)values;
     393            0 :   (void)count;
     394              : #endif
     395           48 : }
     396              : 
     397              : /*******************************************************************************
     398              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT.
     399              :  * \author Ole Schuett
     400              :  ******************************************************************************/
     401       349404 : void cp_mpi_sum_int(int *values, const int count, const cp_mpi_comm_t comm) {
     402              : #if defined(__parallel)
     403       349404 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     404       349404 :     int value = 0;
     405       349404 :     void *recvbuf =
     406       349404 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
     407       349404 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
     408       349404 :     memcpy(values, recvbuf, count * sizeof(int));
     409       349404 :     if (1 < count) {
     410       346757 :       cp_mpi_free_mem(recvbuf);
     411              :     }
     412              :   }
     413              : #else
     414            0 :   (void)comm; // mark used
     415            0 :   (void)values;
     416            0 :   (void)count;
     417              : #endif
     418       349404 : }
     419              : 
     420              : /*******************************************************************************
     421              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_LONG.
     422              :  * \author Hans Pabst
     423              :  ******************************************************************************/
     424      4388000 : void cp_mpi_sum_long(long *values, const int count, const cp_mpi_comm_t comm) {
     425              : #if defined(__parallel)
     426      4387200 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     427      4387200 :     long value = 0;
     428      4387200 :     void *recvbuf =
     429      4387200 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(long)) : &value);
     430      4387200 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_LONG, MPI_SUM, comm));
     431      4387200 :     memcpy(values, recvbuf, count * sizeof(long));
     432      4387200 :     if (1 < count) {
     433            0 :       cp_mpi_free_mem(recvbuf);
     434              :     }
     435              :   }
     436              : #else
     437          800 :   (void)comm; // mark used
     438          800 :   (void)values;
     439          800 :   (void)count;
     440              : #endif
     441      4388000 : }
     442              : 
     443              : /*******************************************************************************
     444              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
     445              :  * \author Ole Schuett
     446              :  ******************************************************************************/
     447       702208 : void cp_mpi_sum_int64(int64_t *values, const int count,
     448              :                       const cp_mpi_comm_t comm) {
     449              : #if defined(__parallel)
     450       702208 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     451       702208 :     int64_t value = 0;
     452       702208 :     void *recvbuf =
     453       702208 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(int64_t)) : &value);
     454       702208 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
     455       702208 :     memcpy(values, recvbuf, count * sizeof(int64_t));
     456       702208 :     if (1 < count) {
     457            0 :       cp_mpi_free_mem(recvbuf);
     458              :     }
     459              :   }
     460              : #else
     461            0 :   (void)comm; // mark used
     462            0 :   (void)values;
     463            0 :   (void)count;
     464              : #endif
     465       702208 : }
     466              : 
     467              : /*******************************************************************************
     468              :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_DOUBLE.
     469              :  * \author Ole Schuett
     470              :  ******************************************************************************/
     471          190 : void cp_mpi_sum_double(double *values, const int count,
     472              :                        const cp_mpi_comm_t comm) {
     473              : #if defined(__parallel)
     474          190 :   if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
     475          190 :     double value = 0;
     476          190 :     void *recvbuf =
     477          190 :         (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
     478          190 :     CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_SUM, comm));
     479          190 :     memcpy(values, recvbuf, count * sizeof(double));
     480          190 :     if (1 < count) {
     481            0 :       cp_mpi_free_mem(recvbuf);
     482              :     }
     483              :   }
     484              : #else
     485            0 :   (void)comm; // mark used
     486            0 :   (void)values;
     487            0 :   (void)count;
     488              : #endif
     489          190 : }
     490              : 
     491              : /*******************************************************************************
     492              :  * \brief Wrapper around MPI_Sendrecv for datatype MPI_BYTE.
     493              :  * \author Ole Schuett
     494              :  ******************************************************************************/
     495        33686 : int cp_mpi_sendrecv_byte(const void *sendbuf, const int sendcount,
     496              :                          const int dest, const int sendtag, void *recvbuf,
     497              :                          const int recvcount, const int source,
     498              :                          const int recvtag, const cp_mpi_comm_t comm) {
     499              : #if defined(__parallel)
     500        33686 :   MPI_Status status;
     501        33686 :   CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
     502              :                      recvcount, MPI_BYTE, source, recvtag, comm, &status));
     503        33686 :   int count_received = 0;
     504        33686 :   CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
     505        33686 :   return count_received;
     506              : #else
     507            0 :   (void)sendbuf; // mark used
     508            0 :   (void)sendcount;
     509            0 :   (void)dest;
     510            0 :   (void)sendtag;
     511            0 :   (void)recvbuf;
     512            0 :   (void)recvcount;
     513            0 :   (void)source;
     514            0 :   (void)recvtag;
     515            0 :   (void)comm;
     516            0 :   fprintf(stderr, "Error: cp_mpi_sendrecv_byte not available without MPI\n");
     517            0 :   abort();
     518              : #endif
     519              : }
     520              : 
     521              : /*******************************************************************************
     522              :  * \brief Wrapper around MPI_Sendrecv for datatype MPI_DOUBLE.
     523              :  * \author Ole Schuett
     524              :  ******************************************************************************/
     525        33686 : int cp_mpi_sendrecv_double(const double *sendbuf, const int sendcount,
     526              :                            const int dest, const int sendtag, double *recvbuf,
     527              :                            const int recvcount, const int source,
     528              :                            const int recvtag, const cp_mpi_comm_t comm) {
     529              : #if defined(__parallel)
     530        33686 :   MPI_Status status;
     531        33686 :   CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
     532              :                      recvcount, MPI_DOUBLE, source, recvtag, comm, &status));
     533        33686 :   int count_received;
     534        33686 :   CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
     535        33686 :   return count_received;
     536              : #else
     537            0 :   (void)sendbuf; // mark used
     538            0 :   (void)sendcount;
     539            0 :   (void)dest;
     540            0 :   (void)sendtag;
     541            0 :   (void)recvbuf;
     542            0 :   (void)recvcount;
     543            0 :   (void)source;
     544            0 :   (void)recvtag;
     545            0 :   (void)comm;
     546            0 :   fprintf(stderr, "Error: cp_mpi_sendrecv_double not available without MPI\n");
     547            0 :   abort();
     548              : #endif
     549              : }
     550              : 
     551              : /*******************************************************************************
     552              :  * \brief Wrapper around MPI_Alltoall for datatype MPI_INT.
     553              :  * \author Ole Schuett
     554              :  ******************************************************************************/
     555       732638 : void cp_mpi_alltoall_int(const int *sendbuf, const int sendcount, int *recvbuf,
     556              :                          const int recvcount, const cp_mpi_comm_t comm) {
     557              : #if defined(__parallel)
     558       732638 :   CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
     559              :                      comm));
     560              : #else
     561            0 :   (void)comm; // mark used
     562            0 :   assert(sendcount == recvcount);
     563            0 :   memcpy(recvbuf, sendbuf, sendcount * sizeof(int));
     564              : #endif
     565       732638 : }
     566              : 
     567              : /*******************************************************************************
     568              :  * \brief Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
     569              :  * \author Ole Schuett
     570              :  ******************************************************************************/
     571       732494 : void cp_mpi_alltoallv_byte(const void *sendbuf, const int *sendcounts,
     572              :                            const int *sdispls, void *recvbuf,
     573              :                            const int *recvcounts, const int *rdispls,
     574              :                            const cp_mpi_comm_t comm) {
     575              : #if defined(__parallel)
     576       732494 :   CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
     577              :                       recvcounts, rdispls, MPI_BYTE, comm));
     578              : #else
     579            0 :   (void)comm; // mark used
     580            0 :   assert(sendcounts[0] == recvcounts[0]);
     581            0 :   assert(sdispls[0] == 0 && rdispls[0] == 0);
     582            0 :   memcpy(recvbuf, sendbuf, sendcounts[0]);
     583              : #endif
     584       732494 : }
     585              : 
     586              : /*******************************************************************************
     587              :  * \brief Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
     588              :  * \author Ole Schuett
     589              :  ******************************************************************************/
     590       732638 : void cp_mpi_alltoallv_double(const double *sendbuf, const int *sendcounts,
     591              :                              const int *sdispls, double *recvbuf,
     592              :                              const int *recvcounts, const int *rdispls,
     593              :                              const cp_mpi_comm_t comm) {
     594              : #if defined(__parallel)
     595       732638 :   CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
     596              :                       recvcounts, rdispls, MPI_DOUBLE, comm));
     597              : #else
     598            0 :   (void)comm; // mark used
     599            0 :   assert(sendcounts[0] == recvcounts[0]);
     600            0 :   assert(sdispls[0] == 0 && rdispls[0] == 0);
     601            0 :   memcpy(recvbuf, sendbuf, sendcounts[0] * sizeof(double));
     602              : #endif
     603       732638 : }
     604              : 
     605              : /*******************************************************************************
     606              :  * \brief Wrapper around MPI_Alloc_mem.
     607              :  * \author Hans Pabst
     608              :  ******************************************************************************/
     609      3175963 : void *cp_mpi_alloc_mem(size_t size) {
     610      3175963 :   void *result = NULL;
     611              : #if DBM_ALLOC_MPI && defined(__parallel)
     612              :   CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
     613              : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
     614              :   result = omp_alloc(size, omp_null_allocator);
     615              : #else
     616      3175963 :   result = malloc(size);
     617              : #endif
     618      3175963 :   return result;
     619              : }
     620              : 
     621              : /*******************************************************************************
     622              :  * \brief Wrapper around MPI_Free_mem.
     623              :  * \author Hans Pabst
     624              :  ******************************************************************************/
     625      3175963 : void cp_mpi_free_mem(void *mem) {
     626              : #if DBM_ALLOC_MPI && defined(__parallel)
     627              :   CHECK(MPI_Free_mem(mem));
     628              : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
     629              :   omp_free(mem, omp_null_allocator);
     630              : #else
     631      3175963 :   free(mem);
     632              : #endif
     633      3175963 : }
     634              : 
     635              : // EOF
        

Generated by: LCOV version 2.0-1