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 > struct ToDatatypeHelper
47  {
48  static std::string type( );
49  };
50 
51  template < typename T > struct ToDatatypeHelper< std::vector< T > >
52  {
53  static std::string type( );
54  };
55 
56  template < typename T, size_t n >
57  struct ToDatatypeHelper< std::array< T, n > >
58  {
59  static std::string type( );
60  };
61 
62  template <> struct ToDatatypeHelper< bool >
63  {
64  static std::string type( );
65  };
66 
67  struct ToDatatype
68  {
69  template < typename T > std::string operator( )( );
70 
71 
72  template < int n > std::string operator( )( );
73  };
74 
81  Datatype fromADIOS2Type( std::string const & dt, bool verbose = true );
82 
83  enum class VariableOrAttribute : unsigned char
84  {
85  Variable,
86  Attribute
87  };
88 
90  {
91  template< typename T >
92  Extent
93  operator()(
94  adios2::IO &,
95  std::string const & attributeName,
96  VariableOrAttribute );
97 
98  template < int n, typename... Params >
99  Extent operator( )( Params &&... );
100  };
101 
111  Datatype
112  attributeInfo(
113  adios2::IO & IO,
114  std::string const & attributeName,
115  bool verbose,
116  VariableOrAttribute = VariableOrAttribute::Attribute );
117 } // namespace detail
118 
119 #if defined( _MSC_VER ) && !defined( __INTEL_COMPILER ) && !defined( __clang__ )
120 #define OPENPMD_TEMPLATE_OPERATOR operator
121 #else
122 #define OPENPMD_TEMPLATE_OPERATOR template operator
123 #endif
124 
143 template< typename Action, typename... Args >
144 auto switchAdios2AttributeType( Datatype dt, Action action, Args &&... args )
145  -> decltype(
146  action.OPENPMD_TEMPLATE_OPERATOR() < char >
147  ( std::forward< Args >( args )... ) )
148 {
149  using ReturnType = decltype(
150  action.OPENPMD_TEMPLATE_OPERATOR() < char >
151  ( std::forward< Args >( args )... ) );
152  switch( dt )
153  {
154  case Datatype::CHAR:
155  return action.OPENPMD_TEMPLATE_OPERATOR()< char >(
156  std::forward< Args >( args )... );
157  case Datatype::UCHAR:
158  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned char >(
159  std::forward< Args >( args )... );
160  case Datatype::SHORT:
161  return action.OPENPMD_TEMPLATE_OPERATOR()< short >(
162  std::forward< Args >( args )... );
163  case Datatype::INT:
164  return action.OPENPMD_TEMPLATE_OPERATOR()< int >(
165  std::forward< Args >( args )... );
166  case Datatype::LONG:
167  return action.OPENPMD_TEMPLATE_OPERATOR()< long >(
168  std::forward< Args >( args )... );
169  case Datatype::LONGLONG:
170  return action.OPENPMD_TEMPLATE_OPERATOR()< long long >(
171  std::forward< Args >( args )... );
172  case Datatype::USHORT:
173  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned short >(
174  std::forward< Args >( args )... );
175  case Datatype::UINT:
176  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned int >(
177  std::forward< Args >( args )... );
178  case Datatype::ULONG:
179  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long >(
180  std::forward< Args >( args )... );
181  case Datatype::ULONGLONG:
182  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long long >(
183  std::forward< Args >( args )... );
184  case Datatype::FLOAT:
185  return action.OPENPMD_TEMPLATE_OPERATOR()< float >(
186  std::forward< Args >( args )... );
187  case Datatype::DOUBLE:
188  return action.OPENPMD_TEMPLATE_OPERATOR()< double >(
189  std::forward< Args >( args )... );
190  case Datatype::LONG_DOUBLE:
191  return action.OPENPMD_TEMPLATE_OPERATOR()< long double >(
192  std::forward< Args >( args )... );
193  case Datatype::CFLOAT:
194  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< float > >(
195  std::forward< Args >( args )... );
196  case Datatype::CDOUBLE:
197  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< double > >(
198  std::forward< Args >( args )... );
199  // missing std::complex< long double > type in ADIOS2 v2.6.0
200  // case Datatype::CLONG_DOUBLE:
201  // return action
202  // .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
203  // std::forward< Args >( args )... );
204  case Datatype::STRING:
205  return action.OPENPMD_TEMPLATE_OPERATOR()< std::string >(
206  std::forward< Args >( args )... );
207  case Datatype::DATATYPE:
209  HIGHEST_DATATYPE,
210  ReturnType,
211  Action,
212  void,
213  Args &&... >::
214  call( std::move( action ), std::forward< Args >( args )... );
215  case Datatype::UNDEFINED:
217  LOWEST_DATATYPE,
218  ReturnType,
219  Action,
220  void,
221  Args &&... >::
222  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(
252  action.OPENPMD_TEMPLATE_OPERATOR() < char >
253  ( std::forward< Args >( args )... ) )
254 {
255  using ReturnType = decltype(
256  action.OPENPMD_TEMPLATE_OPERATOR() < char >
257  ( std::forward< Args >( args )... ) );
258  switch( dt )
259  {
260  case Datatype::CHAR:
261  return action.OPENPMD_TEMPLATE_OPERATOR()< char >(
262  std::forward< Args >( args )... );
263  case Datatype::UCHAR:
264  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned char >(
265  std::forward< Args >( args )... );
266  case Datatype::SHORT:
267  return action.OPENPMD_TEMPLATE_OPERATOR()< short >(
268  std::forward< Args >( args )... );
269  case Datatype::INT:
270  return action.OPENPMD_TEMPLATE_OPERATOR()< int >(
271  std::forward< Args >( args )... );
272  case Datatype::LONG:
273  return action.OPENPMD_TEMPLATE_OPERATOR()< long >(
274  std::forward< Args >( args )... );
275  case Datatype::LONGLONG:
276  return action.OPENPMD_TEMPLATE_OPERATOR()< long long >(
277  std::forward< Args >( args )... );
278  case Datatype::USHORT:
279  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned short >(
280  std::forward< Args >( args )... );
281  case Datatype::UINT:
282  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned int >(
283  std::forward< Args >( args )... );
284  case Datatype::ULONG:
285  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long >(
286  std::forward< Args >( args )... );
287  case Datatype::ULONGLONG:
288  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long long >(
289  std::forward< Args >( args )... );
290  case Datatype::FLOAT:
291  return action.OPENPMD_TEMPLATE_OPERATOR()< float >(
292  std::forward< Args >( args )... );
293  case Datatype::DOUBLE:
294  return action.OPENPMD_TEMPLATE_OPERATOR()< double >(
295  std::forward< Args >( args )... );
296  case Datatype::LONG_DOUBLE:
297  return action.OPENPMD_TEMPLATE_OPERATOR()< long double >(
298  std::forward< Args >( args )... );
299  case Datatype::CFLOAT:
300  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< float > >(
301  std::forward< Args >( args )... );
302  case Datatype::CDOUBLE:
303  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< double > >(
304  std::forward< Args >( args )... );
305  // missing std::complex< long double > type in ADIOS2 v2.6.0
306  // case Datatype::CLONG_DOUBLE:
307  // return action
308  // .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
309  // std::forward< Args >( args )... );
310  case Datatype::DATATYPE:
312  HIGHEST_DATATYPE,
313  ReturnType,
314  Action,
315  void,
316  Args &&... >::
317  call( std::move( action ), std::forward< Args >( args )... );
318  case Datatype::UNDEFINED:
320  LOWEST_DATATYPE,
321  ReturnType,
322  Action,
323  void,
324  Args &&... >::
325  call( std::move( action ), std::forward< Args >( args )... );
326  default:
327  throw std::runtime_error(
328  "Internal error: Encountered unknown datatype (switchType) ->" +
329  std::to_string( static_cast< int >( dt ) ) );
330  }
331 }
332 
333 #undef OPENPMD_TEMPLATE_OPERATOR
334 } // namespace openPMD
335 
336 #endif // openPMD_HAVE_ADIOS2
Definition: ADIOS2Auxiliary.hpp:67
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
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:89
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:144
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:50
Definition: Container.cpp:51
Public definitions of openPMD-api.
Definition: Date.cpp:29
Definition: ADIOS2Auxiliary.hpp:46