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