Loading...
Searching...
No Matches
ASENwchemPot Class Reference

#include <ASE_NWCHEM.h>

Inheritance diagram for ASENwchemPot:

Public Member Functions

 ASENwchemPot (const eonc::Parameters &a_params)
virtual ~ASENwchemPot ()
void force (long nAtoms, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
bool isThreadSafe () const noexcept override
 Whether this potential's force() can be called from multiple threads on the SAME instance.
bool needsPerImageInstance () const noexcept override
 NWChem runs as external subprocess; separate instances are independent.
bool requiresIsolatedMoleculeLayout () const noexcept override
 ASE-NWChem molecular SCF does not support PBC (#188).
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 unsigned layoutFlags () const noexcept
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 Attributes

py::object calc
py::object ase
std::filesystem::path workDir
size_t counter {0}

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 25 of file ASE_NWCHEM.h.

Constructor & Destructor Documentation

◆ ASENwchemPot()

ASENwchemPot::ASENwchemPot ( const eonc::Parameters & a_params)

Definition at line 47 of file ASE_NWCHEM.cpp.

48 : eonc::Potential(eonc::PotType::ASE_NWCHEM, a_params) {
49 using namespace pybind11::literals;
51 counter = 0;
52 py::module_ sys = py::module_::import("sys");
53 // Fix for gh-184, see
54 // https://github.com/numpy/numpy/issues/20504#issuecomment-985542508
55 eonc::FPEHandler fpeh;
56 fpeh.eat_fpe();
57 ase = py::module_::import("ase");
58 fpeh.restore_fpe();
59 py::module_ ase_nwchem = py::module_::import("ase.calculators.nwchem");
60 py::module_ psutil = py::module_::import("psutil");
61 std::string nwchempth = eonc::helpers::get_value_from_env_or_param(
62 "NWCHEM_COMMAND", a_params.ase_nwchem_options().path, "", "", true);
63 std::string nwc_mult = eonc::helpers::get_value_from_env_or_param(
64 "NWCHEM_MULTIPLICITY", a_params.ase_nwchem_options().multiplicity, "1",
65 "Using 1 as a default multiplicity, i.e. an RHF calculation suitable for "
66 "closed shell molecules, set multiplicity or the "
67 "environment variable NWCHEM_MULTIPLICITY.\n");
68
69 py::object NWCHEM = ase_nwchem.attr("NWChem");
70 size_t nproc{0};
71 auto mult = std::stoi(nwc_mult); // 1 for singlet, 2 for doublet
72
73 if (a_params.ase_nwchem_options().nproc == "auto") {
74 nproc = py::cast<int>(psutil.attr("cpu_count")(false));
75 } else {
76 nproc = std::stoi(a_params.ase_nwchem_options().nproc);
77 }
78
79 // dont_verify so we always get an energy and gradient
80 // mpi_launcher: mpirun (default) or srun on Slurm nodes (issue #193)
81 const std::string &launcher = a_params.ase_nwchem_options().mpi_launcher;
82 std::string mpi_cmd;
83 if (launcher == "srun") {
84 // srun uses -n for tasks; avoid OpenMPI-specific flags.
85 mpi_cmd =
86 std::format("srun -n {} {} PREFIX.nwi > PREFIX.nwo", nproc, nwchempth);
87 } else {
88 // Default and any other launcher treated as OpenMPI-style mpirun -n.
89 mpi_cmd = std::format("{} -n {} {} PREFIX.nwi > PREFIX.nwo", launcher,
90 nproc, nwchempth);
91 }
92
93 if (mult != 1 && mult != 2) {
94 throw std::runtime_error("Unknown spin multiplicity, we support 1 for "
95 "singlet and 2 for doublet ONLY.");
96 }
97
98 // One directory per calculator instance so two LocalInProcess jobs in
99 // the same cwd do not write PREFIX.nwi / PREFIX.nwo over each other.
100 workDir = makeAseWorkDir("eon_ase_nwchem");
101
102 // Common NWCHEM parameters
103 py::dict nwchem_params = py::dict(
104 "label"_a = "_eonpot_engrad",
105 "set"_a = py::dict("geom:dont_verify"_a = true),
106 "command"_a = py::str(mpi_cmd),
107 "memory"_a = py::str(a_params.ase_nwchem_options().memory),
108 "scf"_a =
109 py::dict("nopen"_a = mult - 1,
110 "thresh"_a = a_params.ase_nwchem_options().scf_thresh,
111 "maxiter"_a = a_params.ase_nwchem_options().scf_maxiter),
112 "basis"_a = py::str(a_params.ase_nwchem_options().basis),
113 "task"_a = py::str("gradient"), "directory"_a = workDir.string());
114
115 // Set flag for doublet (mult == 2)
116 if (mult == 2) {
117 nwchem_params["scf"]["uhf"] = py::none();
118 }
119
120 try {
121 this->calc = NWCHEM(**nwchem_params);
122 } catch (...) {
123 std::error_code ec;
124 std::filesystem::remove_all(workDir, ec);
125 workDir.clear();
126 throw;
127 }
128};
std::filesystem::path workDir
Definition ASE_NWCHEM.h:30
py::object calc
Definition ASE_NWCHEM.h:28
py::object ase
Definition ASE_NWCHEM.h:29
size_t counter
Definition ASE_NWCHEM.h:31
const ase_nwchem_options_t & ase_nwchem_options() const
std::string get_value_from_env_or_param(const char *env_variable, const std::string &param_value, const std::string &default_value, const std::string &warning_message, const bool is_mandatory)
Definition EnvHelpers.cc:7
void ensure_interpreter()
Definition NbGuard.h:21

◆ ~ASENwchemPot()

ASENwchemPot::~ASENwchemPot ( )
virtual

Definition at line 130 of file ASE_NWCHEM.cpp.

130 {
131 QUILL_LOG_INFO(eonc::log::get(), "[ASENwchem] called potential {} times",
132 counter);
133 if (!workDir.empty()) {
134 std::error_code ec;
135 std::filesystem::remove_all(workDir, ec);
136 }
137}
quill::Logger * get() noexcept
Get or create the default "combi" logger.
Definition EonLogger.h:44

Member Function Documentation

◆ force()

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

Implements eonc::Potential.

Definition at line 139 of file ASE_NWCHEM.cpp.

141 {
142 using namespace pybind11::literals;
143 if (variance != nullptr) {
144 *variance = 0.0;
145 }
146 try {
147 const Eigen::Map<const AtomMatrix> positions(R, nAtoms, 3);
148 const Eigen::Map<const RotationMatrix> boxx(box);
149 const Eigen::Map<const Eigen::VectorXi> atmnmrs(atomicNrs, nAtoms);
150 if (!boxx.isIdentity(1e-6)) {
151 QUILL_LOG_WARNING(eonc::log::get(), "ASE-NWChem ignores the simulation "
152 "cell; NWChem SCF is molecular only");
153 }
154 py::object atoms = this->ase.attr("Atoms")("symbols"_a = atmnmrs,
155 "positions"_a = positions);
156 atoms.attr("calc") = this->calc;
157 // atoms.attr("center")();
158 double py_e = py::cast<double>(atoms.attr("get_potential_energy")());
159 Eigen::MatrixXd py_force =
160 py::cast<Eigen::MatrixXd>(atoms.attr("get_forces")());
161
162 // Populate the output parameters
163 *U = py_e;
164 for (long i = 0; i < nAtoms; ++i) {
165 F[3 * i] = py_force(i, 0);
166 F[3 * i + 1] = py_force(i, 1);
167 F[3 * i + 2] = py_force(i, 2);
168 }
169 } catch (py::error_already_set &e) {
170 throw std::runtime_error(std::string("ASE-NWChem Python error: ") +
171 e.what());
172 } catch (const std::exception &e) {
173 throw std::runtime_error(std::string("ASE-NWChem C++ exception: ") +
174 e.what());
175 }
176
177 counter++;
178 return;
179}

◆ isThreadSafe()

bool ASENwchemPot::isThreadSafe ( ) const
inlinenodiscardoverridevirtualnoexcept

Whether this potential's force() can be called from multiple threads on the SAME instance.

Python-based potentials return false. Potentials with internal mutex (MetatomicPotential) return true but serialize internally – use needsPerImageInstance() to check if separate instances would enable true parallelism.

Reimplemented from eonc::Potential.

Definition at line 40 of file ASE_NWCHEM.h.

40{ return false; }

◆ needsPerImageInstance()

bool ASENwchemPot::needsPerImageInstance ( ) const
inlinenodiscardoverridevirtualnoexcept

NWChem runs as external subprocess; separate instances are independent.

Reimplemented from eonc::Potential.

Definition at line 42 of file ASE_NWCHEM.h.

42 {
43 return true;
44 }

◆ requiresIsolatedMoleculeLayout()

bool ASENwchemPot::requiresIsolatedMoleculeLayout ( ) const
inlinenodiscardoverridevirtualnoexcept

ASE-NWChem molecular SCF does not support PBC (#188).

Reimplemented from eonc::Potential.

Definition at line 46 of file ASE_NWCHEM.h.

46 {
47 return true;
48 }

Member Data Documentation

◆ ase

py::object ASENwchemPot::ase
private

Definition at line 29 of file ASE_NWCHEM.h.

◆ calc

py::object ASENwchemPot::calc
private

Definition at line 28 of file ASE_NWCHEM.h.

◆ counter

size_t ASENwchemPot::counter {0}
private

Definition at line 31 of file ASE_NWCHEM.h.

31{0};

◆ workDir

std::filesystem::path ASENwchemPot::workDir
private

Definition at line 30 of file ASE_NWCHEM.h.


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