ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/io/DumpWriter.cpp
Revision: 2762
Committed: Fri May 19 21:26:41 2006 UTC (18 years, 11 months ago) by chrisfen
File size: 21374 byte(s)
Log Message:
Last bug showed up in 2 places, fixed the other one.

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 #include "io/DumpWriter.hpp"
43 #include "primitives/Molecule.hpp"
44 #include "utils/simError.h"
45 #include "io/basic_teebuf.hpp"
46 #include "io/gzstream.hpp"
47 #include "io/Globals.hpp"
48
49 #ifdef IS_MPI
50 #include <mpi.h>
51 #endif //is_mpi
52
53 namespace oopse {
54
55 DumpWriter::DumpWriter(SimInfo* info)
56 : info_(info), filename_(info->getDumpFileName()), eorFilename_(info->getFinalConfigFileName()){
57
58 Globals* simParams = info->getSimParams();
59 needCompression_ = simParams->getCompressDumpFile();
60 needForceVector_ = simParams->getOutputForceVector();
61 createDumpFile_ = true;
62 #ifdef HAVE_LIBZ
63 if (needCompression_) {
64 filename_ += ".gz";
65 eorFilename_ += ".gz";
66 }
67 #endif
68
69 #ifdef IS_MPI
70
71 if (worldRank == 0) {
72 #endif // is_mpi
73
74
75 dumpFile_ = createOStream(filename_);
76
77 if (!dumpFile_) {
78 sprintf(painCave.errMsg, "Could not open \"%s\" for dump output.\n",
79 filename_.c_str());
80 painCave.isFatal = 1;
81 simError();
82 }
83
84 #ifdef IS_MPI
85
86 }
87
88 sprintf(checkPointMsg, "Sucessfully opened output file for dumping.\n");
89 MPIcheckPoint();
90
91 #endif // is_mpi
92
93 }
94
95
96 DumpWriter::DumpWriter(SimInfo* info, const std::string& filename)
97 : info_(info), filename_(filename){
98
99 Globals* simParams = info->getSimParams();
100 eorFilename_ = filename_.substr(0, filename_.rfind(".")) + ".eor";
101
102 needCompression_ = simParams->getCompressDumpFile();
103 needForceVector_ = simParams->getOutputForceVector();
104 createDumpFile_ = true;
105 #ifdef HAVE_LIBZ
106 if (needCompression_) {
107 filename_ += ".gz";
108 eorFilename_ += ".gz";
109 }
110 #endif
111
112 #ifdef IS_MPI
113
114 if (worldRank == 0) {
115 #endif // is_mpi
116
117
118 dumpFile_ = createOStream(filename_);
119
120 if (!dumpFile_) {
121 sprintf(painCave.errMsg, "Could not open \"%s\" for dump output.\n",
122 filename_.c_str());
123 painCave.isFatal = 1;
124 simError();
125 }
126
127 #ifdef IS_MPI
128
129 }
130
131 sprintf(checkPointMsg, "Sucessfully opened output file for dumping.\n");
132 MPIcheckPoint();
133
134 #endif // is_mpi
135
136 }
137
138 DumpWriter::DumpWriter(SimInfo* info, const std::string& filename, bool writeDumpFile)
139 : info_(info), filename_(filename){
140
141 Globals* simParams = info->getSimParams();
142 eorFilename_ = filename_.substr(0, filename_.rfind(".")) + ".eor";
143
144 needCompression_ = simParams->getCompressDumpFile();
145 needForceVector_ = simParams->getOutputForceVector();
146
147 #ifdef HAVE_LIBZ
148 if (needCompression_) {
149 filename_ += ".gz";
150 eorFilename_ += ".gz";
151 }
152 #endif
153
154 #ifdef IS_MPI
155
156 if (worldRank == 0) {
157 #endif // is_mpi
158
159 createDumpFile_ = writeDumpFile;
160 if (createDumpFile_) {
161 dumpFile_ = createOStream(filename_);
162
163 if (!dumpFile_) {
164 sprintf(painCave.errMsg, "Could not open \"%s\" for dump output.\n",
165 filename_.c_str());
166 painCave.isFatal = 1;
167 simError();
168 }
169 }
170 #ifdef IS_MPI
171
172 }
173
174 sprintf(checkPointMsg, "Sucessfully opened output file for dumping.\n");
175 MPIcheckPoint();
176
177 #endif // is_mpi
178
179 }
180
181
182
183
184
185
186 DumpWriter::~DumpWriter() {
187
188 #ifdef IS_MPI
189
190 if (worldRank == 0) {
191 #endif // is_mpi
192 if (createDumpFile_){
193 delete dumpFile_;
194 }
195 #ifdef IS_MPI
196
197 }
198
199 #endif // is_mpi
200
201 }
202
203 void DumpWriter::writeCommentLine(std::ostream& os, Snapshot* s) {
204
205 RealType currentTime;
206 Mat3x3d hmat;
207 RealType chi;
208 RealType integralOfChiDt;
209 Mat3x3d eta;
210
211 currentTime = s->getTime();
212 hmat = s->getHmat();
213 chi = s->getChi();
214 integralOfChiDt = s->getIntegralOfChiDt();
215 eta = s->getEta();
216
217 os << currentTime << ";\t"
218 << hmat(0, 0) << "\t" << hmat(1, 0) << "\t" << hmat(2, 0) << ";\t"
219 << hmat(0, 1) << "\t" << hmat(1, 1) << "\t" << hmat(2, 1) << ";\t"
220 << hmat(0, 2) << "\t" << hmat(1, 2) << "\t" << hmat(2, 2) << ";\t";
221
222 //write out additional parameters, such as chi and eta
223
224 os << chi << "\t" << integralOfChiDt << ";\t";
225
226 os << eta(0, 0) << "\t" << eta(1, 0) << "\t" << eta(2, 0) << ";\t"
227 << eta(0, 1) << "\t" << eta(1, 1) << "\t" << eta(2, 1) << ";\t"
228 << eta(0, 2) << "\t" << eta(1, 2) << "\t" << eta(2, 2) << ";";
229
230 os << "\n";
231 }
232
233 void DumpWriter::writeFrame(std::ostream& os) {
234 const int BUFFERSIZE = 2000;
235 const int MINIBUFFERSIZE = 100;
236
237 char tempBuffer[BUFFERSIZE];
238 char writeLine[BUFFERSIZE];
239
240 Quat4d q;
241 Vector3d ji;
242 Vector3d pos;
243 Vector3d vel;
244 Vector3d frc;
245 Vector3d trq;
246
247 Molecule* mol;
248 StuntDouble* integrableObject;
249 SimInfo::MoleculeIterator mi;
250 Molecule::IntegrableObjectIterator ii;
251
252 int nTotObjects;
253 nTotObjects = info_->getNGlobalIntegrableObjects();
254
255 #ifndef IS_MPI
256
257
258 os << nTotObjects << "\n";
259
260 writeCommentLine(os, info_->getSnapshotManager()->getCurrentSnapshot());
261
262 for (mol = info_->beginMolecule(mi); mol != NULL; mol = info_->nextMolecule(mi)) {
263
264 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
265 integrableObject = mol->nextIntegrableObject(ii)) {
266
267
268 pos = integrableObject->getPos();
269 vel = integrableObject->getVel();
270
271 sprintf(tempBuffer, "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
272 integrableObject->getType().c_str(),
273 pos[0], pos[1], pos[2],
274 vel[0], vel[1], vel[2]);
275
276 strcpy(writeLine, tempBuffer);
277
278 if (integrableObject->isDirectional()) {
279 q = integrableObject->getQ();
280 ji = integrableObject->getJ();
281
282 sprintf(tempBuffer, "%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
283 q[0], q[1], q[2], q[3],
284 ji[0], ji[1], ji[2]);
285 strcat(writeLine, tempBuffer);
286 } else {
287 strcat(writeLine, "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0");
288 }
289
290 if (needForceVector_) {
291 frc = integrableObject->getFrc();
292 trq = integrableObject->getTrq();
293
294 sprintf(tempBuffer, "\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
295 frc[0], frc[1], frc[2],
296 trq[0], trq[1], trq[2]);
297 strcat(writeLine, tempBuffer);
298 }
299
300 strcat(writeLine, "\n");
301 os << writeLine;
302
303 }
304 }
305
306 os.flush();
307 #else // is_mpi
308 /*********************************************************************
309 * Documentation? You want DOCUMENTATION?
310 *
311 * Why all the potatoes below?
312 *
313 * To make a long story short, the original version of DumpWriter
314 * worked in the most inefficient way possible. Node 0 would
315 * poke each of the node for an individual atom's formatted data
316 * as node 0 worked its way down the global index. This was particularly
317 * inefficient since the method blocked all processors at every atom
318 * (and did it twice!).
319 *
320 * An intermediate version of DumpWriter could be described from Node
321 * zero's perspective as follows:
322 *
323 * 1) Have 100 of your friends stand in a circle.
324 * 2) When you say go, have all of them start tossing potatoes at
325 * you (one at a time).
326 * 3) Catch the potatoes.
327 *
328 * It was an improvement, but MPI has buffers and caches that could
329 * best be described in this analogy as "potato nets", so there's no
330 * need to block the processors atom-by-atom.
331 *
332 * This new and improved DumpWriter works in an even more efficient
333 * way:
334 *
335 * 1) Have 100 of your friend stand in a circle.
336 * 2) When you say go, have them start tossing 5-pound bags of
337 * potatoes at you.
338 * 3) Once you've caught a friend's bag of potatoes,
339 * toss them a spud to let them know they can toss another bag.
340 *
341 * How's THAT for documentation?
342 *
343 *********************************************************************/
344 const int masterNode = 0;
345
346 int * potatoes;
347 int myPotato;
348 int nProc;
349 int which_node;
350 RealType atomData[19];
351 int isDirectional;
352 char MPIatomTypeString[MINIBUFFERSIZE];
353 int msgLen; // the length of message actually recieved at master nodes
354 int haveError;
355 MPI_Status istatus;
356 int nCurObj;
357
358 // code to find maximum tag value
359 int * tagub;
360 int flag;
361 int MAXTAG;
362 MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, &tagub, &flag);
363
364 if (flag) {
365 MAXTAG = *tagub;
366 } else {
367 MAXTAG = 32767;
368 }
369
370 if (worldRank == masterNode) { //master node (node 0) is responsible for writing the dump file
371
372 // Node 0 needs a list of the magic potatoes for each processor;
373
374 MPI_Comm_size(MPI_COMM_WORLD, &nProc);
375 potatoes = new int[nProc];
376
377 //write out the comment lines
378 for(int i = 0; i < nProc; i++) {
379 potatoes[i] = 0;
380 }
381
382
383 os << nTotObjects << "\n";
384 writeCommentLine(os, info_->getSnapshotManager()->getCurrentSnapshot());
385
386 for(int i = 0; i < info_->getNGlobalMolecules(); i++) {
387
388 // Get the Node number which has this atom;
389
390 which_node = info_->getMolToProc(i);
391
392 if (which_node != masterNode) { //current molecule is in slave node
393 if (potatoes[which_node] + 1 >= MAXTAG) {
394 // The potato was going to exceed the maximum value,
395 // so wrap this processor potato back to 0:
396
397 potatoes[which_node] = 0;
398 MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0,
399 MPI_COMM_WORLD);
400 }
401
402 myPotato = potatoes[which_node];
403
404 //recieve the number of integrableObject in current molecule
405 MPI_Recv(&nCurObj, 1, MPI_INT, which_node, myPotato,
406 MPI_COMM_WORLD, &istatus);
407 myPotato++;
408
409 for(int l = 0; l < nCurObj; l++) {
410 if (potatoes[which_node] + 2 >= MAXTAG) {
411 // The potato was going to exceed the maximum value,
412 // so wrap this processor potato back to 0:
413
414 potatoes[which_node] = 0;
415 MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node,
416 0, MPI_COMM_WORLD);
417 }
418
419 MPI_Recv(MPIatomTypeString, MINIBUFFERSIZE, MPI_CHAR,
420 which_node, myPotato, MPI_COMM_WORLD,
421 &istatus);
422
423 myPotato++;
424
425 MPI_Recv(atomData, 19, MPI_REALTYPE, which_node, myPotato,
426 MPI_COMM_WORLD, &istatus);
427 myPotato++;
428
429 MPI_Get_count(&istatus, MPI_REALTYPE, &msgLen);
430
431 if (msgLen == 13 || msgLen == 19)
432 isDirectional = 1;
433 else
434 isDirectional = 0;
435
436 // If we've survived to here, format the line:
437
438 if (!isDirectional) {
439 sprintf(writeLine, "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
440 MPIatomTypeString, atomData[0],
441 atomData[1], atomData[2],
442 atomData[3], atomData[4],
443 atomData[5]);
444
445 strcat(writeLine,
446 "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0");
447 } else {
448 sprintf(writeLine,
449 "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
450 MPIatomTypeString,
451 atomData[0],
452 atomData[1],
453 atomData[2],
454 atomData[3],
455 atomData[4],
456 atomData[5],
457 atomData[6],
458 atomData[7],
459 atomData[8],
460 atomData[9],
461 atomData[10],
462 atomData[11],
463 atomData[12]);
464 }
465
466 if (needForceVector_) {
467 if (!isDirectional) {
468 sprintf(writeLine, "\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
469 atomData[6],
470 atomData[7],
471 atomData[8],
472 atomData[9],
473 atomData[10],
474 atomData[11]);
475 } else {
476 sprintf(writeLine, "\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
477 atomData[13],
478 atomData[14],
479 atomData[15],
480 atomData[16],
481 atomData[17],
482 atomData[18]);
483 }
484 }
485
486 os << writeLine << "\n";
487
488 } // end for(int l =0)
489
490 potatoes[which_node] = myPotato;
491 } else { //master node has current molecule
492
493 mol = info_->getMoleculeByGlobalIndex(i);
494
495 if (mol == NULL) {
496 sprintf(painCave.errMsg, "Molecule not found on node %d!", worldRank);
497 painCave.isFatal = 1;
498 simError();
499 }
500
501 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
502 integrableObject = mol->nextIntegrableObject(ii)) {
503
504 pos = integrableObject->getPos();
505 vel = integrableObject->getVel();
506
507 atomData[0] = pos[0];
508 atomData[1] = pos[1];
509 atomData[2] = pos[2];
510
511 atomData[3] = vel[0];
512 atomData[4] = vel[1];
513 atomData[5] = vel[2];
514
515 isDirectional = 0;
516
517 if (integrableObject->isDirectional()) {
518 isDirectional = 1;
519
520 q = integrableObject->getQ();
521 ji = integrableObject->getJ();
522
523 for(int j = 0; j < 6; j++) {
524 atomData[j] = atomData[j];
525 }
526
527 atomData[6] = q[0];
528 atomData[7] = q[1];
529 atomData[8] = q[2];
530 atomData[9] = q[3];
531
532 atomData[10] = ji[0];
533 atomData[11] = ji[1];
534 atomData[12] = ji[2];
535 }
536
537 if (needForceVector_) {
538 frc = integrableObject->getFrc();
539 trq = integrableObject->getTrq();
540
541 if (!isDirectional) {
542 atomData[6] = frc[0];
543 atomData[7] = frc[1];
544 atomData[8] = frc[2];
545 atomData[9] = trq[0];
546 atomData[10] = trq[1];
547 atomData[11] = trq[2];
548 } else {
549 atomData[13] = frc[0];
550 atomData[14] = frc[1];
551 atomData[15] = frc[2];
552 atomData[16] = trq[0];
553 atomData[17] = trq[1];
554 atomData[18] = trq[2];
555 }
556 }
557
558 // If we've survived to here, format the line:
559
560 if (!isDirectional) {
561 sprintf(writeLine, "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
562 integrableObject->getType().c_str(), atomData[0],
563 atomData[1], atomData[2],
564 atomData[3], atomData[4],
565 atomData[5]);
566
567 strcat(writeLine,
568 "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0");
569 } else {
570 sprintf(writeLine,
571 "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
572 integrableObject->getType().c_str(),
573 atomData[0],
574 atomData[1],
575 atomData[2],
576 atomData[3],
577 atomData[4],
578 atomData[5],
579 atomData[6],
580 atomData[7],
581 atomData[8],
582 atomData[9],
583 atomData[10],
584 atomData[11],
585 atomData[12]);
586 }
587
588 if (needForceVector_) {
589 if (!isDirectional) {
590 sprintf(writeLine, "\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
591 atomData[6],
592 atomData[7],
593 atomData[8],
594 atomData[9],
595 atomData[10],
596 atomData[11]);
597 } else {
598 sprintf(writeLine, "\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
599 atomData[13],
600 atomData[14],
601 atomData[15],
602 atomData[16],
603 atomData[17],
604 atomData[18]);
605 }
606 }
607
608 os << writeLine << "\n";
609
610 } //end for(iter = integrableObject.begin())
611 }
612 } //end for(i = 0; i < mpiSim->getNmol())
613
614 os.flush();
615
616 sprintf(checkPointMsg, "Sucessfully took a dump.\n");
617 MPIcheckPoint();
618
619 delete [] potatoes;
620 } else {
621
622 // worldRank != 0, so I'm a remote node.
623
624 // Set my magic potato to 0:
625
626 myPotato = 0;
627
628 for(int i = 0; i < info_->getNGlobalMolecules(); i++) {
629
630 // Am I the node which has this integrableObject?
631 int whichNode = info_->getMolToProc(i);
632 if (whichNode == worldRank) {
633 if (myPotato + 1 >= MAXTAG) {
634
635 // The potato was going to exceed the maximum value,
636 // so wrap this processor potato back to 0 (and block until
637 // node 0 says we can go:
638
639 MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD,
640 &istatus);
641 }
642
643 mol = info_->getMoleculeByGlobalIndex(i);
644
645
646 nCurObj = mol->getNIntegrableObjects();
647
648 MPI_Send(&nCurObj, 1, MPI_INT, 0, myPotato, MPI_COMM_WORLD);
649 myPotato++;
650
651 for (integrableObject = mol->beginIntegrableObject(ii); integrableObject != NULL;
652 integrableObject = mol->nextIntegrableObject(ii)) {
653
654 if (myPotato + 2 >= MAXTAG) {
655
656 // The potato was going to exceed the maximum value,
657 // so wrap this processor potato back to 0 (and block until
658 // node 0 says we can go:
659
660 MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD,
661 &istatus);
662 }
663
664 pos = integrableObject->getPos();
665 vel = integrableObject->getVel();
666
667 atomData[0] = pos[0];
668 atomData[1] = pos[1];
669 atomData[2] = pos[2];
670
671 atomData[3] = vel[0];
672 atomData[4] = vel[1];
673 atomData[5] = vel[2];
674
675 isDirectional = 0;
676
677 if (integrableObject->isDirectional()) {
678 isDirectional = 1;
679
680 q = integrableObject->getQ();
681 ji = integrableObject->getJ();
682
683 atomData[6] = q[0];
684 atomData[7] = q[1];
685 atomData[8] = q[2];
686 atomData[9] = q[3];
687
688 atomData[10] = ji[0];
689 atomData[11] = ji[1];
690 atomData[12] = ji[2];
691 }
692
693 if (needForceVector_) {
694 frc = integrableObject->getFrc();
695 trq = integrableObject->getTrq();
696
697 if (!isDirectional) {
698 atomData[6] = frc[0];
699 atomData[7] = frc[1];
700 atomData[8] = frc[2];
701
702 atomData[9] = trq[0];
703 atomData[10] = trq[1];
704 atomData[11] = trq[2];
705 } else {
706 atomData[13] = frc[0];
707 atomData[14] = frc[1];
708 atomData[15] = frc[2];
709
710 atomData[16] = trq[0];
711 atomData[17] = trq[1];
712 atomData[18] = trq[2];
713 }
714 }
715
716 strncpy(MPIatomTypeString, integrableObject->getType().c_str(), MINIBUFFERSIZE);
717
718 // null terminate the std::string before sending (just in case):
719 MPIatomTypeString[MINIBUFFERSIZE - 1] = '\0';
720
721 MPI_Send(MPIatomTypeString, MINIBUFFERSIZE, MPI_CHAR, 0,
722 myPotato, MPI_COMM_WORLD);
723
724 myPotato++;
725
726 if (isDirectional && needForceVector_) {
727 MPI_Send(atomData, 19, MPI_REALTYPE, 0, myPotato,
728 MPI_COMM_WORLD);
729 } else if (isDirectional) {
730 MPI_Send(atomData, 13, MPI_REALTYPE, 0, myPotato,
731 MPI_COMM_WORLD);
732 } else if (needForceVector_) {
733 MPI_Send(atomData, 12, MPI_REALTYPE, 0, myPotato,
734 MPI_COMM_WORLD);
735 } else {
736 MPI_Send(atomData, 6, MPI_REALTYPE, 0, myPotato,
737 MPI_COMM_WORLD);
738 }
739
740 myPotato++;
741 }
742
743 }
744
745 }
746 sprintf(checkPointMsg, "Sucessfully took a dump.\n");
747 MPIcheckPoint();
748 }
749
750 #endif // is_mpi
751
752 }
753
754 void DumpWriter::writeDump() {
755 writeFrame(*dumpFile_);
756 }
757
758 void DumpWriter::writeEor() {
759 std::ostream* eorStream;
760
761 #ifdef IS_MPI
762 if (worldRank == 0) {
763 #endif // is_mpi
764
765 eorStream = createOStream(eorFilename_);
766
767 #ifdef IS_MPI
768 }
769 #endif // is_mpi
770
771 writeFrame(*eorStream);
772
773 #ifdef IS_MPI
774 if (worldRank == 0) {
775 #endif // is_mpi
776 delete eorStream;
777
778 #ifdef IS_MPI
779 }
780 #endif // is_mpi
781
782 }
783
784
785 void DumpWriter::writeDumpAndEor() {
786 std::vector<std::streambuf*> buffers;
787 std::ostream* eorStream;
788 #ifdef IS_MPI
789 if (worldRank == 0) {
790 #endif // is_mpi
791
792 buffers.push_back(dumpFile_->rdbuf());
793
794 eorStream = createOStream(eorFilename_);
795
796 buffers.push_back(eorStream->rdbuf());
797
798 #ifdef IS_MPI
799 }
800 #endif // is_mpi
801
802 TeeBuf tbuf(buffers.begin(), buffers.end());
803 std::ostream os(&tbuf);
804
805 writeFrame(os);
806
807 #ifdef IS_MPI
808 if (worldRank == 0) {
809 #endif // is_mpi
810 delete eorStream;
811
812 #ifdef IS_MPI
813 }
814 #endif // is_mpi
815
816 }
817
818 std::ostream* DumpWriter::createOStream(const std::string& filename) {
819
820 std::ostream* newOStream;
821 #ifdef HAVE_LIBZ
822 if (needCompression_) {
823 newOStream = new ogzstream(filename.c_str());
824 } else {
825 newOStream = new std::ofstream(filename.c_str());
826 }
827 #else
828 newOStream = new std::ofstream(filename.c_str());
829 #endif
830 return newOStream;
831 }
832
833 }//end namespace oopse