ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/DumpWriter.cpp
Revision: 1203
Committed: Thu May 27 18:59:17 2004 UTC (20 years, 1 month ago) by gezelter
File size: 15843 byte(s)
Log Message:
Cutoff group changes under MPI

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 tim 934 int i, k;
174 gezelter 916
175 mmeineke 787 #ifdef IS_MPI
176 gezelter 916
177 gezelter 947 /*********************************************************************
178     * Documentation? You want DOCUMENTATION?
179     *
180     * Why all the potatoes below?
181     *
182     * To make a long story short, the original version of DumpWriter
183     * worked in the most inefficient way possible. Node 0 would
184     * poke each of the node for an individual atom's formatted data
185     * as node 0 worked its way down the global index. This was particularly
186     * inefficient since the method blocked all processors at every atom
187     * (and did it twice!).
188     *
189     * An intermediate version of DumpWriter could be described from Node
190     * zero's perspective as follows:
191     *
192     * 1) Have 100 of your friends stand in a circle.
193     * 2) When you say go, have all of them start tossing potatoes at
194     * you (one at a time).
195     * 3) Catch the potatoes.
196     *
197     * It was an improvement, but MPI has buffers and caches that could
198     * best be described in this analogy as "potato nets", so there's no
199     * need to block the processors atom-by-atom.
200     *
201     * This new and improved DumpWriter works in an even more efficient
202     * way:
203     *
204     * 1) Have 100 of your friend stand in a circle.
205     * 2) When you say go, have them start tossing 5-pound bags of
206     * potatoes at you.
207     * 3) Once you've caught a friend's bag of potatoes,
208     * toss them a spud to let them know they can toss another bag.
209     *
210     * How's THAT for documentation?
211     *
212     *********************************************************************/
213    
214 gezelter 916 int *potatoes;
215     int myPotato;
216    
217     int nProc;
218 tim 929 int j, which_node, done, which_atom, local_index, currentIndex;
219 tim 1152 double atomData[13];
220 gezelter 907 int isDirectional;
221     char* atomTypeString;
222 gezelter 910 char MPIatomTypeString[MINIBUFFERSIZE];
223 tim 1108 int nObjects;
224 tim 1152 int msgLen; // the length of message actually recieved at master nodes
225 mmeineke 787 #endif //is_mpi
226    
227 gezelter 1097 double q[4], ji[3];
228 mmeineke 377 DirectionalAtom* dAtom;
229 mmeineke 670 double pos[3], vel[3];
230 tim 1108 int nTotObjects;
231     StuntDouble* sd;
232     char* molName;
233     vector<StuntDouble*> integrableObjects;
234     vector<StuntDouble*>::iterator iter;
235     nTotObjects = entry_plug->getTotIntegrableObjects();
236 mmeineke 377 #ifndef IS_MPI
237 tim 934
238     for(k = 0; k < outFile.size(); k++){
239 tim 1108 *outFile[k] << nTotObjects << "\n";
240 tim 837
241 tim 934 *outFile[k] << currentTime << ";\t"
242     << entry_plug->Hmat[0][0] << "\t"
243     << entry_plug->Hmat[1][0] << "\t"
244     << entry_plug->Hmat[2][0] << ";\t"
245    
246     << entry_plug->Hmat[0][1] << "\t"
247     << entry_plug->Hmat[1][1] << "\t"
248     << entry_plug->Hmat[2][1] << ";\t"
249 tim 837
250 tim 934 << entry_plug->Hmat[0][2] << "\t"
251     << entry_plug->Hmat[1][2] << "\t"
252     << entry_plug->Hmat[2][2] << ";";
253 mmeineke 572
254 tim 934 //write out additional parameters, such as chi and eta
255     *outFile[k] << entry_plug->the_integrator->getAdditionalParameters() << endl;
256     }
257    
258 tim 1108 for( i=0; i< entry_plug->n_mol; i++ ){
259 tim 837
260 tim 1108 integrableObjects = entry_plug->molecules[i].getIntegrableObjects();
261     molName = (entry_plug->compStamps[entry_plug->molecules[i].getStampID()])->getID();
262    
263     for( iter = integrableObjects.begin();iter != integrableObjects.end(); ++iter){
264     sd = *iter;
265     sd->getPos(pos);
266     sd->getVel(vel);
267 mmeineke 377
268 tim 1108 sprintf( tempBuffer,
269     "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
270     sd->getType(),
271     pos[0],
272     pos[1],
273     pos[2],
274     vel[0],
275     vel[1],
276     vel[2]);
277     strcpy( writeLine, tempBuffer );
278 mmeineke 377
279 tim 1108 if( sd->isDirectional() ){
280 tim 837
281 tim 1108 sd->getQ( q );
282     sd->getJ( ji );
283 tim 837
284 tim 1108 sprintf( tempBuffer,
285     "%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\n",
286     q[0],
287     q[1],
288     q[2],
289     q[3],
290     ji[0],
291     ji[1],
292     ji[2]);
293     strcat( writeLine, tempBuffer );
294     }
295     else
296     strcat( writeLine, "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\n" );
297 mmeineke 377 }
298 tim 837
299 tim 1108
300 tim 934 for(k = 0; k < outFile.size(); k++)
301     *outFile[k] << writeLine;
302 tim 1108 }
303 mmeineke 377
304     #else // is_mpi
305 gezelter 416
306 chuckv 913 /* code to find maximum tag value */
307 tim 919
308 tim 920 int *tagub, flag, MAXTAG;
309 chuckv 913 MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, &tagub, &flag);
310     if (flag) {
311 tim 920 MAXTAG = *tagub;
312 chuckv 913 } else {
313     MAXTAG = 32767;
314 gezelter 916 }
315 mmeineke 440
316     int haveError;
317    
318 mmeineke 447 MPI_Status istatus;
319 tim 1108 int nCurObj;
320     int *MolToProcMap = mpiSim->getMolToProcMap();
321 tim 837
322 mmeineke 377 // write out header and node 0's coordinates
323 tim 837
324 mmeineke 377 if( worldRank == 0 ){
325 gezelter 916
326     // Node 0 needs a list of the magic potatoes for each processor;
327    
328 gezelter 1203 nProc = mpiSim->getNProcessors();
329 gezelter 916 potatoes = new int[nProc];
330    
331 tim 934 //write out the comment lines
332 gezelter 916 for (i = 0; i < nProc; i++)
333     potatoes[i] = 0;
334    
335 tim 934 for(k = 0; k < outFile.size(); k++){
336 tim 1108 *outFile[k] << nTotObjects << "\n";
337 tim 837
338 tim 934 *outFile[k] << currentTime << ";\t"
339     << entry_plug->Hmat[0][0] << "\t"
340     << entry_plug->Hmat[1][0] << "\t"
341     << entry_plug->Hmat[2][0] << ";\t"
342 tim 837
343 tim 934 << entry_plug->Hmat[0][1] << "\t"
344     << entry_plug->Hmat[1][1] << "\t"
345     << entry_plug->Hmat[2][1] << ";\t"
346 tim 837
347 tim 934 << entry_plug->Hmat[0][2] << "\t"
348     << entry_plug->Hmat[1][2] << "\t"
349     << entry_plug->Hmat[2][2] << ";";
350    
351     *outFile[k] << entry_plug->the_integrator->getAdditionalParameters() << endl;
352     }
353 tim 837
354 tim 929 currentIndex = 0;
355 tim 934
356 gezelter 1203 for (i = 0 ; i < mpiSim->getNMolGlobal(); i++ ) {
357 chuckv 913
358 gezelter 417 // Get the Node number which has this atom;
359 chuckv 913
360 tim 1108 which_node = MolToProcMap[i];
361 chuckv 913
362 gezelter 907 if (which_node != 0) {
363 tim 1108
364     if (potatoes[which_node] + 1 >= MAXTAG) {
365 gezelter 916 // The potato was going to exceed the maximum value,
366     // so wrap this processor potato back to 0:
367    
368     potatoes[which_node] = 0;
369 tim 1129 MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0, MPI_COMM_WORLD);
370 gezelter 916
371     }
372    
373     myPotato = potatoes[which_node];
374 tim 1108
375     //recieve the number of integrableObject in current molecule
376     MPI_Recv(&nCurObj, 1, MPI_INT, which_node,
377 gezelter 916 myPotato, MPI_COMM_WORLD, &istatus);
378 tim 1129 myPotato++;
379 gezelter 907
380 tim 1108 for(int l = 0; l < nCurObj; l++){
381 gezelter 916
382 tim 1152 if (potatoes[which_node] + 2 >= MAXTAG) {
383 tim 1108 // The potato was going to exceed the maximum value,
384     // so wrap this processor potato back to 0:
385    
386     potatoes[which_node] = 0;
387 tim 1129 MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0, MPI_COMM_WORLD);
388 tim 1108
389     }
390    
391     MPI_Recv(MPIatomTypeString, MINIBUFFERSIZE, MPI_CHAR, which_node,
392     myPotato, MPI_COMM_WORLD, &istatus);
393    
394     atomTypeString = MPIatomTypeString;
395    
396     myPotato++;
397    
398 tim 1152 MPI_Recv(atomData, 13, MPI_DOUBLE, which_node, myPotato, MPI_COMM_WORLD, &istatus);
399 tim 1108 myPotato++;
400 gezelter 907
401 tim 1152 MPI_Get_count(&istatus, MPI_DOUBLE, &msgLen);
402 tim 1108
403 tim 1152 if(msgLen == 13)
404     isDirectional = 1;
405     else
406     isDirectional = 0;
407    
408 gezelter 907 }
409 gezelter 916 potatoes[which_node] = myPotato;
410 gezelter 907
411     } else {
412    
413 tim 934 haveError = 0;
414 gezelter 916
415 tim 1108 local_index = indexArray[currentIndex].first;
416 tim 837
417 tim 1108 integrableObjects = (entry_plug->molecules[local_index]).getIntegrableObjects();
418 gezelter 907
419 tim 1108 for(iter= integrableObjects.begin(); iter != integrableObjects.end(); ++iter){
420     sd = *iter;
421     atomTypeString = sd->getType();
422    
423     sd->getPos(pos);
424     sd->getVel(vel);
425    
426 tim 1152 atomData[0] = pos[0];
427     atomData[1] = pos[1];
428     atomData[2] = pos[2];
429 tim 837
430 tim 1152 atomData[3] = vel[0];
431     atomData[4] = vel[1];
432     atomData[5] = vel[2];
433 tim 1108
434     isDirectional = 0;
435 gezelter 916
436 tim 1108 if( sd->isDirectional() ){
437    
438     isDirectional = 1;
439    
440     sd->getQ( q );
441     sd->getJ( ji );
442    
443     for (int j = 0; j < 6 ; j++)
444 tim 1152 atomData[j] = atomData[j];
445 tim 1108
446 tim 1152 atomData[6] = q[0];
447     atomData[7] = q[1];
448     atomData[8] = q[2];
449     atomData[9] = q[3];
450 tim 1108
451 tim 1152 atomData[10] = ji[0];
452     atomData[11] = ji[1];
453     atomData[12] = ji[2];
454 tim 1108 }
455 gezelter 907
456 tim 1108 }
457 gezelter 916
458 tim 1108 currentIndex++;
459 tim 926 }
460     // If we've survived to here, format the line:
461    
462     if (!isDirectional) {
463    
464 tim 934 sprintf( writeLine,
465 chuckv 949 "%s\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t",
466     atomTypeString,
467 tim 1152 atomData[0],
468     atomData[1],
469     atomData[2],
470     atomData[3],
471     atomData[4],
472     atomData[5]);
473 tim 926
474 chuckv 949 strcat( writeLine, "0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\n" );
475    
476 tim 926 } else {
477    
478 chuckv 949 sprintf( writeLine,
479     "%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",
480     atomTypeString,
481 tim 1152 atomData[0],
482     atomData[1],
483     atomData[2],
484     atomData[3],
485     atomData[4],
486     atomData[5],
487     atomData[6],
488     atomData[7],
489     atomData[8],
490     atomData[9],
491     atomData[10],
492     atomData[11],
493     atomData[12]);
494 gezelter 907
495     }
496 tim 926
497 tim 934 for(k = 0; k < outFile.size(); k++)
498     *outFile[k] << writeLine;
499 mmeineke 377 }
500 tim 926
501 tim 934 for(k = 0; k < outFile.size(); k++)
502     outFile[k]->flush();
503    
504 gezelter 907 sprintf( checkPointMsg,
505     "Sucessfully took a dump.\n");
506 chuckv 949
507 gezelter 907 MPIcheckPoint();
508 chuckv 949
509 tim 919 delete[] potatoes;
510 chuckv 949
511 gezelter 415 } else {
512 tim 837
513 gezelter 907 // worldRank != 0, so I'm a remote node.
514 gezelter 916
515     // Set my magic potato to 0:
516    
517     myPotato = 0;
518 tim 929 currentIndex = 0;
519 gezelter 907
520 gezelter 1203 for (i = 0 ; i < mpiSim->getNMolGlobal(); i++ ) {
521 gezelter 907
522 tim 1108 // Am I the node which has this integrableObject?
523 gezelter 907
524 tim 1108 if (MolToProcMap[i] == worldRank) {
525 tim 837
526 tim 1108
527     if (myPotato + 1 >= MAXTAG) {
528 chuckv 949
529 gezelter 916 // The potato was going to exceed the maximum value,
530     // so wrap this processor potato back to 0 (and block until
531     // node 0 says we can go:
532 chuckv 949
533 gezelter 916 MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &istatus);
534    
535     }
536 chuckv 949
537 tim 1108 local_index = indexArray[currentIndex].first;
538     integrableObjects = entry_plug->molecules[local_index].getIntegrableObjects();
539    
540     nCurObj = integrableObjects.size();
541    
542     MPI_Send(&nCurObj, 1, MPI_INT, 0,
543     myPotato, MPI_COMM_WORLD);
544 tim 1129 myPotato++;
545 tim 1108
546     for( iter = integrableObjects.begin(); iter != integrableObjects.end(); iter++){
547    
548 tim 1152 if (myPotato + 2 >= MAXTAG) {
549 tim 1108
550     // The potato was going to exceed the maximum value,
551     // so wrap this processor potato back to 0 (and block until
552     // node 0 says we can go:
553    
554     MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &istatus);
555    
556     }
557    
558     sd = *iter;
559    
560     atomTypeString = sd->getType();
561    
562     sd->getPos(pos);
563     sd->getVel(vel);
564    
565 tim 1152 atomData[0] = pos[0];
566     atomData[1] = pos[1];
567     atomData[2] = pos[2];
568 tim 1108
569 tim 1152 atomData[3] = vel[0];
570     atomData[4] = vel[1];
571     atomData[5] = vel[2];
572 tim 1108
573     isDirectional = 0;
574    
575     if( sd->isDirectional() ){
576    
577     isDirectional = 1;
578 tim 920
579 tim 1108 sd->getQ( q );
580     sd->getJ( ji );
581    
582    
583 tim 1152 atomData[6] = q[0];
584     atomData[7] = q[1];
585     atomData[8] = q[2];
586     atomData[9] = q[3];
587 tim 1108
588 tim 1152 atomData[10] = ji[0];
589     atomData[11] = ji[1];
590     atomData[12] = ji[2];
591 tim 1108 }
592 tim 837
593 tim 1108
594     strncpy(MPIatomTypeString, atomTypeString, MINIBUFFERSIZE);
595 tim 837
596 tim 1108 // null terminate the string before sending (just in case):
597     MPIatomTypeString[MINIBUFFERSIZE-1] = '\0';
598 mmeineke 377
599 tim 1108 MPI_Send(MPIatomTypeString, MINIBUFFERSIZE, MPI_CHAR, 0,
600     myPotato, MPI_COMM_WORLD);
601 gezelter 907
602 tim 1108 myPotato++;
603 gezelter 907
604 tim 1108 if (isDirectional) {
605 tim 837
606 tim 1152 MPI_Send(atomData, 13, MPI_DOUBLE, 0,
607 tim 1108 myPotato, MPI_COMM_WORLD);
608    
609     } else {
610 tim 837
611 tim 1152 MPI_Send(atomData, 6, MPI_DOUBLE, 0,
612 tim 1108 myPotato, MPI_COMM_WORLD);
613     }
614 tim 837
615 tim 1108 myPotato++;
616 gezelter 916
617 tim 1108 }
618 gezelter 907
619 tim 1108 currentIndex++;
620 gezelter 907
621     }
622 tim 1108
623 mmeineke 377 }
624 mmeineke 440
625 gezelter 907 sprintf( checkPointMsg,
626 gezelter 916 "Sucessfully took a dump.\n");
627 tim 1129 MPIcheckPoint();
628 gezelter 907
629 tim 1129 }
630    
631    
632 gezelter 907
633 mmeineke 377 #endif // is_mpi
634     }
635 mmeineke 440
636     #ifdef IS_MPI
637    
638     // a couple of functions to let us escape the write loop
639    
640 gezelter 907 void dWrite::DieDieDie( void ){
641 tim 837
642 mmeineke 440 MPI_Finalize();
643     exit (0);
644     }
645    
646     #endif //is_mpi