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/Error.hpp"
25 #include "openPMD/IO/ADIOS/macros.hpp"
26 #include "openPMD/config.hpp"
27 
28 #if openPMD_HAVE_ADIOS2
29 #include "openPMD/Dataset.hpp"
30 #include "openPMD/Datatype.hpp"
31 #include "openPMD/DatatypeHelpers.hpp"
32 
33 #include <adios2.h>
34 
35 #include <complex>
36 #include <stdexcept>
37 #include <utility>
38 #include <vector>
39 #endif
40 
41 namespace openPMD
42 {
43 enum class GroupOrDataset
44 {
45  GROUP,
46  DATASET
47 };
48 
49 namespace adios_defs
50 {
51  enum class FlushTarget : unsigned char
52  {
53  Buffer,
54  Buffer_Override,
55  Disk,
56  Disk_Override
57  };
58 
59  using FlushTarget = adios_defs::FlushTarget;
60  FlushTarget flushTargetFromString(std::string const &str);
61 
62  enum class UseGroupTable
63  {
64  Yes,
65  No
66  };
67 } // namespace adios_defs
68 
69 /*
70  * The following strings are used during parsing of the JSON configuration
71  * string for the ADIOS2 backend.
72  */
73 namespace adios_defaults
74 {
75  using const_str = char const *const;
76  constexpr const_str str_engine = "engine";
77  constexpr const_str str_type = "type";
78  constexpr const_str str_params = "parameters";
79  constexpr const_str str_usesteps = "usesteps";
80  constexpr const_str str_flushtarget = "preferred_flush_target";
81  constexpr const_str str_usesstepsAttribute = "__openPMD_internal/useSteps";
82  constexpr const_str str_adios2Schema =
83  "__openPMD_internal/openPMD2_adios2_schema";
84  constexpr const_str str_isBoolean = "__is_boolean__";
85  constexpr const_str str_activeTablePrefix = "__openPMD_groups";
86  constexpr const_str str_groupBasedWarning =
87  "__openPMD_internal/warning_bugprone_groupbased_encoding";
88 } // namespace adios_defaults
89 
90 #if openPMD_HAVE_ADIOS2
91 namespace detail
92 {
93  // ADIOS2 does not natively support boolean values
94  // Since we need them for attributes,
95  // we represent booleans as unsigned chars
96  using bool_representation = unsigned char;
97 
98  template <typename T>
100  {
101  static std::string type();
102  };
103 
104  template <typename T>
105  struct ToDatatypeHelper<std::vector<T>>
106  {
107  static std::string type();
108  };
109 
110  template <typename T, size_t n>
111  struct ToDatatypeHelper<std::array<T, n>>
112  {
113  static std::string type();
114  };
115 
116  template <>
117  struct ToDatatypeHelper<bool>
118  {
119  static std::string type();
120  };
121 
122  struct ToDatatype
123  {
124  template <typename T>
125  std::string operator()();
126 
127  template <int n>
128  std::string operator()();
129  };
130 
137  Datatype fromADIOS2Type(std::string const &dt, bool verbose = true);
138 
139  enum class VariableOrAttribute : unsigned char
140  {
141  Variable,
142  Attribute
143  };
144 
146  {
147  template <typename T>
148  static Extent call(
149  adios2::IO &,
150  std::string const &attributeName,
151  VariableOrAttribute);
152 
153  template <int n, typename... Params>
154  static Extent call(Params &&...);
155  };
156 
169  Datatype attributeInfo(
170  adios2::IO &IO,
171  std::string const &attributeName,
172  bool verbose,
173  VariableOrAttribute voa = VariableOrAttribute::Attribute);
174 
175  inline bool readOnly(adios2::Mode mode)
176  {
177  switch (mode)
178  {
179  case adios2::Mode::Append:
180  case adios2::Mode::Write:
181  return false;
182  case adios2::Mode::Read:
183 #if openPMD_HAS_ADIOS_2_8
184  case adios2::Mode::ReadRandomAccess:
185 #endif
186  return true;
187  case adios2::Mode::Undefined:
188  case adios2::Mode::Sync:
189  case adios2::Mode::Deferred:
190  break;
191  }
192  throw error::Internal("Control flow error: No ADIOS2 open mode.");
193  }
194  inline bool writeOnly(adios2::Mode mode)
195  {
196  switch (mode)
197  {
198  case adios2::Mode::Append:
199  case adios2::Mode::Write:
200  return true;
201  case adios2::Mode::Read:
202 #if openPMD_HAS_ADIOS_2_8
203  case adios2::Mode::ReadRandomAccess:
204 #endif
205  return false;
206  case adios2::Mode::Undefined:
207  case adios2::Mode::Sync:
208  case adios2::Mode::Deferred:
209  break;
210  }
211  throw error::Internal("Control flow error: No ADIOS2 open mode.");
212  }
213 } // namespace detail
214 
230 template <typename Action, typename... Args>
231 auto switchAdios2AttributeType(Datatype dt, Args &&...args)
232  -> decltype(Action::template call<char>(std::forward<Args>(args)...))
233 {
234  using ReturnType =
235  decltype(Action::template call<char>(std::forward<Args>(args)...));
236  switch (dt)
237  {
238  case Datatype::CHAR:
239  return Action::template call<char>(std::forward<Args>(args)...);
240  case Datatype::UCHAR:
241  return Action::template call<unsigned char>(
242  std::forward<Args>(args)...);
243  case Datatype::SCHAR:
244  return Action::template call<signed char>(std::forward<Args>(args)...);
245  case Datatype::SHORT:
246  return Action::template call<short>(std::forward<Args>(args)...);
247  case Datatype::INT:
248  return Action::template call<int>(std::forward<Args>(args)...);
249  case Datatype::LONG:
250  return Action::template call<long>(std::forward<Args>(args)...);
251  case Datatype::LONGLONG:
252  return Action::template call<long long>(std::forward<Args>(args)...);
253  case Datatype::USHORT:
254  return Action::template call<unsigned short>(
255  std::forward<Args>(args)...);
256  case Datatype::UINT:
257  return Action::template call<unsigned int>(std::forward<Args>(args)...);
258  case Datatype::ULONG:
259  return Action::template call<unsigned long>(
260  std::forward<Args>(args)...);
261  case Datatype::ULONGLONG:
262  return Action::template call<unsigned long long>(
263  std::forward<Args>(args)...);
264  case Datatype::FLOAT:
265  return Action::template call<float>(std::forward<Args>(args)...);
266  case Datatype::DOUBLE:
267  return Action::template call<double>(std::forward<Args>(args)...);
268  case Datatype::LONG_DOUBLE:
269  return Action::template call<long double>(std::forward<Args>(args)...);
270  case Datatype::CFLOAT:
271  return Action::template call<std::complex<float>>(
272  std::forward<Args>(args)...);
273  case Datatype::CDOUBLE:
274  return Action::template call<std::complex<double>>(
275  std::forward<Args>(args)...);
276  // missing std::complex< long double > type in ADIOS2 v2.6.0
277  // case Datatype::CLONG_DOUBLE:
278  // return action
279  // .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
280  // std::forward< Args >( args )... );
281  case Datatype::STRING:
282  return Action::template call<std::string>(std::forward<Args>(args)...);
283  case Datatype::UNDEFINED:
284  return detail::
285  CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call(
286  std::forward<Args>(args)...);
287  default:
288  throw std::runtime_error(
289  "Internal error: Encountered unknown datatype (switchType) ->" +
290  std::to_string(static_cast<int>(dt)));
291  }
292 }
293 
310 template <typename Action, typename... Args>
311 auto switchAdios2VariableType(Datatype dt, Args &&...args)
312  -> decltype(Action::template call<char>(std::forward<Args>(args)...))
313 {
314  using ReturnType =
315  decltype(Action::template call<char>(std::forward<Args>(args)...));
316  switch (dt)
317  {
318  case Datatype::CHAR:
319  return Action::template call<char>(std::forward<Args>(args)...);
320  case Datatype::UCHAR:
321  return Action::template call<unsigned char>(
322  std::forward<Args>(args)...);
323  case Datatype::SCHAR:
324  return Action::template call<signed char>(std::forward<Args>(args)...);
325  case Datatype::SHORT:
326  return Action::template call<short>(std::forward<Args>(args)...);
327  case Datatype::INT:
328  return Action::template call<int>(std::forward<Args>(args)...);
329  case Datatype::LONG:
330  return Action::template call<long>(std::forward<Args>(args)...);
331  case Datatype::LONGLONG:
332  return Action::template call<long long>(std::forward<Args>(args)...);
333  case Datatype::USHORT:
334  return Action::template call<unsigned short>(
335  std::forward<Args>(args)...);
336  case Datatype::UINT:
337  return Action::template call<unsigned int>(std::forward<Args>(args)...);
338  case Datatype::ULONG:
339  return Action::template call<unsigned long>(
340  std::forward<Args>(args)...);
341  case Datatype::ULONGLONG:
342  return Action::template call<unsigned long long>(
343  std::forward<Args>(args)...);
344  case Datatype::FLOAT:
345  return Action::template call<float>(std::forward<Args>(args)...);
346  case Datatype::DOUBLE:
347  return Action::template call<double>(std::forward<Args>(args)...);
348  case Datatype::LONG_DOUBLE:
349  return Action::template call<long double>(std::forward<Args>(args)...);
350  case Datatype::CFLOAT:
351  return Action::template call<std::complex<float>>(
352  std::forward<Args>(args)...);
353  case Datatype::CDOUBLE:
354  return Action::template call<std::complex<double>>(
355  std::forward<Args>(args)...);
356  // missing std::complex< long double > type in ADIOS2 v2.6.0
357  // case Datatype::CLONG_DOUBLE:
358  // return action
359  // .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
360  // std::forward< Args >( args )... );
361  case Datatype::UNDEFINED:
362  return detail::
363  CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call(
364  std::forward<Args>(args)...);
365  default:
366  throw std::runtime_error(
367  "Internal error: Encountered unknown datatype (switchType) ->" +
368  std::to_string(static_cast<int>(dt)));
369  }
370 }
371 #endif // openPMD_HAVE_ADIOS2
372 } // namespace openPMD
Variant datatype supporting at least all formats for attributes specified in the openPMD standard.
Definition: Attribute.hpp:56
Internal errors that should not happen.
Definition: Error.hpp:83
Public definitions of openPMD-api.
Definition: Date.cpp:29
auto switchAdios2VariableType(Datatype dt, Args &&...args) -> decltype(Action::template call< char >(std::forward< Args >(args)...))
Generalizes switching over an openPMD datatype.
Definition: ADIOS2Auxiliary.hpp:311
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:51
auto switchAdios2AttributeType(Datatype dt, Args &&...args) -> decltype(Action::template call< char >(std::forward< Args >(args)...))
Generalizes switching over an openPMD datatype.
Definition: ADIOS2Auxiliary.hpp:231
Definition: ADIOS2Auxiliary.hpp:146
Definition: ADIOS2Auxiliary.hpp:100
Definition: ADIOS2Auxiliary.hpp:123