24#include "io/XYZFormat.hpp"
34#include "utils/Trim.hpp"
35#include "utils/simError.h"
39 bool XYZFormat::ReadMolecule(std::istream& ifs) {
40 char buffer[BUFF_SIZE];
42 std::stringstream errorMsg;
47 if (!ifs.getline(buffer, BUFF_SIZE)) {
48 strcpy(painCave.errMsg,
49 "Problems reading an XYZ file: Cannot read the first line.\n");
54 if (sscanf(buffer,
"%d", &natoms) == 0 || !natoms) {
55 strcpy(painCave.errMsg,
"Problems reading an XYZ file: The first line "
56 "must contain the number of atoms.\n");
66 if (!ifs.getline(buffer, BUFF_SIZE)) {
67 strcpy(painCave.errMsg,
"Problems reading an XYZ file: Could not read "
68 "the second line (title/comments).\n");
72 std::string readTitle(buffer);
73 std::string::size_type location = readTitle.find(
"Energy");
74 if (location != std::string::npos) readTitle.erase(location);
75 Utils::trim(readTitle);
77 location = readTitle.find_first_not_of(
" \t\n\r");
78 if (location != std::string::npos)
85 for (
unsigned int i = 1; i <= natoms; i++) {
86 if (!ifs.getline(buffer, BUFF_SIZE)) {
87 errorMsg <<
"Problems reading an XYZ file: "
88 <<
"Could not read line #" << i + 2 <<
", file error.\n"
89 <<
" According to line one, there should be " << natoms
90 <<
" atoms, and therefore " << natoms + 2
91 <<
" lines in the file.";
93 strcpy(painCave.errMsg, errorMsg.str().c_str());
95 painCave.severity = OPENMD_WARNING;
99 StringTokenizer tokenizer(buffer,
" ;,\t\n\r");
100 std::vector<std::string> vs = tokenizer.getAllTokens();
103 errorMsg <<
"Problems reading an XYZ file: "
104 <<
"Could not read line #" << i + 2 <<
".\n"
105 <<
"OpenBabel found the line '" << buffer <<
"'\n"
106 <<
"According to the specifications, this line should contain "
107 "exactly 4 entries, separated by white space.\n"
108 <<
"However, OpenBabel found " << vs.size() <<
" items.";
110 strcpy(painCave.errMsg, errorMsg.str().c_str());
111 painCave.isFatal = 0;
112 painCave.severity = OPENMD_WARNING;
125 XYZAtom* atom =
new XYZAtom();
126 mol_.push_back(atom);
130 if (atomicNum == 0) {
134 atomicNum = atoi(vs[0].c_str());
137 atom->atomicNum = atomicNum;
143 double x = strtod((
char*)vs[1].c_str(), &endptr);
144 if (endptr == (
char*)vs[1].c_str()) {
145 errorMsg <<
"Problems reading an XYZ file: "
146 <<
"Could not read line #" << i + 2 <<
".\n"
147 <<
"OpenBabel found the line '" << buffer <<
"'\n"
148 <<
"According to the specifications, this line should contain "
149 "exactly 4 entries, separated by white space.\n"
150 <<
"OpenBabel could not interpret item #1 as a number.";
152 strcpy(painCave.errMsg, errorMsg.str().c_str());
153 painCave.isFatal = 1;
156 double y = strtod((
char*)vs[2].c_str(), &endptr);
157 if (endptr == (
char*)vs[2].c_str()) {
158 errorMsg <<
"Problems reading an XYZ file: "
159 <<
"Could not read line #" << i + 2 <<
".\n"
160 <<
"OpenBabel found the line '" << buffer <<
"'\n"
161 <<
"According to the specifications, this line should contain "
162 "exactly 4 entries, separated by white space.\n"
163 <<
"OpenBabel could not interpret item #2 as a number.";
165 strcpy(painCave.errMsg, errorMsg.str().c_str());
166 painCave.isFatal = 1;
169 double z = strtod((
char*)vs[3].c_str(), &endptr);
170 if (endptr == (
char*)vs[3].c_str()) {
171 errorMsg <<
"Problems reading an XYZ file: "
172 <<
"Could not read line #" << i + 2 <<
".\n"
173 <<
"OpenBabel found the line '" << buffer <<
"'\n"
174 <<
"According to the specifications, this line should contain "
175 "exactly 4 entries, separated by white space.\n"
176 <<
"OpenBabel could not interpret item #3 as a number.";
178 strcpy(painCave.errMsg, errorMsg.str().c_str());
179 painCave.isFatal = 0;
180 painCave.severity = OPENMD_WARNING;
184 atom->pos = Vector3d(x, y, z);
188 std::string::size_type decimal = vs[4].find(
'.');
189 if (decimal != std::string::npos) {
190 double charge = strtod((
char*)vs[4].c_str(), &endptr);
191 if (endptr != (
char*)vs[4].c_str()) atom->charge = charge;
200 ifs.getline(buffer, BUFF_SIZE);
201 }
while (strlen(buffer) == 0 && !ifs.eof());
This basic Periodic Table class was originally taken from the data.h file in OpenBabel.
int GetAtomicNum(const char *str)
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.