00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "largefiles.h"
00046
00047 #include <stdio.h>
00048 #include <sys/stat.h>
00049 #include <sys/types.h>
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include <math.h>
00053 #include <time.h>
00054 #include "endianswap.h"
00055 #include "fastio.h"
00056 #include "molfile_plugin.h"
00057
00058 #ifndef M_PI_2
00059 #define M_PI_2 1.57079632679489661922
00060 #endif
00061
00062 #define RECSCALE32BIT 1
00063 #define RECSCALE64BIT 2
00064 #define RECSCALEMAX 2
00065
00066 typedef struct {
00067 fio_fd fd;
00068 int natoms;
00069 int nsets;
00070 int setsread;
00071 int istart;
00072 int nsavc;
00073 double delta;
00074 int nfixed;
00075 float *x, *y, *z;
00076 int *freeind;
00077 float *fixedcoords;
00078 int reverse;
00079 int charmm;
00080 int first;
00081 int with_unitcell;
00082 } dcdhandle;
00083
00084
00085 #define DCD_SUCCESS 0
00086 #define DCD_EOF -1
00087 #define DCD_DNE -2
00088 #define DCD_OPENFAILED -3
00089 #define DCD_BADREAD -4
00090 #define DCD_BADEOF -5
00091 #define DCD_BADFORMAT -6
00092 #define DCD_FILEEXISTS -7
00093 #define DCD_BADMALLOC -8
00094 #define DCD_BADWRITE -9
00095
00096
00097 #define DCD_IS_XPLOR 0x00
00098 #define DCD_IS_CHARMM 0x01
00099 #define DCD_HAS_4DIMS 0x02
00100 #define DCD_HAS_EXTRA_BLOCK 0x04
00101 #define DCD_HAS_64BIT_REC 0x08
00102
00103
00104 #define NFILE_POS 8L
00105 #define NSTEP_POS 20L
00106
00107
00108 #define READ(fd, buf, size) fio_fread(((void *) buf), (size), 1, (fd))
00109
00110
00111 #define WRITE(fd, buf, size) fio_fwrite(((void *) buf), (size), 1, (fd))
00112
00113
00114 #define CHECK_FREAD(X, msg) if (X==-1) { return(DCD_BADREAD); }
00115 #define CHECK_FEOF(X, msg) if (X==0) { return(DCD_BADEOF); }
00116
00117
00118
00119 static void print_dcderror(const char *func, int errcode) {
00120 const char *errstr;
00121
00122 switch (errcode) {
00123 case DCD_EOF: errstr = "end of file"; break;
00124 case DCD_DNE: errstr = "file not found"; break;
00125 case DCD_OPENFAILED: errstr = "file open failed"; break;
00126 case DCD_BADREAD: errstr = "error during read"; break;
00127 case DCD_BADEOF: errstr = "premature end of file"; break;
00128 case DCD_BADFORMAT: errstr = "corruption or unrecognized file structure"; break;
00129 case DCD_FILEEXISTS: errstr = "output file already exists"; break;
00130 case DCD_BADMALLOC: errstr = "memory allocation failed"; break;
00131 case DCD_BADWRITE: errstr = "error during write"; break;
00132 case DCD_SUCCESS:
00133 default:
00134 errstr = "no error";
00135 break;
00136 }
00137 printf("dcdplugin) %s: %s\n", func, errstr);
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 static int read_dcdheader(fio_fd fd, int *N, int *NSET, int *ISTART,
00156 int *NSAVC, double *DELTA, int *NAMNF,
00157 int **FREEINDEXES, float **fixedcoords, int *reverseEndian,
00158 int *charmm)
00159 {
00160 unsigned int input_integer[2];
00161 int i, ret_val, rec_scale;
00162 char hdrbuf[84];
00163 int NTITLE;
00164 int dcdcordmagic;
00165 char *corp = (char *) &dcdcordmagic;
00166
00167
00168 corp[0] = 'C';
00169 corp[1] = 'O';
00170 corp[2] = 'R';
00171 corp[3] = 'D';
00172
00173
00174
00175
00176
00177 ret_val = READ(fd, input_integer, 2*sizeof(unsigned int));
00178 CHECK_FREAD(ret_val, "reading first int from dcd file");
00179 CHECK_FEOF(ret_val, "reading first int from dcd file");
00180
00181
00182 if ((input_integer[0]+input_integer[1]) == 84) {
00183 *reverseEndian=0;
00184 rec_scale=RECSCALE64BIT;
00185 printf("dcdplugin) detected CHARMM -i8 64-bit DCD file of native endianness\n");
00186 } else if (input_integer[0] == 84 && input_integer[1] == dcdcordmagic) {
00187 *reverseEndian=0;
00188 rec_scale=RECSCALE32BIT;
00189 printf("dcdplugin) detected standard 32-bit DCD file of native endianness\n");
00190 } else {
00191
00192 swap4_aligned(input_integer, 2);
00193 if ((input_integer[0]+input_integer[1]) == 84) {
00194 *reverseEndian=1;
00195 rec_scale=RECSCALE64BIT;
00196 printf("dcdplugin) detected CHARMM -i8 64-bit DCD file of opposite endianness\n");
00197 } else {
00198 swap4_aligned(&input_integer[1], 1);
00199 if (input_integer[0] == 84 && input_integer[1] == dcdcordmagic) {
00200 *reverseEndian=1;
00201 rec_scale=RECSCALE32BIT;
00202 printf("dcdplugin) detected standard 32-bit DCD file of opposite endianness\n");
00203 } else {
00204
00205 printf("dcdplugin) unrecognized DCD header:\n");
00206 printf("dcdplugin) [0]: %10d [1]: %10d\n", input_integer[0], input_integer[1]);
00207 printf("dcdplugin) [0]: 0x%08x [1]: 0x%08x\n", input_integer[0], input_integer[1]);
00208 return DCD_BADFORMAT;
00209
00210 }
00211 }
00212 }
00213
00214
00215 if (rec_scale == RECSCALE64BIT) {
00216 ret_val = READ(fd, input_integer, sizeof(unsigned int));
00217 if (input_integer[0] != dcdcordmagic) {
00218 printf("dcdplugin) failed to find CORD magic in CHARMM -i8 64-bit DCD file\n");
00219 return DCD_BADFORMAT;
00220 }
00221 }
00222
00223
00224 ret_val = READ(fd, hdrbuf, 80);
00225 CHECK_FREAD(ret_val, "buffering header");
00226 CHECK_FEOF(ret_val, "buffering header");
00227
00228
00229
00230
00231
00232 if (*((int *) (hdrbuf + 76)) != 0) {
00233 (*charmm) = DCD_IS_CHARMM;
00234 if (*((int *) (hdrbuf + 40)) != 0)
00235 (*charmm) |= DCD_HAS_EXTRA_BLOCK;
00236
00237 if (*((int *) (hdrbuf + 44)) == 1)
00238 (*charmm) |= DCD_HAS_4DIMS;
00239
00240 if (rec_scale == RECSCALE64BIT)
00241 (*charmm) |= DCD_HAS_64BIT_REC;
00242
00243 } else {
00244 (*charmm) = DCD_IS_XPLOR;
00245 }
00246
00247 if (*charmm & DCD_IS_CHARMM) {
00248
00249 printf("dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)\n");
00250 } else {
00251
00252 printf("dcdplugin) X-PLOR format DCD file (also NAMD 2.0 and earlier)\n");
00253 }
00254
00255
00256 (*NSET) = *((int *) (hdrbuf));
00257 if (*reverseEndian) swap4_unaligned(NSET, 1);
00258
00259
00260 (*ISTART) = *((int *) (hdrbuf + 4));
00261 if (*reverseEndian) swap4_unaligned(ISTART, 1);
00262
00263
00264 (*NSAVC) = *((int *) (hdrbuf + 8));
00265 if (*reverseEndian) swap4_unaligned(NSAVC, 1);
00266
00267
00268 (*NAMNF) = *((int *) (hdrbuf + 32));
00269 if (*reverseEndian) swap4_unaligned(NAMNF, 1);
00270
00271
00272
00273 if ((*charmm) & DCD_IS_CHARMM) {
00274 float ftmp;
00275 ftmp = *((float *)(hdrbuf+36));
00276 if (*reverseEndian)
00277 swap4_aligned(&ftmp, 1);
00278
00279 *DELTA = (double)ftmp;
00280 } else {
00281 (*DELTA) = *((double *)(hdrbuf + 36));
00282 if (*reverseEndian) swap8_unaligned(DELTA, 1);
00283 }
00284
00285
00286 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00287 CHECK_FREAD(ret_val, "reading second 84 from dcd file");
00288 CHECK_FEOF(ret_val, "reading second 84 from dcd file");
00289 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00290
00291 if (rec_scale == RECSCALE64BIT) {
00292 if ((input_integer[0]+input_integer[1]) != 84) {
00293 return DCD_BADFORMAT;
00294 }
00295 } else {
00296 if (input_integer[0] != 84) {
00297 return DCD_BADFORMAT;
00298 }
00299 }
00300
00301
00302 input_integer[1] = 0;
00303 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00304 CHECK_FREAD(ret_val, "reading size of title block");
00305 CHECK_FEOF(ret_val, "reading size of title block");
00306 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00307
00308 if ((((input_integer[0]+input_integer[1])-4) % 80) == 0) {
00309
00310 ret_val = READ(fd, &NTITLE, sizeof(int));
00311 CHECK_FREAD(ret_val, "reading NTITLE");
00312 CHECK_FEOF(ret_val, "reading NTITLE");
00313 if (*reverseEndian) swap4_aligned(&NTITLE, 1);
00314
00315 for (i=0; i<NTITLE; i++) {
00316 fio_fseek(fd, 80, FIO_SEEK_CUR);
00317 CHECK_FEOF(ret_val, "reading TITLE");
00318 }
00319
00320
00321 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00322 CHECK_FREAD(ret_val, "reading size of title block");
00323 CHECK_FEOF(ret_val, "reading size of title block");
00324 } else {
00325 return DCD_BADFORMAT;
00326 }
00327
00328
00329 input_integer[1] = 0;
00330 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00331
00332 CHECK_FREAD(ret_val, "reading a '4'");
00333 CHECK_FEOF(ret_val, "reading a '4'");
00334 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00335
00336 if ((input_integer[0]+input_integer[1]) != 4) {
00337 return DCD_BADFORMAT;
00338 }
00339
00340
00341 ret_val = READ(fd, N, sizeof(int));
00342 CHECK_FREAD(ret_val, "reading number of atoms");
00343 CHECK_FEOF(ret_val, "reading number of atoms");
00344 if (*reverseEndian) swap4_aligned(N, 1);
00345
00346
00347 input_integer[1] = 0;
00348 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00349 CHECK_FREAD(ret_val, "reading a '4'");
00350 CHECK_FEOF(ret_val, "reading a '4'");
00351 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00352
00353 if ((input_integer[0]+input_integer[1]) != 4) {
00354 return DCD_BADFORMAT;
00355 }
00356
00357 *FREEINDEXES = NULL;
00358 *fixedcoords = NULL;
00359 if (*NAMNF != 0) {
00360 (*FREEINDEXES) = (int *) calloc(((*N)-(*NAMNF)), sizeof(int));
00361 if (*FREEINDEXES == NULL)
00362 return DCD_BADMALLOC;
00363
00364 *fixedcoords = (float *) calloc((*N)*4 - (*NAMNF), sizeof(float));
00365 if (*fixedcoords == NULL)
00366 return DCD_BADMALLOC;
00367
00368
00369 input_integer[1]=0;
00370 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00371 CHECK_FREAD(ret_val, "reading size of index array");
00372 CHECK_FEOF(ret_val, "reading size of index array");
00373 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00374
00375 if ((input_integer[0]+input_integer[1]) != ((*N)-(*NAMNF))*4) {
00376 return DCD_BADFORMAT;
00377 }
00378
00379 ret_val = READ(fd, (*FREEINDEXES), ((*N)-(*NAMNF))*sizeof(int));
00380 CHECK_FREAD(ret_val, "reading size of index array");
00381 CHECK_FEOF(ret_val, "reading size of index array");
00382
00383 if (*reverseEndian)
00384 swap4_aligned((*FREEINDEXES), ((*N)-(*NAMNF)));
00385
00386 input_integer[1]=0;
00387 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00388 CHECK_FREAD(ret_val, "reading size of index array");
00389 CHECK_FEOF(ret_val, "reading size of index array");
00390 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00391
00392 if ((input_integer[0]+input_integer[1]) != ((*N)-(*NAMNF))*4) {
00393 return DCD_BADFORMAT;
00394 }
00395 }
00396
00397 return DCD_SUCCESS;
00398 }
00399
00400 static int read_charmm_extrablock(fio_fd fd, int charmm, int reverseEndian,
00401 float *unitcell) {
00402 int i, input_integer[2], rec_scale;
00403
00404 if (charmm & DCD_HAS_64BIT_REC) {
00405 rec_scale = RECSCALE64BIT;
00406 } else {
00407 rec_scale = RECSCALE32BIT;
00408 }
00409
00410 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_EXTRA_BLOCK)) {
00411
00412 input_integer[1] = 0;
00413 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale)
00414 return DCD_BADREAD;
00415 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00416 if ((input_integer[0]+input_integer[1]) == 48) {
00417 double tmp[6];
00418 if (fio_fread(tmp, 48, 1, fd) != 1) return DCD_BADREAD;
00419 if (reverseEndian)
00420 swap8_aligned(tmp, 6);
00421 for (i=0; i<6; i++) unitcell[i] = (float)tmp[i];
00422 } else {
00423
00424 if (fio_fseek(fd, (input_integer[0]+input_integer[1]), FIO_SEEK_CUR)) return DCD_BADREAD;
00425 }
00426 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00427 }
00428
00429 return DCD_SUCCESS;
00430 }
00431
00432 static int read_fixed_atoms(fio_fd fd, int N, int num_free, const int *indexes,
00433 int reverseEndian, const float *fixedcoords,
00434 float *freeatoms, float *pos, int charmm) {
00435 int i, input_integer[2], rec_scale;
00436
00437 if(charmm & DCD_HAS_64BIT_REC) {
00438 rec_scale=RECSCALE64BIT;
00439 } else {
00440 rec_scale=RECSCALE32BIT;
00441 }
00442
00443
00444 input_integer[1]=0;
00445 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00446 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00447 if ((input_integer[0]+input_integer[1]) != 4*num_free) return DCD_BADFORMAT;
00448
00449
00450 if (fio_fread(freeatoms, 4*num_free, 1, fd) != 1) return DCD_BADREAD;
00451 if (reverseEndian)
00452 swap4_aligned(freeatoms, num_free);
00453
00454
00455 memcpy(pos, fixedcoords, 4*N);
00456 for (i=0; i<num_free; i++)
00457 pos[indexes[i]-1] = freeatoms[i];
00458
00459
00460 input_integer[1]=0;
00461 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00462 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00463 if ((input_integer[0]+input_integer[1]) != 4*num_free) return DCD_BADFORMAT;
00464
00465 return DCD_SUCCESS;
00466 }
00467
00468 static int read_charmm_4dim(fio_fd fd, int charmm, int reverseEndian) {
00469 int input_integer[2],rec_scale;
00470
00471 if (charmm & DCD_HAS_64BIT_REC) {
00472 rec_scale=RECSCALE64BIT;
00473 } else {
00474 rec_scale=RECSCALE32BIT;
00475 }
00476
00477
00478
00479 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_4DIMS)) {
00480 input_integer[1]=0;
00481 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00482 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00483 if (fio_fseek(fd, (input_integer[0]+input_integer[1]), FIO_SEEK_CUR)) return DCD_BADREAD;
00484 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00485 }
00486
00487 return DCD_SUCCESS;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 static int read_dcdstep(fio_fd fd, int N, float *X, float *Y, float *Z,
00505 float *unitcell, int num_fixed,
00506 int first, int *indexes, float *fixedcoords,
00507 int reverseEndian, int charmm) {
00508 int ret_val, rec_scale;
00509
00510 if (charmm & DCD_HAS_64BIT_REC) {
00511 rec_scale=RECSCALE64BIT;
00512 } else {
00513 rec_scale=RECSCALE32BIT;
00514 }
00515
00516 if ((num_fixed==0) || first) {
00517
00518
00519 int tmpbuf[6*RECSCALEMAX];
00520
00521 fio_iovec iov[7];
00522 fio_size_t readlen;
00523 int i;
00524
00525
00526
00527
00528
00529
00530
00531
00532 ret_val = read_charmm_extrablock(fd, charmm, reverseEndian, unitcell);
00533 if (ret_val) return ret_val;
00534
00535
00536 iov[0].iov_base = (fio_caddr_t) &tmpbuf[0];
00537 iov[0].iov_len = rec_scale*sizeof(int);
00538
00539 iov[1].iov_base = (fio_caddr_t) X;
00540 iov[1].iov_len = sizeof(float)*N;
00541
00542 iov[2].iov_base = (fio_caddr_t) &tmpbuf[1*rec_scale];
00543 iov[2].iov_len = rec_scale*sizeof(int) * 2;
00544
00545 iov[3].iov_base = (fio_caddr_t) Y;
00546 iov[3].iov_len = sizeof(float)*N;
00547
00548 iov[4].iov_base = (fio_caddr_t) &tmpbuf[3*rec_scale];
00549 iov[4].iov_len = rec_scale*sizeof(int) * 2;
00550
00551 iov[5].iov_base = (fio_caddr_t) Z;
00552 iov[5].iov_len = sizeof(float)*N;
00553
00554 iov[6].iov_base = (fio_caddr_t) &tmpbuf[5*rec_scale];
00555 iov[6].iov_len = rec_scale*sizeof(int);
00556
00557 readlen = fio_readv(fd, &iov[0], 7);
00558
00559 if (readlen != (rec_scale*6*sizeof(int) + 3*N*sizeof(float)))
00560 return DCD_BADREAD;
00561
00562
00563 if (reverseEndian) {
00564 swap4_aligned(&tmpbuf[0], rec_scale*6);
00565 swap4_aligned(X, N);
00566 swap4_aligned(Y, N);
00567 swap4_aligned(Z, N);
00568 }
00569
00570
00571 if(rec_scale == 1) {
00572 for (i=0; i<6; i++) {
00573 if (tmpbuf[i] != sizeof(float)*N) return DCD_BADFORMAT;
00574 }
00575 } else {
00576 for (i=0; i<6; i++) {
00577 if ((tmpbuf[2*i]+tmpbuf[2*i+1]) != sizeof(float)*N) return DCD_BADFORMAT;
00578 }
00579 }
00580
00581
00582
00583 if (num_fixed && first) {
00584 memcpy(fixedcoords, X, N*sizeof(float));
00585 memcpy(fixedcoords+N, Y, N*sizeof(float));
00586 memcpy(fixedcoords+2*N, Z, N*sizeof(float));
00587 }
00588
00589
00590
00591
00592
00593 ret_val = read_charmm_4dim(fd, charmm, reverseEndian);
00594 if (ret_val) return ret_val;
00595 } else {
00596
00597
00598 ret_val = read_charmm_extrablock(fd, charmm, reverseEndian, unitcell);
00599 if (ret_val) return ret_val;
00600 ret_val = read_fixed_atoms(fd, N, N-num_fixed, indexes, reverseEndian,
00601 fixedcoords, fixedcoords+3*N, X, charmm);
00602 if (ret_val) return ret_val;
00603 ret_val = read_fixed_atoms(fd, N, N-num_fixed, indexes, reverseEndian,
00604 fixedcoords+N, fixedcoords+3*N, Y, charmm);
00605 if (ret_val) return ret_val;
00606 ret_val = read_fixed_atoms(fd, N, N-num_fixed, indexes, reverseEndian,
00607 fixedcoords+2*N, fixedcoords+3*N, Z, charmm);
00608 if (ret_val) return ret_val;
00609 ret_val = read_charmm_4dim(fd, charmm, reverseEndian);
00610 if (ret_val) return ret_val;
00611 }
00612
00613 return DCD_SUCCESS;
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 static int skip_dcdstep(fio_fd fd, int natoms, int nfixed, int charmm) {
00629
00630 int seekoffset = 0;
00631 int rec_scale;
00632
00633 if (charmm & DCD_HAS_64BIT_REC) {
00634 rec_scale=RECSCALE64BIT;
00635 } else {
00636 rec_scale=RECSCALE32BIT;
00637 }
00638
00639
00640 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_EXTRA_BLOCK)) {
00641 seekoffset += 4*rec_scale + 48 + 4*rec_scale;
00642 }
00643
00644
00645 seekoffset += 3 * (2*rec_scale + natoms - nfixed) * 4;
00646
00647
00648 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_4DIMS)) {
00649 seekoffset += (2*rec_scale + natoms - nfixed) * 4;
00650 }
00651
00652 if (fio_fseek(fd, seekoffset, FIO_SEEK_CUR)) return DCD_BADEOF;
00653
00654 return DCD_SUCCESS;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 static int write_dcdstep(fio_fd fd, int curframe, int curstep, int N,
00669 const float *X, const float *Y, const float *Z,
00670 const double *unitcell, int charmm) {
00671 int out_integer;
00672
00673 if (charmm) {
00674
00675 if (unitcell != NULL) {
00676 out_integer = 48;
00677 fio_write_int32(fd, out_integer);
00678 WRITE(fd, unitcell, out_integer);
00679 fio_write_int32(fd, out_integer);
00680 }
00681 }
00682
00683
00684 out_integer = N*4;
00685 fio_write_int32(fd, out_integer);
00686 if (fio_fwrite((void *) X, out_integer, 1, fd) != 1) return DCD_BADWRITE;
00687 fio_write_int32(fd, out_integer);
00688 fio_write_int32(fd, out_integer);
00689 if (fio_fwrite((void *) Y, out_integer, 1, fd) != 1) return DCD_BADWRITE;
00690 fio_write_int32(fd, out_integer);
00691 fio_write_int32(fd, out_integer);
00692 if (fio_fwrite((void *) Z, out_integer, 1, fd) != 1) return DCD_BADWRITE;
00693 fio_write_int32(fd, out_integer);
00694
00695
00696 fio_fseek(fd, NFILE_POS, FIO_SEEK_SET);
00697 fio_write_int32(fd, curframe);
00698 fio_fseek(fd, NSTEP_POS, FIO_SEEK_SET);
00699 fio_write_int32(fd, curstep);
00700 fio_fseek(fd, 0, FIO_SEEK_END);
00701
00702 return DCD_SUCCESS;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 static int write_dcdheader(fio_fd fd, const char *remarks, int N,
00715 int ISTART, int NSAVC, double DELTA, int with_unitcell,
00716 int charmm) {
00717 int out_integer;
00718 float out_float;
00719 char title_string[200];
00720 time_t cur_time;
00721 struct tm *tmbuf;
00722 char time_str[81];
00723
00724 out_integer = 84;
00725 WRITE(fd, (char *) & out_integer, sizeof(int));
00726 strcpy(title_string, "CORD");
00727 WRITE(fd, title_string, 4);
00728 fio_write_int32(fd, 0);
00729 fio_write_int32(fd, ISTART);
00730 fio_write_int32(fd, NSAVC);
00731 fio_write_int32(fd, 0);
00732 fio_write_int32(fd, 0);
00733 fio_write_int32(fd, 0);
00734 fio_write_int32(fd, 0);
00735 fio_write_int32(fd, 0);
00736 fio_write_int32(fd, 0);
00737 if (charmm) {
00738 out_float = DELTA;
00739 WRITE(fd, (char *) &out_float, sizeof(float));
00740 if (with_unitcell) {
00741 fio_write_int32(fd, 1);
00742 } else {
00743 fio_write_int32(fd, 0);
00744 }
00745 } else {
00746 WRITE(fd, (char *) &DELTA, sizeof(double));
00747 }
00748 fio_write_int32(fd, 0);
00749 fio_write_int32(fd, 0);
00750 fio_write_int32(fd, 0);
00751 fio_write_int32(fd, 0);
00752 fio_write_int32(fd, 0);
00753 fio_write_int32(fd, 0);
00754 fio_write_int32(fd, 0);
00755 fio_write_int32(fd, 0);
00756 if (charmm) {
00757 fio_write_int32(fd, 24);
00758 } else {
00759 fio_write_int32(fd, 0);
00760 }
00761 fio_write_int32(fd, 84);
00762 fio_write_int32(fd, 164);
00763 fio_write_int32(fd, 2);
00764
00765 strncpy(title_string, remarks, 80);
00766 title_string[79] = '\0';
00767 WRITE(fd, title_string, 80);
00768
00769 cur_time=time(NULL);
00770 tmbuf=localtime(&cur_time);
00771 strftime(time_str, 80, "REMARKS Created %d %B, %Y at %R", tmbuf);
00772 WRITE(fd, time_str, 80);
00773
00774 fio_write_int32(fd, 164);
00775 fio_write_int32(fd, 4);
00776 fio_write_int32(fd, N);
00777 fio_write_int32(fd, 4);
00778
00779 return DCD_SUCCESS;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789 static void close_dcd_read(int *indexes, float *fixedcoords) {
00790 free(indexes);
00791 free(fixedcoords);
00792 }
00793
00794
00795
00796
00797
00798 static void *open_dcd_read(const char *path, const char *filetype,
00799 int *natoms) {
00800 dcdhandle *dcd;
00801 fio_fd fd;
00802 int rc;
00803 struct stat stbuf;
00804
00805 if (!path) return NULL;
00806
00807
00808 memset(&stbuf, 0, sizeof(struct stat));
00809 if (stat(path, &stbuf)) {
00810 printf("dcdplugin) Could not access file '%s'.\n", path);
00811 return NULL;
00812 }
00813
00814 if (fio_open(path, FIO_READ, &fd) < 0) {
00815 printf("dcdplugin) Could not open file '%s' for reading.\n", path);
00816 return NULL;
00817 }
00818
00819 dcd = (dcdhandle *)malloc(sizeof(dcdhandle));
00820 memset(dcd, 0, sizeof(dcdhandle));
00821 dcd->fd = fd;
00822
00823 if ((rc = read_dcdheader(dcd->fd, &dcd->natoms, &dcd->nsets, &dcd->istart,
00824 &dcd->nsavc, &dcd->delta, &dcd->nfixed, &dcd->freeind,
00825 &dcd->fixedcoords, &dcd->reverse, &dcd->charmm))) {
00826 print_dcderror("read_dcdheader", rc);
00827 fio_fclose(dcd->fd);
00828 free(dcd);
00829 return NULL;
00830 }
00831
00832
00833
00834
00835
00836
00837 {
00838 fio_size_t ndims, firstframesize, framesize, extrablocksize;
00839 fio_size_t trjsize, filesize, curpos;
00840 int newnsets;
00841
00842 extrablocksize = dcd->charmm & DCD_HAS_EXTRA_BLOCK ? 48 + 8 : 0;
00843 ndims = dcd->charmm & DCD_HAS_4DIMS ? 4 : 3;
00844 firstframesize = (dcd->natoms+2) * ndims * sizeof(float) + extrablocksize;
00845 framesize = (dcd->natoms-dcd->nfixed+2) * ndims * sizeof(float)
00846 + extrablocksize;
00847
00848
00849
00850
00851
00852
00853 curpos = fio_ftell(dcd->fd);
00854
00855 #if defined(_MSC_VER) && defined(FASTIO_NATIVEWIN32)
00856
00857
00858
00859 fio_fseek(dcd->fd, 0, FIO_SEEK_END);
00860 filesize = fio_ftell(dcd->fd);
00861 fio_fseek(dcd->fd, curpos, FIO_SEEK_SET);
00862 #else
00863 filesize = stbuf.st_size;
00864 #endif
00865 trjsize = filesize - curpos - firstframesize;
00866 if (trjsize < 0) {
00867 printf("dcdplugin) file '%s' appears to contain no timesteps.\n", path);
00868 fio_fclose(dcd->fd);
00869 free(dcd);
00870 return NULL;
00871 }
00872
00873 newnsets = trjsize / framesize + 1;
00874
00875 if (dcd->nsets > 0 && newnsets != dcd->nsets) {
00876 printf("dcdplugin) Warning: DCD header claims %d frames, file size indicates there are actually %d frames\n", dcd->nsets, newnsets);
00877 }
00878
00879 dcd->nsets = newnsets;
00880 dcd->setsread = 0;
00881 }
00882
00883 dcd->first = 1;
00884 dcd->x = (float *)malloc(dcd->natoms * sizeof(float));
00885 dcd->y = (float *)malloc(dcd->natoms * sizeof(float));
00886 dcd->z = (float *)malloc(dcd->natoms * sizeof(float));
00887 if (!dcd->x || !dcd->y || !dcd->z) {
00888 printf("dcdplugin) Unable to allocate space for %d atoms.\n", dcd->natoms);
00889 if (dcd->x)
00890 free(dcd->x);
00891 if (dcd->y)
00892 free(dcd->y);
00893 if (dcd->z)
00894 free(dcd->z);
00895 fio_fclose(dcd->fd);
00896 free(dcd);
00897 return NULL;
00898 }
00899 *natoms = dcd->natoms;
00900 return dcd;
00901 }
00902
00903
00904 static int read_next_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00905 dcdhandle *dcd;
00906 int i, j, rc;
00907 float unitcell[6];
00908 unitcell[0] = unitcell[2] = unitcell[5] = 1.0f;
00909 unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;
00910 dcd = (dcdhandle *)v;
00911
00912
00913 if (dcd->setsread == dcd->nsets) return MOLFILE_EOF;
00914 dcd->setsread++;
00915 if (!ts) {
00916 if (dcd->first && dcd->nfixed) {
00917
00918 rc = read_dcdstep(dcd->fd, dcd->natoms, dcd->x, dcd->y, dcd->z,
00919 unitcell, dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords,
00920 dcd->reverse, dcd->charmm);
00921 dcd->first = 0;
00922 return rc;
00923 }
00924 dcd->first = 0;
00925
00926 return skip_dcdstep(dcd->fd, dcd->natoms, dcd->nfixed, dcd->charmm);
00927 }
00928 rc = read_dcdstep(dcd->fd, dcd->natoms, dcd->x, dcd->y, dcd->z, unitcell,
00929 dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords,
00930 dcd->reverse, dcd->charmm);
00931 dcd->first = 0;
00932 if (rc < 0) {
00933 print_dcderror("read_dcdstep", rc);
00934 return MOLFILE_ERROR;
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 {
00946 int natoms = dcd->natoms;
00947 float *nts = ts->coords;
00948 const float *bufx = dcd->x;
00949 const float *bufy = dcd->y;
00950 const float *bufz = dcd->z;
00951
00952 for (i=0, j=0; i<natoms; i++, j+=3) {
00953 nts[j ] = bufx[i];
00954 nts[j + 1] = bufy[i];
00955 nts[j + 2] = bufz[i];
00956 }
00957 }
00958
00959 ts->A = unitcell[0];
00960 ts->B = unitcell[2];
00961 ts->C = unitcell[5];
00962
00963 if (unitcell[1] >= -1.0 && unitcell[1] <= 1.0 &&
00964 unitcell[3] >= -1.0 && unitcell[3] <= 1.0 &&
00965 unitcell[4] >= -1.0 && unitcell[4] <= 1.0) {
00966
00967
00968
00969
00970 ts->alpha = 90.0 - asin(unitcell[4]) * 90.0 / M_PI_2;
00971 ts->beta = 90.0 - asin(unitcell[3]) * 90.0 / M_PI_2;
00972 ts->gamma = 90.0 - asin(unitcell[1]) * 90.0 / M_PI_2;
00973 } else {
00974
00975
00976 ts->alpha = unitcell[4];
00977 ts->beta = unitcell[3];
00978 ts->gamma = unitcell[1];
00979 }
00980
00981 return MOLFILE_SUCCESS;
00982 }
00983
00984
00985 static void close_file_read(void *v) {
00986 dcdhandle *dcd = (dcdhandle *)v;
00987 close_dcd_read(dcd->freeind, dcd->fixedcoords);
00988 fio_fclose(dcd->fd);
00989 free(dcd->x);
00990 free(dcd->y);
00991 free(dcd->z);
00992 free(dcd);
00993 }
00994
00995
00996 static void *open_dcd_write(const char *path, const char *filetype,
00997 int natoms) {
00998 dcdhandle *dcd;
00999 fio_fd fd;
01000 int rc;
01001 int istart, nsavc;
01002 double delta;
01003 int with_unitcell;
01004 int charmm;
01005
01006 if (fio_open(path, FIO_WRITE, &fd) < 0) {
01007 printf("dcdplugin) Could not open file '%s' for writing\n", path);
01008 return NULL;
01009 }
01010
01011 dcd = (dcdhandle *)malloc(sizeof(dcdhandle));
01012 memset(dcd, 0, sizeof(dcdhandle));
01013 dcd->fd = fd;
01014
01015 istart = 0;
01016 nsavc = 1;
01017 delta = 1.0;
01018
01019 if (getenv("VMDDCDWRITEXPLORFORMAT") != NULL) {
01020 with_unitcell = 0;
01021 charmm = DCD_IS_XPLOR;
01022 printf("dcdplugin) WARNING: Writing DCD file in X-PLOR format, \n");
01023 printf("dcdplugin) WARNING: unit cell information will be lost!\n");
01024 } else {
01025 with_unitcell = 1;
01026 charmm = DCD_IS_CHARMM;
01027 if (with_unitcell)
01028 charmm |= DCD_HAS_EXTRA_BLOCK;
01029 }
01030
01031 rc = write_dcdheader(dcd->fd, "Created by DCD plugin", natoms,
01032 istart, nsavc, delta, with_unitcell, charmm);
01033
01034 if (rc < 0) {
01035 print_dcderror("write_dcdheader", rc);
01036 fio_fclose(dcd->fd);
01037 free(dcd);
01038 return NULL;
01039 }
01040
01041 dcd->natoms = natoms;
01042 dcd->nsets = 0;
01043 dcd->istart = istart;
01044 dcd->nsavc = nsavc;
01045 dcd->with_unitcell = with_unitcell;
01046 dcd->charmm = charmm;
01047 dcd->x = (float *)malloc(natoms * sizeof(float));
01048 dcd->y = (float *)malloc(natoms * sizeof(float));
01049 dcd->z = (float *)malloc(natoms * sizeof(float));
01050 return dcd;
01051 }
01052
01053
01054 static int write_timestep(void *v, const molfile_timestep_t *ts) {
01055 dcdhandle *dcd = (dcdhandle *)v;
01056 int i, rc, curstep;
01057 float *pos = ts->coords;
01058 double unitcell[6];
01059 unitcell[0] = unitcell[2] = unitcell[5] = 1.0f;
01060 unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;
01061
01062
01063 for (i=0; i<dcd->natoms; i++) {
01064 dcd->x[i] = *(pos++);
01065 dcd->y[i] = *(pos++);
01066 dcd->z[i] = *(pos++);
01067 }
01068 dcd->nsets++;
01069 curstep = dcd->istart + dcd->nsets * dcd->nsavc;
01070
01071 unitcell[0] = ts->A;
01072 unitcell[2] = ts->B;
01073 unitcell[5] = ts->C;
01074 unitcell[1] = sin((M_PI_2 / 90.0) * (90.0 - ts->gamma));
01075 unitcell[3] = sin((M_PI_2 / 90.0) * (90.0 - ts->beta));
01076 unitcell[4] = sin((M_PI_2 / 90.0) * (90.0 - ts->alpha));
01077
01078 rc = write_dcdstep(dcd->fd, dcd->nsets, curstep, dcd->natoms,
01079 dcd->x, dcd->y, dcd->z,
01080 dcd->with_unitcell ? unitcell : NULL,
01081 dcd->charmm);
01082 if (rc < 0) {
01083 print_dcderror("write_dcdstep", rc);
01084 return MOLFILE_ERROR;
01085 }
01086
01087 return MOLFILE_SUCCESS;
01088 }
01089
01090 static void close_file_write(void *v) {
01091 dcdhandle *dcd = (dcdhandle *)v;
01092 fio_fclose(dcd->fd);
01093 free(dcd->x);
01094 free(dcd->y);
01095 free(dcd->z);
01096 free(dcd);
01097 }
01098
01099
01100
01101
01102
01103 static molfile_plugin_t plugin;
01104
01105 VMDPLUGIN_API int VMDPLUGIN_init() {
01106 memset(&plugin, 0, sizeof(molfile_plugin_t));
01107 plugin.abiversion = vmdplugin_ABIVERSION;
01108 plugin.type = MOLFILE_PLUGIN_TYPE;
01109 plugin.name = "dcd";
01110 plugin.prettyname = "CHARMM,NAMD,XPLOR DCD Trajectory";
01111 plugin.author = "Justin Gullingsrud, John Stone";
01112 plugin.majorv = 1;
01113 plugin.minorv = 10;
01114 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
01115 plugin.filename_extension = "dcd";
01116 plugin.open_file_read = open_dcd_read;
01117 plugin.read_next_timestep = read_next_timestep;
01118 plugin.close_file_read = close_file_read;
01119 plugin.open_file_write = open_dcd_write;
01120 plugin.write_timestep = write_timestep;
01121 plugin.close_file_write = close_file_write;
01122 return VMDPLUGIN_SUCCESS;
01123 }
01124
01125 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
01126 (*cb)(v, (vmdplugin_t *)&plugin);
01127 return VMDPLUGIN_SUCCESS;
01128 }
01129
01130 VMDPLUGIN_API int VMDPLUGIN_fini() {
01131 return VMDPLUGIN_SUCCESS;
01132 }
01133
01134
01135 #ifdef TEST_DCDPLUGIN
01136
01137 #include <sys/time.h>
01138
01139
01140 double time_of_day(void) {
01141 #if defined(_MSC_VER)
01142 double t;
01143
01144 t = GetTickCount();
01145 t = t / 1000.0;
01146
01147 return t;
01148 #else
01149 struct timeval tm;
01150 struct timezone tz;
01151
01152 gettimeofday(&tm, &tz);
01153 return((double)(tm.tv_sec) + (double)(tm.tv_usec)/1000000.0);
01154 #endif
01155 }
01156
01157 int main(int argc, char *argv[]) {
01158 molfile_timestep_t timestep;
01159 void *v;
01160 dcdhandle *dcd;
01161 int i, natoms;
01162 float sizeMB =0.0, totalMB = 0.0;
01163 double starttime, endtime, totaltime = 0.0;
01164
01165 while (--argc) {
01166 ++argv;
01167 natoms = 0;
01168 v = open_dcd_read(*argv, "dcd", &natoms);
01169 if (!v) {
01170 fprintf(stderr, "main) open_dcd_read failed for file %s\n", *argv);
01171 return 1;
01172 }
01173 dcd = (dcdhandle *)v;
01174 sizeMB = ((natoms * 3.0) * dcd->nsets * 4.0) / (1024.0 * 1024.0);
01175 totalMB += sizeMB;
01176 printf("main) file: %s\n", *argv);
01177 printf(" %d atoms, %d frames, size: %6.1fMB\n", natoms, dcd->nsets, sizeMB);
01178
01179 starttime = time_of_day();
01180 timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
01181 for (i=0; i<dcd->nsets; i++) {
01182 int rc = read_next_timestep(v, natoms, ×tep);
01183 if (rc) {
01184 fprintf(stderr, "error in read_next_timestep on frame %d\n", i);
01185 return 1;
01186 }
01187 }
01188 endtime = time_of_day();
01189 close_file_read(v);
01190 totaltime += endtime - starttime;
01191 printf(" Time: %5.1f seconds\n", endtime - starttime);
01192 printf(" Speed: %5.1f MB/sec, %5.1f timesteps/sec\n", sizeMB / (endtime - starttime), (dcd->nsets / (endtime - starttime)));
01193 }
01194 printf("Overall Size: %6.1f MB\n", totalMB);
01195 printf("Overall Time: %6.1f seconds\n", totaltime);
01196 printf("Overall Speed: %5.1f MB/sec\n", totalMB / totaltime);
01197 return 0;
01198 }
01199
01200 #endif
01201