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

# User Rev Content
1 chrisfen 2420 /*
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 chrisfen 2903
75 chrisfen 2420 #ifdef IS_MPI
76 chrisfen 2903
77     if (worldRank == 0) {
78 chrisfen 2420 #endif
79 chrisfen 2903
80 chrisfen 2420 inFile_ = new std::ifstream(filename_.c_str());
81 chrisfen 2903
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 chrisfen 2420 #ifdef IS_MPI
91 chrisfen 2903
92     }
93    
94     strcpy(checkPointMsg, "Dump file opened for reading successfully.");
95     MPIcheckPoint();
96    
97 chrisfen 2420 #endif
98 chrisfen 2903
99     return;
100     }
101    
102 chrisfen 2420 DumpReader::~DumpReader() {
103 chrisfen 2903
104 chrisfen 2420 #ifdef IS_MPI
105 chrisfen 2903
106 chrisfen 2420 if (worldRank == 0) {
107     #endif
108 chrisfen 2903
109 chrisfen 2420 delete inFile_;
110 chrisfen 2903
111 chrisfen 2420 #ifdef IS_MPI
112 chrisfen 2903
113 chrisfen 2420 }
114 chrisfen 2903
115 chrisfen 2420 strcpy(checkPointMsg, "Dump file closed successfully.");
116     MPIcheckPoint();
117 chrisfen 2903
118 chrisfen 2420 #endif
119 chrisfen 2903
120 chrisfen 2420 return;
121     }
122 chrisfen 2903
123 chrisfen 2420 int DumpReader::getNFrames(void) {
124    
125     if (!isScanned_)
126     scanFile();
127    
128     return nframes_;
129     }
130    
131     void DumpReader::scanFile(void) {
132 tim 2982 int lineNo = 0;
133     std::streampos prevPos;
134 chrisfen 2420 std::streampos currPos;
135 tim 2982
136 chrisfen 2420 #ifdef IS_MPI
137 tim 2982
138 chrisfen 2420 if (worldRank == 0) {
139     #endif // is_mpi
140 tim 2982
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 chrisfen 2420 sprintf(painCave.errMsg,
153 tim 2982 "DumpReader:<Snapshot> is multiply nested at line %d in %s \n", lineNo,
154     filename_.c_str());
155 chrisfen 2420 painCave.isFatal = 1;
156 tim 2982 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 chrisfen 2420 simError();
169 tim 2982 }
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 chrisfen 2420 nframes_ = framePos_.size();
195 tim 2982
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 chrisfen 2420 #ifdef IS_MPI
203     }
204    
205     MPI_Bcast(&nframes_, 1, MPI_INT, 0, MPI_COMM_WORLD);
206 tim 2982
207 chrisfen 2420 #endif // is_mpi
208 tim 2982
209 chrisfen 2420 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 tim 2982 void DumpReader::readSet(int whichFrame) {
246     std::string line;
247    
248 chrisfen 2420 #ifndef IS_MPI
249 tim 2982
250 chrisfen 2420 inFile_->clear();
251     inFile_->seekg(framePos_[whichFrame]);
252 tim 2982
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 chrisfen 2420 sprintf(painCave.errMsg,
296 tim 2982 "DumpReader Error: can not find <Snapshot>\n");
297 chrisfen 2420 painCave.isFatal = 1;
298     simError();
299     }
300 tim 2982
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 chrisfen 2420 sprintf(painCave.errMsg,
311 tim 2982 "DumpReader Error: can not find </Snapshot>\n");
312 chrisfen 2420 painCave.isFatal = 1;
313     simError();
314 tim 2982 }
315    
316 chrisfen 2420 }
317    
318 tim 2982 void DumpReader::parseDumpLine(const std::string& line) {
319    
320    
321 chrisfen 2420 StringTokenizer tokenizer(line);
322     int nTokens;
323    
324     nTokens = tokenizer.countTokens();
325    
326 tim 2982 if (nTokens < 2) {
327 chrisfen 2420 sprintf(painCave.errMsg,
328 tim 2982 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
329 chrisfen 2420 painCave.isFatal = 1;
330     simError();
331     }
332 tim 2982
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 chrisfen 2420
432 tim 2982 }
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 chrisfen 2420 sprintf(painCave.errMsg,
442 tim 2982 "DumpReader Error: Missing <StuntDoubles>\n");
443 chrisfen 2420 painCave.isFatal = 1;
444 tim 2982 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 chrisfen 2420 sprintf(painCave.errMsg,
482 tim 2982 "DumpReader Error: Not enough Tokens.\n%s\n", line.c_str());
483 chrisfen 2420 painCave.isFatal = 1;
484 tim 2982 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 chrisfen 2420
532     }//end namespace oopse