Line data Source code
1 : // SPDX-FileCopyrightText: 2024 Daniel Abele <daniel.abele@dlr.de>
2 : //
3 : // SPDX-License-Identifier: BSD-3-Clause
4 :
5 : #pragma once
6 :
7 : #include "issm-precice/config.hpp"
8 : #include "mpi.h"
9 : #include <cstdint>
10 : #include <string>
11 :
12 : namespace ipc
13 : {
14 :
15 : /**
16 : * RAII class for initializing and finalizing MPI.
17 : * On construction initializes MPI.
18 : * On destruction finalizes MPI.
19 : */
20 : class [[nodiscard]] MpiInit
21 : {
22 : public:
23 : /**
24 : * Initialize MPI if not initialized yet.
25 : */
26 7 : [[nodiscard]] MpiInit(int* argc, char*** argv) : m_is_initialized(0)
27 : {
28 7 : MPI_Initialized(&m_is_initialized);
29 7 : if (!m_is_initialized)
30 : {
31 7 : MPI_Init(argc, argv);
32 : }
33 7 : }
34 :
35 : /**
36 : * Finalize MPI if it was initialized by this object.
37 : */
38 7 : ~MpiInit()
39 : {
40 7 : if (!m_is_initialized)
41 : {
42 7 : MPI_Finalize();
43 : }
44 7 : }
45 :
46 : private:
47 : int m_is_initialized;
48 : };
49 :
50 : /**
51 : * Get the rank of the MPI process.
52 : */
53 596 : inline int mpi_rank(MPI_Comm comm)
54 : {
55 : int rank;
56 596 : MPI_Comm_rank(comm, &rank);
57 596 : return rank;
58 : }
59 :
60 : /**
61 : * Split a communicator based on the given category.
62 : */
63 4 : inline MPI_Comm split_comm(MPI_Comm comm, const std::string& category)
64 : {
65 4 : auto hash_fnv1a = [](const std::string& str)
66 : {
67 4 : uint32_t hash = 2166136261;
68 8 : for (auto&& c : str)
69 : {
70 4 : hash ^= c;
71 4 : hash *= 16777619;
72 : }
73 4 : return hash;
74 : };
75 :
76 : MPI_Comm new_comm;
77 4 : auto comm_key = std::abs(int(hash_fnv1a(category)));
78 4 : MPI_Comm_split(comm, comm_key, 0, &new_comm);
79 4 : return new_comm;
80 : }
81 :
82 : } // namespace ipc
|