svFSIplus
CmMod.h
1 /**
2  * Copyright (c) Stanford University, The Regents of the University of California, and others.
3  *
4  * All Rights Reserved.
5  *
6  * See Copyright-SimVascular.txt for additional details.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining
9  * a copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sublicense, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject
14  * to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 // The classes defined here duplicate the data structures in the Fortran CMMOD module
33 // defined in COMU.f.
34 
35 #ifndef CMMOD_H
36 #define CMMOD_H
37 
38 #include "Array.h"
39 #include "Vector.h"
40 
41 #include "mpi.h"
42 #include "consts.h"
43 
44 #include <string>
45 
46 namespace cm_mod {
47 
48 using MpiCommWorldType = MPI_Comm;
49 //using MpiCommWorldType = decltype(MPI_COMM_WORLD);
50 
51 // Set MPI data type names.
52 const decltype(MPI_CXX_BOOL) mplog = MPI_CXX_BOOL;
53 //const decltype(MPI_LOGICAL) mplog = MPI_LOGICAL;
54 const decltype(MPI_INTEGER) mpint = MPI_INTEGER;
55 const decltype(MPI_DOUBLE_PRECISION) mpreal = MPI_DOUBLE_PRECISION;
56 const decltype(MPI_CHARACTER) mpchar = MPI_CHARACTER;
57 };
58 
59 /// @brief The CmMod class duplicates the data structures in the Fortran CMMOD module
60 /// defined in COMU.f.
61 ///
62 /// The data members here are the global variables exposed by the CMMOD module.
63 class CmMod {
64 
65  public:
66  CmMod();
67  ~CmMod();
68 
69  // Size of blocks for openMP communications.
70  int mpBs = 1000;
71 
72  // master is assumed to have zero ID
73  int master = 0;
74 
75  // Abstracted MPI names.
76  decltype(MPI_LOGICAL) mplog = MPI_LOGICAL;
77  decltype(MPI_INTEGER) mpint = MPI_INTEGER;
78  decltype(MPI_DOUBLE_PRECISION) mpreal = MPI_DOUBLE_PRECISION;
79  decltype(MPI_CHARACTER) mpchar = MPI_CHARACTER;
80 };
81 
82 /// @brief The cmType class stores data and defines methods used for mpi communication.
83 class cmType {
84  public:
85  cmType();
86  ~cmType();
87 
88  // Communicator handle.
89  decltype(MPI_COMM_WORLD) cHndl;
90 
91  // Processors ID.
92  int taskId = 0;
93 
94  // Number of openMP threads in this cm
95  int nThreads = 0;
96 
97  // Number of processors
98  int nProcs = 0;
99 
100  //----- M e t h o d s -----//
101 
102  void bcast(const CmMod& cm_mod, bool* data) const;
103  void bcast(const CmMod& cm_mod, std::vector<bool>& data) const;
104 
105  void bcast(const CmMod& cm_mod, std::string& data) const;
106 
107  void bcast(const CmMod& cm_mod, double* data) const;
108  void bcast(const CmMod& cm_mod, Vector<double>& data, const std::string& name="") const;
109  void bcast(const CmMod& cm_mod, Array<double>& data, const std::string& name="") const;
110 
111  void bcast(const CmMod& cm_mod, int* data) const;
112  void bcast(const CmMod& cm_mod, Vector<int>& data) const;
113 
114  //------------
115  // bcast_enum
116  //------------
117  //
118  template <typename T>
119  void bcast_enum(const CmMod& cm_mod, T* data) const
120  {
121  int idata = static_cast<int>(*data);
122  //std::cout << "[bcast_enum] idata in: " << idata << std::endl;
123  MPI_Bcast(&idata, 1, cm_mod::mpint, cm_mod.master, com());
124  //std::cout << "[bcast_enum] idata out: " << idata << std::endl;
125  *data = static_cast<T>(idata);
126  }
127 
128  //------------
129  // bcast_prop
130  //------------
131  //
132  template <typename T>
133  void bcast_prop(const CmMod& cm_mod, std::map<T,double>& props) const
134  {
135  static const int MAX_SIZE = 100;
136 
137  if (2*props.size() > MAX_SIZE) {
138  throw std::runtime_error("bcast prop is larger than " + std::to_string(MAX_SIZE) + ".");
139  }
140 
141  double prop_array[MAX_SIZE];
142  std::fill_n(prop_array, MAX_SIZE, -1.0);
143 
144  int n = 0;
145  for (auto& entry : props) {
146  prop_array[n++] = static_cast<int>(entry.first);
147  prop_array[n++] = entry.second;
148  }
149 
150  MPI_Bcast(prop_array, MAX_SIZE, cm_mod::mpreal, cm_mod.master, com());
151 
152  props.clear();
153  int num_props = MAX_SIZE / 2;;
154 
155  for (int i = 0; i < num_props; i++) {
156  int iprop = static_cast<int>(prop_array[2*i]);
157  if (iprop == -1) {
158  break;
159  }
160  auto prop = static_cast<T>(iprop);
161  props[prop] = prop_array[2*i+1];
162  }
163  }
164 
165  // Returns commu handle
166  cm_mod::MpiCommWorldType com() const;
167  //decltype(MPI_COMM_WORLD) com() const;
168 
169  int idcm() const { return taskId; };
170  int id() { return taskId; };
171  bool mas(const CmMod& cm_mod) const { return (taskId == cm_mod.master); };
172 
173  // Create a new Communicator
174  void new_cm(decltype(MPI_COMM_WORLD) comHandle);
175 
176  int np() const { return nProcs; };
177 
178  int nT() { return nThreads; };
179 
180 
181  //--------
182  // reduce
183  //--------
184  // For an int or double scalar.
185  //
186  template<typename T>
187  T reduce(const CmMod& cm_mod, T u, MPI_Op op = MPI_SUM) const
188  {
189  T gU{};
190 
191  MPI_Datatype data_type;
192  if (typeid(T) == typeid(double)) {
193  data_type = MPI_DOUBLE_PRECISION;
194  } else if (typeid(T) == typeid(int)) {
195  data_type = MPI_INTEGER;
196  } else {
197  throw std::runtime_error("[cm_mod::reduce called with unknown data type.");
198  }
199 
200  if (seq()) {
201  gU = u;
202  } else {
203  MPI_Allreduce(&u, &gU, 1, data_type, op, com());
204  }
205 
206  return gU;
207  }
208 
209  //--------
210  // reduce
211  //--------
212  // For an int or double Vector.
213  //
214  template<typename T>
215  Vector<T> reduce(const CmMod& cm_mod, Vector<T>& u, MPI_Op op = MPI_SUM) const
216  {
217  int size = u.size();
218  Vector<T> gU(size);
219 
220  MPI_Datatype data_type;
221  if (typeid(T) == typeid(double)) {
222  data_type = MPI_DOUBLE_PRECISION;
223  } if (typeid(T) == typeid(int)) {
224  data_type = MPI_INTEGER;
225  }
226 
227  if (seq()) {
228  gU = u;
229  } else {
230  MPI_Allreduce(u.data(), gU.data(), size, data_type, op, com());
231  }
232 
233  return gU;
234  }
235 
236  bool seq() const { return (nProcs == 1); };
237 
238  bool slv(const CmMod& cm_mod) const { return (taskId != cm_mod.master); };
239 
240  // Returns processor ID in fortran indexing
241  int tF(const CmMod& cm_mod) const { return taskId + 1; };
242 
243 };
244 
245 
246 #endif
247 
The CmMod class duplicates the data structures in the Fortran CMMOD module defined in COMU....
Definition: CmMod.h:63
CmMod()
Definition: CmMod.cpp:39
The cmType class stores data and defines methods used for mpi communication.
Definition: CmMod.h:83
void bcast(const CmMod &cm_mod, bool *data) const
bcast bool.
Definition: CmMod.cpp:81
Definition: CmMod.h:46