19 #include <type_traits>
27 struct get_value_type {
using value_type = T; };
29 struct get_value_type<std::complex<T>> {
using value_type = T; };
31 using get_value_type_t =
typename get_value_type<T>::value_type;
35 constexpr
bool is_not_const ()
37 return std::is_same_v<
54 using namespace amrex;
65 auto const len =
length(a4);
69 auto shape = py::make_tuple(
70 py::ssize_t(a4.
ncomp),
71 py::ssize_t(len.z <= 0 ? 1 : len.z),
72 py::ssize_t(len.y <= 0 ? 1 : len.y),
73 py::ssize_t(len.x <= 0 ? 1 : len.x)
76 auto const strides = py::make_tuple(
77 py::ssize_t(
sizeof(T) * a4.
nstride),
78 py::ssize_t(
sizeof(T) * a4.
kstride),
79 py::ssize_t(
sizeof(T) * a4.
jstride),
80 py::ssize_t(
sizeof(T))
82 bool const read_only =
false;
86 d[
"data"] = py::make_tuple(std::intptr_t(a4.
dataPtr()), read_only);
98 d[
"strides"] = strides;
104 using T_no_cv = std::remove_cv_t<T>;
105 d[
"typestr"] = py::format_descriptor<T_no_cv>::format();
111 template<
typename T >
114 using namespace amrex;
116 using T_no_cv = std::remove_cv_t<T>;
120 auto const array_name = std::string(
"Array4_").append(typestr);
121 py::class_< Array4<T> > py_array4(m, array_name.c_str());
127 return "<amrex.Array4 of type '" + typestr +
128 "' and size '" + s.str() +
"'>";
131 #
if defined(AMREX_DEBUG) || defined(AMREX_BOUND_CHECK)
141 .def(py::init<
Array4<T> const &,
int >())
142 .def(py::init<
Array4<T> const &,
int,
int >())
147 .def(py::init([](py::array_t<T> & arr) {
148 py::buffer_info buf = arr.request();
151 "We can only create amrex::Array4 views into 3D Python arrays at the moment.");
158 if (buf.format != py::format_descriptor<T_no_cv>::format())
159 throw std::runtime_error(
"Incompatible format: expected '" +
160 py::format_descriptor<T_no_cv>::format() +
161 "' and received '" + buf.format +
"'!");
163 auto a4 = std::make_unique< Array4<T> >();
164 a4.get()->
p =
static_cast<T*
>(buf.ptr);
168 a4.get()->
end.
x = (
int)buf.shape.at(2);
169 a4.get()->
end.
y = (
int)buf.shape.at(1);
170 a4.get()->
end.
z = (
int)buf.shape.at(0);
173 a4.get()->
jstride = (
int)buf.strides.at(1) /
sizeof(T);
174 a4.get()->
kstride = (
int)buf.strides.at(0) /
sizeof(T);
190 .def_property_readonly(
"__array_interface__", [](
Array4<T> const & a4) {
204 .def_property_readonly(
"__cuda_array_interface__", [](
Array4<T> const & a4) {
218 d[
"stream"] = py::none();
233 .def(
"to_host", [](
Array4<T> const & a4) {
236 auto const shape = py::cast<std::vector<py::ssize_t>>(a4i[
"shape"]);
237 auto const strides_bytes = py::cast<std::vector<py::ssize_t>>(a4i[
"strides"]);
240 auto h_data = py::array_t<T_no_cv>(shape, strides_bytes);
243 Gpu::copy(Gpu::deviceToHost,
245 h_data.mutable_data()
248 }, py::return_value_policy::move)
255 .def(
"__getitem__", [](
Array4<T> & a4, std::array<int, 4>
const key){
256 return a4(key[0], key[1], key[2], key[3]);
258 .def(
"__getitem__", [](
Array4<T> & a4, std::array<int, 3>
const key){
259 return a4(key[0], key[1], key[2]);
264 if constexpr (is_not_const<T>())
267 .def(
"__setitem__", [](
Array4<T> & a4,
IntVect const & v, T
const value){ a4(v) = value; })
268 .def(
"__setitem__", [](
Array4<T> & a4, std::array<int, 4>
const key, T
const value){
269 a4(key[0], key[1], key[2], key[3]) = value;
271 .def(
"__setitem__", [](
Array4<T> & a4, std::array<int, 3>
const key, T
const value){
272 a4(key[0], key[1], key[2]) = value;
278 m.def(
"lbound", &lbound< T >);
279 m.def(
"ubound", &ubound< T >);
280 m.def(
"length", &length< T >);
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 length(Array4< T > const &a) noexcept
void make_Array4(py::module &m, std::string typestr)
Definition: Array4.H:112
py::dict array_interface(Array4< T > const &a4)
Definition: Array4.H:62
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::size_t size() const noexcept
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T * dataPtr() const noexcept