Multiscale Universal Interface  2.0
A Concurrent Framework for Coupling Heterogeneous Solvers
comm_mpi.h
Go to the documentation of this file.
1 /*****************************************************************************
2 * Multiscale Universal Interface Code Coupling Library *
3 * *
4 * Copyright (C) 2019 Y. H. Tang, S. Kudo, X. Bian, Z. Li, G. E. Karniadakis *
5 * *
6 * This software is jointly licensed under the Apache License, Version 2.0 *
7 * and the GNU General Public License version 3, you may use it according *
8 * to either. *
9 * *
10 * ** Apache License, version 2.0 ** *
11 * *
12 * Licensed under the Apache License, Version 2.0 (the "License"); *
13 * you may not use this file except in compliance with the License. *
14 * You may obtain a copy of the License at *
15 * *
16 * http://www.apache.org/licenses/LICENSE-2.0 *
17 * *
18 * Unless required by applicable law or agreed to in writing, software *
19 * distributed under the License is distributed on an "AS IS" BASIS, *
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
21 * See the License for the specific language governing permissions and *
22 * limitations under the License. *
23 * *
24 * ** GNU General Public License, version 3 ** *
25 * *
26 * This program is free software: you can redistribute it and/or modify *
27 * it under the terms of the GNU General Public License as published by *
28 * the Free Software Foundation, either version 3 of the License, or *
29 * (at your option) any later version. *
30 * *
31 * This program is distributed in the hope that it will be useful, *
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
34 * GNU General Public License for more details. *
35 * *
36 * You should have received a copy of the GNU General Public License *
37 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
38 ******************************************************************************/
39 
47 #ifndef COMM_MPI_H_
48 #define COMM_MPI_H_
49 
50 #include <mpi.h>
51 #include "comm.h"
52 #include "../general/util.h"
53 #include "lib_uri.h"
54 
55 namespace mui {
56 
57 /*
58  * MPI base implementation of Comm
59  */
60 
61 class comm_mpi : public communicator {
62 public:
63  comm_mpi( const char URI[], const bool quiet, MPI_Comm world ) :
64  domain_local_(0),
65  domain_remote_(0),
66  local_size_(0),
67  local_rank_(0),
68  remote_size_(0),
69  global_size_(0),
70  global_rank_(0),
71  uri_host_(std::string()),
72  uri_path_(std::string()),
73  uri_protocol_(std::string()),
74  initialized(false),
75  init_by_me(false) {
76  init(URI, quiet, world);
77  }
78  virtual ~comm_mpi() {
79  finalize();
80  }
81 
82  void init( const char URI[], const bool quiet, MPI_Comm world ) {
83  if ( initialized )
84  throw( std::runtime_error("MUI Error [comm_mpi.h]: Duplicate MUI communicator initialization") );
85 
86  // check MPI initialization status
87  int init;
88  MPI_Initialized( &init );
89  if (!init) {
90  init_by_me = true;
91  MPI_Init( NULL, NULL );
92  }
93 
94  // duplicate world to avoid potential conflict with host program
95  if (world == MPI_COMM_WORLD) MPI_Comm_dup( MPI_COMM_WORLD, &world );
96  MPI_Comm_size( world, &global_size_ );
97  MPI_Comm_rank( world, &global_rank_ );
98  if (global_size_ < 2)
99  std::cout << "MUI Warning [comm_mpi.h]: Number of global ranks less than 2" << std::endl;
100 
101  // get upper bond for tag hash
102  int prime;
103  {
104  int* v;
105  int flag;
106  MPI_Comm_get_attr(MPI_COMM_WORLD,MPI_TAG_UB,&v,&flag);
107  prime = *v;
108  }
109 
110  // parse URI, split the world using domain tag
111  uri desc(URI);
112  uri_host_ = desc.host();
113  uri_path_ = desc.path();
114  uri_protocol_ = desc.protocol();
115  int domain_hash = std::hash<std::string>()( desc.host() );
116  domain_hash=std::abs(domain_hash);
117  int ifs_hash = std::hash<std::string>()( desc.path() );
118  ifs_hash=std::abs(ifs_hash);
119  MPI_Comm_split( world, domain_hash % prime, global_rank_, &domain_local_ );
120  MPI_Comm_size( domain_local_, &local_size_ );
121  MPI_Comm_rank( domain_local_, &local_rank_ );
122 
123  // set intercommunication using interface tag
124  std::vector<int> all_domain( global_size_, 0 );
125  std::vector<int> all_ifs ( global_size_, 0 );
126  MPI_Allgather( &domain_hash, 1, MPI_INT, &all_domain[0], 1, MPI_INT, world );
127  MPI_Allgather( &ifs_hash, 1, MPI_INT, &all_ifs[0], 1, MPI_INT, world );
128  for( int i = 0 ; i < global_size_ ; i++ ) {
129  if ( i == global_rank_ ) continue;
130  if ( all_domain[i] != domain_hash && all_ifs[i] == ifs_hash ) {
131  MPI_Intercomm_create( domain_local_, 0, world, i, ifs_hash % prime, &domain_remote_ );
132  break;
133  }
134  }
135  MPI_Comm_remote_size( domain_remote_, &remote_size_ );
136 
137  // output for debugging
138  if( !quiet ) {
139  std::cout << "MUI [comm_mpi.h]: Rank: " << global_rank_ << ", "
140  << "Identifier: " << URI << ", "
141  << "Domain size: " << local_size_ << ", "
142  << "Peers: " << remote_size_
143  << std::endl;
144  }
145  else {
146  if( local_rank_ == 0 ) {
147  std::cout << "MUI [comm_mpi.h]: " << "Identifier: " << URI << ", "
148  << "Domain size: " << local_size_ << ", "
149  << "Peers: " << remote_size_
150  << std::endl;
151  }
152  }
153  MPI_Barrier( world );
154 
155  initialized = true;
156  }
157 
158  void finalize() {
159  if ( initialized && init_by_me ) MPI_Finalize();
160  }
161 
162  virtual int local_size() const { return local_size_; }
163  virtual int local_rank() const { return local_rank_; }
164  virtual int remote_size() const { return remote_size_; }
165  virtual int global_size() const { return global_size_; }
166  virtual int global_rank() const { return global_rank_; }
167  virtual std::string uri_host() const { return uri_host_; }
168  virtual std::string uri_path() const { return uri_path_; }
169  virtual std::string uri_protocol() const { return uri_protocol_; }
170 
171 protected:
172  MPI_Comm domain_local_;
173  MPI_Comm domain_remote_;
179  std::string uri_host_;
180  std::string uri_path_;
181  std::string uri_protocol_;
182 private:
183  bool initialized;
184  bool init_by_me;
185 };
186 
187 }
188 
189 #endif
Definition: comm_mpi.h:61
int local_rank_
Definition: comm_mpi.h:175
void init(const char URI[], const bool quiet, MPI_Comm world)
Definition: comm_mpi.h:82
virtual ~comm_mpi()
Definition: comm_mpi.h:78
MPI_Comm domain_remote_
Definition: comm_mpi.h:173
int global_rank_
Definition: comm_mpi.h:178
std::string uri_protocol_
Definition: comm_mpi.h:181
MPI_Comm domain_local_
Definition: comm_mpi.h:172
virtual int local_size() const
Definition: comm_mpi.h:162
virtual std::string uri_path() const
Definition: comm_mpi.h:168
int global_size_
Definition: comm_mpi.h:177
std::string uri_host_
Definition: comm_mpi.h:179
int remote_size_
Definition: comm_mpi.h:176
void finalize()
Definition: comm_mpi.h:158
virtual int local_rank() const
Definition: comm_mpi.h:163
std::string uri_path_
Definition: comm_mpi.h:180
virtual int remote_size() const
Definition: comm_mpi.h:164
virtual std::string uri_host() const
Definition: comm_mpi.h:167
virtual int global_rank() const
Definition: comm_mpi.h:166
virtual int global_size() const
Definition: comm_mpi.h:165
comm_mpi(const char URI[], const bool quiet, MPI_Comm world)
Definition: comm_mpi.h:63
int local_size_
Definition: comm_mpi.h:174
virtual std::string uri_protocol() const
Definition: comm_mpi.h:169
Definition: comm.h:55
Definition: lib_uri.h:55
const std::string & protocol() const
Definition: lib_uri.h:63
const std::string & host() const
Definition: lib_uri.h:64
const std::string & path() const
Definition: lib_uri.h:65
File containing class definition of communication interface. This is the base class for all other com...
Base class to contain and manipulate a unique URI (Uniform Resource Identifier).
Definition: comm.h:54