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

Generated on Mon Nov 23 04:59:22 2009 for NAMD by  doxygen 1.3.9.1