My Project
MPIPacker.hpp
1 /*
2  Copyright 2019 Equinor AS.
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef MPI_PACKER_HPP
20 #define MPI_PACKER_HPP
21 
22 #include <opm/common/utility/TimeService.hpp>
23 #include <opm/simulators/utils/ParallelCommunication.hpp>
24 
25 #include <dune/common/parallel/mpitraits.hh>
26 
27 #include <bitset>
28 #include <cstddef>
29 #include <string>
30 
31 namespace Opm {
32 namespace Mpi {
33 namespace detail {
34 
36 template <bool pod, class T>
37 struct Packing
38 {
39  static std::size_t packSize(const T&, Parallel::MPIComm);
40  static void pack(const T&, std::vector<char>&, int&, Parallel::MPIComm);
41  static void unpack(T&, std::vector<char>&, int&, Parallel::MPIComm);
42 };
43 
45 template<class T>
46 struct Packing<true,T>
47 {
51  static std::size_t packSize(const T& data, Parallel::MPIComm comm)
52  {
53  return packSize(&data, 1, comm);
54  }
55 
60  static std::size_t packSize(const T*, std::size_t n, Parallel::MPIComm comm)
61  {
62  int size = 0;
63  MPI_Pack_size(n, Dune::MPITraits<T>::getType(), comm, &size);
64  return size;
65  }
66 
72  static void pack(const T& data,
73  std::vector<char>& buffer,
74  int& position,
75  Parallel::MPIComm comm)
76  {
77  pack(&data, 1, buffer, position, comm);
78  }
79 
86  static void pack(const T* data,
87  std::size_t n,
88  std::vector<char>& buffer,
89  int& position,
90  Parallel::MPIComm comm)
91  {
92  MPI_Pack(data, n, Dune::MPITraits<T>::getType(), buffer.data(),
93  buffer.size(), &position, comm);
94  }
95 
101  static void unpack(T& data,
102  std::vector<char>& buffer,
103  int& position,
104  Parallel::MPIComm comm)
105  {
106  unpack(&data, 1, buffer, position, comm);
107  }
108 
115  static void unpack(T* data,
116  std::size_t n,
117  std::vector<char>& buffer,
118  int& position,
119  Parallel::MPIComm comm)
120  {
121  MPI_Unpack(buffer.data(), buffer.size(), &position, data, n,
122  Dune::MPITraits<T>::getType(), comm);
123  }
124 };
125 
127 template<class T>
128 struct Packing<false,T>
129 {
130  static std::size_t packSize(const T&, Parallel::MPIComm)
131  {
132  static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
133  return 0;
134  }
135 
136  static void pack(const T&, std::vector<char>&, int&,
137  Parallel::MPIComm)
138  {
139  static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
140  }
141 
142  static void unpack(T&, std::vector<char>&, int&,
143  Parallel::MPIComm)
144  {
145  static_assert(!std::is_same_v<T,T>, "Packing not supported for type");
146  }
147 };
148 
150 template <std::size_t Size>
151 struct Packing<false,std::bitset<Size>>
152 {
153  static std::size_t packSize(const std::bitset<Size>&, Opm::Parallel::MPIComm);
154  static void pack(const std::bitset<Size>&, std::vector<char>&, int&, Opm::Parallel::MPIComm);
155  static void unpack(std::bitset<Size>&, std::vector<char>&, int&, Opm::Parallel::MPIComm);
156 };
157 
158 #define ADD_PACK_SPECIALIZATION(T) \
159  template<> \
160  struct Packing<false,T> \
161  { \
162  static std::size_t packSize(const T&, Parallel::MPIComm); \
163  static void pack(const T&, std::vector<char>&, int&, Parallel::MPIComm); \
164  static void unpack(T&, std::vector<char>&, int&, Parallel::MPIComm); \
165  };
166 
167 ADD_PACK_SPECIALIZATION(std::string)
168 ADD_PACK_SPECIALIZATION(time_point)
169 
170 #undef ADD_PACK_SPECIALIZATION
171 
172 }
173 
175 struct Packer {
178  Packer(Parallel::Communication comm)
179  : m_comm(comm)
180  {}
181 
185  template<class T>
186  std::size_t packSize(const T& data) const
187  {
188  return detail::Packing<std::is_pod_v<T>,T>::packSize(data, m_comm);
189  }
190 
195  template<class T>
196  std::size_t packSize(const T* data, std::size_t n) const
197  {
198  static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
199  return detail::Packing<true,T>::packSize(data, n, m_comm);
200  }
201 
207  template<class T>
208  void pack(const T& data,
209  std::vector<char>& buffer,
210  int& position) const
211  {
212  detail::Packing<std::is_pod_v<T>,T>::pack(data, buffer, position, m_comm);
213  }
214 
221  template<class T>
222  void pack(const T* data,
223  std::size_t n,
224  std::vector<char>& buffer,
225  int& position) const
226  {
227  static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
228  detail::Packing<true,T>::pack(data, n, buffer, position, m_comm);
229  }
230 
236  template<class T>
237  void unpack(T& data,
238  std::vector<char>& buffer,
239  int& position) const
240  {
241  detail::Packing<std::is_pod_v<T>,T>::unpack(data, buffer, position, m_comm);
242  }
243 
250  template<class T>
251  void unpack(T* data,
252  std::size_t n,
253  std::vector<char>& buffer,
254  int& position) const
255  {
256  static_assert(std::is_pod_v<T>, "Array packing not supported for non-pod data");
257  detail::Packing<true,T>::unpack(data, n, buffer, position, m_comm);
258  }
259 
260 private:
261  Parallel::Communication m_comm;
262 };
263 
264 } // end namespace Mpi
265 } // end namespace Opm
266 
267 #endif // MPI_PACKER_HPP
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
Struct handling packing of serialization for MPI communication.
Definition: MPIPacker.hpp:175
void unpack(T *data, std::size_t n, std::vector< char > &buffer, int &position) const
Unpack an array.
Definition: MPIPacker.hpp:251
void pack(const T *data, std::size_t n, std::vector< char > &buffer, int &position) const
Pack an array.
Definition: MPIPacker.hpp:222
Packer(Parallel::Communication comm)
Constructor.
Definition: MPIPacker.hpp:178
std::size_t packSize(const T *data, std::size_t n) const
Calculates the pack size for an array.
Definition: MPIPacker.hpp:196
void pack(const T &data, std::vector< char > &buffer, int &position) const
Pack a variable.
Definition: MPIPacker.hpp:208
std::size_t packSize(const T &data) const
Calculates the pack size for a variable.
Definition: MPIPacker.hpp:186
void unpack(T &data, std::vector< char > &buffer, int &position) const
Unpack a variable.
Definition: MPIPacker.hpp:237
static void unpack(T &data, std::vector< char > &buffer, int &position, Parallel::MPIComm comm)
Unpack a POD.
Definition: MPIPacker.hpp:101
static void pack(const T *data, std::size_t n, std::vector< char > &buffer, int &position, Parallel::MPIComm comm)
Pack an array of POD.
Definition: MPIPacker.hpp:86
static std::size_t packSize(const T *, std::size_t n, Parallel::MPIComm comm)
Calculates the pack size for an array of POD.
Definition: MPIPacker.hpp:60
static void unpack(T *data, std::size_t n, std::vector< char > &buffer, int &position, Parallel::MPIComm comm)
Unpack an array of POD.
Definition: MPIPacker.hpp:115
static void pack(const T &data, std::vector< char > &buffer, int &position, Parallel::MPIComm comm)
Pack a POD.
Definition: MPIPacker.hpp:72
static std::size_t packSize(const T &data, Parallel::MPIComm comm)
Calculates the pack size for a POD.
Definition: MPIPacker.hpp:51
Abstract struct for packing which is (partially) specialized for specific types.
Definition: MPIPacker.hpp:38