24#include <system_error>
27#ifndef WIN32_LEAN_AND_MEAN
28#define WIN32_LEAN_AND_MEAN
44constexpr const char *kToExtPot =
"from_eon_to_extpot";
45constexpr const char *kFromExtPot =
"from_extpot_to_eon";
49constexpr const char *kRunDirVariable =
"EON_EXTPOT_RUN_DIR";
53 return static_cast<long>(_getpid());
55 return static_cast<long>(getpid());
64std::string windowsPythonCommand() {
67 SearchPathA(
nullptr,
"python.exe",
nullptr, MAX_PATH, buf,
nullptr);
68 if (n > 0 && n < MAX_PATH) {
81std::string composeCommand(
const std::string &workDir,
82 const std::string &runDir,
83 const std::string &command) {
85 const std::string quotedCommand =
88 return std::format(
"cd /d {} && set \"{}={}\" && {}",
93 return std::format(
"cd {} && export {}={} && {}",
106std::string resolveCommand(
const std::string &command) {
108 const std::filesystem::path named{command};
109 if (!std::filesystem::is_regular_file(named, ec) || ec) {
112 const std::filesystem::path resolved = std::filesystem::absolute(named, ec);
116 return resolved.string();
130 std::filesystem::remove(
exchangeDir / kToExtPot, ec);
131 std::filesystem::remove(
exchangeDir / kFromExtPot, ec);
145 static std::atomic<long> instanceCount{0};
146 const std::filesystem::path named{
147 std::format(
"extpot_{}_{}", processId(), instanceCount.fetch_add(1))};
148 exchangeDir = std::filesystem::absolute(named, ec);
151 throw std::runtime_error(std::format(
"Could not resolve {}: {}",
152 named.string(), ec.message()));
155 std::filesystem::create_directory(
exchangeDir, ec);
157 throw std::runtime_error(std::format(
"Could not create {} to run {} in: {}",
164 std::filesystem::remove(
exchangeDir / kFromExtPot, ec);
168 double *U,
double *variance,
const double *box) {
169 if (variance !=
nullptr) {
173 throw std::runtime_error(
174 "ExtPot needs potential_options.extPotPath to name a program to run");
180 const std::filesystem::path runDir = std::filesystem::current_path(ec);
182 ec ? std::string{} : runDir.string(),
193 const std::filesystem::path toExtPot =
exchangeDir / kToExtPot;
194 std::ofstream out(toExtPot, std::ios::trunc);
196 throw std::runtime_error(
197 std::format(
"Could not open {} for writing", toExtPot.string()));
200 for (
int i = 0; i < 3; i++) {
201 out << std::format(
"{:.19f}\t{:.19f}\t{:.19f}\n", box[i * 3 + 0],
202 box[i * 3 + 1], box[i * 3 + 2]);
205 for (
long i = 0; i < N; i++) {
206 out << std::format(
"{}\t{:.19f}\t{:.19f}\t{:.19f}\n", atomicNrs[i],
207 R[i * 3 + 0], R[i * 3 + 1], R[i * 3 + 2]);
212 throw std::runtime_error(
213 std::format(
"Could not write the structure to {}", toExtPot.string()));
222 const std::filesystem::path fromExtPot =
exchangeDir / kFromExtPot;
223 std::ifstream in(fromExtPot);
225 throw std::runtime_error(
226 std::format(
"Could not open {}; the external program left no result",
227 fromExtPot.string()));
231 throw std::runtime_error(
232 std::format(
"Could not read the energy from {}", fromExtPot.string()));
235 for (
long i = 0; i < N; i++) {
236 if (!(in >> F[i * 3 + 0] >> F[i * 3 + 1] >> F[i * 3 + 2])) {
237 throw std::runtime_error(
238 std::format(
"{} holds forces for {} atoms, expected {}",
239 fromExtPot.string(), i, N));
void recieveFromSystem(long N, double *F, double *U)
void prepareExchangeDir()
std::string eon_extpot_path
ExtPot(const eonc::Parameters &p)
std::filesystem::path exchangeDir
void passToSystem(long N, const double *R, const int *atomicNrs, const double *box)
void force(long N, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
Potential(PotType a_ptype)
Production default: construction-scope registry, else PotRegistry::get().
void runOrThrow(const std::string &command)
Run a shell command, throwing when it does not succeed.
std::string shellQuote(const std::string &text)
Wrap a path for the shell system() hands the command to, so spaces in it survive.
std::string wrapResolvedProgram(const std::string &command, const std::string &python)
Quote a resolved program path, and on Windows prefix a script so cmd.exe can start it.
RAII resource manager for the ARTn C library with global synchronization.