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