ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-3.0/src/io/RestReader.cpp
Revision: 2101
Committed: Thu Mar 10 15:10:24 2005 UTC (19 years, 3 months ago) by chrisfen
File size: 26064 byte(s)
Log Message:
First commit of the new restraints code

File Contents

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