votca 2024.1-dev
Loading...
Searching...
No Matches
dlpolytrajectoryreader.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2023 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18// Standard includes
19#include <cmath>
20#include <cstdlib>
21#include <filesystem>
22#include <iostream>
23
24// VOTCA includes
26#include <votca/tools/getline.h>
27
28// Local VOTCA includes
30#include "votca/csg/topology.h"
31
32// Local private VOTCA includes
34
35namespace votca {
36namespace csg {
37
38using namespace std;
39
40bool DLPOLYTrajectoryReader::Open(const string &file)
41// open the original dlpoly configuration or trajectory file
42// NOTE: allowed file naming - <name>.dlpc or <name>.dlph (convention:
43// ".dlpc"="CONFIG", ".dlph"="HISTORY")
44{
45 std::filesystem::path filepath(file.c_str());
46 string inp_name = "HISTORY";
47
48 if (!filepath.has_extension()) {
49
50 throw std::ios_base::failure(
51 "Error on opening dlpoly file '" + file +
52 "' - extension is expected, use .dlph or .dlpc");
53
54 } else if (filepath.extension() == ".dlpc") {
55
56 isConfig_ = true;
57 inp_name = "CONFIG";
58
59 } else if (filepath.extension() == ".dlph") {
60
61 isConfig_ = false;
62
63 } else {
64 throw std::ios_base::failure("Error on opening dlpoly file '" + file +
65 "' - wrong extension, use .dlph or .dlpc");
66 }
67
68 if (!filepath.has_stem()) {
69 if (filepath.parent_path().string().size() == 0) {
70 fname_ = inp_name;
71 } else {
72 fname_ = filepath.parent_path().string() + "/" + inp_name;
73 }
74 } else {
75 fname_ = file;
76 }
77
78 fl_.open(fname_);
79 if (!fl_.is_open()) {
80 throw std::ios_base::failure("Error on opening dlpoly file '" + fname_ +
81 "'");
82 }
83 return true;
84}
85
87
89 first_frame_ = true;
90 bool res = NextFrame(conf);
91 first_frame_ = false;
92 return res;
93}
94
96 static bool hasVs = false;
97 static bool hasFs = false;
98 static Index mavecs =
99 0; // number of 3d vectors per atom = keytrj in DL_POLY manuals
100 static Index mpbct = 0; // cell PBC type = imcon in DL_POLY manuals
101 static Index matoms = 0; // number of atoms/beads in a frame
102 const double scale = tools::conv::ang2nm;
103
104 static Index nerrt = 0;
105
106 string line;
107
109
110 if (first_frame_) {
111
112 tools::getline(fl_, line); // title
113
114#ifndef NDEBUG
115 cout << "Read from dlpoly file '" << fname_ << "' : '" << line
116 << "' - header" << endl;
117#endif
118
119 tools::getline(fl_, line); // 2nd header line
120
121#ifndef NDEBUG
122 cout << "Read from dlpoly file '" << fname_ << "' : '" << line
123 << "' - directives line" << endl;
124#endif
125
126 tools::Tokenizer tok(line, " \t");
127 vector<Index> fields = tok.ToVector<Index>();
128
129 if (fields.size() < 3) {
130 throw std::runtime_error("Error: too few directive switches (<3) in '" +
131 fname_ + "' header (check its 2-nd line)");
132 }
133
134 mavecs = fields[0];
135 mpbct = fields[1];
136 matoms = fields[2];
137
138 hasVs = (mavecs > 0); // 1 or 2 => in DL_POLY frame velocity vector follows
139 // coords for each atom/bead
140 hasFs = (mavecs > 1); // 2 => in DL_POLY frame force vector follows
141 // velocities for each atom/bead
142
143#ifndef NDEBUG
144 if (hasVs != conf.HasVel() || hasFs != conf.HasForce()) {
145 cout << "WARNING: N of atom vectors (keytrj) in '" << fname_
146 << "' header differs from that read with topology" << endl;
147 }
148#endif
149
150 conf.SetHasVel(hasVs);
151 conf.SetHasForce(hasFs);
152
153#ifndef NDEBUG
154 cout << "Read from dlpoly file '" << fname_ << "' : keytrj - " << mavecs
155 << ", hasV - " << conf.HasVel() << ", hasF - " << conf.HasForce()
156 << endl;
157#endif
158
159 if (matoms != conf.BeadCount()) {
160 throw std::runtime_error("Number of atoms/beads in '" + fname_ +
161 "' header differs from that read with topology");
162 }
163
164 if (mpbct == 0) {
166 } else if (mpbct == 1 || mpbct == 2) {
168 } else if (mpbct == 3) {
170 }
171
172#ifndef NDEBUG
173 cout << "Read from dlpoly file '" << fname_ << "' : pbc_type (imcon) - '"
174 << pbc_type << "'" << endl;
175
176 if (pbc_type != conf.getBoxType())
177 cout << "WARNING: PBC type in dlpoly file '" << fname_
178 << "' header differs from that read with topology" << endl;
179// throw std::runtime_error("Error: Boundary conditions in '"+ fname_+"'
180// header differs from that read with topology");
181#endif
182 } else if (isConfig_) {
183
184 return false;
185 }
186 // read normal frame
187
188 if (!isConfig_) {
189 tools::getline(fl_, line); // timestep line - only present in HISTORY, and
190 // not in CONFIG
191#ifndef NDEBUG
192 cout << "Read from dlpoly file '" << fname_ << "' : '" << line << "'"
193 << endl;
194#endif
195 }
196
197 if (!fl_.eof()) {
198 Index nstep;
199 Index natoms;
200 Index navecs;
201
202 if (isConfig_) {
203 // use the above read specs from the header, and skip the data missing in
204 // CONFIG
205
206 natoms = matoms;
207 navecs = mavecs;
208
209 conf.SetHasVel(hasVs);
210 conf.SetHasForce(hasFs);
211
212#ifndef NDEBUG
213 cout << "Read from CONFIG: traj_key - " << navecs << ", hasV - "
214 << conf.HasVel() << ", hasF - " << conf.HasForce() << endl;
215#endif
216
217 } else {
218
219 tools::Tokenizer tok(line, " \t");
220 vector<string> fields = tok.ToVector();
221
222 if (fields.size() < 6) {
223 throw std::runtime_error(
224 "Error: too few directive switches (<6) in 'timestep' record");
225 }
226
227 nstep = boost::lexical_cast<Index>(fields[1]);
228 natoms = boost::lexical_cast<Index>(fields[2]);
229 navecs = boost::lexical_cast<Index>(fields[3]);
230 Index npbct = boost::lexical_cast<Index>(fields[4]);
231 double dtime =
232 stod(fields[5]); // normally it is the 5-th column in 'timestep' line
233 double stime =
234 stod(fields[fields.size() - 1]); // normally it is the last
235 // column in 'timestep' line
236
237#ifndef NDEBUG
238 cout << "Read from dlpoly file '" << fname_ << "' : natoms = " << natoms
239 << ", levcfg = " << fields[3];
240 cout << ", dt = " << fields[5] << ", time = " << stime << endl;
241#endif
242
243 if (natoms != conf.BeadCount()) {
244 throw std::runtime_error(
245 "Error: N of atoms/beads in '" + fname_ +
246 "' header differs from that found in topology");
247 }
248 if (natoms != matoms) {
249 throw std::runtime_error(
250 "Error: N of atoms/beads in '" + fname_ +
251 "' header differs from that found in the frame");
252 }
253 if (navecs != mavecs) {
254 throw std::runtime_error(
255 "Error: N of atom vectors (keytrj) in '" + fname_ +
256 "' header differs from that found in the frame");
257 }
258 if (npbct != mpbct) {
259 throw std::runtime_error(
260 "Error: boundary conditions (imcon) in '" + fname_ +
261 "' header differs from that found in the frame");
262 }
263
264 // total time - calculated as product due to differences between DL_POLY
265 // versions in HISTORY formats
266 conf.setTime(double(nstep) * dtime);
267 conf.setStep(nstep);
268
269 if (std::abs(stime - conf.getTime()) > 1.e-8) {
270 nerrt++;
271 if (nerrt < 11) {
272 cout << "Check: nstep = " << nstep << ", dt = " << dtime
273 << ", time = " << stime << " (correct?)" << endl;
274 } else if (nerrt == 11) {
275 cout << "Check: timestep - more than 10 mismatches in total time "
276 "found..."
277 << endl;
278 }
279 }
280
281 if (npbct == 0) {
283 } else if (npbct == 1 || npbct == 2) {
285 } else if (npbct == 3) {
287 }
288 }
289
290 Eigen::Matrix3d box = Eigen::Matrix3d::Zero();
291 for (Index i = 0; i < 3; i++) { // read 3 box/cell lines
292
293 tools::getline(fl_, line);
294
295#ifndef NDEBUG
296 cout << "Read from dlpoly file '" << fname_ << "' : '" << line
297 << "' - box vector # " << i + 1 << endl;
298#endif
299
300 if (fl_.eof()) {
301 throw std::runtime_error("Error: unexpected EOF in dlpoly file '" +
302 fname_ + "', when reading box vector" +
303 boost::lexical_cast<string>(i));
304 }
305
306 tools::Tokenizer tok(line, " \t");
307 vector<double> fields = tok.ToVector<double>();
308 // Angs -> nm
309 box.col(i) = scale * Eigen::Vector3d(fields[0], fields[1], fields[2]);
310 }
311
312 conf.setBox(box, pbc_type);
313
314 for (Index i = 0; i < natoms; i++) {
315
316 {
317 tools::getline(fl_, line); // atom header line
318
319#ifndef NDEBUG
320 cout << "Read from dlpoly file '" << fname_ << "' : '" << line << "'"
321 << endl;
322#endif
323
324 if (fl_.eof()) {
325 throw std::runtime_error("Error: unexpected EOF in dlpoly file '" +
326 fname_ + "', when reading atom/bead # " +
327 boost::lexical_cast<string>(i + 1));
328 }
329
330 tools::Tokenizer tok(line, " \t");
331 vector<string> fields = tok.ToVector();
332 Index id = boost::lexical_cast<Index>(fields[1]);
333 if (i + 1 != id) {
334 throw std::runtime_error(
335 "Error: unexpected atom/bead index in dlpoly file '" + fname_ +
336 "' : expected " + boost::lexical_cast<string>(i + 1) +
337 " but got " + boost::lexical_cast<string>(id));
338 }
339 }
340
341 Bead *b = conf.getBead(i);
342 Eigen::Matrix3d atom_vecs = Eigen::Matrix3d::Zero();
343 for (Index j = 0; j < std::min(navecs, Index(2)) + 1; j++) {
344
345 tools::getline(fl_, line); // read atom positions
346
347#ifndef NDEBUG
348 cout << "Read from dlpoly file '" << fname_ << "' : '" << line << "'"
349 << endl;
350#endif
351
352 if (fl_.eof()) {
353 throw std::runtime_error(
354 "Error: unexpected EOF in dlpoly file '" + fname_ +
355 "', when reading atom/bead vector # " +
356 boost::lexical_cast<string>(j) + " of atom " +
357 boost::lexical_cast<string>(i + 1));
358 }
359
360 tools::Tokenizer tok(line, " \t");
361 vector<double> fields = tok.ToVector<double>();
362 // Angs -> nm
363 atom_vecs.col(j) =
364 scale * Eigen::Vector3d(fields[0], fields[1], fields[2]);
365 }
366
367 b->setPos(atom_vecs.col(0));
368#ifndef NDEBUG
369 cout << "Crds from dlpoly file '" << fname_ << "' : " << atom_vecs.col(0)
370 << endl;
371#endif
372 if (navecs > 0) {
373 b->setVel(atom_vecs.col(1));
374#ifndef NDEBUG
375 cout << "Vels from dlpoly file '" << fname_
376 << "' : " << atom_vecs.col(1) << endl;
377#endif
378 if (navecs > 1) {
379 b->setF(atom_vecs.col(2));
380#ifndef NDEBUG
381 cout << "Frcs from dlpoly file '" << fname_
382 << "' : " << atom_vecs.col(2) << endl;
383#endif
384 }
385 }
386 }
387 }
388
389 return !fl_.eof();
390}
391
392} // namespace csg
393} // namespace votca
virtual void setPos(const Eigen::Vector3d &bead_position)
Definition basebead.h:161
information about a bead
Definition bead.h:50
void setF(const Eigen::Vector3d &bead_force)
Definition bead.h:356
void setVel(const Eigen::Vector3d &r)
Definition bead.h:315
void Close() override
close original trajectory file
bool FirstFrame(Topology &conf) override
read in the first frame
bool Open(const std::string &file) override
open original trajectory file
bool NextFrame(Topology &conf) override
read in the next frame
topology of the whole system
Definition topology.h:81
double getTime() const
Definition topology.h:317
BoundaryCondition::eBoxtype getBoxType() const
Definition topology.h:394
void setBox(const Eigen::Matrix3d &box, BoundaryCondition::eBoxtype boxtype=BoundaryCondition::typeAuto)
Definition topology.h:272
void setTime(double t)
Definition topology.h:311
void SetHasVel(const bool v)
Definition topology.h:400
void SetHasForce(const bool v)
Definition topology.h:403
Index BeadCount() const
Definition topology.h:150
Bead * getBead(const Index i)
Returns a pointer to the bead with index i.
Definition topology.h:227
void setStep(Index s)
Definition topology.h:323
break string into words
Definition tokenizer.h:72
std::vector< T > ToVector()
store all words in a vector of type T, does type conversion.
Definition tokenizer.h:109
STL namespace.
const double ang2nm
Definition constants.h:51
std::istream & getline(std::istream &is, std::string &str)
Wrapper for a getline function.
Definition getline.h:35
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26