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

vaspoutcarplugin.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  * RCS INFORMATION:
00003  *
00004  *      $RCSfile: vaspoutcarplugin.c,v $
00005  *      $Author: johns $       $Locker:  $             $State: Exp $
00006  *      $Revision: 1.10 $       $Date: 2017/10/27 18:03:58 $
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  *  g++ -O2 -Wall -I. -I$VMDBASEDIR/plugins/include -c vaspoutcarplugin.c
00019  *  ld -shared -o vaspoutcarplugin.so vaspoutcarplugin.o
00020  *
00021  *  MACOSX
00022  *  c++ -O2 -Wall -I. -I$VMDBASEDIR/plugins/include -c vaspoutcarplugin.c
00023  *  c++ -bundle -o vaspoutcarplugin.so vaspoutcarplugin.o
00024  *
00025  *  Install
00026  *  copy vaspoutcarplugin.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_vaspoutcar_read(const char *filename, const char *filetype, int *natoms)
00039 {
00040   vasp_plugindata_t *data;
00041   char lineptr[LINESIZE];
00042 
00043   /* Verify that input is OK */
00044   if (!filename || !natoms) return NULL;
00045 
00046   /* Start with undefined value; set it after successful read */
00047   *natoms = MOLFILE_NUMATOMS_UNKNOWN;
00048 
00049   data = vasp_plugindata_malloc();
00050   if (!data) return NULL;
00051 
00052   data->file = fopen(filename, "rb");
00053   if (!data->file) {
00054     vasp_plugindata_free(data);
00055     return NULL;
00056   }
00057   
00058   data->filename = strdup(filename);
00059 
00060   /* Catch total number of atoms */
00061   data->numatoms = 0;
00062   while (fgets(lineptr, LINESIZE, data->file) && data->numatoms == 0) {
00063    if (strstr(lineptr, "NIONS =") != NULL) {
00064       sscanf(lineptr, " %*[ a-zA-Z] = %*d %*[ a-zA-Z] = %d", &data->numatoms);
00065       break;
00066     }
00067   }
00068 
00069   if (data->numatoms <= 0) {
00070     vasp_plugindata_free(data);
00071     fprintf(stderr, "\n\nVASP OUTCAR read) ERROR: file '%s' does not contain the number of atoms.\n", filename);
00072     return NULL;
00073   }
00074 
00075   *natoms = data->numatoms;
00076 
00077   /* Catch the lattice vectors */
00078   while (fgets(lineptr, LINESIZE, data->file)) {
00079      if (strstr(lineptr, "direct lattice vectors") != NULL) {
00080        int i;
00081        for (i = 0; i < 3; ++i) {
00082          fgets(lineptr, LINESIZE, data->file);
00083          if (3 != sscanf(lineptr, "%f %f %f", &data->cell[i][0], &data->cell[i][1], &data->cell[i][2])) {
00084            vasp_plugindata_free(data);
00085            fprintf(stderr, "\n\nVASP OUTCAR read) ERROR: file '%s' does not contain lattice vectors.\n", filename);
00086            return NULL;
00087          }
00088        }
00089        break;
00090      }
00091   }
00092   vasp_buildrotmat(data);
00093 
00094   rewind(data->file);
00095 
00096   return data;
00097 }
00098 
00099 
00100 static int read_vaspoutcar_structure(void *mydata, int *optflags, molfile_atom_t *atoms)
00101 {
00102   vasp_plugindata_t *data = (vasp_plugindata_t *)mydata;
00103   FILE *potcar;
00104   char lineptr[LINESIZE], potcarfile[1000];
00105   float atommass[MAXATOMTYPES];
00106   int atomcount, typecount, i;
00107 
00108   if (!data || !optflags || !atoms) return MOLFILE_ERROR;
00109 
00110   *optflags = MOLFILE_MASS; /* we set atom mass from the PTE. */
00111   *optflags |= MOLFILE_ATOMICNUMBER | MOLFILE_RADIUS;
00112 
00113   typecount = 0;
00114   atomcount = 0;
00115   while (fgets(lineptr, LINESIZE, data->file) && atomcount < data->numatoms) {
00116     if (strstr(lineptr, "POMASS") != NULL) sscanf(lineptr, " POMASS = %f;", &atommass[typecount++]);
00117 
00118     if (strstr(lineptr, "ions per type =") != NULL) {
00119       char const *token = strtok(lineptr, "=");
00120       for (i = 0; i < typecount; ++i) {
00121         token = strtok(NULL, " ");
00122         atomcount += data->eachatom[i] = atoi(token);
00123       }
00124     }
00125   }
00126 
00127   if (atomcount != data->numatoms) {
00128     fprintf(stderr, "\n\nVASP OUTCAR read) ERROR: file '%s' does not have number of each atom.\n", data->filename);
00129     return MOLFILE_ERROR;
00130   }
00131 
00132   /* Read POTCAR file to determine atom types.
00133    * Each atom type section in POTCAR starts with a line
00134    * that contains the name of the element (H, He, C etc.).
00135    * Otherwise try to find similar mass in periodic table.
00136    */
00137   if (strstr(data->filename, "OUTCAR")) {
00138     strcpy(potcarfile, data->filename);
00139     strcpy(strstr(potcarfile, "OUTCAR"), "POTCAR");
00140     potcar = fopen(potcarfile, "r");
00141   } else {
00142     potcar = NULL;
00143   }
00144 
00145   for (atomcount = i = 0; atomcount < data->numatoms; ++i) {
00146     char const *label;
00147     float mass, radius;
00148     int k, idx = 0;
00149 
00150     if (potcar) {
00151       /* Obtain atom types from POTCAR file */
00152       char atomtype[5] = "X";
00153       if (fgets(lineptr, LINESIZE, potcar)) sscanf(lineptr, "%*s %4[^_. 0-9]", atomtype);
00154       idx = get_pte_idx(atomtype);
00155 
00156       /* Skip lines in potcar file until next element */
00157       while (fgets(lineptr, LINESIZE, potcar)) if (strstr(lineptr, "End of Dataset")) break;
00158     }
00159     
00160     if (idx == 0) {
00161         /* Try to find atom type by browsing through periodic table */
00162         idx = sizeof(pte_mass)/sizeof(pte_mass[0]);
00163         do idx--;
00164         while (idx > 0 && fabs(get_pte_mass(idx) - atommass[i]) > 0.01);
00165     }
00166 
00167     label = get_pte_label(idx);
00168     mass = (idx ? get_pte_mass(idx) : atommass[i]);
00169     radius = get_pte_vdw_radius(idx);
00170     for (k = 0; k < data->eachatom[i]; ++k, ++atomcount) {
00171       molfile_atom_t *atom = &(atoms[atomcount]);
00172 
00173       /* Required settings */
00174       strncpy(atom->name, label, sizeof(atom->name));
00175       strncpy(atom->type, atom->name, sizeof(atom->type));
00176       atom->resname[0] = '\0';
00177       atom->resid = 1;
00178       atom->segid[0]='\0';
00179       atom->chain[0]='\0';
00180 
00181       /* Optional flags (as defined in *optflags) */
00182       atom->mass = mass;
00183       atom->radius = radius;
00184       atom->atomicnumber = idx;
00185     }
00186   }
00187   if (potcar) fclose(potcar);
00188 
00189   if (atomcount != data->numatoms) {
00190     fprintf(stderr, "\n\nVASP OUTCAR read) ERROR: file '%s' does contain list of atom names.\n", data->filename);
00191     return MOLFILE_ERROR;
00192   }
00193 
00194   atomcount = 0;
00195   while (fgets(lineptr, LINESIZE, data->file) && atomcount == 0) {
00196     if (strstr(lineptr, "position of ions in cartesian coordinates") != NULL) {
00197       for (i = 0; i < data->numatoms; ++i, ++atomcount) {
00198         float coord;
00199         fgets(lineptr, LINESIZE, data->file);
00200         if (3 != sscanf(lineptr, "%f %f %f", &coord, &coord, &coord)) {
00201           fprintf(stderr, "\n\nVASP OUTCAR read) missing type or coordinate(s) in file '%s' for atom '%d'\n", data->filename, i+1);
00202           return MOLFILE_ERROR;
00203         }
00204       }
00205     }
00206   }
00207 
00208   if (atomcount != data->numatoms) {
00209     fprintf(stderr, "\n\nVASP OUTCAR read) ERROR: file '%s' does contain list of atom names.\n", data->filename);
00210     return MOLFILE_ERROR;
00211   }
00212  
00213   rewind(data->file);
00214 
00215   return MOLFILE_SUCCESS;
00216 }
00217 
00218 
00219 static int read_vaspoutcar_timestep(void *mydata, int natoms, molfile_timestep_t *ts)
00220 {
00221   vasp_plugindata_t *data = (vasp_plugindata_t *)mydata;
00222   char lineptr[LINESIZE];
00223   int atomcount;
00224 
00225   /* Save coords only if we're given a timestep pointer,
00226    * otherwise assume that VMD wants us to skip past it.
00227    */
00228   if (!data || !ts) return MOLFILE_EOF;
00229 
00230   atomcount = 0;
00231   while (fgets(lineptr, LINESIZE, data->file) && atomcount == 0) {
00232     if (strstr(lineptr, "TOTAL-FORCE") != NULL) {
00233       int i;
00234       fgets(lineptr, LINESIZE, data->file);
00235       for (i = 0; i < data->numatoms; ++i, ++atomcount) {
00236         float x, y, z;
00237         fgets(lineptr, LINESIZE, data->file);
00238         if (3 != sscanf(lineptr, "%f %f %f", &x, &y, &z)) return MOLFILE_EOF;
00239       
00240         ts->coords[3*i  ] = data->rotmat[0][0]*x+data->rotmat[0][1]*y+data->rotmat[0][2]*z;
00241         ts->coords[3*i+1] = data->rotmat[1][0]*x+data->rotmat[1][1]*y+data->rotmat[1][2]*z;
00242         ts->coords[3*i+2] = data->rotmat[2][0]*x+data->rotmat[2][1]*y+data->rotmat[2][2]*z;
00243       }
00244     }
00245   }
00246   if (atomcount != data->numatoms) return MOLFILE_EOF;
00247 
00248   vasp_timestep_unitcell(ts, data);
00249 
00250   return MOLFILE_SUCCESS;
00251 }
00252 
00253 
00254 static void close_vaspoutcar_read(void *mydata)
00255 {
00256   vasp_plugindata_t *data = (vasp_plugindata_t *)mydata;
00257   vasp_plugindata_free(data);
00258 }
00259 
00260 
00261 /* registration stuff */
00262 static molfile_plugin_t plugin;
00263 
00264 int VMDPLUGIN_init() {
00265   memset(&plugin, 0, sizeof(molfile_plugin_t));
00266   plugin.abiversion = vmdplugin_ABIVERSION;
00267   plugin.type = MOLFILE_PLUGIN_TYPE;
00268   plugin.name = "OUTCAR";
00269   plugin.prettyname = "VASP_OUTCAR";
00270   plugin.author = "Sung Sakong";
00271   plugin.majorv = 0;
00272   plugin.minorv = 8;
00273   plugin.is_reentrant = VMDPLUGIN_THREADUNSAFE;
00274   plugin.filename_extension = "OUTCAR";
00275   plugin.open_file_read = open_vaspoutcar_read;
00276   plugin.read_structure = read_vaspoutcar_structure;
00277   plugin.read_next_timestep = read_vaspoutcar_timestep;
00278   plugin.close_file_read = close_vaspoutcar_read;
00279   return VMDPLUGIN_SUCCESS;
00280 }
00281 
00282 int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00283   (*cb)(v, (vmdplugin_t *)&plugin);
00284   return VMDPLUGIN_SUCCESS;
00285 }
00286 
00287 int VMDPLUGIN_fini() {
00288   return VMDPLUGIN_SUCCESS;
00289 }

Generated on Thu Nov 14 02:15:37 2024 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002