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

Generated on Fri Sep 22 01:17:14 2017 for NAMD by  doxygen 1.4.7