ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/DumpReader.cpp
Revision: 1958
Committed: Tue Jan 25 21:59:18 2005 UTC (19 years, 5 months ago) by tim
File size: 18893 byte(s)
Log Message:
fix a bug in SimInfo, use number of cutoff stamp as counter to loop over rigidbody stamp

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_ = fopen(filename_.c_str(), "r");
81
82 if (inFile_ == NULL) {
83 sprintf(painCave.errMsg, "DumpReader: Cannot open file: %s\n", filename_.c_str());
84 painCave.isFatal = 1;
85 simError();
86 }
87
88 #ifdef IS_MPI
89
90 }
91
92 strcpy(checkPointMsg, "Dump file opened for reading successfully.");
93 MPIcheckPoint();
94
95 #endif
96
97 return;
98 }
99
100 DumpReader::~DumpReader() {
101
102 #ifdef IS_MPI
103
104 if (worldRank == 0) {
105 #endif
106
107 int error;
108 error = fclose(inFile_);
109
110 if (error) {
111 sprintf(painCave.errMsg, "DumpReader Error: Error closing %s\n", filename_.c_str());
112 painCave.isFatal = 1;
113 simError();
114 }
115
116 MemoryUtils::deleteVectorOfPointer(framePos_);
117
118 #ifdef IS_MPI
119
120 }
121
122 strcpy(checkPointMsg, "Dump file closed successfully.");
123 MPIcheckPoint();
124
125 #endif
126
127 return;
128 }
129
130 int DumpReader::getNFrames(void) {
131
132 if (!isScanned_)
133 scanFile();
134
135 return nframes_;
136 }
137
138 void DumpReader::scanFile(void) {
139 int i, j;
140 int lineNum = 0;
141 char readBuffer[maxBufferSize];
142 fpos_t * currPos;
143
144 #ifdef IS_MPI
145
146 if (worldRank == 0) {
147 #endif // is_mpi
148
149 rewind(inFile_);
150
151 currPos = new fpos_t;
152 fgetpos(inFile_, currPos);
153 fgets(readBuffer, sizeof(readBuffer), inFile_);
154 lineNum++;
155
156 if (feof(inFile_)) {
157 sprintf(painCave.errMsg,
158 "DumpReader Error: File \"%s\" ended unexpectedly at line %d\n",
159 filename_.c_str(),
160 lineNum);
161 painCave.isFatal = 1;
162 simError();
163 }
164
165 while (!feof(inFile_)) {
166 framePos_.push_back(currPos);
167
168 i = atoi(readBuffer);
169
170 fgets(readBuffer, sizeof(readBuffer), inFile_);
171 lineNum++;
172
173 if (feof(inFile_)) {
174 sprintf(painCave.errMsg,
175 "DumpReader Error: File \"%s\" ended unexpectedly at line %d\n",
176 filename_.c_str(),
177 lineNum);
178 painCave.isFatal = 1;
179 simError();
180 }
181
182 for(j = 0; j < i; j++) {
183 fgets(readBuffer, sizeof(readBuffer), inFile_);
184 lineNum++;
185
186 if (feof(inFile_)) {
187 sprintf(painCave.errMsg,
188 "DumpReader Error: File \"%s\" ended unexpectedly at line %d,"
189 " with atom %d\n", filename_.c_str(),
190 lineNum,
191 j);
192
193 painCave.isFatal = 1;
194 simError();
195 }
196 }
197
198 currPos = new fpos_t;
199 fgetpos(inFile_, currPos);
200 fgets(readBuffer, sizeof(readBuffer), inFile_);
201 lineNum++;
202 }
203
204 delete currPos;
205 rewind(inFile_);
206
207 nframes_ = framePos_.size();
208 #ifdef IS_MPI
209 }
210
211 MPI_Bcast(&nframes_, 1, MPI_INT, 0, MPI_COMM_WORLD);
212
213 strcpy(checkPointMsg, "Successfully scanned DumpFile\n");
214 MPIcheckPoint();
215
216 #endif // is_mpi
217
218 isScanned_ = true;
219 }
220
221 void DumpReader::readFrame(int whichFrame) {
222 readSet(whichFrame);
223 }
224
225 void DumpReader::readSet(int whichFrame) {
226 int i;
227 int nTotObjs; // the number of atoms
228 char read_buffer[maxBufferSize]; //the line buffer for reading
229 char * eof_test; // ptr to see when we reach the end of the file
230
231 Molecule* mol;
232 StuntDouble* integrableObject;
233 SimInfo::MoleculeIterator mi;
234 Molecule::IntegrableObjectIterator ii;
235
236 #ifndef IS_MPI
237
238 fsetpos(inFile_, framePos_[whichFrame]);
239 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
240
241 if (eof_test == NULL) {
242 sprintf(painCave.errMsg,
243 "DumpReader error: error reading 1st line of \"%s\"\n",
244 filename_.c_str());
245 painCave.isFatal = 1;
246 simError();
247 }
248
249 nTotObjs = atoi(read_buffer);
250
251 if (nTotObjs != info_->getNGlobalIntegrableObjects()) {
252 sprintf(painCave.errMsg,
253 "DumpReader error. %s nIntegrable, %d, "
254 "does not match the meta-data file's nIntegrable, %d.\n",
255 filename_.c_str(),
256 nTotObjs,
257 info_->getNGlobalIntegrableObjects());
258
259 painCave.isFatal = 1;
260 simError();
261 }
262
263 //read the box mat from the comment line
264
265 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
266
267 if (eof_test == NULL) {
268 sprintf(painCave.errMsg, "DumpReader Error: error in reading commment in %s\n",
269 filename_.c_str());
270 painCave.isFatal = 1;
271 simError();
272 }
273
274 parseCommentLine(read_buffer, info_->getSnapshotManager()->getCurrentSnapshot());
275
276 //parse dump lines
277
278 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) {
279
280 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
281 integrableObject = mol->nextIntegrableObject(ii)) {
282
283 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
284
285 if (eof_test == NULL) {
286 sprintf(painCave.errMsg,
287 "DumpReader Error: error in reading file %s\n"
288 "natoms = %d; index = %d\n"
289 "error reading the line from the file.\n",
290 filename_.c_str(),
291 nTotObjs,
292 i);
293
294 painCave.isFatal = 1;
295 simError();
296 }
297
298 parseDumpLine(read_buffer, integrableObject);
299
300 }
301 }
302
303 // MPI Section of code..........
304
305 #else //IS_MPI
306
307 // first thing first, suspend fatalities.
308 int masterNode = 0;
309 int nCurObj;
310 painCave.isEventLoop = 1;
311
312 int myStatus; // 1 = wakeup & success; 0 = error; -1 = AllDone
313 int haveError;
314
315 MPI_Status istatus;
316 int nitems;
317
318 nTotObjs = info_->getNGlobalIntegrableObjects();
319 haveError = 0;
320
321 if (worldRank == masterNode) {
322 fsetpos(inFile_, framePos_[whichFrame]);
323
324 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
325
326 if (eof_test == NULL) {
327 sprintf(painCave.errMsg, "DumpReader Error: Error reading 1st line of %s \n ",
328 filename_.c_str());
329 painCave.isFatal = 1;
330 simError();
331 }
332
333 nitems = atoi(read_buffer);
334
335 // Check to see that the number of integrable objects in the
336 // intial configuration file is the same as derived from the
337 // meta-data file.
338
339 if (nTotObjs != nitems) {
340 sprintf(painCave.errMsg,
341 "DumpReader Error. %s nIntegrable, %d, "
342 "does not match the meta-data file's nIntegrable, %d.\n",
343 filename_.c_str(),
344 nTotObjs,
345 info_->getNGlobalIntegrableObjects());
346
347 painCave.isFatal = 1;
348 simError();
349 }
350
351 //read the boxMat from the comment line
352
353 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
354
355 if (eof_test == NULL) {
356 sprintf(painCave.errMsg, "DumpReader Error: error in reading commment in %s\n",
357 filename_.c_str());
358 painCave.isFatal = 1;
359 simError();
360 }
361
362 //Every single processor will parse the comment line by itself
363 //By using this way, we might lose some efficiency, but if we want to add
364 //more parameters into comment line, we only need to modify function
365 //parseCommentLine
366
367 MPI_Bcast(read_buffer, maxBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
368 parseCommentLine(read_buffer, info_->getSnapshotManager()->getCurrentSnapshot());
369
370 for(i = 0; i < info_->getNGlobalMolecules(); i++) {
371 int which_node = info_->getMolToProc(i);
372
373 if (which_node == masterNode) {
374 //molecules belong to master node
375
376 mol = info_->getMoleculeByGlobalIndex(i);
377
378 if (mol == NULL) {
379 sprintf(painCave.errMsg, "DumpReader Error: Molecule not found on node %d!", worldRank);
380 painCave.isFatal = 1;
381 simError();
382 }
383
384 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
385 integrableObject = mol->nextIntegrableObject(ii)){
386
387 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
388
389 if (eof_test == NULL) {
390 sprintf(painCave.errMsg,
391 "DumpReader Error: error in reading file %s\n"
392 "natoms = %d; index = %d\n"
393 "error reading the line from the file.\n",
394 filename_.c_str(),
395 nTotObjs,
396 i);
397
398 painCave.isFatal = 1;
399 simError();
400 }
401
402 parseDumpLine(read_buffer, integrableObject);
403 }
404 } else {
405 //molecule belongs to slave nodes
406
407 MPI_Recv(&nCurObj, 1, MPI_INT, which_node, TAKE_THIS_TAG_INT,
408 MPI_COMM_WORLD, &istatus);
409
410 for(int j = 0; j < nCurObj; j++) {
411 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
412
413 if (eof_test == NULL) {
414 sprintf(painCave.errMsg,
415 "DumpReader Error: error in reading file %s\n"
416 "natoms = %d; index = %d\n"
417 "error reading the line from the file.\n",
418 filename_.c_str(),
419 nTotObjs,
420 i);
421
422 painCave.isFatal = 1;
423 simError();
424 }
425
426 MPI_Send(read_buffer, maxBufferSize, MPI_CHAR, which_node,
427 TAKE_THIS_TAG_CHAR, MPI_COMM_WORLD);
428 }
429 }
430 }
431 } else {
432 //actions taken at slave nodes
433 MPI_Bcast(read_buffer, maxBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
434
435 /**@todo*/
436 parseCommentLine(read_buffer, info_->getSnapshotManager()->getCurrentSnapshot());
437
438 for(i = 0; i < info_->getNGlobalMolecules(); i++) {
439 int which_node = info_->getMolToProc(i);
440
441 if (which_node == worldRank) {
442 //molecule with global index i belongs to this processor
443
444 mol = info_->getMoleculeByGlobalIndex(i);
445 if (mol == NULL) {
446 sprintf(painCave.errMsg, "DumpReader Error: Molecule not found on node %d!", worldRank);
447 painCave.isFatal = 1;
448 simError();
449 }
450
451 nCurObj = mol->getNIntegrableObjects();
452
453 MPI_Send(&nCurObj, 1, MPI_INT, masterNode, TAKE_THIS_TAG_INT,
454 MPI_COMM_WORLD);
455
456 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
457 integrableObject = mol->nextIntegrableObject(ii)){
458
459 MPI_Recv(read_buffer, maxBufferSize, MPI_CHAR, masterNode,
460 TAKE_THIS_TAG_CHAR, MPI_COMM_WORLD, &istatus);
461
462 parseDumpLine(read_buffer, integrableObject);
463 }
464
465 }
466
467 }
468
469 }
470
471 #endif
472
473 }
474
475 void DumpReader::parseDumpLine(char *line, StuntDouble *integrableObject) {
476
477 Vector3d pos; // position place holders
478 Vector3d vel; // velocity placeholders
479 Quat4d q; // the quaternions
480 Vector3d ji; // angular velocity placeholders;
481 StringTokenizer tokenizer(line);
482 int nTokens;
483
484 nTokens = tokenizer.countTokens();
485
486 if (nTokens < 14) {
487 sprintf(painCave.errMsg,
488 "DumpReader Error: Not enough Tokens.\n");
489 painCave.isFatal = 1;
490 simError();
491 }
492
493 std::string name = tokenizer.nextToken();
494
495 if (name != integrableObject->getType()) {
496
497 sprintf(painCave.errMsg,
498 "DumpReader Error: Atom type [%s] in %s does not match Atom Type [%s] in .md file.\n",
499 name.c_str(), filename_.c_str(), integrableObject->getType().c_str());
500 painCave.isFatal = 1;
501 simError();
502 }
503
504 pos[0] = tokenizer.nextTokenAsDouble();
505 pos[1] = tokenizer.nextTokenAsDouble();
506 pos[2] = tokenizer.nextTokenAsDouble();
507 integrableObject->setPos(pos);
508
509 vel[0] = tokenizer.nextTokenAsDouble();
510 vel[1] = tokenizer.nextTokenAsDouble();
511 vel[2] = tokenizer.nextTokenAsDouble();
512 integrableObject->setVel(vel);
513
514 if (integrableObject->isDirectional()) {
515
516 q[0] = tokenizer.nextTokenAsDouble();
517 q[1] = tokenizer.nextTokenAsDouble();
518 q[2] = tokenizer.nextTokenAsDouble();
519 q[3] = tokenizer.nextTokenAsDouble();
520
521 double qlen = q.length();
522 if (qlen < oopse::epsilon) { //check quaternion is not equal to 0
523
524 sprintf(painCave.errMsg,
525 "DumpReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2 ~ 0).\n");
526 painCave.isFatal = 1;
527 simError();
528
529 }
530
531 q.normalize();
532
533 integrableObject->setQ(q);
534
535 ji[0] = tokenizer.nextTokenAsDouble();
536 ji[1] = tokenizer.nextTokenAsDouble();
537 ji[2] = tokenizer.nextTokenAsDouble();
538 integrableObject->setJ(ji);
539 }
540
541 }
542
543
544 void DumpReader::parseCommentLine(char* line, Snapshot* s) {
545 double currTime;
546 Mat3x3d hmat;
547 double chi;
548 double integralOfChiDt;
549 Mat3x3d eta;
550
551 StringTokenizer tokenizer(line);
552 int nTokens;
553
554 nTokens = tokenizer.countTokens();
555
556 //comment line should at least contain 10 tokens: current time(1 token) and h-matrix(9 tokens)
557 if (nTokens < 10) {
558 sprintf(painCave.errMsg,
559 "DumpReader Error: Not enough tokens in comment line: %s", line);
560 painCave.isFatal = 1;
561 simError();
562 }
563
564 //read current time
565 currTime = tokenizer.nextTokenAsDouble();
566 s->setTime(currTime);
567
568 //read h-matrix
569 hmat(0, 0) = tokenizer.nextTokenAsDouble();
570 hmat(0, 1) = tokenizer.nextTokenAsDouble();
571 hmat(0, 2) = tokenizer.nextTokenAsDouble();
572 hmat(1, 0) = tokenizer.nextTokenAsDouble();
573 hmat(1, 1) = tokenizer.nextTokenAsDouble();
574 hmat(1, 2) = tokenizer.nextTokenAsDouble();
575 hmat(2, 0) = tokenizer.nextTokenAsDouble();
576 hmat(2, 1) = tokenizer.nextTokenAsDouble();
577 hmat(2, 2) = tokenizer.nextTokenAsDouble();
578 s->setHmat(hmat);
579
580 //read chi and integrablOfChidt, they should apprear in pair
581 if (tokenizer.countTokens() >= 2) {
582 chi = tokenizer.nextTokenAsDouble();
583 integralOfChiDt = tokenizer.nextTokenAsDouble();
584
585 s->setChi(chi);
586 s->setIntegralOfChiDt(integralOfChiDt);
587 }
588
589 //read eta (eta is 3x3 matrix)
590 if (tokenizer.countTokens() >= 9) {
591 eta(0, 0) = tokenizer.nextTokenAsDouble();
592 eta(0, 1) = tokenizer.nextTokenAsDouble();
593 eta(0, 2) = tokenizer.nextTokenAsDouble();
594 eta(1, 0) = tokenizer.nextTokenAsDouble();
595 eta(1, 1) = tokenizer.nextTokenAsDouble();
596 eta(1, 2) = tokenizer.nextTokenAsDouble();
597 eta(2, 0) = tokenizer.nextTokenAsDouble();
598 eta(2, 1) = tokenizer.nextTokenAsDouble();
599 eta(2, 2) = tokenizer.nextTokenAsDouble();
600
601 s->setEta(eta);
602 }
603
604
605 }
606
607 }//end namespace oopse