55 if (
const char *e = std::getenv(
"RGPOT_BACKEND"))
57 if (
const char *e = std::getenv(
"RGPOT_NWCHEM_BASIS"))
59 if (
const char *e = std::getenv(
"RGPOT_NWCHEM_THEORY"))
61 if (
const char *e = std::getenv(
"RGPOT_NWCHEM_SCF_TYPE"))
63 if (
const char *e = std::getenv(
"RGPOT_PARAMS_PATH"))
67 std::string backend_lc = opt.
backend;
68 std::ranges::transform(backend_lc, backend_lc.begin(),
69 [](
unsigned char c) { return std::tolower(c); });
70 if (backend_lc.rfind(
"nwchem", 0) == 0) {
71 if (const char *e = std::getenv(
"NWCHEMC_LIBRARY"))
73 else if (const char *e = std::getenv(
"RGPOT_NWCHEMC_ENGINE"))
75 else if (const char *e = std::getenv(
"RGPOT_NWCHEM_ENGINE"))
77 }
else if (backend_lc.rfind(
"cpmd", 0) == 0) {
78 if (const char *e = std::getenv(
"CPMDC_LIBRARY"))
80 else if (const char *e = std::getenv(
"RGPOT_CPMDC_ENGINE"))
82 }
else if (backend_lc.rfind(
"meta", 0) == 0 || backend_lc ==
"mta") {
83 if (const char *e = std::getenv(
"RGPOT_METATOMIC_ENGINE"))
85 else if (const char *e = std::getenv(
"METATOMIC_ENGINE"))
87 if (const char *e = std::getenv(
"RGPOT_METATOMIC_MODEL"))
89 }
else if (backend_lc ==
"xtb" || backend_lc ==
"xtbpot" ||
90 backend_lc ==
"gfn" || backend_lc ==
"gfnxtb") {
91 if (
const char *e = std::getenv(
"RGPOT_XTB_ENGINE"))
93 else if (
const char *e = std::getenv(
"XTB_ENGINE"))
102 if ((backend_lc.rfind(
"meta", 0) == 0 || backend_lc ==
"mta") &&
105 if ((backend_lc.rfind(
"meta", 0) == 0 || backend_lc ==
"mta") &&
109 impl_ = std::make_unique<RGPotEngine>(opt);
113 <<
"RgpotPot: in-process rgpot backend=" <<
backend_
114 <<
" (dlopen: libnwchemc/libcpmdc/libmetatomic_engine/libxtb_engine)"
118 impl_->finalizeMpiAtExit();
119 impl_->armGroupedExit();
126 const bool grouped =
impl_ &&
impl_->calculatorWorld() > 1;
132 (void)
impl_.release();
141enum : std::int64_t { kStop = 0, kSingle = 1, kBatch = 2, kDown = 3 };
151 std::int64_t hdr[3] = {kStop, 0, 0};
152 impl_->broadcastFromDriver(hdr,
sizeof(hdr));
154 if (g_driver ==
this)
161 const bool grouped =
driver_ &&
impl_->calculatorWorld() > 1;
165 impl_->shutdownModule();
169 std::int64_t hdr[3] = {kDown, 0, 0};
170 impl_->broadcastFromDriver(hdr,
sizeof(hdr));
176 if (g_driver || !
impl_ ||
impl_->calculatorWorld() <= 1)
185 g_driver->stopAndDrop();
192bool try_force(
const RGPotEngine &engine,
long N,
const double *R,
193 const int *atomicNrs,
double *F,
double *U,
const double *box,
194 std::string &error) {
196 engine.
force(N, R, atomicNrs, F, U, box);
198 }
catch (
const std::exception &ex) {
204[[noreturn]]
void raise_failure(
long system,
int owner,
205 const std::string &error) {
206 std::string msg =
"RGPOT: calculator " + std::to_string(owner) +
207 " failed on system " + std::to_string(system);
210 throw std::runtime_error(msg);
215 double *F,
double *U,
const double *box) {
219 if (
impl_->calculatorIndex() == 0)
220 ok = try_force(*
impl_, N, R, atomicNrs, F, U, box, error);
221 if (!
impl_->shareResult(0, N, F, U, ok, error))
222 raise_failure(0, 0, error);
226 const double *
const *positions,
227 const int *
const *atomicNrs,
double *
const *forces,
228 double *energies,
const double *
const *boxes,
229 const std::int64_t *owners) {
230 const int groups =
impl_->calculatorGroups();
231 const int mine =
impl_->calculatorIndex();
232 auto ownerOf = [&](
long j) {
233 const std::int64_t
id = owners && owners[j] >= 0 ? owners[j] : j;
234 return static_cast<int>(
id % groups);
236 if (
impl_->calculatorWorld() <= 1) {
237 for (
long j = 0; j < nSystems; j++)
238 impl_->force(nAtoms, positions[j], atomicNrs[j], forces[j], &energies[j],
242 std::vector<char> ok(
static_cast<size_t>(nSystems), 1);
243 std::vector<std::string> errors(
static_cast<size_t>(nSystems));
244 for (
long j = 0; j < nSystems; j++) {
245 if (ownerOf(j) == mine)
246 ok[
static_cast<size_t>(j)] =
247 try_force(*
impl_, nAtoms, positions[j], atomicNrs[j], forces[j],
248 &energies[j], boxes[j], errors[
static_cast<size_t>(j)]);
252 for (
long j = 0; j < nSystems; j++) {
253 const int owner = ownerOf(j);
254 if (!
impl_->shareResult(owner, nAtoms, forces[j], &energies[j],
255 ok[
static_cast<size_t>(j)] != 0,
256 errors[
static_cast<size_t>(j)]) &&
261 raise_failure(failed, ownerOf(failed), errors[
static_cast<size_t>(failed)]);
266 std::int64_t hdr[3] = {kStop, 0, 0};
267 impl_->broadcastFromDriver(hdr,
sizeof(hdr));
268 if (hdr[0] == kStop) {
272 impl_->shutdownModule();
275 std::int64_t ack[3] = {kDown, 0, 0};
276 impl_->broadcastFromDriver(ack,
sizeof(ack));
279 const long n =
static_cast<long>(hdr[1]);
280 const long m = hdr[0] == kBatch ?
static_cast<long>(hdr[2]) : 1;
281 std::vector<double> R(
static_cast<size_t>(3 * n * m));
282 std::vector<int> Z(
static_cast<size_t>(n * m));
283 std::vector<double> box(
static_cast<size_t>(9 * m));
284 impl_->broadcastFromDriver(R.data(), R.size() *
sizeof(
double));
285 impl_->broadcastFromDriver(Z.data(), Z.size() *
sizeof(
int));
286 impl_->broadcastFromDriver(box.data(), box.size() *
sizeof(
double));
287 std::vector<std::int64_t> ids(
static_cast<size_t>(m), -1);
288 if (hdr[0] == kBatch)
289 impl_->broadcastFromDriver(ids.data(), ids.size() *
sizeof(std::int64_t));
290 std::vector<double> F(R.size()), U(
static_cast<size_t>(m));
293 if (hdr[0] == kSingle) {
295 computeSingle(n, R.data(), Z.data(), F.data(), U.data(), box.data());
296 }
catch (
const std::runtime_error &) {
300 std::vector<const double *> pos(
static_cast<size_t>(m)), bx(pos.size());
301 std::vector<const int *> nrs(pos.size());
302 std::vector<double *> frc(pos.size());
303 for (
long j = 0; j < m; j++) {
304 pos[
static_cast<size_t>(j)] = R.data() + 3 * n * j;
305 nrs[
static_cast<size_t>(j)] = Z.data() + n * j;
306 frc[
static_cast<size_t>(j)] = F.data() + 3 * n * j;
307 bx[
static_cast<size_t>(j)] = box.data() + 9 * j;
310 computeBatch(m, n, pos.data(), nrs.data(), frc.data(), U.data(),
311 bx.data(), ids.data());
312 }
catch (
const std::runtime_error &) {
318 double *U,
double *variance,
const double *box) {
321 if (
impl_->calculatorWorld() <= 1) {
322 impl_->force(N, R, atomicNrs, F, U, box);
325 std::int64_t hdr[3] = {kSingle, N, 1};
326 impl_->broadcastFromDriver(hdr,
sizeof(hdr));
327 impl_->broadcastFromDriver(
const_cast<double *
>(R), 3 * N *
sizeof(
double));
328 impl_->broadcastFromDriver(
const_cast<int *
>(atomicNrs), N *
sizeof(
int));
329 impl_->broadcastFromDriver(
const_cast<double *
>(box), 9 *
sizeof(
double));
337 return impl_ &&
impl_->calculatorGroups() > 1;
341 const double *
const *positions,
342 const int *
const *atomicNrs,
double *
const *forces,
343 double *energies,
double *variances,
344 const double *
const *boxes) {
345 forceBatchOwned(nSystems, nAtoms, positions, atomicNrs, forces, energies,
346 variances, boxes,
nullptr);
350 const double *
const *positions,
351 const int *
const *atomicNrs,
352 double *
const *forces,
double *energies,
353 double *variances,
const double *
const *boxes,
354 const long *owners) {
355 std::vector<std::int64_t> ids(
static_cast<size_t>(nSystems), -1);
357 for (
long j = 0; j < nSystems; j++)
358 ids[
static_cast<size_t>(j)] = owners[j];
360 if (
impl_->calculatorWorld() > 1) {
361 std::int64_t hdr[3] = {kBatch, nAtoms, nSystems};
362 impl_->broadcastFromDriver(hdr,
sizeof(hdr));
363 std::vector<double> R(
static_cast<size_t>(3 * nAtoms * nSystems));
364 std::vector<int> Z(
static_cast<size_t>(nAtoms * nSystems));
365 std::vector<double> box(
static_cast<size_t>(9 * nSystems));
366 for (
long j = 0; j < nSystems; j++) {
367 std::copy(positions[j], positions[j] + 3 * nAtoms,
368 R.begin() + 3 * nAtoms * j);
369 std::copy(atomicNrs[j], atomicNrs[j] + nAtoms, Z.begin() + nAtoms * j);
370 std::copy(boxes[j], boxes[j] + 9, box.begin() + 9 * j);
372 impl_->broadcastFromDriver(R.data(), R.size() *
sizeof(
double));
373 impl_->broadcastFromDriver(Z.data(), Z.size() *
sizeof(
int));
374 impl_->broadcastFromDriver(box.data(), box.size() *
sizeof(
double));
375 impl_->broadcastFromDriver(ids.data(), ids.size() *
sizeof(std::int64_t));
378 computeBatch(nSystems, nAtoms, positions, atomicNrs, forces, energies, boxes,
380 for (
long j = 0; j < nSystems; j++) {
Opaque rgpot-backed engine (nwchemc / cpmdc / metatomic / xtb).
static bool mpiAbortRequested() noexcept
True once rgpot asked for MPI_Abort at exit in this process.
void force(long N, const double *R, const int *atomicNrs, double *F, double *U, const double *box) const
Potential backed by rgpot NWChemPot / CPMDPot (in-process dlopen of libnwchemc / libcpmdc).
RgpotPot(const eonc::Parameters &p)
bool engineAvailable() const
void computeSingle(long N, const double *R, const int *atomicNrs, double *F, double *U, const double *box)
std::unique_ptr< RGPotEngine > impl_
void forceBatchOwned(long nSystems, long nAtoms, const double *const *positions, const int *const *atomicNrs, double *const *forces, double *energies, double *variances, const double *const *boxes, const long *owners) override
System j runs on group owners[j] mod G when owners is given (an owner below zero falls back to j),...
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
void computeBatch(long nSystems, long nAtoms, const double *const *positions, const int *const *atomicNrs, double *const *forces, double *energies, const double *const *boxes, const std::int64_t *owners)
void force(long N, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
bool supportsBatchEvaluation() const noexcept override
With cpmdc calculator groups ([RgpotPot] ranks_per_image), a batch is spread over the groups: system ...
void releaseWorkersAtExit()
const metatomic_options_t & metatomic_options() const
const xtb_options_t & xtb_options() const
const rgpot_options_t & rgpot_options() const
void on_force_call(PotType t) noexcept override
static PotRegistry & get() noexcept
Process-lifetime singleton.
std::atomic< size_t > forceCallCounter
Potential(PotType a_ptype)
Production default: construction-scope registry, else PotRegistry::get().
RAII resource manager for the ARTn C library with global synchronization.
std::string extensions_directory
std::string engine_library
double xtb_electronic_temperature
std::string permanent_dir
bool torch_determinism_strict
double uncertainty_threshold