ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/DumpWriter.cpp
Revision: 1252
Committed: Mon Jun 7 14:26:33 2004 UTC (20 years, 1 month ago) by gezelter
File size: 17418 byte(s)
Log Message:
Fixes from gcc -Wall

File Contents

# User Rev Content
1 tim 1078 #define _LARGEFILE_SOURCE64
2 mmeineke 723 #define _FILE_OFFSET_BITS 64
3    
4 gezelter 829 #include <string.h>
5 mmeineke 377 #include <iostream>
6     #include <fstream>
7 tim 929 #include <algorithm>
8     #include <utility>
9 mmeineke 377
10     #ifdef IS_MPI
11     #include <mpi.h>
12     #include "mpiSimulation.hpp"
13 mmeineke 440
14     namespace dWrite{
15 gezelter 907 void DieDieDie( void );
16 mmeineke 440 }
17    
18     using namespace dWrite;
19 mmeineke 377 #endif //is_mpi
20    
21     #include "ReadWrite.hpp"
22     #include "simError.h"
23    
24     DumpWriter::DumpWriter( SimInfo* the_entry_plug ){
25    
26     entry_plug = the_entry_plug;
27    
28     #ifdef IS_MPI
29     if(worldRank == 0 ){
30     #endif // is_mpi
31 tim 837
32 tim 929 dumpFile.open(entry_plug->sampleName, ios::out | ios::trunc );
33 tim 837
34 tim 929 if( !dumpFile ){
35 tim 837
36 mmeineke 377 sprintf( painCave.errMsg,
37     "Could not open \"%s\" for dump output.\n",
38 tim 929 entry_plug->sampleName);
39 mmeineke 377 painCave.isFatal = 1;
40     simError();
41     }
42 mmeineke 469
43 mmeineke 377 #ifdef IS_MPI
44     }
45    
46 tim 929 //sort the local atoms by global index
47     sortByGlobalIndex();
48    
49 mmeineke 377 sprintf( checkPointMsg,
50     "Sucessfully opened output file for dumping.\n");
51     MPIcheckPoint();
52     #endif // is_mpi
53     }
54    
55     DumpWriter::~DumpWriter( ){
56    
57     #ifdef IS_MPI
58     if(worldRank == 0 ){
59     #endif // is_mpi
60    
61 tim 929 dumpFile.close();
62 mmeineke 377
63     #ifdef IS_MPI
64     }
65     #endif // is_mpi
66     }
67    
68 tim 929 #ifdef IS_MPI
69 tim 837
70 tim 929 /**
71     * A hook function to load balancing
72     */
73    
74     void DumpWriter::update(){
75     sortByGlobalIndex();
76     }
77    
78     /**
79     * Auxiliary sorting function
80     */
81    
82     bool indexSortingCriterion(const pair<int, int>& p1, const pair<int, int>& p2){
83     return p1.second < p2.second;
84     }
85    
86     /**
87     * Sorting the local index by global index
88     */
89    
90     void DumpWriter::sortByGlobalIndex(){
91 tim 1108 Molecule* mols = entry_plug->molecules;
92 tim 929 indexArray.clear();
93    
94 tim 1129 for(int i = 0; i < entry_plug->n_mol;i++)
95 tim 1108 indexArray.push_back(make_pair(i, mols[i].getGlobalIndex()));
96 tim 929
97     sort(indexArray.begin(), indexArray.end(), indexSortingCriterion);
98     }
99 chuckv 949
100 tim 929 #endif
101    
102     void DumpWriter::writeDump(double currentTime){
103    
104 tim 936 ofstream finalOut;
105 tim 934 vector<ofstream*> fileStreams;
106    
107     #ifdef IS_MPI
108     if(worldRank == 0 ){
109 tim 952 #endif
110 tim 936 finalOut.open( entry_plug->finalName, ios::out | ios::trunc );
111     if( !finalOut ){
112     sprintf( painCave.errMsg,
113     "Could not open \"%s\" for final dump output.\n",
114     entry_plug->finalName );
115     painCave.isFatal = 1;
116     simError();
117     }
118 tim 952 #ifdef IS_MPI
119 tim 934 }
120     #endif // is_mpi
121    
122     fileStreams.push_back(&finalOut);
123     fileStreams.push_back(&dumpFile);
124    
125     writeFrame(fileStreams, currentTime);
126 tim 936
127     #ifdef IS_MPI
128     finalOut.close();
129     #endif
130 tim 929
131     }
132    
133     void DumpWriter::writeFinal(double currentTime){
134    
135 tim 936 ofstream finalOut;
136 tim 934 vector<ofstream*> fileStreams;
137    
138 tim 929 #ifdef IS_MPI
139     if(worldRank == 0 ){
140 mmeineke 951 #endif // is_mpi
141 tim 936
142     finalOut.open( entry_plug->finalName, ios::out | ios::trunc );
143    
144     if( !finalOut ){
145     sprintf( painCave.errMsg,
146     "Could not open \"%s\" for final dump output.\n",
147     entry_plug->finalName );
148     painCave.isFatal = 1;
149     simError();
150     }
151    
152 mmeineke 951 #ifdef IS_MPI
153 tim 934 }
154 tim 929 #endif // is_mpi
155    
156 tim 934 fileStreams.push_back(&finalOut);
157     writeFrame(fileStreams, currentTime);
158 tim 936
159     #ifdef IS_MPI
160     finalOut.close();
161     #endif
162 tim 929
163     }
164    
165 tim 934 void DumpWriter::writeFrame( vector<ofstream*>& outFile, double currentTime ){
166 tim 929
167 mmeineke 377 const int BUFFERSIZE = 2000;
168 gezelter 912 const int MINIBUFFERSIZE = 100;
169 gezelter 907
170 tim 936 char tempBuffer[BUFFERSIZE];
171 mmeineke 377 char writeLine[BUFFERSIZE];
172    
173 gezelter 1252 int i;
174     unsigned int k;
175 gezelter 916
176 mmeineke 787 #ifdef IS_MPI
177 gezelter 916
178 gezelter 947 /*********************************************************************
179     * Documentation? You want DOCUMENTATION?
180     *
181     * Why all the potatoes below?
182     *
183     * To make a long story short, the original version of DumpWriter
184     * worked in the most inefficient way possible. Node 0 would
185     * poke each of the node for an individual atom's formatted data
186     * as node 0 worked its way down the global index. This was particularly
187     * inefficient since the method blocked all processors at every atom
188     * (and did it twice!).
189     *
190     * An intermediate version of DumpWriter could be described from Node
191     * zero's perspective as follows:
192     *
193     * 1) Have 100 of your friends stand in a circle.
194     * 2) When you say go, have all of them start tossing potatoes at
195     * you (one at a time).
196     * 3) Catch the potatoes.
197     *
198     * It was an improvement, but MPI has buffers and caches that could
199     * best be described in this analogy as "potato nets", so there's no
200     * need to block the processors atom-by-atom.
201     *
202     * This new and improved DumpWriter works in an even more efficient
203     * way:
204     *
205     * 1) Have 100 of your friend stand in a circle.
206     * 2) When you say go, have them start tossing 5-pound bags of
207     * potatoes at you.
208     * 3) Once you've caught a friend's bag of potatoes,
209     * toss them a spud to let them know they can toss another bag.
210     *
211     * How's THAT for documentation?
212     *
213     *********************************************************************/
214    
215 gezelter 916 int *potatoes;
216     int myPotato;
217    
218     int nProc;
219 tim 929 int j, which_node, done, which_atom, local_index, currentIndex;
220 tim 1152 double atomData[13];
221 gezelter 907 int isDirectional;
222     char* atomTypeString;
223 gezelter 910 char MPIatomTypeString[MINIBUFFERSIZE];
224 tim 1108 int nObjects;
225 tim 1152 int msgLen; // the length of message actually recieved at master nodes
226 mmeineke 787 #endif //is_mpi
227    
228 gezelter 1097 double q[4], ji[3];
229 mmeineke 377 DirectionalAtom* dAtom;
230 mmeineke 670 double pos[3], vel[3];
231 tim 1108 int nTotObjects;
232     StuntDouble* sd;
233     char* molName;
234     vector<StuntDouble*> integrableObjects;
235     vector<StuntDouble*>::iterator iter;
236     nTotObjects = entry_plug->getTotIntegrableObjects();
237 mmeineke 377 #ifndef IS_MPI
238 tim 934
239     for(k = 0; k < outFile.size(); k++){
240 tim 1108 *outFile[k] << nTotObjects << "\n";
241 tim 837
242 tim 934 *outFile[k] << currentTime << ";\t"
243     << entry_plug->Hmat[0][0] << "\t"
244     << entry_plug->Hmat[1][0] << "\t"
245     << entry_plug->Hmat[2][0] << ";\t"
246    
247     << entry_plug->Hmat[0][1] << "\t"
248     << entry_plug->Hmat[1][1] << "\t"
249     << entry_plug->Hmat[2][1] << ";\t"
250 tim 837
251 tim 934 << entry_plug->Hmat[0][2] << "\t"
252     << entry_plug->Hmat[1][2] << "\t"
253     << entry_plug->Hmat[2][2] << ";";
254 mmeineke 572
255 tim 934 //write out additional parameters, such as chi and eta
256     *outFile[k] << entry_plug->the_integrator->getAdditionalParameters() << endl;
257     }
258    
259 tim 1108 for( i=0; i< entry_plug->n_mol; i++ ){
260 tim 837
261 tim 1108 integrableObjects = entry_plug->molecules[i].getIntegrableObjects();
262     molName = (entry_plug->compStamps[entry_plug->molecules[i].getStampID()])->getID();
263    
264     for( iter = integrableObjects.begin();iter != integrableObjects.end(); ++iter){
265     sd = *iter;
266     sd->getPos(pos);
267     sd->getVel(vel);
268 mmeineke 377
269 tim 1108 sprintf( tempBuffer,
270     "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
271     sd->getType(),
272     pos[0],
273     pos[1],
274     pos[2],
275     vel[0],
276     vel[1],
277     vel[2]);
278     strcpy( writeLine, tempBuffer );
279 mmeineke 377
280 tim 1108 if( sd->isDirectional() ){
281 tim 837
282 tim 1108 sd->getQ( q );
283     sd->getJ( ji );
284 tim 837
285 tim 1108 sprintf( tempBuffer,
286     "%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\n",
287     q[0],
288     q[1],
289     q[2],
290     q[3],
291     ji[0],
292     ji[1],
293     ji[2]);
294     strcat( writeLine, tempBuffer );
295     }
296     else
297     strcat( writeLine, "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\n" );
298 tim 1231
299     for(k = 0; k < outFile.size(); k++)
300     *outFile[k] << writeLine;
301 mmeineke 377 }
302 tim 837
303 tim 1108 }
304 mmeineke 377
305     #else // is_mpi
306 gezelter 416
307 chuckv 913 /* code to find maximum tag value */
308 tim 919
309 tim 920 int *tagub, flag, MAXTAG;
310 chuckv 913 MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, &tagub, &flag);
311     if (flag) {
312 tim 920 MAXTAG = *tagub;
313 chuckv 913 } else {
314     MAXTAG = 32767;
315 gezelter 916 }
316 mmeineke 440
317     int haveError;
318    
319 mmeineke 447 MPI_Status istatus;
320 tim 1108 int nCurObj;
321     int *MolToProcMap = mpiSim->getMolToProcMap();
322 tim 837
323 mmeineke 377 // write out header and node 0's coordinates
324 tim 837
325 mmeineke 377 if( worldRank == 0 ){
326 gezelter 916
327     // Node 0 needs a list of the magic potatoes for each processor;
328    
329 gezelter 1203 nProc = mpiSim->getNProcessors();
330 gezelter 916 potatoes = new int[nProc];
331    
332 tim 934 //write out the comment lines
333 gezelter 916 for (i = 0; i < nProc; i++)
334     potatoes[i] = 0;
335    
336 tim 934 for(k = 0; k < outFile.size(); k++){
337 tim 1108 *outFile[k] << nTotObjects << "\n";
338 tim 837
339 tim 934 *outFile[k] << currentTime << ";\t"
340     << entry_plug->Hmat[0][0] << "\t"
341     << entry_plug->Hmat[1][0] << "\t"
342     << entry_plug->Hmat[2][0] << ";\t"
343 tim 837
344 tim 934 << entry_plug->Hmat[0][1] << "\t"
345     << entry_plug->Hmat[1][1] << "\t"
346     << entry_plug->Hmat[2][1] << ";\t"
347 tim 837
348 tim 934 << entry_plug->Hmat[0][2] << "\t"
349     << entry_plug->Hmat[1][2] << "\t"
350     << entry_plug->Hmat[2][2] << ";";
351    
352     *outFile[k] << entry_plug->the_integrator->getAdditionalParameters() << endl;
353     }
354 tim 837
355 tim 929 currentIndex = 0;
356 tim 934
357 gezelter 1203 for (i = 0 ; i < mpiSim->getNMolGlobal(); i++ ) {
358 chuckv 913
359 gezelter 417 // Get the Node number which has this atom;
360 chuckv 913
361 tim 1108 which_node = MolToProcMap[i];
362 chuckv 913
363 gezelter 907 if (which_node != 0) {
364 tim 1108
365     if (potatoes[which_node] + 1 >= MAXTAG) {
366 gezelter 916 // The potato was going to exceed the maximum value,
367     // so wrap this processor potato back to 0:
368    
369     potatoes[which_node] = 0;
370 tim 1129 MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0, MPI_COMM_WORLD);
371 gezelter 916
372     }
373    
374     myPotato = potatoes[which_node];
375 tim 1108
376     //recieve the number of integrableObject in current molecule
377     MPI_Recv(&nCurObj, 1, MPI_INT, which_node,
378 gezelter 916 myPotato, MPI_COMM_WORLD, &istatus);
379 tim 1129 myPotato++;
380 gezelter 907
381 tim 1108 for(int l = 0; l < nCurObj; l++){
382 gezelter 916
383 tim 1152 if (potatoes[which_node] + 2 >= MAXTAG) {
384 tim 1108 // The potato was going to exceed the maximum value,
385     // so wrap this processor potato back to 0:
386    
387     potatoes[which_node] = 0;
388 tim 1129 MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0, MPI_COMM_WORLD);
389 tim 1108
390     }
391    
392     MPI_Recv(MPIatomTypeString, MINIBUFFERSIZE, MPI_CHAR, which_node,
393     myPotato, MPI_COMM_WORLD, &istatus);
394    
395     atomTypeString = MPIatomTypeString;
396    
397     myPotato++;
398    
399 tim 1152 MPI_Recv(atomData, 13, MPI_DOUBLE, which_node, myPotato, MPI_COMM_WORLD, &istatus);
400 tim 1108 myPotato++;
401 gezelter 907
402 tim 1152 MPI_Get_count(&istatus, MPI_DOUBLE, &msgLen);
403 tim 1108
404 tim 1152 if(msgLen == 13)
405     isDirectional = 1;
406     else
407     isDirectional = 0;
408 tim 1231
409     // If we've survived to here, format the line:
410 tim 1152
411 tim 1231 if (!isDirectional) {
412    
413     sprintf( writeLine,
414     "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
415     atomTypeString,
416     atomData[0],
417     atomData[1],
418     atomData[2],
419     atomData[3],
420     atomData[4],
421     atomData[5]);
422    
423     strcat( writeLine, "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\n" );
424    
425     }
426     else {
427    
428     sprintf( writeLine,
429     "%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\n",
430     atomTypeString,
431     atomData[0],
432     atomData[1],
433     atomData[2],
434     atomData[3],
435     atomData[4],
436     atomData[5],
437     atomData[6],
438     atomData[7],
439     atomData[8],
440     atomData[9],
441     atomData[10],
442     atomData[11],
443     atomData[12]);
444    
445     }
446    
447     for(k = 0; k < outFile.size(); k++)
448     *outFile[k] << writeLine;
449    
450     }// end for(int l =0)
451 gezelter 916 potatoes[which_node] = myPotato;
452 gezelter 907
453 tim 1231 }
454     else {
455 gezelter 907
456 tim 934 haveError = 0;
457 gezelter 916
458 tim 1108 local_index = indexArray[currentIndex].first;
459 tim 837
460 tim 1108 integrableObjects = (entry_plug->molecules[local_index]).getIntegrableObjects();
461 gezelter 907
462 tim 1108 for(iter= integrableObjects.begin(); iter != integrableObjects.end(); ++iter){
463     sd = *iter;
464     atomTypeString = sd->getType();
465    
466     sd->getPos(pos);
467     sd->getVel(vel);
468    
469 tim 1152 atomData[0] = pos[0];
470     atomData[1] = pos[1];
471     atomData[2] = pos[2];
472 tim 837
473 tim 1152 atomData[3] = vel[0];
474     atomData[4] = vel[1];
475     atomData[5] = vel[2];
476 tim 1108
477     isDirectional = 0;
478 gezelter 916
479 tim 1108 if( sd->isDirectional() ){
480    
481     isDirectional = 1;
482    
483     sd->getQ( q );
484     sd->getJ( ji );
485    
486     for (int j = 0; j < 6 ; j++)
487 tim 1152 atomData[j] = atomData[j];
488 tim 1108
489 tim 1152 atomData[6] = q[0];
490     atomData[7] = q[1];
491     atomData[8] = q[2];
492     atomData[9] = q[3];
493 tim 1108
494 tim 1152 atomData[10] = ji[0];
495     atomData[11] = ji[1];
496     atomData[12] = ji[2];
497 tim 1108 }
498 gezelter 907
499 tim 1231 // If we've survived to here, format the line:
500    
501     if (!isDirectional) {
502    
503     sprintf( writeLine,
504     "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
505     atomTypeString,
506     atomData[0],
507     atomData[1],
508     atomData[2],
509     atomData[3],
510     atomData[4],
511     atomData[5]);
512    
513     strcat( writeLine, "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\n" );
514    
515     }
516     else {
517    
518     sprintf( writeLine,
519     "%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\n",
520     atomTypeString,
521     atomData[0],
522     atomData[1],
523     atomData[2],
524     atomData[3],
525     atomData[4],
526     atomData[5],
527     atomData[6],
528     atomData[7],
529     atomData[8],
530     atomData[9],
531     atomData[10],
532     atomData[11],
533     atomData[12]);
534    
535     }
536    
537     for(k = 0; k < outFile.size(); k++)
538     *outFile[k] << writeLine;
539    
540    
541     }//end for(iter = integrableObject.begin())
542 gezelter 916
543 tim 1108 currentIndex++;
544 tim 926 }
545 tim 1231
546     }//end for(i = 0; i < mpiSim->getNmol())
547 tim 926
548 tim 934 for(k = 0; k < outFile.size(); k++)
549     outFile[k]->flush();
550    
551 gezelter 907 sprintf( checkPointMsg,
552     "Sucessfully took a dump.\n");
553 chuckv 949
554 gezelter 907 MPIcheckPoint();
555 chuckv 949
556 tim 919 delete[] potatoes;
557 chuckv 949
558 gezelter 415 } else {
559 tim 837
560 gezelter 907 // worldRank != 0, so I'm a remote node.
561 gezelter 916
562     // Set my magic potato to 0:
563    
564     myPotato = 0;
565 tim 929 currentIndex = 0;
566 gezelter 907
567 gezelter 1203 for (i = 0 ; i < mpiSim->getNMolGlobal(); i++ ) {
568 gezelter 907
569 tim 1108 // Am I the node which has this integrableObject?
570 gezelter 907
571 tim 1108 if (MolToProcMap[i] == worldRank) {
572 tim 837
573 tim 1108
574     if (myPotato + 1 >= MAXTAG) {
575 chuckv 949
576 gezelter 916 // The potato was going to exceed the maximum value,
577     // so wrap this processor potato back to 0 (and block until
578     // node 0 says we can go:
579 chuckv 949
580 gezelter 916 MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &istatus);
581    
582     }
583 chuckv 949
584 tim 1108 local_index = indexArray[currentIndex].first;
585     integrableObjects = entry_plug->molecules[local_index].getIntegrableObjects();
586    
587     nCurObj = integrableObjects.size();
588    
589     MPI_Send(&nCurObj, 1, MPI_INT, 0,
590     myPotato, MPI_COMM_WORLD);
591 tim 1129 myPotato++;
592 tim 1108
593     for( iter = integrableObjects.begin(); iter != integrableObjects.end(); iter++){
594    
595 tim 1152 if (myPotato + 2 >= MAXTAG) {
596 tim 1108
597     // The potato was going to exceed the maximum value,
598     // so wrap this processor potato back to 0 (and block until
599     // node 0 says we can go:
600    
601     MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &istatus);
602    
603     }
604    
605     sd = *iter;
606    
607     atomTypeString = sd->getType();
608    
609     sd->getPos(pos);
610     sd->getVel(vel);
611    
612 tim 1152 atomData[0] = pos[0];
613     atomData[1] = pos[1];
614     atomData[2] = pos[2];
615 tim 1108
616 tim 1152 atomData[3] = vel[0];
617     atomData[4] = vel[1];
618     atomData[5] = vel[2];
619 tim 1108
620     isDirectional = 0;
621    
622     if( sd->isDirectional() ){
623    
624     isDirectional = 1;
625 tim 920
626 tim 1108 sd->getQ( q );
627     sd->getJ( ji );
628    
629    
630 tim 1152 atomData[6] = q[0];
631     atomData[7] = q[1];
632     atomData[8] = q[2];
633     atomData[9] = q[3];
634 tim 1108
635 tim 1152 atomData[10] = ji[0];
636     atomData[11] = ji[1];
637     atomData[12] = ji[2];
638 tim 1108 }
639 tim 837
640 tim 1108
641     strncpy(MPIatomTypeString, atomTypeString, MINIBUFFERSIZE);
642 tim 837
643 tim 1108 // null terminate the string before sending (just in case):
644     MPIatomTypeString[MINIBUFFERSIZE-1] = '\0';
645 mmeineke 377
646 tim 1108 MPI_Send(MPIatomTypeString, MINIBUFFERSIZE, MPI_CHAR, 0,
647     myPotato, MPI_COMM_WORLD);
648 gezelter 907
649 tim 1108 myPotato++;
650 gezelter 907
651 tim 1108 if (isDirectional) {
652 tim 837
653 tim 1152 MPI_Send(atomData, 13, MPI_DOUBLE, 0,
654 tim 1108 myPotato, MPI_COMM_WORLD);
655    
656     } else {
657 tim 837
658 tim 1152 MPI_Send(atomData, 6, MPI_DOUBLE, 0,
659 tim 1108 myPotato, MPI_COMM_WORLD);
660     }
661 tim 837
662 tim 1108 myPotato++;
663 gezelter 916
664 tim 1108 }
665 gezelter 907
666 tim 1108 currentIndex++;
667 gezelter 907
668     }
669 tim 1108
670 mmeineke 377 }
671 mmeineke 440
672 gezelter 907 sprintf( checkPointMsg,
673 gezelter 916 "Sucessfully took a dump.\n");
674 tim 1129 MPIcheckPoint();
675 gezelter 907
676 tim 1129 }
677    
678    
679 gezelter 907
680 mmeineke 377 #endif // is_mpi
681     }
682 mmeineke 440
683     #ifdef IS_MPI
684    
685     // a couple of functions to let us escape the write loop
686    
687 gezelter 907 void dWrite::DieDieDie( void ){
688 tim 837
689 mmeineke 440 MPI_Finalize();
690     exit (0);
691     }
692    
693     #endif //is_mpi