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 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include "molfile_plugin.h"
00034 #include "vaspplugin.h"
00035 #include "periodic_table.h"
00036
00037
00038 static void *open_vaspxdatcar_read(const char *filename, const char *filetype, int *natoms)
00039 {
00040 FILE *poscar;
00041 vasp_plugindata_t *data;
00042 char lineptr[LINESIZE], poscarfile[1000];
00043 float lc;
00044 int i;
00045
00046
00047 if (!filename || !natoms) return NULL;
00048
00049
00050 *natoms = MOLFILE_NUMATOMS_UNKNOWN;
00051
00052
00053 if (strstr(filename, "XDATCAR") == NULL) {
00054 fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: file name '%s' does not contain 'XDATCAR'.\n", filename);
00055 return NULL;
00056 }
00057 strcpy(poscarfile, filename);
00058 strcpy(strstr(poscarfile, "XDATCAR"), "POSCAR");
00059 poscar = fopen(poscarfile, "r");
00060 if (!poscar) {
00061 strcpy(poscarfile, filename);
00062 strcpy(strstr(poscarfile, "XDATCAR"), "CONTCAR");
00063 poscar = fopen(poscarfile, "r");
00064 if (!poscar) {
00065 fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: corresponding POSCAR or CONTCAR file not found.\n");
00066 return NULL;
00067 }
00068 }
00069 fprintf(stderr, "\n\nVASP XDATCAR read) determining lattice vectors and number of atoms from file '%s'.\n", poscarfile);
00070
00071 data = vasp_plugindata_malloc();
00072 if (!data) return NULL;
00073
00074
00075 data->version = 4;
00076 data->file = fopen(filename, "rb");
00077 if (!data->file) {
00078 vasp_plugindata_free(data);
00079 return NULL;
00080 }
00081
00082 data->filename = strdup(filename);
00083
00084 fgets(lineptr, LINESIZE, poscar);
00085 data->titleline = strdup(lineptr);
00086
00087 fgets(lineptr, LINESIZE, poscar);
00088 lc = atof(strtok(lineptr, " "));
00089
00090 for (i = 0; i < 3; ++i) {
00091 float x, y, z;
00092 fgets(lineptr, LINESIZE, poscar);
00093 if (3 != sscanf(lineptr, "%f %f %f", &x, &y, &z)) {
00094 vasp_plugindata_free(data);
00095 fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: POSCAR file '%s' does not have lattice vectors.\n", poscarfile);
00096 return NULL;
00097 }
00098 data->cell[i][0] = x*lc;
00099 data->cell[i][1] = y*lc;
00100 data->cell[i][2] = z*lc;
00101 }
00102 vasp_buildrotmat(data);
00103
00104
00105 data->numatoms = 0;
00106 fgets(lineptr, LINESIZE, poscar);
00107 for (i = 0; i < MAXATOMTYPES; ++i) {
00108 char const *tmplineptr = strdup(lineptr);
00109 char const *token = (i == 0 ? strtok(lineptr, " ") : strtok(NULL, " "));
00110 int const n = (token ? atoi(token) : -1);
00111
00112
00113 if (i == 0 && n <= 0) {
00114 data->version = 5;
00115 data->titleline = strdup(tmplineptr);
00116 fgets(lineptr, LINESIZE, poscar);
00117 break;
00118 }else if (n <= 0) break;
00119
00120 data->eachatom[i] = n;
00121 data->numatoms += n;
00122 }
00123
00124 if (data->version == 5) {
00125 data->numatoms = 0;
00126 for (i = 0; i < MAXATOMTYPES; ++i) {
00127 char const *token = (i == 0 ? strtok(lineptr, " ") : strtok(NULL, " "));
00128 int const n = (token ? atoi(token) : -1);
00129
00130 if (n <= 0) break;
00131
00132 data->eachatom[i] = n;
00133 data->numatoms += n;
00134 }
00135 }
00136
00137 fclose(poscar);
00138
00139 if (data->numatoms == 0) {
00140 vasp_plugindata_free(data);
00141 fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: POSCAR file '%s' does not have the list of atom numbers.\n", poscarfile);
00142 return NULL;
00143 }
00144
00145 *natoms = data->numatoms;
00146
00147 return data;
00148 }
00149
00150
00151 static int read_vaspxdatcar_structure(void *mydata, int *optflags, molfile_atom_t *atoms)
00152 {
00153 vasp_plugindata_t *data = (vasp_plugindata_t *)mydata;
00154 FILE *potcar;
00155 char lineptr[LINESIZE], potcarfile[1000];
00156 int atomcount, i;
00157
00158
00159 if (!data || !optflags || !atoms) return MOLFILE_ERROR;
00160
00161 *optflags = MOLFILE_MASS;
00162 *optflags |= MOLFILE_ATOMICNUMBER | MOLFILE_RADIUS;
00163
00164
00165
00166
00167
00168
00169 strcpy(potcarfile, data->filename);
00170 strcpy(strstr(potcarfile, "XDATCAR"), "POTCAR");
00171 potcar = fopen(potcarfile, "r");
00172 if (potcar) fprintf(stderr, "\n\nVASP XDATCAR read) using file '%s' for determining atom types.\n", potcarfile);
00173
00174 for (atomcount = i = 0; atomcount < data->numatoms; ++i) {
00175 int j;
00176 int idx;
00177 char const *label;
00178 float mass, radius;
00179
00180 if (potcar) {
00181
00182 char atomtype[5] = "X";
00183 if (fgets(lineptr, LINESIZE, potcar)) sscanf(lineptr, "%*s %4s", atomtype);
00184 idx = get_pte_idx(atomtype);
00185
00186
00187 while (fgets(lineptr, LINESIZE, potcar)) if (strstr(lineptr, "End of Dataset")) break;
00188 } else {
00189
00190 char const *token = (i == 0 ? strtok(data->titleline, " ") : strtok(NULL, " "));
00191 idx = get_pte_idx(token);
00192 }
00193
00194 label = get_pte_label(idx);
00195 mass = get_pte_mass(idx);
00196 radius = get_pte_vdw_radius(idx);
00197 for (j = 0; j < data->eachatom[i]; ++j, ++atomcount) {
00198 molfile_atom_t *const atom = &(atoms[atomcount]);
00199
00200
00201 strncpy(atom->name, label, sizeof(atom->name));
00202 strncpy(atom->type, atom->name, sizeof(atom->type));
00203 atom->resname[0] = '\0';
00204 atom->resid = 1;
00205 atom->segid[0]='\0';
00206 atom->chain[0]='\0';
00207
00208
00209 atom->mass = mass;
00210 atom->radius = radius;
00211 atom->atomicnumber = idx;
00212 }
00213 }
00214 if (potcar) fclose(potcar);
00215
00216 if (atomcount != data->numatoms) {
00217
00218 fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: problem occurred when setting the atom types.\n");
00219 return MOLFILE_ERROR;
00220 }
00221
00222
00223 for (i = 0; i < 4; ++i) fgets(lineptr, LINESIZE, data->file);
00224
00225
00226 if (tolower(lineptr[0]) == 'd'){
00227 data->version = 5;
00228 fgets(lineptr, LINESIZE, data->file);
00229 }
00230 else {
00231 data->version = 4;
00232 for (i = 0; i < 2; ++i) fgets(lineptr, LINESIZE, data->file);
00233 }
00234
00235
00236 for (i = 0; i < data->numatoms && fgets(lineptr, LINESIZE, data->file); ++i) {
00237 float coord;
00238 if (3 != sscanf(lineptr, "%f %f %f", &coord, &coord, &coord)) break;
00239 }
00240 if (i != data->numatoms) {
00241 fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: file '%s' does not contain all coordinates of the atoms.\n", data->filename);
00242 return MOLFILE_ERROR;
00243 }
00244
00245
00246 rewind(data->file);
00247 for (i = 0; i < 10 - data->version; ++i) fgets(lineptr, LINESIZE, data->file);
00248
00249 return MOLFILE_SUCCESS;
00250 }
00251
00252
00253 static int read_vaspxdatcar_timestep(void *mydata, int natoms, molfile_timestep_t *ts)
00254 {
00255 vasp_plugindata_t *data = (vasp_plugindata_t *)mydata;
00256 char lineptr[LINESIZE];
00257 int i;
00258
00259
00260
00261 if (!data || !ts) return MOLFILE_EOF;
00262
00263 for (i = 0; i < data->numatoms && fgets(lineptr, LINESIZE, data->file); ++i) {
00264 float x, y, z, rotx, roty, rotz;
00265 if (3 != sscanf(lineptr, "%f %f %f", &x, &y, &z)) break;
00266
00267 rotx = x*data->cell[0][0] + y*data->cell[1][0] + z*data->cell[2][0];
00268 roty = x*data->cell[0][1] + y*data->cell[1][1] + z*data->cell[2][1];
00269 rotz = x*data->cell[0][2] + y*data->cell[1][2] + z*data->cell[2][2];
00270
00271 ts->coords[3*i ] = data->rotmat[0][0]*rotx + data->rotmat[0][1]*roty + data->rotmat[0][2]*rotz;
00272 ts->coords[3*i+1] = data->rotmat[1][0]*rotx + data->rotmat[1][1]*roty + data->rotmat[1][2]*rotz;
00273 ts->coords[3*i+2] = data->rotmat[2][0]*rotx + data->rotmat[2][1]*roty + data->rotmat[2][2]*rotz;
00274 }
00275 if (i != data->numatoms) return MOLFILE_EOF;
00276
00277
00278 fgets(lineptr, LINESIZE, data->file);
00279
00280 vasp_timestep_unitcell(ts, data);
00281
00282 return MOLFILE_SUCCESS;
00283 }
00284
00285
00286 static void close_vaspxdatcar_read(void *mydata)
00287 {
00288 vasp_plugindata_t *data = (vasp_plugindata_t *)mydata;
00289 vasp_plugindata_free(data);
00290 }
00291
00292
00293
00294 static molfile_plugin_t plugin;
00295
00296 int VMDPLUGIN_init() {
00297 memset(&plugin, 0, sizeof(molfile_plugin_t));
00298 plugin.abiversion = vmdplugin_ABIVERSION;
00299 plugin.type = MOLFILE_PLUGIN_TYPE;
00300 plugin.name = "XDATCAR";
00301 plugin.prettyname = "VASP_XDATCAR";
00302 plugin.author = "Sung Sakong";
00303 plugin.majorv = 0;
00304 plugin.minorv = 7;
00305 plugin.is_reentrant = VMDPLUGIN_THREADUNSAFE;
00306 plugin.filename_extension = "XDATCAR";
00307 plugin.open_file_read = open_vaspxdatcar_read;
00308 plugin.read_structure = read_vaspxdatcar_structure;
00309 plugin.read_next_timestep = read_vaspxdatcar_timestep;
00310 plugin.close_file_read = close_vaspxdatcar_read;
00311 return VMDPLUGIN_SUCCESS;
00312 }
00313
00314 int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00315 (*cb)(v, (vmdplugin_t *)&plugin);
00316 return VMDPLUGIN_SUCCESS;
00317 }
00318
00319 int VMDPLUGIN_fini() {
00320 return VMDPLUGIN_SUCCESS;
00321 }
00322
00323