6#ifndef PYMADNESS_PY_FUNCTOR_H
7#define PYMADNESS_PY_FUNCTOR_H
9#include <pybind11/pybind11.h>
10#include <pybind11/numpy.h>
11#include <pybind11/complex.h>
18namespace py = pybind11;
29template<
typename T, std::
size_t NDIM>
41 py::gil_scoped_acquire gil;
46 py::gil_scoped_acquire gil;
49 py::array_t<double> arr(
NDIM);
50 auto buf = arr.mutable_unchecked<1>();
51 for (std::size_t i = 0; i <
NDIM; ++i) {
56 return result.cast<
T>();
65 py::gil_scoped_acquire gil;
68 py::array_t<double> coords({
static_cast<py::ssize_t
>(
npts),
69 static_cast<py::ssize_t
>(
NDIM)});
70 auto cbuf = coords.mutable_unchecked<2>();
71 for (
int i = 0; i <
npts; ++i) {
72 for (std::size_t
d = 0;
d <
NDIM; ++
d) {
73 cbuf(i,
d) = xvals[
d][i];
83 std::memory_order_acq_rel, std::memory_order_acquire)) {
88 py::array_t<T> arr = result.cast<py::array_t<T>>();
89 if (arr.ndim() == 1 && arr.shape(0) ==
npts) {
91 auto rbuf = arr.template unchecked<1>();
92 for (
int i = 0; i <
npts; ++i) {
102 if (result_mode == 2) {
114 py::gil_scoped_release release;
115 std::this_thread::yield();
122 py::array_t<T> arr = result.cast<py::array_t<T>>();
123 if (arr.ndim() != 1 || arr.shape(0) !=
npts) {
124 throw std::runtime_error(
125 "PyFunctor: vectorized callable returned array with wrong shape; "
126 "expected 1D array of length " + std::to_string(
npts));
128 auto rbuf = arr.template unchecked<1>();
129 for (
int i = 0; i <
npts; ++i) {
139 auto cbuf = coords.unchecked<2>();
140 for (
int i = 0; i <
npts; ++i) {
141 py::array_t<double> pt(
NDIM);
142 auto pbuf = pt.mutable_unchecked<1>();
143 for (std::size_t
d = 0;
d <
NDIM; ++
d) {
144 pbuf(
d) = cbuf(i,
d);
147 fvals[i] = result.cast<
T>();
Definition py_functor.h:30
bool supports_vectorized() const override
Does the interface support a vectorized operator()?
Definition py_functor.h:59
void operator()(const madness::Vector< double *, 5 > &xvals, T *fvals, int npts) const override
Definition py_functor.h:172
void operator()(const madness::Vector< double *, 2 > &xvals, T *fvals, int npts) const override
Definition py_functor.h:160
void operator()(const madness::Vector< double *, 4 > &xvals, T *fvals, int npts) const override
Definition py_functor.h:168
void eval_vectorized(const madness::Vector< double *, NDIM > &xvals, T *fvals, int npts) const
Definition py_functor.h:64
py::object py_callable_
Definition py_functor.h:31
std::atomic< int > vectorized_mode_
Definition py_functor.h:32
void operator()(const madness::Vector< double *, 1 > &xvals, T *fvals, int npts) const override
Definition py_functor.h:156
void operator()(const madness::Vector< double *, 3 > &xvals, T *fvals, int npts) const override
Definition py_functor.h:164
void eval_scalar_loop(const py::array_t< double > &coords, T *fvals, int npts) const
Evaluate the callable per-point using scalar convention (still 1 GIL acquisition).
Definition py_functor.h:138
~PyFunctor()
Definition py_functor.h:37
void operator()(const madness::Vector< double *, 6 > &xvals, T *fvals, int npts) const override
Definition py_functor.h:176
PyFunctor(py::object f)
Definition py_functor.h:35
T operator()(const madness::Vector< double, NDIM > &r) const override
You should implement this to return f(x)
Definition py_functor.h:45
Abstract base class interface required for functors used as input to Functions.
Definition function_interface.h:68
A simple, fixed dimension vector.
Definition vector.h:64
double(* f)(const coord_3d &)
Definition derivatives.cc:54
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:28
static const double d
Definition nonlinschro.cc:121
constexpr std::size_t NDIM
Definition testgconv.cc:54
const auto npts
Definition testgconv.cc:52