XGC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
adios2_io.hpp
Go to the documentation of this file.
1 #ifndef ADIOS2_IO_HPP
2 #define ADIOS2_IO_HPP
3 #ifdef ADIOS2
4 #include "adios2.hpp"
5 #include "space_settings.hpp"
6 
7 struct IOData{
8  // These virtual functions must be defined in derived classes
9  virtual void adios_def_and_shape(const ADIOS2Stream& stream) const = 0;
10  virtual void adios_put(const ADIOS2Stream& stream) const = 0;
11  virtual void adios_get(const ADIOS2Stream& stream) = 0;
12  virtual ~IOData(){}
13 };
14 
15 // IOScalar is a helper struct to handle an scalar being written/read with ADIOS2
16 template<class T>
17 struct IOScalar : public IOData {
18  using value_type = T;
19  std::string name;
20  value_type* value_addr;
21  value_type value;
22  bool var_is_const;
23 
24  // Input value is not const; assign address
25  IOScalar(const std::string& name_in, T& value_in)
26  : name(name_in),
27  var_is_const(false),
28  value_addr(&value_in),
29  value(value_in){}
30 
31  // Input value is const; assign value
32  IOScalar(const std::string& name_in, const T& value_in)
33  : name(name_in),
34  var_is_const(true),
35  value(value_in){}
36 
37  void adios_def_and_shape(const ADIOS2Stream& stream) const {
38  if(!stream.io->InquireVariable<T>(name)){
39  stream.io->DefineVariable<T>(name);
40  }
41  }
42 
43  void adios_put(const ADIOS2Stream& stream) const {
44  stream.engine->Put(name, value);
45  }
46 
47  void adios_get(const ADIOS2Stream& stream) {
48  if(var_is_const) printf("\nError: Tried to read into const variable\n"); // Should be compiletime check?
49  else stream.engine->Get(name, *value_addr);
50  }
51 };
52 
53 // IOArray is a helper struct to represent an array being written/read with ADIOS2
54 template<class T>
55 struct IOArray : public IOData {
56  using view_type = T;
57  std::string name;
58  view_type view;
59 
60  // These are std::vector<size_t>
61  adios2::Dims full_size;
62  adios2::Dims offsets;
63  adios2::Dims size;
64 
65  // Dims arguments are implicitly converted to size_t
66  // If the view has fewer dimensions than full_size and offsets, pad with outer dimensions of size 1, i.e. assume that
67  // the intention is for the data to be written/read contiguously.
68  IOArray(const std::string& name_in, const T& view_in, const adios2::Dims& full_size_in, const adios2::Dims& offsets_in)
69  : name(name_in),
70  view(view_in), // shallow copy of view
71  full_size(full_size_in),
72  offsets(offsets_in),
73  size(full_size.size()) // size needs to have the same length (i.e. refer to the same number of dimensions) as full_size
74  {
75  // If the input view has fewer dimensions than the global view, treat the outermost dimensions as size 1
76  int dim_offset = size.size() - T::rank;
77  // Write the dimensions of the view into size
78  for(int i=0; i<size.size(); i++){
79  if(i - dim_offset >= 0){
80  size[i] = view.extent(i - dim_offset);
81  }else{
82  size[i] = 1; // Outer dimension doesn't exist, set it to 1
83  }
84  }
85  }
86 
87  // Constructor without full size or offset --> full_size = size, offset = 0
88  IOArray(const std::string& name_in, const T& view_in)
89  : name(name_in),
90  view(view_in), // shallow copy of view
91  full_size(T::rank),
92  offsets(T::rank),
93  size(T::rank)
94  {
95  // Write the dimensions of the view into size
96  for(int i=0; i<size.size(); i++){
97  size[i] = view.extent(i);
98 
99  // full_size = size, offsets are 0
100  full_size[i] = size[i];
101  offsets[i] = 0;
102  }
103  }
104 
105  void adios_def_and_shape(const ADIOS2Stream& stream) const {
106  auto TAG = stream.io->InquireVariable<typename T::value_type>(name);
107  if(!TAG){
108  TAG = stream.io->DefineVariable<typename T::value_type>(name, full_size, offsets, size);
109  }else{
110  TAG.SetShape(full_size);
111  }
112  }
113 
114  void adios_put(const ADIOS2Stream& stream) const {
115  auto TAG = stream.io->InquireVariable<typename T::value_type>(name);
116  TAG.SetSelection({offsets, size});
117  stream.engine->Put<typename T::value_type>(TAG, view.data(), adios2::Mode::Sync);
118  }
119 
120  void adios_get(const ADIOS2Stream& stream) {
121  auto TAG = stream.io->InquireVariable<typename T::value_type>(name);
122  TAG.SetSelection({offsets, size});
123  stream.engine->Get<typename T::value_type>(TAG, view.data());
124  }
125 };
126 
127 /* This class contains a vector of data ready to be written/read with ADIOS2 */
128 class ADIOS2_IO{
129  std::vector<std::unique_ptr<IOData>> io_data;
130 
131  public:
132 
133  // Adds a single new entry to the data vector
134  template<class T>
135  void add(const T& new_data){
136  io_data.push_back(std::make_unique<T>(new_data));
137  }
138 
139  // Adds an unspecified number of entries to the data vector
140  template<class T, class... Ts>
141  void add(const T& new_data, const Ts&... new_data_rest){
142  add(new_data);
143  add(new_data_rest...);
144  }
145 
146  // Writes the data to the stream
147  void write(const ADIOS2Stream& stream) const{
148  // Define and shape all data
149  for(int i=0; i<io_data.size(); i++)
150  io_data[i]->adios_def_and_shape(stream);
151 
152  // Stage all data for writing
153  for(int i=0; i<io_data.size(); i++)
154  io_data[i]->adios_put(stream);
155 
156  // Perform puts
157  stream.engine->PerformPuts();
158  }
159 
160  // Reads the data from the stream
161  void read(const ADIOS2Stream& stream) {
162  // Stage all data for reading
163  for(int i=0; i<io_data.size(); i++)
164  io_data[i]->adios_get(stream);
165 
166  // Perform gets
167  stream.engine->PerformGets();
168  }
169 };
170 
171 #endif
172 #endif
EnginePtr engine
Definition: adios2.hpp:30
Definition: adios2.hpp:26
IOPtr io
Definition: adios2.hpp:29