ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/RestraintReader.cpp
Revision: 1778
Committed: Wed Nov 24 18:06:34 2004 UTC (19 years, 7 months ago) by chrisfen
File size: 21432 byte(s)
Log Message:
improved restraints - mpi should work fine

File Contents

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