pyAMReX
Vector.H
Go to the documentation of this file.
1 /* Copyright 2022-2023 The AMReX Community
2  *
3  * Authors: Ryan Sandberg, Axel Huebl
4  * License: BSD-3-Clause-LBNL
5  */
6 #pragma once
7 
8 #include "pyAMReX.H"
9 
10 #include <AMReX_Vector.H>
11 
12 #include <cstdint>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 #include <type_traits>
17 #include <vector>
18 
19 
20 namespace
21 {
26  template <class T, class Allocator = std::allocator<T> >
27  py::dict
29  {
30  auto d = py::dict();
31  bool const read_only = false;
32  d["data"] = py::make_tuple(std::intptr_t(vector.dataPtr()), read_only);
33  d["shape"] = py::make_tuple(vector.size());
34  d["strides"] = py::none();
35  d["typestr"] = py::format_descriptor<T>::format();
36  d["version"] = 3;
37  return d;
38  }
39 }
40 
50 template <class T, class Allocator = std::allocator<T> >
51 void make_Vector(py::module &m, std::string typestr)
52 {
53  using namespace amrex;
54 
55  using Vector_type = Vector<T, Allocator>;
56  auto const v_name = std::string("Vector_").append(typestr);
57 
58  auto py_vect = py::bind_vector<Vector_type>(m, v_name.c_str());
59  py_vect
60  .def("__repr__",
61  [typestr](Vector_type const & v) {
62  std::stringstream s, rs;
63  s << v.size();
64  rs << "<amrex.Vector of type '" + typestr +
65  "' and size '" + s.str() + "'>\n";
66  rs << "[ ";
67  for (int ii = 0; ii < int(v.size()); ii++) {
68  rs << v[ii] << " ";
69  }
70  rs << "]\n";
71  return rs.str();
72  }
73  )
74  .def(py::init<>())
75  .def(py::init<Vector_type const &>())
76 
77  .def("size", &Vector_type::size)
78  ;
79 
80  if constexpr(std::is_fundamental_v<T>)
81  {
82  py_vect
83  .def_property_readonly("__array_interface__", [](Vector_type const & vector) {
84  return array_interface(vector);
85  })
86  .def_property_readonly("__cuda_array_interface__", [](Vector_type const & vector) {
87  // Nvidia GPUs: __cuda_array_interface__ v3
88  // https://numba.readthedocs.io/en/latest/cuda/cuda_array_interface.html
89  auto d = array_interface(vector);
90 
91  // data:
92  // Because the user of the interface may or may not be in the same context, the most common case is to use cuPointerGetAttribute with CU_POINTER_ATTRIBUTE_DEVICE_POINTER in the CUDA driver API (or the equivalent CUDA Runtime API) to retrieve a device pointer that is usable in the currently active context.
93  // TODO For zero-size arrays, use 0 here.
94 
95  // None or integer
96  // An optional stream upon which synchronization must take place at the point of consumption, either by synchronizing on the stream or enqueuing operations on the data on the given stream. Integer values in this entry are as follows:
97  // 0: This is disallowed as it would be ambiguous between None and the default stream, and also between the legacy and per-thread default streams. Any use case where 0 might be given should either use None, 1, or 2 instead for clarity.
98  // 1: The legacy default stream.
99  // 2: The per-thread default stream.
100  // Any other integer: a cudaStream_t represented as a Python integer.
101  // When None, no synchronization is required.
102  d["stream"] = py::none();
103 
104  d["version"] = 3;
105  return d;
106  });
107  }
108 
109  py_vect
110  // setter & getter
111  .def("__setitem__", [](Vector_type & vector, int const idx, T const value){ vector[idx] = value; })
112  .def("__getitem__", [](Vector_type & v, int const idx){ return v[idx]; })
113  ;
114 }
void make_Vector(py::module &m, std::string typestr)
Definition: Vector.H:51
Long size() const noexcept
T * dataPtr() noexcept
const int[]
py::dict array_interface(Array4< T > const &a4)
Definition: Array4.H:62