Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

Output.C

Go to the documentation of this file.
00001 
00007 /*
00008    This object outputs the data collected on the master node
00009 */
00010 
00011 #include "largefiles.h"  // must be first!
00012 
00013 #include <string.h>
00014 #include <stdlib.h>
00015 
00016 #include "InfoStream.h"
00017 #include "IMDOutput.h"
00018 #include "Output.h"
00019 #include "dcdlib.h"
00020 #include "strlib.h"
00021 #include "Molecule.h"
00022 #include "Node.h"
00023 #include "Parameters.h"
00024 #include "PDB.h"
00025 #include "SimParameters.h"
00026 #include "Vector.h"
00027 #include "structures.h"
00028 #include "MStream.h"
00029 #include "Communicate.h"
00030 #include "PatchMap.h"
00031 #include "PatchMap.inl"
00032 #include "ScriptTcl.h"
00033 #include "Lattice.h"
00034 #include <fcntl.h>
00035 #include <sys/stat.h>
00036 #ifdef WIN32
00037 #include <io.h>
00038 #endif
00039 
00040 #if defined(WIN32) && !defined(__CYGWIN__)
00041 #define PATHSEPSTR "\\"
00042 #define MKDIR(X) mkdir(X)
00043 #else
00044 #define PATHSEPSTR "/"
00045 #define MKDIR(X) mkdir(X,0777)
00046 #endif
00047 
00048 #define NAMD_write NAMD_write64
00049 // same as write, only does error checking internally
00050 void NAMD_write(int fd, const char *buf, size_t count, const char *errmsg="NAMD_write64") {
00051   while ( count ) {
00052 #if defined(WIN32) && !defined(__CYGWIN__)
00053     long retval = _write(fd,buf,count);
00054 #else
00055     ssize_t retval = write(fd,buf,count);
00056 #endif
00057     if ( retval < 0 && errno == EINTR ) retval = 0;
00058     if ( retval < 0 ) NAMD_err(errmsg);
00059     if ( retval > count ) NAMD_bug("extra bytes written in NAMD_write64()");
00060     buf += retval;
00061     count -= retval;
00062   }
00063 }
00064 
00065 #ifndef O_LARGEFILE
00066 #define O_LARGEFILE 0x0
00067 #endif
00068 
00069 
00070 // These make the NAMD 1 names work in NAMD 2
00071 #define namdMyNode Node::Object()
00072 #define simParams simParameters
00073 #define pdbData pdb
00074 
00075 /************************************************************************/
00076 /*                  */
00077 /*      FUNCTION Output          */
00078 /*                  */
00079 /*  This is the constructor for the Ouput class.  It just sets   */
00080 /*  up some values for the VMD connection.        */
00081 /*                  */
00082 /************************************************************************/
00083 
00084 Output::Output() { }
00085 
00086 /*      END OF FUNCTION Output        */
00087 
00088 /************************************************************************/
00089 /*                  */
00090 /*      FUNCTION ~Output        */
00091 /*                  */
00092 /************************************************************************/
00093 
00094 Output::~Output() { }
00095 
00096 /*      END OF FUNCTION ~Output        */
00097 
00098 /************************************************************************/
00099 /*                  */
00100 /*      FUNCTION coordinate        */
00101 /*                  */
00102 /*   INPUTS:                */
00103 /*  timestep - Timestep coordinates were accumulated for    */
00104 /*  n - This is the number of coordinates accumulated.    */
00105 /*  vel - Array of Vectors containing the velocities    */
00106 /*                  */
00107 /*  This function receives the coordinates accumulated for a given  */
00108 /*   timestep from the Collect object and calls the appropriate output  */
00109 /*   functions.  ALL routines used to output coordinates information    */
00110 /*   should be called from here.          */
00111 /*                  */
00112 /************************************************************************/
00113 
00114 int Output::coordinateNeeded(int timestep)
00115 {
00116   SimParameters *simParams = Node::Object()->simParameters;
00117 
00118   if(simParams->benchTimestep) return 0;
00119 
00120   int positionsNeeded = 0;
00121 
00122   if ( timestep >= 0 ) {
00123 
00124     //  Output a DCD trajectory 
00125     if ( simParams->dcdFrequency &&
00126        ((timestep % simParams->dcdFrequency) == 0) )
00127     { positionsNeeded |= 1; }
00128 
00129     //  Output a restart file
00130     if ( simParams->restartFrequency &&
00131        ((timestep % simParams->restartFrequency) == 0) )
00132     { positionsNeeded |= 2; }
00133 
00134     //  Iteractive MD
00135     if ( simParams->IMDon &&
00136        ( ((timestep % simParams->IMDfreq) == 0) ||
00137          (timestep == simParams->firstTimestep) ) )
00138       { positionsNeeded |= 1; }
00139 
00140   }
00141 
00142   //  Output final coordinates
00143   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN ||
00144                                         timestep == EVAL_MEASURE)
00145   {
00146     positionsNeeded |= 2;
00147   }
00148 
00149   return positionsNeeded;
00150 }
00151 
00152 template <class xVector, class xDone>
00153 void wrap_coor_int(xVector *coor, Lattice &lattice, xDone *done) {
00154   SimParameters *simParams = Node::Object()->simParameters;
00155   if ( *done ) return;
00156   *done = 1;
00157   if ( ! ( simParams->wrapAll || simParams->wrapWater ) ) return;
00158   const int wrapNearest = simParams->wrapNearest;
00159   const int wrapAll = simParams->wrapAll;
00160   Molecule *molecule = Node::Object()->molecule;
00161   int n = molecule->numAtoms;
00162   int i;
00163 #ifndef MEM_OPT_VERSION
00164   Position *con = new Position[n];
00165   for ( i = 0; i < n; ++i ) {
00166     con[i] = 0;
00167     int ci = molecule->get_cluster(i);
00168     con[ci] += coor[i];
00169   }
00170   for ( i = 0; i < n; ++i ) {
00171     if ( ! wrapAll && ! molecule->is_water(i) ) continue;
00172     int ci = molecule->get_cluster(i);
00173     if ( ci == i ) {
00174       Vector coni = con[i] / molecule->get_clusterSize(i);
00175       Vector trans = ( wrapNearest ?
00176         lattice.wrap_nearest_delta(coni) : lattice.wrap_delta(coni) );
00177       con[i] = trans;
00178     }
00179     coor[i] = coor[i] + con[ci];
00180   }
00181   delete [] con;
00182 #endif
00183 }
00184 
00185 void wrap_coor(Vector *coor, Lattice &lattice, double *done) {
00186   wrap_coor_int(coor,lattice,done);
00187 };
00188 
00189 void wrap_coor(FloatVector *coor, Lattice &lattice, float *done) {
00190   wrap_coor_int(coor,lattice,done);
00191 };
00192 
00193 void Output::coordinate(int timestep, int n, Vector *coor, FloatVector *fcoor,
00194                                                         Lattice &lattice)
00195 {
00196   SimParameters *simParams = Node::Object()->simParameters;
00197   double coor_wrapped = 0;
00198   float fcoor_wrapped = 0;
00199 
00200   if ( timestep >= 0 ) {
00201 
00202     //  Output a DCD trajectory 
00203     if ( simParams->dcdFrequency &&
00204        ((timestep % simParams->dcdFrequency) == 0) )
00205     {
00206       wrap_coor(fcoor,lattice,&fcoor_wrapped);
00207       output_dcdfile(timestep, n, fcoor, 
00208           simParams->dcdUnitCell ? &lattice : NULL);
00209     }
00210 
00211     //  Output a restart file
00212     if ( simParams->restartFrequency &&
00213        ((timestep % simParams->restartFrequency) == 0) )
00214     {
00215       iout << "WRITING COORDINATES TO RESTART FILE AT STEP "
00216                                 << timestep << "\n" << endi;
00217       wrap_coor(coor,lattice,&coor_wrapped);
00218       output_restart_coordinates(coor, n, timestep);
00219       iout << "FINISHED WRITING RESTART COORDINATES\n" <<endi;
00220       fflush(stdout);
00221     }
00222 
00223     //  Interactive MD
00224     if ( simParams->IMDon &&
00225        ( ((timestep % simParams->IMDfreq) == 0) ||
00226          (timestep == simParams->firstTimestep) ) )
00227     {
00228       IMDOutput *imd = Node::Object()->imd;
00229       wrap_coor(fcoor,lattice,&fcoor_wrapped);
00230       if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
00231     }
00232 
00233   }
00234 
00235   if (timestep == EVAL_MEASURE)
00236   {
00237 #ifdef NAMD_TCL
00238     wrap_coor(coor,lattice,&coor_wrapped);
00239     Node::Object()->getScript()->measure(coor);
00240 #endif
00241   }
00242 
00243   //  Output final coordinates
00244   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
00245   {
00246     int realstep = ( timestep == FILE_OUTPUT ?
00247           simParams->firstTimestep : simParams->N );
00248     iout << "WRITING COORDINATES TO OUTPUT FILE AT STEP "
00249                                 << realstep << "\n" << endi;
00250     fflush(stdout);
00251     wrap_coor(coor,lattice,&coor_wrapped);
00252     output_final_coordinates(coor, n, realstep);
00253   }
00254 
00255   //  Close trajectory files
00256   if (timestep == END_OF_RUN)
00257   {
00258     if (simParams->dcdFrequency) output_dcdfile(END_OF_RUN,0,0, 
00259         simParams->dcdUnitCell ? &lattice : NULL);
00260   }
00261 
00262 }
00263 /*    END OF FUNCTION coordinate        */
00264 
00265 /************************************************************************/
00266 /*                  */
00267 /*      FUNCTION velocity        */
00268 /*                  */
00269 /*   INPUTS:                */
00270 /*  timestep - Timestep velocities were accumulated for    */
00271 /*  n - This is the number of velocities accumulated.    */
00272 /*  vel - Array of Vectors containing the velocities    */
00273 /*                  */
00274 /*  This function receives the velocities accumulated for a given   */
00275 /*   timestep from the Collect object and calls the appropriate output  */
00276 /*   functions.  ALL routines used to output velocity information should*/
00277 /*   be called from here.            */
00278 /*                  */
00279 /************************************************************************/
00280 
00281 int Output::velocityNeeded(int timestep)
00282 {
00283   SimParameters *simParams = Node::Object()->simParameters;
00284 
00285   if(simParams->benchTimestep) return 0;
00286 
00287   int velocitiesNeeded = 0;
00288 
00289   if ( timestep >= 0 ) {
00290 
00291     //  Output a velocity DCD trajectory
00292     if ( simParams->velDcdFrequency &&
00293        ((timestep % simParams->velDcdFrequency) == 0) )
00294       { velocitiesNeeded |= 1; }
00295 
00296     //  Output a restart file
00297     if ( simParams->restartFrequency &&
00298        ((timestep % simParams->restartFrequency) == 0) )
00299       { velocitiesNeeded |= 2; }
00300 
00301   }
00302 
00303   //  Output final velocities
00304   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
00305   {
00306     velocitiesNeeded |= 2;
00307   }
00308 
00309   return velocitiesNeeded;
00310 }
00311 
00312 void Output::velocity(int timestep, int n, Vector *vel)
00313 {
00314   SimParameters *simParams = Node::Object()->simParameters;
00315 
00316   if ( timestep >= 0 ) {
00317 
00318     //  Output velocity DCD trajectory
00319     if ( simParams->velDcdFrequency &&
00320        ((timestep % simParams->velDcdFrequency) == 0) )
00321     {
00322       output_veldcdfile(timestep, n, vel);
00323     }
00324 
00325   //  Output restart file
00326     if ( simParams->restartFrequency &&
00327        ((timestep % simParams->restartFrequency) == 0) )
00328     {
00329       iout << "WRITING VELOCITIES TO RESTART FILE AT STEP "
00330                                 << timestep << "\n" << endi;
00331       output_restart_velocities(timestep, n, vel);
00332       iout << "FINISHED WRITING RESTART VELOCITIES\n" <<endi;
00333       fflush(stdout);
00334     }
00335 
00336   }
00337 
00338   //  Output final velocities
00339   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
00340   {
00341     int realstep = ( timestep == FILE_OUTPUT ?
00342           simParams->firstTimestep : simParams->N );
00343     iout << "WRITING VELOCITIES TO OUTPUT FILE AT STEP "
00344                                 << realstep << "\n" << endi;
00345     fflush(stdout);
00346     output_final_velocities(realstep, n, vel);
00347   }
00348 
00349   //  Close trajectory files
00350   if (timestep == END_OF_RUN)
00351   {
00352     if (simParams->velDcdFrequency) output_veldcdfile(END_OF_RUN,0,0);
00353     // close force dcd file here since no final force output below
00354     if (simParams->forceDcdFrequency) output_forcedcdfile(END_OF_RUN,0,0);
00355   }
00356 
00357 }
00358 /*      END OF FUNCTION velocity      */
00359 
00360 /************************************************************************/
00361 /*                  */
00362 /*      FUNCTION force */
00363 /*                  */
00364 /*   INPUTS:                */
00365 /*  timestep - Timestep forces were accumulated for    */
00366 /*  n - This is the number of forces accumulated.    */
00367 /*  frc - Array of Vectors containing the forces */
00368 /*                  */
00369 /*  This function receives the forces accumulated for a given   */
00370 /*   timestep from the Collect object and calls the appropriate output  */
00371 /*   functions.  ALL routines used to output force information should*/
00372 /*   be called from here.            */
00373 /*                  */
00374 /************************************************************************/
00375 
00376 int Output::forceNeeded(int timestep)
00377 {
00378   SimParameters *simParams = Node::Object()->simParameters;
00379 
00380   if(simParams->benchTimestep) return 0;
00381 
00382   int forcesNeeded = 0;
00383 
00384   if ( timestep >= 0 ) {
00385 
00386     //  Output a force DCD trajectory
00387     if ( simParams->forceDcdFrequency &&
00388        ((timestep % simParams->forceDcdFrequency) == 0) )
00389       { forcesNeeded |= 1; }
00390 
00391   }
00392 
00393   //  Output forces
00394   if (timestep == FORCE_OUTPUT)
00395   {
00396     forcesNeeded |= 2;
00397   }
00398 
00399   return forcesNeeded;
00400 }
00401 
00402 void Output::force(int timestep, int n, Vector *frc)
00403 {
00404   SimParameters *simParams = Node::Object()->simParameters;
00405 
00406   if ( timestep >= 0 ) {
00407 
00408     //  Output force DCD trajectory
00409     if ( simParams->forceDcdFrequency &&
00410        ((timestep % simParams->forceDcdFrequency) == 0) )
00411     {
00412       output_forcedcdfile(timestep, n, frc);
00413     }
00414 
00415   }
00416 
00417   //  Output forces
00418   if (timestep == FORCE_OUTPUT)
00419   {
00420     int realstep = simParams->firstTimestep;
00421     iout << "WRITING FORCES TO OUTPUT FILE AT STEP "
00422                                 << realstep << "\n" << endi;
00423     fflush(stdout);
00424     output_forces(realstep, n, frc);
00425   }
00426 
00427   //  Trajectory file closed by velocity() above
00428 
00429 }
00430 /*      END OF FUNCTION force */
00431 
00432 /************************************************************************/
00433 /*                  */
00434 /*      FUNCTION output_restart_coordinates    */
00435 /*                  */
00436 /*   INPUTS:                */
00437 /*  coor - Array of vectors containing current positions    */
00438 /*  n - Number of coordinates to output        */
00439 /*  timestep - Timestep for which the coordinates are being written */
00440 /*                  */
00441 /*  This function writes out the current positions of all the atoms */
00442 /*   in PDB format to the restart file specified by the user in the   */
00443 /*   configuration file.            */
00444 /*                  */
00445 /************************************************************************/
00446 
00447 void Output::output_restart_coordinates(Vector *coor, int n, int timestep)
00448 
00449 {
00450   char comment[128];    //  Comment for header of PDB file
00451   char timestepstr[20];
00452 
00453   int baselen = strlen(namdMyNode->simParams->restartFilename);
00454   char *restart_name = new char[baselen+26];
00455 
00456   strcpy(restart_name, namdMyNode->simParams->restartFilename);
00457   if ( namdMyNode->simParams->restartSave ) {
00458     sprintf(timestepstr,".%d",timestep);
00459     strcat(restart_name, timestepstr);
00460   }
00461   strcat(restart_name, ".coor");
00462 
00463   NAMD_backup_file(restart_name,".old");
00464 
00465   //  Check to see if we should generate a binary or PDB file
00466   if (!namdMyNode->simParams->binaryRestart)
00467   {
00468     //  Generate a PDB restart file
00469     sprintf(comment, "RESTART COORDINATES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00470 
00471     namdMyNode->pdbData->set_all_positions(coor);
00472     namdMyNode->pdbData->write(restart_name, comment);
00473   }
00474   else
00475   {
00476     //  Generate a binary restart file
00477     write_binary_file(restart_name, n, coor);
00478   }
00479 
00480   delete [] restart_name;
00481 }
00482 /*      END OF FUNCTION output_restart_coordinates  */
00483 
00484 /************************************************************************/
00485 /*                  */
00486 /*      FUNCTION output_restart_velocities    */
00487 /*                  */
00488 /*   INPUTS:                */
00489 /*  vel - Array of vectors containing current velocities    */
00490 /*  timestep - Timestep for which the velocities are being written  */
00491 /*                  */
00492 /*  This function writes out the current velocites of all the atoms */
00493 /*   in PDB format to the restart file specified by the user in the   */
00494 /*   configuration file.            */
00495 /*                  */
00496 /************************************************************************/
00497 
00498 void Output::output_restart_velocities(int timestep, int n, Vector *vel)
00499 
00500 {
00501   char comment[128];    //  comment for the header of PDB file
00502   char timestepstr[20];
00503 
00504   int baselen = strlen(namdMyNode->simParams->restartFilename);
00505   char *restart_name = new char[baselen+26];
00506 
00507   strcpy(restart_name, namdMyNode->simParams->restartFilename);
00508   if ( namdMyNode->simParams->restartSave ) {
00509     sprintf(timestepstr,".%d",timestep);
00510     strcat(restart_name, timestepstr);
00511   }
00512   strcat(restart_name, ".vel");
00513 
00514   NAMD_backup_file(restart_name,".old");
00515 
00516   //  Check to see if we should write out a PDB or a binary file
00517   if (!namdMyNode->simParams->binaryRestart)
00518   {
00519     //  Write the coordinates to a PDB file.  Multiple them by 20
00520     //  first to make the numbers bigger
00521     sprintf(comment, "RESTART VELOCITIES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00522 
00523     scale_vels(vel, n, PDBVELFACTOR);
00524     namdMyNode->pdbData->set_all_positions(vel);
00525     namdMyNode->pdbData->write(restart_name, comment);
00526     scale_vels(vel, n, PDBVELINVFACTOR);
00527   }
00528   else
00529   {
00530     //  Write the velocities to a binary file
00531     write_binary_file(restart_name, n, vel);
00532   }
00533 
00534   delete [] restart_name;
00535 }
00536 /*      END OF FUNCTION output_restart_velocities  */
00537 
00538 /************************************************************************/
00539 /*                  */
00540 /*      FUNCTION output_dcdfile        */
00541 /*                  */
00542 /*   INPUTS:                */
00543 /*  timestep - Current timestep          */
00544 /*  n - Number of atoms in simulation        */
00545 /*  coor - Coordinate vectors for all atoms        */
00546 /*  lattice - periodic cell data; NULL if not to be written */
00547 /*                  */
00548 /*  This function maintains the interface between the Output object */
00549 /*   and the dcd writing routines contained in dcdlib.      */
00550 /*                  */
00551 /************************************************************************/
00552 
00553 #define RAD2DEG 180.0/3.14159265359
00554 
00555 void Output::output_dcdfile(int timestep, int n, FloatVector *coor,
00556     const Lattice *lattice)
00557 
00558 {
00559   static Bool first=TRUE;  //  Flag indicating first call
00560   static int fileid;  //  File id for the dcd file
00561 
00562   static float *x, *y, *z; // Arrays to hold x, y, and z arrays
00563   
00564   int i;      //  Loop counter
00565   int ret_code;    //  Return code from DCD calls
00566   SimParameters *simParams = namdMyNode->simParams;
00567 
00568   //  If this is the last time we will be writing coordinates,
00569   //  close the file before exiting
00570   if ( timestep == END_OF_RUN ) {
00571     if ( ! first ) {
00572       iout << "CLOSING COORDINATE DCD FILE\n" << endi;
00573       close_dcd_write(fileid);
00574     } else {
00575       iout << "COORDINATE DCD FILE WAS NOT CREATED\n" << endi;
00576     }
00577     return;
00578   }
00579 
00580   if (first)
00581   {
00582     //  Allocate x, y, and z arrays since the DCD file routines
00583     //  need them passed as three independant arrays to be
00584     //  efficient
00585     x = new float[n];
00586     y = new float[n];
00587     z = new float[n];
00588 
00589     if ( (x==NULL) || (y==NULL) || (z==NULL) )
00590     {
00591       NAMD_err("memory allocation failed in Output::output_dcdfile");
00592     }
00593 
00594     //  Open the DCD file
00595     iout << "OPENING COORDINATE DCD FILE\n" << endi;
00596 
00597     fileid=open_dcd_write(simParams->dcdFilename);
00598 
00599     if (fileid == DCD_FILEEXISTS)
00600     {
00601       char err_msg[257];
00602 
00603       sprintf(err_msg, "DCD file %s already exists!!",
00604         simParams->dcdFilename);
00605 
00606       NAMD_err(err_msg);
00607     }
00608     else if (fileid < 0)
00609     {
00610       char err_msg[257];
00611 
00612       sprintf(err_msg, "Couldn't open DCD file %s",
00613         simParams->dcdFilename);
00614 
00615       NAMD_err(err_msg);
00616     }
00617 
00618     int NSAVC, NFILE, NPRIV, NSTEP;
00619     NSAVC = simParams->dcdFrequency;
00620     NPRIV = timestep;
00621     NSTEP = NPRIV - NSAVC;
00622     NFILE = 0;
00623 
00624     //  Write out the header
00625     ret_code = write_dcdheader(fileid, 
00626         simParams->dcdFilename,
00627         n, NFILE, NPRIV, NSAVC, NSTEP,
00628         simParams->dt/TIMEFACTOR, lattice != NULL);
00629 
00630 
00631     if (ret_code<0)
00632     {
00633       NAMD_err("Writing of DCD header failed!!");
00634     }
00635 
00636     first = FALSE;
00637   }
00638 
00639   //  Copy the coordinates for output
00640   for (i=0; i<n; i++)
00641   {
00642     x[i] = coor[i].x;
00643     y[i] = coor[i].y;
00644     z[i] = coor[i].z;
00645   }
00646 
00647   //  Write out the values for this timestep
00648   iout << "WRITING COORDINATES TO DCD FILE AT STEP "
00649         << timestep << "\n" << endi;
00650   fflush(stdout);
00651   if (lattice) {
00652     double unitcell[6];
00653     if (lattice->a_p() && lattice->b_p() && lattice->c_p()) {
00654       const Vector &a=lattice->a();
00655       const Vector &b=lattice->b();
00656       const Vector &c=lattice->c();
00657       unitcell[0] = a.length();
00658       unitcell[2] = b.length();
00659       unitcell[5] = c.length();
00660       double cosAB = (a*b)/(unitcell[0]*unitcell[2]);
00661       double cosAC = (a*c)/(unitcell[0]*unitcell[5]);
00662       double cosBC = (b*c)/(unitcell[2]*unitcell[5]);
00663       if (cosAB > 1.0) cosAB = 1.0; else if (cosAB < -1.0) cosAB = -1.0;
00664       if (cosAC > 1.0) cosAC = 1.0; else if (cosAC < -1.0) cosAC = -1.0;
00665       if (cosBC > 1.0) cosBC = 1.0; else if (cosBC < -1.0) cosBC = -1.0;
00666       unitcell[1] = cosAB;
00667       unitcell[3] = cosAC;
00668       unitcell[4] = cosBC;
00669     } else {
00670       unitcell[0] = unitcell[2] = unitcell[5] = 1.0;
00671       unitcell[1] = unitcell[3] = unitcell[4] = 0.0;
00672     }
00673     ret_code = write_dcdstep(fileid, n, x, y, z, unitcell);
00674   } else {
00675     ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
00676   }
00677   if (ret_code < 0)
00678   {
00679     NAMD_err("Writing of DCD step failed!!");
00680   }
00681 
00682 }
00683 /*      END OF FUNCTION output_dcdfile      */
00684 
00685 /************************************************************************/
00686 /*                  */
00687 /*      FUNCTION output_final_coordinates    */
00688 /*                  */
00689 /*   INPUTS:                */
00690 /*  coor - Array of vectors containing final coordinates    */
00691 /*  n - Number of coordinates to output        */
00692 /*  timestep - Timestep that coordinates are being written in  */
00693 /*                  */
00694 /*  This function writes out the final coordinates for the    */
00695 /*   simulation in PDB format to the file specified in the config  */
00696 /*   file.                */
00697 /*                  */
00698 /************************************************************************/
00699 
00700 void Output::output_final_coordinates(Vector *coor, int n, int timestep)
00701 
00702 {
00703   char output_name[140];  //  Output filename
00704   char comment[128];    //  comment for PDB header
00705 
00706   //  Built the output filename
00707   strcpy(output_name, namdMyNode->simParams->outputFilename);
00708   strcat(output_name, ".coor");
00709 
00710   NAMD_backup_file(output_name);
00711 
00712   //  Check to see if we should write out a binary file or a
00713   //  PDB file
00714   if (!namdMyNode->simParams->binaryOutput)
00715   {
00716     sprintf(comment, "FINAL COORDINATES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00717 
00718     namdMyNode->pdbData->set_all_positions(coor);
00719     namdMyNode->pdbData->write(output_name, comment);
00720   }
00721   else
00722   {
00723     //  Write the velocities to a binary file
00724     write_binary_file(output_name, n, coor);
00725   }
00726 }
00727 /*    END OF FUNCTION output_final_coordinates    */
00728 
00729 /************************************************************************/
00730 /*                  */
00731 /*      FUNCTION output_final_velocities    */
00732 /*                  */
00733 /*   INPUTS:                */
00734 /*  vel - Array of vectors containing final velocities    */
00735 /*  timestep - Timestep that vleocities are being written in  */
00736 /*                  */
00737 /*  This function writes out the final vleocities for the    */
00738 /*   simulation in PDB format to the file specified in the config  */
00739 /*   file.                */
00740 /*                  */
00741 /************************************************************************/
00742 
00743 void Output::output_final_velocities(int timestep, int n, Vector *vel)
00744 
00745 {
00746   char output_name[140];  //  Output filename
00747   char comment[128];    //  Comment for PDB header
00748 
00749   //  Build the output filename
00750   strcpy(output_name, namdMyNode->simParams->outputFilename);
00751   strcat(output_name, ".vel");
00752 
00753   NAMD_backup_file(output_name);
00754 
00755   //  Check to see if we should write a PDB or binary file
00756   if (!(namdMyNode->simParams->binaryOutput))
00757   {
00758     //  Write the final velocities to a PDB file
00759     sprintf(comment, "FINAL VELOCITIES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00760 
00761     scale_vels(vel, n, PDBVELFACTOR);
00762     namdMyNode->pdbData->set_all_positions(vel);
00763     namdMyNode->pdbData->write(output_name, comment);
00764     scale_vels(vel, n, PDBVELINVFACTOR);
00765   }
00766   else
00767   {
00768     //  Write the coordinates to a binary file
00769     write_binary_file(output_name, n, vel);
00770   }
00771 
00772 }
00773 /*      END OF FUNCTION output_final_velocities    */
00774 
00775 /************************************************************************/
00776 /*                  */
00777 /*      FUNCTION output_veldcdfile      */
00778 /*                  */
00779 /*   INPUTS:                */
00780 /*  timestep - Current timestep          */
00781 /*  n - Number of atoms in simulation        */
00782 /*  coor - velocity vectors for all atoms        */
00783 /*                  */
00784 /*  This function maintains the interface between the Output object */
00785 /*   and the dcd writing routines contained in dcdlib.  This fucntion   */
00786 /*   writes out the velocity vectors in DCD format.      */
00787 /*                  */
00788 /************************************************************************/
00789 
00790 void Output::output_veldcdfile(int timestep, int n, Vector *vel)
00791 
00792 {
00793   static Bool first=TRUE;  //  Flag indicating first call
00794   static int fileid;  //  File id for the dcd file
00795   static float *x, *y, *z; // Arrays to hold x, y, and z arrays
00796   int i;      //  Loop counter
00797   int ret_code;    //  Return code from DCD calls
00798   SimParameters *simParams = Node::Object()->simParameters;
00799 
00800   //  If this is the last time we will be writing coordinates,
00801   //  close the file before exiting
00802   if ( timestep == END_OF_RUN ) {
00803     if ( ! first ) {
00804       iout << "CLOSING VELOCITY DCD FILE\n" << endi;
00805       close_dcd_write(fileid);
00806     } else {
00807       iout << "VELOCITY DCD FILE WAS NOT CREATED\n" << endi;
00808     }
00809     return;
00810   }
00811 
00812   if (first)
00813   {
00814     //  Allocate x, y, and z arrays since the DCD file routines
00815     //  need them passed as three independant arrays to be
00816     //  efficient
00817     x = new float[n];
00818     y = new float[n];
00819     z = new float[n];
00820 
00821     if ( (x==NULL) || (y==NULL) || (z==NULL) )
00822     {
00823       NAMD_err("memory allocation failed in Output::output_veldcdfile");
00824     }
00825 
00826     //  Open the DCD file
00827     iout << "OPENING VELOCITY DCD FILE\n" << endi;
00828 
00829     fileid=open_dcd_write(namdMyNode->simParams->velDcdFilename);
00830 
00831     if (fileid == DCD_FILEEXISTS)
00832     {
00833       char err_msg[257];
00834 
00835       sprintf(err_msg, "Velocity DCD file %s already exists!!",
00836         namdMyNode->simParams->velDcdFilename);
00837 
00838       NAMD_err(err_msg);
00839     }
00840     else if (fileid < 0)
00841     {
00842       char err_msg[257];
00843 
00844       sprintf(err_msg, "Couldn't open velocity DCD file %s",
00845         namdMyNode->simParams->velDcdFilename);
00846 
00847       NAMD_err(err_msg);
00848     }
00849 
00850     int NSAVC, NFILE, NPRIV, NSTEP;
00851     NSAVC = simParams->velDcdFrequency;
00852     NPRIV = timestep;
00853     NSTEP = NPRIV - NSAVC;
00854     NFILE = 0;
00855 
00856     //  Write out the header
00857     const int with_unitcell = 0;
00858     ret_code = write_dcdheader(fileid, 
00859         simParams->velDcdFilename,
00860         n, NFILE, NPRIV, NSAVC, NSTEP,
00861         simParams->dt/TIMEFACTOR, with_unitcell);
00862 
00863 
00864     if (ret_code<0)
00865     {
00866       NAMD_err("Writing of velocity DCD header failed!!");
00867     }
00868 
00869     first = FALSE;
00870   }
00871 
00872   //  Copy the coordinates for output
00873   for (i=0; i<n; i++)
00874   {
00875     x[i] = vel[i].x;
00876     y[i] = vel[i].y;
00877     z[i] = vel[i].z;
00878   }
00879 
00880   //  Write out the values for this timestep
00881   iout << "WRITING VELOCITIES TO DCD FILE AT STEP "
00882         << timestep << "\n" << endi;
00883   fflush(stdout);
00884   ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
00885 
00886   if (ret_code < 0)
00887   {
00888     NAMD_err("Writing of velocity DCD step failed!!");
00889   }
00890 
00891 }
00892 /*      END OF FUNCTION output_veldcdfile    */
00893 
00894 /************************************************************************/
00895 /*                  */
00896 /*      FUNCTION output_forces    */
00897 /*                  */
00898 /*   INPUTS:                */
00899 /*  frc - Array of vectors containing final forces */
00900 /*  timestep - Timestep that vleocities are being written in  */
00901 /*                  */
00902 /*  This function writes out the final vleocities for the    */
00903 /*   simulation in PDB format to the file specified in the config  */
00904 /*   file.                */
00905 /*                  */
00906 /************************************************************************/
00907 
00908 void Output::output_forces(int timestep, int n, Vector *frc)
00909 
00910 {
00911   char output_name[140];  //  Output filename
00912   char comment[128];    //  Comment for PDB header
00913 
00914   //  Build the output filename
00915   strcpy(output_name, namdMyNode->simParams->outputFilename);
00916   strcat(output_name, ".force");
00917 
00918   NAMD_backup_file(output_name);
00919 
00920   //  Check to see if we should write a PDB or binary file
00921   if (!(namdMyNode->simParams->binaryOutput))
00922   {
00923     //  Write the forces to a PDB file
00924     sprintf(comment, "FORCES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00925 
00926     namdMyNode->pdbData->set_all_positions(frc);
00927     namdMyNode->pdbData->write(output_name, comment);
00928   }
00929   else
00930   {
00931     //  Write the coordinates to a binary file
00932     write_binary_file(output_name, n, frc);
00933   }
00934 
00935 }
00936 /*      END OF FUNCTION output_forces */
00937 
00938 /************************************************************************/
00939 /*                  */
00940 /*      FUNCTION output_forcedcdfile      */
00941 /*                  */
00942 /*   INPUTS:                */
00943 /*  timestep - Current timestep          */
00944 /*  n - Number of atoms in simulation        */
00945 /*  frc - force vectors for all atoms        */
00946 /*                  */
00947 /*  This function maintains the interface between the Output object */
00948 /*   and the dcd writing routines contained in dcdlib.  This fucntion   */
00949 /*   writes out the force vectors in DCD format.      */
00950 /*                  */
00951 /************************************************************************/
00952 
00953 void Output::output_forcedcdfile(int timestep, int n, Vector *frc)
00954 
00955 {
00956   static Bool first=TRUE;  //  Flag indicating first call
00957   static int fileid;  //  File id for the dcd file
00958   static float *x, *y, *z; // Arrays to hold x, y, and z arrays
00959   int i;      //  Loop counter
00960   int ret_code;    //  Return code from DCD calls
00961   SimParameters *simParams = Node::Object()->simParameters;
00962 
00963   //  If this is the last time we will be writing coordinates,
00964   //  close the file before exiting
00965   if ( timestep == END_OF_RUN ) {
00966     if ( ! first ) {
00967       iout << "CLOSING FORCE DCD FILE\n" << endi;
00968       close_dcd_write(fileid);
00969     } else {
00970       iout << "FORCE DCD FILE WAS NOT CREATED\n" << endi;
00971     }
00972     return;
00973   }
00974 
00975   if (first)
00976   {
00977     //  Allocate x, y, and z arrays since the DCD file routines
00978     //  need them passed as three independant arrays to be
00979     //  efficient
00980     x = new float[n];
00981     y = new float[n];
00982     z = new float[n];
00983 
00984     if ( (x==NULL) || (y==NULL) || (z==NULL) )
00985     {
00986       NAMD_err("memory allocation failed in Output::output_forcedcdfile");
00987     }
00988 
00989     //  Open the DCD file
00990     iout << "OPENING FORCE DCD FILE\n" << endi;
00991 
00992     fileid=open_dcd_write(namdMyNode->simParams->forceDcdFilename);
00993 
00994     if (fileid == DCD_FILEEXISTS)
00995     {
00996       char err_msg[257];
00997 
00998       sprintf(err_msg, "Force DCD file %s already exists!!",
00999         namdMyNode->simParams->forceDcdFilename);
01000 
01001       NAMD_err(err_msg);
01002     }
01003     else if (fileid < 0)
01004     {
01005       char err_msg[257];
01006 
01007       sprintf(err_msg, "Couldn't open force DCD file %s",
01008         namdMyNode->simParams->forceDcdFilename);
01009 
01010       NAMD_err(err_msg);
01011     }
01012 
01013     int NSAVC, NFILE, NPRIV, NSTEP;
01014     NSAVC = simParams->forceDcdFrequency;
01015     NPRIV = timestep;
01016     NSTEP = NPRIV - NSAVC;
01017     NFILE = 0;
01018 
01019     //  Write out the header
01020     const int with_unitcell = 0;
01021     ret_code = write_dcdheader(fileid, 
01022         simParams->forceDcdFilename,
01023         n, NFILE, NPRIV, NSAVC, NSTEP,
01024         simParams->dt/TIMEFACTOR, with_unitcell);
01025 
01026 
01027     if (ret_code<0)
01028     {
01029       NAMD_err("Writing of force DCD header failed!!");
01030     }
01031 
01032     first = FALSE;
01033   }
01034 
01035   //  Copy the coordinates for output
01036   for (i=0; i<n; i++)
01037   {
01038     x[i] = frc[i].x;
01039     y[i] = frc[i].y;
01040     z[i] = frc[i].z;
01041   }
01042 
01043   //  Write out the values for this timestep
01044   iout << "WRITING FORCES TO DCD FILE AT STEP "
01045         << timestep << "\n" << endi;
01046   fflush(stdout);
01047   ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
01048 
01049   if (ret_code < 0)
01050   {
01051     NAMD_err("Writing of force DCD step failed!!");
01052   }
01053 
01054 }
01055 /*      END OF FUNCTION output_forcedcdfile    */
01056 
01057 /************************************************************************/
01058 /*                  */
01059 /*      FUNCTION write_binary_file      */
01060 /*                  */
01061 /*   INPUTS:                */
01062 /*  fname - file name to write velocities to      */
01063 /*  n - Number of atoms in system          */
01064 /*  vels - Array of vectors            */
01065 /*                  */
01066 /*  This function writes out vectors in binary format to    */
01067 /*   the specified file.            */
01068 /*                  */
01069 /************************************************************************/
01070 
01071 void Output::write_binary_file(char *fname, int n, Vector *vecs)
01072 
01073 {
01074   char errmsg[256];
01075   int fd;    //  File descriptor
01076   int32 n32 = n;
01077 
01078   //  open the file and die if the open fails
01079 #ifdef WIN32
01080   if ( (fd = _open(fname, O_WRONLY|O_CREAT|O_EXCL|O_BINARY|O_LARGEFILE,_S_IREAD|_S_IWRITE)) < 0)
01081 #else
01082 #ifdef NAMD_NO_O_EXCL
01083   if ( (fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE,
01084 #else
01085   if ( (fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE,
01086 #endif
01087                            S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
01088 #endif
01089   {
01090     sprintf(errmsg, "Unable to open binary file %s", fname);
01091     NAMD_err(errmsg);
01092   }
01093 
01094   sprintf(errmsg, "Error on write to binary file %s", fname);
01095 
01096   //  Write out the number of atoms and the vectors
01097   NAMD_write(fd, (char *) &n32, sizeof(int32), errmsg);
01098   NAMD_write(fd, (char *) vecs, sizeof(Vector)*n, errmsg);
01099 
01100 #ifdef WIN32
01101   if ( _close(fd) )
01102 #else
01103   if ( close(fd) )
01104 #endif
01105   {
01106     sprintf(errmsg, "Error on closing binary file %s", fname);
01107     NAMD_err(errmsg);
01108   }
01109 }
01110 /*      END OF FUNCTION write_binary_file    */
01111 
01112 /************************************************************************/
01113 /*                  */
01114 /*      FUNCTION scale_vels        */
01115 /*                  */
01116 /*   INPUTS:                */
01117 /*  v - Array of velocity vectors          */
01118 /*  n - Number of atoms in system          */
01119 /*  fact - Scaling factor            */
01120 /*                  */
01121 /*  This function scales all the vectors passed in by a constant  */
01122 /*   factor.  This is used before writing out velocity vectors that  */
01123 /*   need to be resized.            */
01124 /*                  */
01125 /************************************************************************/
01126 
01127 void Output::scale_vels(Vector *v, int n, Real fact)
01128 
01129 {
01130   int i;
01131 
01132   for (i=0; i<n; i++)
01133   {
01134     v[i].x *= fact;
01135     v[i].y *= fact;
01136     v[i].z *= fact;
01137   }
01138 }
01139 /*      END OF FUNCTION scale_vels      */
01140 
01141 
01142 #ifdef MEM_OPT_VERSION
01144 void ParOutput::velocityMaster(int timestep, int n){
01145     SimParameters *simParams = Node::Object()->simParameters;
01146 
01147     if ( timestep >= 0 ) {
01148 
01149       //  Output velocity DCD trajectory
01150       if ( simParams->velDcdFrequency &&
01151          ((timestep % simParams->velDcdFrequency) == 0) )
01152       {         
01153         output_veldcdfile_master(timestep, n);        
01154       }
01155 
01156     //  Output restart file
01157       if ( simParams->restartFrequency &&
01158          ((timestep % simParams->restartFrequency) == 0) )
01159       {
01160         iout << "WRITING VELOCITIES TO RESTART FILE AT STEP "
01161                   << timestep << "\n" << endi;
01162         output_restart_velocities_master(timestep, n);
01163         iout << "FINISHED WRITING RESTART VELOCITIES\n" <<endi;
01164         fflush(stdout);
01165       }
01166 
01167     }
01168 
01169     //  Output final velocities
01170     if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
01171     {
01172       int realstep = ( timestep == FILE_OUTPUT ?
01173           simParams->firstTimestep : simParams->N );
01174       iout << "WRITING VELOCITIES TO OUTPUT FILE AT STEP "
01175                   << realstep << "\n" << endi;
01176       fflush(stdout);
01177       output_final_velocities_master(n);
01178     }
01179 
01180     //  Close trajectory files
01181     if (timestep == END_OF_RUN)
01182     {
01183       if (simParams->velDcdFrequency) output_veldcdfile_master(END_OF_RUN,0);
01184       if (simParams->forceDcdFrequency) output_forcedcdfile_master(END_OF_RUN,0);
01185     }
01186 
01187 }
01188 
01189 //output atoms' velocities from id fID to tID.
01190 void ParOutput::velocitySlave(int timestep, int fID, int tID, Vector *vecs){
01191     SimParameters *simParams = Node::Object()->simParameters;
01192 
01193     if ( timestep >= 0 ) {
01194 
01195       //  Output velocity DCD trajectory
01196       if ( simParams->velDcdFrequency &&
01197          ((timestep % simParams->velDcdFrequency) == 0) )
01198       {         
01199         output_veldcdfile_slave(timestep, fID, tID, vecs);
01200       }
01201 
01202     //  Output restart file
01203       if ( simParams->restartFrequency &&
01204          ((timestep % simParams->restartFrequency) == 0) )
01205       {          
01206           int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
01207           output_restart_velocities_slave(timestep, fID, tID, vecs, offset);     
01208       }
01209 
01210     }
01211 
01212     //  Output final velocities
01213     if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
01214     {
01215         int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
01216         output_final_velocities_slave(fID, tID, vecs, offset);
01217     }
01218 
01219     //  Close trajectory files
01220     if (timestep == END_OF_RUN)
01221     {
01222       if (simParams->velDcdFrequency) output_veldcdfile_slave(END_OF_RUN, 0, 0, NULL);
01223       if (simParams->forceDcdFrequency) output_forcedcdfile_slave(END_OF_RUN, 0, 0, NULL);
01224     }
01225 }
01226 
01227 void ParOutput::output_veldcdfile_master(int timestep, int n){
01228     int ret_code;    //  Return code from DCD calls
01229     SimParameters *simParams = Node::Object()->simParameters;
01230 
01231     //  If this is the last time we will be writing coordinates,
01232     //  close the file before exiting
01233     if ( timestep == END_OF_RUN ) {
01234       if ( ! veldcdFirst ) {
01235         iout << "CLOSING VELOCITY DCD FILE\n" << endi;
01236         close_dcd_write(veldcdFileID);
01237       } else {
01238         iout << "VELOCITY DCD FILE WAS NOT CREATED\n" << endi;
01239       }
01240       return;      
01241     }
01242 
01243     if (veldcdFirst)
01244     {
01245       //  Open the DCD file
01246       iout << "OPENING VELOCITY DCD FILE\n" << endi;
01247           
01248         #if OUTPUT_SINGLE_FILE
01249           char *veldcdFilename = simParams->velDcdFilename;
01250         #else     
01251           char *veldcdFilename = buildFileName(veldcdType);
01252         #endif
01253 
01254       veldcdFileID=open_dcd_write(veldcdFilename);
01255 
01256       if (veldcdFileID == DCD_FILEEXISTS)
01257       {
01258         char err_msg[257];
01259         sprintf(err_msg, "Velocity DCD file %s already exists!",veldcdFilename);
01260         NAMD_err(err_msg);
01261       }
01262       else if (veldcdFileID < 0)
01263       {
01264         char err_msg[257];
01265         sprintf(err_msg, "Couldn't open velocity DCD file %s",veldcdFilename);
01266         NAMD_err(err_msg);
01267       }
01268 
01269         #if !OUTPUT_SINGLE_FILE
01270           // Write out extra fields as MAGIC number etc.
01271           int32 tmpInt = OUTPUT_MAGIC_NUMBER;
01272           float tmpFlt = OUTPUT_FILE_VERSION;
01273           NAMD_write(veldcdFileID, (char *) &tmpInt, sizeof(int32));
01274           NAMD_write(veldcdFileID, (char *) &tmpFlt, sizeof(float));
01275           tmpInt = simParams->numoutputprocs;
01276           NAMD_write(veldcdFileID, (char *) &tmpInt, sizeof(int32));
01277         #endif
01278 
01279       int NSAVC, NFILE, NPRIV, NSTEP;
01280       NSAVC = simParams->velDcdFrequency;
01281       NPRIV = timestep;
01282       NSTEP = NPRIV - NSAVC;
01283       NFILE = 0;
01284 
01285       //  Write out the header
01286       const int with_unitcell = 0;
01287       ret_code = write_dcdheader(veldcdFileID, 
01288           veldcdFilename,
01289           n, NFILE, NPRIV, NSAVC, NSTEP,
01290           simParams->dt/TIMEFACTOR, with_unitcell);
01291 
01292 
01293       if (ret_code<0)
01294       {
01295         NAMD_err("Writing of velocity DCD header failed!!");
01296       }
01297 
01298         #if !OUTPUT_SINGLE_FILE
01299           //In this case, the file name is dynamically allocated
01300           delete [] veldcdFilename;
01301         #endif
01302 
01303       veldcdFirst = FALSE;
01304     }
01305 
01306     //  Write out the values for this timestep
01307     iout << "WRITING VELOCITIES TO DCD FILE AT STEP "
01308       << timestep << "\n" << endi;
01309     fflush(stdout);
01310 
01311         //In the case of writing to multiple files, only the header
01312         //of the dcd file needs to be updated. Note that the format of
01313         //the new dcd file has also changed! -Chao Mei 
01314 
01315 #if OUTPUT_SINGLE_FILE
01316     //The following seek will set the stream position to the
01317     //beginning of the place where a new timestep output should
01318     //be performed.
01319     seek_dcdfile(veldcdFileID, 0, SEEK_END);
01320 
01321     // Write out the Cell data which is not necessary right now
01322     
01323     //write X,Y,Z headers
01324     int totalAtoms = namdMyNode->molecule->numAtoms;
01325     write_dcdstep_par_XYZUnits(veldcdFileID, totalAtoms);
01326 #endif
01327 
01328     //update the header
01329     update_dcdstep_par_header(veldcdFileID);    
01330 
01331 }
01332 
01333 void ParOutput::output_veldcdfile_slave(int timestep, int fID, int tID, Vector *vecs){
01334     int ret_code;    //  Return code from DCD calls
01335     SimParameters *simParams = Node::Object()->simParameters;
01336 
01337     //  If this is the last time we will be writing coordinates,
01338     //  close the file before exiting
01339     if ( timestep == END_OF_RUN ) {
01340       if ( ! veldcdFirst ) {        
01341         close_dcd_write(veldcdFileID);
01342       }
01343 #if OUTPUT_SINGLE_FILE
01344       delete [] veldcdX;
01345       delete [] veldcdY;
01346       delete [] veldcdZ;
01347 #endif
01348       return;
01349     }
01350 
01351     int parN = tID-fID+1;
01352 
01353     if (veldcdFirst)
01354     {
01355 
01356         #if OUTPUT_SINGLE_FILE
01357           char *veldcdFilename = namdMyNode->simParams->velDcdFilename;
01358         #else     
01359           char *veldcdFilename = buildFileName(veldcdType);
01360         #endif
01361       veldcdFileID=open_dcd_write_par_slave(veldcdFilename);
01362       if(veldcdFileID < 0)
01363       {
01364         char err_msg[257];
01365         sprintf(err_msg, "Couldn't open velocity DCD file %s",veldcdFilename);
01366         NAMD_err(err_msg);
01367       }
01368         #if OUTPUT_SINGLE_FILE
01369           //If outputting to a single file, dcd files conforms to the old format
01370           //as data are organized as 3 seperate arrays of X,Y,Z, while in the new
01371           //format used in outputing multiple files, the data are organized as an
01372           //array of XYZs.
01373       veldcdX = new float[parN];
01374       veldcdY = new float[parN];
01375       veldcdZ = new float[parN];
01376           //seek to beginning of X,Y,Z sections which means skipping header. 
01377           //Cell data is not needed because this is velocity trajectory
01378           int skipbytes = get_dcdheader_size();
01379           seek_dcdfile(veldcdFileID, skipbytes, SEEK_SET);
01380         #endif
01381 
01382         #if !OUTPUT_SINGLE_FILE
01383           delete [] veldcdFilename;
01384           // Write out extra fields as MAGIC number etc.
01385           int32 tmpInt = OUTPUT_MAGIC_NUMBER;
01386           float tmpFlt = OUTPUT_FILE_VERSION;
01387           NAMD_write(veldcdFileID, (char *) &tmpInt, sizeof(int32));
01388           NAMD_write(veldcdFileID, (char *) &tmpFlt, sizeof(float));      
01389           NAMD_write(veldcdFileID, (char *) &outputID, sizeof(int));
01390           NAMD_write(veldcdFileID, (char *) &fID, sizeof(int));
01391           NAMD_write(veldcdFileID, (char *) &tID, sizeof(int));
01392         #endif
01393           
01394       veldcdFirst = FALSE;
01395     }
01396 
01397 #if OUTPUT_SINGLE_FILE
01398     //The following seek will set the stream position to the
01399     //beginning of the place where a new timestep output should
01400     //be performed.
01401     CmiAssert(sizeof(off_t)==8);
01402     int totalAtoms = namdMyNode->molecule->numAtoms;
01403 
01404     for(int i=0; i<parN; i++){
01405         veldcdX[i] = vecs[i].x;
01406         veldcdY[i] = vecs[i].y;
01407         veldcdZ[i] = vecs[i].z;
01408     }
01409 
01410     write_dcdstep_par_slave(veldcdFileID, fID, tID, totalAtoms, veldcdX, veldcdY, veldcdZ);
01411 
01412         //same with the slave output for coordiantes trajectory file
01413         //but cell data is not needed because this is velocity trajectory
01414         int atomsRemains = (totalAtoms-1)-(tID+1)+1;
01415         off_t offset = ((off_t)atomsRemains)*sizeof(float)+1*sizeof(int);
01416         seek_dcdfile(veldcdFileID, offset, SEEK_CUR);
01417 
01418 #else
01419         //write the timestep
01420         NAMD_write(veldcdFileID, (char *)&timestep, sizeof(int));
01421         //write the values for this timestep
01422         NAMD_write(veldcdFileID, (char *)vecs, sizeof(Vector)*parN);
01423 #endif
01424 }
01425 
01426 void ParOutput::output_restart_velocities_master(int timestep, int n){
01427 #if OUTPUT_SINGLE_FILE
01428         char timestepstr[20];
01429 
01430     int baselen = strlen(namdMyNode->simParams->restartFilename);
01431     char *restart_name = new char[baselen+26];
01432 
01433     strcpy(restart_name, namdMyNode->simParams->restartFilename);
01434     if ( namdMyNode->simParams->restartSave ) {
01435       sprintf(timestepstr,".%d",timestep);
01436       strcat(restart_name, timestepstr);
01437     }
01438     strcat(restart_name, ".vel");
01439 #else
01440         char *restart_name = NULL;
01441         if ( namdMyNode->simParams->restartSave )
01442                 restart_name = buildFileName(velType);
01443         else
01444                 restart_name = buildFileName(velType,timestep); 
01445 #endif
01446 
01447     NAMD_backup_file(restart_name,".old");
01448 
01449     //Always output a binary file
01450     write_binary_file_master(restart_name, n);
01451 
01452     delete [] restart_name;
01453 }
01454 
01455 void ParOutput::output_restart_velocities_slave(int timestep, int fID, int tID, Vector *vecs, int64 offset){    
01456 #if OUTPUT_SINGLE_FILE
01457     char timestepstr[20];
01458 
01459     int baselen = strlen(namdMyNode->simParams->restartFilename);
01460     char *restart_name = new char[baselen+26];
01461 
01462     strcpy(restart_name, namdMyNode->simParams->restartFilename);
01463     if ( namdMyNode->simParams->restartSave ) {
01464       sprintf(timestepstr,".%d",timestep);
01465       strcat(restart_name, timestepstr);
01466     }
01467     strcat(restart_name, ".vel");    
01468 #else
01469         char *restart_name = NULL;
01470         if ( namdMyNode->simParams->restartSave )
01471                 restart_name = buildFileName(velType);
01472         else
01473                 restart_name = buildFileName(velType,timestep); 
01474 
01475         NAMD_backup_file(restart_name,".old");
01476 #endif
01477 
01478     //Always output a binary file       
01479     write_binary_file_slave(restart_name, fID, tID, vecs, offset);
01480 
01481     delete [] restart_name;
01482 }
01483 
01484 void ParOutput::output_final_velocities_master(int n){
01485 #if OUTPUT_SINGLE_FILE
01486     char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
01487     //  Build the output filename
01488     strcpy(output_name, namdMyNode->simParams->outputFilename);
01489     strcat(output_name, ".vel");
01490 #else   
01491         char *output_name = buildFileName(velType);
01492 #endif
01493 
01494     NAMD_backup_file(output_name);
01495 
01496     //Write the velocities to a binary file
01497     write_binary_file_master(output_name, n);
01498 }
01499 
01500 void ParOutput::output_final_velocities_slave(int fID, int tID, Vector *vecs, int64 offset){
01501 #if OUTPUT_SINGLE_FILE
01502     char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
01503     //  Build the output filename
01504     strcpy(output_name, namdMyNode->simParams->outputFilename);
01505     strcat(output_name, ".vel");
01506 #else
01507         char *output_name = buildFileName(velType);
01508         NAMD_backup_file(output_name);
01509 #endif
01510     
01511     //Write the velocities to a binary file
01512     write_binary_file_slave(output_name, fID, tID, vecs, offset);
01513 
01514         delete [] output_name;
01515 }
01516 
01517 void ParOutput::write_binary_file_master(char *fname, int n){
01518     char errmsg[256];
01519     int fd;    //  File descriptor
01520     int32 n32 = n;
01521 
01522     //  open the file and die if the open fails
01523   #ifdef WIN32
01524     if ( (fd = _open(fname, O_WRONLY|O_CREAT|O_EXCL|O_BINARY|O_LARGEFILE,_S_IREAD|_S_IWRITE)) < 0)
01525   #else
01526   #ifdef NAMD_NO_O_EXCL
01527     if ( (fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE,
01528   #else
01529     if ( (fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE,
01530   #endif
01531                              S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
01532   #endif
01533     {
01534       sprintf(errmsg, "Unable to open binary file %s", fname);
01535       NAMD_err(errmsg);
01536     }
01537 
01538   #if !OUTPUT_SINGLE_FILE
01539         // Write out extra fields as MAGIC number etc.
01540         int32 tmpInt = OUTPUT_MAGIC_NUMBER;
01541         float tmpFlt = OUTPUT_FILE_VERSION;
01542         NAMD_write(fd, (char *) &tmpInt, sizeof(int32), errmsg);
01543         NAMD_write(fd, (char *) &tmpFlt, sizeof(float), errmsg);
01544         tmpInt = namdMyNode->simParams->numoutputprocs;
01545         NAMD_write(fd, (char *) &tmpInt, sizeof(int32), errmsg);
01546   #endif
01547 
01548     //  Write out the number of atoms and the vectors
01549     NAMD_write(fd, (char *) &n32, sizeof(int32), errmsg);
01550 
01551   #ifdef WIN32
01552     if ( _close(fd) )
01553   #else
01554     if ( close(fd) )
01555   #endif
01556     {
01557       sprintf(errmsg, "Error on closing binary file %s", fname);
01558       NAMD_err(errmsg);
01559     }
01560 }
01561 
01562 void ParOutput::write_binary_file_slave(char *fname, int fID, int tID, Vector *vecs, int64 offset){
01563     char errmsg[256];
01564 
01565 #if OUTPUT_SINGLE_FILE
01566         //the mode has to be "r+" because the file already exists
01567         FILE *ofp = fopen(fname, "rb+");
01568         if ( ! ofp ) {
01569           sprintf(errmsg, "Error on opening binary file %s", fname);
01570           NAMD_err(errmsg);
01571         }
01572 
01573         //if the output is a single file, then the file position needs to be set correctly
01574 #ifdef WIN32
01575         if ( _fseeki64(ofp, offset, SEEK_SET) )
01576 #else
01577         if ( fseeko(ofp, offset, SEEK_SET) )
01578 #endif
01579         {
01580           sprintf(errmsg, "Error on seeking binary file %s", fname);
01581           NAMD_err(errmsg);
01582         }
01583 #else
01584         //the mode has to be "w+" because the file doesn't exist yet
01585         FILE *ofp = fopen(fname, "wb+"); 
01586         if ( ! ofp ) {
01587           sprintf(errmsg, "Error on opening binary file %s", fname);
01588           NAMD_err(errmsg);
01589         }
01590 
01591         // Write out extra fields as MAGIC number etc.
01592         int32 tmpInt = OUTPUT_MAGIC_NUMBER;
01593         float tmpFlt = OUTPUT_FILE_VERSION;     
01594         fwrite(&tmpInt, sizeof(int32), 1, ofp); 
01595         fwrite(&tmpFlt, sizeof(float), 1, ofp);
01596         fwrite(&outputID, sizeof(int), 1, ofp);
01597         fwrite(&fID, sizeof(int), 1, ofp);
01598         fwrite(&tID, sizeof(int), 1, ofp);
01599 #endif
01600 
01601         int parN = tID-fID+1;
01602         if ( fwrite(vecs, sizeof(Vector), parN, ofp) != parN ) {
01603           sprintf(errmsg, "Error on writing to binary file %s", fname);
01604           NAMD_err(errmsg);
01605         }
01606 
01607         if ( fclose(ofp) ) {
01608           sprintf(errmsg, "Error on closing binary file %s", fname);
01609           NAMD_err(errmsg);
01610         }
01611 }
01613 
01614 
01616 void ParOutput::forceMaster(int timestep, int n){
01617     SimParameters *simParams = Node::Object()->simParameters;
01618 
01619     if ( timestep >= 0 ) {
01620 
01621       //  Output force DCD trajectory
01622       if ( simParams->forceDcdFrequency &&
01623          ((timestep % simParams->forceDcdFrequency) == 0) )
01624       {         
01625         output_forcedcdfile_master(timestep, n);        
01626       }
01627 
01628     }
01629 
01630     //  Output forces
01631     if (timestep == FORCE_OUTPUT)
01632     {
01633       int realstep = simParams->firstTimestep;
01634       iout << "WRITING FORCES TO OUTPUT FILE AT STEP "
01635                   << realstep << "\n" << endi;
01636       fflush(stdout);
01637       output_forces_master(n);
01638     }
01639 
01640     //  Close trajectory files in velocityMaster above
01641 }
01642 
01643 //output atoms' forces from id fID to tID.
01644 void ParOutput::forceSlave(int timestep, int fID, int tID, Vector *vecs){
01645     SimParameters *simParams = Node::Object()->simParameters;
01646 
01647     if ( timestep >= 0 ) {
01648 
01649       //  Output force DCD trajectory
01650       if ( simParams->forceDcdFrequency &&
01651          ((timestep % simParams->forceDcdFrequency) == 0) )
01652       {         
01653         output_forcedcdfile_slave(timestep, fID, tID, vecs);
01654       }
01655 
01656     }
01657 
01658     //  Output forces
01659     if (timestep == FORCE_OUTPUT)
01660     {
01661         int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
01662         output_forces_slave(fID, tID, vecs, offset);
01663     }
01664 
01665     //  Close trajectory files in velocitySlave above
01666 }
01667 
01668 void ParOutput::output_forcedcdfile_master(int timestep, int n){
01669     int ret_code;    //  Return code from DCD calls
01670     SimParameters *simParams = Node::Object()->simParameters;
01671 
01672     //  If this is the last time we will be writing coordinates,
01673     //  close the file before exiting
01674     if ( timestep == END_OF_RUN ) {
01675       if ( ! forcedcdFirst ) {
01676         iout << "CLOSING FORCE DCD FILE\n" << endi;
01677         close_dcd_write(forcedcdFileID);
01678       } else {
01679         iout << "FORCE DCD FILE WAS NOT CREATED\n" << endi;
01680       }
01681       return;      
01682     }
01683 
01684     if (forcedcdFirst)
01685     {
01686       //  Open the DCD file
01687       iout << "OPENING FORCE DCD FILE\n" << endi;
01688           
01689         #if OUTPUT_SINGLE_FILE
01690           char *forcedcdFilename = simParams->forceDcdFilename;
01691         #else     
01692           char *forcedcdFilename = buildFileName(forcedcdType);
01693         #endif
01694 
01695       forcedcdFileID=open_dcd_write(forcedcdFilename);
01696 
01697       if (forcedcdFileID == DCD_FILEEXISTS)
01698       {
01699         char err_msg[257];
01700         sprintf(err_msg, "Force DCD file %s already exists!",forcedcdFilename);
01701         NAMD_err(err_msg);
01702       }
01703       else if (forcedcdFileID < 0)
01704       {
01705         char err_msg[257];
01706         sprintf(err_msg, "Couldn't open force DCD file %s",forcedcdFilename);
01707         NAMD_err(err_msg);
01708       }
01709 
01710         #if !OUTPUT_SINGLE_FILE
01711           // Write out extra fields as MAGIC number etc.
01712           int32 tmpInt = OUTPUT_MAGIC_NUMBER;
01713           float tmpFlt = OUTPUT_FILE_VERSION;
01714           NAMD_write(forcedcdFileID, (char *) &tmpInt, sizeof(int32));
01715           NAMD_write(forcedcdFileID, (char *) &tmpFlt, sizeof(float));
01716           tmpInt = simParams->numoutputprocs;
01717           NAMD_write(forcedcdFileID, (char *) &tmpInt, sizeof(int32));
01718         #endif
01719 
01720       int NSAVC, NFILE, NPRIV, NSTEP;
01721       NSAVC = simParams->forceDcdFrequency;
01722       NPRIV = timestep;
01723       NSTEP = NPRIV - NSAVC;
01724       NFILE = 0;
01725 
01726       //  Write out the header
01727       const int with_unitcell = 0;
01728       ret_code = write_dcdheader(forcedcdFileID, 
01729           forcedcdFilename,
01730           n, NFILE, NPRIV, NSAVC, NSTEP,
01731           simParams->dt/TIMEFACTOR, with_unitcell);
01732 
01733 
01734       if (ret_code<0)
01735       {
01736         NAMD_err("Writing of force DCD header failed!!");
01737       }
01738 
01739         #if !OUTPUT_SINGLE_FILE
01740           //In this case, the file name is dynamically allocated
01741           delete [] forcedcdFilename;
01742         #endif
01743 
01744       forcedcdFirst = FALSE;
01745     }
01746 
01747     //  Write out the values for this timestep
01748     iout << "WRITING FORCES TO DCD FILE AT STEP "
01749       << timestep << "\n" << endi;
01750     fflush(stdout);
01751 
01752         //In the case of writing to multiple files, only the header
01753         //of the dcd file needs to be updated. Note that the format of
01754         //the new dcd file has also changed! -Chao Mei 
01755 
01756 #if OUTPUT_SINGLE_FILE
01757     //The following seek will set the stream position to the
01758     //beginning of the place where a new timestep output should
01759     //be performed.
01760     seek_dcdfile(forcedcdFileID, 0, SEEK_END);
01761 
01762     // Write out the Cell data which is not necessary right now
01763     
01764     //write X,Y,Z headers
01765     int totalAtoms = namdMyNode->molecule->numAtoms;
01766     write_dcdstep_par_XYZUnits(forcedcdFileID, totalAtoms);
01767 #endif
01768 
01769     //update the header
01770     update_dcdstep_par_header(forcedcdFileID);    
01771 
01772 }
01773 
01774 void ParOutput::output_forcedcdfile_slave(int timestep, int fID, int tID, Vector *vecs){
01775     int ret_code;    //  Return code from DCD calls
01776     SimParameters *simParams = Node::Object()->simParameters;
01777 
01778     //  If this is the last time we will be writing coordinates,
01779     //  close the file before exiting
01780     if ( timestep == END_OF_RUN ) {
01781       if ( ! forcedcdFirst ) {        
01782         close_dcd_write(forcedcdFileID);
01783       }
01784 #if OUTPUT_SINGLE_FILE
01785       delete [] forcedcdX;
01786       delete [] forcedcdY;
01787       delete [] forcedcdZ;
01788 #endif
01789       return;
01790     }
01791 
01792     int parN = tID-fID+1;
01793 
01794     if (forcedcdFirst)
01795     {
01796 
01797         #if OUTPUT_SINGLE_FILE
01798           char *forcedcdFilename = namdMyNode->simParams->forceDcdFilename;
01799         #else     
01800           char *forcedcdFilename = buildFileName(forcedcdType);
01801         #endif
01802       forcedcdFileID=open_dcd_write_par_slave(forcedcdFilename);
01803       if(forcedcdFileID < 0)
01804       {
01805         char err_msg[257];
01806         sprintf(err_msg, "Couldn't open force DCD file %s",forcedcdFilename);
01807         NAMD_err(err_msg);
01808       }
01809         #if OUTPUT_SINGLE_FILE
01810           //If outputting to a single file, dcd files conforms to the old format
01811           //as data are organized as 3 seperate arrays of X,Y,Z, while in the new
01812           //format used in outputing multiple files, the data are organized as an
01813           //array of XYZs.
01814       forcedcdX = new float[parN];
01815       forcedcdY = new float[parN];
01816       forcedcdZ = new float[parN];
01817           //seek to beginning of X,Y,Z sections which means skipping header. 
01818           //Cell data is not needed because this is force trajectory
01819           int skipbytes = get_dcdheader_size();
01820           seek_dcdfile(forcedcdFileID, skipbytes, SEEK_SET);
01821         #endif
01822 
01823         #if !OUTPUT_SINGLE_FILE
01824           delete [] forcedcdFilename;
01825           // Write out extra fields as MAGIC number etc.
01826           int32 tmpInt = OUTPUT_MAGIC_NUMBER;
01827           float tmpFlt = OUTPUT_FILE_VERSION;
01828           NAMD_write(forcedcdFileID, (char *) &tmpInt, sizeof(int32));
01829           NAMD_write(forcedcdFileID, (char *) &tmpFlt, sizeof(float));    
01830           NAMD_write(forcedcdFileID, (char *) &outputID, sizeof(int));
01831           NAMD_write(forcedcdFileID, (char *) &fID, sizeof(int));
01832           NAMD_write(forcedcdFileID, (char *) &tID, sizeof(int));
01833         #endif
01834           
01835       forcedcdFirst = FALSE;
01836     }
01837 
01838 #if OUTPUT_SINGLE_FILE
01839     //The following seek will set the stream position to the
01840     //beginning of the place where a new timestep output should
01841     //be performed.
01842     CmiAssert(sizeof(off_t)==8);
01843     int totalAtoms = namdMyNode->molecule->numAtoms;
01844 
01845     for(int i=0; i<parN; i++){
01846         forcedcdX[i] = vecs[i].x;
01847         forcedcdY[i] = vecs[i].y;
01848         forcedcdZ[i] = vecs[i].z;
01849     }
01850 
01851     write_dcdstep_par_slave(forcedcdFileID, fID, tID, totalAtoms, forcedcdX, forcedcdY, forcedcdZ);
01852         //same with the slave output for coordiantes trajectory file
01853         //but cell data is not needed because this is force trajectory
01854         int atomsRemains = (totalAtoms-1)-(tID+1)+1;
01855         off_t offset = ((off_t)atomsRemains)*sizeof(float)+1*sizeof(int);
01856         seek_dcdfile(forcedcdFileID, offset, SEEK_CUR);
01857 #else
01858         //write the timestep
01859         NAMD_write(forcedcdFileID, (char *)&timestep, sizeof(int));
01860         //write the values for this timestep
01861         NAMD_write(forcedcdFileID, (char *)vecs, sizeof(Vector)*parN);
01862 #endif
01863 }
01864 
01865 void ParOutput::output_forces_master(int n){
01866 #if OUTPUT_SINGLE_FILE
01867     char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
01868     //  Build the output filename
01869     strcpy(output_name, namdMyNode->simParams->outputFilename);
01870     strcat(output_name, ".force");
01871 #else   
01872         char *output_name = buildFileName(forceType);
01873 #endif
01874 
01875     NAMD_backup_file(output_name);
01876 
01877     //Write the force to a binary file
01878     write_binary_file_master(output_name, n);
01879 }
01880 
01881 void ParOutput::output_forces_slave(int fID, int tID, Vector *vecs, int64 offset){
01882 #if OUTPUT_SINGLE_FILE
01883     char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
01884     //  Build the output filename
01885     strcpy(output_name, namdMyNode->simParams->outputFilename);
01886     strcat(output_name, ".force");
01887 #else
01888         char *output_name = buildFileName(forceType);
01889         NAMD_backup_file(output_name);
01890 #endif
01891     
01892     //Write the forces to a binary file
01893     write_binary_file_slave(output_name, fID, tID, vecs, offset);
01894 
01895         delete [] output_name;
01896 }
01898 
01899 
01901 void ParOutput::coordinateMaster(int timestep, int n, Lattice &lat){
01902     SimParameters *simParams = Node::Object()->simParameters;
01903 
01904     if ( timestep >= 0 ) {
01905       //  Output a DCD trajectory 
01906       if ( simParams->dcdFrequency &&
01907          ((timestep % simParams->dcdFrequency) == 0) )
01908       {        
01909         output_dcdfile_master(timestep, n, 
01910             simParams->dcdUnitCell ? &lat : NULL);
01911       }
01912 
01913       //  Output a restart file
01914       if ( simParams->restartFrequency &&
01915          ((timestep % simParams->restartFrequency) == 0) )
01916       {
01917         iout << "WRITING COORDINATES TO RESTART FILE AT STEP "
01918                   << timestep << "\n" << endi;
01919         output_restart_coordinates_master(timestep, n);
01920         iout << "FINISHED WRITING RESTART COORDINATES\n" <<endi;
01921         fflush(stdout);
01922       }
01923 
01924 /*  Interactive MD is not supported in Parallel IO
01925       //  Interactive MD
01926       if ( simParams->IMDon &&
01927          ( ((timestep % simParams->IMDfreq) == 0) ||
01928            (timestep == simParams->firstTimestep) ) )
01929       {
01930         IMDOutput *imd = Node::Object()->imd;
01931         wrap_coor(fcoor,lattice,&fcoor_wrapped);
01932         if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
01933       }
01934 */
01935     }
01936 
01937 /*  EVAL_MEASURE of a timestep is not supported in Parallel IO 
01938     if (timestep == EVAL_MEASURE)
01939     {
01940   #ifdef NAMD_TCL
01941       wrap_coor(coor,lattice,&coor_wrapped);
01942       Node::Object()->getScript()->measure(coor);
01943   #endif
01944     }
01945 */
01946     //  Output final coordinates
01947     if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
01948     {
01949       int realstep = ( timestep == FILE_OUTPUT ?
01950           simParams->firstTimestep : simParams->N );
01951       iout << "WRITING COORDINATES TO OUTPUT FILE AT STEP "
01952                   << realstep << "\n" << endi;
01953       fflush(stdout);      
01954       output_final_coordinates_master(n);
01955     }
01956 
01957     //  Close trajectory files
01958     if (timestep == END_OF_RUN)
01959     {
01960       if (simParams->dcdFrequency) output_dcdfile_master(END_OF_RUN,0,NULL);
01961     }
01962 }
01963 
01964 void ParOutput::coordinateSlave(int timestep, int fID, int tID, Vector *vecs, FloatVector *fvecs){
01965     SimParameters *simParams = Node::Object()->simParameters;
01966 
01967     if ( timestep >= 0 ) {
01968       //  Output a DCD trajectory 
01969       if ( simParams->dcdFrequency &&
01970          ((timestep % simParams->dcdFrequency) == 0) )
01971       {        
01972         output_dcdfile_slave(timestep, fID, tID, fvecs);
01973       }
01974 
01975       //  Output a restart file
01976       if ( simParams->restartFrequency &&
01977          ((timestep % simParams->restartFrequency) == 0) )
01978       {
01979         int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
01980         output_restart_coordinates_slave(timestep, fID, tID, vecs, offset);
01981       }
01982 
01983 /*  Interactive MD is not supported in Parallel IO
01984       //  Interactive MD
01985       if ( simParams->IMDon &&
01986          ( ((timestep % simParams->IMDfreq) == 0) ||
01987            (timestep == simParams->firstTimestep) ) )
01988       {
01989         IMDOutput *imd = Node::Object()->imd;
01990         wrap_coor(fcoor,lattice,&fcoor_wrapped);
01991         if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
01992       }
01993 */
01994     }
01995 
01996 /*  EVAL_MEASURE of a timestep is not supported in Parallel IO 
01997     if (timestep == EVAL_MEASURE)
01998     {
01999   #ifdef NAMD_TCL
02000       wrap_coor(coor,lattice,&coor_wrapped);
02001       Node::Object()->getScript()->measure(coor);
02002   #endif
02003     }
02004 */
02005     //  Output final coordinates
02006     if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
02007     {
02008       int64 offset = sizeof(int)+sizeof(Vector)*((int64)fID);
02009       output_final_coordinates_slave(fID, tID, vecs, offset);
02010     }
02011 
02012     //  Close trajectory files
02013     if (timestep == END_OF_RUN)
02014     {
02015       if (simParams->dcdFrequency) output_dcdfile_slave(END_OF_RUN,0,0,NULL);
02016     }
02017 }
02018 
02019 void ParOutput::output_dcdfile_master(int timestep, int n, const Lattice *lattice){
02020     int ret_code;    //  Return code from DCD calls
02021     SimParameters *simParams = namdMyNode->simParams;
02022 
02023     //  If this is the last time we will be writing coordinates,
02024     //  close the file before exiting
02025     if ( timestep == END_OF_RUN ) {
02026       if ( ! dcdFirst ) {
02027         iout << "CLOSING COORDINATE DCD FILE\n" << endi;
02028         close_dcd_write(dcdFileID);
02029       } else {
02030         iout << "COORDINATE DCD FILE WAS NOT CREATED\n" << endi;
02031       }
02032       return;
02033     }
02034 
02035     if (dcdFirst)
02036     {
02037       //  Open the DCD file
02038       iout << "OPENING COORDINATE DCD FILE\n" << endi;
02039 
02040         #if OUTPUT_SINGLE_FILE
02041           char *dcdFilename = simParams->dcdFilename;
02042         #else     
02043           char *dcdFilename = buildFileName(dcdType);
02044         #endif
02045 
02046 
02047       dcdFileID=open_dcd_write(dcdFilename);
02048 
02049       if (dcdFileID == DCD_FILEEXISTS)
02050       {
02051         char err_msg[257];
02052         sprintf(err_msg, "DCD file %s already exists!!",dcdFilename);
02053         NAMD_err(err_msg);
02054       }
02055       else if (dcdFileID < 0)
02056       {
02057         char err_msg[257];
02058         sprintf(err_msg, "Couldn't open DCD file %s",dcdFilename);
02059         NAMD_err(err_msg);
02060       }
02061 
02062         #if !OUTPUT_SINGLE_FILE
02063           // Write out extra fields as MAGIC number etc.
02064           int32 tmpInt = OUTPUT_MAGIC_NUMBER;
02065           float tmpFlt = OUTPUT_FILE_VERSION;
02066           NAMD_write(dcdFileID, (char *) &tmpInt, sizeof(int32));
02067           NAMD_write(dcdFileID, (char *) &tmpFlt, sizeof(float));
02068           tmpInt = simParams->numoutputprocs;
02069           NAMD_write(dcdFileID, (char *) &tmpInt, sizeof(int32));
02070         #endif
02071 
02072       int NSAVC, NFILE, NPRIV, NSTEP;
02073       NSAVC = simParams->dcdFrequency;
02074       NPRIV = timestep;
02075       NSTEP = NPRIV - NSAVC;
02076       NFILE = 0;
02077 
02078       //  Write out the header
02079       ret_code = write_dcdheader(dcdFileID, 
02080           dcdFilename,
02081           n, NFILE, NPRIV, NSAVC, NSTEP,
02082           simParams->dt/TIMEFACTOR, lattice != NULL);
02083 
02084 
02085       if (ret_code<0)
02086       {
02087         NAMD_err("Writing of DCD header failed!!");
02088       }
02089 
02090           #if !OUTPUT_SINGLE_FILE
02091           //dcdFilename needs to be freed as it is dynamically allocated
02092           delete [] dcdFilename;
02093           #endif
02094 
02095       dcdFirst = FALSE;
02096     }
02097 
02098     //  Write out the values for this timestep
02099     iout << "WRITING COORDINATES TO DCD FILE AT STEP "
02100       << timestep << "\n" << endi;
02101     fflush(stdout);
02102 
02103         //In the case of writing to multiple files, the header of the
02104         //dcd file needs to be updated. In addition, the lattice data
02105         //needs to be written if necessary. Note that the format of     
02106         //the new dcd file has also changed! -Chao Mei
02107 
02108 #if OUTPUT_SINGLE_FILE
02109     //The following seek will set the stream position to the
02110     //beginning of the place where a new timestep output should
02111     //be performed.
02112     seek_dcdfile(dcdFileID, 0, SEEK_END);
02113 #endif
02114 
02115     // Write out the Cell data
02116     if (lattice) {
02117       double unitcell[6];
02118       if (lattice->a_p() && lattice->b_p() && lattice->c_p()) {
02119         const Vector &a=lattice->a();
02120         const Vector &b=lattice->b();
02121         const Vector &c=lattice->c();
02122         unitcell[0] = a.length();
02123         unitcell[2] = b.length();
02124         unitcell[5] = c.length();
02125         double cosAB = (a*b)/(unitcell[0]*unitcell[2]);
02126         double cosAC = (a*c)/(unitcell[0]*unitcell[5]);
02127         double cosBC = (b*c)/(unitcell[2]*unitcell[5]);
02128         if (cosAB > 1.0) cosAB = 1.0; else if (cosAB < -1.0) cosAB = -1.0;
02129         if (cosAC > 1.0) cosAC = 1.0; else if (cosAC < -1.0) cosAC = -1.0;
02130         if (cosBC > 1.0) cosBC = 1.0; else if (cosBC < -1.0) cosBC = -1.0;
02131         unitcell[1] = cosAB;
02132         unitcell[3] = cosAC;
02133         unitcell[4] = cosBC;
02134       } else {
02135         unitcell[0] = unitcell[2] = unitcell[5] = 1.0;
02136         unitcell[1] = unitcell[3] = unitcell[4] = 0.0;
02137       }
02138       write_dcdstep_par_cell(dcdFileID, unitcell);
02139     }
02140             
02141 #if OUTPUT_SINGLE_FILE
02142     //write X,Y,Z headers
02143     int totalAtoms = namdMyNode->molecule->numAtoms;
02144     write_dcdstep_par_XYZUnits(dcdFileID, totalAtoms);
02145 #endif
02146 
02147     //update the header
02148     update_dcdstep_par_header(dcdFileID);
02149 }
02150 void ParOutput::output_dcdfile_slave(int timestep, int fID, int tID, FloatVector *fvecs){
02151     int ret_code;    //  Return code from DCD calls
02152     SimParameters *simParams = Node::Object()->simParameters;
02153 
02154     //  If this is the last time we will be writing coordinates,
02155     //  close the file before exiting
02156     if ( timestep == END_OF_RUN ) {
02157       if ( ! dcdFirst ) {        
02158         close_dcd_write(dcdFileID);
02159       }
02160 #if OUTPUT_SINGLE_FILE
02161       delete [] dcdX;
02162       delete [] dcdY;
02163       delete [] dcdZ; 
02164 #endif         
02165       return;
02166     }
02167 
02168     int parN = tID-fID+1;
02169 
02170     if (dcdFirst)
02171     {
02172 
02173         #if OUTPUT_SINGLE_FILE
02174           char *dcdFilename = simParams->dcdFilename;
02175         #else
02176           char *dcdFilename = buildFileName(dcdType);
02177         #endif
02178       dcdFileID=open_dcd_write_par_slave(dcdFilename);
02179       if(dcdFileID < 0)
02180       {
02181         char err_msg[257];
02182         sprintf(err_msg, "Couldn't open DCD file %s", dcdFilename);
02183         NAMD_err(err_msg);
02184       }
02185         
02186         #if OUTPUT_SINGLE_FILE
02187       dcdX = new float[parN];
02188       dcdY = new float[parN];
02189       dcdZ = new float[parN];
02190           //seek to beginning of X,Y,Z sections which means skipping header 
02191           //skip the cell data if necessary
02192           int skipbytes = get_dcdheader_size();
02193           if(simParams->dcdUnitCell) {
02194                   skipbytes += sizeof(int)*2 + 6*sizeof(double);
02195           }
02196           seek_dcdfile(dcdFileID, skipbytes, SEEK_SET);
02197         #endif
02198 
02199         #if !OUTPUT_SINGLE_FILE
02200           delete [] dcdFilename;
02201 
02202           // Write out extra fields as MAGIC number etc.
02203           int32 tmpInt = OUTPUT_MAGIC_NUMBER;
02204           float tmpFlt = OUTPUT_FILE_VERSION;
02205           NAMD_write(dcdFileID, (char *) &tmpInt, sizeof(int32));
02206           NAMD_write(dcdFileID, (char *) &tmpFlt, sizeof(float));
02207           NAMD_write(dcdFileID, (char *) &outputID, sizeof(int));
02208           NAMD_write(dcdFileID, (char *) &fID, sizeof(int));
02209           NAMD_write(dcdFileID, (char *) &tID, sizeof(int));
02210         #endif
02211       dcdFirst = FALSE;
02212     }
02213 
02214 #if OUTPUT_SINGLE_FILE
02215     //The following seek will set the stream position to the
02216     //beginning of the place where a new timestep output should
02217     //be performed.
02218     CmiAssert(sizeof(off_t)==8);
02219     int totalAtoms = namdMyNode->molecule->numAtoms;
02220 
02221     for(int i=0; i<parN; i++){
02222         dcdX[i] = fvecs[i].x;
02223         dcdY[i] = fvecs[i].y;
02224         dcdZ[i] = fvecs[i].z;
02225     }
02226 
02227     write_dcdstep_par_slave(dcdFileID, fID, tID, totalAtoms, dcdX, dcdY, dcdZ);
02228 
02229         //1. Always foward to the beginning position of X,Y,Z sections in the
02230         //next timeframe.       
02231         //2. SHOULD AVOID USING SEEK_END: although the file size is updated on the
02232         //master proc, slave procs should rely on this update by seeking 
02233         //from SEEK_END because such info may not be updated in a timely manner
02234         //when this slave proc needs it.
02235 
02236         //We know the current position of file after slave writing is at the
02237         //end of Z output for atom "tID" (tID is the atom id indexed from 0)
02238         //(totalAtoms-1) is the last atom id, (tID+1) is the next atom id
02239         int atomsRemains = (totalAtoms-1)-(tID+1)+1;
02240         off_t offset = ((off_t)atomsRemains)*sizeof(float)+1*sizeof(int);
02241         //then skip the cell data if necessary
02242         if(simParams->dcdUnitCell) {
02243                 offset += sizeof(int)*2 + 6*sizeof(double);             
02244         }
02245         seek_dcdfile(dcdFileID, offset, SEEK_CUR);
02246 #else
02247         //write the timestep
02248         NAMD_write(dcdFileID, (char *)&timestep, sizeof(int));
02249         //write the values for this timestep
02250         NAMD_write(dcdFileID, (char *)fvecs, sizeof(FloatVector)*parN);
02251 #endif
02252 }
02253 
02254 void ParOutput::output_restart_coordinates_master(int timestep, int n){
02255 #if OUTPUT_SINGLE_FILE
02256         char timestepstr[20];
02257 
02258     int baselen = strlen(namdMyNode->simParams->restartFilename);
02259     char *restart_name = new char[baselen+26];
02260 
02261     strcpy(restart_name, namdMyNode->simParams->restartFilename);
02262     if ( namdMyNode->simParams->restartSave ) {
02263       sprintf(timestepstr,".%d",timestep);
02264       strcat(restart_name, timestepstr);
02265     }
02266     strcat(restart_name, ".coor");
02267 #else
02268         char *restart_name = NULL;
02269         if ( namdMyNode->simParams->restartSave )
02270                 restart_name = buildFileName(coorType);
02271         else
02272                 restart_name = buildFileName(coorType,timestep);
02273 #endif
02274 
02275     NAMD_backup_file(restart_name,".old");
02276 
02277     //  Generate a binary restart file
02278     write_binary_file_master(restart_name, n);
02279 
02280     delete [] restart_name;
02281 }
02282 void ParOutput::output_restart_coordinates_slave(int timestep, int fID, int tID, Vector *vecs, int64 offset){
02283 #if OUTPUT_SINGLE_FILE
02284         char timestepstr[20];
02285 
02286     int baselen = strlen(namdMyNode->simParams->restartFilename);
02287     char *restart_name = new char[baselen+26];
02288 
02289     strcpy(restart_name, namdMyNode->simParams->restartFilename);
02290     if ( namdMyNode->simParams->restartSave ) {
02291       sprintf(timestepstr,".%d",timestep);
02292       strcat(restart_name, timestepstr);
02293     }
02294     strcat(restart_name, ".coor");
02295 #else
02296         char *restart_name = NULL;
02297         if ( namdMyNode->simParams->restartSave )
02298                 restart_name = buildFileName(coorType);
02299         else
02300                 restart_name = buildFileName(coorType,timestep);
02301 
02302         NAMD_backup_file(restart_name,".old");
02303 #endif
02304 
02305     //  Generate a binary restart file
02306     write_binary_file_slave(restart_name, fID, tID, vecs, offset);
02307 
02308     delete [] restart_name;
02309 }
02310 
02311 void ParOutput::output_final_coordinates_master(int n){
02312 #if OUTPUT_SINGLE_FILE
02313         char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
02314 
02315     //  Built the output filename
02316     strcpy(output_name, namdMyNode->simParams->outputFilename);
02317     strcat(output_name, ".coor");
02318 #else   
02319         char *output_name = buildFileName(coorType);
02320 #endif
02321 
02322     NAMD_backup_file(output_name);
02323 
02324     //  Write the coordinates to a binary file
02325     write_binary_file_master(output_name, n);
02326 
02327         delete [] output_name;
02328 }
02329 void ParOutput::output_final_coordinates_slave(int fID, int tID, Vector *vecs, int64 offset){
02330 #if OUTPUT_SINGLE_FILE
02331     char *output_name = new char[strlen(namdMyNode->simParams->outputFilename)+8];
02332 
02333     //  Built the output filename
02334     strcpy(output_name, namdMyNode->simParams->outputFilename);
02335     strcat(output_name, ".coor");
02336 #else   
02337         char *output_name = buildFileName(coorType);    
02338         NAMD_backup_file(output_name);
02339 #endif
02340 
02341     //  Write the coordinates to a binary file
02342     write_binary_file_slave(output_name, fID, tID, vecs, offset);
02343 
02344         delete [] output_name;
02345 }
02347 
02349 #if !OUTPUT_SINGLE_FILE
02350 char *ParOutput::buildFileName(OUTPUTFILETYPE type, int timestep){
02351         char *filename = NULL;
02352         const char *typeName = NULL;
02353         switch(type) {
02354         case dcdType:
02355                 typeName = "dcd";
02356                 break;
02357         case forcedcdType:
02358                 typeName = "forcedcd";
02359                 break;
02360         case veldcdType:
02361                 typeName = "veldcd";
02362                 break;
02363         case coorType:
02364                 typeName = "coor";
02365                 break;
02366         case forceType:
02367                 typeName = "force";
02368                 break;
02369         case velType:
02370                 typeName = "vel";
02371                 break;
02372         default:
02373                 typeName = "invalid";
02374                 break;
02375         }
02376         int baselen = strlen(namdMyNode->simParams->outputFilename);    
02377         filename = new char[baselen+32];
02378         memset(filename, 0, baselen+32);
02379 
02380 #if 0
02381         strcpy(filename, namdMyNode->simParams->outputFilename);
02382 
02383         //check if the directory exists or not
02384         struct stat st;
02385         if(stat(filename, &st)!=0) {
02386                 int ret = MKDIR(filename);
02387                 if(ret!=0) {
02388                         char errmsg[512];
02389                         sprintf(errmsg, "Error in creating top-level directory %s!", filename);
02390                         NAMD_err(errmsg);
02391                 }
02392         }
02393 
02394         strcat(filename, PATHSEPSTR);
02395         strcat(filename, typeName);
02396 
02397         //check if the directory exists or not  
02398         if(stat(filename, &st)!=0) {
02399                 int ret = MKDIR(filename);
02400                 if(ret!=0) {
02401                         char errmsg[512];
02402                         sprintf(errmsg, "Error in creating middle-level directory %s!", filename);
02403                         NAMD_err(errmsg);
02404                 }
02405         }
02406 #else
02407         sprintf(filename, "%s%s%s", namdMyNode->simParams->outputFilename, PATHSEPSTR, typeName);
02408 #endif
02409 
02410         char tmpstr[20];
02411         if(outputID == -1) {
02412                 //indicating the output from master                     
02413                 if(timestep!=-9999) {
02414                         //not the default value
02415                         sprintf(tmpstr, "%smeta.%d", PATHSEPSTR, timestep);
02416                 }else{
02417                         sprintf(tmpstr, "%smeta", PATHSEPSTR);
02418                 }
02419         }else{
02420                 //indicating the output from slave              
02421                 sprintf(tmpstr, "%s%d", PATHSEPSTR, outputID);
02422                 strcat(filename, tmpstr);
02423                 #if 0
02424                 if(stat(filename, &st)!=0) {
02425                         int ret = MKDIR(filename);
02426                         if(ret!=0) {
02427                                 char errmsg[512];
02428                                 sprintf(errmsg, "Error in creating last-level directory %s!", filename);
02429                                 NAMD_err(errmsg);
02430                         }
02431                 }
02432                 #endif
02433                 if(timestep!=-9999) {
02434                         //not the default value
02435                         sprintf(tmpstr, "%s%s_%d.%d", PATHSEPSTR,typeName,outputID,timestep);
02436                 }else{
02437                         sprintf(tmpstr,"%s%s_%d", PATHSEPSTR,typeName,outputID);
02438                 }       
02439         }
02440 
02441         strcat(filename, tmpstr);
02442         return filename;
02443 }
02444 #endif
02445 
02446 #endif

Generated on Fri May 25 04:07:16 2012 for NAMD by  doxygen 1.3.9.1