00001
00007
00008
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
00034 #define namdMyNode Node::Object()
00035 #define simParams simParameters
00036 #define pdbData pdb
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 Output::Output() { }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 Output::~Output() { }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
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
00086 if ( simParams->dcdFrequency &&
00087 ((timestep % simParams->dcdFrequency) == 0) )
00088 { positionsNeeded |= 1; }
00089
00090
00091 if ( simParams->restartFrequency &&
00092 ((timestep % simParams->restartFrequency) == 0) )
00093 { positionsNeeded |= 2; }
00094
00095
00096 if ( simParams->IMDon &&
00097 ( ((timestep % simParams->IMDfreq) == 0) ||
00098 (timestep == simParams->firstTimestep) ) )
00099 { positionsNeeded |= 1; }
00100
00101 }
00102
00103
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
00115
00116
00117
00118
00119
00120
00121
00122
00123
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
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
00141 Position curClusterCon = 0;
00142
00143 for(int i=aid; i<aid+curClusterSize; i++){
00144 curClusterCon += coor[i];
00145 }
00146
00147
00148
00149
00150
00151
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
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
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
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
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
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
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
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
00289 if ( simParams->velDcdFrequency &&
00290 ((timestep % simParams->velDcdFrequency) == 0) )
00291 { velocitiesNeeded |= 1; }
00292
00293
00294 if ( simParams->restartFrequency &&
00295 ((timestep % simParams->restartFrequency) == 0) )
00296 { velocitiesNeeded |= 2; }
00297
00298 }
00299
00300
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
00316 if ( simParams->velDcdFrequency &&
00317 ((timestep % simParams->velDcdFrequency) == 0) )
00318 {
00319 output_veldcdfile(timestep, n, vel);
00320 }
00321
00322
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
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
00345 if (timestep == END_OF_RUN)
00346 {
00347 if (simParams->velDcdFrequency) output_veldcdfile(END_OF_RUN,0,0);
00348 }
00349
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 void Output::output_restart_coordinates(Vector *coor, int n, int timestep)
00369
00370 {
00371 char comment[128];
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
00387 if (!namdMyNode->simParams->binaryRestart)
00388 {
00389
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
00398 write_binary_file(restart_name, n, coor);
00399 }
00400
00401 delete [] restart_name;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 void Output::output_restart_velocities(int timestep, int n, Vector *vel)
00420
00421 {
00422 char comment[128];
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
00438 if (!namdMyNode->simParams->binaryRestart)
00439 {
00440
00441
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
00452 write_binary_file(restart_name, n, vel);
00453 }
00454
00455 delete [] restart_name;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
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;
00481 static int fileid;
00482
00483 #ifndef MEM_OPT_VERSION
00484 static float *x, *y, *z;
00485 #endif
00486
00487 int i;
00488 int ret_code;
00489 SimParameters *simParams = namdMyNode->simParams;
00490
00491
00492
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
00507
00508
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
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
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
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
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
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void Output::output_final_coordinates(Vector *coor, int n, int timestep)
00637
00638 {
00639 char output_name[140];
00640 char comment[128];
00641
00642
00643 strcpy(output_name, namdMyNode->simParams->outputFilename);
00644 strcat(output_name, ".coor");
00645
00646 NAMD_backup_file(output_name);
00647
00648
00649
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
00660 write_binary_file(output_name, n, coor);
00661 }
00662 }
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 void Output::output_final_velocities(int timestep, int n, Vector *vel)
00680
00681 {
00682 char output_name[140];
00683 char comment[128];
00684
00685
00686 strcpy(output_name, namdMyNode->simParams->outputFilename);
00687 strcat(output_name, ".vel");
00688
00689 NAMD_backup_file(output_name);
00690
00691
00692 if (!(namdMyNode->simParams->binaryOutput))
00693 {
00694
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
00705 write_binary_file(output_name, n, vel);
00706 }
00707
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 void Output::output_veldcdfile(int timestep, int n, Vector *vel)
00727
00728 {
00729 static Bool first=TRUE;
00730 static int fileid;
00731 static float *x, *y, *z;
00732 int i;
00733 int ret_code;
00734 SimParameters *simParams = Node::Object()->simParameters;
00735
00736
00737
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
00751
00752
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
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
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
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
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
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 void Output::write_binary_file(char *fname, int n, Vector *vecs)
00846
00847 {
00848 FILE *fp;
00849 int32 n32 = n;
00850
00851
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
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
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
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
00902