ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/RestraintWriter.cpp
Revision: 1772
Committed: Tue Nov 23 22:48:31 2004 UTC (19 years, 7 months ago) by chrisfen
File size: 10034 byte(s)
Log Message:
Improvements to restraints

File Contents

# User Rev Content
1 chrisfen 1772 #define _LARGEFILE_SOURCE64
2     #define _FILE_OFFSET_BITS 64
3    
4     #include <string.h>
5     #include <iostream>
6     #include <fstream>
7     #include <algorithm>
8     #include <utility>
9    
10     #ifdef IS_MPI
11     #include <mpi.h>
12     #include "brains/mpiSimulation.hpp"
13     #endif // is_mpi
14    
15     #include "io/ReadWrite.hpp"
16     #include "utils/simError.h"
17    
18     RestraintWriter::RestraintWriter( SimInfo* the_entry_plug ){
19    
20     entry_plug = the_entry_plug;
21    
22     #ifdef IS_MPI
23     //sort the local atoms by global index
24     sortByGlobalIndex();
25     #endif // is_mpi
26    
27     }
28    
29     RestraintWriter::~RestraintWriter( ){}
30    
31     #ifdef IS_MPI
32    
33     /**
34     * A hook function to load balancing
35     */
36    
37     void RestraintWriter::update(){
38     sortByGlobalIndex();
39     }
40    
41     /**
42     * Auxiliary sorting function
43     */
44    
45     bool indexSortingCriterion2(const pair<int, int>& p1, const pair<int, int>& p2){
46     return p1.second < p2.second;
47     }
48    
49     /**
50     * Sorting the local index by global index
51     */
52    
53     void RestraintWriter::sortByGlobalIndex(){
54     Molecule* mols = entry_plug->molecules;
55     indexArray.clear();
56    
57     for(int i = 0; i < entry_plug->n_mol;i++)
58     indexArray.push_back(make_pair(i, mols[i].getGlobalIndex()));
59    
60     sort(indexArray.begin(), indexArray.end(), indexSortingCriterion2);
61     }
62    
63     #endif
64    
65     void RestraintWriter::writeZangle(double currentTime){
66    
67     ofstream angleOut;
68     vector<ofstream*> fileStreams;
69    
70     #ifdef IS_MPI
71     if(worldRank == 0 ){
72     #endif
73     angleOut.open( entry_plug->zAngleName.c_str(), ios::out | ios::trunc );
74     if( !angleOut ){
75     sprintf( painCave.errMsg,
76     "Could not open \"%s\" for zAngle output.\n",
77     entry_plug->zAngleName.c_str() );
78     painCave.isFatal = 1;
79     simError();
80     }
81     #ifdef IS_MPI
82     }
83     #endif // is_mpi
84    
85     fileStreams.push_back(&angleOut);
86     writeFrame(fileStreams, currentTime);
87    
88     #ifdef IS_MPI
89     angleOut.close();
90     #endif
91    
92     }
93    
94     void RestraintWriter::writeZangle(double currentTime, const char *in_name){
95    
96     ofstream finalOut;
97     vector<ofstream*> fileStreams;
98    
99     #ifdef IS_MPI
100     if(worldRank == 0 ){
101     #endif
102     finalOut.open( in_name, ios::out | ios::trunc );
103     if( !finalOut ){
104     sprintf( painCave.errMsg,
105     "Could not open \"%s\" for zAngle output.\n",
106     in_name );
107     painCave.isFatal = 1;
108     simError();
109     }
110     #ifdef IS_MPI
111     }
112     #endif // is_mpi
113    
114     fileStreams.push_back(&finalOut);
115     writeFrame(fileStreams, currentTime);
116    
117     #ifdef IS_MPI
118     finalOut.close();
119     #endif
120    
121     }
122    
123     void RestraintWriter::writeFrame( vector<ofstream*>& outFile, double currentTime ){
124    
125     const int BUFFERSIZE = 2000;
126     const int MINIBUFFERSIZE = 100;
127    
128     char tempBuffer[BUFFERSIZE];
129     char writeLine[BUFFERSIZE];
130    
131     int i;
132     unsigned int k;
133    
134     #ifdef IS_MPI
135    
136     /*********************************************************************
137     * Documentation? You want DOCUMENTATION?
138     *
139     * Why all the potatoes below?
140     *
141     * To make a long story short, the original version of RestraintWriter
142     * worked in the most inefficient way possible. Node 0 would
143     * poke each of the node for an individual atom's formatted data
144     * as node 0 worked its way down the global index. This was particularly
145     * inefficient since the method blocked all processors at every atom
146     * (and did it twice!).
147     *
148     * An intermediate version of RestraintWriter could be described from Node
149     * zero's perspective as follows:
150     *
151     * 1) Have 100 of your friends stand in a circle.
152     * 2) When you say go, have all of them start tossing potatoes at
153     * you (one at a time).
154     * 3) Catch the potatoes.
155     *
156     * It was an improvement, but MPI has buffers and caches that could
157     * best be described in this analogy as "potato nets", so there's no
158     * need to block the processors atom-by-atom.
159     *
160     * This new and improved RestraintWriter works in an even more efficient
161     * way:
162     *
163     * 1) Have 100 of your friend stand in a circle.
164     * 2) When you say go, have them start tossing 5-pound bags of
165     * potatoes at you.
166     * 3) Once you've caught a friend's bag of potatoes,
167     * toss them a spud to let them know they can toss another bag.
168     *
169     * How's THAT for documentation?
170     *
171     *********************************************************************/
172    
173     int *potatoes;
174     int myPotato;
175    
176     int nProc;
177     int j, which_node, done, which_atom, local_index, currentIndex;
178     double atomData;
179     int isDirectional;
180     char* atomTypeString;
181     char MPIatomTypeString[MINIBUFFERSIZE];
182     int nObjects;
183     int msgLen; // the length of message actually recieved at master nodes
184     #endif //is_mpi
185    
186     double angle;
187     DirectionalAtom* dAtom;
188     int nTotObjects;
189     StuntDouble* sd;
190     char* molName;
191     vector<StuntDouble*> integrableObjects;
192     vector<StuntDouble*>::iterator iter;
193     nTotObjects = entry_plug->getTotIntegrableObjects();
194     #ifndef IS_MPI
195    
196     for(k = 0; k < outFile.size(); k++)
197     *outFile[k] << currentTime << " : omega values at this time\n";
198    
199     for( i=0; i<nTotObjects; i++ ){
200    
201     integrableObjects = entry_plug->molecules[i].getIntegrableObjects();
202    
203     for( iter = integrableObjects.begin();iter != integrableObjects.end(); ++iter){
204     sd = *iter;
205    
206     sprintf( tempBuffer,
207     "%14.10lf\n",
208     sd->getZangle());
209     strcpy( writeLine, tempBuffer );
210    
211     for(k = 0; k < outFile.size(); k++)
212     *outFile[k] << writeLine;
213     }
214    
215     }
216    
217     #else // is_mpi
218    
219     /* code to find maximum tag value */
220    
221     int *tagub, flag, MAXTAG;
222     MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, &tagub, &flag);
223     if (flag) {
224     MAXTAG = *tagub;
225     } else {
226     MAXTAG = 32767;
227     }
228    
229     int haveError;
230    
231     MPI_Status istatus;
232     int nCurObj;
233     int *MolToProcMap = mpiSim->getMolToProcMap();
234    
235     // write out header and node 0's coordinates
236    
237     if( worldRank == 0 ){
238    
239     // Node 0 needs a list of the magic potatoes for each processor;
240    
241     nProc = mpiSim->getNProcessors();
242     potatoes = new int[nProc];
243    
244     //write out the comment lines
245     for (i = 0; i < nProc; i++)
246     potatoes[i] = 0;
247    
248     for(k = 0; k < outFile.size(); k++)
249     *outFile[k] << currentTime << " fs: omega values at this time\n";
250    
251     currentIndex = 0;
252    
253     for (i = 0 ; i < mpiSim->getNMolGlobal(); i++ ) {
254    
255     // Get the Node number which has this atom;
256    
257     which_node = MolToProcMap[i];
258    
259     if (which_node != 0) {
260    
261     if (potatoes[which_node] + 1 >= MAXTAG) {
262     // The potato was going to exceed the maximum value,
263     // so wrap this processor potato back to 0:
264    
265     potatoes[which_node] = 0;
266     MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0,
267     MPI_COMM_WORLD);
268    
269     }
270    
271     myPotato = potatoes[which_node];
272    
273     //recieve the number of integrableObject in current molecule
274     MPI_Recv(&nCurObj, 1, MPI_INT, which_node,
275     myPotato, MPI_COMM_WORLD, &istatus);
276     myPotato++;
277    
278     for(int l = 0; l < nCurObj; l++){
279    
280     if (potatoes[which_node] + 1 >= MAXTAG) {
281     // The potato was going to exceed the maximum value,
282     // so wrap this processor potato back to 0:
283    
284     potatoes[which_node] = 0;
285     MPI_Send(&potatoes[which_node], 1, MPI_INT, which_node, 0,
286     MPI_COMM_WORLD);
287    
288     }
289    
290     MPI_Recv(&atomData, 1, MPI_DOUBLE, which_node, myPotato, MPI_COMM_WORLD, &istatus);
291     myPotato++;
292    
293     // If we've survived to here, format the line:
294     sprintf( writeLine,
295     "%14.10lf\n",
296     atomData);
297    
298     for(k = 0; k < outFile.size(); k++)
299     *outFile[k] << writeLine;
300    
301     }// end for(int l =0)
302     potatoes[which_node] = myPotato;
303    
304     }
305     else {
306    
307     haveError = 0;
308    
309     local_index = indexArray[currentIndex].first;
310    
311     integrableObjects = (entry_plug->molecules[local_index]).getIntegrableObjects();
312    
313     for(iter= integrableObjects.begin(); iter != integrableObjects.end(); ++iter){
314     sd = *iter;
315     atomData = sd->getZangle();
316    
317     // If we've survived to here, format the line:
318    
319     sprintf( writeLine,
320     "%14.10lf\n",
321     atomData);
322    
323     for(k = 0; k < outFile.size(); k++)
324     *outFile[k] << writeLine;
325    
326     }//end for(iter = integrableObject.begin())
327    
328     currentIndex++;
329     }
330    
331     }//end for(i = 0; i < mpiSim->getNmol())
332    
333     for(k = 0; k < outFile.size(); k++)
334     outFile[k]->flush();
335    
336     sprintf( checkPointMsg,
337     "Successfully printed a zAngle.\n");
338    
339     MPIcheckPoint();
340    
341     delete[] potatoes;
342    
343     } else {
344    
345     // worldRank != 0, so I'm a remote node.
346    
347     // Set my magic potato to 0:
348    
349     myPotato = 0;
350     currentIndex = 0;
351    
352     for (i = 0 ; i < mpiSim->getNMolGlobal(); i++ ) {
353    
354     // Am I the node which has this integrableObject?
355    
356     if (MolToProcMap[i] == worldRank) {
357    
358    
359     if (myPotato + 1 >= MAXTAG) {
360    
361     // The potato was going to exceed the maximum value,
362     // so wrap this processor potato back to 0 (and block until
363     // node 0 says we can go:
364    
365     MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &istatus);
366     }
367    
368     local_index = indexArray[currentIndex].first;
369     integrableObjects = entry_plug->molecules[local_index].getIntegrableObjects();
370    
371     nCurObj = integrableObjects.size();
372    
373     MPI_Send(&nCurObj, 1, MPI_INT, 0,
374     myPotato, MPI_COMM_WORLD);
375     myPotato++;
376    
377     for( iter = integrableObjects.begin();
378     iter != integrableObjects.end(); iter++ ){
379    
380     if (myPotato + 1 >= MAXTAG) {
381    
382     // The potato was going to exceed the maximum value,
383     // so wrap this processor potato back to 0 (and block until
384     // node 0 says we can go:
385    
386     MPI_Recv(&myPotato, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &istatus);
387     }
388    
389     sd = *iter;
390    
391     atomData = sd->getZangle();
392    
393     MPI_Send(&atomData, 1, MPI_DOUBLE, 0,
394     myPotato, MPI_COMM_WORLD);
395    
396     myPotato++;
397     }
398    
399     currentIndex++;
400     }
401     }
402    
403     sprintf( checkPointMsg,
404     "Successfully dropped a zAngle.\n");
405     MPIcheckPoint();
406     }
407     #endif // is_mpi
408     }
409