Loading...
Searching...
No Matches
ExtPot Class Reference

#include <ExtPot.h>

Inheritance diagram for ExtPot:

Public Member Functions

 ExtPot (const eonc::Parameters &p)
 ~ExtPot ()
void cleanMemory (void)
void force (long N, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
bool isThreadSafe () const noexcept override
 One instance owns one exchange directory, so two threads in force() on it write the same structure file and read the same result.
bool needsPerImageInstance () const noexcept override
 The external program runs as a subprocess and each instance runs it in a directory of its own, so separate instances are independent.
unsigned layoutFlags () const noexcept override
Public Member Functions inherited from eonc::Potential
 Potential (PotType a_ptype)
 Production default: construction-scope registry, else PotRegistry::get().
 Potential (PotType a_ptype, IPotRegistry &registry)
 Test seam: injected registry, no process-default get() counters.
 Potential (PotType a_ptype, const Parameters &p)
 Potential (const Parameters &a_params)
virtual ~Potential ()
void force (std::span< const double > positions, std::span< const int > atomicNrs, std::span< double > forces, double *energy, double *variance, std::span< const double > box)
 C++ call site: size-checked view over the raw FFI force().
virtual void setFixedMask (long nAtoms, const double *isFixed)
 Optional frozen-atom mask (nAtoms*3, 1.0 = fixed).
std::tuple< double, AtomMatrix > get_ef (const AtomMatrix &pos, const VectorXi &atmnrs, const Matrix3d &box)
PotType getType () const
virtual double finiteCutoff () const noexcept
 Finite interaction range in position length units.
virtual bool isSurrogate () const noexcept
 Whether this is a surrogate (GP) potential.
virtual bool requiresIsolatedMoleculeLayout () const noexcept
 True for molecular QM / non-PBC backends (NWChem socket, ASE ORCA/NWChem, …).
virtual bool isSharedInstanceThreadSafe () const noexcept
 Conservative gate for sharing one Potential instance across threads.
virtual std::shared_ptr< Potential > clonePotential () const
 Independent instance that does not reload from disk.
virtual bool supportsBatchEvaluation () const noexcept
 Whether this potential supports batched evaluation of N systems in a single call.
virtual bool computesStress () const noexcept
 True when force() leaves a Cauchy stress that cauchyStress() can read until the next force() on this instance.
virtual Matrix3d cauchyStress () const
 Cauchy stress in eV/Angstrom^3.
virtual 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)
 Evaluate forces for N systems in a single call.
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)

Private Member Functions

void passToSystem (long N, const double *R, const int *atomicNrs, const double *box)
void recieveFromSystem (long N, double *F, double *U)
void prepareExchangeDir ()

Private Attributes

std::string eon_extpot_path
std::filesystem::path exchangeDir
bool retainExchangeDir {false}

Additional Inherited Members

Public Types inherited from eonc::Potential
enum class  PotLayout : unsigned { InProcess = 1u << 0 , NeedsWorkingDirectory = 1u << 1 , Subprocess = 1u << 2 }
 How the pot is executed. Combine with bitwise or. More...
Public Attributes inherited from eonc::Potential
std::atomic< size_t > forceCallCounter
Protected Attributes inherited from eonc::Potential
PotType ptype

Detailed Description

Definition at line 19 of file ExtPot.h.

Constructor & Destructor Documentation

◆ ExtPot()

ExtPot::ExtPot ( const eonc::Parameters & p)

Definition at line 121 of file ExtPot.cpp.

122 : eonc::Potential(p),
123 eon_extpot_path{resolveCommand(p.potential_options().extPotPath)} {}
std::string eon_extpot_path
Definition ExtPot.h:50
const potential_options_t & potential_options() const

◆ ~ExtPot()

ExtPot::~ExtPot ( )

Definition at line 137 of file ExtPot.cpp.

137{ cleanMemory(); }
void cleanMemory(void)
Definition ExtPot.cpp:125

Member Function Documentation

◆ cleanMemory()

void ExtPot::cleanMemory ( void )

Definition at line 125 of file ExtPot.cpp.

125 {
126 if (exchangeDir.empty() || retainExchangeDir) {
127 return;
128 }
129 std::error_code ec;
130 std::filesystem::remove(exchangeDir / kToExtPot, ec);
131 std::filesystem::remove(exchangeDir / kFromExtPot, ec);
132 // Removes the directory only when it is empty, so whatever else the
133 // external program wrote there stays.
134 std::filesystem::remove(exchangeDir, ec);
135}
bool retainExchangeDir
Definition ExtPot.h:57
std::filesystem::path exchangeDir
Definition ExtPot.h:54

◆ force()

void ExtPot::force ( long N,
const double * R,
const int * atomicNrs,
double * F,
double * U,
double * variance,
const double * box )
overridevirtual

Implements eonc::Potential.

Definition at line 167 of file ExtPot.cpp.

