ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/io/DumpReader.cpp
Revision: 2982
Committed: Wed Aug 30 18:42:29 2006 UTC (17 years, 10 months ago) by tim
File size: 15818 byte(s)
Log Message:
Massive changes preparing for release of OOPSE-4: The main difference
is that the new MD file format (.md, .dump, .eor) now contains meta-data
information along with the configuration information.

File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 #define _LARGEFILE_SOURCE64
43 #define _FILE_OFFSET_BITS 64
44
45 #include <sys/types.h>
46 #include <sys/stat.h>
47
48 #include <iostream>
49 #include <math.h>
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #include "io/DumpReader.hpp"
56 #include "primitives/Molecule.hpp"
57 #include "utils/simError.h"
58 #include "utils/MemoryUtils.hpp"
59 #include "utils/StringTokenizer.hpp"
60
61 #ifdef IS_MPI
62
63 #include <mpi.h>
64 #define TAKE_THIS_TAG_CHAR 0
65 #define TAKE_THIS_TAG_INT 1
66
67 #endif // is_mpi
68
69
70 namespace oopse {
71
72 DumpReader::DumpReader(SimInfo* info, const std::string& filename)
73 : info_(info), filename_(filename), isScanned_(false), nframes_(0) {
74
75 #ifdef IS_MPI
76
77 if (worldRank == 0) {
78 #endif
79
80 inFile_ = new std::ifstream(filename_.c_str());
81
82 if (inFile_->fail()) {
83 sprintf(painCave.errMsg,
84 "DumpReader: Cannot open file: %s\n",
85 filename_.c_str());
86 painCave.isFatal = 1;
87 simError();
88 }
89
90 #ifdef IS_MPI
91
92 }
93
94 strcpy(checkPointMsg, "Dump file opened for reading successfully.");
95 MPIcheckPoint();
96
97 #endif
98
99 return;
100 }
101
102 DumpReader::~DumpReader() {
103
104 #ifdef IS_MPI
105
106 if (worldRank == 0) {
107 #endif
108
109 delete inFile_;
110
111 #ifdef IS_MPI
112
113 }
114
115 strcpy(checkPointMsg, "Dump file closed successfully.");
116 MPIcheckPoint();
117
118 #endif
119
120 return;
121 }
122
123 int DumpReader::getNFrames(void) {
124
125 if (!isScanned_)
126 scanFile();
127
128 return nframes_;
129 }
130
131 void DumpReader::scanFile(void) {
132 int lineNo = 0;
133 std::streampos prevPos;
134 std::streampos currPos;
135
136 #ifdef IS_MPI
137
138 if (worldRank == 0) {
139 #endif // is_mpi
140
141 currPos = inFile_->tellg();
142 prevPos = currPos;
143 bool foundOpenSnapshotTag = false;
144 bool foundClosedSnapshotTag = false;
145 while(inFile_->getline(buffer, bufferSize)) {
146 ++lineNo;
147
148 std::string line = buffer;
149 currPos = inFile_->tellg();
150 if (line.find("<Snapshot>")!= std::string::npos) {
151 if (foundOpenSnapshotTag) {
152 sprintf(painCave.errMsg,
153 "DumpReader:<Snapshot> is multiply nested at line %d in %s \n", lineNo,
154 filename_.c_str());
155 painCave.isFatal = 1;
156 simError();
157 }
158 foundOpenSnapshotTag = true;
159 foundClosedSnapshotTag = false;
160 framePos_.push_back(prevPos);
161
162 } else if (line.find("</Snapshot>") != std::string::npos){
163 if (!foundOpenSnapshotTag) {
164 sprintf(painCave.errMsg,
165 "DumpReader:</Snapshot> appears before <Snapshot> at line %d in %s \n", lineNo,
166 filename_.c_str());
167 painCave.isFatal = 1;
168 simError();
169 }
170
171 if (foundClosedSnapshotTag) {
172 sprintf(painCave.errMsg,
173 "DumpReader:</Snapshot> appears multiply nested at line %d in %s \n", lineNo,
174 filename_.c_str());
175 painCave.isFatal = 1;
176 simError();
177 }
178 foundClosedSnapshotTag = true;
179 foundOpenSnapshotTag = false;
180 }
181 prevPos = currPos;
182 }
183
184 // only found <Snapshot> for the last frame means the file is corrupted, we should discard
185 // it and give a warning message
186 if (foundOpenSnapshotTag) {
187 sprintf(painCave.errMsg,
188 "DumpReader: last frame in %s is invalid\n", filename_.c_str());
189 painCave.isFatal = 0;
190 simError();
191 framePos_.pop_back();
192 }
193
194 nframes_ = framePos_.size();
195
196 if (nframes_ == 0) {
197 sprintf(painCave.errMsg,
198 "DumpReader: %s does not contain a valid frame\n", filename_.c_str());
199 painCave.isFatal = 1;
200 simError();
201 }
202 #ifdef IS_MPI
203 }
204
205 MPI_Bcast(&nframes_, 1, MPI_INT, 0, MPI_COMM_WORLD);
206
207 #endif // is_mpi
208
209 isScanned_ = true;
210 }
211
212 void DumpReader::readFrame(int whichFrame) {
213 if (!isScanned_)
214 scanFile();
215
216 int storageLayout = info_->getSnapshotManager()->getStorageLayout();
217
218 if (storageLayout & DataStorage::dslPosition) {
219 needPos_ = true;
220 } else {
221 needPos_ = false;
222 }
223
224 if (storageLayout & DataStorage::dslVelocity) {
225 needVel_ = true;
226 } else {
227 needVel_ = false;
228 }
229
230 if (storageLayout & DataStorage::dslAmat || storageLayout & DataStorage::dslElectroFrame) {
231 needQuaternion_ = true;
232 } else {
233 needQuaternion_ = false;
234 }
235
236 if (storageLayout & DataStorage::dslAngularMomentum) {
237 needAngMom_ = true;
238 } else {
239 needAngMom_ = false;
240 }
241
242 readSet(whichFrame);
243 }
244
245 void DumpReader::readSet(int whichFrame) {
246 std::string line;
247
248 #ifndef IS_MPI
249
250 inFile_->clear();
251 inFile_->seekg(framePos_[whichFrame]);
252
253 std::istream& inputStream = *inFile_;
254
255 #else
256 int masterNode = 0;
257 std::stringstream sstream;
258 if (worldRank == masterNode) {
259 std::string sendBuffer;
260
261 inFile_->clear();
262 inFile_->seekg(framePos_[whichFrame]);
263
264 while (inFile_->getline(buffer, bufferSize)) {
265
266 line = buffer;
267 sendBuffer += line;
268 sendBuffer += '\n';
269 if (line.find("</Snapshot>") != std::string::npos) {
270 break;
271 }
272 }
273
274 int sendBufferSize = sendBuffer.size();
275 MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
276 MPI_Bcast((void *)sendBuffer.c_str(), sendBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
277
278 sstream.str(sendBuffer);
279 std::cerr << sendBuffer;
280 } else {
281 int sendBufferSize;
282 MPI_Bcast(&sendBufferSize, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
283 char * recvBuffer = new char[sendBufferSize+1];
284 MPI_Bcast(recvBuffer, sendBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
285 sstream.str(recvBuffer);
286 }
287
288 std::istream& inputStream = sstream;
289 #endif
290
291 inputStream.getline(buffer, bufferSize);
292
293 line = buffer;
294 if (line.find("<Snapshot>") == std::string::npos) {
295 sprintf(painCave.errMsg,
296 "DumpReader Error: can not find <Snapshot>\n");
297 painCave.isFatal = 1;
298 simError();
299 }
300
301 //read frameData
302 readFrameProperties(inputStream);
303
304 //read StuntDoubles
305 readStuntDoubles(inputStream);
306
307 inputStream.getline(buffer, bufferSize);
308 line = buffer;
309 if (line.find("</Snapshot>") == std::string::npos) {
310 sprintf(painCave.errMsg,
311 "DumpReader Error: can not find </Snapshot>\n");
312 painCave.isFatal = 1;
313 simError();
314 }
315
316 }
317
318 void DumpReader::parseDumpLine(const std::string& line) {
319
320
321 StringTokenizer tokenizer(line);
322 int nTokens;
323
324 nTokens = tokenizer.countTokens();
325
326 if (nTokens < 2) {
327 sprintf(painCave.errMsg,
328 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
329 painCave.isFatal = 1;
330 simError();
331 }
332
333 int index = tokenizer.nextTokenAsInt();
334
335 StuntDouble* integrableObject = info_->getIOIndexToIntegrableObject(index);
336
337 if (integrableObject == NULL) {
338 return;
339 }
340 std::string type = tokenizer.nextToken();
341 int size = type.size();
342 for(int i = 0; i < size; ++i) {
343 switch(type[i]) {
344
345 case 'p': {
346 Vector3d pos;
347 pos[0] = tokenizer.nextTokenAsDouble();
348 pos[1] = tokenizer.nextTokenAsDouble();
349 pos[2] = tokenizer.nextTokenAsDouble();
350 if (needPos_) {
351 integrableObject->setPos(pos);
352 }
353 break;
354 }
355 case 'v' : {
356 Vector3d vel;
357 vel[0] = tokenizer.nextTokenAsDouble();
358 vel[1] = tokenizer.nextTokenAsDouble();
359 vel[2] = tokenizer.nextTokenAsDouble();
360 if (needVel_) {
361 integrableObject->setVel(vel);
362 }
363 break;
364 }
365
366 case 'q' : {
367 Quat4d q;
368 if (integrableObject->isDirectional()) {
369
370 q[0] = tokenizer.nextTokenAsDouble();
371 q[1] = tokenizer.nextTokenAsDouble();
372 q[2] = tokenizer.nextTokenAsDouble();
373 q[3] = tokenizer.nextTokenAsDouble();
374
375 RealType qlen = q.length();
376 if (qlen < oopse::epsilon) { //check quaternion is not equal to 0
377
378 sprintf(painCave.errMsg,
379 "DumpReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2) ~ 0\n");
380 painCave.isFatal = 1;
381 simError();
382
383 }
384
385 q.normalize();
386 if (needQuaternion_) {
387 integrableObject->setQ(q);
388 }
389 }
390 break;
391 }
392 case 'j' : {
393 Vector3d ji;
394 if (integrableObject->isDirectional()) {
395 ji[0] = tokenizer.nextTokenAsDouble();
396 ji[1] = tokenizer.nextTokenAsDouble();
397 ji[2] = tokenizer.nextTokenAsDouble();
398 if (needAngMom_) {
399 integrableObject->setJ(ji);
400 }
401 }
402 }
403 case 'f': {
404
405 Vector3d force;
406 force[0] = tokenizer.nextTokenAsDouble();
407 force[1] = tokenizer.nextTokenAsDouble();
408 force[2] = tokenizer.nextTokenAsDouble();
409 integrableObject->setFrc(force);
410 break;
411 }
412 case 't' : {
413
414 Vector3d torque;
415 torque[0] = tokenizer.nextTokenAsDouble();
416 torque[1] = tokenizer.nextTokenAsDouble();
417 torque[2] = tokenizer.nextTokenAsDouble();
418 integrableObject->setTrq(torque);
419 break;
420 }
421 default: {
422 sprintf(painCave.errMsg,
423 "DumpReader Error: %s is an unrecognized type\n", type.c_str());
424 painCave.isFatal = 1;
425 simError();
426 break;
427 }
428
429 }
430 }
431
432 }
433
434
435 void DumpReader::readStuntDoubles(std::istream& inputStream) {
436
437 inputStream.getline(buffer, bufferSize);
438 std::string line(buffer);
439
440 if (line.find("<StuntDoubles>") == std::string::npos) {
441 sprintf(painCave.errMsg,
442 "DumpReader Error: Missing <StuntDoubles>\n");
443 painCave.isFatal = 1;
444 simError();
445 }
446
447 while(inputStream.getline(buffer, bufferSize)) {
448 line = buffer;
449
450 if(line.find("</StuntDoubles>") != std::string::npos) {
451 break;
452 }
453
454 parseDumpLine(line);
455 }
456
457 }
458
459 void DumpReader::readFrameProperties(std::istream& inputStream) {
460
461 Snapshot* s = info_->getSnapshotManager()->getCurrentSnapshot();
462 inputStream.getline(buffer, bufferSize);
463 std::string line(buffer);
464
465 if (line.find("<FrameData>") == std::string::npos) {
466 sprintf(painCave.errMsg,
467 "DumpReader Error: Missing <FrameData>\n");
468 painCave.isFatal = 1;
469 simError();
470 }
471
472 while(inputStream.getline(buffer, bufferSize)) {
473 line = buffer;
474
475 if(line.find("</FrameData>") != std::string::npos) {
476 break;
477 }
478
479 StringTokenizer tokenizer(line, " ;\t\n\r{}:,");
480 if (!tokenizer.hasMoreTokens()) {
481 sprintf(painCave.errMsg,
482 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
483 painCave.isFatal = 1;
484 simError();
485 }
486
487 std::string propertyName = tokenizer.nextToken();
488 if (propertyName == "Time") {
489 RealType currTime = tokenizer.nextTokenAsDouble();
490 s->setTime(currTime);
491 } else if (propertyName == "Hmat"){
492 Mat3x3d hmat;
493 hmat(0, 0) = tokenizer.nextTokenAsDouble();
494 hmat(0, 1) = tokenizer.nextTokenAsDouble();
495 hmat(0, 2) = tokenizer.nextTokenAsDouble();
496 hmat(1, 0) = tokenizer.nextTokenAsDouble();
497 hmat(1, 1) = tokenizer.nextTokenAsDouble();
498 hmat(1, 2) = tokenizer.nextTokenAsDouble();
499 hmat(2, 0) = tokenizer.nextTokenAsDouble();
500 hmat(2, 1) = tokenizer.nextTokenAsDouble();
501 hmat(2, 2) = tokenizer.nextTokenAsDouble();
502 s->setHmat(hmat);
503 } else if (propertyName == "Thermostat") {
504 RealType chi = tokenizer.nextTokenAsDouble();
505 RealType integralOfChiDt = tokenizer.nextTokenAsDouble();
506 s->setChi(chi);
507 s->setIntegralOfChiDt(integralOfChiDt);
508 } else if (propertyName == "Barostat") {
509 Mat3x3d eta;
510 eta(0, 0) = tokenizer.nextTokenAsDouble();
511 eta(0, 1) = tokenizer.nextTokenAsDouble();
512 eta(0, 2) = tokenizer.nextTokenAsDouble();
513 eta(1, 0) = tokenizer.nextTokenAsDouble();
514 eta(1, 1) = tokenizer.nextTokenAsDouble();
515 eta(1, 2) = tokenizer.nextTokenAsDouble();
516 eta(2, 0) = tokenizer.nextTokenAsDouble();
517 eta(2, 1) = tokenizer.nextTokenAsDouble();
518 eta(2, 2) = tokenizer.nextTokenAsDouble();
519 s->setEta(eta);
520 } else {
521 sprintf(painCave.errMsg,
522 "DumpReader Error: %s is an invalid property in <FrameData>\n", propertyName.c_str());
523 painCave.isFatal = 0;
524 simError();
525 }
526
527 }
528
529 }
530
531
532 }//end namespace oopse