eOn client
Long-timescale dynamics: aKMC, NEB, parallel replica
☾
Toggle main menu visibility
Loading...
Searching...
No Matches
ASE_ORCA.cpp
Go to the documentation of this file.
1
/*
2
** This file is part of eOn.
3
**
4
** SPDX-License-Identifier: BSD-3-Clause
5
**
6
** Copyright (c) 2010--present, eOn Development Team
7
** All rights reserved.
8
**
9
** Repo:
10
** https://github.com/TheochemUI/eOn
11
*/
12
13
#include "
eon/potentials/ASE_ORCA/ASE_ORCA.h
"
14
#include "
eon/EnvHelpers.hpp
"
15
#include "
eon/EonLogger.h
"
16
#include "
eon/PyGuard.h
"
17
#include "
eon/fpe_handler.h
"
18
19
#include <atomic>
20
#include <format>
21
#include <stdexcept>
22
#include <string>
23
#include <system_error>
24
25
#ifdef _WIN32
26
#include <process.h>
27
#else
28
#include <unistd.h>
29
#endif
30
31
namespace
{
32
33
std::filesystem::path makeAseWorkDir(
const
char
*prefix) {
34
static
std::atomic<long> instanceCount{0};
35
#ifdef _WIN32
36
const
long
pid =
static_cast<
long
>
(_getpid());
37
#else
38
const
long
pid =
static_cast<
long
>
(getpid());
39
#endif
40
std::error_code ec;
41
auto
dir = std::filesystem::temp_directory_path(ec);
42
if
(ec) {
43
throw
std::runtime_error(std::format(
44
"ASE-ORCA: cannot resolve temp directory: {}"
, ec.message()));
45
}
46
dir /= std::format(
"{}_{}_{}"
, prefix, pid, instanceCount.fetch_add(1));
47
std::filesystem::create_directories(dir, ec);
48
if
(ec) {
49
throw
std::runtime_error(
50
std::format(
"ASE-ORCA: cannot create work directory {}: {}"
,
51
dir.string(), ec.message()));
52
}
53
return
dir;
54
}
55
56
}
// namespace
57
58
// XXX: This always assumes that charge is 0, mult is 1
59
// ASE default ----------------------------^ ---------^
60
// See also: https://gitlab.com/ase/ase/-/issues/1357
61
ASEOrcaPot::ASEOrcaPot
(
const
Parameters
&a_params)
62
:
Potential
(
PotType
::ASE_ORCA, a_params) {
63
eonc::ensure_interpreter
();
64
counter
= 0;
65
py::module_ sys = py::module_::import(
"sys"
);
66
// Fix for gh-184, see
67
// https://github.com/numpy/numpy/issues/20504#issuecomment-985542508
68
eonc::FPEHandler
fpeh;
69
fpeh.
eat_fpe
();
70
ase
= py::module_::import(
"ase"
);
71
fpeh.
restore_fpe
();
72
py::module_ ase_orca = py::module_::import(
"ase.calculators.orca"
);
73
py::module_ psutil = py::module_::import(
"psutil"
);
74
std::string orcpth =
eonc::helpers::get_value_from_env_or_param
(
75
"ORCA_COMMAND"
, a_params.
ase_orca_options
.
path
,
""
,
""
,
true
);
76
std::string orca_simpleinput =
eonc::helpers::get_value_from_env_or_param
(
77
"ORCA_SIMPLEINPUT"
, a_params.
ase_orca_options
.
simpleinput
,
"ENGRAD HF-3c"
,
78
"Using ENGRAD HF-3c as a default input, set simpleinput or the "
79
"environment variable ORCA_SIMPLEINPUT.\n"
);
80
81
// Set up ORCA profile and calculator
82
py::object OrcaProfile = ase_orca.attr(
"OrcaProfile"
);
83
py::object ORCA = ase_orca.attr(
"ORCA"
);
84
size_t
nproc{0};
85
86
if
(a_params.
ase_orca_options
.
nproc
==
"auto"
) {
87
nproc = py::cast<int>(psutil.attr(
"cpu_count"
)(
false
));
88
}
else
{
89
nproc = std::stoi(a_params.
ase_orca_options
.
nproc
);
90
}
91
92
// One directory per calculator instance so two LocalInProcess jobs in
93
// the same cwd do not share ORCA scratch and output files.
94
workDir
= makeAseWorkDir(
"eon_ase_orca"
);
95
96
try
{
97
this->
calc
=
98
ORCA(
"profile"
_a = OrcaProfile(py::str(orcpth)),
99
"orcasimpleinput"
_a = orca_simpleinput,
100
"orcablocks"
_a = py::str(std::format(
"%pal nprocs {} end"
, nproc)),
101
"directory"
_a =
workDir
.string());
102
}
catch
(...) {
103
std::error_code ec;
104
std::filesystem::remove_all(
workDir
, ec);
105
workDir
.clear();
106
throw
;
107
}
108
};
109
110
ASEOrcaPot::~ASEOrcaPot
() {
111
QUILL_LOG_INFO(
eonc::log::get
(),
"[ASEOrca] called potential {} times"
,
112
counter
);
113
if
(!
workDir
.empty()) {
114
std::error_code ec;
115
std::filesystem::remove_all(
workDir
, ec);
116
}
117
}
118
119
void
ASEOrcaPot::force
(
long
nAtoms,
const
double
*R,
const
int
*atomicNrs,
120
double
*F,
double
*U,
double
*variance,
121
const
double
*box) {
122
variance =
nullptr
;
123
try
{
124
AtomMatrix
positions = AtomMatrix::Map(
const_cast<
double
*
>
(R), nAtoms, 3);
125
RotationMatrix
boxx = RotationMatrix::Map(
const_cast<
double
*
>
(box), 3, 3);
126
Eigen::VectorXi atmnmrs =
127
Eigen::Map<Eigen::VectorXi>(
const_cast<
int
*
>
(atomicNrs), nAtoms);
128
py::object atoms = this->
ase
.attr(
"Atoms"
)(
129
"symbols"
_a = atmnmrs,
"positions"
_a = positions,
"cell"
_a = boxx);
130
atoms.attr(
"set_calculator"
)(this->
calc
);
131
atoms.attr(
"set_pbc"
)(std::tuple<bool, bool, bool>(
true
,
true
,
true
));
132
double
py_e = py::cast<double>(atoms.attr(
"get_potential_energy"
)());
133
Eigen::MatrixXd py_force =
134
py::cast<Eigen::MatrixXd>(atoms.attr(
"get_forces"
)());
135
136
// Populate the output parameters
137
*U = py_e;
138
for
(
long
i = 0; i < nAtoms; ++i) {
139
F[3 * i] = py_force(i, 0);
140
F[3 * i + 1] = py_force(i, 1);
141
F[3 * i + 2] = py_force(i, 2);
142
}
143
}
catch
(py::error_already_set &e) {
144
throw
std::runtime_error(std::string(
"ASE-ORCA Python error: "
) + e.what());
145
}
catch
(
const
std::exception &e) {
146
throw
std::runtime_error(std::string(
"ASE-ORCA C++ exception: "
) +
147
e.what());
148
}
149
150
counter
++;
151
return
;
152
}
ASE_ORCA.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
ASEOrcaPot::force
void force(long nAtoms, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box) override
Definition
ASE_ORCA.cpp:119
ASEOrcaPot::~ASEOrcaPot
virtual ~ASEOrcaPot()
Definition
ASE_ORCA.cpp:110
ASEOrcaPot::ASEOrcaPot
ASEOrcaPot(const Parameters &a_params)
Definition
ASE_ORCA.cpp:61
ASEOrcaPot::ase
py::object ase
Definition
ASE_ORCA.h:30
ASEOrcaPot::counter
size_t counter
Definition
ASE_ORCA.h:32
ASEOrcaPot::calc
py::object calc
Definition
ASE_ORCA.h:29
ASEOrcaPot::workDir
std::filesystem::path workDir
Definition
ASE_ORCA.h:31
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_orca_options
struct eonc::Parameters::ase_orca_options_t ase_orca_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_orca_options_t::simpleinput
std::string simpleinput
Definition
Parameters.h:360
eonc::Parameters::ase_orca_options_t::nproc
std::string nproc
Definition
Parameters.h:359
eonc::Parameters::ase_orca_options_t::path
std::string path
Definition
Parameters.h:358
client
potentials
ASE_ORCA
ASE_ORCA.cpp
Generated by
1.17.0
Generated by
Doxygen 1.17.0
Analytics by
Antics
provided by
TurtleTech ehf