70 }
catch (
const std::exception &e) {
73 throw std::runtime_error(std::string(
"ASE calculator import failed: ") +
79void ASE::force(
long nAtoms,
const double *R,
const int *atomicNrs,
double *F,
80 double *U,
double *variance,
const double *box) {
81 if (variance !=
nullptr) {
84 py::gil_scoped_acquire gil;
86 const Eigen::Map<const AtomMatrix> positions(R, nAtoms, 3);
87 const Eigen::Map<const RotationMatrix> boxx(box);
88 const Eigen::Map<const Eigen::VectorXi> atmnmrs(atomicNrs, nAtoms);
90 std::tuple<double, py::array_t<double>> py_result =
92 .cast<std::tuple<double, py::array_t<double>>>();
94 *U = std::get<0>(py_result);
95 py::array_t<double> forces = std::get<1>(py_result);
96 auto buffer = forces.request();
97 if (buffer.size < nAtoms * 3) {
98 throw std::runtime_error(
99 "ASE _calculate returned forces of the wrong size");
101 Eigen::Map<AtomMatrix>(F, nAtoms, 3) = Eigen::Map<const AtomMatrix>(
102 static_cast<const double *
>(buffer.ptr), nAtoms, 3);
104 }
catch (py::error_already_set &e) {
106 throw std::runtime_error(std::string(
"ASE calculator Python error: ") +
108 }
catch (
const std::exception &e) {
110 throw std::runtime_error(std::string(
"ASE calculator C++ exception: ") +
118void ASE::forceBatch(
long nSystems,
long nAtoms,
const double *
const *positions,
119 const int *
const *atomicNrs,
double *
const *forces,
120 double *energies,
double *variances,
121 const double *
const *boxes) {
124 energies, variances, boxes);
127 py::gil_scoped_acquire gil;
129 const auto ns =
static_cast<size_t>(nSystems);
130 const auto na =
static_cast<size_t>(nAtoms);
131 std::vector<double> R_data(ns * na * 3);
132 std::vector<int> Z_data(ns * na);
133 std::vector<double> box_data(ns * 9);
134 for (
long s = 0; s < nSystems; ++s) {
135 std::copy(positions[s], positions[s] +
static_cast<long>(na) * 3,
136 R_data.data() +
static_cast<size_t>(s) * na * 3);
137 std::copy(atomicNrs[s], atomicNrs[s] + nAtoms,
138 Z_data.data() +
static_cast<size_t>(s) * na);
139 std::copy(boxes[s], boxes[s] + 9,
140 box_data.data() +
static_cast<size_t>(s) * 9);
142 py::array_t<double> R_np({ns, na,
size_t{3}}, R_data.data());
143 py::array_t<int> Z_np({ns, na}, Z_data.data());
144 py::array_t<double> box_np({ns,
size_t{3},
size_t{3}}, box_data.data());
147 .cast<std::tuple<py::array_t<double>, py::array_t<double>>>();
148 py::array_t<double> E = std::get<0>(py_result);
149 py::array_t<double> F = std::get<1>(py_result);
150 auto bufE = E.request();
151 auto bufF = F.request();
152 if (bufE.size < nSystems || bufF.size < nSystems * nAtoms * 3) {
153 throw std::runtime_error(
154 "ASE batch_calculate returned energies/forces of the wrong size");
156 auto *ePtr =
static_cast<double *
>(bufE.ptr);
157 auto *fPtr =
static_cast<double *
>(bufF.ptr);
158 std::copy(ePtr, ePtr + nSystems, energies);
159 for (
long s = 0; s < nSystems; ++s) {
160 std::copy(fPtr + s * nAtoms * 3, fPtr + (s + 1) * nAtoms * 3, forces[s]);
165 }
catch (py::error_already_set &e) {
void force(long nAtoms, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
void forceBatch(long nSystems, long nAtoms, const double *const *positions, const int *const *atomicNrs, double *const *forces, double *energies, double *variances, const double *const *boxes) override
virtual void forceBatch(long nSystems, long nAtoms, const double *const *positions, const int *const *atomicNrs, double *const *forces, double *energies, double *variances, const double *const *boxes)