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

gamessplugin.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2006 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 
00010 /* *******************************************************
00011  *
00012  *          G A M E S S     P L U G I N 
00013  *
00014  * This plugin allows VMD to read GAMESS log files
00015  * currently only single point geometries and trajectories
00016  * for optimizations, saddle point runs are supported 
00017  *
00018  * ********************************************************/
00019 
00020 #include "gamessplugin.h"
00021 
00022 /* 
00023  * pre-processor macro to activate grid code 
00024  */
00025 #ifdef GRID_ACTIVE
00026 #define GRID 1
00027 #else
00028 #define GRID 0
00029 #endif
00030 
00031 /*
00032  * Error reporting macro for use in DEBUG mode
00033  */
00034 #ifdef GAMESS_DEBUG
00035 #define PRINTERR fprintf(stderr, "\n In file %s, line %d: \n %s \n \n", \
00036                             __FILE__, __LINE__, strerror(errno))
00037 #else
00038 #define PRINTERR (void)(0)
00039 #endif
00040 
00041 /*
00042  * Error reporting macro for the multiple fgets calls in
00043  * the code
00044  */
00045 #define ERR_FALSE(x) if ( x == NULL ) return FALSE;
00046 
00047 
00048 
00049 /***************************************************************
00050  *
00051  * subroutine doing the initial reading of the GAMESS
00052  * input file
00053  *
00054  * *************************************************************/
00055 static void *open_gamess_read(const char *filename, 
00056                   const char *filetype, int *natoms) {
00057 
00058   FILE *fd;
00059   gamessdata *data;
00060   char mytime[BUFSIZ];
00061 
00062   /* initialize array */
00063   mytime[0] = '\0';
00064 
00065   
00066   /* open the input file */
00067   fd = fopen(filename, "rb");
00068  
00069   /* make sure we were able to load the file properly*/
00070   if (!fd) 
00071   {
00072     PRINTERR;
00073     return NULL;
00074   }
00075 
00076   /* obtain the current time */
00077   get_time(mytime);
00078 
00079   /* print out a short warning message -- we're very alpha */
00080   printf("\n");
00081   printf("     *************************************************\n");
00082   printf("     ***       GAMESSPLUGIN for VMD                ***\n");
00083   printf("     *** %s      ***\n", mytime);
00084   printf("     *** email bugs to vmd@ks.uiuc.edu             ***\n");
00085   printf("     *** v0.3.0-rc1 03/05/2006 (c) Markus Dittrich ***\n");
00086   printf("     *************************************************\n");
00087   printf("\n");
00088 
00089   /* allocate memory for main data structure */
00090   data = (gamessdata *)calloc(1,sizeof(gamessdata));
00091 
00092   /* make sure memory was allocated properly */
00093   if (data == NULL) 
00094   {
00095     PRINTERR;
00096     return NULL;
00097   }
00098 
00099 
00100   /**********************************
00101    * initialize some variables
00102    *********************************/
00103 
00104   /* volumetric */
00105   data->have_volumetric = 0; 
00106 
00107   /* runtyp */
00108   data->runtyp = 0;
00109 
00110   /* have_trajectory flag to 1 */
00111   data->have_trajectory = 1; 
00112 
00113   /* reset trajectory counter */
00114   data->num_traj_points = 0;
00115 
00116   /* presence of wavefunction */
00117   data->got_wavefunction = FALSE;
00118 
00119   /* orbital index of HOMO */
00120   data->homo_index = 0;
00121 
00122   /* flag indicating the presence of
00123    * internal coordinates */
00124   data->have_internals = FALSE;
00125 
00126   /* flag indicating the presence of
00127    * the cartesian Hessian */
00128   data->have_cart_hessian = FALSE;
00129 
00130   /* initialize the number of imaginary 
00131    * modes for HESSIAN type runs */
00132   data->nimag = 0;
00133 
00134   /* initialize the GAMESS version */
00135   data->version = 0;
00136 
00137   /* initialize the basis set info */
00138   data->ngauss = 0;
00139   data->npfunc = 0;
00140   data->ndfunc = 0;
00141   data->nffunc = 0;
00142   data->diffs  = 0;
00143   data->diffsp = 0;
00144 
00145   /* initialize the number of scfenergies */
00146   data->num_scfenergies = 0;
00147 
00148   /* initialize some of the character arrays */
00149   strncpy(data->runtyp_string,"\0",sizeof(data->runtyp_string));
00150   strncpy(data->basis_string,"\0",sizeof(data->basis_string));
00151   strncpy(data->version_string,"\0",sizeof(data->version_string));
00152   strncpy(data->scftyp_string,"\0",sizeof(data->scftyp_string));
00153   strncpy(data->memory,"\0",sizeof(data->memory));
00154 
00155   
00156   /***********************************
00157    * done intializing
00158    **********************************/
00159 
00160 
00161   /* store file pointer and filename in gamess
00162    * struct */
00163   data->file = fd;
00164   data->file_name = strdup(filename);
00165 
00166 
00167   /* check if the file is GAMESS format; if yes
00168    * parse it, if no exit */
00169   if ( have_gamess(data) == TRUE ) 
00170   {
00171     /* if we're dealing with an unsupported GAMESS
00172      * version, we better quit */
00173     if ( data->version == 0 )
00174     {
00175       printf("gamessplugin> GAMESS version %s not supported. \n",
00176           data->version_string);
00177       printf("gamessplugin> .... bombing out! Sorry :( \n");
00178       return NULL;
00179     }
00180 
00181     /* get the "static" information from the log file */    
00182     if ( parse_gamess_log_static(data,natoms) == FALSE ) 
00183       return NULL;
00184   }
00185   else 
00186   {
00187     return NULL;
00188   }
00189 
00190 
00191   /* done with the gamess plugin */
00192   rewind(fd);
00193   printf("\n");
00194 
00195 
00196   /* copy pointer also in bogus tcl data pointer */
00197   /* tcl_pointer = data; */
00198 
00199   return data;
00200 }
00201 
00202 
00203 /************************************************************
00204  * 
00205  * subroutine reading in the structure of the molecule
00206  * in the GAMESS output file
00207  *
00208  *************************************************************/
00209 static int read_gamess_structure(void *mydata, int *optflags, 
00210                       molfile_atom_t *atoms) 
00211 {
00212   gamessdata *data = (gamessdata *)mydata;
00213   gamess_temp *temp_atom;
00214   molfile_atom_t *atom;
00215   unsigned int i = 0;
00216  
00217   *optflags = MOLFILE_NOOPTIONS; /* no optional data */
00218 
00219   /* all the information I need has already been read in
00220    * via the initial scan and I simply need to copy 
00221    * everything from the temporary arrays into the 
00222    * proper VMD arrays.
00223    * Since there are no atom names in the GAMESS output
00224    * I use the atom type here --- maybe there is a better
00225    * way to do this !!?? */
00226 
00227   /* get initial pointer for temp arrays */
00228   temp_atom = data->temporary;
00229 
00230   for(i=0;i<data->numatoms;i++)
00231   {
00232     atom=atoms+i;
00233     strncpy(atom->name,temp_atom->type,sizeof(atom->name)); 
00234     strncpy(atom->type,temp_atom->type,sizeof(atom->type));
00235     strncpy(atom->resname,"",sizeof(atom->resname)); 
00236     atom->resid = 1;
00237     atom->charge = temp_atom->charge;
00238     atom->chain[0] = '\0';
00239     atom->segid[0] = '\0';
00240    
00241 
00242     temp_atom++;
00243   }
00244  
00245   return MOLFILE_SUCCESS; 
00246 }
00247 
00248 
00249 /***********************************************************
00250  *
00251  * this function reads in the information for the next
00252  * timestep
00253  *
00254  ***********************************************************/
00255 static int read_next_timestep(void *mydata, int natoms, 
00256     molfile_timestep_t *ts) 
00257 {
00258   gamessdata *data = (gamessdata *)mydata;
00259   gamess_temp *temp_atom;
00260   unsigned int i = 0;
00261 
00262 #ifdef ANIMATE_MODE
00263   mode_data *animated_mode = data->animated_mode;
00264 #endif
00265   
00266   /* Now, if we are not dealing with a trajectory (a single 
00267    * * point conformation is considered one element of a trajectory
00268    */
00269   if (data->have_trajectory == 0) return MOLFILE_ERROR;
00270  
00271 
00272   /* in the case of RUNTYP=ENERGY read data from temp
00273    * arrays and that's it;
00274    * in the case of RUNTYP=OPTIMIZE and SADPOINT just start with
00275    * the first 1NSERCH entry */
00276   if ( data->runtyp == ENERGY ) 
00277   {
00278      /* initialize pointer for temporary arrays */
00279      temp_atom = data->temporary; 
00280  
00281 
00282      /* now copy the initial coordinates from the temporary
00283       * arrays into the VMD ones */
00284      for(i=0;i<natoms;i++)  {
00285 
00286        ts->coords[3*i  ] = temp_atom->x;
00287        ts->coords[3*i+1] = temp_atom->y;
00288        ts->coords[3*i+2] = temp_atom->z; 
00289 
00290        temp_atom++;
00291      }    
00292 
00293      /* Since we are only dealing with a single point which has
00294       * just been read we have to make sure to let VMD know 
00295       * and also register the number of trajectory points as 1 */
00296      data->have_trajectory = 0;
00297 
00298      return MOLFILE_SUCCESS;
00299   }
00300 
00301 #ifndef ANIMATE_MODE
00302   else if ( data->runtyp == HESSIAN ) 
00303   {
00304      /* initialize pointer for temporary arrays */
00305      temp_atom = data->temporary; 
00306  
00307 
00308      /* now copy the initial coordinates from the temporary
00309       * arrays into the VMD ones */
00310      for(i=0;i<natoms;i++)  {
00311 
00312        ts->coords[3*i  ] = temp_atom->x;
00313        ts->coords[3*i+1] = temp_atom->y;
00314        ts->coords[3*i+2] = temp_atom->z; 
00315 
00316        temp_atom++;
00317      }    
00318 
00319      /* Since we are only dealing with a single point which has
00320       * just been read we have to make sure to let VMD know 
00321       * and also register the number of trajectory points as 1 */
00322      data->have_trajectory = 0;
00323 
00324      return MOLFILE_SUCCESS;
00325   }
00326 #endif
00327 
00328 #ifdef ANIMATE_MODE
00329   else if ( data->runtyp == HESSIAN ) 
00330   {
00331     /* read until we run out of frames for the current mode */
00332     if ( animated_mode->current_mode_frame < 
00333               4*animated_mode->mode_num_frames+3 )
00334     {
00335       /* now copy the initial coordinates from the temporary
00336         * arrays into the VMD ones */
00337       for(i=0; i< natoms; i++)  
00338       {
00339         ts->coords[3*i  ] = *(animated_mode->mode_frames +
00340             (animated_mode->current_mode_frame*3*natoms)+3*i);
00341 
00342         ts->coords[3*i+1] = *(animated_mode->mode_frames +
00343             (animated_mode->current_mode_frame*3*natoms)+3*i+1);
00344 
00345         ts->coords[3*i+2] = *(animated_mode->mode_frames +
00346             (animated_mode->current_mode_frame*3*natoms)+3*i+2);
00347       }    
00348 
00349       /* increase the trajectory and mode counter */ 
00350       (animated_mode->current_mode_frame)++;
00351     }
00352     else 
00353     {
00354       return MOLFILE_ERROR;
00355     }
00356 
00357     return MOLFILE_SUCCESS;
00358   }
00359 #endif
00360 
00361   else if ( data->runtyp == OPTIMIZE || data->runtyp == SADPOINT ) 
00362   {
00363     /* call the routine scanning the output file for the
00364      * trajectory */
00365     if ( get_trajectory(data,ts,natoms) == FALSE) {
00366 
00367       /* before we return let's check if we have read
00368        * any trajectory points whatsoever; if not
00369        * this could mean that the file might be
00370        * truncated, and in this case we dump the initial
00371        * coordinate info, such that the user has something
00372        * to look at; */
00373       if ( data->num_traj_points == 0 ) {
00374 
00375         /* initialize pointer for temporary arrays */
00376         temp_atom = data->temporary; 
00377  
00378         
00379         /* now copy the initial coordinates from the temporary
00380         * arrays into the VMD ones */
00381         for(i=0;i<natoms;i++)  {
00382 
00383           ts->coords[3*i  ] = temp_atom->x;
00384           ts->coords[3*i+1] = temp_atom->y;
00385           ts->coords[3*i+2] = temp_atom->z; 
00386 
00387           temp_atom++; }
00388 
00389 
00390         /* make sure we don't continue reading the
00391          * trajectory */
00392         data->have_trajectory = 0;
00393 
00394 
00395         /* that's all we can do */
00396         return MOLFILE_SUCCESS;
00397       }
00398 
00399 
00400       return MOLFILE_ERROR;
00401     }
00402 
00403 
00404     /* increase the trajectory counter */
00405     (data->num_traj_points)++;
00406    
00407 
00408     /* success, it seems :) */
00409     return MOLFILE_SUCCESS;
00410   }
00411 
00412 
00413   /* all other cases should have been rejected allready
00414    * in open_gamess_read;
00415    * but just to make sure we return MOLFILE_ERROR 
00416    * by default */
00417   return MOLFILE_ERROR;
00418 }
00419 
00420 
00421 /*********************************************************
00422  *
00423  * this subroutine makes the volumetric orbital metadata
00424  * available to VMD;
00425  *
00426  ********************************************************/
00427 static int read_orbital_metadata( void *mydata, int *nsets, 
00428                           molfile_volumetric_t **metadata) 
00429 {
00430     gamessdata *data = (gamessdata *)mydata;
00431 
00432     /* first of all we have to test the presence of
00433      * volumetric data; if not set number of volumetric
00434      * data sets to zero and return */
00435 
00436     if ( data->have_volumetric != 1 ) 
00437     {
00438       *nsets = 0;
00439       return MOLFILE_SUCCESS;
00440     }
00441 
00442     /* we only have one set of volumetric data */
00443     *nsets = 1; 
00444 
00445     /* all the necessary data structures have been filled
00446      * in the function get_system_dimensions and we only
00447      * need to copy the pointer. */
00448     *metadata = data->vol;
00449 
00450     return MOLFILE_SUCCESS;
00451 }
00452 
00453 
00454 /**********************************************************
00455  *
00456  * this subroutine makes the volumetric data available 
00457  * to VMD
00458  *
00459  *********************************************************/
00460 static int read_orbital_data( void *mydata, int set, 
00461     float *datablock, float *colorblock) 
00462 {
00463   gamessdata *data = (gamessdata *)mydata;
00464   gamess_temp *temp_data;
00465   molfile_volumetric_t *vol_metadata;
00466   unsigned int i = 0;
00467   int numxyz;
00468 
00469   /* get pointer of temporary data storage */
00470   temp_data = data->temporary; 
00471 
00472   /* get pointer to volumetric metadata */
00473   vol_metadata = data->vol;
00474 
00475   /* move array containing volumetric over to datablock 
00476    * the array contains xsize*ysize*zsize elements */
00477   numxyz = ( vol_metadata->xsize * vol_metadata->ysize * 
00478              vol_metadata->zsize );
00479 
00480   for ( i = 0 ; i < numxyz ; ++i )
00481   {
00482     *(datablock + i) = *(data->orbital_grid+i);
00483   }
00484 
00485   return MOLFILE_SUCCESS;
00486 }
00487 
00488 
00489 /**********************************************************
00490  *
00491  * clean up when done and free all the memory do avoid
00492  * memory leaks
00493  *
00494  **********************************************************/
00495 static void close_gamess_read(void *mydata) {
00496 
00497   gamessdata *data = (gamessdata *)mydata;
00498   fclose(data->file);
00499 
00500   /* free memory */
00501   free(data->temporary);
00502   free(data->basis);
00503   free(data->system_dimensions);
00504   free(data->system_center); 
00505   free(data->orbital_grid);
00506   free(data->basis_counter);
00507   free(data->wave_function);
00508   free(data->orbital_symmetry);
00509   free(data->atomic_shells);
00510   free(data->shell_primitives);
00511   free(data->orbital_energy);
00512   free(data->atomic_number);
00513   free(data->mulliken_charges);
00514   free(data->esp_charges);
00515   free(data->bonds);
00516   free(data->angles);
00517   free(data->dihedrals);
00518   free(data->impropers);
00519   free(data->internal_coordinates);
00520   free(data->bond_force_const);
00521   free(data->angle_force_const);
00522   free(data->dihedral_force_const);
00523   free(data->improper_force_const);
00524   free(data->inthessian);
00525   free(data->carthessian);
00526   free(data->vol);
00527   free(data->scfenergies);
00528   free(data->wavenumbers);
00529   free(data->intensities);
00530   free(data->normal_modes);
00531   
00532   if ( data->runtyp == HESSIAN )
00533   {
00534 #ifdef ANIMATE_MODE
00535     free(data->animated_mode->mode_frames);
00536     free(data->animated_mode);
00537 #endif
00538   }
00539 
00540   free(data);
00541 }
00542 
00543 
00544 /*************************************************************
00545  *
00546  * registration stuff 
00547  *
00548  **************************************************************/
00549 static molfile_plugin_t gamessplugin = {
00550   vmdplugin_ABIVERSION,
00551   MOLFILE_PLUGIN_TYPE,                         /* type */
00552   "gamess",                                    /* short name */
00553   "GAMESS",                                    /* pretty name */
00554   "Markus Dittrich",                           /* author */
00555   0,                                           /* major version */
00556   3,                                           /* minor version */
00557   VMDPLUGIN_THREADSAFE,                        /* is reentrant */
00558   "log",
00559   open_gamess_read,
00560   read_gamess_structure,
00561   0,
00562   read_next_timestep,
00563   close_gamess_read,
00564   0,
00565   0,
00566   0,
00567   0,
00568   read_orbital_metadata,
00569   read_orbital_data
00570 };
00571 
00572 
00573 VMDPLUGIN_API int VMDPLUGIN_init(void) {
00574   return VMDPLUGIN_SUCCESS;
00575 }
00576 
00577 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00578   (*cb)(v, (vmdplugin_t *)&gamessplugin);
00579   return VMDPLUGIN_SUCCESS;
00580 }
00581 
00582 VMDPLUGIN_API int VMDPLUGIN_fini(void) {
00583   return VMDPLUGIN_SUCCESS;
00584 }
00585 
00586 
00587 
00588 
00589 /********************************************************
00590  *
00591  * THE NEXT SECTION CONTAINs THE GAMESS OUTPUT FILE
00592  * SPECIFIC SUBROUTINES
00593  *
00594  ********************************************************/
00595 
00596 
00597 
00598 
00599 
00600 /********************************************************
00601  *
00602  * this routine is the main gamess log file
00603  * parser responsible for static, i.e. 
00604  * non-trajectory information 
00605  *
00606  ********************************************************/
00607 int parse_gamess_log_static(void *mydata, int *natoms) 
00608 {
00609   gamessdata *data = (gamessdata *)mydata;
00610 
00611   /* determine the number of procs and the amount
00612    * of memory requested */
00613   if ( get_proc_mem(data) == FALSE ) return FALSE;
00614 
00615 
00616   /* determine the GBASIS used for the run */
00617   if ( get_gbasis(data) == FALSE ) return FALSE;
00618 
00619 
00620   /* read the run title */
00621   if ( get_runtitle(data) == FALSE ) return FALSE;
00622 
00623 
00624   /* read the contrl group; here we determine the
00625    * RUNTYP and bomb out if we don't support
00626    * it; also read in some controlflow related
00627    * info as well as the COORD type */
00628   if ( check_contrl(data) == FALSE ) return FALSE;
00629 
00630 
00631   /* now call routine get_initial_info to obtain 
00632    * the number of atoms, the atom types, and the
00633    * coordinates, which will be stored in gamess_temp */
00634   if ( get_initial_info(data) == FALSE ) return FALSE;
00635 
00636 
00637   /* provide VMD with the proper number of atoms */
00638   *natoms = data->numatoms;
00639 
00640 
00641   /* read in the number of orbitals, charge, 
00642    * multiplicity, ... */
00643   if ( get_num_orbitals(data) == FALSE ) return FALSE;
00644 
00645 
00646   /* check if the wavefunction and orbital stuff
00647    * is suported for current GBASIS; if not stop
00648    * here and return data pointer */
00649   if ( have_supported_gbasis(data) == FALSE) return TRUE;
00650 
00651 
00652   /* read in the guess options */
00653   if ( get_guess(data) == FALSE ) return FALSE;
00654 
00655   
00656   /* read in the final wavefunction; do this only for 
00657    * RUNTYP=ENERGY for now. For the other runs I have to
00658    * put in some more infrastructure to make sure to
00659    * correlate each of the possible many geometries
00660    * during e.g. an optimization run with the correstpoding
00661    * wavefunction 
00662    * for now we also have to restrict reading the wavefunctions
00663    * for singlets only, since otherwise the punched wavefunction
00664    * output differs;
00665    * At least the call to generate orbital grid should
00666    * not be done automagically but rather after a TCL call
00667    * only */
00668   if ( data->runtyp == ENERGY 
00669          && data->num_orbitals_A == data->num_orbitals_B 
00670          && GRID)
00671   {
00672     /* read in the basis set information */
00673     if ( get_basis(data) == FALSE ) return FALSE; 
00674 
00675 
00676     /* read the wavefunction */
00677     if ( get_wavefunction(data) == FALSE) return FALSE;  
00678 
00679 
00680     /* figure out which one of the orbitals is the HOMO */
00681     if ( find_homo(data) == FALSE) return FALSE; 
00682 
00683  
00684     /* generate the grid containing the volumetric data
00685      * for an orbital */
00686     if( orbital_grid_driver(data) == FALSE ) return FALSE;  
00687 
00688   }
00689 
00690   return TRUE;
00691 }
00692 
00693 
00694 
00695 /******************************************************
00696  *
00697  * this function extracts the trajectory information
00698  * from the output file
00699  *
00700  * *****************************************************/
00701 int get_trajectory(void *mydata, molfile_timestep_t *ts,
00702                    int natoms) 
00703 {
00704   gamessdata *data = (gamessdata *)mydata;
00705   char buffer[BUFSIZ];
00706   char word[4][BUFSIZ];
00707   char type[8];
00708   unsigned int i = 0;
00709   float charge,x,y,z;
00710   double scfenergy = 0.0;
00711 
00712   /* zero out the word arrays */
00713   buffer[0] = '\0';
00714   type[0] = '\0';
00715   for ( i = 0; i < 4; ++i) word[i][0] = '\0';
00716 
00717 
00718   /* search for the first coordinate frame during optimization */
00719   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00720 
00721 
00722   /* at this point we have to distinguish between
00723    * pre="27 JUN 2005 (R2)" and "27 JUN 2005 (R2)"
00724    * versions since the output format for geometry
00725    * optimizations has changed */
00726   if ( data->version == 1)
00727   {
00728      /* scan for the next optimized geometry punched in the 
00729       * logfile */
00730      do 
00731      {
00732        sscanf(buffer,"%s %s",&word[0][0],&word[1][0]); ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00733 
00734      } while (strcmp(&word[0][0],"1NSERCH="));
00735   }
00736   else if ( data->version == 2 )
00737   {
00738      /* scan for the next optimized geometry punched in the 
00739       * logfile */
00740      do 
00741      {
00742        sscanf(buffer,"%s %s %s",&word[0][0],&word[1][0],
00743             &word[2][0]); 
00744        ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00745 
00746      } while (strcmp(&word[0][0],"BEGINNING") || 
00747               strcmp(&word[1][0],"GEOMETRY")  ||
00748               strcmp(&word[2][0],"SEARCH"));
00749   }
00750 
00751 
00752   /* skip the next three lines */
00753   eatline(data->file);
00754   eatline(data->file);
00755   eatline(data->file);
00756   
00757 
00758   /* read the actual coordinates */
00759   for(i=0;i<natoms;i++) 
00760   {
00761     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00762     sscanf(buffer,"%s %f %f %f %f",type,&charge,&x,&y,&z);  
00763 
00764     /* store the coordinates */
00765     ts->coords[3*i  ] = x; 
00766     ts->coords[3*i+1] = y;
00767     ts->coords[3*i+2] = z; 
00768   }     
00769 
00770 
00771   /* now we look for the SCF energy of this trajectory 
00772    * point */
00773    do 
00774    {
00775     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00776     sscanf(buffer,"%s %s %s %lf",&word[0][0],&word[1][0],
00777         &word[2][0],&scfenergy); 
00778  
00779     } while (strcmp(&word[2][0],"ENERGY=") && 
00780              strcmp(&word[1][0],"ENERGY=")); 
00781   
00782   /* allocate more memory for scfenergy array */
00783   data->scfenergies = (double *)realloc(data->scfenergies,
00784         (data->num_traj_points+1)*sizeof(double));
00785 
00786 
00787   /* append current scfenergy to array and increase counter */
00788   *(data->scfenergies+data->num_traj_points) = scfenergy;
00789   data->num_scfenergies++;
00790 
00791 
00792   /* done with this trajectory point */ 
00793   return TRUE;
00794 }
00795 
00796 
00797 
00798 /******************************************************
00799  *
00800  * this function performs an initial file read
00801  * to check its validity and determine the number
00802  * of atoms in the system 
00803  *
00804  * *****************************************************/
00805 int get_initial_info(void *mydata)
00806 {
00807   gamessdata *data = (gamessdata *)mydata;
00808   gamess_temp *atoms;
00809   char buffer[BUFSIZ];
00810   char word[4][BUFSIZ];
00811   char atname[BUFSIZ];
00812   float charge;
00813   float x,y,z;
00814   unsigned int numatoms;
00815   unsigned int bohr;
00816   unsigned int i,n;
00817   unsigned int have_normal_modes = TRUE;
00818   double scfenergy;
00819   char *status;
00820 
00821   /* initialize buffers */
00822   buffer[0] = '\0';
00823   atname[0] = '\0';
00824   for ( i = 0; i < 4; ++i ) word[i][0] = '\0';
00825  
00826 
00827   /* alocate temporary data structure */
00828   atoms = (gamess_temp *)calloc(MAXQMATOMS,sizeof(gamess_temp));
00829 
00830   /* make sure memory was allocated properly */
00831   if ( atoms == NULL) 
00832   {
00833     PRINTERR; 
00834     return FALSE;
00835   }
00836 
00837 
00838   /* save pointer */
00839   data->temporary = atoms;
00840 
00841 
00842   /* counts the number of atoms in input file */
00843   numatoms=0;  
00844 
00845   /* look for the initial coordinate section 
00846    * NOTE: I also have to check if the coordinates are
00847    * in Angstrom or Bohr and convert them to A in the
00848    * latter case */
00849   rewind(data->file);
00850 
00851   do 
00852   {
00853     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00854     sscanf(buffer,"%s %s %s %s",&word[0][0],&word[1][0],
00855         &word[2][0],&word[3][0]);
00856 
00857   } while(strcmp(&word[0][0],"ATOM") || 
00858           strcmp(&word[1][0],"ATOMIC"));
00859 
00860   
00861   /* test if coordinate units are Bohr */
00862   bohr = (!strcmp(&word[3][0],"(BOHR)"));
00863 
00864 
00865   /* skip next line */
00866   eatline(data->file);
00867 
00868 
00869   /* now read in the coordinates until an empty line is being
00870    * encoutered */
00871   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00872   n = sscanf(buffer,"%s %f %f %f %f",atname,&charge,&x,&y,&z);
00873 
00874   /* we expect 5 entries per line */
00875   while( n == 5 ) 
00876   {
00877     strncpy(atoms->type,atname,sizeof(atoms->type));
00878     atoms->charge = charge;
00879 
00880 
00881     /* if coordinates are in Bohr convert them to Angstrom here */
00882     if (bohr) 
00883     {
00884       x = BOHR_TO_ANGS * x;
00885       y = BOHR_TO_ANGS * y;
00886       z = BOHR_TO_ANGS * z;
00887     }
00888 
00889     atoms->x = x;
00890     atoms->y = y;
00891     atoms->z = z; 
00892 
00893 
00894     atoms++;
00895     numatoms++;
00896 
00897     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
00898     n = sscanf(buffer,"%s %f %f %f %f",atname,&charge,&x,&y,&z);
00899   }
00900 
00901   /* store number of atoms in data structure */
00902   data->numatoms = numatoms;
00903 
00904 
00905 
00906   /* save a copy of atom charges in atomic_number array
00907    * of gamessdata */
00908 
00909   /* alocate temporary data structure */
00910   data->atomic_number = (int *)calloc(numatoms,sizeof(int));
00911 
00912   /* make sure memory was allocated properly */
00913   if (data->atomic_number == NULL) 
00914   {
00915     PRINTERR; 
00916     return FALSE;
00917   }
00918 
00919   
00920   /* move data over */ 
00921   for ( n = 0; n < numatoms; n++) 
00922   {
00923     *(data->atomic_number + n) = (int)(data->temporary + n)->charge;
00924   }
00925 
00926 
00927   /* at this point we create an empty scfenergy arrar */
00928   data->scfenergies = (double *)calloc(0,sizeof(double));
00929 
00930 
00931   /* of we are dealing with a single point energy run 
00932    * we read in the final SCF energy and store it;
00933    * TODO: for now also include HESSIAN runs here even though
00934    * this is not completely correct in the case of numerical
00935    * runs*/
00936   if ( (data->runtyp == ENERGY) || (data->runtyp == HESSIAN) )
00937   {
00938     status = fgets(buffer,sizeof(buffer),data->file);
00939      
00940     while ( strcmp(&word[0][0],"FINAL") || 
00941             strcmp(&word[2][0],"ENERGY") ||
00942             strcmp(&word[3][0],"IS"))
00943     {
00944       sscanf(buffer,"%s %s %s %s %lf",&word[0][0],&word[1][0],
00945              &word[2][0],&word[3][0],&scfenergy);
00946 
00947       if ( fgets(buffer,sizeof(buffer),data->file) == NULL) break;
00948     }
00949 
00950     data->scfenergies = (double *)realloc(data->scfenergies,
00951              sizeof(double));
00952     *(data->scfenergies) = scfenergy;
00953     data->num_scfenergies++;
00954   }
00955 
00956 
00957   /* next we check for the Mulliken charges; if they are present
00958    * we set the have_mulliken charge flag, but don't bomb out */
00959 
00960   /* set have_mulliken initially to true */
00961   data->have_mulliken = TRUE;
00962 
00963   do 
00964   {
00965     status = fgets(buffer,sizeof(buffer),data->file);
00966 
00967     /* check for EOF */
00968     if (status == NULL) {
00969      
00970       data->have_mulliken = FALSE;
00971       break;
00972     }
00973 
00974     sscanf(buffer,"%s %s %s %s",&word[0][0],&word[1][0],
00975         &word[2][0],&word[3][0]);
00976 
00977   } while(strcmp(&word[0][0],"TOTAL") || 
00978           strcmp(&word[1][0],"MULLIKEN") ||
00979           strcmp(&word[2][0],"AND")   || 
00980           strcmp(&word[3][0],"LOWDIN") );
00981 
00982 
00983   /* if Mulliken Charges are present read them, if not, rewind
00984    * the file and look for the ESP charges */
00985   if ( data->have_mulliken == TRUE ) 
00986   {
00987     /* reserve memory for dynamically allocated
00988      * Mulliken charge array */
00989     data->mulliken_charges = 
00990       (double *)calloc(numatoms,sizeof(double));
00991 
00992     /* check for success */
00993     if (data->mulliken_charges == NULL) 
00994     {
00995       PRINTERR; 
00996       return FALSE;
00997     }
00998 
00999 
01000     /* skip next line */
01001     eatline(data->file);
01002 
01003     for ( n = 0; n < numatoms; ++n) 
01004     {
01005       /* make sure we don't get nuked by a bad file */
01006       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01007 
01008       sscanf(buffer,"%s %s %s %lf ",&word[0][0], &word[1][0], 
01009           &word[2][0], (data->mulliken_charges+n));
01010     }
01011   }
01012 
01013   /* no Mulliken charges found; in this case we don't know where
01014    * we are in the file; hence rewind file */
01015   else 
01016   {
01017     rewind(data->file); 
01018   }
01019 
01020 
01021   /* next we check for the ESP charges; if they are present
01022    * we set the have_esp charge flag, but don't bomb out */
01023 
01024   /* set have_esd initially to true */
01025   data->have_esp = TRUE;
01026 
01027   do 
01028   {
01029     status = fgets(buffer,sizeof(buffer),data->file);
01030 
01031     /* check for EOF */
01032     if (status == NULL) {
01033      
01034       data->have_esp = FALSE;
01035       break;
01036     }
01037 
01038     sscanf(buffer,"%s %s %s",&word[0][0],&word[1][0],&word[2][0]);
01039 
01040   } while(strcmp(&word[0][0],"ATOM") || 
01041           strcmp(&word[1][0],"CHARGE") ||
01042           strcmp(&word[2][0],"E.S.D.") );
01043 
01044 
01045   /* if ESP Charges are present read them, if not, rewind
01046    * the file and return */
01047   if ( data->have_esp == TRUE ) 
01048   {
01049     /* reserve memory for dynamically allocated
01050      * Mulliken charge array */
01051     data->esp_charges = 
01052       (double *)calloc(numatoms,sizeof(double));
01053 
01054     /* check for success */
01055     if (data->esp_charges == NULL) 
01056     {
01057       PRINTERR; 
01058       return FALSE;
01059     }
01060 
01061 
01062     /* skip next line */
01063     eatline(data->file);
01064 
01065     for ( n = 0; n < numatoms; ++n) {
01066 
01067       /* make sure we don't get nuked by a bad file */
01068       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01069       sscanf(buffer,"%s %lf ",&word[0][0], (data->esp_charges+n));
01070     }
01071   }
01072 
01073   /* no ESP charges found; in this case we don't know where
01074    * we are in the file; hence rewind file */
01075   else 
01076   {
01077     rewind(data->file); 
01078   }
01079 
01080 
01081   /* short message */ 
01082   printf("gamessplugin> Detected %d atoms in the input file. \n",
01083           data->numatoms);
01084 
01085 
01086   if ( data->runtyp == HESSIAN ) 
01087   {
01088 
01089 #ifdef ANIMATE_MODE
01090     initialize_animated_mode(data);
01091 #endif
01092 
01093     /* try reading the hessian matrix in internal and
01094      * cartesian coordinates as well as the internal
01095      * coordinates together with their associated
01096      * force constants */
01097     if ( get_int_coords(data) == TRUE ) 
01098     {
01099       data->have_internals = TRUE;
01100     }
01101     else 
01102     {
01103       printf("gamessplugin> \n");
01104       printf("gamessplugin> Could not determine the internal \n");
01105       printf("gamessplugin> coordinate and Hessian info!! \n");
01106       printf("gamessplugin> \n");
01107     }
01108     
01109  
01110     if ( get_cart_hessian(data) == TRUE ) 
01111     {
01112       data->have_cart_hessian = TRUE;
01113     }
01114     else 
01115     {
01116       printf("gamessplugin> \n");
01117       printf("gamessplugin> Could not determine the cartesian \n");
01118       printf("gamessplugin> Hessian matrix!! \n");
01119       printf("gamessplugin> \n");
01120     }
01121 
01122 
01123     /* read the wavenumbers, intensities of the normal modes 
01124      * as well as the modes themselves */
01125     if ( get_normal_modes(data) == FALSE ) 
01126     {
01127       printf("gamessplugin> \n");
01128       printf("gamessplugin> Could not scan the normal modes,\n");
01129       printf("gamessplugin> \n");
01130 
01131       have_normal_modes = FALSE;
01132     }
01133 
01134 #ifdef ANIMATE_MODE
01135     /* generate an animated trajectory for mode i */ 
01136     if (data->have_cart_hessian && have_normal_modes) 
01137     {
01138       if ( animate_normal_mode(data, 62) == FALSE )
01139       {
01140         printf("gamessplugin> \n");
01141         printf("gamessplugin> Error generating animated normal mode");
01142         printf("gamessplugin> \n \n");
01143       }
01144     }
01145 #endif
01146 
01147   }
01148 
01149   /* done with this one */
01150   return TRUE; 
01151 }
01152 
01153 
01154 
01155 /******************************************************
01156  *
01157  * this function generates animated frames for normal
01158  * mode mode_to_animate
01159  *
01160  * *****************************************************/
01161 int initialize_animated_mode(void *mydata)
01162 {
01163   gamessdata *data = (gamessdata *)mydata;
01164   mode_data *animated_mode;
01165 
01166   /* allocate memory for a mode_data struct */
01167   animated_mode = (mode_data *)calloc(1,sizeof(mode_data)); 
01168 
01169   if ( animated_mode == NULL )
01170   {
01171     PRINTERR;
01172     return FALSE;
01173   }
01174 
01175   /* save pointer in gamessdata struct */
01176   data->animated_mode = animated_mode;
01177 
01178   /* set the number of frames per animated mode */
01179   animated_mode->mode_num_frames = 25;
01180 
01181   /* initialize the animated mode tracker */
01182   animated_mode->current_mode_frame = 0;
01183 
01184   /* set the scaling factor for the animated mode */
01185   animated_mode->mode_scaling = 0.01;
01186 
01187   /* reserve memory for animated mode trajectory */
01188   animated_mode->mode_frames = (double *)calloc((4 *
01189       animated_mode->mode_num_frames+3)*data->numatoms*3, 
01190       sizeof(double));
01191 
01192   if ( animated_mode->mode_frames == NULL )
01193   {
01194     PRINTERR;
01195     return FALSE;
01196   }
01197 
01198   return TRUE;
01199 }
01200 
01201 
01202 
01203 /************************************************************
01204  *
01205  * this function animates a given normal mode by means of
01206  * generating mod_num_frames frames away from the equilibrium
01207  * structure in a direction given by the hessiane 
01208  *
01209  ************************************************************/
01210 int animate_normal_mode(void *mydata, unsigned int mode)
01211 {
01212   gamessdata *data = (gamessdata *)mydata;
01213   mode_data *animated_mode = data->animated_mode;
01214   double *normal_modes = data->normal_modes;
01215   double scale = animated_mode->mode_scaling;
01216   unsigned int i = 0, k = 0; 
01217   int l = 0, m = 0;
01218   unsigned int natoms = data->numatoms;
01219   unsigned int num_frames = animated_mode->mode_num_frames;
01220 
01221   /* first sweep to max of interval */
01222   for ( k = 0; k < num_frames+1; ++k)
01223   {
01224     for ( i = 0; i < natoms; ++i)
01225     {
01226       *(animated_mode->mode_frames+(k*natoms*3)+(3*i)) = 
01227           (data->temporary+i)->x * (1+( k*scale * 
01228           (*(normal_modes+(mode*natoms*3)+(3*i)))));
01229 
01230       *(animated_mode->mode_frames+(k*natoms*3)+(3*i+1)) = 
01231           (data->temporary+i)->y * (1+( k*scale * 
01232           (*(normal_modes+(mode*natoms*3)+(3*i+1)))));
01233 
01234       *(animated_mode->mode_frames+(k*natoms*3)+(3*i+2)) = 
01235           (data->temporary+i)->z * (1+( k*scale * 
01236           (*(normal_modes+(mode*natoms*3)+(3*i+2)))));
01237     }
01238   }
01239 
01240 
01241   /* second sweep all the way back to min of interval */
01242   for ( l = 0; l < 2*num_frames+1; ++l)
01243   {
01244     for ( i = 0; i < natoms; ++i)
01245     {
01246       *(animated_mode->mode_frames+((l+k)*natoms*3)+(3*i)) = 
01247           (data->temporary+i)->x * (1+((int)(num_frames-l)*scale * 
01248           (*(normal_modes+(mode*natoms*3)+(3*i)))));
01249 
01250       *(animated_mode->mode_frames+((l+k)*natoms*3)+(3*i+1)) = 
01251           (data->temporary+i)->y * (1+((int)(num_frames-l)*scale * 
01252           (*(normal_modes+(mode*natoms*3)+(3*i+1)))));
01253 
01254       *(animated_mode->mode_frames+((l+k)*natoms*3)+(3*i+2)) = 
01255           (data->temporary+i)->z * (1+((int)(num_frames-l)*scale * 
01256           (*(normal_modes+(mode*natoms*3)+(3*i+2)))));
01257     }
01258   }
01259 
01260 
01261   /* third sweep back to the native starting structure */
01262   for ( m = 0; m < num_frames+1; ++m)
01263   {
01264     for ( i = 0; i < natoms; ++i)
01265     {
01266       *(animated_mode->mode_frames+((l+k+m)*natoms*3)+(3*i)) = 
01267           (data->temporary+i)->x * (1+((int)(m-num_frames)*scale * 
01268           (*(normal_modes+(mode*natoms*3)+(3*i)))));
01269 
01270       *(animated_mode->mode_frames+((l+k+m)*natoms*3)+(3*i+1)) = 
01271           (data->temporary+i)->y * (1+((int)(m-num_frames)*scale * 
01272           (*(normal_modes+(mode*natoms*3)+(3*i+1)))));
01273 
01274       *(animated_mode->mode_frames+((l+k+m)*natoms*3)+(3*i+2)) = 
01275           (data->temporary+i)->z * (1+((int)(m-num_frames)*scale * 
01276           (*(normal_modes+(mode*natoms*3)+(3*i+2)))));
01277     }
01278   }
01279 
01280   /* short message */
01281   printf("gamessplugin> Successfully animated mode %d \n", mode);
01282 
01283   return TRUE;
01284 }
01285 
01286 
01287 
01288 /***********************************************************
01289  *
01290  * this function reads in the wavenumbers and intensities of
01291  * the normal modes
01292  *
01293  * *********************************************************/
01294 int get_normal_modes(void *mydata)
01295 {
01296   gamessdata *data = (gamessdata *)mydata;
01297   char word[4][BUFSIZ];
01298   char buffer[BUFSIZ];
01299   unsigned int i = 0, k = 0, j = 0;
01300   unsigned int remaining_columns;
01301   double entry[6]; 
01302   char separator;
01303   char *item;
01304   unsigned int counter;
01305 
01306 
01307   /* initialize arrays */
01308   buffer[0] = '\0';
01309   memset(entry, 0, sizeof(entry));
01310   for ( i = 0; i < 4; ++i) word[i][0] = '\0';
01311 
01312     
01313   /* reserve memory for dynamically allocated data
01314    * arrays */
01315   item = (char *)calloc(BUFSIZ,sizeof(char));
01316 
01317   if ( item == NULL )
01318   {
01319     PRINTERR;
01320     return FALSE;
01321   }
01322 
01323 
01324   data->wavenumbers = 
01325     (double *)calloc(data->numatoms*3,sizeof(double));
01326 
01327   if ( data->wavenumbers == NULL ) 
01328   {
01329     PRINTERR;
01330     return FALSE;
01331   }
01332 
01333 
01334   data->intensities = 
01335     (double *)calloc(data->numatoms*3,sizeof(double));
01336 
01337   if ( data->intensities == NULL ) 
01338   {
01339     PRINTERR;
01340     return FALSE;
01341   }
01342 
01343 
01344   data->normal_modes = 
01345     (double *)calloc((data->numatoms*3)*(data->numatoms*3),
01346                      sizeof(double));
01347 
01348   if ( data->normal_modes == NULL ) 
01349   {
01350     PRINTERR;
01351     return FALSE;
01352   }
01353 
01354 
01355   /* look for FREQUENCYs and IR INTENSITIES */
01356   for ( i = 0; i < (unsigned int)(data->numatoms*3/5); ++i) 
01357   {
01358     do 
01359     {
01360       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01361       sscanf(buffer,"%s ",&word[0][0]);
01362 
01363     } while(strcmp(&word[0][0],"FREQUENCY:"));
01364 
01365 
01366     /* scan the frequencies; 
01367      * this requires some care since there might
01368      * be imaginary modes present which leads to
01369      * an additional char per imaginary mode per
01370      * line */
01371 
01372     /* check for imaginary modes */
01373     if ( strchr(buffer,'I') != NULL ) 
01374     {
01375       /* initialize */
01376       separator = ' ';
01377       counter = 0;
01378 
01379       /* read all line elements into individual strings */
01380 
01381       /* skip first entry "FREQUENCY" */
01382       item = strtok(buffer,&separator);
01383       
01384       /* start going through the string */
01385       while ( (item = strtok(NULL,&separator)) != NULL ) 
01386       {
01387         /* check if item is 'I'; if yes, mark previous mode
01388          * as imaginary; otherwise save the mode */
01389         if ( *item == 'I' ) 
01390         {
01391           data->nimag++;
01392         }
01393         else 
01394         {
01395           /* save only the first 5 modes - there NEVER should
01396            * be more in any case, but just to make sure
01397            * we don't overrun the array */
01398           if ( counter < 5 ) 
01399           {
01400             *(data->wavenumbers+(i*5)+counter) = atof(item);
01401             counter++;
01402           }
01403         }
01404       } 
01405     }
01406 
01407 
01408     /* no imaginary mode, reading is straightforward */
01409     else 
01410     {
01411       sscanf(buffer,"%s %lf %lf %lf %lf %lf",&word[0][0],
01412         &entry[0],&entry[1],&entry[2],&entry[3],&entry[4]); 
01413     
01414       /* save 'em */
01415       for ( k = 0; k < 5; ++k) 
01416       {
01417         *(data->wavenumbers+(i*5)+k) = entry[k]; 
01418       }
01419     }
01420 
01421 
01422     /* skip next line */
01423     eatline(data->file);
01424 
01425 
01426     /* next line contains the IR INTENSITIES */
01427     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01428 
01429     /* scan the IR INTENSITIES */
01430     sscanf(buffer,"%s %s %lf %lf %lf %lf %lf",&word[0][0],&word[1][0],
01431         &entry[0],&entry[1],&entry[2],&entry[3],&entry[4]);
01432  
01433 
01434     /* save 'em */
01435     for ( k = 0; k < 5; ++k) 
01436     {
01437       *(data->intensities+(i*5)+k) = entry[k]; 
01438     }
01439 
01440     /* skip the next line */
01441     eatline(data->file);
01442 
01443     /* read the following five modes */
01444     for ( k = 0; k < data->numatoms; ++k)
01445     {
01446       /* x */
01447       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01448       sscanf(buffer,"%s %s %s %lf %lf %lf %lf %lf",&word[0][0], 
01449           &word[1][0], &word[2][0], &entry[0], &entry[1], &entry[2],
01450           &entry[3], &entry[4]);
01451 
01452       /* store 'em */
01453       for ( j = 0; j < 5; ++j)
01454       {
01455         *(data->normal_modes+(3*k)+((i*5+j)*3*data->numatoms)) = 
01456             entry[j];
01457       }
01458 
01459 
01460       /* y */
01461       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01462       sscanf(buffer,"%s %lf %lf %lf %lf %lf",&word[0][0], &entry[0],
01463           &entry[1],&entry[2], &entry[3],&entry[4]);
01464 
01465       /* store 'em */
01466       for ( j = 0; j < 5; ++j)
01467       {
01468         *(data->normal_modes+(3*k+1)+((i*5+j)*3*data->numatoms)) = 
01469             entry[j];
01470       }
01471 
01472 
01473       /* z */
01474       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01475       sscanf(buffer,"%s %lf %lf %lf %lf %lf",&word[0][0], &entry[0],
01476           &entry[1], &entry[2], &entry[3],&entry[4]);
01477 
01478       /* store 'em */
01479       for ( j = 0; j < 5; ++j)
01480       {
01481         *(data->normal_modes+(3*k+2)+((i*5+j)*3*data->numatoms)) = 
01482             entry[j];
01483       }
01484     }
01485   }
01486 
01487 
01488   /* read the remaining columns */
01489   if ( ( remaining_columns = (data->numatoms*3)%5) != 0 ) { 
01490 
01491     /* move to next set of modes */
01492     do 
01493     {
01494       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01495       sscanf(buffer,"%s ",&word[0][0]);
01496 
01497     } while(strcmp(&word[0][0],"FREQUENCY:"));
01498 
01499 
01500     /* scan the frequencies; 
01501      * this requires some care since there might
01502      * be imaginary modes present which leads to
01503      * an additional char per imaginary mode per
01504      * line */
01505 
01506     /* check for imaginary modes */
01507     if ( strchr(buffer,'I') != NULL ) 
01508     {
01509       /* initialize */
01510       separator = ' ';
01511       counter = 0;
01512 
01513       /* read all line elements into individual strings */
01514 
01515       /* skip first entry "FREQUENCY" */
01516       item = strtok(buffer,&separator);
01517 
01518       
01519       /* start going through the string */
01520       while ( (item = strtok(NULL,&separator)) != NULL ) 
01521       {
01522         /* check if item is 'I'; if yes, mark previous mode
01523          * as imaginary; otherwise save the mode */
01524         if ( *item == 'I' ) 
01525         {
01526           data->nimag++;
01527         }
01528         else 
01529         {
01530           /* save only the first remaining columns modes - 
01531            * there NEVER should
01532            * be more in any case, but just to make sure
01533            * we don't overrun the array */
01534           if ( counter < remaining_columns ) 
01535           {
01536             *(data->wavenumbers+(i*5)+counter) = atof(item);
01537             counter++;
01538           }
01539         }
01540       } 
01541     }
01542 
01543 
01544     /* no imaginary mode, reading is straightforward */
01545     else 
01546     {
01547       sscanf(buffer,"%s %lf %lf %lf %lf %lf",&word[0][0],
01548         &entry[0],&entry[1],&entry[2],&entry[3],&entry[4]); 
01549  
01550       /* save 'em */
01551       for ( k = 0; k < remaining_columns; ++k) 
01552       {
01553         *(data->wavenumbers+(i*5)+k) = entry[k]; 
01554       }
01555     }
01556 
01557 
01558     /* skip next line */
01559     eatline(data->file);
01560 
01561     
01562     /* next line contains the IR INTENSITIES */
01563     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01564 
01565     /* scan the IR INTENSITIES */
01566     sscanf(buffer,"%s %s %lf %lf %lf %lf %lf",&word[0][0],&word[1][0],
01567         &entry[0],&entry[1],&entry[2],&entry[3],&entry[4]);
01568  
01569     /* save 'em */
01570     for ( k = 0; k < remaining_columns; ++k) 
01571     {
01572       *(data->intensities+(i*5)+k) = entry[k];
01573     }
01574 
01575 
01576     /* skip the next line */
01577     eatline(data->file);
01578 
01579     /* read the following five modes */
01580     for ( k = 0; k < data->numatoms; ++k)
01581     {
01582       /* x */
01583       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01584       sscanf(buffer,"%s %s %s %lf %lf %lf %lf %lf",&word[0][0], 
01585           &word[1][0], &word[2][0], &entry[0], &entry[1], &entry[2],
01586           &entry[3], &entry[4]);
01587 
01588       /* store 'em */
01589       for ( j = 0; j < remaining_columns; ++j)
01590       {
01591         *(data->normal_modes+(3*k)+((i*5+j)*3*data->numatoms)) = 
01592             entry[j];
01593       }
01594       
01595       /* y */
01596       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01597       sscanf(buffer,"%s %lf %lf %lf %lf %lf",&word[0][0], &entry[0],
01598           &entry[1],&entry[2], &entry[3],&entry[4]);
01599       
01600       /* store 'em */
01601       for ( j = 0; j < remaining_columns; ++j)
01602       {
01603         *(data->normal_modes+(3*k+1)+((i*5+j)*3*data->numatoms)) = 
01604             entry[j];
01605       }
01606       /* z */
01607       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01608       sscanf(buffer,"%s %lf %lf %lf %lf %lf",&word[0][0], &entry[0],
01609           &entry[1], &entry[2], &entry[3],&entry[4]);
01610       
01611       /* store 'em */
01612       for ( j = 0; j < remaining_columns; ++j)
01613       {
01614         *(data->normal_modes+(3*k+2)+((i*5+j)*3*data->numatoms)) = 
01615             entry[j];
01616       }
01617     }
01618   }
01619 
01620   /* release memory that is not needed any more */
01621   free(item);
01622 
01623   /* print brief message */
01624   printf("gamessplugin> Successfully scanned normal modes \n");
01625 
01626   return TRUE;
01627 }
01628 
01629 
01630 
01631 /***********************************************************
01632  *
01633  * this function reads in the cartesian hessian matrix 
01634  *
01635  * *********************************************************/
01636 int get_cart_hessian(void *mydata)
01637 {
01638 
01639   gamessdata *data = (gamessdata *)mydata;
01640   char word[4][BUFSIZ];
01641   char buffer[BUFSIZ];
01642   char dummy; 
01643   unsigned int i,j,k;
01644   float entry[6]; 
01645 
01646   /* intitialize arrays */
01647   buffer[0] = '\0';
01648   memset(entry, 0, sizeof(entry));
01649   for ( i = 0; i < 4; ++i) word[i][0] = '\0';
01650 
01651 
01652   /* at this point we need to rewind the file, since
01653    * in case that there is no internal Hessian stuff the
01654    * previous call to get_int_coords scanned the file
01655    * until EOF */
01656   rewind(data->file);
01657 
01658 
01659   /* look for CARTESIAN FORCE CONSTANT MATRIX */
01660   do 
01661   {
01662     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01663     sscanf(buffer,"%s %s %s %s",&word[0][0],&word[1][0],
01664         &word[2][0],&word[3][0]);
01665 
01666   } while(strcmp(&word[0][0],"CARTESIAN") || 
01667           strcmp(&word[1][0],"FORCE") ||
01668           strcmp(&word[2][0],"CONSTANT") ||
01669           strcmp(&word[3][0],"MATRIX"));
01670 
01671 
01672   /* skip next 5 lines */
01673   for ( i=0; i<5; ++i) eatline(data->file);
01674 
01675 
01676   /* reserve memory for array; 
01677    * NOTE: this is a lower triangular matrix, but for now
01678    * we save it in an square matrix of dim(3Nx3N) to 
01679    * facilitate element access */
01680   data->carthessian = 
01681     (double *)calloc((data->numatoms*3)*(data->numatoms*3),
01682                      sizeof(double));
01683 
01684   
01685   /* make sure memory was allocated properly */
01686   if (data->carthessian == NULL) 
01687   {
01688     PRINTERR;
01689     return FALSE;
01690   }
01691 
01692 
01693   /* start scanning; the cartesian hessian matrix is a lower
01694    * triangular matrix, organized in rows of 6 */
01695 
01696   /* read blocks with complete rows of 6 */
01697   for ( i = 0; i < (int)(data->numatoms/2) ; ++i) 
01698   {
01699     for ( j = 0; j < (data->numatoms*3)-(i*6); ++j) 
01700     {
01701       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01702  
01703       if ( j%3 == 0 ) 
01704       {
01705         sscanf(buffer,"%s %s %c %f %f %f %f %f %f",
01706             &word[0][0],&word[1][0],&dummy,&entry[0],&entry[1],
01707             &entry[2],&entry[3],&entry[4],&entry[5]);
01708       }
01709       else 
01710       {
01711         sscanf(buffer,"%1s %f %f %f %f %f %f",
01712           &dummy,&entry[0],&entry[1],&entry[2],&entry[3],&entry[4],
01713           &entry[5]);
01714       }
01715 
01716 
01717       /* save entries (lower triangular matrix) in a 
01718        * square matrix */
01719       for ( k = 0; k <= ( j<5 ? j : 5 ) ; ++k) {
01720         *(data->carthessian+((j+(i*6))*3*data->numatoms)+
01721             (k+(i*6))) = entry[k];
01722       }
01723     }
01724 
01725 
01726     /* skip the three line separating the matrix entries */
01727     eatline(data->file);
01728     eatline(data->file);
01729     eatline(data->file);
01730     eatline(data->file);
01731   }
01732 
01733 
01734 
01735   /* short message */
01736   printf("gamessplugin> Scanned Hessian in CARTESIAN coordinates\n");
01737 
01738   return TRUE;
01739 }
01740   
01741   
01742   
01743 /***********************************************************
01744  *
01745  * this function reads in the hessian in internal coordinates
01746  * as well as the internal coordinates 
01747  *
01748  * *********************************************************/
01749 int get_int_coords(void *mydata)
01750 {
01751 
01752   gamessdata *data = (gamessdata *)mydata;
01753   char word[5][BUFSIZ];
01754   char buffer[BUFSIZ];
01755   long position;
01756   int first, second, third, fourth;
01757   double value;
01758   double hess[5];
01759   unsigned int i = 0, j = 0, k = 0, l = 0;
01760   int n, dummy, remaining_blocks;
01761 
01762 
01763   /* initialize arrays */
01764   buffer[0] = '\0';
01765   memset(hess, 0, sizeof(hess));
01766   for ( i = 0; i < 5; ++i) word[i][0] = '\0';
01767 
01768 
01769   /* initialize counters */
01770   data->nintcoords = 0;
01771   data->nbonds = 0;
01772   data->nangles = 0;
01773   data->ndiheds = 0;
01774   data->nimprops = 0;
01775 
01776 
01777   /* look for list of INTERNAL COORDINATES */
01778   do 
01779   {
01780     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01781     sscanf(buffer,"%s %s ",&word[0][0],&word[1][0]);
01782 
01783   } while(strcmp(&word[0][0],"INTERNAL") || 
01784           strcmp(&word[1][0],"COORDINATES"));
01785 
01786   
01787   /* skip next 5 lines */
01788   for ( i = 0; i < 5; ++i) eatline(data->file);
01789 
01790 
01791   /* remember current position so we can jump back */
01792   position = ftell(data->file);
01793 
01794 
01795   /* scan the next line */
01796   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01797   n = sscanf(buffer,"%s %s", &word[0][0], &word[1][0]); 
01798  
01799 
01800   /* read line by line */
01801   while ( n != -1) 
01802   {
01803     /* start counting the number of internal coordinates */
01804     data->nintcoords++;
01805 
01806 
01807     /* count the number of bonds, angles, dihedrals */
01808     if (!strcmp(&word[1][0],"STRETCH")) 
01809     {
01810       data->nbonds++;
01811     }
01812     else if (!strcmp(&word[1][0],"BEND")) 
01813     {
01814       data->nangles++;
01815     }
01816     else if (!strcmp(&word[1][0],"TORSION")) 
01817     {
01818       data->ndiheds++;
01819     }
01820     else if (!strcmp(&word[1][0],"PLA.BEND")) 
01821     {
01822       data->nimprops++;
01823     }
01824 
01825             
01826     /* scan next line */
01827     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01828     n = sscanf(buffer,"%s %s", &word[0][0], &word[1][0]); 
01829   }
01830 
01831   /* now that we know the number of bonds, angles, etc.
01832    * we can read and store the internal coordinates */
01833   fseek(data->file,position,SEEK_SET);
01834 
01835 
01836   /* reserve memory for the arrays storing the internal
01837    * coordinates and their values */
01838   data->bonds = (int *)calloc(2*data->nbonds,sizeof(int));
01839   data->angles = (int *)calloc(3*data->nangles,sizeof(int));
01840   data->dihedrals = (int *)calloc(4*data->ndiheds,sizeof(int));
01841   data->impropers = (int *)calloc(4*data->nimprops,sizeof(int));
01842   data->internal_coordinates = (double *)calloc(data->nintcoords,
01843         sizeof(double));
01844 
01845 
01846   /* check if we have sufficient memory available */
01847   if ( (data->bonds == NULL) || 
01848        (data->angles == NULL) ||
01849        (data->dihedrals == NULL) || 
01850        (data->internal_coordinates == NULL)) 
01851   {
01852     PRINTERR; 
01853     return FALSE;
01854   }
01855 
01856 
01857   /* now start going through the internal coordinates
01858    * and save them in the appropriate arrays; here
01859    * I drop all safety check since we went through
01860    * this part of the file already once and should
01861    * be good */
01862  
01863   /* scan the STRETCHES */
01864   for ( i = 0; i < data->nbonds; ++i) 
01865   {
01866     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01867     sscanf(buffer,"%s %s %d %d %lf", &word[0][0], &word[1][0], 
01868         &first, &second, &value);
01869 
01870     /* save 'em */
01871     *(data->bonds+2*i) = first;
01872     *(data->bonds+2*i+1) = second;
01873     *(data->internal_coordinates+i) = value;
01874   }
01875 
01876 
01877   /* scan the BENDS */
01878   for ( j = 0; j < data->nangles; ++j) 
01879   {
01880     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01881     sscanf(buffer,"%s %s %d %d %d %lf", &word[0][0], &word[1][0], 
01882         &first, &second, &third, &value);
01883 
01884     /* save 'em */
01885     *(data->angles+3*j) = first;
01886     *(data->angles+3*j+1) = second;
01887     *(data->angles+3*j+2) = third;
01888     *(data->internal_coordinates+i+j) = value;
01889   }
01890 
01891 
01892   /* scan the TORSIONS */
01893   for ( k = 0; k < data->ndiheds; ++k) 
01894   {
01895     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01896     sscanf(buffer,"%s %s %d %d %d %d %lf", &word[0][0], &word[1][0],
01897         &first, &second, &third, &fourth, &value);
01898 
01899     /* save 'em */
01900     *(data->dihedrals+4*k) = first;
01901     *(data->dihedrals+4*k+1) = second;
01902     *(data->dihedrals+4*k+2) = third;
01903     *(data->dihedrals+4*k+3) = fourth;
01904     *(data->internal_coordinates+i+j+k) = value;
01905   }
01906 
01907 
01908   /* scan the IMPROPERS */
01909   for ( l = 0; l < data->nimprops; ++l) 
01910   {
01911     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01912     sscanf(buffer,"%s %s %d %d %d %d %lf", &word[0][0], &word[1][0],
01913         &first, &second, &third, &fourth, &value);
01914 
01915     /* save 'em */
01916     *(data->impropers+4*l) = first;
01917     *(data->impropers+4*l+1) = second;
01918     *(data->impropers+4*l+2) = third;
01919     *(data->impropers+4*l+3) = fourth;
01920     *(data->internal_coordinates+i+j+k+l) = value;
01921   }
01922 
01923 
01924   /* short message */
01925   printf("gamessplugin> Scanned %d INTERNAL coordinates \n",
01926       data->nintcoords);
01927   printf("gamessplugin>    %d BONDS \n",data->nbonds);
01928   printf("gamessplugin>    %d ANGLES \n",data->nangles);
01929   printf("gamessplugin>    %d DIHEDRALS \n",data->ndiheds);
01930   printf("gamessplugin>    %d IMPROPERS \n",data->nimprops);
01931 
01932 
01933   /* next read in the hessian in internal coordinates;
01934    * we would expect the matrix immediately after the
01935    * internal coordinates in the output files;
01936    * we check this first */
01937   eatline(data->file);
01938 
01939 
01940   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01941   sscanf(buffer,"%s %s %s %s %s", &word[0][0], &word[1][0], 
01942       &word[2][0], &word[3][0], &word[4][0]);
01943 
01944   if ( strcmp(&word[0][0],"HESSIAN") || 
01945        strcmp(&word[1][0],"MATRIX") ||
01946        strcmp(&word[3][0],"INTERNAL") || 
01947        strcmp(&word[4][0],"COORDINATES")) 
01948   {
01949     /* apparently we are out of luck - no Hessian in internal
01950      * coordinates -- GOOD BYE :) */
01951     return FALSE;
01952   }
01953  
01954 
01955   /* skip to the hessian arrays */
01956   while ( sscanf(buffer,"%d %lf %lf %lf %lf %lf", 
01957                  &dummy, &hess[0], &hess[1], &hess[2], 
01958                  &hess[3], &hess[4]) != 6 ) 
01959   {
01960     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01961   }
01962 
01963   
01964   /* reserve memory for inthessian array */
01965   data->inthessian = 
01966     (double *)calloc((data->nintcoords)*(data->nintcoords),
01967                      sizeof(double));
01968 
01969 
01970   /* make sure memory was allocated properly */
01971   if (data->inthessian == NULL)  
01972   {
01973     PRINTERR;
01974     return FALSE;
01975   }
01976 
01977 
01978   /* start scanning; GAMESS organized the output of the
01979    * internal HESSIAN in rows of 5 */
01980 
01981   /* read blocks with complete rows of 5 */
01982   for ( i = 0; i < (int)(data->nintcoords/5); ++i) 
01983   {
01984     for ( j = 0; j < data->nintcoords; ++j) 
01985     {
01986       sscanf(buffer,"%d %lf %lf %lf %lf %lf", &dummy, &hess[0], 
01987               &hess[1], &hess[2], &hess[3], &hess[4]);
01988 
01989       /* save entries */
01990       for ( k = 0; k < 5; ++k) 
01991       { 
01992         *(data->inthessian+(j*data->nintcoords)+(i*5)+k) = hess[k];
01993       }
01994 
01995       /* next line */
01996       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
01997     }
01998 
01999     /* skip the two lines separating the matrix entries 
02000      * and scan next line */
02001     eatline(data->file);
02002     eatline(data->file);
02003 
02004     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02005   }
02006 
02007   
02008   /* read the remaining block with less then 5 rows
02009    * if present */
02010   remaining_blocks = data->nintcoords%5;
02011   
02012   if ( remaining_blocks != 0 ) 
02013   {
02014     for ( j = 0; j < data->nintcoords; ++j) 
02015     {
02016       sscanf(buffer,"%d %lf %lf %lf %lf %lf", &dummy, &hess[0], 
02017               &hess[1], &hess[2], &hess[3], &hess[4]);
02018 
02019       for ( k = 0; k < remaining_blocks; ++k) 
02020       { 
02021         *(data->inthessian+(j*data->nintcoords)+(i*5)+k) = hess[k];
02022       }
02023 
02024       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02025     }
02026   }
02027 
02028 
02029   /* short message */
02030   printf("gamessplugin> Scanned Hessian in INTERNAL coordinates\n");
02031 
02032 
02033 
02034   /* finally, dump the diagonal elements of the hessian into the
02035    * force constant arrays, after converting the units 
02036    * appropriately;
02037    * BONDS are in HARTREE/BOHR**2
02038    * ANGLES,DIHEDRALS,IMPROPERS are in HARTREE/RADIAN**2 */
02039 
02040   
02041   /* alocate dynamic arrays */
02042   data->bond_force_const = 
02043     (double *)calloc(data->nbonds,sizeof(double));
02044  
02045   if ( data->bond_force_const == NULL ) 
02046   {
02047     PRINTERR;
02048     return FALSE;
02049   }
02050 
02051 
02052   data->angle_force_const =
02053     (double *)calloc(data->nangles,sizeof(double));
02054 
02055   if ( data->angle_force_const == NULL ) 
02056   {
02057     PRINTERR;
02058     return FALSE;
02059   }
02060 
02061 
02062   data->dihedral_force_const =
02063     (double *)calloc(data->ndiheds,sizeof(double));
02064 
02065   if ( data->dihedral_force_const == NULL ) 
02066   {
02067     PRINTERR;
02068     return FALSE;
02069   }
02070 
02071 
02072   data->improper_force_const =
02073     (double *)calloc(data->nimprops,sizeof(double));
02074 
02075   if ( data->improper_force_const == NULL ) 
02076   {
02077     PRINTERR;
02078     return FALSE;
02079   }
02080 
02081 
02082   /* scan the bonds */
02083   for ( i = 0; i < data->nbonds; ++i) 
02084   {
02085     *(data->bond_force_const + i) = 
02086       *(data->inthessian+(i*data->nintcoords)+i) 
02087       * HARTREE_TO_KCAL / BOHR_TO_ANGS / BOHR_TO_ANGS;
02088 
02089     printf("%3d (BOND) %2d - %2d : %lf (CHARMM) %lf \n",i, 
02090         *(data->bonds+2*i), *(data->bonds+2*i+1),
02091         *(data->bond_force_const +i),
02092         *(data->bond_force_const +i)*0.5); 
02093   }
02094   
02095 
02096   /* scan the angles */
02097   for ( j = i; j < i+(data->nangles); ++j) 
02098   {
02099     *(data->angle_force_const + (j-i)) = 
02100       *(data->inthessian+(j*data->nintcoords)+j) 
02101       * HARTREE_TO_KCAL;
02102     
02103      printf("%3d (ANGLE) %2d - %2d - %2d : %lf (CHARMM) %lf \n",j,
02104          *(data->angles+3*(j-i)), *(data->angles+3*(j-i)+1), 
02105          *(data->angles+3*(j-i)+2), 
02106          *(data->angle_force_const + (j-i)),
02107          *(data->angle_force_const + (j-i))*0.5);
02108   }
02109 
02110 
02111   /* scan the dihedrals */
02112   for ( k = j; k < j+(data->ndiheds); ++k) 
02113   {
02114     *(data->dihedral_force_const + (k-j)) = 
02115       *(data->inthessian+(k*data->nintcoords)+k)
02116       * HARTREE_TO_KCAL;
02117     
02118      printf("%3d (DIHEDRAL) %2d - %2d - %2d - %2d : %lf \n",k,
02119          *(data->dihedrals+4*(k-j)), *(data->dihedrals+4*(k-j)+1),
02120          *(data->dihedrals+4*(k-j)+2), *(data->dihedrals+4*(k-j)+3),
02121          *(data->dihedral_force_const + (k-j))); 
02122   }
02123 
02124 
02125   /* scan the impropers */
02126   for ( l = k; l < k+(data->nimprops); ++l) 
02127   {
02128     *(data->improper_force_const + (l-k)) = 
02129       *(data->inthessian+(l*data->nintcoords)+l)
02130       * HARTREE_TO_KCAL;
02131     
02132    printf("%3d (IMPROPERS) %2d - %2d - %2d - %2d : %lf \n",l,
02133       *(data->impropers+4*(l-k)), *(data->impropers+4*(l-k)+1),
02134       *(data->impropers+4*(l-k)+2), *(data->impropers+4*(l-k)+3),
02135       *(data->improper_force_const + (l-k)));
02136   }
02137 
02138 
02139   /* DONE */
02140   return TRUE;
02141 }
02142 
02143 
02144 
02145 /*******************************************************
02146  *
02147  * this function reads in the guess options
02148  *
02149  * ******************************************************/
02150 int get_guess(void *mydata)
02151 {
02152   gamessdata *data = (gamessdata *)mydata;
02153   char word[2][BUFSIZ];
02154   char buffer[BUFSIZ];
02155   unsigned int i = 0;
02156 
02157   
02158   /* rewind the file
02159    * TODO: check if this is neccessary at this point */
02160   rewind(data->file);
02161 
02162 
02163   /* initialize buffers */
02164   buffer[0] = '\0';
02165   for ( i = 0; i < 2; ++i) word[i][0] = '\0';
02166 
02167 
02168   /* parse for GUESS field */
02169   do
02170   {
02171     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02172     sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
02173 
02174   } while(strcmp(&word[0][0],"GUESS") || 
02175           strcmp(&word[1][0],"OPTIONS"));
02176 
02177 
02178   /* next line contains all we need */
02179   eatline(data->file);
02180   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02181   sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
02182 
02183   /* store it */
02184   strncpy(data->guess,(&word[1][0])+1,sizeof(data->guess));
02185 
02186   
02187   /* short info */
02188   printf("gamessplugin> Run was performed with GUESS = %s \n",
02189           data->guess);
02190 
02191   return TRUE;
02192 }
02193 
02194 
02195 
02196 /*******************************************************
02197  *
02198  * this function reads in the basis set data 
02199  *
02200  * ******************************************************/
02201 int get_basis(void *mydata)
02202 {
02203 
02204   gamessdata *data = (gamessdata *)mydata;
02205   float *basis;
02206   int *basis_counter;
02207   int *atomic_shells;
02208   int *shell_primitives;
02209   char *orbital_symmetry;
02210   char buffer[BUFSIZ];
02211   char word[3][BUFSIZ];
02212   unsigned int i = 0; 
02213   int counter = 0, oldcounter = 0, nat = 0;
02214 
02215   
02216   /* initialize buffers */
02217   buffer[0] = '\0';
02218   for ( i = 0; i < 3; ++i ) word[i][0] = '\0';
02219 
02220 
02221   /* reserve space for pointer to array containing basis
02222    * info, i.e. contraction coeficients and expansion 
02223    * coefficients; need 2 entries per basis function, i.e.
02224    * exponent and contraction coefficient; also,
02225    * allocate space for the basis_counter (i.e. # of
02226    * basis functions per atoms as well as the array
02227    * holding the orbital symmetry information per primitive
02228    * Gaussian
02229    * Finally, initialize the arrays holding the number of 
02230    * shells per atom and the number of primitives per shell*/
02231   basis = (float *)calloc(2*MAXBASISFUNCTIONS,sizeof(float));
02232 
02233   /* make sure memory was allocated properly */
02234   if (basis == NULL) 
02235   {
02236     PRINTERR;
02237     return MOLFILE_ERROR;
02238   }
02239 
02240 
02241   basis_counter = (int *)calloc(MAXQMATOMS,sizeof(int));
02242 
02243   /* make sure memory was allocated properly */
02244   if (basis_counter == NULL) 
02245   {
02246     PRINTERR;       
02247     return MOLFILE_ERROR;
02248   }
02249 
02250 
02251   orbital_symmetry = (char *)calloc(MAXBASISFUNCTIONS,
02252                      sizeof(char));
02253   
02254   /* make sure memory was allocated properly */
02255   if (orbital_symmetry == NULL) 
02256   {
02257     PRINTERR; 
02258     return MOLFILE_ERROR;
02259   }
02260 
02261   atomic_shells = (int *)calloc(MAXBASISFUNCTIONS, sizeof(int));
02262 
02263   /* make sure memory was allocated properly */
02264   if (atomic_shells == NULL) 
02265   {
02266     PRINTERR; 
02267     return MOLFILE_ERROR;
02268   }
02269 
02270 
02271   shell_primitives = (int *)calloc(MAXBASISFUNCTIONS, sizeof(int));
02272 
02273   /* make sure memory was allocated properly */
02274   if (shell_primitives == NULL) 
02275   {
02276     PRINTERR;       
02277     return MOLFILE_ERROR;
02278   }
02279 
02280 
02281   /* store pointers in struct gamessdata */
02282   data->basis = basis;
02283   data->basis_counter = basis_counter;
02284   data->orbital_symmetry = orbital_symmetry;
02285   data->atomic_shells = atomic_shells;
02286   data->shell_primitives = shell_primitives;
02287 
02288   /* next parse through output file and look for the 
02289    * atomic basis set, i.e.
02290    *
02291    * ATOMIC BASIS SET
02292    *
02293    */
02294 
02295   rewind(data->file);
02296  
02297   /* initialize the per-atom basis function counter */
02298   oldcounter = 0;
02299   counter = 0;
02300 
02301   /* start reading the basis function field */
02302   do
02303   {
02304     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02305     sscanf(buffer,"%s %s %s",&word[0][0],&word[1][0],&word[2][0]);
02306 
02307   } while(strcmp(&word[0][0],"ATOMIC") || 
02308           strcmp(&word[1][0],"BASIS") || 
02309           strcmp(&word[2][0],"SET"));
02310 
02311 
02312   /* skip the next 8 lines */
02313   for(i=0; i<7; i++)
02314   {
02315     eatline(data->file);
02316   }
02317 
02318 
02319   /* the number of atoms determines how often we have
02320    * to loop through the basis function array */
02321   nat = data->numatoms;
02322  
02323 
02324   /* now loop through the basis function section of the
02325    * output file and read in the exponents/coefficients */
02326   for(i=0; i<nat; i++)
02327   {
02328     /* here I go trough the basis set information on a 
02329      * per atom basis and put all the exps and coefficients
02330      * in the right place */
02331     counter = atomic_basis(oldcounter, data, basis, 
02332          orbital_symmetry, atomic_shells,shell_primitives); 
02333 
02334 
02335     /* if atomic_basis() returns -1 we need to bomb
02336      * out */
02337     if ( counter == -1 ) return FALSE;
02338 
02339 
02340     /* store number of basis-functions in array
02341     * basis_counter */
02342     *basis_counter = counter;
02343 
02344 
02345     /* increase pointer to next entry */
02346     basis_counter++;
02347 
02348 
02349     /* update the pointer for the basis arrays */ 
02350     oldcounter += counter;
02351 
02352 
02353     /* increase atomic_shell pointer to hold value for
02354     * next atom */
02355     atomic_shells++;
02356   } 
02357 
02358 
02359   /* store the total number of basis functions */
02360   data->num_basis_funcs = oldcounter;
02361 
02362 
02363   /* short info */ 
02364   printf("gamessplugin> Parsed %d uncontracted basis functions. \n",
02365       data->num_basis_funcs);
02366 
02367   return TRUE;
02368 }
02369 
02370 
02371 
02372 /*******************************************************
02373  *
02374  * function renormalizing basis set coefficients of
02375  * primitives
02376  *
02377  *******************************************************/
02378 float renorm_coefficient(float coefficient, float exponent, 
02379         char orb)
02380 {
02381   /* normalization for S shells */
02382   if ( orb == 'S' )
02383   {
02384     return pow(exponent,1.5) *  pow((8/pow(MY_PI,3)),0.5)
02385       * coefficient;
02386   }
02387 
02388   /* normalization for P shells */
02389   else if ( orb == 'P' )
02390   {
02391     return pow(exponent,2.5) * pow((128/pow(MY_PI,3)),0.5) 
02392       * coefficient;
02393   }
02394 
02395   /* TODO: the renormalization factor for D and F shells
02396    * are taken from MOLDEN; check them! */
02397 
02398   /* normalization for D shells */
02399   else if ( orb == 'D' )
02400   {
02401     return pow(exponent,3.5) * pow((2048/9/pow(MY_PI,3)),0.5)
02402         * coefficient;
02403   }
02404 
02405   /* normalization for F shells */
02406   else if ( orb == 'F' )
02407   {
02408     return pow(exponent,4.5) * 1.875 * pow((512/pow(MY_PI,3)),0.5)
02409         * coefficient;
02410   }
02411 
02412 
02413   /* return 0 otherwise */
02414   return 0;
02415 }
02416 
02417 
02418 
02419 /******************************************************
02420  *
02421  * this function scans a single line in the basis set
02422  * data section 
02423  *
02424  * *****************************************************/
02425 int atomic_basis(int oldcounter, void *mydata, float *basis, 
02426              char *orbital_symmetry, int *atomic_shells, 
02427              int *shell_primitives)
02428 {
02429   gamessdata *data = (gamessdata *)mydata;
02430   char dummy[BUFSIZ];
02431   char buffer[BUFSIZ];
02432   char orbsym;
02433   float exponent = 0.0; 
02434   float contract_c1 = 0.0, contract_c2 = 0.0;
02435   int counter, success;
02436   static int prim_count = -1;
02437   int prev_shell = 0;
02438   int shell;
02439 
02440 
02441   /* initialize arrays */
02442   dummy[0] = '\0';
02443   buffer[0] = '\0';
02444 
02445 
02446   /* initialize basis function counter for current atom */
02447   counter = oldcounter;
02448 
02449 
02450   /* skip one line */
02451   eatline(data->file);
02452 
02453 
02454   /* loop through basis set info for next atom */
02455   do
02456   {
02457     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02458     success = sscanf(buffer,"%d %c %s %f %f %f", &shell, \
02459                      &orbsym, dummy, \
02460                      &exponent, &contract_c1, &contract_c2); 
02461 
02462     
02463     /* make sure we have eiter S, L, P, or D shells;
02464      * otherwise we bomb out;
02465      * TODO: Add support for F SHELLS */
02466     if ( (success == 5  || success == 6 ) && 
02467          (orbsym != 'S' && orbsym != 'L' && orbsym != 'P' && 
02468           orbsym != 'D' && orbsym != 'F' ))
02469     {
02470       printf("gamessplugin> WARNING ... %c shells are not supported \n", orbsym);
02471       return -1;
02472     }
02473 
02474 
02475     /* when this function is called prev_shell is
02476      * initialized to zero;
02477      * Next we compare it to the shell number just read in;
02478      * in case they are different we increase atomic_shell
02479      * by one and then update prev_shell with the new shell
02480      * value */
02481    if ( prev_shell != shell && success > 0 )
02482     {
02483       prim_count++;
02484       (*atomic_shells)++;
02485       prev_shell = shell;
02486     }
02487    
02488 
02489     /* store in basis array and increase the counter */ 
02490     switch(success)
02491     {
02492       case(5):
02493         {
02494           /* store exponent */
02495           *(basis+(2*counter)) = exponent;
02496 
02497 
02498           /* renormalize and store coefficient */
02499           *(basis+(2*counter+1)) = 
02500               renorm_coefficient(contract_c1,exponent,orbsym);
02501 
02502 
02503           /* store orbital symmetry */
02504           *(orbital_symmetry+counter) = orbsym;
02505 
02506 
02507           /* increase counter */
02508           counter++;
02509 
02510 
02511           /* increase counter for number of primitives
02512            * for current shell */
02513           (*(shell_primitives+prim_count))++;
02514 
02515           break;
02516         }
02517       case(6):
02518         { 
02519           /* in the case of two contraction
02520            * coefficients we expect "L" as orbital 
02521            * symmetry, meaning that the first coefficient
02522            * has S and the second P symmetry. Otherwise
02523            * print a warning */
02524           if ( orbsym != 'L' ) 
02525           {
02526             printf("gamessplugin>\n");
02527             printf("gamessplugin> WARNING ... Non SP-Shell %c", 
02528                 orbsym);
02529             printf(" interpreted as SP-Shell\n");
02530             printf("gamessplugin>\n");
02531           }
02532 
02533 
02534           /* line has two coefficient pairs,
02535            * store the first one */
02536           *(basis+(2*counter)) = exponent;
02537 
02538           
02539           /* renormalize and store coefficient */
02540           *(basis+(2*counter+1)) = 
02541               renorm_coefficient(contract_c1,exponent,'S');
02542 
02543 
02544           /* the first coefficient has S symmetry */
02545           *(orbital_symmetry+counter) = 'S';
02546 
02547 
02548           /* increase counter */
02549           counter++;
02550 
02551 
02552           /* increase counter for number of primitives
02553            * for current shell */
02554           (*(shell_primitives+prim_count))++;
02555 
02556           
02557           /* same procedure for the second pair */
02558           *(basis+(2*counter)) = exponent;
02559 
02560 
02561           /* renormalize and store coefficient */
02562           *(basis+(2*counter+1)) = 
02563               renorm_coefficient(contract_c2,exponent,'P');
02564 
02565 
02566           /* the second coefficient has P symmetry */
02567           *(orbital_symmetry+counter) = 'P';
02568 
02569           counter++;
02570           (*(shell_primitives+prim_count))++;
02571 
02572           break;
02573         }
02574        case(-1):
02575         {
02576           break; 
02577         }
02578        case(0):
02579         {
02580           break;
02581         }
02582        case(3):
02583         {
02584           break; 
02585         } 
02586        default:    /* this should never happen */
02587         {
02588         return MOLFILE_ERROR; 
02589         break;
02590         }
02591     }
02592   }  while((success!=0) && (success!=3));
02593 
02594 
02595   /* return only the counter difference */
02596   return (counter - oldcounter);
02597 }
02598 
02599 
02600 /********************************************************
02601  *
02602  * this function reads the number of A/B orbitals 
02603  *
02604  ********************************************************/
02605 int get_num_orbitals(void *mydata)
02606 {
02607 
02608   gamessdata *data = (gamessdata *)mydata; 
02609   char buffer[BUFSIZ];
02610   char word[7][BUFSIZ];
02611   unsigned int i;
02612 
02613   /* initialize buffers */
02614   buffer[0] = '\0';
02615   for ( i = 0; i < 7; ++i) word[i][0] = '\0';
02616 
02617 
02618   /* we start reading the file from the beginning */
02619   rewind(data->file);
02620 
02621 
02622   /* look for the orbital/charge/... info section */
02623   do
02624   {
02625     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02626     sscanf(buffer,"%s %s %s %s",&word[0][0], &word[1][0],
02627         &word[2][0], &word[3][0]);
02628 
02629   } while(strcmp(&word[0][0],"TOTAL") || 
02630           strcmp(&word[1][0],"NUMBER") || 
02631           strcmp(&word[2][0],"OF")    || 
02632           strcmp(&word[3][0],"BASIS"));
02633 
02634   
02635   /* go ahead reading the info */
02636   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02637   sscanf(buffer,"%s %s %s %s %s %s %s %d", &word[0][0],
02638       &word[1][0], &word[2][0], &word[3][0], &word[4][0],
02639       &word[5][0], &word[6][0], &(data->num_gauss_basis_funcs));
02640 
02641 
02642 
02643   /* read the number of electrons */
02644   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02645   sscanf(buffer,"%s %s %s %s %d", &word[0][0], &word[1][0],
02646       &word[2][0], &word[3][0], &(data->num_electrons));
02647 
02648 
02649 
02650   /* read the charge of the molecule */
02651   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02652   sscanf(buffer,"%s %s %s %s %d", &word[0][0], &word[1][0],
02653       &word[2][0], &word[3][0], &(data->totalcharge));
02654 
02655 
02656 
02657   /* read the multiplicity of the molecule */
02658   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02659   sscanf(buffer,"%s %s %s %d", &word[0][0], &word[1][0],
02660        &word[2][0], &(data->multiplicity));
02661 
02662   
02663   /* read number of A orbitals */
02664   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02665 
02666 
02667   /* note the different number of items per line for A/B orbitals
02668    * due to "(ALPHA)" and "(BETA )" !! */
02669   sscanf(buffer,"%s %s %s %s %s %s %d", &word[0][0], &word[1][0],
02670       &word[2][0], &word[3][0], &word[4][0], &word[5][0],
02671       &(data->num_orbitals_A)); 
02672   
02673   
02674   
02675   /* read number of B orbitals */
02676   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02677   sscanf(buffer,"%s %s %s %s %s %s %s %d", &word[0][0], &word[1][0],
02678       &word[2][0], &word[3][0], &word[4][0], &word[5][0], 
02679       &word[6][0], &(data->num_orbitals_B)); 
02680 
02681 
02682   
02683   /* short message */
02684   printf("gamessplugin> Number of Electrons: %d \n",
02685       data->num_electrons);
02686 
02687   printf("gamessplugin> Charge of Molecule : %d \n",
02688       data->totalcharge);
02689 
02690   printf("gamessplugin> Multiplicity of Wavefunction: %d \n",
02691       data->multiplicity);
02692 
02693   printf("gamessplugin> Number of A / B orbitals: %d / %d \n",\
02694       data->num_orbitals_A, data->num_orbitals_B);
02695 
02696   printf("gamessplugin> Number of gaussian basis functions: %d \n",\
02697       data->num_gauss_basis_funcs);
02698 
02699  
02700   return TRUE;
02701 }
02702 
02703 
02704 /*********************************************************
02705  *
02706  * this function reads the actual wavefunction, which is
02707  * punched at the end of the log file
02708  *
02709  **********************************************************/
02710 int get_wavefunction(void *mydata)
02711 {
02712   gamessdata *data = (gamessdata *)mydata; 
02713   float *wave_function;
02714   float *orbital_energy;
02715   char buffer[BUFSIZ];
02716   char word[5][BUFSIZ];
02717   char dummy1, dummy2, dummy3, dummy4;
02718   int orbital_counter = 0;
02719   unsigned int i = 0, j = 0, num_values = 0;
02720   int length = 0;
02721 
02722 
02723   /* initialize buffers */
02724   buffer[0] = '\0';
02725   for ( i = 0; i < 5; ++i ) word[i][0] = '\0';
02726 
02727   
02728   /* reserve space for arrays storing wavefunction and orbital
02729    * energies 
02730    * For the wavefunction I reserve twice the number of A orbitals
02731    * times MAXBASISFUNCTIONS;
02732    * I should check the gamess sources how much are printed out,
02733    * but this should cover me for now. 
02734    * Accordingly, for the energies I use the number of A orbitals */
02735   wave_function = (float *)calloc(data->num_gauss_basis_funcs * \
02736                   data->num_gauss_basis_funcs,sizeof(float)); 
02737 
02738   /* make sure memory was allocated properly */
02739   if (wave_function == NULL) 
02740   {
02741     PRINTERR;       
02742     return FALSE;
02743   }
02744   
02745   orbital_energy = (float *)calloc(data->num_gauss_basis_funcs, \
02746                       sizeof(float));
02747 
02748   /* make sure memory was allocated properly */
02749   if (orbital_energy == NULL) 
02750   {
02751     PRINTERR; 
02752     return FALSE;
02753   }
02754 
02755   /* store the pointers in gamessdata */
02756   data->wave_function = wave_function;
02757   data->orbital_energy = orbital_energy;
02758 
02759   
02760   /* rewind the file before starting to look for
02761    * the wavefunction */
02762 
02763   rewind(data->file);
02764   
02765   do
02766   {
02767     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02768     length = sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
02769 
02770   } while(strcmp(&word[0][0],"EIGENVECTORS") || length != 1);
02771 
02772   
02773   /* skip the next three lines */
02774   eatline(data->file);
02775   eatline(data->file);
02776   eatline(data->file);
02777 
02778 
02779   /* go ahead */
02780   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02781   num_values = sscanf(buffer,"%s %s %s %s %s",&word[0][0],
02782       &word[1][0],&word[2][0],&word[3][0],&word[4][0]);
02783 
02784 
02785   while(strcmp(&word[0][0],"TOTAL"))
02786   {
02787     /* store the orbital energies in the appropriate arrays 
02788      * read them until we encounter an empty string */
02789     for(i=0; i<num_values; i++)
02790     {
02791       *(orbital_energy+i) = atof(&word[i][0]);
02792       orbital_counter++;
02793     }
02794 
02795     /* increase orbital energy pointer */
02796     orbital_energy = orbital_energy+5;
02797 
02798     /* skip the next line */
02799     eatline(data->file);
02800 
02801     /* now read in the wavefunction */
02802     /* markus: go ahead here, instead of just looping
02803      * over the lines actually store them :) */
02804     for(i=0; i< data->num_gauss_basis_funcs; i++)
02805     {
02806       ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02807       
02808       /* now read in the wavefunction coefficients for 5
02809        * orbitals at a time line by line */
02810       num_values = sscanf(buffer,"%s %s %s %s %s %s %s %s %s", 
02811                  &dummy1,&dummy2,&dummy3,&dummy4,&word[0][0], 
02812                  &word[1][0],&word[2][0],&word[3][0],&word[4][0]);
02813 
02814 
02815       /* each orbital has data->num_gauss_basis_funcs entries, 
02816        * hence we have to use this number as offset when storing 
02817        * them in groups of five */
02818       for(j=0 ; j<num_values-4; j++) {
02819 
02820         *(wave_function+(j*data->num_gauss_basis_funcs)+i) \
02821                 = atof(&word[j][0]);
02822       }
02823     }
02824 
02825     /* move wavefunction pointer to start of next five orbitals */
02826     wave_function = wave_function + 5*data->num_gauss_basis_funcs;
02827 
02828     /* skip next line */
02829     eatline(data->file);
02830     eatline(data->file);
02831 
02832 
02833     /* read next line to allow do/while loop to decide if
02834      * wavefunction data is over */
02835     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
02836     num_values = sscanf(buffer,"%s %s %s %s %s",&word[0][0],
02837         &word[1][0], &word[2][0], &word[3][0], &word[4][0]);
02838   } 
02839 
02840   /* store the number of orbitals read in */
02841   data->orbital_counter = orbital_counter;
02842 
02843   
02844   /* at this point we should have proper wavefunction information
02845    * in our arrays */
02846   data->got_wavefunction = TRUE;
02847 
02848   
02849   /* short message */ 
02850   printf("gamessplugin> Number of orbitals scanned: %d \n",\
02851              data->orbital_counter);
02852 
02853 
02854   return TRUE;
02855 }
02856 
02857 
02858 
02859 /*************************************************************
02860  *
02861  * this subroutine scans all the orbitals to find the HOMO 
02862  *
02863  *************************************************************/
02864 int find_homo(void *mydata) {
02865 
02866   gamessdata *data = (gamessdata *)mydata; 
02867   float *orbital_energy;
02868   int orbital_counter;
02869 
02870   /* initialize the counter pointing to the HOMO */
02871   unsigned int homo_counter = 0;
02872 
02873   /* loop through the orbital energies and find the smallest
02874    * negative value, i.e. HOMO. Actually, for pathological
02875    * systems identifications of the HOMO in this way might
02876    * be flawed, since higher energy orbitals could be occupied
02877    * as well, but for now this should do */
02878   orbital_energy = data->orbital_energy;
02879   orbital_counter = data->orbital_counter;
02880 
02881   while ( *orbital_energy < 0 )
02882   {
02883     orbital_energy++;
02884     homo_counter++;
02885   }
02886 
02887   /* there is probably a lot that can go wrong here;
02888    * let's at least check if the HOMO is the last orbital
02889    * present in which case there is probably something
02890    * fishy going on */
02891   if ( homo_counter == orbital_counter)
02892   {
02893     printf("gamessplugin> WARNING: HOMO is last orbital");
02894   }
02895 
02896   
02897   /* store homo index */
02898   data->homo_index = homo_counter;
02899 
02900   
02901   /* short message */
02902   printf("gamessplugin> Identified orbital #%d (%f au) as HOMO \n",
02903         data->homo_index, 
02904         *(data->orbital_energy+(data->homo_index)-1)); 
02905  
02906 
02907   return TRUE;
02908 }
02909 
02910 
02911 
02912 /**********************************************************
02913  *
02914  * this function generates the computational grid for
02915  * the orbitals; as a proof of concept case we do the
02916  * HOMO first 
02917  *
02918  ***********************************************************/
02919 int orbital_grid_driver(void *mydata)
02920 {
02921   gamessdata *data = (gamessdata *)mydata; 
02922 
02923   /* in order to set up the grid properly, we
02924    * have to know the dimensions of the system.
02925    * Hence let's determine it ! */
02926   if (get_system_dimensions(data) == FALSE) return FALSE;
02927  
02928 
02929   /* finally, we're ready to evaluate the value
02930    * of the orbital at the computational grid
02931    * points */
02932   if (calculate_orbital(data) == FALSE ) return FALSE; 
02933 
02934 
02935   /* at this point we should have proper volumetric metadata/
02936      * data (otherwise it is the fault of generate_orbital_grid)
02937      * and can hence allow VMD to parse the apropriate arrays
02938      * in the metadata/data routines */
02939   data->have_volumetric = 1; 
02940 
02941 
02942   return TRUE;
02943 }
02944 
02945 
02946 /*********************************************************
02947  *
02948  * this function creates the computational grid given the
02949  * system dimensions 
02950  *
02951  **********************************************************/
02952 int calculate_orbital(void *mydata) 
02953 {
02954   gamessdata *data = (gamessdata *)mydata;
02955   float *orbital_grid;
02956   float *xyzdim;
02957   molfile_volumetric_t *vol_metadata;
02958   float *wave_function;
02959   float grid_x = 0.0, grid_y = 0.0, grid_z = 0.0;
02960   int numx, numy, numz, numxy, maxpoints;
02961   unsigned int nx = 0, ny = 0, nz = 0, i = 0;
02962   float *center;
02963   int success[3] = { 0, 0, 0};
02964   float grid_size = 1.0; 
02965   float buffer_region[3] = {3.0, 3.0, 3.0};
02966   int grid_bad[3] = { 1, 1, 1};
02967   float grid_dim[3]; /* gridsize in A */
02968   int shrink_grid_size = 0;
02969   int voxel[3];
02970   int tot_voxel;
02971 
02972   /* request memory for volume metadata */
02973   vol_metadata = (molfile_volumetric_t *)calloc(1, \
02974                 sizeof(molfile_volumetric_t)); 
02975 
02976   /* make sure the call was succesful */
02977   if (vol_metadata == NULL) 
02978   {
02979      PRINTERR;
02980      return FALSE;
02981   }
02982 
02983   /* store pointer to volumetric metadata */
02984   data->vol = vol_metadata;
02985 
02986 
02987   /* retrieve the pointer for the temp arrays */
02988   /* temp_data = data->temporary; */
02989 
02990 
02991   /* retrieve array with # of primitives available
02992    * for each indivual atom of the system */
02993   /* basis_counter = data->basis_counter; */
02994 
02995 
02996   /* retrieve the pointer for the grid dimensions */
02997   xyzdim = data->system_dimensions;
02998 
02999 
03000   /* retrieve pointer for wavefunction */
03001   wave_function = data->wave_function;
03002 
03003 
03004   /* move wavefunction pointer to HOMO */
03005   wave_function += (data->num_gauss_basis_funcs*
03006       (data->homo_index - 1));
03007 
03008 
03009   /* retrieve orbital symmetry of shel primitives */
03010   /* orbital_symmetry = data->orbital_symmetry; */
03011 
03012 
03013   /* retrieve pointer to system center */
03014   center = data->system_center;
03015 
03016 
03017   /* now we scan the surface of the grid and see if there
03018    * are any values > 0.01; if not, we reduce the buffer
03019    * region by 1A and try again */
03020   printf("gamessplugin>\n");
03021   printf("gamessplugin> Optimizing size of orbital grid. \n");
03022  
03023 
03024   /* determine an optimal grid dimension and grid spacing */
03025   while ( grid_bad[0] || grid_bad[1] || grid_bad[2] )
03026   {
03027     /* examine the current grid and shrink it if possible */
03028 
03029     for ( i = 0 ; i < 3 ; ++i)
03030     {
03031       grid_dim[i] = (xyzdim[i+3] - xyzdim[i]); 
03032 
03033       /* pad with a buffer region subject to the constraint
03034        * the grid_dim[i] has an integer number of voxels */
03035         
03036       grid_dim[i] = grid_dim[i] - fmod(grid_dim[i],2*grid_size) 
03037                     + 2.0 * buffer_region[i]; 
03038 
03039       vol_metadata->origin[i] = center[i] - grid_dim[i]/2.0; 
03040     }
03041 
03042     /* make results available as volumetric metadata:
03043      * the {xyz}axis point in the xyz direction with
03044      * lengths determined by the size of the grid in
03045      * each direction;
03046      * the {xyz}size is given by the size of the grid
03047      * plus a buffer region BUFFER_REGION
03048      * in the respective direction divided by the
03049      * GRIDSIZE (i.e. number of voxels) */
03050       
03051     vol_metadata->xaxis[0] = grid_dim[0];
03052     vol_metadata->yaxis[1] = grid_dim[1];
03053     vol_metadata->zaxis[2] = grid_dim[2];
03054     vol_metadata->xsize = (int)(grid_dim[0] / grid_size)+1;
03055     vol_metadata->ysize = (int)(grid_dim[1] / grid_size)+1;
03056     vol_metadata->zsize = (int)(grid_dim[2] / grid_size)+1; 
03057 
03058     /* don't have color information */
03059     vol_metadata->has_color = 0;
03060     
03061     /* default name for data set */
03062     sprintf(vol_metadata->dataname,"wavefunction data"); 
03063 
03064      
03065     /* calculate the number of grid points in each dimension
03066      * as well as the total number of points needed
03067      * in order to dimension the orbital_grid
03068      * array properly */
03069     numx = vol_metadata->xsize;
03070     numy = vol_metadata->ysize;
03071     numz = vol_metadata->zsize;
03072 
03073 
03074     /* scan xy surfaces */
03075     nz = 0;
03076 
03077     if ( !success[0] )
03078     {
03079       for ( nx = 0 ; nx < numx ; ++nx)
03080       {
03081         if ( !success[0] ) 
03082         {
03083           for ( ny = 0 ; ny < numy ; ++ny)
03084           {
03085             /* calculate the xyz coordinate of the current
03086              * grid point */
03087             grid_x = vol_metadata->origin[0] + nx * grid_size;
03088             grid_y = vol_metadata->origin[1] + ny * grid_size;
03089             grid_z = vol_metadata->origin[2] + nz * grid_size;
03090 
03091         
03092             /* calculate the value of the wavefunction of the
03093              * selected orbital at the current grid point */
03094             if ( fabs(orbital_at_grid_xyz(data, wave_function, 
03095                   grid_size, grid_x, grid_y, grid_z)) > 0.01 )
03096             {
03097               success[0] = 1;
03098               break;
03099             }
03100           } 
03101         }
03102       }
03103     } 
03104         
03105     /* scan back side of xy plane */
03106     nz = numz - 1;
03107 
03108     if ( ! success[0] )
03109     {
03110       for ( nx = 0 ; nx < numx ; ++nx)
03111       {
03112         if ( !success[0] ) 
03113         {
03114           for ( ny = 0 ; ny < numy ; ++ny)
03115           {
03116             /* calculate the xyz coordinate of the current
03117             * grid point */
03118             grid_x = vol_metadata->origin[0] + nx * grid_size;
03119             grid_y = vol_metadata->origin[1] + ny * grid_size;
03120             grid_z = vol_metadata->origin[2] + nz * grid_size;
03121           
03122         
03123             /* calculate the value of the wavefunction of the
03124              * selected orbital at the current grid point */
03125             if ( fabs(orbital_at_grid_xyz(data, wave_function, 
03126                   grid_size, grid_x, grid_y, grid_z)) > 0.01 )
03127             {
03128               success[0] = 1;
03129               break;
03130             }
03131           } 
03132         }
03133       }
03134     }
03135 
03136 
03137     /* adjust buffer region in z direction */
03138     if ( success[0] )
03139     {
03140       grid_bad[2] = 0;
03141 
03142     }
03143     else
03144     {
03145       buffer_region[2] -= 0.5;
03146     }
03147 
03148 
03149 
03150     /* scan xz surfaces */
03151     ny = 0;
03152 
03153     if ( !success[1] )
03154     {
03155       for ( nx = 0 ; nx < numx ; ++nx)
03156       {
03157         if ( !success[1] ) 
03158         {
03159           for ( nz = 0 ; nz < numz ; ++nz)
03160           {
03161             /* calculate the xyz coordinate of the current
03162             * grid point */
03163             grid_x = vol_metadata->origin[0] + nx * grid_size;
03164             grid_y = vol_metadata->origin[1] + ny * grid_size;
03165             grid_z = vol_metadata->origin[2] + nz * grid_size;
03166           
03167         
03168             /* calculate the value of the wavefunction of the
03169              * selected orbital at the current grid point */
03170             if ( fabs(orbital_at_grid_xyz(data, wave_function, 
03171                   grid_size, grid_x, grid_y, grid_z)) > 0.01 )
03172             {
03173               success[1] = 1;
03174               break;
03175             }
03176           } 
03177         }
03178       }
03179     }
03180 
03181 
03182     /* scan back side of xz surface */      
03183     ny = numy - 1; 
03184     
03185     if ( !success[1] )
03186     {
03187       for ( nx = 0 ; nx < numx ; ++nx)
03188       {
03189         if ( !success[1] ) 
03190         {
03191           for ( nz = 0 ; nz < numz ; ++nz)
03192           {
03193             /* calculate the xyz coordinate of the current
03194             * grid point */
03195             grid_x = vol_metadata->origin[0] + nx * grid_size;
03196             grid_y = vol_metadata->origin[1] + ny * grid_size;
03197             grid_z = vol_metadata->origin[2] + nz * grid_size;
03198           
03199         
03200             /* calculate the value of the wavefunction of the
03201              * selected orbital at the current grid point */
03202             if ( fabs(orbital_at_grid_xyz(data, wave_function, 
03203                   grid_size, grid_x, grid_y, grid_z)) > 0.01 )
03204             {
03205               success[1] = 1;
03206               break;
03207             }
03208           } 
03209         }
03210       }
03211     }
03212 
03213     /* adjust buffer region in y direction */
03214     if ( success[1] )
03215     {
03216       grid_bad[1] = 0;
03217     }
03218     else
03219     {
03220       buffer_region[1] -= 0.5;
03221     }
03222 
03223 
03224     /* scan yz surfaces */
03225     nx = 0;
03226 
03227     if ( !success[2] )
03228     {
03229       for ( ny = 0 ; ny < numy ; ++ny)
03230       {
03231         if ( !success[2] ) 
03232         {
03233           for ( nz = 0 ; nz < numz ; ++nz)
03234           {
03235             /* calculate the xyz coordinate of the current
03236             * grid point */
03237             grid_x = vol_metadata->origin[0] + nx * grid_size;
03238             grid_y = vol_metadata->origin[1] + ny * grid_size;
03239             grid_z = vol_metadata->origin[2] + nz * grid_size;
03240           
03241         
03242             /* calculate the value of the wavefunction of the
03243              * selected orbital at the current grid point */
03244             if ( fabs(orbital_at_grid_xyz(data, wave_function, 
03245                   grid_size, grid_x, grid_y, grid_z)) > 0.01 )
03246             {
03247               success[2] = 1;
03248               break;
03249             }
03250           } 
03251         }
03252       }
03253     }
03254 
03255 
03256     /* scan back side of yz surface */      
03257     nx = numx - 1; 
03258     
03259     if ( !success[2] )
03260     {
03261       for ( ny = 0 ; ny < numy ; ++ny)
03262       {
03263         if ( !success[2] ) 
03264         {
03265           for ( nz = 0 ; nz < numz ; ++nz)
03266           {
03267             /* calculate the xyz coordinate of the current
03268             * grid point */
03269             grid_x = vol_metadata->origin[0] + nx * grid_size;
03270             grid_y = vol_metadata->origin[1] + ny * grid_size;
03271             grid_z = vol_metadata->origin[2] + nz * grid_size;
03272           
03273         
03274             /* calculate the value of the wavefunction of the
03275              * selected orbital at the current grid point */
03276             if ( fabs(orbital_at_grid_xyz(data, wave_function, 
03277                   grid_size, grid_x, grid_y, grid_z)) > 0.01 )
03278             {
03279               success[2] = 1;
03280               break;
03281             }
03282           } 
03283         }
03284       }
03285     }
03286 
03287     /* adjust buffer region in x direction */
03288     if ( success[2] )
03289     {
03290       grid_bad[0] = 0;
03291     }
03292     else
03293     {
03294       buffer_region[0] -= 0.5;
03295     }
03296 
03297   }
03298 
03299   /* at this point we have optimized the dimensions of
03300    * the grid and we can now chose an optimal low value for
03301    * the grid size depending such that we either have 
03302    * less than MAX_GRIDPOINTS or a value of 0.1 A */
03303   shrink_grid_size = 1;
03304 
03305   while ( shrink_grid_size ) 
03306   {
03307     for ( i = 0 ; i < 3 ; ++i)
03308     {
03309       grid_dim[i] = (xyzdim[i+3] - xyzdim[i]);
03310 
03311       voxel[i] = (int)((grid_dim[i] + 2.0 * buffer_region[i]) /
03312           grid_size);
03313     }
03314 
03315     tot_voxel = voxel[0] * voxel[1] * voxel[2];
03316 
03317 
03318     if (tot_voxel > MAX_GRIDPOINTS)
03319     {
03320       shrink_grid_size = 0;
03321 
03322       /* we need to bump up the gridsize again
03323        * since at this point we've already gone
03324        * beyond MAX_GRIDPOINTS */
03325       grid_size += 0.1;
03326     }
03327     else
03328     {
03329       if ( grid_size > 0.1 )
03330       {
03331         grid_size -= 0.1;
03332       }
03333       else
03334       {
03335         shrink_grid_size = 0;
03336       }
03337     }
03338   }
03339 
03340   for ( i = 0 ; i < 3 ; ++i)
03341   {
03342     /* pad with a buffer region subject to the constraint
03343      * the grid_dim[i] has an integer number of voxels */
03344         
03345     grid_dim[i] = grid_dim[i] - fmod(grid_dim[i],2*grid_size) 
03346                     + 2.0 * buffer_region[i]; 
03347 
03348     vol_metadata->origin[i] = center[i] - grid_dim[i]/2.0; 
03349   }
03350 
03351   /* make results available as volumetric metadata:
03352    * the {xyz}axis point in the xyz direction with
03353    * lengths determined by the size of the grid in
03354    * each direction;
03355    * the {xyz}size is given by the size of the grid
03356    * plus a buffer region BUFFER_REGION
03357    * in the respective direction divided by the
03358    * GRIDSIZE (i.e. number of voxels) */
03359       
03360   vol_metadata->xaxis[0] = grid_dim[0];
03361   vol_metadata->yaxis[1] = grid_dim[1];
03362   vol_metadata->zaxis[2] = grid_dim[2];
03363   vol_metadata->xsize = (int)(grid_dim[0] / grid_size)+1;
03364   vol_metadata->ysize = (int)(grid_dim[1] / grid_size)+1;
03365   vol_metadata->zsize = (int)(grid_dim[2] / grid_size)+1; 
03366 
03367 
03368   /* calculate the number of grid points in each dimension
03369    * as well as the total number of points needed
03370    * in order to dimension the orbital_grid
03371    * array properly */
03372   numx = vol_metadata->xsize;
03373   numy = vol_metadata->ysize;
03374   numz = vol_metadata->zsize;
03375   maxpoints = numx * numy * numz;
03376 
03377 
03378   /* useful shorthand notation needed for storage
03379    * of orbital values in an array */
03380   numxy = numx*numy;
03381 
03382 
03383   /* store number of gridpoints */
03384   data->num_gridpoints = maxpoints;
03385 
03386 
03387   /* now we can reserve the space for the grid array */
03388   orbital_grid = (float *)calloc(maxpoints,sizeof(float));
03389 
03390 
03391   /* make sure we have enough memory */
03392   if (orbital_grid== NULL) 
03393   {
03394     PRINTERR; 
03395     return FALSE;
03396   }
03397 
03398   /* store the pointer to the grid */
03399   data->orbital_grid = orbital_grid;
03400 
03401 
03402   /* let's give the user a warning, since the calculation
03403    * could take a while, otherwise they might think the
03404    * system is borked */
03405   printf("gamessplugin> Calculating orbital grid. \n");
03406   printf("              Please be patient ....... \n");
03407 
03408 
03409   /* now we start one heck of a large loop going through the
03410    * whole grid calculating the value of the orbital at each
03411    * point */
03412 
03413   /* start looping and calculating ........... */
03414   for ( nx = 0 ; nx < numx ; ++nx)
03415   {
03416     for ( ny = 0 ; ny < numy ; ++ny)
03417     {
03418       for ( nz = 0 ; nz < numz ; ++nz)
03419       {
03420 
03421         /* calculate the xyz coordinate of the current
03422          * grid point */
03423         grid_x = vol_metadata->origin[0] + nx * grid_size;
03424         grid_y = vol_metadata->origin[1] + ny * grid_size;
03425         grid_z = vol_metadata->origin[2] + nz * grid_size;
03426 
03427         
03428         /* calculate the value of the wavefunction of the
03429          * selected orbital at the current grid point */
03430         *(orbital_grid + nx + ny*numx + nz*numxy) = 
03431             orbital_at_grid_xyz(data, wave_function, grid_size, 
03432                 grid_x, grid_y, grid_z);
03433       }
03434     } 
03435   }
03436 
03437   /* everything went fine */ 
03438   return TRUE;
03439 }
03440 
03441 
03442 
03443 /*********************************************************
03444  *
03445  * this function provides the system dimensions 
03446  *
03447  *********************************************************/
03448 int get_system_dimensions(void *mydata) {
03449 
03450   gamessdata *data = (gamessdata *)mydata; 
03451   gamess_temp *temp_data;
03452   unsigned int i = 0;
03453 
03454   /* array holding geometric center of system */
03455   float *center;   
03456  
03457   /* array containing system dimensions in the form
03458    * [x_min,y_min,....z_max] */
03459   float *xyzdim;   
03460   
03461   /* request memory for center array */
03462   center = (float *)calloc(3,sizeof(float));
03463 
03464   /* make sure memory could be allocated */
03465   if (center == NULL)
03466   {
03467     PRINTERR;
03468     return FALSE;
03469   }
03470 
03471 
03472   /* request memory for xyzdim array */
03473   xyzdim = (float *)calloc(6,sizeof(float));
03474 
03475   /* make sure the call was succesful */
03476   if (xyzdim == NULL) 
03477   {
03478     PRINTERR;
03479     return FALSE;
03480   }
03481 
03482 
03483   /* retrieve pointer of gamess_temp struct */
03484   temp_data = data->temporary;
03485 
03486   /* store pointer to volumetric metadata */
03487   /* data->vol = vol_meta_data; */
03488 
03489   /* store pointer to center of system */
03490   data->system_center = center;
03491 
03492 
03493   /* determine the origin of the system; this is needed
03494    * to properly initialize the volumetric metadata */
03495   for ( i = 0 ; i != data->numatoms ; ++i) 
03496   {
03497     center[0] = ( center[0] + (temp_data+i)->x ); 
03498     center[1] = ( center[1] + (temp_data+i)->y ); 
03499     center[2] = ( center[2] + (temp_data+i)->z ); 
03500   }
03501 
03502   for ( i = 0 ; i < 3; ++i) 
03503   {
03504     center[i] = center[i] / data->numatoms;
03505   }
03506 
03507 
03508   /* determine the the minimum and maximum {xyz}
03509    * coordintes of the system; having that we
03510    * can dimension the orbital grid */
03511 
03512   /* set initial values of temp values to the coordinates
03513    * of the first atom */
03514   xyzdim[0] = xyzdim[3] = temp_data->x;
03515   xyzdim[1] = xyzdim[4] = temp_data->y;
03516   xyzdim[2] = xyzdim[5] = temp_data->z;  
03517 
03518   /* now loop over the rest of the atoms to check if there's
03519    * something larger/smaller for the maximum and minimum
03520    * respectively */
03521   for( i = 0 ; i != data->numatoms; ++i)
03522   {
03523     if ( (temp_data+i)->x < xyzdim[0] ) 
03524        xyzdim[0] = (temp_data+i)->x;
03525     if ( (temp_data+i)->y < xyzdim[1] )
03526        xyzdim[1] = (temp_data+i)->y;
03527     if ( (temp_data+i)->z < xyzdim[2] ) 
03528        xyzdim[2] = (temp_data+i)->z;
03529     if ( (temp_data+i)->x > xyzdim[3] ) 
03530        xyzdim[3] = (temp_data+i)->x;
03531     if ( (temp_data+i)->y > xyzdim[4] ) 
03532        xyzdim[4] = (temp_data+i)->y;
03533     if ( (temp_data+i)->z > xyzdim[5] )
03534        xyzdim[5] = (temp_data+i)->z;
03535   }
03536 
03537   /* store final results in array */
03538   data->system_dimensions = xyzdim;
03539 
03540   /* done :) */
03541   return TRUE;
03542 }
03543 
03544 
03545 /**********************************************************
03546  *
03547  * this subroutine reads the number of procs and the amount
03548  * of memory requested
03549  *
03550  **********************************************************/
03551 static int get_proc_mem(void *mydata) {
03552 
03553   gamessdata *data = (gamessdata *)mydata;
03554   char word[3][BUFSIZ];
03555   char buffer[BUFSIZ];
03556   unsigned int nproc;
03557   unsigned int i;
03558 
03559 
03560   /* initialize arrays */
03561   buffer[0] = '\0';
03562   for ( i = 0; i < 3; ++i) word[i][0] = '\0';
03563 
03564 
03565   /* first, we need to rewind the file */
03566   rewind(data->file);
03567 
03568   
03569   /* scan for the number of processors */
03570   do 
03571   {
03572     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03573     sscanf(buffer,"%s %d %s",&word[0][0],&nproc,&word[1][0]);
03574 
03575   } while( strcmp(&word[0][0],"Initiating") || 
03576            strcmp(&word[1][0],"compute") );
03577 
03578   
03579   /* store the number of processors */
03580   data->nproc = nproc;
03581 
03582   
03583   /* scan for the amount of memory requested */
03584   do 
03585   {
03586     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03587     sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
03588 
03589   } while( strcmp(&word[0][0],"$SYSTEM") || 
03590            strcmp(&word[1][0],"OPTIONS") );
03591 
03592    
03593   /* skip next line */
03594   eatline(data->file);
03595 
03596 
03597   /* next line contains the amount of memory requested */
03598   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03599   sscanf(buffer,"%s %s %s",&word[0][0],&word[1][0],&word[2][0]);
03600 
03601   /* store it */
03602   strncpy(data->memory,&word[2][0],sizeof(data->memory));
03603 
03604 
03605   /* short message */
03606   printf("gamessplugin> GAMESS used %d compute processes \n",nproc);
03607   printf("gamessplugin> GAMESS used %s words of memory \n",
03608       data->memory);
03609 
03610 
03611   /* done here */
03612   return TRUE;
03613 }
03614 
03615 
03616 
03617 /**********************************************************
03618  *
03619  * this subroutine checks if the provided files is
03620  * actually a GAMESS file;
03621  *
03622  **********************************************************/
03623 static int have_gamess(void *mydata) 
03624 {
03625   gamessdata *data = (gamessdata *)mydata;
03626   char word[3][BUFSIZ];
03627   char buffer[BUFSIZ];
03628   int day, year;
03629   char month[BUFSIZ], rev[BUFSIZ];
03630   unsigned int i = 0;
03631  
03632 
03633   /* initialize arrays */
03634   buffer[0] = '\0';
03635   for ( i = 0; i < 3; ++i ) word[i][0] = '\0';
03636 
03637 
03638   /* check if the file is GAMESS format 
03639    * for now I just read line by line until 
03640    * the word GAMESS appears                */
03641   do
03642   {
03643     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03644     sscanf(buffer,"%s %s %s",&word[0][0],&word[1][0],&word[2][0]);
03645 
03646   } while( strcmp(&word[1][0],"GAMESS") || 
03647            strcmp(&word[2][0],"VERSION") );
03648 
03649 
03650   /* extract the version number if possible; otherwise
03651    * return empty string */
03652   if ( strstr(buffer,"=") != NULL ) 
03653   {
03654     strncpy(data->version_string,strstr(buffer,"=")+2,16); 
03655   }
03656 
03657   
03658   /* determine if we're dealing with pre-"27 JUN 2005"
03659    * version */
03660   sscanf(data->version_string,"%d %s %d %s",&day, month, &year, rev);
03661   
03662   if ( ( year >= 2006 ) ||
03663        ( year == 2005 && !strcmp(month,"JUN") ) ||
03664        ( year == 2005 && !strcmp(month,"NOV") ) ||
03665        ( year == 2005 && !strcmp(month,"DEC") ) )
03666   {
03667     data->version = 2;
03668   }
03669   else
03670   { 
03671     data->version = 1;
03672   }
03673 
03674 
03675   /* short messsage to stdout */
03676   printf("gamessplugin> Detected GAMESS format :)\n");
03677   printf("gamessplugin> GAMESS version = %s \n", 
03678       data->version_string);
03679 
03680   return TRUE;
03681 }
03682 
03683 
03684 
03685 /**********************************************************
03686  *
03687  * this subroutine extracts the GBASIS
03688  *
03689  **********************************************************/
03690 static int get_gbasis(void *mydata) {
03691 
03692   gamessdata *data = (gamessdata *)mydata;
03693   char word[4][BUFSIZ];
03694   char buffer[BUFSIZ];
03695   char diffuse[BUFSIZ];
03696   char polarization[BUFSIZ];
03697   unsigned int i = 0;
03698 
03699 
03700   /* initialize arrays */
03701   buffer[0] = '\0';
03702   diffuse[0] = '\0';
03703   polarization[0] = '\0';
03704   for ( i = 0; i < 4; ++i) word[i][0] = '\0';
03705 
03706 
03707   /* to be safe let's rewind the file */
03708   rewind(data->file);
03709 
03710 
03711   /* start scanning */
03712   do 
03713   {
03714     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03715     sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
03716 
03717   } while((strcmp(&word[0][0],"BASIS")) || 
03718           (strcmp(&word[1][0],"OPTIONS")));
03719 
03720 
03721   /* skip next line */
03722   eatline(data->file);
03723 
03724 
03725   /* the first string in the current line contains the
03726    * GBASIS used; copy it over into the gbasis variable
03727    * of gamessdata */
03728   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03729   sscanf(buffer,"%s %s %s",&word[0][0],&word[1][0],&word[2][0]);
03730  
03731   strncpy(data->gbasis,(&word[0][0])+7,sizeof(data->gbasis));
03732 
03733   printf("gamessplugin> Run was performed with GBASIS = %s \n",
03734           data->gbasis);
03735 
03736 
03737   /* in case we're using a pople style basis set, i.e. 
03738    * GBASIS=N311,N31,N21 or STO we also scan for the number 
03739    * of gaussians, as well as p,d,f and diffuse functions
03740    * and use this info to assemble a "basis set string" */
03741   if ( !strncmp(data->gbasis,"N311",sizeof(data->gbasis)) ||
03742        !strncmp(data->gbasis,"N31",sizeof(data->gbasis)) ||
03743        !strncmp(data->gbasis,"N21",sizeof(data->gbasis)) ||
03744        !strncmp(data->gbasis,"STO",sizeof(data->gbasis)) ) 
03745   {
03746     /* word[2] read previously should still contain the
03747      * number of gaussians used */
03748     data->ngauss = atoi(&word[2][0]);
03749 
03750 
03751     /* the next line gives us the d,f and diffuse sp
03752      * functions */
03753     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03754     sscanf(buffer,"%s %d %s %d %s %s",&word[0][0],&data->ndfunc,
03755         &word[1][0],&data->nffunc,&word[2][0],&word[3][0]);
03756 
03757     /* convert GAMESS' .TRUE./.FALSE. for DIFFSP into 1/0 */
03758     if ( !strncmp(&word[3][0],"T",sizeof(&word[3][0])) ) 
03759         data->diffsp = TRUE;
03760 
03761 
03762     /* the next line gives us the p and diffuse s
03763      * functions */
03764     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03765     sscanf(buffer,"%s %d %s %s",&word[0][0],&data->npfunc,
03766         &word[1][0],&word[2][0]);
03767 
03768     /* convert GAMESS' .TRUE./.FALSE. for DIFFSP into 1/0 */
03769     if ( !strncmp(&word[2][0],"T",sizeof(&word[3][0])) ) 
03770         data->diffs = TRUE;
03771 
03772 
03773     /* now we need some logic to assemble this info into
03774      * some nice looking string a la "6-31G*" */
03775 
03776     /* create the diffuse function string */
03777     if ( data->diffs && data->diffsp )
03778     {
03779         strncpy(diffuse,"++",sizeof(diffuse));
03780     }
03781     else if ( data->diffsp ) 
03782     {
03783         strncpy(diffuse,"+",sizeof(diffuse));
03784     }
03785     else 
03786     {
03787         strncpy(diffuse,"",sizeof(diffuse));
03788     }
03789 
03790 
03791     /* create the polarization function string */
03792     if ( ( data->npfunc > 0 ) && ( data->ndfunc > 0) &&
03793          ( data->nffunc > 0 )) 
03794     {
03795 #if 1
03796         /* Windows doesn't provide snprintf in MSVC 6 */
03797         sprintf(polarization,
03798             "(%dp,%dd,%df)", data->npfunc, data->ndfunc,
03799             data->nffunc);
03800 #else
03801         snprintf(polarization,sizeof(polarization),
03802             "(%dp,%dd,%df)", data->npfunc, data->ndfunc,
03803             data->nffunc);
03804 #endif
03805     }
03806     else if ( ( data->npfunc > 0 ) && ( data->ndfunc > 0) ) 
03807     {
03808 #if 1
03809         /* Windows doesn't provide snprintf in MSVC 6 */
03810         sprintf(polarization,
03811             "(%dp,%dd)", data->npfunc, data->ndfunc);
03812 #else
03813         snprintf(polarization,sizeof(polarization),
03814             "(%dp,%dd)", data->npfunc, data->ndfunc);
03815 #endif
03816     }
03817     else if ( ( data->npfunc > 0 ) )  
03818     {
03819 #if 1
03820         /* Windows doesn't provide snprintf in MSVC 6 */
03821         sprintf(polarization,
03822             "(%dp)", data->npfunc);
03823 #else
03824         snprintf(polarization,sizeof(polarization),
03825             "(%dp)", data->npfunc);
03826 #endif
03827     }
03828     else if ( ( data->ndfunc > 0) ) 
03829     {
03830 #if 1
03831         /* Windows doesn't provide snprintf in MSVC 6 */
03832         sprintf(polarization,
03833             "(%dd)", data->ndfunc);
03834 #else
03835         snprintf(polarization,sizeof(polarization),
03836             "(%dd)", data->ndfunc);
03837 #endif
03838     } 
03839     else 
03840     {
03841         strncpy(polarization,"",sizeof(polarization));
03842     } 
03843    
03844 
03845     /* assemble the bits */ 
03846     if ( !strcmp(data->gbasis,"STO") ) 
03847     {
03848 #if 1
03849       /* Windows doesn't provide snprintf in MSVC 6 */
03850       sprintf(data->basis_string,
03851           "STO-%dG%s%s", data->ngauss, diffuse, polarization);
03852 #else
03853       snprintf(data->basis_string,sizeof(data->basis_string),
03854           "STO-%dG%s%s", data->ngauss, diffuse, polarization);
03855 #endif
03856      }
03857      else 
03858      {
03859 #if 1
03860       /* Windows doesn't provide snprintf in MSVC 6 */
03861       sprintf(data->basis_string,
03862           "%d-%s%sG%s", data->ngauss, (data->gbasis+1), diffuse, 
03863           polarization);
03864 #else
03865       snprintf(data->basis_string,sizeof(data->basis_string),
03866           "%d-%s%sG%s", data->ngauss, (data->gbasis+1), diffuse, 
03867           polarization);
03868 #endif
03869      }      
03870   }
03871 
03872   /* for non pople style basis sets we just use the GBASIS
03873    * for the basis string;
03874    * TODO: make the basis_string more comprehensive for non
03875    *       pople-style basis sets */
03876   else 
03877   {
03878     strncpy(data->basis_string,data->gbasis,
03879         sizeof(data->basis_string));
03880   }
03881 
03882 
03883   /* short message */
03884   printf("gamessplugin> Run was performed with BASIS = %s \n",
03885       data->basis_string);
03886 
03887 
03888   return TRUE;
03889 }
03890 
03891 
03892 
03893 /**********************************************************
03894  *
03895  * this subroutine extracts run title 
03896  *
03897  **********************************************************/
03898 static int get_runtitle(void *mydata) 
03899 {
03900   gamessdata *data = (gamessdata *)mydata;
03901   char word[2][BUFSIZ];
03902   char buffer[BUFSIZ];
03903 
03904 
03905   /* initialize arrays */
03906   word[0][0] = '\0';
03907   word[1][0] = '\0';
03908   buffer[0] = '\0';
03909 
03910   
03911   /* look for RUN TITLE section */
03912   do 
03913   {
03914     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file))
03915     sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
03916 
03917   } while( (strcmp(&word[0][0],"RUN")) || 
03918            (strcmp(&word[1][0],"TITLE")));
03919 
03920 
03921   /* the second to next line has what we want */
03922   eatline(data->file);
03923   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file))
03924   strncpy(data->runtitle,chop_string_nl(buffer),sizeof(data->runtitle));
03925 
03926   return TRUE;
03927 } 
03928 
03929 
03930 
03931 /**********************************************************
03932  *
03933  * this subroutine checks the is we support wavefunction
03934  * and orbital stuff for the current gbasis
03935  *
03936  **********************************************************/
03937 static int have_supported_gbasis(void *mydata) {
03938 
03939   gamessdata *data = (gamessdata *)mydata;
03940 
03941   /* check for supported gbasis, otherwise don't even attempt
03942    * to parse the orbital data/wavefunction */
03943   if ( !strcmp(data->gbasis,"MINI") ||
03944        !strcmp(data->gbasis,"MIDI") ||
03945        !strcmp(data->gbasis,"STO") ||
03946        !strcmp(data->gbasis,"N21") ||
03947        !strcmp(data->gbasis,"N31") ||
03948        !strcmp(data->gbasis,"N311") ||
03949        !strcmp(data->gbasis,"DZV") ||
03950        !strcmp(data->gbasis,"DH") ||
03951        !strcmp(data->gbasis,"TZV") ||
03952        !strcmp(data->gbasis,"MC") ) return TRUE;
03953        
03954 
03955   /* I guess we dont' support it then */
03956   return FALSE;
03957 }
03958 
03959 
03960 
03961 /**********************************************************
03962  *
03963  * this subroutine checks the RUNTYP
03964  *
03965  **********************************************************/
03966 static int check_contrl(void *mydata) {
03967 
03968   gamessdata *data = (gamessdata *)mydata;
03969   char word[2][BUFSIZ];
03970   char buffer[BUFSIZ];
03971 
03972 
03973   /* initialize buffer */
03974   word[0][0] = '\0';
03975   word[1][0] = '\0';
03976   buffer[0] = '\0';
03977 
03978 
03979   /* start scanning; currently we support
03980    * RUNTYP = ENERGY, OPTIMIZE, SADPOINT, HESSIAN */
03981   do 
03982   {
03983     ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03984     sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
03985 
03986   } while( strcmp(&word[0][0],"\044CONTRL") || 
03987            strcmp(&word[1][0],"OPTIONS") );
03988 
03989            
03990   /* skip next line */
03991   eatline(data->file);
03992 
03993 
03994   /* current line contains RUNTYP info; scan it */
03995   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
03996   sscanf(buffer,"%s %s",&word[0][0],&word[1][0]);
03997 
03998 
03999   /* check for supported RUNTYPs */
04000   if (!strcmp(&word[1][0],"RUNTYP=ENERGY")) 
04001   {
04002     printf("gamessplugin> File generated via %s \n",&word[1][0]);
04003     data->runtyp = ENERGY;
04004     strncpy(data->runtyp_string,"Single point",
04005             sizeof(data->runtyp_string));
04006   }
04007   else if (!strcmp(&word[1][0],"RUNTYP=OPTIMIZE")) 
04008   {
04009     printf("gamessplugin> File generated via %s \n",&word[1][0]);
04010     data->runtyp = OPTIMIZE;
04011     strncpy(data->runtyp_string,"Geometry optimization",
04012             sizeof(data->runtyp_string));
04013   }
04014   else if (!strcmp(&word[1][0],"RUNTYP=SADPOINT")) 
04015   {
04016     printf("gamessplugin> File generated via %s \n",&word[1][0]);
04017     data->runtyp = SADPOINT;
04018     strncpy(data->runtyp_string,"Saddle point search",
04019             sizeof(data->runtyp_string));
04020   }
04021   else if (!strcmp(&word[1][0],"RUNTYP=HESSIAN")) 
04022   {
04023     printf("gamessplugin> File generated via %s \n",&word[1][0]);
04024     data->runtyp = HESSIAN;
04025     strncpy(data->runtyp_string,"Hessian calculation",
04026             sizeof(data->runtyp_string));
04027   }
04028   else 
04029   {
04030     printf("gamessplugin> The %s is currently not supported \n",
04031             &word[1][0]);
04032     return FALSE;
04033   }
04034 
04035   
04036   /* reserve memory for scfenergy array */
04037   data->scfenergies = (double *)calloc(1,sizeof(double));
04038 
04039 
04040   /* determine SCFTYP */
04041   if (!strcmp(&word[0][0],"SCFTYP=RHF")) 
04042   {
04043     printf("gamessplugin> Type of wavefunction used %s \n",
04044         &word[0][0]);
04045     data->scftyp = RHF;
04046     strncpy(data->scftyp_string,"RHF",sizeof(data->scftyp_string));
04047   }
04048   else if (!strcmp(&word[0][0],"SCFTYP=UHF")) 
04049   {
04050     printf("gamessplugin> Type of wavefunction used %s \n",
04051         &word[0][0]);
04052     data->scftyp = UHF;
04053     strncpy(data->scftyp_string,"UHF",sizeof(data->scftyp_string));
04054   }
04055   else if (!strcmp(&word[0][0],"SCFTYP=ROHF")) 
04056   {
04057     printf("gamessplugin> Type of wavefunction used %s \n",
04058         &word[0][0]);
04059     data->scftyp = ROHF;
04060     strncpy(data->scftyp_string,"ROHF",sizeof(data->scftyp_string));
04061   }
04062   else if (!strcmp(&word[0][0],"SCFTYP=GVB")) 
04063   {
04064     printf("gamessplugin> Type of wavefunction used %s \n",
04065         &word[0][0]);
04066     data->scftyp = GVB;
04067     strncpy(data->scftyp_string,"GVB",sizeof(data->scftyp_string));
04068   }
04069   else if (!strcmp(&word[0][0],"SCFTYP=MCSCF")) 
04070   {
04071     printf("gamessplugin> Type of wavefunction used %s \n",
04072         &word[0][0]);
04073     data->scftyp = MCSCF;
04074     strncpy(data->scftyp_string,"MCSCF",sizeof(data->scftyp_string));
04075   }
04076   else 
04077   {
04078     /* if we don't find a supported SCFTYP we bomb out; this
04079      * might be a little drastic */
04080     printf("gamessplugin> %s is currently not supported \n",
04081             &word[0][0]);
04082     strncpy(data->scftyp_string,"\0",sizeof(data->scftyp_string));
04083     return FALSE;
04084   }
04085 
04086 
04087   eatline(data->file);
04088 
04089   /* next we determine the coord type (i.e. zmatrix, unique ..)
04090    * as provided with the COORD keyword */
04091   ERR_FALSE( fgets(buffer,sizeof(buffer),data->file) )
04092   strcpy(data->geometry,
04093       chop_string_all(strstr(buffer,"COORD =")+7)); 
04094 
04095 
04096   /* brief message */
04097   printf("gamessplugin> Coordinate type %s used \n",data->geometry);
04098 
04099 
04100   /* at this point everything should be in good shape */
04101   return TRUE;
04102 }
04103 
04104 
04105 
04106 
04107 /********************************************************
04108  *
04109  * THIS IS THE END OF THE GAMESS SPECIFIC SUBROUTINES
04110  *
04111  ********************************************************/
04112 
04113 
04114 
04115 
04116 /*********************************************************
04117  *
04118  * this function prints the current date and time 
04119  *
04120  *********************************************************/
04121 void 
04122 get_time(char *mytime)
04123 {
04124   time_t current_time;
04125   struct tm *curtime;
04126 
04127   /* get the current time */
04128 
04129   time(& current_time);
04130 
04131   /* figure out the local time */
04132 
04133   curtime = localtime(& current_time);
04134 
04135   /* print it */
04136 
04137   (void) strftime(mytime,BUFSIZ, 
04138                   "programm start: %a, %0d %b %0H:%0M:%0S", 
04139                   curtime);
04140   
04141   return;
04142 }
04143 
04144 
04145 
04146 /********************************************************
04147  *
04148  * this function removes trailing spaces/newlines off
04149  * a character array
04150  *
04151  ********************************************************/
04152 char* chop_string_all( char* the_string )
04153 {
04154   int i = 0;
04155 
04156   while ( (*(the_string+i) != '\n') && (*(the_string+i) != ' ') && 
04157           (*(the_string+i) != '\0')) 
04158   {
04159     ++i;
04160   }
04161 
04162   *(the_string+i) = '\0';
04163 
04164   return the_string;
04165 }
04166 
04167 
04168 
04169 /********************************************************
04170  *
04171  * this function removes trailing newlines off
04172  * a character array
04173  *
04174  ********************************************************/
04175 char* chop_string_nl( char* the_string )
04176 {
04177   int i = 0;
04178 
04179   while ( (*(the_string+i) != '\n') && (*(the_string+i) != '\0')) 
04180   {
04181     ++i;
04182   }
04183   *(the_string+i) = '\0';
04184 
04185   return the_string;
04186 }
04187 
04188 
04189 
04190 /*********************************************************
04191  *
04192  * this function calculates the value of the wavefunction
04193  * corresponding to a particular orbital at grid point
04194  * grid_x, grid_y, grid_z
04195  *
04196  *********************************************************/
04197 float orbital_at_grid_xyz(void *mydata, float *wave_function,
04198     float grid_size, float grid_x, float grid_y, float grid_z)
04199 {
04200   gamessdata *data = (gamessdata *)mydata;
04201   gamess_temp *temp_data;
04202   int *basis_counter, position;
04203   float xtemp = 0.0, ytemp = 0.0, ztemp = 0.0;
04204   float xtemp2 = 0.0, ytemp2 = 0.0, ztemp2 = 0.0;
04205   char *orbital_symmetry;
04206   int at;
04207   int prim, shell;
04208   int orbital_pointer = 0;
04209   float dist2 = 0; 
04210   float value, value_grid;
04211   int *temp_shell;
04212   int *temp_prims;
04213   int sym_counter;
04214   float temp_p_value, temp_s_value, temp_d_value, temp_f_value;
04215   int have_s, have_p, have_d, have_f;
04216   float temp;
04217 
04218     
04219   /* initialize value of orbital at gridpoint */
04220   value_grid = 0.0;
04221   value = 0.0;
04222 
04223 
04224   /* retrieve orbital symmetry of shel primitives */
04225   orbital_symmetry = data->orbital_symmetry;
04226 
04227         
04228   /* retrieve array with # of primitives available
04229   * for each indivual atom of the system */
04230   basis_counter = data->basis_counter;
04231 
04232 
04233   /* retrieve the pointer for the temp arrays */
04234   temp_data = data->temporary;
04235 
04236   /* initialize the orbital pointer */
04237   orbital_pointer = 0; 
04238 
04239 
04240   /* initialize the primitive counter */
04241   position = 0;
04242   sym_counter = 0;
04243 
04244 
04245   /* store shells and primitive counter in
04246   * temporary arrays */
04247   temp_shell = data->atomic_shells;
04248   temp_prims = data->shell_primitives;
04249 
04250         
04251   /* loop over all the QM atoms */
04252   for ( at = 0 ; at < data->numatoms ; ++at) 
04253   {
04254     /* at this point we can calculate the
04255      * distance of the current grid point
04256      * from the center of atom at */
04257     xtemp =  ( grid_x - (temp_data+at)->x );
04258     ytemp =  ( grid_y - (temp_data+at)->y );
04259     ztemp =  ( grid_z - (temp_data+at)->z );
04260 
04261     xtemp2 =  pow(xtemp,2.0);
04262     ytemp2 =  pow(ytemp,2.0);
04263     ztemp2 =  pow(ztemp,2.0);
04264 
04265           
04266     dist2 = xtemp2 + ytemp2 + ztemp2;
04267 
04268     /* loop over the primitives belonging to
04269      * this atom;
04270      * the number of shells per atom is encoded
04271      * in the array atomic_shells;
04272      * the number of primitives per shell is 
04273      * stored in the array shell_primitives */
04274     for ( shell = 0; shell < *temp_shell; ++shell)
04275     {
04276 
04277       /* initialize temp arrays */
04278       temp_p_value = 0.0; 
04279       temp_s_value = 0.0;
04280       temp_d_value = 0.0;
04281       temp_f_value = 0.0;
04282 
04283 
04284       /* flags keepting track of what orbital
04285        * symmetries we parsed in the current 
04286        * shell */
04287       have_s = FALSE;
04288       have_p = FALSE;
04289       have_d = FALSE;
04290       have_f = FALSE;
04291 
04292 
04293       /* start looping over the shell primitives */
04294       for ( prim = 0; prim < *temp_prims;  ++prim)
04295       {
04296         temp = *(data->basis+position+1) * 
04297           exp(*(data->basis + position)*-1.0*dist2);
04298 
04299         
04300         /* compute-routine for S-shells */
04301         if ( *(orbital_symmetry+sym_counter) == 'S' )
04302         {
04303           /* indicate presence of S shell primitives */ 
04304           have_s = TRUE;
04305 
04306           /* add primitive to s shell */
04307           temp_s_value = temp_s_value + temp;
04308 
04309           /* increase the counter keeping track of the total
04310            * number of primitives */
04311           position += 2;
04312         }
04313            
04314         /* compute-routine for L-shells */
04315         else if ( *(orbital_symmetry+sym_counter) == 'P' )
04316         {
04317           /* indicate presence of P shell primitives */
04318           have_p = TRUE;
04319                
04320           /* add primitive to p shell */
04321           temp_p_value = temp_p_value + temp;
04322 
04323 
04324           /* increase the counter keeping track of the total
04325            * number of primitives */
04326           position += 2;
04327         } 
04328                
04329                 
04330         /* compute-routine for D-shells */
04331         else if ( *(orbital_symmetry+sym_counter) == 'D' )
04332         {
04333           /* indicate presence of P shell primitives */
04334           have_d = TRUE;
04335                
04336           /* add primitive to p shell */
04337           temp_d_value = temp_d_value + temp;
04338 
04339 
04340           /* increase the counter keeping track of the total
04341            * number of primitives */
04342           position += 2;
04343         } 
04344 
04345                
04346         /* compute-routine for F-shells */
04347         else if ( *(orbital_symmetry+sym_counter) == 'F' )
04348         {
04349           /* indicate presence of P shell primitives */
04350           have_f = TRUE;
04351                
04352           /* add primitive to p shell */
04353           temp_f_value = temp_f_value + temp;
04354 
04355 
04356           /* increase the counter keeping track of the total
04357            * number of primitives */
04358           position += 2;
04359         }
04360 
04361 
04362         /* at this point we have fallen through all the
04363          * shell types we know and we better quit */
04364         else
04365         {
04366           printf("gamessplugin> WARNING ... ");
04367           printf("Encountered unknown shell type %d \n", 
04368             *(orbital_symmetry+sym_counter));
04369           return FALSE;
04370         }
04371 
04372 
04373         /* update counter that keeps track of the orbital
04374          * symmetry of the current shell */
04375         sym_counter++;   
04376       }
04377 
04378         
04379       /* multiply with the appropriate wavefunction
04380       * coefficient */
04381 
04382       /* S shells */
04383       if ( have_s ) 
04384       {
04385         /* s */
04386         value = *(wave_function + orbital_pointer) * temp_s_value;
04387         orbital_pointer++;
04388       }
04389           
04390 
04391       /* p shells */
04392       if ( have_p )
04393       {
04394         /* px */
04395         value = *(wave_function + orbital_pointer) * temp_p_value * 
04396             xtemp;
04397         orbital_pointer++;
04398 
04399         /* py */
04400         value = *(wave_function + orbital_pointer) * temp_p_value * 
04401             ytemp;
04402         orbital_pointer++;
04403              
04404         /* pz */ 
04405         value = *(wave_function + orbital_pointer) * temp_p_value * 
04406             ztemp;
04407         orbital_pointer++;
04408       }
04409 
04410             
04411       /* d shells */
04412       if ( have_d )
04413       {
04414         /* d_xx */
04415         value = *(wave_function + orbital_pointer) * temp_d_value * 
04416             xtemp * xtemp;
04417         orbital_pointer++;
04418 
04419         /* d_yy */
04420         value = *(wave_function + orbital_pointer) * temp_d_value * 
04421             ytemp * ytemp;
04422         orbital_pointer++;
04423 
04424         /* d_zz */
04425         value = *(wave_function + orbital_pointer) * temp_d_value * 
04426             ztemp * ztemp;
04427         orbital_pointer++;
04428 
04429         /* d_xy */
04430         value = *(wave_function + orbital_pointer) * temp_d_value * 
04431             xtemp * ytemp;
04432         orbital_pointer++;
04433 
04434         /* d_xz */
04435         value = *(wave_function + orbital_pointer) * temp_d_value * 
04436             xtemp * ztemp;
04437         orbital_pointer++;
04438 
04439         /* d_yz */
04440         value = *(wave_function + orbital_pointer) * temp_d_value * 
04441             ytemp * ztemp;
04442         orbital_pointer++;
04443       }
04444 
04445 
04446       /* f shells */
04447       if ( have_f )
04448       {
04449         /* f_xxx */
04450         value = *(wave_function + orbital_pointer) * temp_d_value * 
04451             xtemp * xtemp * xtemp;
04452         orbital_pointer++;
04453 
04454         /* f_yyy */
04455         value = *(wave_function + orbital_pointer) * temp_d_value * 
04456           ytemp * ytemp * ytemp;
04457         orbital_pointer++;
04458 
04459         /* f_zzz */
04460         value = *(wave_function + orbital_pointer) * temp_d_value * 
04461             ztemp * ztemp * ztemp;
04462         orbital_pointer++;
04463 
04464         /* f_xxy */
04465         value = *(wave_function + orbital_pointer) * temp_d_value * 
04466             xtemp * xtemp * ytemp;
04467         orbital_pointer++;
04468 
04469         /* f_xxz */
04470         value = *(wave_function + orbital_pointer) * temp_d_value * 
04471             xtemp * xtemp * ztemp;
04472         orbital_pointer++;
04473 
04474         /* f_yyx */
04475         value = *(wave_function + orbital_pointer) * temp_d_value * 
04476             ytemp * ytemp * xtemp;
04477         orbital_pointer++;
04478 
04479         /* f_yyz */
04480         value = *(wave_function + orbital_pointer) * temp_d_value * 
04481             ytemp * ytemp * ztemp;
04482         orbital_pointer++;
04483 
04484         /* f_zzx */
04485         value = *(wave_function + orbital_pointer) * temp_d_value * 
04486             ztemp * ztemp * xtemp;
04487         orbital_pointer++;
04488 
04489         /* f_zzy */
04490         value = *(wave_function + orbital_pointer) * temp_d_value * 
04491             ztemp * ztemp * ytemp;
04492         orbital_pointer++;
04493 
04494         /* f_xyz */
04495         value = *(wave_function + orbital_pointer) * temp_d_value * 
04496             xtemp * ytemp * ztemp;
04497         orbital_pointer++;
04498       }
04499 
04500 
04501       /* move primitives pointer to next shell */
04502       ++temp_prims;
04503 
04504 
04505       /* store value in temporary array, and 
04506       * reset value */
04507       value_grid = value_grid + value;
04508       value = 0.0; 
04509     } 
04510 
04511 
04512     /* move shell pointer to next atom */
04513     temp_shell++;
04514   }
04515 
04516   /* return value at grid point */
04517   return value_grid;
04518 }
04519 
04520 

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