168 {
169 if (variance != nullptr) {
170 *variance = 0.0;
171 }
172 if (eon_extpot_path.empty()) {
173 throw std::runtime_error(
174 "ExtPot needs potential_options.extPotPath to name a program to run");
175 }
177 retainExchangeDir = true;
178 passToSystem(N, R, atomicNrs, box);
179 std::error_code ec;
180 const std::filesystem::path runDir = std::filesystem::current_path(ec);
181 eonc::pot::runOrThrow(composeCommand(exchangeDir.string(),
182 ec ? std::string{} : runDir.string(),
184 recieveFromSystem(N, F, U);
185 retainExchangeDir = false;
186 return;
187}
void recieveFromSystem(long N, double *F, double *U)
Definition ExtPot.cpp:218
void prepareExchangeDir()
Definition ExtPot.cpp:139
void passToSystem(long N, const double *R, const int *atomicNrs, const double *box)
Definition ExtPot.cpp:189
void runOrThrow(const std::string &command)
Run a shell command, throwing when it does not succeed.

◆ isThreadSafe()

bool ExtPot::isThreadSafe ( ) const
inlinenodiscardoverridevirtualnoexcept

One instance owns one exchange directory, so two threads in force() on it write the same structure file and read the same result.

Reimplemented from eonc::Potential.

Definition at line 29 of file ExtPot.h.

29{ return false; }

◆ layoutFlags()

unsigned ExtPot::layoutFlags ( ) const
inlinenodiscardoverridevirtualnoexcept

Reimplemented from eonc::Potential.

Definition at line 35 of file ExtPot.h.

35 {
36 return static_cast<unsigned>(eonc::Potential::PotLayout::Subprocess) |
37 static_cast<unsigned>(
39 }

◆ needsPerImageInstance()

bool ExtPot::needsPerImageInstance ( ) const
inlinenodiscardoverridevirtualnoexcept

The external program runs as a subprocess and each instance runs it in a directory of its own, so separate instances are independent.

Reimplemented from eonc::Potential.

Definition at line 32 of file ExtPot.h.

32 {
33 return true;
34 }

◆ passToSystem()

void ExtPot::passToSystem ( long N,
const double * R,
const int * atomicNrs,
const double * box )
private

Definition at line 189 of file ExtPot.cpp.

192{
193 const std::filesystem::path toExtPot = exchangeDir / kToExtPot;
194 std::ofstream out(toExtPot, std::ios::trunc);
195 if (!out) {
196 throw std::runtime_error(
197 std::format("Could not open {} for writing", toExtPot.string()));
198 }
199
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]);
203 }
204
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]);
208 }
209
210 out.close();
211 if (!out) {
212 throw std::runtime_error(
213 std::format("Could not write the structure to {}", toExtPot.string()));
214 }
215 return;
216}

◆ prepareExchangeDir()

void ExtPot::prepareExchangeDir ( )
private

Definition at line 139 of file ExtPot.cpp.

139 {
140 std::error_code ec;
141 if (exchangeDir.empty()) {
142 // One directory per potential object. A client started alongside this
143 // one carries a different process id, and a second potential in this
144 // process a different index, so no two of them name the same file.
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);
149 if (ec) {
150 exchangeDir.clear();
151 throw std::runtime_error(std::format("Could not resolve {}: {}",
152 named.string(), ec.message()));
153 }
154 }
155 std::filesystem::create_directory(exchangeDir, ec);
156 if (ec) {
157 throw std::runtime_error(std::format("Could not create {} to run {} in: {}",
159 ec.message()));
160 }
161 // A result left by an earlier call, or by a client that died holding this
162 // process id, is read as this call's forces when the external program
163 // writes nothing.
164 std::filesystem::remove(exchangeDir / kFromExtPot, ec);
165}

◆ recieveFromSystem()

void ExtPot::recieveFromSystem ( long N,
double * F,
double * U )
private

Create the directory the external command runs in and clear any exchange file left in it.

Definition at line 218 of file ExtPot.cpp.

221{
222 const std::filesystem::path fromExtPot = exchangeDir / kFromExtPot;
223 std::ifstream in(fromExtPot);
224 if (!in) {
225 throw std::runtime_error(
226 std::format("Could not open {}; the external program left no result",
227 fromExtPot.string()));
228 }
229
230 if (!(in >> *U)) {
231 throw std::runtime_error(
232 std::format("Could not read the energy from {}", fromExtPot.string()));
233 }
234
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));
240 }
241 }
242 return;
243}

Member Data Documentation

◆ eon_extpot_path

std::string ExtPot::eon_extpot_path
private

The directory this potential runs the external command in. The exchange files keep their documented names and live here, so two clients started in one directory cannot read each other's numbers.

Definition at line 50 of file ExtPot.h.

◆ exchangeDir

std::filesystem::path ExtPot::exchangeDir
private

Set while a call is in flight, so a call that fails leaves its exchange files in place to be looked at.

Definition at line 54 of file ExtPot.h.

◆ retainExchangeDir

bool ExtPot::retainExchangeDir {false}
private

Definition at line 57 of file ExtPot.h.

57{false};

The documentation for this class was generated from the following files:
  • /home/runner/work/eOn/eOn/include/eon/potentials/ExtPot/ExtPot.h
  • /home/runner/work/eOn/eOn/client/potentials/ExtPot/ExtPot.cpp