eOn 3.2.0
Long-timescale dynamics: aKMC, NEB, parallel replica
☾
Toggle main menu visibility
Loading...
Searching...
No Matches
AMS_IO.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/AMS_IO/AMS_IO.h
"
14
#include "
eon/Parameters.h
"
15
#include "
eon/potentials/ExternalCommand.h
"
16
17
#include <cstddef>
18
#include <cstdint>
19
#include <cstring>
20
#include <format>
21
#include <fstream>
22
#include <iostream>
23
#include <iterator>
24
#include <readcon-core.hpp>
25
#include <stdexcept>
26
#include <string>
27
#ifndef _WIN32
28
#include <sys/stat.h>
29
#include <unistd.h>
30
#endif
31
32
namespace
{
33
34
// The driver script and its output, both relative to the working directory.
35
constexpr
const
char
*kRunScript =
"run_AMS_IO.sh"
;
36
constexpr
const
char
*kOutputFile =
"ams_output"
;
37
// Truncating rather than appending keeps the previous call's block out of the
38
// parse, so a failed run cannot hand back stale forces.
39
constexpr
const
char
*kRunCommand =
"./run_AMS_IO.sh > ams_output"
;
40
41
// Lines that precede the two blocks of interest in the AMS output.
42
constexpr
const
char
*kEnergyMarker =
" CALCULATION RESULTS"
;
43
constexpr
const
char
*kGradientMarker =
44
" Index Atom d/dx d/dy d/dz"
;
45
46
constexpr
double
kHartreeToEv = 27.2114;
47
constexpr
double
kHartreeBohrToEvAngstrom = 51.4220862;
48
49
}
// namespace
50
51
AMS_IO::AMS_IO
(
const
eonc::Parameters
&p)
52
:
eonc
::
Potential
(
eonc
::PotType::
AMS_IO
, p) {
53
engine
= p.
ams_options
().
engine
;
54
forcefield
= p.
ams_options
().
forcefield
;
55
model
= p.
ams_options
().
model
;
56
xc
= p.
ams_options
().
xc
;
57
return
;
58
}
59
60
void
AMS_IO::cleanMemory
(
void
) {
return
; }
61
62
AMS_IO::~AMS_IO
() {
cleanMemory
(); }
63
64
namespace
{
65
66
std::string symbol_for_z(
int
n) {
67
if
(n <= 0) {
68
throw
std::runtime_error(
69
std::format(
"AMS_IO knows no element symbol for atomic number {}"
, n));
70
}
71
return
readcon::z_to_symbol(
static_cast<
uint64_t
>
(n));
72
}
73
}
// namespace
74
75
void
AMS_IO::force
(
long
N,
const
double
*R,
const
int
*atomicNrs,
double
*F,
76
double
*U,
double
*variance,
const
double
*box) {
77
variance =
nullptr
;
78
passToSystem
(N, R, atomicNrs, box);
79
// Run a single point AMS_IO calculation and write the results into
80
// ams_output
81
eonc::pot::runOrThrow
(kRunCommand);
82
recieveFromSystem
(N, F, U);
83
return
;
84
}
85
86
void
AMS_IO::passToSystem
(
long
N,
const
double
*R,
const
int
*atomicNrs,
87
const
double
*box)
88
// Creating the standard input file that will be read by the AMS_IO driver
89
{
90
std::ofstream out(kRunScript, std::ios::trunc);
91
if
(!out) {
92
throw
std::runtime_error(
93
std::format(
"Could not open {} for writing"
, kRunScript));
94
}
95
96
out <<
"#!/bin/sh\n"
;
97
out <<
"ams --delete-old-results <<eor\n"
;
98
out <<
"Task SinglePoint\n"
;
99
out <<
"System\n"
;
100
out <<
" Atoms\n"
;
101
for
(
long
i = 0; i < N; i++) {
102
out << std::format(
" {}\t{:.19f}\t{:.19f}\t{:.19f}\n"
,
103
symbol_for_z(atomicNrs[i]), R[i * 3 + 0], R[i * 3 + 1],
104
R[i * 3 + 2]);
105
}
106
out <<
" End\n"
;
107
if
(!
model
.empty() || !
forcefield
.empty()) {
108
out <<
" Lattice\n"
;
109
for
(
int
i = 0; i < 3; i++) {
110
out << std::format(
" {:.19f}\t{:.19f}\t{:.19f}\n"
, box[i * 3 + 0],
111
box[i * 3 + 1], box[i * 3 + 2]);
112
}
113
out <<
" End\n"
;
114
}
115
out <<
"End\n"
;
116
out << std::format(
"Engine {}\n"
,
engine
);
117
if
(!
forcefield
.empty()) {
118
out << std::format(
" Forcefield {}\n"
,
forcefield
);
119
}
120
if
(!
model
.empty()) {
121
out << std::format(
" Model {}\n"
,
model
);
122
}
123
if
(!
xc
.empty()) {
124
out << std::format(
"xc {}\n"
,
xc
);
125
// basis set not specified (default = DZ)
126
out << std::format(
" hybrid {}\n"
,
xc
);
127
out <<
"end\n"
;
128
}
129
out <<
"EndEngine\n"
;
130
out <<
"Properties\n"
;
131
out <<
" Gradients\n"
;
132
out <<
"End\n"
;
133
out <<
"eor"
;
134
135
out.close();
136
if
(!out) {
137
throw
std::runtime_error(
138
std::format(
"Could not write the AMS input to {}"
, kRunScript));
139
}
140
141
#ifndef _WIN32
142
if
(chmod(kRunScript, S_IRWXU) != 0) {
143
throw
std::runtime_error(
144
std::format(
"Could not make {} executable"
, kRunScript));
145
}
146
#endif
147
return
;
148
}
149
150
void
AMS_IO::recieveFromSystem
(
long
N,
double
*F,
double
*U) {
151
std::ifstream in(kOutputFile);
152
if
(!in) {
153
throw
std::runtime_error(
154
std::format(
"Could not open {}; AMS left no output"
, kOutputFile));
155
}
156
157
bool
haveEnergy =
false
;
158
bool
haveGradients =
false
;
159
std::string line;
160
161
while
(std::getline(in, line)) {
162
163
if
(line == kEnergyMarker) {
// Finding the Energy in the output file
164
std::string junk;
165
if
(!(in >> junk >> junk >> junk >> *U)) {
166
throw
std::runtime_error(
167
std::format(
"Could not read the energy following \"{}\" in {}"
,
168
kEnergyMarker, kOutputFile));
169
}
170
*U = *U * kHartreeToEv;
// Energy in hartree to eV
171
haveEnergy =
true
;
172
}
173
174
if
(line == kGradientMarker) {
// Finding the forces
175
double
index;
176
std::string symbol;
177
for
(
long
i = 0; i < N; i++) {
178
if
(!(in >> index >> symbol >> F[i * 3 + 0] >> F[i * 3 + 1] >>
179
F[i * 3 + 2])) {
180
throw
std::runtime_error(
181
std::format(
"{} holds gradients for {} atoms, expected {}"
,
182
kOutputFile, i, N));
183
}
184
// AMS_IO gives gradients, not forces, hence the change.
185
F[i * 3 + 0] = -F[i * 3 + 0];
186
F[i * 3 + 1] = -F[i * 3 + 1];
187
F[i * 3 + 2] = -F[i * 3 + 2];
188
}
189
haveGradients =
true
;
190
}
191
}
192
193
if
(!haveEnergy || !haveGradients) {
194
throw
std::runtime_error(std::format(
195
"{} holds no {}"
, kOutputFile,
196
!haveEnergy
197
? (!haveGradients ?
"energy and no gradient block"
:
"energy"
)
198
:
"gradient block"
));
199
}
200
201
for
(
long
i = 0; i < 3 * N; i++) {
202
F[i] = F[i] * kHartreeBohrToEvAngstrom;
// Forces from hartree/bohr to
203
// eV/Angstrom
204
}
205
return
;
206
}
AMS_IO.h
ExternalCommand.h
Parameters.h
AMS_IO::~AMS_IO
~AMS_IO()
Definition
AMS_IO.cpp:62
AMS_IO::forcefield
std::string forcefield
Definition
AMS_IO.h:37
AMS_IO::model
std::string model
Definition
AMS_IO.h:36
AMS_IO::engine
std::string engine
Definition
AMS_IO.h:35
AMS_IO::AMS_IO
AMS_IO(const eonc::Parameters &p)
Definition
AMS_IO.cpp:51
AMS_IO::force
void force(long N, const double *R, const int *atomicNrs, double *F, double *U, double *variance, const double *box)
Definition
AMS_IO.cpp:75
AMS_IO::recieveFromSystem
void recieveFromSystem(long N, double *F, double *U)
Definition
AMS_IO.cpp:150
AMS_IO::cleanMemory
void cleanMemory(void)
Definition
AMS_IO.cpp:60
AMS_IO::xc
std::string xc
Definition
AMS_IO.h:38
AMS_IO::passToSystem
void passToSystem(long N, const double *R, const int *atomicNrs, const double *box)
Definition
AMS_IO.cpp:86
eonc::Parameters
Definition
Parameters.h:35
eonc::Parameters::ams_options
const ams_options_t & ams_options() const
Definition
ParametersAccess.cpp:83
eonc::Potential::Potential
Potential(PotType a_ptype)
Production default: construction-scope registry, else PotRegistry::get().
Definition
PotentialParams.cpp:29
eonc::pot::runOrThrow
void runOrThrow(const std::string &command)
Run a shell command, throwing when it does not succeed.
Definition
ExternalCommand.h:56
eonc
RAII resource manager for the ARTn C library with global synchronization.
Definition
ARTnSaddleSearch.cpp:23
client
potentials
AMS_IO
AMS_IO.cpp
Generated by
1.17.0
Generated by
Doxygen 1.17.0
Analytics by
Antics
provided by
TurtleTech ehf