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

Output.C

Go to the documentation of this file.
00001 
00007 /*
00008    This object outputs the data collected on the master node
00009 */
00010 
00011 #include <string.h>
00012 #include <stdlib.h>
00013 
00014 #include "InfoStream.h"
00015 #include "IMDOutput.h"
00016 #include "Output.h"
00017 #include "dcdlib.h"
00018 #include "strlib.h"
00019 #include "Molecule.h"
00020 #include "Node.h"
00021 #include "Parameters.h"
00022 #include "PDB.h"
00023 #include "SimParameters.h"
00024 #include "Vector.h"
00025 #include "structures.h"
00026 #include "MStream.h"
00027 #include "Communicate.h"
00028 #include "PatchMap.h"
00029 #include "PatchMap.inl"
00030 #include "ScriptTcl.h"
00031 #include "Lattice.h"
00032 
00033 // These make the NAMD 1 names work in NAMD 2
00034 #define namdMyNode Node::Object()
00035 #define simParams simParameters
00036 #define pdbData pdb
00037 
00038 /************************************************************************/
00039 /*                  */
00040 /*      FUNCTION Output          */
00041 /*                  */
00042 /*  This is the constructor for the Ouput class.  It just sets   */
00043 /*  up some values for the VMD connection.        */
00044 /*                  */
00045 /************************************************************************/
00046 
00047 Output::Output() { }
00048 
00049 /*      END OF FUNCTION Output        */
00050 
00051 /************************************************************************/
00052 /*                  */
00053 /*      FUNCTION ~Output        */
00054 /*                  */
00055 /************************************************************************/
00056 
00057 Output::~Output() { }
00058 
00059 /*      END OF FUNCTION ~Output        */
00060 
00061 /************************************************************************/
00062 /*                  */
00063 /*      FUNCTION coordinate        */
00064 /*                  */
00065 /*   INPUTS:                */
00066 /*  timestep - Timestep coordinates were accumulated for    */
00067 /*  n - This is the number of coordinates accumulated.    */
00068 /*  vel - Array of Vectors containing the velocities    */
00069 /*                  */
00070 /*  This function receives the coordinates accumulated for a given  */
00071 /*   timestep from the Collect object and calls the appropriate output  */
00072 /*   functions.  ALL routines used to output coordinates information    */
00073 /*   should be called from here.          */
00074 /*                  */
00075 /************************************************************************/
00076 
00077 int Output::coordinateNeeded(int timestep)
00078 {
00079   SimParameters *simParams = Node::Object()->simParameters;
00080 
00081   int positionsNeeded = 0;
00082 
00083   if ( timestep >= 0 ) {
00084 
00085     //  Output a DCD trajectory 
00086     if ( simParams->dcdFrequency &&
00087        ((timestep % simParams->dcdFrequency) == 0) )
00088     { positionsNeeded |= 1; }
00089 
00090     //  Output a restart file
00091     if ( simParams->restartFrequency &&
00092        ((timestep % simParams->restartFrequency) == 0) )
00093     { positionsNeeded |= 2; }
00094 
00095     //  Iteractive MD
00096     if ( simParams->IMDon &&
00097        ( ((timestep % simParams->IMDfreq) == 0) ||
00098          (timestep == simParams->firstTimestep) ) )
00099       { positionsNeeded |= 1; }
00100 
00101   }
00102 
00103   //  Output final coordinates
00104   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN ||
00105                                         timestep == EVAL_MEASURE)
00106   {
00107     positionsNeeded |= 2;
00108   }
00109 
00110   return positionsNeeded;
00111 }
00112 
00113 /*
00114  * In order to reduce memory usage, the conditions for calling
00115  * Molecule::get_cluster_size and Molecule::is_water are very important. 
00116  *
00117  * 1. If get_cluster_size is called (wrapAll==true or wrapWater==true), the cluster
00118  * information has to be maintained. And it is only needed to store on pe 1 (where CollectionMaster resides on)
00119  * if namd runs with more than 1 processors.
00120  *
00121  * 2. If is_water is called (wrapAll==false and wrapWater==true), the "hydrogenGroup" 
00122  * and "atoms" fields in Molecule object have to be maintained. And such fields are only needed to store on
00123  * pe 1 (where CollectionMaster resides on) if namd runs with more than 1 processors.
00124  */
00125 template <class xVector, class xDone>
00126 void wrap_coor_int(xVector *coor, Lattice &lattice, xDone *done) {
00127   SimParameters *simParams = Node::Object()->simParameters;
00128   if ( *done ) return;
00129   *done = 1;
00130   if ( ! ( simParams->wrapAll || simParams->wrapWater ) ) return;
00131   const int wrapNearest = simParams->wrapNearest;
00132   const int wrapAll = simParams->wrapAll;
00133   Molecule *molecule = Node::Object()->molecule;
00134   int n = molecule->numAtoms;
00135 #ifdef MEM_OPT_VERSION
00136   //iterate over every cluster
00137   for(int aid=0; aid<n;){
00138       int curClusterSize = molecule->get_cluster_size(aid);
00139       if(curClusterSize<0) NAMD_bug("Cluster size is less than 0 at wrap_coor_int");
00140       //we encountered the beginning of a cluster, and aid is the current cluster id          
00141       Position curClusterCon = 0;
00142       //This cluster begins from atom "aid" to atom "aid+curClusterSize-1"
00143       for(int i=aid; i<aid+curClusterSize; i++){
00144           curClusterCon += coor[i];
00145       }
00146 
00147       //The order of evaluating the following if-condition is very important since it
00148       //is related with reducting memory usage. Two points worth noting:
00149       //1. molecule->is_water is more expensive to evaluate, so evaluatte wrapAll first
00150       //2. if molecule->is_water is actually called, we have to reserve a memory space (O(numAtoms)) 
00151       //   for its correctness
00152       if(wrapAll || molecule->is_water(aid)){
00153           Vector coni = curClusterCon/curClusterSize;
00154           Vector trans = ( wrapNearest ? lattice.wrap_nearest_delta(coni) : lattice.wrap_delta(coni));
00155           curClusterCon = trans;
00156       }
00157       for(int i=aid; i<aid+curClusterSize; i++){
00158           if(!wrapAll && !molecule->is_water(i)) continue;
00159           coor[i] = coor[i] + curClusterCon;
00160       }
00161       aid += curClusterSize;
00162   }
00163 #else
00164   int i;
00165   Position *con = new Position[n];
00166   for ( i = 0; i < n; ++i ) {
00167     con[i] = 0;
00168     int ci = molecule->get_cluster(i);
00169     con[ci] += coor[i];
00170   }
00171   for ( i = 0; i < n; ++i ) {
00172     if ( ! wrapAll && ! molecule->is_water(i) ) continue;
00173     int ci = molecule->get_cluster(i);
00174     if ( ci == i ) {
00175       Vector coni = con[i] / molecule->get_clusterSize(i);
00176       Vector trans = ( wrapNearest ?
00177         lattice.wrap_nearest_delta(coni) : lattice.wrap_delta(coni) );
00178       con[i] = trans;
00179     }
00180     coor[i] = coor[i] + con[ci];
00181   }
00182   delete [] con;
00183 #endif
00184 }
00185 
00186 void wrap_coor(Vector *coor, Lattice &lattice, double *done) {
00187   wrap_coor_int(coor,lattice,done);
00188 };
00189 
00190 void wrap_coor(FloatVector *coor, Lattice &lattice, float *done) {
00191   wrap_coor_int(coor,lattice,done);
00192 };
00193 
00194 void Output::coordinate(int timestep, int n, Vector *coor, FloatVector *fcoor,
00195                                                         Lattice &lattice)
00196 {
00197   SimParameters *simParams = Node::Object()->simParameters;
00198   double coor_wrapped = 0;
00199   float fcoor_wrapped = 0;
00200 
00201   if ( timestep >= 0 ) {
00202 
00203     //  Output a DCD trajectory 
00204     if ( simParams->dcdFrequency &&
00205        ((timestep % simParams->dcdFrequency) == 0) )
00206     {
00207       wrap_coor(fcoor,lattice,&fcoor_wrapped);
00208       output_dcdfile(timestep, n, fcoor, 
00209           simParams->dcdUnitCell ? &lattice : NULL);
00210     }
00211 
00212     //  Output a restart file
00213     if ( simParams->restartFrequency &&
00214        ((timestep % simParams->restartFrequency) == 0) )
00215     {
00216       iout << "WRITING COORDINATES TO RESTART FILE AT STEP "
00217                                 << timestep << "\n" << endi;
00218       wrap_coor(coor,lattice,&coor_wrapped);
00219       output_restart_coordinates(coor, n, timestep);
00220       iout << "FINISHED WRITING RESTART COORDINATES\n" <<endi;
00221       fflush(stdout);
00222     }
00223 
00224     //  Interactive MD
00225     if ( simParams->IMDon &&
00226        ( ((timestep % simParams->IMDfreq) == 0) ||
00227          (timestep == simParams->firstTimestep) ) )
00228     {
00229       IMDOutput *imd = Node::Object()->imd;
00230       wrap_coor(fcoor,lattice,&fcoor_wrapped);
00231       if (imd != NULL) imd->gather_coordinates(timestep, n, fcoor);
00232     }
00233 
00234   }
00235 
00236   if (timestep == EVAL_MEASURE)
00237   {
00238 #ifdef NAMD_TCL
00239     wrap_coor(coor,lattice,&coor_wrapped);
00240     Node::Object()->getScript()->measure(coor);
00241 #endif
00242   }
00243 
00244   //  Output final coordinates
00245   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
00246   {
00247     iout << "WRITING COORDINATES TO OUTPUT FILE AT STEP "
00248                                 << simParams->N << "\n" << endi;
00249     fflush(stdout);
00250     wrap_coor(coor,lattice,&coor_wrapped);
00251     output_final_coordinates(coor, n, simParams->N);
00252   }
00253 
00254   //  Close trajectory files
00255   if (timestep == END_OF_RUN)
00256   {
00257     if (simParams->dcdFrequency) output_dcdfile(END_OF_RUN,0,0, 
00258         simParams->dcdUnitCell ? &lattice : NULL);
00259   }
00260 
00261 }
00262 /*    END OF FUNCTION coordinate        */
00263 
00264 /************************************************************************/
00265 /*                  */
00266 /*      FUNCTION velocity        */
00267 /*                  */
00268 /*   INPUTS:                */
00269 /*  timestep - Timestep velocities were accumulated for    */
00270 /*  n - This is the number of velocities accumulated.    */
00271 /*  vel - Array of Vectors containing the velocities    */
00272 /*                  */
00273 /*  This function receives the velocities accumulated for a given   */
00274 /*   timestep from the Collect object and calls the appropriate output  */
00275 /*   functions.  ALL routines used to output velocity information should*/
00276 /*   be called from here.            */
00277 /*                  */
00278 /************************************************************************/
00279 
00280 int Output::velocityNeeded(int timestep)
00281 {
00282   SimParameters *simParams = Node::Object()->simParameters;
00283 
00284   int velocitiesNeeded = 0;
00285 
00286   if ( timestep >= 0 ) {
00287 
00288     //  Output a velocity DCD trajectory
00289     if ( simParams->velDcdFrequency &&
00290        ((timestep % simParams->velDcdFrequency) == 0) )
00291       { velocitiesNeeded |= 1; }
00292 
00293     //  Output a restart file
00294     if ( simParams->restartFrequency &&
00295        ((timestep % simParams->restartFrequency) == 0) )
00296       { velocitiesNeeded |= 2; }
00297 
00298   }
00299 
00300   //  Output final velocities
00301   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
00302   {
00303     velocitiesNeeded |= 2;
00304   }
00305 
00306   return velocitiesNeeded;
00307 }
00308 
00309 void Output::velocity(int timestep, int n, Vector *vel)
00310 {
00311   SimParameters *simParams = Node::Object()->simParameters;
00312 
00313   if ( timestep >= 0 ) {
00314 
00315     //  Output velocity DCD trajectory
00316     if ( simParams->velDcdFrequency &&
00317        ((timestep % simParams->velDcdFrequency) == 0) )
00318     {
00319       output_veldcdfile(timestep, n, vel);
00320     }
00321 
00322   //  Output restart file
00323     if ( simParams->restartFrequency &&
00324        ((timestep % simParams->restartFrequency) == 0) )
00325     {
00326       iout << "WRITING VELOCITIES TO RESTART FILE AT STEP "
00327                                 << timestep << "\n" << endi;
00328       output_restart_velocities(timestep, n, vel);
00329       iout << "FINISHED WRITING RESTART VELOCITIES\n" <<endi;
00330       fflush(stdout);
00331     }
00332 
00333   }
00334 
00335   //  Output final velocities
00336   if (timestep == FILE_OUTPUT || timestep == END_OF_RUN)
00337   {
00338     iout << "WRITING VELOCITIES TO OUTPUT FILE AT STEP "
00339                                 << simParams->N << "\n" << endi;
00340     fflush(stdout);
00341     output_final_velocities(simParams->N, n, vel);
00342   }
00343 
00344   //  Close trajectory files
00345   if (timestep == END_OF_RUN)
00346   {
00347     if (simParams->velDcdFrequency) output_veldcdfile(END_OF_RUN,0,0);
00348   }
00349 
00350 }
00351 /*      END OF FUNCTION velocity      */
00352 
00353 /************************************************************************/
00354 /*                  */
00355 /*      FUNCTION output_restart_coordinates    */
00356 /*                  */
00357 /*   INPUTS:                */
00358 /*  coor - Array of vectors containing current positions    */
00359 /*  n - Number of coordinates to output        */
00360 /*  timestep - Timestep for which the coordinates are being written */
00361 /*                  */
00362 /*  This function writes out the current positions of all the atoms */
00363 /*   in PDB format to the restart file specified by the user in the   */
00364 /*   configuration file.            */
00365 /*                  */
00366 /************************************************************************/
00367 
00368 void Output::output_restart_coordinates(Vector *coor, int n, int timestep)
00369 
00370 {
00371   char comment[128];    //  Comment for header of PDB file
00372   char timestepstr[20];
00373 
00374   int baselen = strlen(namdMyNode->simParams->restartFilename);
00375   char *restart_name = new char[baselen+26];
00376 
00377   strcpy(restart_name, namdMyNode->simParams->restartFilename);
00378   if ( namdMyNode->simParams->restartSave ) {
00379     sprintf(timestepstr,".%d",timestep);
00380     strcat(restart_name, timestepstr);
00381   }
00382   strcat(restart_name, ".coor");
00383 
00384   NAMD_backup_file(restart_name,".old");
00385 
00386   //  Check to see if we should generate a binary or PDB file
00387   if (!namdMyNode->simParams->binaryRestart)
00388   {
00389     //  Generate a PDB restart file
00390     sprintf(comment, "RESTART COORDINATES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00391 
00392     namdMyNode->pdbData->set_all_positions(coor);
00393     namdMyNode->pdbData->write(restart_name, comment);
00394   }
00395   else
00396   {
00397     //  Generate a binary restart file
00398     write_binary_file(restart_name, n, coor);
00399   }
00400 
00401   delete [] restart_name;
00402 }
00403 /*      END OF FUNCTION output_restart_coordinates  */
00404 
00405 /************************************************************************/
00406 /*                  */
00407 /*      FUNCTION output_restart_velocities    */
00408 /*                  */
00409 /*   INPUTS:                */
00410 /*  vel - Array of vectors containing current velocities    */
00411 /*  timestep - Timestep for which the velocities are being written  */
00412 /*                  */
00413 /*  This function writes out the current velocites of all the atoms */
00414 /*   in PDB format to the restart file specified by the user in the   */
00415 /*   configuration file.            */
00416 /*                  */
00417 /************************************************************************/
00418 
00419 void Output::output_restart_velocities(int timestep, int n, Vector *vel)
00420 
00421 {
00422   char comment[128];    //  comment for the header of PDB file
00423   char timestepstr[20];
00424 
00425   int baselen = strlen(namdMyNode->simParams->restartFilename);
00426   char *restart_name = new char[baselen+26];
00427 
00428   strcpy(restart_name, namdMyNode->simParams->restartFilename);
00429   if ( namdMyNode->simParams->restartSave ) {
00430     sprintf(timestepstr,".%d",timestep);
00431     strcat(restart_name, timestepstr);
00432   }
00433   strcat(restart_name, ".vel");
00434 
00435   NAMD_backup_file(restart_name,".old");
00436 
00437   //  Check to see if we should write out a PDB or a binary file
00438   if (!namdMyNode->simParams->binaryRestart)
00439   {
00440     //  Write the coordinates to a PDB file.  Multiple them by 20
00441     //  first to make the numbers bigger
00442     sprintf(comment, "RESTART VELOCITIES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00443 
00444     scale_vels(vel, n, PDBVELFACTOR);
00445     namdMyNode->pdbData->set_all_positions(vel);
00446     namdMyNode->pdbData->write(restart_name, comment);
00447     scale_vels(vel, n, PDBVELINVFACTOR);
00448   }
00449   else
00450   {
00451     //  Write the velocities to a binary file
00452     write_binary_file(restart_name, n, vel);
00453   }
00454 
00455   delete [] restart_name;
00456 }
00457 /*      END OF FUNCTION output_restart_velocities  */
00458 
00459 /************************************************************************/
00460 /*                  */
00461 /*      FUNCTION output_dcdfile        */
00462 /*                  */
00463 /*   INPUTS:                */
00464 /*  timestep - Current timestep          */
00465 /*  n - Number of atoms in simulation        */
00466 /*  coor - Coordinate vectors for all atoms        */
00467 /*  lattice - periodic cell data; NULL if not to be written */
00468 /*                  */
00469 /*  This function maintains the interface between the Output object */
00470 /*   and the dcd writing routines contained in dcdlib.      */
00471 /*                  */
00472 /************************************************************************/
00473 
00474 #define RAD2DEG 180.0/3.14159265359
00475 
00476 void Output::output_dcdfile(int timestep, int n, FloatVector *coor,
00477     const Lattice *lattice)
00478 
00479 {
00480   static Bool first=TRUE;  //  Flag indicating first call
00481   static int fileid;  //  File id for the dcd file
00482 
00483 #ifndef MEM_OPT_VERSION
00484   static float *x, *y, *z; // Arrays to hold x, y, and z arrays
00485 #endif
00486   
00487   int i;      //  Loop counter
00488   int ret_code;    //  Return code from DCD calls
00489   SimParameters *simParams = namdMyNode->simParams;
00490 
00491   //  If this is the last time we will be writing coordinates,
00492   //  close the file before exiting
00493   if ( timestep == END_OF_RUN ) {
00494     if ( ! first ) {
00495       iout << "CLOSING COORDINATE DCD FILE\n" << endi;
00496       close_dcd_write(fileid);
00497     } else {
00498       iout << "COORDINATE DCD FILE WAS NOT CREATED\n" << endi;
00499     }
00500     return;
00501   }
00502 
00503   if (first)
00504   {
00505 #ifndef MEM_OPT_VERSION
00506     //  Allocate x, y, and z arrays since the DCD file routines
00507     //  need them passed as three independant arrays to be
00508     //  efficient
00509     x = new float[n];
00510     y = new float[n];
00511     z = new float[n];
00512 
00513     if ( (x==NULL) || (y==NULL) || (z==NULL) )
00514     {
00515       NAMD_err("memory allocation failed in Output::output_dcdfile");
00516     }
00517 #endif
00518 
00519     //  Open the DCD file
00520     iout << "OPENING COORDINATE DCD FILE\n" << endi;
00521 
00522     fileid=open_dcd_write(simParams->dcdFilename);
00523 
00524     if (fileid == DCD_FILEEXISTS)
00525     {
00526       char err_msg[257];
00527 
00528       sprintf(err_msg, "DCD file %s already exists!!",
00529         simParams->dcdFilename);
00530 
00531       NAMD_err(err_msg);
00532     }
00533     else if (fileid < 0)
00534     {
00535       char err_msg[257];
00536 
00537       sprintf(err_msg, "Couldn't open DCD file %s",
00538         simParams->dcdFilename);
00539 
00540       NAMD_err(err_msg);
00541     }
00542 
00543     int NSAVC, NFILE, NPRIV, NSTEP;
00544     NSAVC = simParams->dcdFrequency;
00545     NSTEP = NSAVC * (simParams->N/NSAVC);
00546     NPRIV = simParams->firstTimestep+NSAVC;
00547     NPRIV = NSAVC * (NPRIV/NSAVC);
00548     NFILE = (NSTEP-NPRIV)/NSAVC + 1;
00549 
00550     //  Write out the header
00551     ret_code = write_dcdheader(fileid, 
00552         simParams->dcdFilename,
00553         n, NFILE, NPRIV, NSAVC, NSTEP,
00554         simParams->dt/TIMEFACTOR, lattice != NULL);
00555 
00556 
00557     if (ret_code<0)
00558     {
00559       NAMD_err("Writing of DCD header failed!!");
00560     }
00561 
00562     first = FALSE;
00563   }
00564 
00565 #ifndef MEM_OPT_VERSION
00566   //  Copy the coordinates for output
00567   for (i=0; i<n; i++)
00568   {
00569     x[i] = coor[i].x;
00570     y[i] = coor[i].y;
00571     z[i] = coor[i].z;
00572   }
00573 #endif
00574 
00575   //  Write out the values for this timestep
00576   iout << "WRITING COORDINATES TO DCD FILE AT STEP "
00577         << timestep << "\n" << endi;
00578   fflush(stdout);
00579   if (lattice) {
00580     double unitcell[6];
00581     if (lattice->a_p() && lattice->b_p() && lattice->c_p()) {
00582       const Vector &a=lattice->a();
00583       const Vector &b=lattice->b();
00584       const Vector &c=lattice->c();
00585       unitcell[0] = a.length();
00586       unitcell[2] = b.length();
00587       unitcell[5] = c.length();
00588       double cosAB = (a*b)/(unitcell[0]*unitcell[2]);
00589       double cosAC = (a*c)/(unitcell[0]*unitcell[5]);
00590       double cosBC = (b*c)/(unitcell[2]*unitcell[5]);
00591       if (cosAB > 1.0) cosAB = 1.0; else if (cosAB < -1.0) cosAB = -1.0;
00592       if (cosAC > 1.0) cosAC = 1.0; else if (cosAC < -1.0) cosAC = -1.0;
00593       if (cosBC > 1.0) cosBC = 1.0; else if (cosBC < -1.0) cosBC = -1.0;
00594       unitcell[1] = cosAB;
00595       unitcell[3] = cosAC;
00596       unitcell[4] = cosBC;
00597     } else {
00598       unitcell[0] = unitcell[2] = unitcell[5] = 1.0;
00599       unitcell[1] = unitcell[3] = unitcell[4] = 0.0;
00600     }
00601 #ifdef MEM_OPT_VERSION
00602     ret_code = write_dcdstep(fileid, n, coor, unitcell);
00603 #else
00604     ret_code = write_dcdstep(fileid, n, x, y, z, unitcell);
00605 #endif
00606   } else {
00607 #ifdef MEM_OPT_VERSION
00608     ret_code = write_dcdstep(fileid, n, coor, NULL);
00609 #else
00610     ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
00611 #endif
00612   }
00613   if (ret_code < 0)
00614   {
00615     NAMD_err("Writing of DCD step failed!!");
00616   }
00617 
00618 }
00619 /*      END OF FUNCTION output_dcdfile      */
00620 
00621 /************************************************************************/
00622 /*                  */
00623 /*      FUNCTION output_final_coordinates    */
00624 /*                  */
00625 /*   INPUTS:                */
00626 /*  coor - Array of vectors containing final coordinates    */
00627 /*  n - Number of coordinates to output        */
00628 /*  timestep - Timestep that coordinates are being written in  */
00629 /*                  */
00630 /*  This function writes out the final coordinates for the    */
00631 /*   simulation in PDB format to the file specified in the config  */
00632 /*   file.                */
00633 /*                  */
00634 /************************************************************************/
00635 
00636 void Output::output_final_coordinates(Vector *coor, int n, int timestep)
00637 
00638 {
00639   char output_name[140];  //  Output filename
00640   char comment[128];    //  comment for PDB header
00641 
00642   //  Built the output filename
00643   strcpy(output_name, namdMyNode->simParams->outputFilename);
00644   strcat(output_name, ".coor");
00645 
00646   NAMD_backup_file(output_name);
00647 
00648   //  Check to see if we should write out a binary file or a
00649   //  PDB file
00650   if (!namdMyNode->simParams->binaryOutput)
00651   {
00652     sprintf(comment, "FINAL COORDINATES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00653 
00654     namdMyNode->pdbData->set_all_positions(coor);
00655     namdMyNode->pdbData->write(output_name, comment);
00656   }
00657   else
00658   {
00659     //  Write the velocities to a binary file
00660     write_binary_file(output_name, n, coor);
00661   }
00662 }
00663 /*    END OF FUNCTION output_final_coordinates    */
00664 
00665 /************************************************************************/
00666 /*                  */
00667 /*      FUNCTION output_final_velocities    */
00668 /*                  */
00669 /*   INPUTS:                */
00670 /*  vel - Array of vectors containing final velocities    */
00671 /*  timestep - Timestep that vleocities are being written in  */
00672 /*                  */
00673 /*  This function writes out the final vleocities for the    */
00674 /*   simulation in PDB format to the file specified in the config  */
00675 /*   file.                */
00676 /*                  */
00677 /************************************************************************/
00678 
00679 void Output::output_final_velocities(int timestep, int n, Vector *vel)
00680 
00681 {
00682   char output_name[140];  //  Output filename
00683   char comment[128];    //  Comment for PDB header
00684 
00685   //  Build the output filename
00686   strcpy(output_name, namdMyNode->simParams->outputFilename);
00687   strcat(output_name, ".vel");
00688 
00689   NAMD_backup_file(output_name);
00690 
00691   //  Check to see if we should write a PDB or binary file
00692   if (!(namdMyNode->simParams->binaryOutput))
00693   {
00694     //  Write the final velocities to a PDB file
00695     sprintf(comment, "FINAL VELOCITIES WRITTEN BY NAMD AT TIMESTEP %d", timestep);
00696 
00697     scale_vels(vel, n, PDBVELFACTOR);
00698     namdMyNode->pdbData->set_all_positions(vel);
00699     namdMyNode->pdbData->write(output_name, comment);
00700     scale_vels(vel, n, PDBVELINVFACTOR);
00701   }
00702   else
00703   {
00704     //  Write the coordinates to a binary file
00705     write_binary_file(output_name, n, vel);
00706   }
00707 
00708 }
00709 /*      END OF FUNCTION output_final_velocities    */
00710 
00711 /************************************************************************/
00712 /*                  */
00713 /*      FUNCTION output_veldcdfile      */
00714 /*                  */
00715 /*   INPUTS:                */
00716 /*  timestep - Current timestep          */
00717 /*  n - Number of atoms in simulation        */
00718 /*  coor - velocity vectors for all atoms        */
00719 /*                  */
00720 /*  This function maintains the interface between the Output object */
00721 /*   and the dcd writing routines contained in dcdlib.  This fucntion   */
00722 /*   writes out the velocity vectors in DCD format.      */
00723 /*                  */
00724 /************************************************************************/
00725 
00726 void Output::output_veldcdfile(int timestep, int n, Vector *vel)
00727 
00728 {
00729   static Bool first=TRUE;  //  Flag indicating first call
00730   static int fileid;  //  File id for the dcd file
00731   static float *x, *y, *z; // Arrays to hold x, y, and z arrays
00732   int i;      //  Loop counter
00733   int ret_code;    //  Return code from DCD calls
00734   SimParameters *simParams = Node::Object()->simParameters;
00735 
00736   //  If this is the last time we will be writing coordinates,
00737   //  close the file before exiting
00738   if ( timestep == END_OF_RUN ) {
00739     if ( ! first ) {
00740       iout << "CLOSING VELOCITY DCD FILE\n" << endi;
00741       close_dcd_write(fileid);
00742     } else {
00743       iout << "VELOCITY DCD FILE WAS NOT CREATED\n" << endi;
00744     }
00745     return;
00746   }
00747 
00748   if (first)
00749   {
00750     //  Allocate x, y, and z arrays since the DCD file routines
00751     //  need them passed as three independant arrays to be
00752     //  efficient
00753     x = new float[n];
00754     y = new float[n];
00755     z = new float[n];
00756 
00757     if ( (x==NULL) || (y==NULL) || (z==NULL) )
00758     {
00759       NAMD_err("memory allocation failed in Output::output_veldcdfile");
00760     }
00761 
00762     //  Open the DCD file
00763     iout << "OPENING VELOCITY DCD FILE\n" << endi;
00764 
00765     fileid=open_dcd_write(namdMyNode->simParams->velDcdFilename);
00766 
00767     if (fileid == DCD_FILEEXISTS)
00768     {
00769       char err_msg[257];
00770 
00771       sprintf(err_msg, "Velocity DCD file %s already exists!!",
00772         namdMyNode->simParams->velDcdFilename);
00773 
00774       NAMD_err(err_msg);
00775     }
00776     else if (fileid < 0)
00777     {
00778       char err_msg[257];
00779 
00780       sprintf(err_msg, "Couldn't open velocity DCD file %s",
00781         namdMyNode->simParams->velDcdFilename);
00782 
00783       NAMD_err(err_msg);
00784     }
00785 
00786     int NSAVC, NFILE, NPRIV, NSTEP;
00787     NSAVC = simParams->velDcdFrequency;
00788     NSTEP = NSAVC * (simParams->N/NSAVC);
00789     NPRIV = simParams->firstTimestep+NSAVC;
00790     NPRIV = NSAVC * (NPRIV/NSAVC);
00791     NFILE = (NSTEP-NPRIV)/NSAVC + 1;
00792 
00793     //  Write out the header
00794     const int with_unitcell = 0;
00795     ret_code = write_dcdheader(fileid, 
00796         simParams->velDcdFilename,
00797         n, NFILE, NPRIV, NSAVC, NSTEP,
00798         simParams->dt/TIMEFACTOR, with_unitcell);
00799 
00800 
00801     if (ret_code<0)
00802     {
00803       NAMD_err("Writing of velocity DCD header failed!!");
00804     }
00805 
00806     first = FALSE;
00807   }
00808 
00809   //  Copy the coordinates for output
00810   for (i=0; i<n; i++)
00811   {
00812     x[i] = vel[i].x;
00813     y[i] = vel[i].y;
00814     z[i] = vel[i].z;
00815   }
00816 
00817   //  Write out the values for this timestep
00818   iout << "WRITING VELOCITIES TO DCD FILE AT STEP "
00819         << timestep << "\n" << endi;
00820   fflush(stdout);
00821   ret_code = write_dcdstep(fileid, n, x, y, z, NULL);
00822 
00823   if (ret_code < 0)
00824   {
00825     NAMD_err("Writing of velocity DCD step failed!!");
00826   }
00827 
00828 }
00829 /*      END OF FUNCTION output_veldcdfile    */
00830 
00831 /************************************************************************/
00832 /*                  */
00833 /*      FUNCTION write_binary_file      */
00834 /*                  */
00835 /*   INPUTS:                */
00836 /*  fname - file name to write velocities to      */
00837 /*  n - Number of atoms in system          */
00838 /*  vels - Array of vectors            */
00839 /*                  */
00840 /*  This function writes out vectors in binary format to    */
00841 /*   the specified file.            */
00842 /*                  */
00843 /************************************************************************/
00844 
00845 void Output::write_binary_file(char *fname, int n, Vector *vecs)
00846 
00847 {
00848   FILE *fp;    //  File descriptor
00849   int32 n32 = n;
00850 
00851   //  open the file and die if the open fails
00852   if ( (fp = fopen(fname, "wb")) == NULL)
00853   {
00854     char errmsg[256];
00855 
00856     sprintf(errmsg, "Unable to open binary file %s", fname);
00857     NAMD_err(errmsg);
00858   }
00859 
00860   //  Write out the number of atoms and the vectors
00861   fwrite(&n32, sizeof(int32), 1, fp);
00862   fwrite(vecs, sizeof(Vector), n, fp);
00863 
00864   if ( ferror(fp) || fclose(fp) )
00865   {
00866     char errmsg[256];
00867 
00868     sprintf(errmsg, "Error on write to binary file %s", fname);
00869     NAMD_err(errmsg);
00870   }
00871 }
00872 /*      END OF FUNCTION write_binary_file    */
00873 
00874 /************************************************************************/
00875 /*                  */
00876 /*      FUNCTION scale_vels        */
00877 /*                  */
00878 /*   INPUTS:                */
00879 /*  v - Array of velocity vectors          */
00880 /*  n - Number of atoms in system          */
00881 /*  fact - Scaling factor            */
00882 /*                  */
00883 /*  This function scales all the vectors passed in by a constant  */
00884 /*   factor.  This is used before writing out velocity vectors that  */
00885 /*   need to be resized.            */
00886 /*                  */
00887 /************************************************************************/
00888 
00889 void Output::scale_vels(Vector *v, int n, Real fact)
00890 
00891 {
00892   int i;
00893 
00894   for (i=0; i<n; i++)
00895   {
00896     v[i].x *= fact;
00897     v[i].y *= fact;
00898     v[i].z *= fact;
00899   }
00900 }
00901 /*      END OF FUNCTION scale_vels      */
00902 

Generated on Sat Oct 11 04:07:42 2008 for NAMD by  doxygen 1.3.9.1