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_vaspoutcar_read(const char *filename, const char *filetype, int *natoms)
00039 {
00040 vasp_plugindata_t *data;
00041 char lineptr[LINESIZE];
00042
00043
00044 if (!filename || !natoms) return NULL;
00045
00046
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
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
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;
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
00133
00134
00135
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
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
00157 while (fgets(lineptr, LINESIZE, potcar)) if (strstr(lineptr, "End of Dataset")) break;
00158 }
00159
00160 if (idx == 0) {
00161
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
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
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
00226
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
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 }