| 1 | #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 | int isPresent; | 
| 497 |  | 
| 498 | #ifdef IS_MPI | 
| 499 | int done, which_node, which_atom; // loop counter | 
| 500 | int nProc; | 
| 501 | MPI_Status istatus; | 
| 502 | #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 | 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 |  | 
| 534 | #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 |  | 
| 539 | if (!isPresent) | 
| 540 | return; | 
| 541 |  | 
| 542 | inAngFileName = in_name; | 
| 543 | #ifdef IS_MPI | 
| 544 | } | 
| 545 |  | 
| 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 | 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 | //      // 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 |  | 
| 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 | int nTotObjs; // the number of atoms | 
| 717 |  | 
| 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 | int haveError, index; | 
| 736 | int which_node; | 
| 737 |  | 
| 738 | MPI_Status istatus; | 
| 739 | int *MolToProcMap = mpiSim->getMolToProcMap(); | 
| 740 | int localIndex; | 
| 741 | int nCurObj; | 
| 742 | double angleTranfer; | 
| 743 |  | 
| 744 | nTotObjs = simnfo->getTotIntegrableObjects(); | 
| 745 | haveError = 0; | 
| 746 |  | 
| 747 | for (i=0 ; i < mpiSim->getNMolGlobal(); i++) { | 
| 748 | // Get the Node number which has this atom | 
| 749 | which_node = MolToProcMap[i]; | 
| 750 |  | 
| 751 | // 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 | } | 
| 780 | } else { | 
| 781 | // I am SLAVE TO THE MASTER | 
| 782 |  | 
| 783 | 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 | } | 
| 801 | } | 
| 802 | } | 
| 803 | #endif | 
| 804 | } |