Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

lammpspluginA.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2005 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: lammpsplugin.c,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.7 $       $Date: 2005/02/16 03:21:16 $
00015  *      $Rewritten by Marco Kalweit on 2005/11/11$
00016  *
00017  ***************************************************************************/
00018 
00019 /*
00020  *  LAMMPS dump file format:
00021  *    ITEM: TIMESTEP
00022  *      %d (timestep number)
00023  *    ITEM: NUMBER OF ATOMS
00024  *      %d (number of atoms)
00025  *    ITEM: BOX BOUNDS
00026  *      %f %f (alpha, a)
00027  *      %f %f (beta,  b)
00028  *      %f %f (gamma, c)
00029  *    ITEM: ATOMS
00030  *      %d %d %f %f %f  (atomid, ?, x, y, z)
00031  *      ...
00032  *
00033  *   This file assumes that the number of atoms keeps constant during 
00034  *   the entire simulation
00035  *   The standard file extension is .lammpstrj
00036  */
00037 
00038 #include "largefiles.h"   /* platform dependent 64-bit file I/O defines */
00039 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <ctype.h>
00044 #include <math.h>
00045 #include <float.h>
00046 #include "molfile_plugin.h"
00047 
00048 #ifndef M_PI_2
00049 #define M_PI_2 1.57079632679489661922
00050 #endif
00051 
00052 typedef struct {
00053   FILE *file;
00054   int numatoms;
00055   char *file_name;
00056   molfile_graphics_t *graphlist;
00057 } lammpsdata;
00058  
00059 static char* find_next_item(FILE* fd, char* szItem) {
00060   char szLine[1024];
00061   char* pcolon;
00062   int nReturn;
00063     
00064   while(fgets(szLine, 1024, fd)) {
00065     pcolon = strrchr(szLine, ':');
00066     if(pcolon) {
00067       *pcolon = 0;
00068       if(0 == strcmp(szLine, "ITEM")) {
00069         *pcolon = ':';
00070         pcolon+=2;
00071         strcpy(szItem, pcolon);
00072         nReturn = (int)strcspn(szItem, "\n\r"); // remove the carriage return
00073         if(nReturn) 
00074           szItem[nReturn] = 0;
00075         return szItem;
00076       }
00077     }
00078   }
00079 
00080   return NULL;
00081 }
00082 
00083 
00084 static int find_item(FILE* fd, char* szItem) {
00085   char szBuffer[1024];
00086   while(find_next_item(fd, szBuffer)) {
00087     if(0 == strcmp(szBuffer, szItem)) 
00088       return 1;
00089   }
00090   return 0;
00091 }
00092 
00093 
00094 static void *open_lammps_read(const char *filename, const char *filetype, int *natoms) {
00095   FILE *fd;
00096   lammpsdata *data;
00097   char szBuffer[1024];
00098 
00099   fd = fopen(filename, "rb");
00100   if (!fd) return NULL;
00101   
00102   data = (lammpsdata *)malloc(sizeof(lammpsdata));
00103   data->file = fd;
00104   data->file_name = strdup(filename);
00105   data->graphlist = NULL;
00106   *natoms = 0; 
00107 
00108   if(!find_item(data->file, "NUMBER OF ATOMS")) {
00109     fprintf(stderr, "lammpsplugin) Unable to fine 'NUMBER OF ATOMS' item\n");   
00110     return NULL;
00111   }
00112   
00113   if(!fgets(szBuffer, 1024, data->file)) {
00114     fprintf(stderr, "lammpsplugin) dump file '%s' should have the number of atoms after line ITEM: NUMBER OF ATOMS.\n", filename);
00115     return NULL;
00116   }
00117   *natoms = atoi(szBuffer);
00118   
00119   data->numatoms=*natoms;
00120   rewind(data->file); /* prepare for first read_timestep call */
00121   
00122   return data;
00123 }
00124 
00125 
00126 static int read_lammps_structure(void *mydata, int *optflags, molfile_atom_t *atoms) {
00127   int i, j;
00128   char szBuffer[1024];
00129   molfile_atom_t *atom;
00130   lammpsdata *data = (lammpsdata *)mydata;
00131   int atomid;
00132   char atom_type[1025];
00133   float x, y, z;
00134   char *k;
00135 
00136   *optflags = MOLFILE_NOOPTIONS; // no optional data
00137   
00138   // go to the beginning of the file
00139   rewind(data->file); /* prepare for first read_timestep call */
00140   
00141   // find the sections with atoms
00142   if(!find_item(data->file, "ATOMS")) {
00143     fprintf(stderr, "lammpsplugin) couldn't find atoms to read structure from file '%s'.\n", data->file_name);
00144     return MOLFILE_ERROR;
00145   }
00146 
00147   // now read the atoms
00149   for(i=0;i<data->numatoms;i++) {
00150     k = fgets(szBuffer, 1024, data->file);
00151     
00152     /* Read in atom type, X, Y, Z, skipping any remaining data fields */
00153     j = sscanf(szBuffer, "%d %s %f %f %f", &atomid, atom_type, &x, &y, &z);
00154    
00155     if (k == NULL) {
00156       fprintf(stderr, "lammpsplugin) Error while reading structure from lammps dump file '%s': atom missing in the first timestep\n",data->file_name);
00157       fprintf(stderr, "lammpsplugin) expecting '%d' atoms, found only '%d'\n",data->numatoms,i+1);
00158       return MOLFILE_ERROR;
00159     } else if (j < 5) {
00160       fprintf(stderr, "lammpsplugin) Error while reading structure from lammps dump file '%s': missing type or coordinate(s) for atom '%d'\n", data->file_name, i+1);
00161       return MOLFILE_ERROR;
00162     }
00163 
00164     atom = atoms + i;
00165     sprintf(atom->name, "%02d", atomid);
00166     strncpy(atom->type, atom_type, sizeof(atom->type));
00167     strcpy(atom->resname, "");
00168     atom->resid = 1;
00169     strcpy(atom->chain, "");
00170     strcpy(atom->segid, "");
00171     // skip to the end of line
00172   }
00173 
00174   rewind(data->file);
00175   return MOLFILE_SUCCESS;
00176 }
00177 
00178 
00179 static int read_lammps_timestep(void *mydata, int natoms, molfile_timestep_t *ts) {
00180   int i, j;
00181   char atom_name[1025], szBuffer[1025];
00182   float x, y, z;
00183   int atomid;
00184   float lo[3],hi[3], l[3];
00185 
00186   lammpsdata *data = (lammpsdata *)mydata;
00187 
00188   // check if there is antother time steps
00189   if(!find_item(data->file, "TIMESTEP")) return MOLFILE_ERROR; 
00190   
00191   // check if we actually have to read something
00192   if(!ts) return MOLFILE_SUCCESS;
00193 
00194   // check the number of atoms in the timestep
00195   if(!find_item(data->file, "NUMBER OF ATOMS")) {
00196     fprintf(stderr, "lammpsplugin) lammps dump file '%s', unable to find item: NUMBER OF ATOMS for current timestep.\n", data->file_name);
00197     return MOLFILE_ERROR;
00198   }
00199 
00200   if(!fgets(szBuffer, 1024, data->file)) {
00201     fprintf(stderr, "lammpsplugin) lammps dump file '%s', should have the number of atoms after line ITEM: NUMBER OF ATOMS.\n", data->file_name);
00202     return MOLFILE_ERROR;
00203   }
00204 
00205   if(natoms != atoi(szBuffer)) {
00206     fprintf(stderr, "lammpsplugin) lammps dump file '%s', wrong number of atoms in timestep.\n", data->file_name);
00207     return MOLFILE_ERROR;
00208   }
00209 
00210   // read the boundary box of the timestep
00211   if(!find_item(data->file, "BOX BOUNDS")) {
00212     fprintf(stderr, "lammpsplugin) lammps dump file '%s', could not find ITEM: BOX BOUNDS.\n", data->file_name);
00213     return MOLFILE_ERROR;
00214   }
00215 
00216   if (NULL == fgets(szBuffer, 1024, data->file))  return MOLFILE_ERROR;
00217   sscanf(szBuffer,"%f %f", lo, hi);
00218   l[0] = hi[0] - lo[0];
00219 
00220   if (NULL == fgets(szBuffer, 1024, data->file))  return MOLFILE_ERROR;
00221   sscanf(szBuffer,"%f %f", lo+1, hi+1);
00222   l[1] = hi[1] - lo[1];
00223 
00224   if (NULL == fgets(szBuffer, 1024, data->file))  return MOLFILE_ERROR;
00225   sscanf(szBuffer,"%f %f", lo+2, hi+2);
00226   l[2] = hi[2] - lo[2];
00227   
00228   ts->A = l[0];
00229   ts->B = l[1];
00230   ts->C = l[2];
00231   ts->alpha = 90.0;
00232   ts->beta = 90.0;
00233   ts->gamma = 90.0;
00234 
00235   // read the coordinates
00236   if (!find_item(data->file, "ATOMS")) {
00237     fprintf(stderr, "lammpsplugin) lammps dump file '%s', could not find ITEM: ATOMS.\n", data->file_name);
00238     return MOLFILE_ERROR;
00239   }
00240 
00241   for (i=0; i<natoms; i++) {
00242     if(!fgets(szBuffer, 1024, data->file)) {
00243       // there is an error or end of file, both cases should not occur
00244       fprintf(stderr, "lammpsplugin) lammps dump file '%s', unexpected end of file or error while reading coordinates for atom %d.\n", data->file_name, i);
00245       return MOLFILE_ERROR;
00246     }
00247 
00248     // Read in atom type, X, Y, Z, skipping any remaining data fields
00249     j = sscanf(szBuffer, "%d %s %f %f %f", &atomid, atom_name, &x, &y, &z);
00250     if (j != 5) {
00251       fprintf(stderr, "lammpsplugin) lammps dump file '%s', error while parsing coordinates for atom %d.\n", data->file_name, i);
00252       return MOLFILE_ERROR;
00253     }
00254             
00255     if (atomid > 0 && atomid <= natoms) {
00256       int addr = 3 * (atomid - 1);
00257       /* LAMMPS coordinates are fractional unit cell coords, */
00258       /* so they need to be scaled by a/b/c etc              */
00259       ts->coords[addr    ] = x * l[0];
00260       ts->coords[addr + 1] = y * l[1];
00261       ts->coords[addr + 2] = z * l[2];
00262     } else {
00263       fprintf(stderr, "lammpsplugin) ignoring illegal atom index %d\n", atomid);
00264     }
00265   }
00266 
00267   return MOLFILE_SUCCESS;
00268 }
00269   
00270 
00271 static void close_lammps_read(void *mydata) {
00272   lammpsdata *data = (lammpsdata *)mydata;
00273   fclose(data->file);
00274   free(data->file_name);
00275   if(data->graphlist) free(data->graphlist);
00276   free(data);
00277 }
00278 
00279 
00280 /* registration stuff */
00281 static molfile_plugin_t lammpsplugin = {
00282   vmdplugin_ABIVERSION,
00283   MOLFILE_PLUGIN_TYPE,                         /* type */
00284   "lammpstrj",                                 /* short name */
00285   "LAMMPS Trajectory",                         /* pretty name */
00286   "John E. Stone",                             /* author */
00287   0,                                           /* major version */
00288   3,                                           /* minor version */
00289   VMDPLUGIN_THREADSAFE,                        /* is reentrant */
00290   "lammpstrj",                                 /* file extension */
00291   open_lammps_read,
00292   read_lammps_structure,
00293   0,
00294   read_lammps_timestep,
00295   close_lammps_read,
00296   0,                            /* write... */
00297   0,
00298   0,
00299   0,
00300   0,                            /* read_volumetric_metadata */
00301   0,                            /* read_volumetric_data */
00302   0,
00303 };
00304 
00305 VMDPLUGIN_API int VMDPLUGIN_init() {
00306   return VMDPLUGIN_SUCCESS;
00307 }
00308 
00309 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00310   (*cb)(v, (vmdplugin_t *)&lammpsplugin);
00311   return VMDPLUGIN_SUCCESS;
00312 }
00313 
00314 VMDPLUGIN_API int VMDPLUGIN_fini() {
00315   return VMDPLUGIN_SUCCESS;
00316 }
00317 
00318 
00319 #ifdef TEST_PLUGIN
00320 
00321 int main(int argc, char *argv[]) {
00322   molfile_timestep_t timestep;
00323   void *v;
00324   int natoms;
00325   int i, nsets, set;
00326 
00327   while (--argc) {
00328     ++argv;
00329     v = open_lammps_read(*argv, "lammps", &natoms);
00330     if (!v) {
00331       fprintf(stderr, "open_lammps_read failed for file %s\n", *argv);
00332       return 1;
00333     }
00334     fprintf(stderr, "open_lammps_read succeeded for file %s\n", *argv);
00335     fprintf(stderr, "number of atoms: %d\n", natoms);
00336 
00337     i = 0;
00338     timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
00339     while (!read_lammps_timestep(v, natoms, &timestep)) {
00340       i++;
00341     }
00342     fprintf(stderr, "ended read_next_timestep on frame %d\n", i);
00343 
00344     close_lammps_read(v);
00345   }
00346   return 0;
00347 }
00348 
00349 #endif
00350 

Generated on Wed Mar 22 13:15:30 2006 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002