Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

vaspxdatcarplugin.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  * RCS INFORMATION:
00003  *
00004  *      $RCSfile: vaspxdatcarplugin.c,v $
00005  *      $Author: johns $       $Locker:  $             $State: Exp $
00006  *      $Revision: 1.10 $       $Date: 2014/10/10 14:41:02 $
00007  *
00008  ***************************************************************************/
00009 
00010 /*
00011  *  VASP plugins for VMD
00012  *  Sung Sakong, Dept. of Phys., Univsity Duisburg-Essen
00013  *  
00014  *  VASP manual   
00015  *  http://cms.mpi.univie.ac.at/vasp/
00016  * 
00017  *  LINUX
00018  *  gcc -O2 -Wall -I. -I$VMDBASEDIR/plugins/include -c vaspxdatcarplugin.c
00019  *  ld -shared -o vaspxdatcarplugin.so vaspxdatcarplugin.o
00020  *
00021  *  MACOSX
00022  *  c++ -O2 -Wall -I. -I$VMDBASEDIR/plugins/include -c vaspxdatcarplugin.c
00023  *  c++ -bundle -o vaspxdatcarplugin.so vaspxdatcarplugin.o
00024  *
00025  *  Install
00026  *  copy vaspxdatcarplugin.so $VMDBASEDIR/plugins/$ARCH/molfile
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   /* Verify that input is OK */
00047   if (!filename || !natoms) return NULL;
00048 
00049   /* Start with undefined value; set it after successful read */
00050   *natoms = MOLFILE_NUMATOMS_UNKNOWN;
00051 
00052   /* Use POSCAR or CONTCAR file for cell data and number of atoms */
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   /* VASP4 is assumed in default */
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   /* Read the number of atoms per atom type */
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     /* if fails to read number of atoms, then assume VASP5 */
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   /* Verify that input is OK */
00159   if (!data || !optflags || !atoms) return MOLFILE_ERROR;
00160 
00161   *optflags = MOLFILE_MASS; /* we set atom mass from the PTE. */
00162   *optflags |= MOLFILE_ATOMICNUMBER | MOLFILE_RADIUS; 
00163 
00164   /* Read POTCAR file to determine atom types.
00165    * Each atom type section in POTCAR starts with a line
00166    * that contains the name of the element (H, He, C etc.).
00167    * Otherwise, try the title line instead.
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        /* Obtain atom types from POTCAR file */
00182        char atomtype[5] = "X";
00183        if (fgets(lineptr, LINESIZE, potcar)) sscanf(lineptr, "%*s %4s", atomtype);
00184        idx = get_pte_idx(atomtype);
00185 
00186        /* Skip lines in potcar file until next element */
00187        while (fgets(lineptr, LINESIZE, potcar)) if (strstr(lineptr, "End of Dataset")) break;
00188     } else {
00189        /* Try to obtain atom types from title line */
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       /* Required settings */
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       /* Optional flags (as defined in *optflags) */
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     /* This can generally not happen; if it happens, there's a bug in the for-loop(i) above */
00218     fprintf(stderr, "\n\nVASP XDATCAR read) ERROR: problem occurred when setting the atom types.\n");
00219     return MOLFILE_ERROR;
00220   }
00221 
00222   /* Ignore header until X,Y,Z-coordinates */
00223   for (i = 0; i < 4; ++i) fgets(lineptr, LINESIZE, data->file);
00224 
00225  /* Determine VASP4 and VASP5 */
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   /* Check whether all coordinates are present in the file */
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   /* Set file pointer to the line of the atoms' coordinates */
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   /* only save coords if we're given a timestep pointer, */
00260   /* otherwise assume that VMD wants us to skip past it. */
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   /* Skip the empty line after coordinates */
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 /* registration stuff */
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 

Generated on Tue Apr 23 04:48:47 2024 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002