eOn 3.2.0
Long-timescale dynamics: aKMC, NEB, parallel replica
☾
Toggle main menu visibility
Loading...
Searching...
No Matches
ASE_NWCHEM.cpp
Go to the documentation of this file.
1
#include "
eon/potentials/ASE_NWCHEM/ASE_NWCHEM.h
"
2
#include "
eon/EnvHelpers.hpp
"
3
#include "
eon/EonLogger.h
"
4
#include "
eon/Parameters.h
"
5
#include "
eon/PyGuard.h
"
6
#include "
eon/fpe_handler.h
"
7
8
#include <atomic>
9
#include <format>
10
#include <stdexcept>
11
#include <string>
12
#include <system_error>
13
14
#ifdef _WIN32
15
#include <process.h>
16
#else
17
#include <unistd.h>
18
#endif
19
20
namespace
{
21
22
std::filesystem::path makeAseWorkDir(
const
char
*prefix) {
23
static
std::atomic<long> instanceCount{0};
24
#ifdef _WIN32
25
const
long
pid =
static_cast<
long
>
(_getpid());
26
#else
27
const
long
pid =
static_cast<
long
>
(getpid());
28
#endif
29
std::error_code ec;
30
auto
dir = std::filesystem::temp_directory_path(ec);
31
if
(ec) {
32
throw
std::runtime_error(std::format(
33
"ASE-NWChem: cannot resolve temp directory: {}"
, ec.message()));
34
}
35
dir /= std::format(
"{}_{}_{}"
, prefix, pid, instanceCount.fetch_add(1));
36
std::filesystem::create_directories(dir, ec);
37
if
(ec) {
38
throw
std::runtime_error(
39
std::format(
"ASE-NWChem: cannot create work directory {}: {}"
,
40
dir.string(), ec.message()));
41
}
42
return
dir;
43
}
44
45
}
// namespace
46
47
ASENwchemPot::ASENwchemPot
(
const
eonc::Parameters
&a_params)
48
:
eonc
::
Potential
(
eonc
::PotType::ASE_NWCHEM, a_params) {
49
using namespace
pybind11::literals;
50
eonc::ensure_interpreter
();
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
};
129
130
ASENwchemPot::~ASENwchemPot
() {
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
}
138
139
void
ASENwchemPot::force
(
long
nAtoms,
const
double
*R,
const
int
*atomicNrs,
140
double
*F,
double
*U,
double
*variance,
141
const
double
*box) {
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
}
ASE_NWCHEM.h
EnvHelpers.hpp
EonLogger.h
Parameters.h
PyGuard.h
ASENwchemPot::force
void force(long nAtoms, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
Definition
ASE_NWCHEM.cpp:139
ASENwchemPot::~ASENwchemPot
virtual ~ASENwchemPot()
Definition
ASE_NWCHEM.cpp:130
ASENwchemPot::ASENwchemPot
ASENwchemPot(const eonc::Parameters &a_params)
Definition
ASE_NWCHEM.cpp:47
ASENwchemPot::workDir
std::filesystem::path workDir
Definition
ASE_NWCHEM.h:30
ASENwchemPot::calc
py::object calc
Definition
ASE_NWCHEM.h:28
ASENwchemPot::ase
py::object ase
Definition
ASE_NWCHEM.h:29
ASENwchemPot::counter
size_t counter
Definition
ASE_NWCHEM.h:31
eonc::FPEHandler
Definition
fpe_handler.h:34
eonc::FPEHandler::restore_fpe
void restore_fpe()
Definition
fpe_handler.cpp:561
eonc::FPEHandler::eat_fpe
void eat_fpe()
Definition
fpe_handler.cpp:556
eonc::Parameters
Definition
Parameters.h:35
eonc::Parameters::ase_nwchem_options
const ase_nwchem_options_t & ase_nwchem_options() const
Definition
ParametersAccess.cpp:156
eonc::Potential::Potential
Potential(PotType a_ptype)
Production default: construction-scope registry, else PotRegistry::get().
Definition
PotentialParams.cpp:29
fpe_handler.h
eonc::helpers::get_value_from_env_or_param
std::string get_value_from_env_or_param(const char *env_variable, const std::string ¶m_value, const std::string &default_value, const std::string &warning_message, const bool is_mandatory)
Definition
EnvHelpers.cc:7
eonc::log::get
quill::Logger * get() noexcept
Get or create the default "combi" logger.
Definition
EonLogger.h:44
eonc
RAII resource manager for the ARTn C library with global synchronization.
Definition
ARTnSaddleSearch.cpp:23
eonc::ensure_interpreter
void ensure_interpreter()
Definition
NbGuard.h:21
eonc::ase_nwchem_options_t::multiplicity
std::string multiplicity
Definition
ParametersOptions.h:411
eonc::ase_nwchem_options_t::basis
std::string basis
Definition
ParametersOptions.h:414
eonc::ase_nwchem_options_t::mpi_launcher
std::string mpi_launcher
Definition
ParametersOptions.h:410
eonc::ase_nwchem_options_t::memory
std::string memory
Definition
ParametersOptions.h:415
eonc::ase_nwchem_options_t::nproc
std::string nproc
Definition
ParametersOptions.h:408
eonc::ase_nwchem_options_t::scf_maxiter
long scf_maxiter
Definition
ParametersOptions.h:413
eonc::ase_nwchem_options_t::path
std::string path
Definition
ParametersOptions.h:407
eonc::ase_nwchem_options_t::scf_thresh
double scf_thresh
Definition
ParametersOptions.h:412
client
potentials
ASE_NWCHEM
ASE_NWCHEM.cpp
Generated by
1.17.0
Generated by
Doxygen 1.17.0
Analytics by
Antics
provided by
TurtleTech ehf