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