b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2comm_MPI.H
1//------------------------------------------------------------------------
2// b2comm_MPI.H
3//
4// written by Harald Klimach <harald.klimach@dlr.de>
5//
6// (c) 2021 Deutsches Zentrum für Luft- und Raumfahrt (DLR) e.V.
7// Linder Höhe, 51147 Köln
8//
9// All Rights Reserved. Proprietary source code. The contents of
10// this file may not be disclosed to third parties, copied or
11// duplicated in any form, in whole or in part, without the prior
12// written permission of DLR.
13//
14//------------------------------------------------------------------------
15
16#ifndef B2COMM_MPI_H_
17#define B2COMM_MPI_H_
18
19//------------------------------------------------------------------------
20//
21// \file
22// MPI communicator encapsulation. Provides the communication via MPI.
23//
24//------------------------------------------------------------------------
25
26#include "b2ppconfig.h"
27#include "utils/b2exception.H"
28
29#ifdef HAVE_MPI
30
31#include <mpi.h>
32
33#include "utils/b2comm.H"
34
35namespace b2000 {
36
37// Communication implementation via MPI.
38//
39// If MPI is available and activated via cmakes USE_MPI option, this class will
40// be used to realize the communication between multiple processes.
41class B2mpi : public Communicator {
42public:
43 // A main constructor that initializes MPI.
44 // May only be called once in the program execution!
45 // This constructor also splits off any processes in MPI_COMM_WORLD,
46 // that may run a different program and don't call this constructor.
47 B2mpi(int argc, char* argv[]);
48
49 explicit B2mpi() = default;
50
51 // Constructor from an existing MPI communicator.
52 explicit B2mpi(MPI_Comm comm);
53
54 // Constructor that splits some processes off from MPI_COMM_WORLD.
55 // Processes that should partake in the new communicator need to
56 // indicate that and pass true.
57 explicit B2mpi(bool participate);
58
59 ~B2mpi();
60
61 static constexpr bool supported = true;
62
63 // Rank of the running process
64 int rank() const override { return rank_; }
65
66 // Number of processes in this communicator
67 int NumRanks() const override { return size_; }
68
69 // Is the running process root of the communicator?
70 bool IsRoot() const override { return 0 == rank_; }
71
72 // Additional command line options for the communication
73 void CmdOpts(b2000::cmdline::CmdLine& cmdline) override {
74 // No additional command line options necessary for the MPI
75 // communication.
76 }
77
78 // Fortran communicator as needed by MUMPS
79 int GetFcomm() const override;
80
81 // Wrap MPI abort
82 void Abort(int errorcode) override { MPI_Abort(comm_, errorcode); }
83
84 // Wrap MPI barrier
85 void Barrier() override {
86 int error = MPI_Barrier(comm_);
87 check_mpi_error(error);
88 }
89
90 // Receive a message from rank source with tag within the communicator.
91 void Recv(char buffer[], uint64_t length, int source, int tag) {
92 const int buflen = static_cast<int>(length);
93 int error = MPI_Recv(buffer, buflen, MPI_BYTE, source, tag, comm_, &status_);
94 check_mpi_error(error);
95 }
96
97 // Send a message to rank target with tag within the communicator.
98 void Send(char buffer[], uint64_t length, int target, int tag) {
99 const int buflen = static_cast<int>(length);
100 int error = MPI_Send(buffer, buflen, MPI_BYTE, target, tag, comm_);
101 check_mpi_error(error);
102 }
103
104 // Wrap MPI bcast
105 void Bcast(uint64_t buffer[], uint64_t length, int root = 0) override {
106 const int buflen = static_cast<int>(length);
107 int error = MPI_Bcast(buffer, buflen, MPI_UNSIGNED_LONG, root, comm_);
108 check_mpi_error(error);
109 }
110
111 void Bcast(int buffer[], uint64_t length, int root = 0) override {
112 int buflen = static_cast<int>(length);
113 int error = MPI_Bcast(buffer, buflen, MPI_INT, root, comm_);
114 check_mpi_error(error);
115 }
116
117 void Bcast(double buffer[], uint64_t length, int root = 0) override {
118 int buflen = static_cast<int>(length);
119 int error = MPI_Bcast(buffer, buflen, MPI_DOUBLE, root, comm_);
120 check_mpi_error(error);
121 }
122
123 // Probe an incoming message for its size in bytes (before calling
124 // the corresponding receive).
125 uint64_t ProbeByteCount(int source, int tag) override {
126 int message_size;
127 int error = MPI_Probe(source, tag, comm_, &status_);
128 if (0 == error) { error = MPI_Get_count(&status_, MPI_BYTE, &message_size); }
129 check_mpi_error(error);
130 return static_cast<uint64_t>(message_size);
131 }
132
133private:
134 // Color to use to identify B2000 processes.
135 static constexpr int kMpiColor = 2000;
136
137 // Color to use to identify shared processes in the FSI context.
138 static constexpr int kFsiColor = 3000;
139
140 // Identification of the running process
141 int rank_ = 0;
142
143 // Size of the Communicator
144 int size_ = 0;
145
146 // Is this the communicator of the main program?
147 bool ismain_ = false;
148
149 // The MPI communicator to encapsulate
150 MPI_Comm comm_ = MPI_COMM_NULL;
151
152 // Hold the status of the last MPI call that returned a status.
153 MPI_Status status_;
154
155 // Check for MPI errors and throw an exception if the MPI call
156 // was not successful.
157 //
158 // Note: usually MPI errors are fatal and the program aborts
159 // when encountering errors likely before running into this
160 // handler. To ensure that this is utilized we'd need to set
161 // a proper MPI Error handler, but this changes the semantic
162 // and would result in ignoring the default MPI configuration.
163 void check_mpi_error(int errorcode) {
164 if (errorcode != MPI_SUCCESS) {
165 char errormessage[MPI_MAX_ERROR_STRING + 1];
166 int resultlen;
167 MPI_Error_string(errorcode, errormessage, &resultlen);
168 errormessage[resultlen] = '\0';
169 Exception() << "MPI Error: " << errormessage << THROW;
170 }
171 }
172
173}; // class B2mpi
174
175} // namespace b2000
176
177#else // HAVE_MPI
178
179namespace b2000 {
180
181// Placeholder when MPI is *NOT* available.
182class B2mpi : public Communicator {
183public:
184 static constexpr bool supported = false;
185
186 explicit B2mpi() { UnimplementedError() << THROW; }
187 B2mpi(int argc, char* argv[]) { UnimplementedError() << THROW; }
188 explicit B2mpi(bool participate) { UnimplementedError() << THROW; }
189
190 int rank() const override { return 0; }
191 int NumRanks() const override { return 0; }
192 bool IsRoot() const override { return false; }
193
194 void CmdOpts(b2000::cmdline::CmdLine& cmdline) override {}
195
196 int GetFcomm() const override { return 0; }
197 void Abort(int errorcode) override {}
198 void Barrier() override {}
199
200 void Recv(char buffer[], uint64_t length, int source, int tag) override {}
201 void Send(char buffer[], uint64_t length, int target, int tag) override {}
202
203 void Bcast(uint64_t buffer[], uint64_t length, int root = 0) override {}
204 void Bcast(int buffer[], uint64_t length, int root = 0) override {}
205 void Bcast(double buffer[], uint64_t length, int root = 0) override {}
206
207 uint64_t ProbeByteCount(int source, int tag) override { return 0; }
208}; // class B2mpi
209
210} // namespace b2000
211
212#endif // HAVE_MPI
213
214#endif // B2COMM_MPI_H_
#define THROW
Definition b2exception.H:198
Definition b2cmdline.H:641
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314