ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/RestReader.cpp
Revision: 2107
Committed: Thu Mar 10 19:11:02 2005 UTC (19 years, 4 months ago) by chrisfen
File size: 25981 byte(s)
Log Message:
Oops...  MPI now builds...

File Contents

# User Rev Content
1 chrisfen 2101 /*
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 "primitives/Molecule.hpp"
56     #include "utils/MemoryUtils.hpp"
57     #include "utils/StringTokenizer.hpp"
58     #include "io/RestReader.hpp"
59     #include "utils/simError.h"
60    
61     #ifdef IS_MPI
62     #include <mpi.h>
63     #define TAKE_THIS_TAG_CHAR 0
64     #define TAKE_THIS_TAG_INT 1
65     #define TAKE_THIS_TAG_DOUBLE 2
66     #endif // is_mpi
67    
68     namespace oopse {
69    
70     RestReader::RestReader( SimInfo* info ) : info_(info){
71    
72     idealName = "idealCrystal.in";
73    
74     isScanned = false;
75    
76     #ifdef IS_MPI
77     if (worldRank == 0) {
78     #endif
79    
80     inIdealFile = fopen(idealName, "r");
81     if(inIdealFile == NULL){
82     sprintf(painCave.errMsg,
83     "RestReader: Cannot open file: %s\n", idealName);
84     painCave.isFatal = 1;
85     simError();
86     }
87    
88     inIdealFileName = idealName;
89     #ifdef IS_MPI
90     }
91     strcpy( checkPointMsg,
92     "File \"idealCrystal.in\" opened successfully for reading." );
93     MPIcheckPoint();
94     #endif
95     return;
96     }
97    
98     RestReader :: ~RestReader( ){
99     #ifdef IS_MPI
100     if (worldRank == 0) {
101     #endif
102     int error;
103     error = fclose( inIdealFile );
104    
105     if( error ){
106     sprintf( painCave.errMsg,
107     "Error closing %s\n", inIdealFileName.c_str());
108     simError();
109     }
110    
111     MemoryUtils::deletePointers(framePos);
112    
113     #ifdef IS_MPI
114     }
115     strcpy( checkPointMsg, "Restraint file closed successfully." );
116     MPIcheckPoint();
117     #endif
118    
119     return;
120     }
121    
122    
123     void RestReader :: readIdealCrystal(){
124    
125     int i;
126     unsigned int j;
127    
128     #ifdef IS_MPI
129     int done, which_node, which_atom; // loop counter
130     #endif //is_mpi
131    
132     const int BUFFERSIZE = 2000; // size of the read buffer
133     int nTotObjs; // the number of atoms
134     char read_buffer[BUFFERSIZE]; //the line buffer for reading
135    
136     char *eof_test; // ptr to see when we reach the end of the file
137     char *parseErr;
138    
139     std::vector<StuntDouble*> integrableObjects;
140    
141     Molecule* mol;
142     StuntDouble* integrableObject;
143     SimInfo::MoleculeIterator mi;
144     Molecule::IntegrableObjectIterator ii;
145    
146     #ifndef IS_MPI
147    
148     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
149     if( eof_test == NULL ){
150     sprintf( painCave.errMsg,
151     "RestraintReader error: error reading 1st line of \"%s\"\n",
152     inIdealFileName.c_str() );
153     painCave.isFatal = 1;
154     simError();
155     }
156    
157     nTotObjs = atoi( read_buffer );
158    
159     if( nTotObjs != info_->getNGlobalIntegrableObjects() ){
160     sprintf( painCave.errMsg,
161     "RestraintReader error. %s nIntegrable, %d, "
162     "does not match the meta-data file's nIntegrable, %d.\n",
163     inIdealFileName.c_str(), nTotObjs,
164     info_->getNGlobalIntegrableObjects());
165     painCave.isFatal = 1;
166     simError();
167     }
168    
169     // skip over the comment line
170     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
171     if(eof_test == NULL){
172     sprintf( painCave.errMsg,
173     "error in reading commment in %s\n", inIdealFileName.c_str());
174     painCave.isFatal = 1;
175     simError();
176     }
177    
178     // parse the ideal crystal lines
179     /*
180     * Note: we assume that there is a one-to-one correspondence between
181     * integrable objects and lines in the idealCrystal.in file. Thermodynamic
182     * integration is only supported for simple rigid bodies.
183     */
184     for (mol = info_->beginMolecule(mi); mol != NULL;
185     mol = info_->nextMolecule(mi)) {
186    
187     for (integrableObject = mol->beginIntegrableObject(ii);
188     integrableObject != NULL;
189     integrableObject = mol->nextIntegrableObject(ii)) {
190    
191     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
192     if(eof_test == NULL){
193     sprintf(painCave.errMsg,
194     "RestReader Error: error in reading file %s\n"
195     "natoms = %d; index = %d\n"
196     "error reading the line from the file.\n",
197     inIdealFileName.c_str(), nTotObjs,
198     integrableObject->getGlobalIndex() );
199     painCave.isFatal = 1;
200     simError();
201     }
202    
203     parseErr = parseIdealLine( read_buffer, integrableObject);
204     if( parseErr != NULL ){
205     strcpy( painCave.errMsg, parseErr );
206     painCave.isFatal = 1;
207     simError();
208     }
209     }
210     }
211    
212     // MPI Section of code..........
213     #else //IS_MPI
214    
215     // first thing first, suspend fatalities.
216     painCave.isEventLoop = 1;
217    
218     int masterNode = 0;
219     int myStatus; // 1 = wakeup & success; 0 = error; -1 = AllDone
220    
221     MPI_Status istatus;
222     int nCurObj;
223     int nitems;
224 chrisfen 2107 int haveError;
225    
226     nTotObjs = info_->getNGlobalIntegrableObjects();
227 chrisfen 2101 haveError = 0;
228    
229     if (worldRank == masterNode) {
230     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
231     if( eof_test == NULL ){
232     sprintf( painCave.errMsg,
233     "Error reading 1st line of %s \n ",inIdealFileName.c_str());
234     painCave.isFatal = 1;
235     simError();
236     }
237    
238     nitems = atoi( read_buffer );
239    
240     // Check to see that the number of integrable objects in the
241     // intial configuration file is the same as derived from the
242     // meta-data file.
243     if( nTotObjs != nitems){
244     sprintf( painCave.errMsg,
245     "RestraintReader Error. %s nIntegrable, %d, "
246     "does not match the meta-data file's nIntegrable, %d.\n",
247     inIdealFileName.c_str(), nTotObjs,
248     info_->getNGlobalIntegrableObjects());
249     painCave.isFatal = 1;
250     simError();
251     }
252    
253     // skip over the comment line
254     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
255     if(eof_test == NULL){
256     sprintf( painCave.errMsg,
257     "error in reading commment in %s\n", inIdealFileName.c_str());
258     painCave.isFatal = 1;
259     simError();
260     }
261    
262     for (i=0 ; i < info_->getNGlobalMolecules(); i++) {
263     int which_node = info_->getMolToProc(i);
264    
265     if(which_node == masterNode){
266     //molecules belong to master node
267    
268 chrisfen 2107 mol = info_->getMoleculeByGlobalIndex(i);
269 chrisfen 2101
270 chrisfen 2107 if(mol == NULL) {
271     sprintf(painCave.errMsg,
272     "RestReader Error: Molecule not found on node %d!\n",
273 chrisfen 2101 worldRank);
274     painCave.isFatal = 1;
275     simError();
276     }
277    
278     for (integrableObject = mol->beginIntegrableObject(ii);
279     integrableObject != NULL;
280     integrableObject = mol->nextIntegrableObject(ii)){
281    
282     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
283    
284     if(eof_test == NULL){
285     sprintf(painCave.errMsg,
286     "RestReader Error: error in reading file %s\n"
287     "natoms = %d; index = %d\n"
288     "error reading the line from the file.\n",
289     inIdealFileName.c_str(), nTotObjs, i );
290     painCave.isFatal = 1;
291     simError();
292     }
293    
294     parseIdealLine(read_buffer, integrableObjects[j]);
295     }
296     } else {
297     //molecule belongs to slave nodes
298    
299     MPI_Recv(&nCurObj, 1, MPI_INT, which_node,
300     TAKE_THIS_TAG_INT, MPI_COMM_WORLD, &istatus);
301    
302     for(j=0; j < nCurObj; j++){
303    
304     eof_test = fgets(read_buffer, sizeof(read_buffer), inIdealFile);
305     if(eof_test == NULL){
306     sprintf(painCave.errMsg,
307     "RestReader Error: error in reading file %s\n"
308     "natoms = %d; index = %d\n"
309     "error reading the line from the file.\n",
310     inIdealFileName.c_str(), nTotObjs, i );
311     painCave.isFatal = 1;
312     simError();
313     }
314    
315 chrisfen 2107 MPI_Send(read_buffer, BUFFERSIZE, MPI_CHAR, which_node,
316 chrisfen 2101 TAKE_THIS_TAG_CHAR, MPI_COMM_WORLD);
317     }
318     }
319     }
320     } else {
321     //actions taken at slave nodes
322     for (i=0 ; i < info_->getNGlobalMolecules(); i++) {
323     int which_node = info_->getMolToProc(i);
324    
325     if(which_node == worldRank){
326     //molecule with global index i belongs to this processor
327    
328 chrisfen 2107 mol = info_->getMoleculeByGlobalIndex(i);
329 chrisfen 2101
330 chrisfen 2107 if(mol == NULL) {
331 chrisfen 2101 sprintf(painCave.errMsg,
332     "RestReader Error: molecule not found on node %d\n",
333     worldRank);
334     painCave.isFatal = 1;
335     simError();
336     }
337    
338 chrisfen 2107 nCurObj = mol->getNIntegrableObjects();
339 chrisfen 2101
340     MPI_Send(&nCurObj, 1, MPI_INT, masterNode,
341     TAKE_THIS_TAG_INT, MPI_COMM_WORLD);
342    
343     for (integrableObject = mol->beginIntegrableObject(ii);
344     integrableObject != NULL;
345     integrableObject = mol->nextIntegrableObject(ii)){
346    
347     MPI_Recv(read_buffer, BUFFERSIZE, MPI_CHAR, masterNode,
348     TAKE_THIS_TAG_CHAR, MPI_COMM_WORLD, &istatus);
349    
350     parseErr = parseIdealLine(read_buffer, integrableObject);
351    
352     if( parseErr != NULL ){
353     strcpy( painCave.errMsg, parseErr );
354     simError();
355     }
356     }
357     }
358     }
359     }
360     #endif
361     }
362    
363     char* RestReader::parseIdealLine(char* readLine, StuntDouble* sd){
364    
365     char *foo; // the pointer to the current string token
366    
367     double pos[3]; // position place holders
368     double q[4]; // the quaternions
369     double RfromQ[3][3]; // the rotation matrix
370     double normalize; // to normalize the reference unit vector
371     double uX, uY, uZ; // reference unit vector place holders
372     double uselessToken;
373     StringTokenizer tokenizer(readLine);
374     int nTokens;
375    
376     nTokens = tokenizer.countTokens();
377    
378     if (nTokens < 14) {
379     sprintf(painCave.errMsg,
380     "RestReader Error: Not enough Tokens.\n");
381     painCave.isFatal = 1;
382     simError();
383     }
384    
385     std::string name = tokenizer.nextToken();
386    
387     if (name != sd->getType()) {
388    
389     sprintf(painCave.errMsg,
390     "RestReader Error: Atom type [%s] in %s does not "
391     "match Atom Type [%s] in .md file.\n",
392     name.c_str(), inIdealFileName.c_str(),
393     sd->getType().c_str());
394     painCave.isFatal = 1;
395     simError();
396     }
397    
398     pos[0] = tokenizer.nextTokenAsDouble();
399     pos[1] = tokenizer.nextTokenAsDouble();
400     pos[2] = tokenizer.nextTokenAsDouble();
401    
402     // store the positions in the stuntdouble as generic data doubles
403     DoubleGenericData* refPosX = new DoubleGenericData();
404     refPosX->setID("refPosX");
405     refPosX->setData(pos[0]);
406     sd->addProperty(refPosX);
407    
408     DoubleGenericData* refPosY = new DoubleGenericData();
409     refPosY->setID("refPosY");
410     refPosY->setData(pos[1]);
411     sd->addProperty(refPosY);
412    
413     DoubleGenericData* refPosZ = new DoubleGenericData();
414     refPosZ->setID("refPosZ");
415     refPosZ->setData(pos[2]);
416     sd->addProperty(refPosZ);
417    
418     // we don't need the velocities
419     uselessToken = tokenizer.nextTokenAsDouble();
420     uselessToken = tokenizer.nextTokenAsDouble();
421     uselessToken = tokenizer.nextTokenAsDouble();
422    
423     if (sd->isDirectional()) {
424    
425     q[0] = tokenizer.nextTokenAsDouble();
426     q[1] = tokenizer.nextTokenAsDouble();
427     q[2] = tokenizer.nextTokenAsDouble();
428     q[3] = tokenizer.nextTokenAsDouble();
429    
430     // now build the rotation matrix and find the unit vectors
431     RfromQ[0][0] = q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3];
432     RfromQ[0][1] = 2*(q[1]*q[2] + q[0]*q[3]);
433     RfromQ[0][2] = 2*(q[1]*q[3] - q[0]*q[2]);
434     RfromQ[1][0] = 2*(q[1]*q[2] - q[0]*q[3]);
435     RfromQ[1][1] = q[0]*q[0] - q[1]*q[1] + q[2]*q[2] - q[3]*q[3];
436     RfromQ[1][2] = 2*(q[2]*q[3] + q[0]*q[1]);
437     RfromQ[2][0] = 2*(q[1]*q[3] + q[0]*q[2]);
438     RfromQ[2][1] = 2*(q[2]*q[3] - q[0]*q[1]);
439     RfromQ[2][2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
440    
441     normalize = sqrt(RfromQ[2][0]*RfromQ[2][0] + RfromQ[2][1]*RfromQ[2][1]
442     + RfromQ[2][2]*RfromQ[2][2]);
443     uX = RfromQ[2][0]/normalize;
444     uY = RfromQ[2][1]/normalize;
445     uZ = RfromQ[2][2]/normalize;
446    
447     // store reference unit vectors as generic data in the stuntdouble
448     DoubleGenericData* refVectorX = new DoubleGenericData();
449     refVectorX->setID("refVectorX");
450     refVectorX->setData(uX);
451     sd->addProperty(refVectorX);
452    
453     DoubleGenericData* refVectorY = new DoubleGenericData();
454     refVectorY->setID("refVectorY");
455     refVectorY->setData(uY);
456     sd->addProperty(refVectorY);
457    
458     DoubleGenericData* refVectorZ = new DoubleGenericData();
459     refVectorZ->setID("refVectorZ");
460     refVectorZ->setData(uZ);
461     sd->addProperty(refVectorZ);
462     }
463    
464     // we don't need the angular velocities, so let's exit the line
465     return NULL;
466     }
467    
468     void RestReader::readZangle(){
469    
470     int i;
471     unsigned int j;
472     int isPresent;
473    
474     Molecule* mol;
475     StuntDouble* integrableObject;
476     SimInfo::MoleculeIterator mi;
477     Molecule::IntegrableObjectIterator ii;
478    
479     #ifdef IS_MPI
480     int done, which_node, which_atom; // loop counter
481     int nProc;
482     MPI_Status istatus;
483     #endif //is_mpi
484    
485     const int BUFFERSIZE = 2000; // size of the read buffer
486     int nTotObjs; // the number of atoms
487     char read_buffer[BUFFERSIZE]; //the line buffer for reading
488    
489     char *eof_test; // ptr to see when we reach the end of the file
490     char *parseErr;
491    
492     std::vector<StuntDouble*> vecParticles;
493     std::vector<double> tempZangs;
494    
495     inAngFileName = info_->getRestFileName();
496    
497     inAngFileName += "0";
498    
499     // open the omega value file for reading
500     #ifdef IS_MPI
501     if (worldRank == 0) {
502     #endif
503     isPresent = 1;
504     inAngFile = fopen(inAngFileName.c_str(), "r");
505     if(!inAngFile){
506     sprintf(painCave.errMsg,
507     "Restraints Warning: %s file is not present\n"
508     "\tAll omega values will be initialized to zero. If the\n"
509     "\tsimulation is starting from the idealCrystal.in reference\n"
510     "\tconfiguration, this is the desired action. If this is not\n"
511     "\tthe case, the energy calculations will be incorrect.\n",
512     inAngFileName.c_str());
513     painCave.severity = OOPSE_WARNING;
514     painCave.isFatal = 0;
515     simError();
516     isPresent = 0;
517     }
518    
519     #ifdef IS_MPI
520     // let the other nodes know the status of the file search
521     MPI_Bcast(&isPresent, 1, MPI_INT, 0, MPI_COMM_WORLD);
522     #endif // is_mpi
523    
524     if (!isPresent) {
525     zeroZangle();
526     return;
527     }
528    
529     #ifdef IS_MPI
530     }
531    
532     // listen to node 0 to see if we should exit this function
533     if (worldRank != 0) {
534     MPI_Bcast(&isPresent, 1, MPI_INT, 0, MPI_COMM_WORLD);
535     if (!isPresent) {
536     zeroZangle();
537     return;
538     }
539     }
540    
541     strcpy( checkPointMsg, "zAngle file opened successfully for reading." );
542     MPIcheckPoint();
543     #endif
544    
545     #ifndef IS_MPI
546    
547     eof_test = fgets(read_buffer, sizeof(read_buffer), inAngFile);
548     if( eof_test == NULL ){
549     sprintf( painCave.errMsg,
550     "RestraintReader error: error reading 1st line of \"%s\"\n",
551     inAngFileName.c_str() );
552     painCave.isFatal = 1;
553     simError();
554     }
555    
556     eof_test = fgets(read_buffer, sizeof(read_buffer), inAngFile);
557     while ( eof_test != NULL ) {
558     // check for and ignore blank lines
559     if ( read_buffer != NULL )
560     tempZangs.push_back( atof(read_buffer) );
561     eof_test = fgets(read_buffer, sizeof(read_buffer), inAngFile);
562     }
563    
564     nTotObjs = info_->getNGlobalIntegrableObjects();
565    
566     if( nTotObjs != tempZangs.size() ){
567     sprintf( painCave.errMsg,
568     "RestraintReader zAngle reading error. %s nIntegrable, %d, "
569     "does not match the meta-data file's nIntegrable, %d.\n",
570     inAngFileName.c_str(), tempZangs.size(), nTotObjs );
571     painCave.isFatal = 1;
572     simError();
573     }
574    
575     // load the zAngles into the integrable objects
576     i = 0;
577     for (mol = info_->beginMolecule(mi); mol != NULL;
578     mol = info_->nextMolecule(mi)) {
579    
580     for (integrableObject = mol->beginIntegrableObject(ii);
581     integrableObject != NULL;
582     integrableObject = mol->nextIntegrableObject(ii)) {
583    
584     integrableObject->setZangle(tempZangs[i]);
585     i++;
586     }
587     }
588    
589     // MPI Section of code..........
590     #else //IS_MPI
591    
592     // first thing first, suspend fatalities.
593     painCave.isEventLoop = 1;
594 chrisfen 2107
595     int masterNode = 0;
596 chrisfen 2101 int myStatus; // 1 = wakeup & success; 0 = error; -1 = AllDone
597 chrisfen 2107 int haveError;
598     int index;
599    
600 chrisfen 2101 int nCurObj;
601     double angleTranfer;
602    
603 chrisfen 2107 nTotObjs = info_->getNGlobalIntegrableObjects();
604 chrisfen 2101 haveError = 0;
605 chrisfen 2107
606     if (worldRank == masterNode) {
607 chrisfen 2101
608     eof_test = fgets(read_buffer, sizeof(read_buffer), inAngFile);
609     if( eof_test == NULL ){
610     sprintf( painCave.errMsg,
611     "Error reading 1st line of %s \n ",inAngFileName.c_str());
612     haveError = 1;
613     simError();
614     }
615    
616     // let node 0 load the temporary angle vector
617     eof_test = fgets(read_buffer, sizeof(read_buffer), inAngFile);
618     while ( eof_test != NULL ) {
619     // check for and ignore blank lines
620     if ( read_buffer != NULL )
621     tempZangs.push_back( atof(read_buffer) );
622     eof_test = fgets(read_buffer, sizeof(read_buffer), inAngFile);
623     }
624    
625     // Check to see that the number of integrable objects in the
626     // intial configuration file is the same as derived from the
627     // meta-data file.
628     if( nTotObjs != tempZangs.size() ){
629     sprintf( painCave.errMsg,
630     "RestraintReader zAngle reading Error. %s nIntegrable, %d, "
631     "does not match the meta-data file's nIntegrable, %d.\n",
632     inAngFileName.c_str(), tempZangs.size(), nTotObjs);
633     haveError= 1;
634     simError();
635     }
636    
637 chrisfen 2107 // At this point, node 0 has a tempZangs vector completed, and
638     // everyone else has nada
639     index = 0;
640 chrisfen 2101
641 chrisfen 2107 for (i=0 ; i < info_->getNGlobalMolecules(); i++) {
642     // Get the Node number which has this atom
643     which_node = info_->getMolToProc(i);
644    
645     if (worldRank == masterNode) {
646     mol = info_->getMoleculeByGlobalIndex(i);
647    
648     if(mol == NULL) {
649     strcpy(painCave.errMsg, "Molecule not found on node 0!");
650     haveError = 1;
651     simError();
652     }
653    
654     for (integrableObject = mol->beginIntegrableObject(ii);
655     integrableObject != NULL;
656     integrableObject = mol->nextIntegrableObject(ii)){
657    
658     integrableObject->setZangle(tempZangs[index]);
659     index++;
660     }
661    
662     } else {
663     // I am MASTER OF THE UNIVERSE, but I don't own this molecule
664    
665     MPI_Recv(&nCurObj, 1, MPI_INT, which_node,
666     TAKE_THIS_TAG_INT, MPI_COMM_WORLD, &istatus);
667    
668     for(j=0; j < nCurObj; j++){
669     angleTransfer = tempZangs[index];
670     MPI_Send(&angleTransfer, 1, MPI_DOUBLE, which_node,
671     TAKE_THIS_TAG_DOUBLE, MPI_COMM_WORLD);
672     index++;
673     }
674    
675     }
676     }
677     } else {
678     // I am SLAVE TO THE MASTER
679     for (i=0 ; i < info_->getNGlobalMolecules(); i++) {
680     int which_node = info_->getMolToProc(i);
681    
682     if (which_node == worldRank) {
683    
684     // BUT I OWN THIS MOLECULE!!!
685    
686     mol = info_->getMoleculeByGlobalIndex(i);
687    
688     if(mol == NULL) {
689     sprintf(painCave.errMsg,
690     "RestReader Error: molecule not found on node %d\n",
691     worldRank);
692     painCave.isFatal = 1;
693 chrisfen 2101 simError();
694     }
695 chrisfen 2107
696     nCurObj = mol->getNIntegrableObjects();
697    
698     MPI_Send(&nCurObj, 1, MPI_INT, 0,
699     TAKE_THIS_TAG_INT, MPI_COMM_WORLD);
700    
701     for (integrableObject = mol->beginIntegrableObject(ii);
702     integrableObject != NULL;
703     integrableObject = mol->nextIntegrableObject(ii)){
704    
705     MPI_Recv(&angleTransfer, 1, MPI_DOUBLE, 0,
706     TAKE_THIS_TAG_DOUBLE, MPI_COMM_WORLD, &istatus);
707    
708     integrableObject->setZangle(angleTransfer);
709     }
710     }
711 chrisfen 2101 }
712 chrisfen 2107 }
713 chrisfen 2101 #endif
714     }
715    
716     void RestReader :: zeroZangle(){
717    
718     int i;
719     unsigned int j;
720     int nTotObjs; // the number of atoms
721    
722     Molecule* mol;
723     StuntDouble* integrableObject;
724     SimInfo::MoleculeIterator mi;
725     Molecule::IntegrableObjectIterator ii;
726    
727     std::vector<StuntDouble*> vecParticles;
728    
729     #ifndef IS_MPI
730     // set all zAngles to 0.0
731     for (mol = info_->beginMolecule(mi); mol != NULL;
732     mol = info_->nextMolecule(mi))
733    
734     for (integrableObject = mol->beginIntegrableObject(ii);
735     integrableObject != NULL;
736     integrableObject = mol->nextIntegrableObject(ii))
737     integrableObject->setZangle( 0.0 );
738    
739    
740     // MPI Section of code..........
741     #else //IS_MPI
742    
743     // first thing first, suspend fatalities.
744     painCave.isEventLoop = 1;
745    
746 chrisfen 2107 int masterNode = 0;
747 chrisfen 2101 int myStatus; // 1 = wakeup & success; 0 = error; -1 = AllDone
748 chrisfen 2107 int haveError;
749 chrisfen 2101 int which_node;
750    
751     MPI_Status istatus;
752 chrisfen 2107
753 chrisfen 2101 int nCurObj;
754     double angleTranfer;
755    
756 chrisfen 2107 nTotObjs = info_->getNGlobalIntegrableObjects();
757 chrisfen 2101 haveError = 0;
758 chrisfen 2107 if (worldRank == masterNode) {
759    
760     for (i=0 ; i < info_->getNGlobalMolecules(); i++) {
761     // Get the Node number which has this atom
762     which_node = info_->getMolToProc(i);
763    
764     // let's let node 0 pass out constant values to all the processors
765     if (worldRank == masterNode) {
766     mol = info_->getMoleculeByGlobalIndex(i);
767    
768     if(mol == NULL) {
769     strcpy(painCave.errMsg, "Molecule not found on node 0!");
770     haveError = 1;
771     simError();
772     }
773    
774     for (integrableObject = mol->beginIntegrableObject(ii);
775     integrableObject != NULL;
776     integrableObject = mol->nextIntegrableObject(ii)){
777    
778     integrableObject->setZangle( 0.0 );
779    
780     }
781    
782     } else {
783     // I am MASTER OF THE UNIVERSE, but I don't own this molecule
784    
785     MPI_Recv(&nCurObj, 1, MPI_INT, which_node,
786     TAKE_THIS_TAG_INT, MPI_COMM_WORLD, &istatus);
787    
788     for(j=0; j < nCurObj; j++){
789     angleTransfer = 0.0;
790     MPI_Send(&angleTransfer, 1, MPI_DOUBLE, which_node,
791     TAKE_THIS_TAG_DOUBLE, MPI_COMM_WORLD);
792    
793     }
794     }
795     }
796     } else {
797     // I am SLAVE TO THE MASTER
798     for (i=0 ; i < info_->getNGlobalMolecules(); i++) {
799     int which_node = info_->getMolToProc(i);
800    
801     if (which_node == worldRank) {
802    
803     // BUT I OWN THIS MOLECULE!!!
804     mol = info_->getMoleculeByGlobalIndex(i);
805    
806     if(mol == NULL) {
807     sprintf(painCave.errMsg,
808     "RestReader Error: molecule not found on node %d\n",
809     worldRank);
810     painCave.isFatal = 1;
811     simError();
812     }
813    
814     nCurObj = mol->getNIntegrableObjects();
815    
816     MPI_Send(&nCurObj, 1, MPI_INT, 0,
817     TAKE_THIS_TAG_INT, MPI_COMM_WORLD);
818    
819     for (integrableObject = mol->beginIntegrableObject(ii);
820     integrableObject != NULL;
821     integrableObject = mol->nextIntegrableObject(ii)){
822    
823 chrisfen 2101 MPI_Recv(&angleTransfer, 1, MPI_DOUBLE, 0,
824     TAKE_THIS_TAG_DOUBLE, MPI_COMM_WORLD, &istatus);
825     vecParticles[j]->setZangle(angleTransfer);
826     }
827     }
828     }
829     }
830     #endif
831     }
832    
833     } // end namespace oopse