eOn client
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/PyGuard.h
"
5
#include "
eon/fpe_handler.h
"
6
7
#include <atomic>
8
#include <format>
9
#include <stdexcept>
10
#include <string>
11
#include <system_error>
12
13
#ifdef _WIN32
14
#include <process.h>
15
#else
16
#include <unistd.h>
17
#endif
18
19
namespace
{
20
21
std::filesystem::path makeAseWorkDir(
const
char
*prefix) {
22
static
std::atomic<long> instanceCount{0};
23
#ifdef _WIN32
24
const
long
pid =
static_cast<
long
>
(_getpid());
25
#else
26
const
long
pid =
static_cast<
long
>
(getpid());
27
#endif
28
std::error_code ec;
29
auto
dir = std::filesystem::temp_directory_path(ec);
30
if
(ec) {
31
throw
std::runtime_error(std::format(
32
"ASE-NWChem: cannot resolve temp directory: {}"
, ec.message()));
33
}
34
dir /= std::format(
"{}_{}_{}"
, prefix, pid, instanceCount.fetch_add(1));
35
std::filesystem::create_directories(dir, ec);
36
if
(ec) {
37
throw
std::runtime_error(
38
std::format(
"ASE-NWChem: cannot create work directory {}: {}"
,
39
dir.string(), ec.message()));
40
}
41
return
dir;
42
}
43
44
}
// namespace
45
46
// TODO(rg): Clean this up.
47
ASENwchemPot::ASENwchemPot
(
const
Parameters
&a_params)
48
:
Potential
(
PotType
::ASE_NWCHEM, a_params) {
49
eonc::ensure_interpreter
();
50
counter
= 0;
51
py::module_ sys = py::module_::import(
"sys"
);
52
// Fix for gh-184, see
53
// https://github.com/numpy/numpy/issues/20504#issuecomment-985542508
54
eonc::FPEHandler
fpeh;
55
fpeh.
eat_fpe
();
56
ase
= py::module_::import(
"ase"
);
57
fpeh.
restore_fpe
();
58
py::module_ ase_nwchem = py::module_::import(
"ase.calculators.nwchem"
);
59
py::module_ psutil = py::module_::import(
"psutil"
);
60
std::string nwchempth =
eonc::helpers::get_value_from_env_or_param
(
61
"NWCHEM_COMMAND"
, a_params.
ase_nwchem_options
.
path
,
""
,
""
,
true
);
62
std::string nwc_mult =
eonc::helpers::get_value_from_env_or_param
(
63
"NWCHEM_MULTIPLICITY"
, a_params.
ase_nwchem_options
.
multiplicity
,
"1"
,
64
"Using 1 as a default multiplicity, i.e. an RHF calculation suitable for "
65
"closed shell molecules, set multiplicity or the "
66
"environment variable NWCHEM_MULTIPLICITY.\n"
);
67
68
// Set up NWCHEM arguments
69
// TODO(rg): Stop hardcoding these
70
py::object NWCHEM = ase_nwchem.attr(
"NWChem"
);
71
size_t
nproc{0};
72
auto
mult = std::stoi(nwc_mult);
// 1 for singlet, 2 for doublet
73
74
// TODO(rg): Use
75
if
(a_params.
ase_nwchem_options
.
nproc
==
"auto"
) {
76
nproc = py::cast<int>(psutil.attr(
"cpu_count"
)(
false
));
77
}
else
{
78
nproc = std::stoi(a_params.
ase_nwchem_options
.
nproc
);
79
}
80
81
// dont_verify so we always get an energy and gradient
82
// mpi_launcher: mpirun (default) or srun on Slurm nodes (issue #193)
83
const
std::string &launcher = a_params.
ase_nwchem_options
.
mpi_launcher
;
84
std::string mpi_cmd;
85
if
(launcher ==
"srun"
) {
86
// srun uses -n for tasks; avoid OpenMPI-specific flags.
87
mpi_cmd =
88
std::format(
"srun -n {} {} PREFIX.nwi > PREFIX.nwo"
, nproc, nwchempth);
89
}
else
{
90
// Default and any other launcher treated as OpenMPI-style mpirun -n.
91
mpi_cmd = std::format(
"{} -n {} {} PREFIX.nwi > PREFIX.nwo"
, launcher,
92
nproc, nwchempth);
93
}
94
95
if
(mult != 1 && mult != 2) {
96
throw
std::runtime_error(
"Unknown spin multiplicity, we support 1 for "
97
"singlet and 2 for doublet ONLY."
);
98
}
99
100
// One directory per calculator instance so two LocalInProcess jobs in
101
// the same cwd do not write PREFIX.nwi / PREFIX.nwo over each other.
102
workDir
= makeAseWorkDir(
"eon_ase_nwchem"
);
103
104
// Common NWCHEM parameters
105
py::dict nwchem_params = py::dict(
106
"label"
_a =
"_eonpot_engrad"
,
107
"set"
_a = py::dict(
"geom:dont_verify"
_a =
true
),
108
"command"
_a = py::str(mpi_cmd),
"memory"
_a = py::str(
"2 gb"
),
109
"scf"
_a = 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(
"3-21G"
),
"task"
_a = py::str(
"gradient"
),
113
"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
variance =
nullptr
;
143
try
{
144
AtomMatrix
positions = AtomMatrix::Map(
const_cast<
double
*
>
(R), nAtoms, 3);
145
RotationMatrix
boxx = RotationMatrix::Map(
const_cast<
double
*
>
(box), 3, 3);
146
Eigen::VectorXi atmnmrs =
147
Eigen::Map<Eigen::VectorXi>(
const_cast<
int
*
>
(atomicNrs), nAtoms);
148
// XXX: NWChem refuses to perform SCF for anything but a molecule, so no box
149
// or pbc can be passed
150
py::object atoms = this->
ase
.attr(
"Atoms"
)(
"symbols"
_a = atmnmrs,
151
"positions"
_a = positions);
152
atoms.attr(
"calc"
) = this->
calc
;
153
// atoms.attr("center")();
154
double
py_e = py::cast<double>(atoms.attr(
"get_potential_energy"
)());
155
Eigen::MatrixXd py_force =
156
py::cast<Eigen::MatrixXd>(atoms.attr(
"get_forces"
)());
157
158
// Populate the output parameters
159
*U = py_e;
160
for
(
long
i = 0; i < nAtoms; ++i) {
161
F[3 * i] = py_force(i, 0);
162
F[3 * i + 1] = py_force(i, 1);
163
F[3 * i + 2] = py_force(i, 2);
164
}
165
}
catch
(py::error_already_set &e) {
166
throw
std::runtime_error(std::string(
"ASE-NWChem Python error: "
) +
167
e.what());
168
}
catch
(
const
std::exception &e) {
169
throw
std::runtime_error(std::string(
"ASE-NWChem C++ exception: "
) +
170
e.what());
171
}
172
173
counter
++;
174
return
;
175
}
ASE_NWCHEM.h
RotationMatrix
Eigen::Matrix< double, 3, 3, eOnStorageOrder > RotationMatrix
Definition
Eigen.h:38
AtomMatrix
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition
Eigen.h:37
EnvHelpers.hpp
EonLogger.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::workDir
std::filesystem::path workDir
Definition
ASE_NWCHEM.h:31
ASENwchemPot::calc
py::object calc
Definition
ASE_NWCHEM.h:29
ASENwchemPot::ase
py::object ase
Definition
ASE_NWCHEM.h:30
ASENwchemPot::ASENwchemPot
ASENwchemPot(const Parameters &a_params)
Definition
ASE_NWCHEM.cpp:47
ASENwchemPot::counter
size_t counter
Definition
ASE_NWCHEM.h:32
eonc::FPEHandler
Definition
fpe_handler.h:25
eonc::FPEHandler::restore_fpe
void restore_fpe()
Definition
fpe_handler.cpp:251
eonc::FPEHandler::eat_fpe
void eat_fpe()
Definition
fpe_handler.cpp:246
eonc::Parameters
Definition
Parameters.h:28
eonc::Parameters::ase_nwchem_options
struct eonc::Parameters::ase_nwchem_options_t ase_nwchem_options
eonc::Potential::Potential
Potential(PotType a_ptype)
Definition
Potential.h:35
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::PotType
PotType
Definition
BaseStructures.h:36
eonc::ensure_interpreter
void ensure_interpreter()
Definition
NbGuard.h:21
eonc::Parameters::ase_nwchem_options_t::nproc
std::string nproc
Definition
Parameters.h:366
eonc::Parameters::ase_nwchem_options_t::scf_maxiter
long scf_maxiter
Definition
Parameters.h:371
eonc::Parameters::ase_nwchem_options_t::path
std::string path
Definition
Parameters.h:365
eonc::Parameters::ase_nwchem_options_t::multiplicity
std::string multiplicity
Definition
Parameters.h:369
eonc::Parameters::ase_nwchem_options_t::mpi_launcher
std::string mpi_launcher
Definition
Parameters.h:368
eonc::Parameters::ase_nwchem_options_t::scf_thresh
double scf_thresh
Definition
Parameters.h:370
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