openPMD-api
ADIOS2Auxiliary.hpp
1 /* Copyright 2017-2021 Franz Poeschel.
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser 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  * openPMD-api 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 and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #pragma once
23 
24 #include "openPMD/config.hpp"
25 #if openPMD_HAVE_ADIOS2
26 #include "openPMD/Dataset.hpp"
27 #include "openPMD/Datatype.hpp"
28 #include "openPMD/DatatypeHelpers.hpp"
29 
30 #include <adios2.h>
31 
32 #include <complex>
33 #include <stdexcept>
34 #include <utility>
35 #include <vector>
36 
37 namespace openPMD
38 {
39 namespace detail
40 {
41  // ADIOS2 does not natively support boolean values
42  // Since we need them for attributes,
43  // we represent booleans as unsigned chars
44  using bool_representation = unsigned char;
45 
46  template <typename T>
48  {
49  static std::string type();
50  };
51 
52  template <typename T>
53  struct ToDatatypeHelper<std::vector<T> >
54  {
55  static std::string type();
56  };
57 
58  template <typename T, size_t n>
59  struct ToDatatypeHelper<std::array<T, n> >
60  {
61  static std::string type();
62  };
63 
64  template <>
65  struct ToDatatypeHelper<bool>
66  {
67  static std::string type();
68  };
69 
70  struct ToDatatype
71  {
72  template <typename T>
73  std::string operator()();
74 
75  template <int n>
76  std::string operator()();
77  };
78 
85  Datatype fromADIOS2Type(std::string const &dt, bool verbose = true);
86 
87  enum class VariableOrAttribute : unsigned char
88  {
89  Variable,
90  Attribute
91  };
92 
94  {
95  template <typename T>
96  Extent operator()(
97  adios2::IO &,
98  std::string const &attributeName,
99  VariableOrAttribute);
100 
101  template <int n, typename... Params>
102  Extent operator()(Params &&...);
103  };
104 
117  Datatype attributeInfo(
118  adios2::IO &IO,
119  std::string const &attributeName,
120  bool verbose,
121  VariableOrAttribute voa = VariableOrAttribute::Attribute);
122 } // namespace detail
123 
124 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
125 #define OPENPMD_TEMPLATE_OPERATOR operator
126 #else
127 #define OPENPMD_TEMPLATE_OPERATOR template operator
128 #endif
129 
148 template <typename Action, typename... Args>
149 auto switchAdios2AttributeType(Datatype dt, Action action, Args &&...args)
150  -> decltype(action.OPENPMD_TEMPLATE_OPERATOR() < char > (std::forward<Args>(args)...))
151 {
152  using ReturnType =
153  decltype(action.OPENPMD_TEMPLATE_OPERATOR() < char > (std::forward<Args>(args)...));
154  switch (dt)
155  {
156  case Datatype::CHAR:
157  return action.OPENPMD_TEMPLATE_OPERATOR()<char>(
158  std::forward<Args>(args)...);
159  case Datatype::UCHAR:
160  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned char>(
161  std::forward<Args>(args)...);
162  case Datatype::SHORT:
163  return action.OPENPMD_TEMPLATE_OPERATOR()<short>(
164  std::forward<Args>(args)...);
165  case Datatype::INT:
166  return action.OPENPMD_TEMPLATE_OPERATOR()<int>(
167  std::forward<Args>(args)...);
168  case Datatype::LONG:
169  return action.OPENPMD_TEMPLATE_OPERATOR()<long>(
170  std::forward<Args>(args)...);
171  case Datatype::LONGLONG:
172  return action.OPENPMD_TEMPLATE_OPERATOR()<long long>(
173  std::forward<Args>(args)...);
174  case Datatype::USHORT:
175  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned short>(
176  std::forward<Args>(args)...);
177  case Datatype::UINT:
178  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned int>(
179  std::forward<Args>(args)...);
180  case Datatype::ULONG:
181  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned long>(
182  std::forward<Args>(args)...);
183  case Datatype::ULONGLONG:
184  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned long long>(
185  std::forward<Args>(args)...);
186  case Datatype::FLOAT:
187  return action.OPENPMD_TEMPLATE_OPERATOR()<float>(
188  std::forward<Args>(args)...);
189  case Datatype::DOUBLE:
190  return action.OPENPMD_TEMPLATE_OPERATOR()<double>(
191  std::forward<Args>(args)...);
192  case Datatype::LONG_DOUBLE:
193  return action.OPENPMD_TEMPLATE_OPERATOR()<long double>(
194  std::forward<Args>(args)...);
195  case Datatype::CFLOAT:
196  return action.OPENPMD_TEMPLATE_OPERATOR()<std::complex<float> >(
197  std::forward<Args>(args)...);
198  case Datatype::CDOUBLE:
199  return action.OPENPMD_TEMPLATE_OPERATOR()<std::complex<double> >(
200  std::forward<Args>(args)...);
201  // missing std::complex< long double > type in ADIOS2 v2.6.0
202  // case Datatype::CLONG_DOUBLE:
203  // return action
204  // .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
205  // std::forward< Args >( args )... );
206  case Datatype::STRING:
207  return action.OPENPMD_TEMPLATE_OPERATOR()<std::string>(
208  std::forward<Args>(args)...);
209  case Datatype::DATATYPE:
211  HIGHEST_DATATYPE,
212  ReturnType,
213  Action,
214  void,
215  Args &&...>::call(std::move(action), std::forward<Args>(args)...);
216  case Datatype::UNDEFINED:
218  LOWEST_DATATYPE,
219  ReturnType,
220  Action,
221  void,
222  Args &&...>::call(std::move(action), std::forward<Args>(args)...);
223  default:
224  throw std::runtime_error(
225  "Internal error: Encountered unknown datatype (switchType) ->" +
226  std::to_string(static_cast<int>(dt)));
227  }
228 }
229 
249 template <typename Action, typename... Args>
250 auto switchAdios2VariableType(Datatype dt, Action action, Args &&...args)
251  -> decltype(action.OPENPMD_TEMPLATE_OPERATOR() < char > (std::forward<Args>(args)...))
252 {
253  using ReturnType =
254  decltype(action.OPENPMD_TEMPLATE_OPERATOR() < char > (std::forward<Args>(args)...));
255  switch (dt)
256  {
257  case Datatype::CHAR:
258  return action.OPENPMD_TEMPLATE_OPERATOR()<char>(
259  std::forward<Args>(args)...);
260  case Datatype::UCHAR:
261  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned char>(
262  std::forward<Args>(args)...);
263  case Datatype::SHORT:
264  return action.OPENPMD_TEMPLATE_OPERATOR()<short>(
265  std::forward<Args>(args)...);
266  case Datatype::INT:
267  return action.OPENPMD_TEMPLATE_OPERATOR()<int>(
268  std::forward<Args>(args)...);
269  case Datatype::LONG:
270  return action.OPENPMD_TEMPLATE_OPERATOR()<long>(
271  std::forward<Args>(args)...);
272  case Datatype::LONGLONG:
273  return action.OPENPMD_TEMPLATE_OPERATOR()<long long>(
274  std::forward<Args>(args)...);
275  case Datatype::USHORT:
276  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned short>(
277  std::forward<Args>(args)...);
278  case Datatype::UINT:
279  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned int>(
280  std::forward<Args>(args)...);
281  case Datatype::ULONG:
282  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned long>(
283  std::forward<Args>(args)...);
284  case Datatype::ULONGLONG:
285  return action.OPENPMD_TEMPLATE_OPERATOR()<unsigned long long>(
286  std::forward<Args>(args)...);
287  case Datatype::FLOAT:
288  return action.OPENPMD_TEMPLATE_OPERATOR()<float>(
289  std::forward<Args>(args)...);
290  case Datatype::DOUBLE:
291  return action.OPENPMD_TEMPLATE_OPERATOR()<double>(
292  std::forward<Args>(args)...);
293  case Datatype::LONG_DOUBLE:
294  return action.OPENPMD_TEMPLATE_OPERATOR()<long double>(
295  std::forward<Args>(args)...);
296  case Datatype::CFLOAT:
297  return action.OPENPMD_TEMPLATE_OPERATOR()<std::complex<float> >(
298  std::forward<Args>(args)...);
299  case Datatype::CDOUBLE:
300  return action.OPENPMD_TEMPLATE_OPERATOR()<std::complex<double> >(
301  std::forward<Args>(args)...);
302  // missing std::complex< long double > type in ADIOS2 v2.6.0
303  // case Datatype::CLONG_DOUBLE:
304  // return action
305  // .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
306  // std::forward< Args >( args )... );
307  case Datatype::DATATYPE:
309  HIGHEST_DATATYPE,
310  ReturnType,
311  Action,
312  void,
313  Args &&...>::call(std::move(action), std::forward<Args>(args)...);
314  case Datatype::UNDEFINED:
316  LOWEST_DATATYPE,
317  ReturnType,
318  Action,
319  void,
320  Args &&...>::call(std::move(action), std::forward<Args>(args)...);
321  default:
322  throw std::runtime_error(
323  "Internal error: Encountered unknown datatype (switchType) ->" +
324  std::to_string(static_cast<int>(dt)));
325  }
326 }
327 
328 #undef OPENPMD_TEMPLATE_OPERATOR
329 } // namespace openPMD
330 
331 #endif // openPMD_HAVE_ADIOS2
Definition: ADIOS2Auxiliary.hpp:70
Purpose of this struct is to detect at compile time whether Action::template operator()<0>() exists...
Definition: DatatypeHelpers.hpp:82
STL namespace.
Definition: ADIOS2Auxiliary.hpp:93
auto switchAdios2AttributeType(Datatype dt, Action action, Args &&...args) -> decltype(action. template operator()< char >(std::forward< Args >(args)...))
Generalizes switching over an openPMD datatype.
Definition: ADIOS2Auxiliary.hpp:149
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:45
Varidic datatype supporting at least all formats for attributes specified in the openPMD standard...
Definition: Attribute.hpp:51
Definition: Container.cpp:50
Public definitions of openPMD-api.
Definition: Date.cpp:28
auto switchAdios2VariableType(Datatype dt, Action action, Args &&...args) -> decltype(action. template operator()< char >(std::forward< Args >(args)...))
Generalizes switching over an openPMD datatype.
Definition: ADIOS2Auxiliary.hpp:250
Definition: ADIOS2Auxiliary.hpp:47