ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/DumpReader.cpp
Revision: 2101
Committed: Thu Mar 10 15:10:24 2005 UTC (19 years, 3 months ago) by chrisfen
File size: 19167 byte(s)
Log Message:
First commit of the new restraints code

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::deletePointers(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 int storageLayout = info_->getSnapshotManager()->getStorageLayout();
223
224 if (storageLayout & DataStorage::dslPosition) {
225 needPos_ = true;
226 } else {
227 needPos_ = false;
228 }
229
230 if (storageLayout & DataStorage::dslVelocity) {
231 needVel_ = true;
232 } else {
233 needVel_ = false;
234 }
235
236 if (storageLayout & DataStorage::dslAmat || storageLayout & DataStorage::dslElectroFrame) {
237 needQuaternion_ = true;
238 } else {
239 needQuaternion_ = false;
240 }
241
242 if (storageLayout & DataStorage::dslAngularMomentum) {
243 needAngMom_ = true;
244 } else {
245 needAngMom_ = false;
246 }
247
248 readSet(whichFrame);
249 }
250
251 void DumpReader::readSet(int whichFrame) {
252 int i;
253 int nTotObjs; // the number of atoms
254 char read_buffer[maxBufferSize]; //the line buffer for reading
255 char * eof_test; // ptr to see when we reach the end of the file
256
257 Molecule* mol;
258 StuntDouble* integrableObject;
259 SimInfo::MoleculeIterator mi;
260 Molecule::IntegrableObjectIterator ii;
261
262 #ifndef IS_MPI
263
264 fsetpos(inFile_, framePos_[whichFrame]);
265 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
266
267 if (eof_test == NULL) {
268 sprintf(painCave.errMsg,
269 "DumpReader error: error reading 1st line of \"%s\"\n",
270 filename_.c_str());
271 painCave.isFatal = 1;
272 simError();
273 }
274
275 nTotObjs = atoi(read_buffer);
276
277 if (nTotObjs != info_->getNGlobalIntegrableObjects()) {
278 sprintf(painCave.errMsg,
279 "DumpReader error. %s nIntegrable, %d, "
280 "does not match the meta-data file's nIntegrable, %d.\n",
281 filename_.c_str(),
282 nTotObjs,
283 info_->getNGlobalIntegrableObjects());
284
285 painCave.isFatal = 1;
286 simError();
287 }
288
289 //read the box mat from the comment line
290
291 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
292
293 if (eof_test == NULL) {
294 sprintf(painCave.errMsg, "DumpReader Error: error in reading commment in %s\n",
295 filename_.c_str());
296 painCave.isFatal = 1;
297 simError();
298 }
299
300 parseCommentLine(read_buffer, info_->getSnapshotManager()->getCurrentSnapshot());
301
302 //parse dump lines
303
304 i = 0;
305 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) {
306
307 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
308 integrableObject = mol->nextIntegrableObject(ii)) {
309
310 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
311
312 if (eof_test == NULL) {
313 sprintf(painCave.errMsg,
314 "DumpReader Error: error in reading file %s\n"
315 "natoms = %d; index = %d\n"
316 "error reading the line from the file.\n",
317 filename_.c_str(),
318 nTotObjs,
319 i);
320
321 painCave.isFatal = 1;
322 simError();
323 }
324
325 parseDumpLine(read_buffer, integrableObject);
326 i++;
327 }
328 }
329
330 // MPI Section of code..........
331
332 #else //IS_MPI
333
334 // first thing first, suspend fatalities.
335 int masterNode = 0;
336 int nCurObj;
337 painCave.isEventLoop = 1;
338
339 int myStatus; // 1 = wakeup & success; 0 = error; -1 = AllDone
340 int haveError;
341
342 MPI_Status istatus;
343 int nitems;
344
345 nTotObjs = info_->getNGlobalIntegrableObjects();
346 haveError = 0;
347
348 if (worldRank == masterNode) {
349 fsetpos(inFile_, framePos_[whichFrame]);
350
351 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
352
353 if (eof_test == NULL) {
354 sprintf(painCave.errMsg, "DumpReader Error: Error reading 1st line of %s \n ",
355 filename_.c_str());
356 painCave.isFatal = 1;
357 simError();
358 }
359
360 nitems = atoi(read_buffer);
361
362 // Check to see that the number of integrable objects in the
363 // intial configuration file is the same as derived from the
364 // meta-data file.
365
366 if (nTotObjs != nitems) {
367 sprintf(painCave.errMsg,
368 "DumpReader Error. %s nIntegrable, %d, "
369 "does not match the meta-data file's nIntegrable, %d.\n",
370 filename_.c_str(),
371 nTotObjs,
372 info_->getNGlobalIntegrableObjects());
373
374 painCave.isFatal = 1;
375 simError();
376 }
377
378 //read the boxMat from the comment line
379
380 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
381
382 if (eof_test == NULL) {
383 sprintf(painCave.errMsg, "DumpReader Error: error in reading commment in %s\n",
384 filename_.c_str());
385 painCave.isFatal = 1;
386 simError();
387 }
388
389 //Every single processor will parse the comment line by itself
390 //By using this way, we might lose some efficiency, but if we want to add
391 //more parameters into comment line, we only need to modify function
392 //parseCommentLine
393
394 MPI_Bcast(read_buffer, maxBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
395 parseCommentLine(read_buffer, info_->getSnapshotManager()->getCurrentSnapshot());
396
397 for(i = 0; i < info_->getNGlobalMolecules(); i++) {
398 int which_node = info_->getMolToProc(i);
399
400 if (which_node == masterNode) {
401 //molecules belong to master node
402
403 mol = info_->getMoleculeByGlobalIndex(i);
404
405 if (mol == NULL) {
406 sprintf(painCave.errMsg, "DumpReader Error: Molecule not found on node %d!", worldRank);
407 painCave.isFatal = 1;
408 simError();
409 }
410
411 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
412 integrableObject = mol->nextIntegrableObject(ii)){
413
414 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
415
416 if (eof_test == NULL) {
417 sprintf(painCave.errMsg,
418 "DumpReader Error: error in reading file %s\n"
419 "natoms = %d; index = %d\n"
420 "error reading the line from the file.\n",
421 filename_.c_str(),
422 nTotObjs,
423 i);
424
425 painCave.isFatal = 1;
426 simError();
427 }
428
429 parseDumpLine(read_buffer, integrableObject);
430 }
431 } else {
432 //molecule belongs to slave nodes
433
434 MPI_Recv(&nCurObj, 1, MPI_INT, which_node, TAKE_THIS_TAG_INT,
435 MPI_COMM_WORLD, &istatus);
436
437 for(int j = 0; j < nCurObj; j++) {
438 eof_test = fgets(read_buffer, sizeof(read_buffer), inFile_);
439
440 if (eof_test == NULL) {
441 sprintf(painCave.errMsg,
442 "DumpReader Error: error in reading file %s\n"
443 "natoms = %d; index = %d\n"
444 "error reading the line from the file.\n",
445 filename_.c_str(),
446 nTotObjs,
447 i);
448
449 painCave.isFatal = 1;
450 simError();
451 }
452
453 MPI_Send(read_buffer, maxBufferSize, MPI_CHAR, which_node,
454 TAKE_THIS_TAG_CHAR, MPI_COMM_WORLD);
455 }
456 }
457 }
458 } else {
459 //actions taken at slave nodes
460 MPI_Bcast(read_buffer, maxBufferSize, MPI_CHAR, masterNode, MPI_COMM_WORLD);
461
462 /**@todo*/
463 parseCommentLine(read_buffer, info_->getSnapshotManager()->getCurrentSnapshot());
464
465 for(i = 0; i < info_->getNGlobalMolecules(); i++) {
466 int which_node = info_->getMolToProc(i);
467
468 if (which_node == worldRank) {
469 //molecule with global index i belongs to this processor
470
471 mol = info_->getMoleculeByGlobalIndex(i);
472 if (mol == NULL) {
473 sprintf(painCave.errMsg, "DumpReader Error: Molecule not found on node %d!", worldRank);
474 painCave.isFatal = 1;
475 simError();
476 }
477
478 nCurObj = mol->getNIntegrableObjects();
479
480 MPI_Send(&nCurObj, 1, MPI_INT, masterNode, TAKE_THIS_TAG_INT,
481 MPI_COMM_WORLD);
482
483 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
484 integrableObject = mol->nextIntegrableObject(ii)){
485
486 MPI_Recv(read_buffer, maxBufferSize, MPI_CHAR, masterNode,
487 TAKE_THIS_TAG_CHAR, MPI_COMM_WORLD, &istatus);
488
489 parseDumpLine(read_buffer, integrableObject);
490 }
491
492 }
493
494 }
495
496 }
497
498 #endif
499
500 }
501
502 void DumpReader::parseDumpLine(char *line, StuntDouble *integrableObject) {
503
504 Vector3d pos; // position place holders
505 Vector3d vel; // velocity placeholders
506 Quat4d q; // the quaternions
507 Vector3d ji; // angular velocity placeholders;
508 StringTokenizer tokenizer(line);
509 int nTokens;
510
511 nTokens = tokenizer.countTokens();
512
513 if (nTokens < 14) {
514 sprintf(painCave.errMsg,
515 "DumpReader Error: Not enough Tokens.\n%s\n", line);
516 painCave.isFatal = 1;
517 simError();
518 }
519
520 std::string name = tokenizer.nextToken();
521
522 if (name != integrableObject->getType()) {
523
524 sprintf(painCave.errMsg,
525 "DumpReader Error: Atom type [%s] in %s does not match Atom Type [%s] in .md file.\n",
526 name.c_str(), filename_.c_str(), integrableObject->getType().c_str());
527 painCave.isFatal = 1;
528 simError();
529 }
530
531 pos[0] = tokenizer.nextTokenAsDouble();
532 pos[1] = tokenizer.nextTokenAsDouble();
533 pos[2] = tokenizer.nextTokenAsDouble();
534 if (needPos_) {
535 integrableObject->setPos(pos);
536 }
537
538 vel[0] = tokenizer.nextTokenAsDouble();
539 vel[1] = tokenizer.nextTokenAsDouble();
540 vel[2] = tokenizer.nextTokenAsDouble();
541 if (needVel_) {
542 integrableObject->setVel(vel);
543 }
544
545 if (integrableObject->isDirectional()) {
546
547 q[0] = tokenizer.nextTokenAsDouble();
548 q[1] = tokenizer.nextTokenAsDouble();
549 q[2] = tokenizer.nextTokenAsDouble();
550 q[3] = tokenizer.nextTokenAsDouble();
551
552 double qlen = q.length();
553 if (qlen < oopse::epsilon) { //check quaternion is not equal to 0
554
555 sprintf(painCave.errMsg,
556 "DumpReader Error: initial quaternion error (q0^2 + q1^2 + q2^2 + q3^2 ~ 0).\n");
557 painCave.isFatal = 1;
558 simError();
559
560 }
561
562 q.normalize();
563 if (needQuaternion_) {
564 integrableObject->setQ(q);
565 }
566
567 ji[0] = tokenizer.nextTokenAsDouble();
568 ji[1] = tokenizer.nextTokenAsDouble();
569 ji[2] = tokenizer.nextTokenAsDouble();
570 if (needAngMom_) {
571 integrableObject->setJ(ji);
572 }
573 }
574
575 }
576
577
578 void DumpReader::parseCommentLine(char* line, Snapshot* s) {
579 double currTime;
580 Mat3x3d hmat;
581 double chi;
582 double integralOfChiDt;
583 Mat3x3d eta;
584
585 StringTokenizer tokenizer(line);
586 int nTokens;
587
588 nTokens = tokenizer.countTokens();
589
590 //comment line should at least contain 10 tokens: current time(1 token) and h-matrix(9 tokens)
591 if (nTokens < 10) {
592 sprintf(painCave.errMsg,
593 "DumpReader Error: Not enough tokens in comment line: %s", line);
594 painCave.isFatal = 1;
595 simError();
596 }
597
598 //read current time
599 currTime = tokenizer.nextTokenAsDouble();
600 s->setTime(currTime);
601
602 //read h-matrix
603 hmat(0, 0) = tokenizer.nextTokenAsDouble();
604 hmat(0, 1) = tokenizer.nextTokenAsDouble();
605 hmat(0, 2) = tokenizer.nextTokenAsDouble();
606 hmat(1, 0) = tokenizer.nextTokenAsDouble();
607 hmat(1, 1) = tokenizer.nextTokenAsDouble();
608 hmat(1, 2) = tokenizer.nextTokenAsDouble();
609 hmat(2, 0) = tokenizer.nextTokenAsDouble();
610 hmat(2, 1) = tokenizer.nextTokenAsDouble();
611 hmat(2, 2) = tokenizer.nextTokenAsDouble();
612 s->setHmat(hmat);
613
614 //read chi and integralOfChidt, they should apprear in pair
615 if (tokenizer.countTokens() >= 2) {
616 chi = tokenizer.nextTokenAsDouble();
617 integralOfChiDt = tokenizer.nextTokenAsDouble();
618
619 s->setChi(chi);
620 s->setIntegralOfChiDt(integralOfChiDt);
621 }
622
623 //read eta (eta is 3x3 matrix)
624 if (tokenizer.countTokens() >= 9) {
625 eta(0, 0) = tokenizer.nextTokenAsDouble();
626 eta(0, 1) = tokenizer.nextTokenAsDouble();
627 eta(0, 2) = tokenizer.nextTokenAsDouble();
628 eta(1, 0) = tokenizer.nextTokenAsDouble();
629 eta(1, 1) = tokenizer.nextTokenAsDouble();
630 eta(1, 2) = tokenizer.nextTokenAsDouble();
631 eta(2, 0) = tokenizer.nextTokenAsDouble();
632 eta(2, 1) = tokenizer.nextTokenAsDouble();
633 eta(2, 2) = tokenizer.nextTokenAsDouble();
634
635 s->setEta(eta);
636 }
637
638
639 }
640
641 }//end namespace oopse