openPMD-api
ADIOS1Auxiliary.hpp
1 /* Copyright 2018-2021 Fabian Koller
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 #pragma once
22 
23 #include "openPMD/IO/ADIOS/ADIOS1FilePosition.hpp"
24 #include "openPMD/ThrowError.hpp"
25 #include "openPMD/auxiliary/StringManip.hpp"
26 #include "openPMD/backend/Attribute.hpp"
27 #include "openPMD/backend/Writable.hpp"
28 
29 #include <adios_types.h>
30 
31 #include <cstring>
32 #include <exception>
33 #include <iostream>
34 #include <iterator>
35 #include <sstream>
36 #include <stack>
37 
38 namespace openPMD
39 {
40 inline std::string
41 getBP1Extent(Extent const &e, std::string const &delimiter = ",")
42 {
43  switch (e.size())
44  {
45  case 0:
46  return "";
47  case 1:
48  return std::to_string(e[0]);
49  default:
50  std::ostringstream os;
51  std::for_each(
52  e.begin(), e.end() - 1, [&os, &delimiter](std::uint64_t const ext) {
53  os << std::to_string(ext) << delimiter;
54  });
55  os << std::to_string(*e.rbegin());
56  return os.str();
57  }
58 }
59 
60 inline std::string
61 getZerosLikeBP1Extent(Extent const &e, std::string const &delimiter = ",")
62 {
63  switch (e.size())
64  {
65  case 0:
66  return "";
67  case 1:
68  return "0";
69  default:
70  std::ostringstream os;
71  std::for_each(
72  e.begin(), e.end() - 1, [&os, &delimiter](std::uint64_t const) {
73  os << "0" << delimiter;
74  });
75  os << "0";
76  return os.str();
77  }
78 }
79 
80 inline ADIOS_DATATYPES getBP1DataType(Datatype dtype)
81 {
82  using DT = Datatype;
83 
84  // note the ill-named fixed-byte adios_... types
85  // https://github.com/ornladios/ADIOS/issues/187
86  switch (dtype)
87  {
88  case DT::CHAR:
89  case DT::VEC_CHAR:
90  case DT::SCHAR:
91  case DT::VEC_SCHAR:
92  return adios_byte;
93  case DT::UCHAR:
94  case DT::VEC_UCHAR:
95  case DT::BOOL:
96  return adios_unsigned_byte;
97  case DT::SHORT:
98  case DT::VEC_SHORT:
99  if (sizeof(short) == 2u)
100  return adios_short;
101  else if (sizeof(short) == 4u)
102  return adios_integer;
103  else if (sizeof(long) == 8u)
104  return adios_long;
105  else
106  error::throwOperationUnsupportedInBackend(
107  "ADIOS1", "No native equivalent for Datatype::SHORT found.");
108  case DT::INT:
109  case DT::VEC_INT:
110  if (sizeof(int) == 2u)
111  return adios_short;
112  else if (sizeof(int) == 4u)
113  return adios_integer;
114  else if (sizeof(int) == 8u)
115  return adios_long;
116  else
117  error::throwOperationUnsupportedInBackend(
118  "ADIOS1", "No native equivalent for Datatype::INT found.");
119  case DT::LONG:
120  case DT::VEC_LONG:
121  if (sizeof(long) == 2u)
122  return adios_short;
123  else if (sizeof(long) == 4u)
124  return adios_integer;
125  else if (sizeof(long) == 8u)
126  return adios_long;
127  else
128  error::throwOperationUnsupportedInBackend(
129  "ADIOS1", "No native equivalent for Datatype::LONG found.");
130  case DT::LONGLONG:
131  case DT::VEC_LONGLONG:
132  if (sizeof(long long) == 2u)
133  return adios_short;
134  else if (sizeof(long long) == 4u)
135  return adios_integer;
136  else if (sizeof(long long) == 8u)
137  return adios_long;
138  else
139  error::throwOperationUnsupportedInBackend(
140  "ADIOS1", "No native equivalent for Datatype::LONGLONG found.");
141  case DT::USHORT:
142  case DT::VEC_USHORT:
143  if (sizeof(unsigned short) == 2u)
144  return adios_unsigned_short;
145  else if (sizeof(unsigned short) == 4u)
146  return adios_unsigned_integer;
147  else if (sizeof(unsigned long) == 8u)
148  return adios_unsigned_long;
149  else
150  error::throwOperationUnsupportedInBackend(
151  "ADIOS1", "No native equivalent for Datatype::USHORT found.");
152  case DT::UINT:
153  case DT::VEC_UINT:
154  if (sizeof(unsigned int) == 2u)
155  return adios_unsigned_short;
156  else if (sizeof(unsigned int) == 4u)
157  return adios_unsigned_integer;
158  else if (sizeof(unsigned int) == 8u)
159  return adios_unsigned_long;
160  else
161  error::throwOperationUnsupportedInBackend(
162  "ADIOS1", "No native equivalent for Datatype::UINT found.");
163  case DT::ULONG:
164  case DT::VEC_ULONG:
165  if (sizeof(unsigned long) == 2u)
166  return adios_unsigned_short;
167  else if (sizeof(unsigned long) == 4u)
168  return adios_unsigned_integer;
169  else if (sizeof(unsigned long) == 8u)
170  return adios_unsigned_long;
171  else
172  error::throwOperationUnsupportedInBackend(
173  "ADIOS1", "No native equivalent for Datatype::ULONG found.");
174  case DT::ULONGLONG:
175  case DT::VEC_ULONGLONG:
176  if (sizeof(unsigned long long) == 2u)
177  return adios_unsigned_short;
178  else if (sizeof(unsigned long long) == 4u)
179  return adios_unsigned_integer;
180  else if (sizeof(unsigned long long) == 8u)
181  return adios_unsigned_long;
182  else
183  error::throwOperationUnsupportedInBackend(
184  "ADIOS1",
185  "No native equivalent for Datatype::ULONGLONG found.");
186  case DT::FLOAT:
187  case DT::VEC_FLOAT:
188  return adios_real;
189  case DT::DOUBLE:
190  case DT::ARR_DBL_7:
191  case DT::VEC_DOUBLE:
192  return adios_double;
193  case DT::LONG_DOUBLE:
194  case DT::VEC_LONG_DOUBLE:
195  return adios_long_double;
196  case DT::CFLOAT:
197  case DT::VEC_CFLOAT:
198  return adios_complex;
199  case DT::CDOUBLE:
200  case DT::VEC_CDOUBLE:
201  return adios_double_complex;
202  case DT::CLONG_DOUBLE:
203  case DT::VEC_CLONG_DOUBLE:
204  error::throwOperationUnsupportedInBackend(
205  "ADIOS1", "No native equivalent for Datatype::CLONG_DOUBLE found.");
206  case DT::STRING:
207  return adios_string;
208  case DT::VEC_STRING:
209  return adios_string_array;
210  case DT::UNDEFINED:
211  throw std::runtime_error("Unknown Attribute datatype (ADIOS datatype)");
212  default:
213  throw std::runtime_error("Datatype not implemented in ADIOS IO");
214  }
215 }
216 
217 inline std::string concrete_bp1_file_position(Writable *w)
218 {
219  std::stack<Writable *> hierarchy;
220  if (!w->abstractFilePosition)
221  w = w->parent;
222  while (w)
223  {
224  hierarchy.push(w);
225  w = w->parent;
226  }
227 
228  std::string pos;
229  while (!hierarchy.empty())
230  {
231  auto const tmp_ptr = std::dynamic_pointer_cast<ADIOS1FilePosition>(
232  hierarchy.top()->abstractFilePosition);
233  if (tmp_ptr == nullptr)
234  throw std::runtime_error(
235  "Dynamic pointer cast returned a nullptr!");
236  pos += tmp_ptr->location;
237  hierarchy.pop();
238  }
239 
240  return auxiliary::replace_all(pos, "//", "/");
241 }
242 
243 inline std::string
244 getEnvNum(std::string const &key, std::string const &defaultValue)
245 {
246  char const *env = std::getenv(key.c_str());
247  if (env != nullptr)
248  {
249  char const *tmp = env;
250  while (tmp)
251  {
252  if (isdigit(*tmp))
253  ++tmp;
254  else
255  {
256  std::cerr << key << " is invalid" << std::endl;
257  break;
258  }
259  }
260  if (!tmp)
261  return std::string(env, std::strlen(env));
262  else
263  return defaultValue;
264  }
265  else
266  return defaultValue;
267 }
268 
269 template <typename T>
270 inline Attribute readVectorAttributeInternal(void *data, int size)
271 {
272  auto d = reinterpret_cast<T *>(data);
273  std::vector<T> v;
274  v.resize(size);
275  for (int i = 0; i < size; ++i)
276  v[i] = d[i];
277  return Attribute(v);
278 }
279 } // namespace openPMD
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:45
Public definitions of openPMD-api.