communicator.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef OOMPH_COMMUNICATOR_CLASS_HEADER
27 #define OOMPH_COMMUNICATOR_CLASS_HEADER
28 
29 // Config header generated by autoconfig
30 #ifdef HAVE_CONFIG_H
31 #include <oomph-lib-config.h>
32 #endif
33 
34 // MPI headers
35 #ifdef OOMPH_HAS_MPI
36 #include "mpi.h"
37 #endif
38 
39 // Oomph-lib error handler
40 #include "oomph_definitions.h"
41 #include "oomph_utilities.h"
42 
43 namespace oomph
44 {
45  template<class T>
46  class DenseMatrix;
47 
48  //=============================================================================
52  //=============================================================================
54  {
55  public:
56 #ifdef OOMPH_HAS_MPI
61  OomphCommunicator(const MPI_Comm mpi_communicator,
62  const bool& owns_mpi_comm = false)
63  : Serial_communicator(false)
64  {
65  // store a pointer to the communicator
66  Comm = mpi_communicator;
67 
68  // hold owns_mpi_comm
69  Owns_mpi_comm = owns_mpi_comm;
70  }
71 #endif
72 
75 #ifdef OOMPH_HAS_MPI
76  : Owns_mpi_comm(false), Serial_communicator(true)
77 #endif
78  {
79  }
80 
82  OomphCommunicator(const OomphCommunicator& communicator)
83 #ifdef OOMPH_HAS_MPI
84  : Owns_mpi_comm(false)
85  {
86  if (communicator.serial_communicator())
87  {
88  Serial_communicator = true;
89  }
90  else
91  {
92  Comm = communicator.mpi_comm();
93  Serial_communicator = false;
94  }
95  }
96 #else
97  {
98  }
99 #endif
100 
102  OomphCommunicator(const OomphCommunicator* communicator_pt)
103 #ifdef OOMPH_HAS_MPI
104  : Owns_mpi_comm(false)
105  {
106  if (communicator_pt->serial_communicator())
107  {
108  Serial_communicator = true;
109  }
110  else
111  {
112  Comm = communicator_pt->mpi_comm();
113  Serial_communicator = false;
114  }
115  }
116 #else
117  {
118  }
119 #endif
120 
126  {
127 #ifdef OOMPH_HAS_MPI
128  if (Owns_mpi_comm)
129  {
130  MPI_Comm_free(&Comm);
131  }
132 #endif
133  }
134 
136  void operator=(const OomphCommunicator& communicator)
137  {
138 #ifdef OOMPH_HAS_MPI
139  if (Owns_mpi_comm)
140  {
141  MPI_Comm_free(&Comm);
142  }
143  Owns_mpi_comm = false;
144  if (communicator.serial_communicator())
145  {
146  Serial_communicator = true;
147  }
148  else
149  {
150  Serial_communicator = false;
151  Comm = communicator.mpi_comm();
152  }
153 #endif
154  }
155 
157  int nproc() const
158  {
159 #ifdef OOMPH_HAS_MPI
160  if (Serial_communicator)
161  {
162  return 1;
163  }
164  else
165  {
166  int n_proc = 1;
167  MPI_Comm_size(Comm, &n_proc);
168  return n_proc;
169  }
170 #else
171  return 1;
172 #endif
173  }
174 
176  int my_rank() const
177  {
178 #ifdef OOMPH_HAS_MPI
179  if (Serial_communicator)
180  {
181  return 0;
182  }
183  else
184  {
185  int My_rank = 0;
186  MPI_Comm_rank(Comm, &My_rank);
187  return My_rank;
188  }
189 #else
190  return 0;
191 #endif
192  }
193 
196  bool operator==(const OomphCommunicator& other_comm) const
197  {
198 #ifdef OOMPH_HAS_MPI
199  if (Serial_communicator != other_comm.serial_communicator())
200  {
201  return false;
202  }
203  else if (Serial_communicator)
204  {
205  return true;
206  }
207  else
208  {
209  int flag;
210  MPI_Comm_compare(Comm, other_comm.mpi_comm(), &flag);
211  if (flag == MPI_IDENT)
212  {
213  return true;
214  }
215  return false;
216  }
217 #else
218  return true;
219 #endif
220  }
221 
224  bool operator!=(const OomphCommunicator& other_comm) const
225  {
226  return !(*this == other_comm);
227  }
228 
229 #ifdef OOMPH_HAS_MPI
232  OomphCommunicator* split(const int& color, const int& key)
233  {
234 #ifdef PARANOID
235  if (Serial_communicator)
236  {
237  std::ostringstream error_message_stream;
238  error_message_stream << "Attempted to split a serial communicator.";
239  throw OomphLibError(error_message_stream.str(),
242  }
243 #endif
244 
245  // pointer for the split oomph-lib communicator
246  OomphCommunicator* split_comm_pt;
247 
248  // the pointer for the new mpi communicator
249  MPI_Comm* mpi_comm_pt = new MPI_Comm;
250 
251  // get the split communicator
252  MPI_Comm_split(Comm, color, key, mpi_comm_pt);
253 
254  // assemble the new oomph-lib ocmmunicator
255  // the new oomph-lib communicator owns the MPI_Comm at mpi_comm_pt
256  // and is responsible for its destruction
257  split_comm_pt = new OomphCommunicator(*mpi_comm_pt, true);
258 
259  // and return
260  return split_comm_pt;
261  }
262 #endif
263 
264 
265 #ifdef OOMPH_HAS_MPI
267  MPI_Comm mpi_comm() const
268  {
269 #ifdef PARANOID
270  if (Serial_communicator)
271  {
272  std::ostringstream error_message_stream;
273  error_message_stream
274  << "Requested the MPI_Comm object for a serial communicator.";
275  throw OomphLibError(error_message_stream.str(),
278  }
279 #endif
280  return Comm;
281  }
282 
283 
285  bool serial_communicator() const
286  {
287  return Serial_communicator;
288  }
289 
291  void broadcast(const int& source, Vector<int>& x)
292  {
293  int n;
294 
295  // Get number of entries on processor source (where the vector exists)
296  unsigned long n_long;
297  if (this->my_rank() == source)
298  {
299  n_long = x.size();
300 
301  // Convert to int
302  n = static_cast<int>(n_long);
303  }
304 
305  // Broadcast to everybody how many entries to expect
306  MPI_Bcast(&n, 1, MPI_INT, source, this->mpi_comm());
307 
308  // Resize Vector everywhere else in preparation
309  if (this->my_rank() != source)
310  {
311  x.resize(n);
312  }
313 
314  // Broadcast the Vector directly
315  MPI_Bcast(&x[0], n, MPI_INT, source, this->mpi_comm());
316  }
317 
319  void broadcast(const int& source, Vector<double>& x)
320  {
321  int n;
322 
323  // Get number of entries on processor source (where the vector exists)
324  unsigned long n_long;
325  if (this->my_rank() == source)
326  {
327  n_long = x.size();
328 
329  // Convert to int
330  n = static_cast<int>(n_long);
331  }
332 
333  // Broadcast to everybody how many entries to expect
334  MPI_Bcast(&n, 1, MPI_INT, source, this->mpi_comm());
335 
336  // Resize Vector everywhere else in preparation
337  if (this->my_rank() != source)
338  {
339  x.resize(n);
340  }
341 
342  // Broadcast the Vector directly
343  MPI_Bcast(&x[0], n, MPI_DOUBLE, source, this->mpi_comm());
344  }
345 
347  void broadcast(const int& source, DenseMatrix<double>& x);
348 
349 #endif
350 
351  private:
352 #ifdef OOMPH_HAS_MPI
354  MPI_Comm Comm;
355 
359  bool Owns_mpi_comm;
360 
363  bool Serial_communicator;
364 
365 #endif
366  }; // end of class Communicator
367 } // namespace oomph
368 #endif
Matrix< Scalar, Dynamic, Dynamic > DenseMatrix
Definition: BenchSparseUtil.h:23
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Definition: communicator.h:54
void operator=(const OomphCommunicator &communicator)
assignment operator
Definition: communicator.h:136
OomphCommunicator()
Serial constructor.
Definition: communicator.h:74
int my_rank() const
my rank
Definition: communicator.h:176
int nproc() const
number of processors
Definition: communicator.h:157
~OomphCommunicator()
Definition: communicator.h:125
OomphCommunicator(const OomphCommunicator &communicator)
Copy constructor.
Definition: communicator.h:82
OomphCommunicator(const OomphCommunicator *communicator_pt)
Pointer (copy) constructor.
Definition: communicator.h:102
bool operator!=(const OomphCommunicator &other_comm) const
Definition: communicator.h:224
bool operator==(const OomphCommunicator &other_comm) const
Definition: communicator.h:196
Definition: oomph_definitions.h:222
void source(const Vector< double > &x, Vector< double > &f)
Source function.
Definition: unstructured_two_d_circle.cc:46
void split(const DoubleVector &in_vector, Vector< DoubleVector * > &out_vector_pt)
Definition: double_vector.cc:1413
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86