eOn client
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/potentials/ExternalCommand.h
"
15
16
#include <cstddef>
17
#include <cstring>
18
#include <format>
19
#include <fstream>
20
#include <iostream>
21
#include <iterator>
22
#include <stdexcept>
23
#include <string>
24
#ifndef _WIN32
25
#include <sys/stat.h>
26
#include <unistd.h>
27
#endif
28
29
namespace
{
30
31
// The driver script and its output, both relative to the working directory.
32
constexpr
const
char
*kRunScript =
"run_AMS_IO.sh"
;
33
constexpr
const
char
*kOutputFile =
"ams_output"
;
34
// Truncating rather than appending keeps the previous call's block out of the
35
// parse, so a failed run cannot hand back stale forces.
36
constexpr
const
char
*kRunCommand =
"./run_AMS_IO.sh > ams_output"
;
37
38
// Lines that precede the two blocks of interest in the AMS output.
39
constexpr
const
char
*kEnergyMarker =
" CALCULATION RESULTS"
;
40
constexpr
const
char
*kGradientMarker =
41
" Index Atom d/dx d/dy d/dz"
;
42
43
constexpr
double
kHartreeToEv = 27.2114;
44
constexpr
double
kHartreeBohrToEvAngstrom = 51.4220862;
45
46
}
// namespace
47
48
AMS_IO::AMS_IO
(
const
Parameters
&p)
49
:
Potential
(
PotType
::
AMS_IO
, p) {
50
engine
= p.
ams_options
.
engine
;
51
forcefield
= p.
ams_options
.
forcefield
;
52
model
= p.
ams_options
.
model
;
53
xc
= p.
ams_options
.
xc
;
54
return
;
55
}
56
57
void
AMS_IO::cleanMemory
(
void
) {
return
; }
58
59
AMS_IO::~AMS_IO
() {
cleanMemory
(); }
60
61
namespace
{
62
63
const
char
*elementArray[] = {
64
"Unknown"
,
"H"
,
"He"
,
"Li"
,
"Be"
,
"B"
,
"C"
,
"N"
,
"O"
,
"F"
,
"Ne"
,
"Na"
,
65
"Mg"
,
"Al"
,
"Si"
,
"P"
,
"S"
,
"Cl"
,
"Ar"
,
"K"
,
"Ca"
,
"Sc"
,
"Ti"
,
"V"
,
66
"Cr"
,
"Mn"
,
"Fe"
,
"Co"
,
"Ni"
,
"Cu"
,
"Zn"
,
"Ga"
,
"Ge"
,
"As"
,
"Se"
,
"Br"
,
67
"Kr"
,
"Rb"
,
"Sr"
,
"Y"
,
"Zr"
,
"Nb"
,
"Mo"
,
"Tc"
,
"Ru"
,
"Rh"
,
"Pd"
,
"Ag"
,
68
"Cd"
,
"In"
,
"Sn"
,
"Sb"
,
"Te"
,
"I"
,
"Xe"
,
"Cs"
,
"Ba"
,
"La"
,
"Ce"
,
"Pr"
,
69
"Nd"
,
"Pm"
,
"Sm"
,
"Eu"
,
"Gd"
,
"Tb"
,
"Dy"
,
"Ho"
,
"Er"
,
"Tm"
,
"Yb"
,
"Lu"
,
70
"Hf"
,
"Ta"
,
"W"
,
"Re"
,
"Os"
,
"Ir"
,
"Pt"
,
"Au"
,
"Hg"
,
"Tl"
,
"Pb"
,
"Bi"
,
71
"Po"
,
"At"
,
"Rn"
,
"Fr"
,
"Ra"
,
"Ac"
,
"Th"
,
"Pa"
,
"U"
, NULL};
72
73
// guess the atom type from the atomic mass,
74
std::string mass2atom(
double
atomicmass) {
75
return
elementArray[int(atomicmass + .5)];
76
}
77
78
int
symbol2atomicNumber(
char
const
*symbol) {
79
int
i = 0;
80
81
while
(elementArray[i] != NULL) {
82
if
(strcmp(symbol, elementArray[i]) == 0) {
83
return
i;
84
}
85
i++;
86
}
87
// invalid symbol
88
return
-1;
89
}
90
91
char
const
*atomicNumber2symbol(
int
n) {
92
// The trailing NULL terminates the table, so it bounds the valid range.
93
if
(n < 0 ||
static_cast<
std::size_t
>
(n) + 1 >= std::size(elementArray)) {
94
throw
std::runtime_error(
95
std::format(
"AMS_IO knows no element symbol for atomic number {}"
, n));
96
}
97
return
elementArray[n];
98
}
99
}
// namespace
100
101
void
AMS_IO::force
(
long
N,
const
double
*R,
const
int
*atomicNrs,
double
*F,
102
double
*U,
double
*variance,
const
double
*box) {
103
variance =
nullptr
;
104
passToSystem
(N, R, atomicNrs, box);
105
// Run a single point AMS_IO calculation and write the results into
106
// ams_output
107
eonc::pot::runOrThrow
(kRunCommand);
108
recieveFromSystem
(N, F, U);
109
return
;
110
}
111
112
void
AMS_IO::passToSystem
(
long
N,
const
double
*R,
const
int
*atomicNrs,
113
const
double
*box)
114
// Creating the standard input file that will be read by the AMS_IO driver
115
{
116
std::ofstream out(kRunScript, std::ios::trunc);
117
if
(!out) {
118
throw
std::runtime_error(
119
std::format(
"Could not open {} for writing"
, kRunScript));
120
}
121
122
out <<
"#!/bin/sh\n"
;
123
out <<
"ams --delete-old-results <<eor\n"
;
124
out <<
"Task SinglePoint\n"
;
125
out <<
"System\n"
;
126
out <<
" Atoms\n"
;
127
for
(
long
i = 0; i < N; i++) {
128
out << std::format(
" {}\t{:.19f}\t{:.19f}\t{:.19f}\n"
,
129
atomicNumber2symbol(atomicNrs[i]), R[i * 3 + 0],
130
R[i * 3 + 1], R[i * 3 + 2]);
131
}
132
out <<
" End\n"
;
133
if
(!
model
.empty() || !
forcefield
.empty()) {
134
out <<
" Lattice\n"
;
135
for
(
int
i = 0; i < 3; i++) {
136
out << std::format(
" {:.19f}\t{:.19f}\t{:.19f}\n"
, box[i * 3 + 0],
137
box[i * 3 + 1], box[i * 3 + 2]);
138
}
139
out <<
" End\n"
;
140
}
141
out <<
"End\n"
;
142
out << std::format(
"Engine {}\n"
,
engine
);
143
if
(!
forcefield
.empty()) {
144
out << std::format(
" Forcefield {}\n"
,
forcefield
);
145
}
146
if
(!
model
.empty()) {
147
out << std::format(
" Model {}\n"
,
model
);
148
}
149
if
(!
xc
.empty()) {
150
out << std::format(
"xc {}\n"
,
xc
);
151
// basis set not specified (default = DZ)
152
out << std::format(
" hybrid {}\n"
,
xc
);
153
out <<
"end\n"
;
154
}
155
out <<
"EndEngine\n"
;
156
out <<
"Properties\n"
;
157
out <<
" Gradients\n"
;
158
out <<
"End\n"
;
159
out <<
"eor"
;
160
161
out.close();
162
if
(!out) {
163
throw
std::runtime_error(
164
std::format(
"Could not write the AMS input to {}"
, kRunScript));
165
}
166
167
#ifndef _WIN32
168
if
(chmod(kRunScript, S_IRWXU) != 0) {
169
throw
std::runtime_error(
170
std::format(
"Could not make {} executable"
, kRunScript));
171
}
172
#endif
173
return
;
174
}
175
176
void
AMS_IO::recieveFromSystem
(
long
N,
double
*F,
double
*U) {
177
std::ifstream in(kOutputFile);
178
if
(!in) {
179
throw
std::runtime_error(
180
std::format(
"Could not open {}; AMS left no output"
, kOutputFile));
181
}
182
183
bool
haveEnergy =
false
;
184
bool
haveGradients =
false
;
185
std::string line;
186
187
while
(std::getline(in, line)) {
188
189
if
(line == kEnergyMarker) {
// Finding the Energy in the output file
190
std::string junk;
191
if
(!(in >> junk >> junk >> junk >> *U)) {
192
throw
std::runtime_error(
193
std::format(
"Could not read the energy following \"{}\" in {}"
,
194
kEnergyMarker, kOutputFile));
195
}
196
*U = *U * kHartreeToEv;
// Energy in hartree to eV
197
haveEnergy =
true
;
198
}
199
200
if
(line == kGradientMarker) {
// Finding the forces
201
double
index;
202
std::string symbol;
203
for
(
long
i = 0; i < N; i++) {
204
if
(!(in >> index >> symbol >> F[i * 3 + 0] >> F[i * 3 + 1] >>
205
F[i * 3 + 2])) {
206
throw
std::runtime_error(
207
std::format(
"{} holds gradients for {} atoms, expected {}"
,
208
kOutputFile, i, N));
209
}
210
// AMS_IO gives gradients, not forces, hence the change.
211
F[i * 3 + 0] = -F[i * 3 + 0];
212
F[i * 3 + 1] = -F[i * 3 + 1];
213
F[i * 3 + 2] = -F[i * 3 + 2];
214
}
215
haveGradients =
true
;
216
}
217
}
218
219
if
(!haveEnergy || !haveGradients) {
220
throw
std::runtime_error(std::format(
221
"{} holds no {}"
, kOutputFile,
222
!haveEnergy
223
? (!haveGradients ?
"energy and no gradient block"
:
"energy"
)
224
:
"gradient block"
));
225
}
226
227
for
(
long
i = 0; i < 3 * N; i++) {
228
F[i] = F[i] * kHartreeBohrToEvAngstrom;
// Forces from hartree/bohr to
229
// eV/Angstrom
230
}
231
return
;
232
}
AMS_IO.h
ExternalCommand.h
AMS_IO::~AMS_IO
~AMS_IO()
Definition
AMS_IO.cpp:59
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 Parameters &p)
Definition
AMS_IO.cpp:48
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:101
AMS_IO::recieveFromSystem
void recieveFromSystem(long N, double *F, double *U)
Definition
AMS_IO.cpp:176
AMS_IO::cleanMemory
void cleanMemory(void)
Definition
AMS_IO.cpp:57
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:112
eonc::Parameters
Definition
Parameters.h:28
eonc::Parameters::ams_options
struct eonc::Parameters::ams_options_t ams_options
eonc::Potential::Potential
Potential(PotType a_ptype)
Definition
Potential.h:35
eonc::pot::runOrThrow
void runOrThrow(const std::string &command)
Run a shell command, throwing when it does not succeed.
Definition
ExternalCommand.h:56
eonc::PotType
PotType
Definition
BaseStructures.h:36
eonc::Parameters::ams_options_t::forcefield
std::string forcefield
Definition
Parameters.h:85
eonc::Parameters::ams_options_t::engine
std::string engine
Definition
Parameters.h:84
eonc::Parameters::ams_options_t::xc
std::string xc
Definition
Parameters.h:88
eonc::Parameters::ams_options_t::model
std::string model
Definition
Parameters.h:86
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