XGC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
xgc_io.hpp
Go to the documentation of this file.
1 #ifndef XGC_IO_HPP
2 #define XGC_IO_HPP
3 #include "space_settings.hpp"
4 
5 #ifdef USE_MPI
6 #include "my_mpi.hpp"
7 #endif
8 
9 
10 #ifdef ADIOS2
11 #include "adios2.hpp"
12 // If ADIOS2 is being used, XGC_IO_Stream is ADIOS2Stream
14 typedef adios2::Mode XGC_IO_Mode;
15 #else
16 // If ADIOS2 is not being used, spoof IO since there is currently no alternative
17 enum class XGC_IO_Mode{
18 Write,
19 Append,
20 Read,
22 };
23 
25 public:
27  XGC_IO_Stream(const std::string &IOName){}
28 
29  void Init(const std::string &IOName){}
30  void Open(const std::string &StreamName, const XGC_IO_Mode mode){}
31 #ifdef USE_MPI
32  void Open(const std::string &StreamName, const XGC_IO_Mode mode, const MPI_Comm &comm){}
33 #endif
34  void Close(){}
35 };
36 #endif
37 
38 // Returns an unmanaged view wrapping the input scalar
39 template<typename T>
40 inline View<T*, HostType, Kokkos::MemoryTraits<Kokkos::Unmanaged>> scalar_view_wrap(T& scalar){
41  return View<T*, HostType, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(&scalar, 1);
42 }
43 
44 struct IOData{
45 #ifdef ADIOS2
46  // These virtual functions must be defined in derived classes
47  virtual void adios_def_and_shape(const ADIOS2Stream& stream) const = 0;
48  virtual void adios_put(const ADIOS2Stream& stream) const = 0;
49  virtual void adios_get(const ADIOS2Stream& stream) = 0;
50 #endif
51  virtual ~IOData(){}
52 };
53 
54 // IOScalar is a helper struct to handle an scalar being written/read with ADIOS2
55 template<class T>
56 struct IOScalar : public IOData {
57  using value_type = T;
58  std::string name;
62 
63  // Input value is not const; assign address
64  IOScalar(const std::string& name_in, T& value_in)
65  : name(name_in),
66  var_is_const(false),
67  value_addr(&value_in),
68  value(value_in){}
69 
70  // Input value is const; assign value
71  IOScalar(const std::string& name_in, const T& value_in)
72  : name(name_in),
73  var_is_const(true),
74  value(value_in){}
75 
76 #ifdef ADIOS2
77  void adios_def_and_shape(const ADIOS2Stream& stream) const {
78  if(!stream.io->InquireVariable<T>(name)){
79  stream.io->DefineVariable<T>(name);
80  }
81  }
82 
83  void adios_put(const ADIOS2Stream& stream) const {
84  stream.engine->Put(name, value);
85  }
86 
87  void adios_get(const ADIOS2Stream& stream) {
88  if(var_is_const) printf("\nError: Tried to read into const variable\n"); // Should be compiletime check?
89  else stream.engine->Get(name, *value_addr);
90  }
91 #endif
92 };
93 
94 // The purpose of this struct is to be able to pass types other than long long int/size_t into the adios2::Dims initialization.
95 struct UpcastVector {
96  std::vector<size_t> vec;
97 
98  UpcastVector() = default;
99 
100  template <typename... Args>
101  UpcastVector(Args... args) {
102  addValues(args...);
103  }
104 
105  template <typename First, typename... Rest>
106  void addValues(First first, Rest... rest) {
107  vec.push_back(static_cast<size_t>(first));
108  if constexpr (sizeof...(rest) > 0) {
109  addValues(rest...);
110  }
111  }
112 };
113 
114 
115 // IOArray is a helper struct to represent an array being written/read with ADIOS2
116 template<class T>
117 struct IOArray : public IOData {
118  using view_type = T;
119  using dim_type = std::vector<size_t>;
120  std::string name;
122 
123  // These are std::vector<size_t>
127 
128  // Dims arguments are implicitly converted to size_t
129  // If the view has fewer dimensions than full_size and offsets, pad with outer dimensions of size 1, i.e. assume that
130  // the intention is for the data to be written/read contiguously.
131  IOArray(const std::string& name_in, const T& view_in, const UpcastVector& full_size_in, const UpcastVector& offsets_in)
132  : name(name_in),
133  view(view_in), // shallow copy of view
134  full_size(full_size_in.vec),
135  offsets(offsets_in.vec),
136  size(full_size.size()) // size needs to have the same length (i.e. refer to the same number of dimensions) as full_size
137  {
138  // If the input view has fewer dimensions than the global view, treat the outermost dimensions as size 1
139  int dim_offset = size.size() - T::rank;
140  // Write the dimensions of the view into size
141  for(int i=0; i<size.size(); i++){
142  if(i - dim_offset >= 0){
143  size[i] = view.extent(i - dim_offset);
144  }else{
145  size[i] = 1; // Outer dimension doesn't exist, set it to 1
146  }
147  }
148  }
149 
150  // Constructor without full size or offset --> full_size = size, offset = 0
151  IOArray(const std::string& name_in, const T& view_in)
152  : name(name_in),
153  view(view_in), // shallow copy of view
154  full_size(T::rank),
155  offsets(T::rank),
156  size(T::rank)
157  {
158  // Write the dimensions of the view into size
159  for(int i=0; i<size.size(); i++){
160  size[i] = view.extent(i);
161 
162  // full_size = size, offsets are 0
163  full_size[i] = size[i];
164  offsets[i] = 0;
165  }
166  }
167 #ifdef ADIOS2
168  void adios_def_and_shape(const ADIOS2Stream& stream) const {
169  auto TAG = stream.io->InquireVariable<typename T::value_type>(name);
170  if(!TAG){
171  TAG = stream.io->DefineVariable<typename T::value_type>(name, full_size, offsets, size);
172  }else{
173  TAG.SetShape(full_size);
174  }
175  }
176 
177  void adios_put(const ADIOS2Stream& stream) const {
178  auto TAG = stream.io->InquireVariable<typename T::value_type>(name);
179  TAG.SetSelection({offsets, size});
180  stream.engine->Put<typename T::value_type>(TAG, view.data(), adios2::Mode::Sync);
181  }
182 
183  void adios_get(const ADIOS2Stream& stream) {
184  auto TAG = stream.io->InquireVariable<typename T::value_type>(name);
185  TAG.SetSelection({offsets, size});
186  stream.engine->Get<typename T::value_type>(TAG, view.data());
187  }
188 #endif
189 };
190 
191 /* This class contains a vector of data ready to be written/read with ADIOS2 */
192 class XGC_IO{
193  std::vector<std::unique_ptr<IOData>> io_data;
194 
195  public:
196 
197  // Adds a single new entry to the data vector
198  template<class T>
199  void add(const T& new_data){
200  io_data.push_back(std::make_unique<T>(new_data));
201  }
202 
203  // Adds an unspecified number of entries to the data vector
204  template<class T, class... Ts>
205  void add(const T& new_data, const Ts&... new_data_rest){
206  add(new_data);
207  add(new_data_rest...);
208  }
209 
210  // Writes the data to the stream
211  void write(const XGC_IO_Stream& stream) const{
212 #ifdef ADIOS2
213  // Define and shape all data
214  for(int i=0; i<io_data.size(); i++)
215  io_data[i]->adios_def_and_shape(stream);
216 
217  // Stage all data for writing
218  for(int i=0; i<io_data.size(); i++)
219  io_data[i]->adios_put(stream);
220 
221  // Perform puts
222  stream.engine->PerformPuts();
223 #endif
224  }
225 
226  // Reads the data from the stream
227  void read(const XGC_IO_Stream& stream) {
228 #ifdef ADIOS2
229  // Stage all data for reading
230  for(int i=0; i<io_data.size(); i++)
231  io_data[i]->adios_get(stream);
232 
233  // Perform gets
234  stream.engine->PerformGets();
235 #endif
236  }
237 
238  // Checks whether a variable varname of type T exists in the stream
239  template<typename T>
240  static bool is_present(const XGC_IO_Stream& stream, const std::string& varname){
241 #ifdef ADIOS2
242  if(stream.io->InquireVariable<T>(varname)) return true;
243  else return false;
244 #else
245  return false;
246 #endif
247  }
248 };
249 
250 #endif
Definition: xgc_io.hpp:95
void write(const XGC_IO_Stream &stream) const
Definition: xgc_io.hpp:211
void Open(const std::string &StreamName, const XGC_IO_Mode mode)
Definition: xgc_io.hpp:30
IOScalar(const std::string &name_in, T &value_in)
Definition: xgc_io.hpp:64
Definition: xgc_io.hpp:44
Definition: xgc_io.hpp:192
dim_type size
Definition: xgc_io.hpp:126
dim_type offsets
Definition: xgc_io.hpp:125
std::vector< std::unique_ptr< IOData > > io_data
Definition: xgc_io.hpp:193
std::vector< size_t > vec
Definition: xgc_io.hpp:96
IOScalar(const std::string &name_in, const T &value_in)
Definition: xgc_io.hpp:71
Definition: xgc_io.hpp:56
void read(const XGC_IO_Stream &stream)
Definition: xgc_io.hpp:227
IOArray(const std::string &name_in, const T &view_in, const UpcastVector &full_size_in, const UpcastVector &offsets_in)
Definition: xgc_io.hpp:131
XGC_IO_Stream()
Definition: xgc_io.hpp:26
bool var_is_const
Definition: xgc_io.hpp:61
void add(const T &new_data)
Definition: xgc_io.hpp:199
std::string name
Definition: xgc_io.hpp:58
void addValues(First first, Rest...rest)
Definition: xgc_io.hpp:106
virtual ~IOData()
Definition: xgc_io.hpp:51
T view_type
Definition: xgc_io.hpp:118
value_type value
Definition: xgc_io.hpp:60
View< T *, HostType, Kokkos::MemoryTraits< Kokkos::Unmanaged > > scalar_view_wrap(T &scalar)
Definition: xgc_io.hpp:40
Definition: xgc_io.hpp:117
UpcastVector(Args...args)
Definition: xgc_io.hpp:101
EnginePtr engine
Definition: adios2.hpp:30
Definition: adios2.hpp:26
UpcastVector()=default
static bool is_present(const XGC_IO_Stream &stream, const std::string &varname)
Definition: xgc_io.hpp:240
std::vector< size_t > dim_type
Definition: xgc_io.hpp:119
XGC_IO_Stream(const std::string &IOName)
Definition: xgc_io.hpp:27
void add(const T &new_data, const Ts &...new_data_rest)
Definition: xgc_io.hpp:205
Definition: xgc_io.hpp:24
XGC_IO_Mode
Definition: xgc_io.hpp:17
IOArray(const std::string &name_in, const T &view_in)
Definition: xgc_io.hpp:151
std::string name
Definition: xgc_io.hpp:120
IOPtr io
Definition: adios2.hpp:29
void Close()
Definition: xgc_io.hpp:34
T value_type
Definition: xgc_io.hpp:57
void Init(const std::string &IOName)
Definition: xgc_io.hpp:29
view_type view
Definition: xgc_io.hpp:121
value_type * value_addr
Definition: xgc_io.hpp:59
dim_type full_size
Definition: xgc_io.hpp:124