CCL Home Page
Up Directory CCL xvibs
/**********************************************************
xvibs
  version 4.0.1 (August 1997)

This program produces XYZ animation files for molecular vibrations
represented by normal modes taken from output files from Aces2,
Gamess, and Gaussian. The program autosenses what output file is
given. It writes separate files, one simple cosine trajectory for
particular normal mode. Vectors representing the normal coordinate are
attached to the atoms, which is useful for a static picture.

This program is not copyrighted. You are welcome to extend it,
or send your files to basmith@pollux.chem.umn.edu and I will gladly
extend it for you.

Send bug reports to: basmith@pollux.chem.umn.edu 


Compiling:
  cc -o xvibs xvibs.c -lm

Running:
  xvibs file {all | 1..(3*N-6)} [palindrome]

Example:
  xvibs ch3oh_gam.out all

    Output files are named ch3oh_gam.{001-018}.xyz

or
  xvibs ch3oh_gam.out 15

    for mode 15 only. Output will be ch3oh_gam.015.xyz

By default, XYZ files created are for loop animation (like in XMol).
The optional 3rd argument "palindrome" will create XYZ files for
palindrome animation (like in Chime).

Examples are provided for ACES2, GAMESS, and GAUSSIAN files.


**********************************************************/

/**********************************************************
Written in 1990 by Milan Hodoscek
Institute of Chemistry, Ljubljana, Slovenia
Modified for XMOL 1992 @NIH, Bethesda, MD
Modified again Fred Brouwer Univ. of Amsterdam 1994
to include vectors (fred@org.chem.uva.nl (Fred Brouwer))
Modified to accept G94, Yos Ginting (Yos.Ginting@chem.utas.edu.au)
Modified by Jan Labanowski, jkl@ccl.net to accept input from GAMESS and ACESS
Rewritten by Bradley A. Smith, (http://pollux.chem.umn.edu/~basmith/,
                                basmith@pollux.chem.umn.edu)

Send bug reports to: basmith@pollux.chem.umn.edu
-------------------------------------------

History:

Version 2 (June 1994)

-- Fixed bug to accept file names without point
-- Maximum number of atoms is now define with MAXAT
-- Added data for drawing vectors representing normal modes
-- Prints energy for G90 and G92 output


Version 3 (July 1996)
Yos Ginting 

-- Add capability to parse G94 output.
   The folowing two function were added:
     is_g94 , return 1 if input is in G94 format
              return 0 if it is in G92 format
              otherwise, display error messages
     vib_g94  is a modification of vib_g88.
              It now properly parses g94 output


Version 3.1 (July 1997)
Jan K. Labanowski 

-- replaced is_94 with which_program, and g94 with file_type
   The which_program returns the code (look up the #define statements) 
   which represents the type of format of OUTPUT file.
   Added global variables:
      vibtotal -- provides info on how many vibrations are listed
                  in output file (ALLVIBS -- 3N, i.e., rotations and 
                  translations included, NORTVIBS -- 3N-6, rotations
                  and translations removed
      debug -- for program debugging purposes, if set to 1, prints
               additional information to stderr
   Added routines for processing GAMESS and ACES2 output files


Version 4 (July 1997)
Bradley A. Smith (http://pollux.chem.umn.edu/~basmith/,
                  basmith@pollux.chem.umn.edu)

- Major rewrite to remove bugs and improve speed and reliability.
- Converted syntax from K&R to ANSI C.
- Only two passes made through input file. File type and
  number of atoms determined on first pass. All data read
  in second pass.
- To increase effeciency, changed searching from
  by word (fscanf("%s") & strcmp()) to by line (fgets() & strncmp()).
  Examples of data searched for are included in comments.
- Dynamic allocation of storage. Number of atoms now limited only
  by memory.
- Data stored in structs for atoms and frequencies improving clarity
  of data structure and handling.
- Debugging statements put inside precompiler directives.
- Added support for pallindrome animation

Version 4.0.1 (August 1997)
Bradley A. Smith (http://pollux.chem.umn.edu/~basmith/,
                  basmith@pollux.chem.umn.edu)

- Fixed bug in g94ReadFrequencies(). (Frequency value can start with
  digit or '-'.  Previously would only read frequencies if there were
  no negative frequencies.)
- Correct for when energy not found.
- Bug: always wrote vectors for first frequency (Thanks to Peter
  Freunscht)

**********************************************************/


#include 
#include 
#include 
#include 
#include 

const char* kXvibsVersion = "4.0.1";
const double angstromPerBohr = 0.529177249;
const double TWOPI = 6.28318530717958647688;

enum fileType { G92, G94, GAMESS, ACES2, UNKNOWN };
typedef enum fileType FileType;

enum animType { LOOP, PALINDROME };
typedef enum animType AnimType;

#define DEBUG 0

struct cartesian {
	double x;
	double y;
	double z;
};
typedef struct cartesian Cartesian;

struct atom {
	int atomicNumber;
	double x;
	double y;
	double z;
};
typedef struct atom Atom;

struct freq {
	double value;
	Cartesian* coordinates;
};
typedef struct freq Freq;

FileType typeInput(FILE* file);
void writeAtom(FILE* out, Atom* a, Cartesian* v, double scaleVector);
double aces2ReadEnergy(FILE* file);
int aces2ReadCoordinates(FILE* file, Atom* atoms);
int aces2ReadFrequencies(FILE* file, int numAtoms, Freq freqs[]);
int aces2CountAtoms(FILE* file);
double gamessReadEnergy(FILE* file);
int gamessReadCoordinates(FILE* file, Atom* atoms);
int gamessReadFrequencies(FILE* file, int numAtoms, Freq freqs[]);
int gamessCountAtoms(FILE* file);
double g94ReadEnergy(FILE* file);
int g94ReadCoordinates(FILE* file, Atom* atoms);
int g94ReadFrequencies(FILE* file, int numAtoms, Freq freqs[]);
int g94CountAtoms(FILE* file);


main(int argc, char* argv[])
{

	Atom* atoms;
	Freq* freqs;
	double energy;
	int numAtoms;
	int frames;
	int freqNumber;
	int numFreqs;
	int startFreq;
	int endFreq;
	FileType inputType = UNKNOWN;
	char* baseName;
	char* fileName;
	int all;
	char* pIndex ;
	FILE* output;
	FILE* input;
	const double freqScale = 0.7;
	const double vectorScale = 2.0;
	int i;
	int j;
	int startFrame;
	double offset;
	AnimType animType = LOOP;

	/* Process command line */
	if(argc < 3) {
	  fprintf(stderr, "Insufficient arguments\n");
		fprintf(stderr, "  xvibs version %s\n", kXvibsVersion);
		fprintf(stderr, "Usage: xvibs file {all | 1..(3*N-6)} [palindrome]\n");
		exit(1);
	}
	all = 0;
	if(argv[2][0] == 'a') {
		/* all vibrations will be processed */
		all = 1;
		freqNumber = 0;
	}
	else  freqNumber = atoi(argv[2]) - 1;
	if(freqNumber < 0) {
		fprintf(stderr, "Error: frequency number must be a positive integer\n");
		exit(6);
	}
	if(argc == 4 && argv[3][0] == 'p') {
		animType = PALINDROME;
	}

	/* Set base name for files */
	baseName = strdup(argv[1]);
	if((pIndex = strrchr(baseName, '.')) != NULL ) {
		*pIndex = '\0';
	}

	/* Open input file */
	input = fopen(argv[1],"r");
	if(input == NULL) {
		fprintf(stderr,"Error opening file '%s'\n", argv[1]);
		exit(2);
	}
	
	/* Get information about the input file format. */
	inputType = typeInput(input);
	if(inputType == UNKNOWN) {
		fprintf(stderr, "Error: unknown input file type\n");
		exit(3);
	}
	else if(inputType == G94 || inputType == G92) {
		numAtoms = g94CountAtoms(input);
	}
	else if(inputType == GAMESS) {
		numAtoms = gamessCountAtoms(input);
	}
	else if(inputType == ACES2) {
		numAtoms = aces2CountAtoms(input);
	}

	/* Allocate memory for storage of atomic coordinates and frequencies */
	atoms = malloc(sizeof(Atom)*numAtoms);
	freqs = malloc(sizeof(Freq)*3*numAtoms);
	for(i=0; i < 3*numAtoms; i++) {
		if((freqs[i].coordinates = malloc(sizeof(Cartesian)*numAtoms)) == NULL) {
			fprintf(stderr, "Error: unable to allocate frequency %d (%s)\n", i,
				strerror(errno));
			exit(4);
		}
	}
	if(!(atoms && freqs)) {
		fprintf(stderr, "Error: unable to allocate memory for %d atoms and %d frequencies\n", numAtoms, 3*numAtoms-6);
		exit(5);
	}	

	/* Back to the start of the file */
	rewind(input);
	
	/* Read input file */
	if(inputType == G94 || inputType == G92) {
		numAtoms = g94ReadCoordinates(input, atoms);
		energy = g94ReadEnergy(input);
		if(energy == 0.0) {
		  /* energy not found after searching to end of file; must
		     rewind to find frequencies */
		  rewind(input);
		}
		numFreqs = g94ReadFrequencies(input, numAtoms, freqs);
	}
	else if(inputType == GAMESS) {
		numAtoms = gamessReadCoordinates(input, atoms);
		energy = gamessReadEnergy(input);
		if(energy == 0.0) {
		  /* energy not found after searching to end of file; must
		     rewind to find frequencies */
		  rewind(input);
		}
		numFreqs = gamessReadFrequencies(input, numAtoms, freqs);
	}
	else if(inputType == ACES2) {
		numAtoms = aces2ReadCoordinates(input, atoms);
		energy = aces2ReadEnergy(input);
		if(energy == 0.0) {
		  /* energy not found after searching to end of file; must
		     rewind to find frequencies */
		  rewind(input);
		}
		numFreqs = aces2ReadFrequencies(input, numAtoms, freqs);
	}
	else {
		fprintf(stderr, "Error reading input file: unknown file type\n");
		exit(7);
	}
#if DEBUG
		fprintf(stderr, "numAtoms=%d\n", numAtoms);
		for(i=0; i < numAtoms; i++) {
			fprintf(stderr, "atoms[%d] = %d	%10.6f %10.6f %10.6f\n", i,
			 atoms[i].atomicNumber, atoms[i].x, atoms[i].y, atoms[i].z);
		}

		fprintf(stderr, "energy = %10.6f\n", energy);

		fprintf(stderr, "numFreqs=%d\n", numFreqs);
		for(i=0; i < numFreqs; i++) {
			fprintf(stderr, "freqs[%d]\t=\t%f\n\t", i, freqs[i].value);
			for(j=0; j < numAtoms; j++) {
				fprintf(stderr, "%10.6f	%10.6f	%10.6f\n\t",
				freqs[i].coordinates[j].x,
				freqs[i].coordinates[j].y,
				freqs[i].coordinates[j].z);
			}
			fprintf(stderr, "\n");
		}
#endif
	
	/* Create animation files */
	if(numFreqs <= 0) {
		fprintf(stderr, "Error: no frequencies found\n");
		exit(8);
	}
	if(all) {
		startFreq = 0;
		endFreq = numFreqs;
	}
	else {
		if(freqNumber > numFreqs) {
			fprintf(stderr,
					"Error: requested frequency is greater than number of frequencies found, %d\n",
					numFreqs);
			exit(9);
		}
		startFreq = freqNumber;
		endFreq = freqNumber+1;
	}
	for(freqNumber = startFreq; freqNumber < endFreq ; freqNumber++) {
		fileName = malloc(sizeof(char)*(strlen(baseName)+8));
		sprintf(fileName, "%s.%03d.xyz", baseName, freqNumber+1);

		output = fopen(fileName, "w");
		if(output == NULL) {
			fprintf(stderr, "Error opening file '%s'\n", fileName);
			exit(10);
		}

		/* Write the coordinates of the equilibrium structure: */
		if(animType == LOOP) {
			fprintf(output, "%d\n", numAtoms);
			fprintf(output, "* %s, Energy %12.6f\n", argv[1], energy);
			for(i=0; i < numAtoms; i++) {
				writeAtom(output, &atoms[i], &freqs[freqNumber].coordinates[i], vectorScale);
			}
		}

		/* Write vibrational structures. */

		/* For looping (default), skip j=0 and j=frames because they are equal
			 to the equilibrium geometry. */
		startFrame = 1;
		frames = 20-1;
		offset = 0.0;

		/* For palindrome animation, offset starting to furthest point in vibration. */
		if(animType == PALINDROME) {
			startFrame = 0;
			frames++;
			offset = M_PI/2.0;
		}
		for(j = startFrame; j <= frames; j++) {
			fprintf(output, "%d\n", numAtoms);
			fprintf(output, "* Frequency(%d) %10.4f\n", freqNumber+1,
					freqs[freqNumber].value);
			
			for(i=0; i < numAtoms; i++) {
				/* modify coordinates along normal modes */
				Atom a;
				a.atomicNumber = atoms[i].atomicNumber;
				a.x = atoms[i].x + freqScale*sin(TWOPI*j/frames+offset)*freqs[freqNumber].coordinates[i].x ;
				a.y = atoms[i].y + freqScale*sin(TWOPI*j/frames+offset)*freqs[freqNumber].coordinates[i].y ;
				a.z = atoms[i].z + freqScale*sin(TWOPI*j/frames+offset)*freqs[freqNumber].coordinates[i].z ;
				writeAtom(output, &a, &freqs[freqNumber].coordinates[i], vectorScale);
			}
		}
		free(fileName);
	}
	
	/* Deallocate memory */
	free(baseName);
	free(atoms);
	for(i=0; i < 3*numAtoms-6; i++) {
		free(freqs[i].coordinates);
	}
	free(freqs);
}

void writeAtom(FILE* out, Atom* a, Cartesian* v, double scaleVector)
{
	/* XMol doesn't understand all the periodic table of elements, so 
		everything above Kr is set to X */
	static char atomicSymbols[37][3] = {
		"H ",                                     "He",
		"Li", "Be", "B ", "C ", "N ", "O ", "F ", "Ne",
		"Na", "Mg", "Al", "Si", "P ", "S ", "Cl", "Ar",
		"K ", "Ca", "Sc",
		"Ti", "V ", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn",
		"Ga", "Ge", "As", "Se", "Br", "Kr", "X " };
	int an;
	
	/* perhaps v's x, y, and z should be set to zero for too small amplitudes */
	an = a->atomicNumber-1;
	if((an >= 0) && (an < 37)) {
		fprintf(out,"%s  %11.6f %11.6f %11.6f %11.6f %11.6f %11.6f\n",
			atomicSymbols[an],
			a->x, a->y, a->z,
			v->x*scaleVector, v->y*scaleVector, v->z*scaleVector);
	}
	else {
		fprintf(out,"%s  %11.6f %11.6f %11.6f %11.6f %11.6f %11.6f\n",
			atomicSymbols[36],
			a->x, a->y, a->z,
			v->x*scaleVector, v->y*scaleVector, v->z*scaleVector);
	}
}

FileType typeInput(FILE* file)
{
  FileType type = UNKNOWN;
  char line[300];
  
  while(fgets(line, 300, file) != NULL) {
	/* For Gaussian 92 identification seach for "Gaussian 92:".  For example, as in the lines:
 ********************************************
 Gaussian 92:  SGI-G92/DFT-RevG.2 28-Feb-1994
                 14-Jul-1997 
 ********************************************
	*/
    if(strncmp(line, " Gaussian 92:", 13) == 0) {
      type = G92;
      break;
    }
	/* For Gaussian 94 identification seach for "Gaussian 94:".  For example, as in the lines:
 **************************************************
 Gaussian 94:  CrayXMP-Unicos-G94RevB.3 30-May-1995
                     8-Jan-1996
 **************************************************
	*/
    if(strncmp(line, " Gaussian 94:", 13) == 0) {
      type = G94;
      break;
    }
	/* For GAMESS identification seach for "GAMESS".  For example, as in the lines:
1         ******************************************************
          *            GAMESS VERSION = 31 OCT 1996            *
          *             FROM IOWA STATE UNIVERSITY             *
          * M.W.SCHMIDT, K.K.BALDRIDGE, J.A.BOATZ, S.T.ELBERT, *
          *   M.S.GORDON, J.H.JENSEN, S.KOSEKI, N.MATSUNAGA,   *
          *          K.A.NGUYEN, S.J.SU, T.L.WINDUS,           *
          *       TOGETHER WITH M.DUPUIS, J.A.MONTGOMERY       *
          *         J.COMPUT.CHEM.  14, 1347-1363(1993)        *
          *************** CRAY T3D/T3E VERSION *****************
	*/
    else if(strncmp(line, "          *            GAMESS", 29) == 0) {
      type=GAMESS;
      break;
    }
	/* For ACES2 identification seach for "* ACES2:".  For example, as in the lines:
           *******************************************************
           * ACES2: Advanced Concepts in Electronic Structure II *
           *******************************************************
	*/
    else if(strncmp(line, "           * ACES2:", 19) == 0) {
      type=ACES2;
      break;
    }
  }
  return(type);
}

double gamessReadEnergy(FILE* file)
{
	char line[300];
	double energy;
	int notFound = 1;

	/* Find energy.  For example:
                TOTAL ENERGY =    -284.4340725614                 TOTAL POTENTIAL ENERGY =    -567.9259211845
	*/
	while(fgets(line, 300, file) != NULL
		&& (notFound = strncmp(line,"                TOTAL ENERGY =", 30)) != 0) ;
  
	if(notFound) {
		fprintf(stderr, "Error reading GAMESS energy: unable to find TOTAL ENERGY\n");
		return 0.0;
	}
	sscanf(line, "%*s %*s %*s %lf", &energy);
	return energy;
}

int gamessReadCoordinates(FILE* file, Atom* atoms)
{
	char line[300];
	int numAtoms;
	int notFound;
	double tmpDouble;

	numAtoms = 0; 
	notFound = 1;
	/* Find initial coordinates.  For example:
 ATOM      ATOMIC                      COORDINATES (BOHR)
           CHARGE         X                   Y                   Z
 C           6.0    -0.6825841446       -2.2557337862       -0.5523839137
 C           6.0     1.9677905683       -2.1875543623       -0.1960401740
 H           1.0     5.2440255207        0.2405281032        0.0105352224
 N           7.0    -3.9086846666       -0.8317610038        1.4705280719
 H           1.0    -1.7347344417       -3.9525017430       -1.0103797939

          INTERNUCLEAR DISTANCES (ANGS.)
          ------------------------------
	*/
	while(fgets(line, 300, file) != NULL
		&& (notFound = strncmp(line, " ATOM      ATOMIC                      COORDINATES (BOHR)", 45)) != 0) ;
	
	if(notFound) {
		fprintf(stderr, "Error reading GAMESS coordinates: unable to find initial coordinates\n");
		return 0;
	}
	
	/* Initial coordinates found.	 Read one more header lines.	*/
	if(!(fgets(line, 300, file) != NULL)) {
		fprintf(stderr, "Error reading GAMESS coordinates\n");
		return 0;
	}
	
	/* Read atomic numbers and count atoms */
	while(fscanf(file, "%s %lf %lf %lf %lf", line, &tmpDouble,
			&atoms[numAtoms].x,
			&atoms[numAtoms].y,
			&atoms[numAtoms].z) == 5) {
		atoms[numAtoms].atomicNumber = (int)tmpDouble;
		/* Record only real atoms (e.g., skip dummy atoms) */
		if(atoms[numAtoms].atomicNumber > 0) {
			atoms[numAtoms].x *= angstromPerBohr;
			atoms[numAtoms].y *= angstromPerBohr;
			atoms[numAtoms].z *= angstromPerBohr;
			numAtoms++;
		}
	}
	return(numAtoms);
}

int gamessReadFrequencies(FILE* file, int numAtoms, Freq freqs[])
{
	char line[300];
	char str[100];
	int notFound = 1;
	int numFreqs;
	int numColumns;
	char* err;
	char i1;
	int i;
	int j;
	char* p;
	char* p2;

	/* Find normal coordinates.  For example:
                          1           2           3           4           5           6           7           8           9
      FREQUENCY:        217.07 I     11.21       10.65        0.48      111.71      119.71      147.44      373.79      487.14  
      INTENSITY:       0.79509     0.00010     0.00014     0.00115     0.10093     0.04353     0.02010     0.13489     0.24478

  1   C            X -0.06525937 -0.06932313  0.07834103 -0.00460444 -0.01980564 -0.07329911 -0.02635176  0.02324915 -0.03769840
                   Y  0.01108711 -0.07550590 -0.06901806 -0.01689686 -0.00306042  0.01949817  0.03203774 -0.03065802 -0.03587336
                   Z -0.04052354  0.01624196  0.00666195 -0.10169318  0.03720340  0.00728284 -0.10698456 -0.05359112  0.15665786
  2   C            X -0.05015375 -0.06955566  0.07969405 -0.00441497 -0.00531244 -0.07142766 -0.02144681  0.02126201 -0.01181436
                   Y -0.00080057 -0.07559116 -0.06803082 -0.01652009  0.00676091 -0.07149885 -0.00148754 -0.00528179  0.00501213
                   Z  0.05897889  0.01397220  0.00576418 -0.10431512 -0.07503940  0.00055594 -0.12912742 -0.09720340 -0.01513864
  3   H            X -0.06353590 -0.07031443  0.07869325 -0.00419081 -0.00348353 -0.12860196 -0.03475153  0.04334156 -0.01287901
                   Y -0.01066747 -0.07479494 -0.06807474 -0.01632475  0.00937945 -0.10622703 -0.00574529  0.01072681  0.00885385
                   Z  0.06829551  0.01350568  0.00569690 -0.10417082 -0.11264075  0.00235976 -0.22276037 -0.13934044 -0.12084604
  4   C            X -0.03338173 -0.07013860  0.07845345 -0.00518733 -0.00779069  0.00389958 -0.00207753 -0.01350458  0.00009270
                   Y -0.02810590 -0.07664076 -0.06810813 -0.01614765  0.00930519 -0.11092367 -0.01811375  0.00955983 -0.00627472
                   Z  0.06395158  0.01414359  0.00585762 -0.10550101 -0.12532348 -0.00902644 -0.02061296  0.09253504 -0.08576888

 TRANS. SAYVETZ    X -0.06873026 -6.35147027  7.10097273 -0.50299607 -0.03522640  0.09327256  0.03130830 -0.01901949  0.02163533
                   Y -0.15436373 -6.96440772 -6.33787366 -1.52043932  0.05770663 -0.09364809  0.11657404 -0.03243428  0.02106756
                   Z -0.12020741  1.46741752  0.64597405 -9.40445607  0.08815627 -0.00012613 -0.06913014  0.01214535 -0.00326919

               TOTAL  0.20736883  9.53925907  9.53990245  9.53983935  0.11109672  0.13217318  0.13909958  0.03951244  0.03037462

   ROT. SAYVETZ    X -0.61180913  0.23517836  0.15963429 -0.11523672 -3.46880727 -4.57261436 18.72391365 -0.21757856 -0.99021463
                   Y -1.72682231  0.07039203  0.14402430  0.24705332 23.74657320  1.82363425  2.45544698 -0.77194604 -0.24478613
                   Z  0.74466282 -0.01595194  0.41284908  0.06033907  3.10802091-29.53230756 -1.84400208  0.47388532 -0.25440341

               TOTAL  1.97756123  0.24600481  0.46547875  0.27920539 24.19901148 29.93980016 18.97404822  0.93156235  1.05126893

                         10          11          12          13          14          15          16          17          18
      FREQUENCY:        509.29      606.07      644.38      723.48      801.29      859.63      907.51      941.12      963.88  
      INTENSITY:       0.39331     0.01822     0.23180     0.43698     0.99749     1.21880     1.53362     1.10749     0.12314

  1   C            X  0.00951508  0.07419555  0.05148156 -0.01203311 -0.02547399  0.00615577 -0.01079594  0.04049035 -0.09227907
                   Y -0.06384551 -0.00285285  0.11027733  0.05300815  0.06629486  0.07938637 -0.04210869  0.14486079 -0.02943428
                   Z -0.06113635  0.03169468 -0.03707645  0.10234522  0.02083381  0.00455239 -0.07654972 -0.00679530  0.04432899
  2   C            X -0.00553438  0.07457762  0.07069040  0.00065188 -0.04748169 -0.01989750 -0.04324235 -0.01109245  0.04791943
                   Y -0.03780747 -0.11252936 -0.01163935  0.01910395  0.05990448 -0.01818107  0.06460952 -0.02772412 -0.00051455
                   Z  0.08132724 -0.02693031  0.05555269 -0.08954265  0.04152869 -0.02146491 -0.01790663 -0.01486294 -0.05978473
  3   H            X  0.03860447  0.09946674 -0.02788065 -0.05774475 -0.08783155 -0.07366254 -0.05643700 -0.09943890 -0.02048499
                   Y -0.01803259 -0.09203001 -0.07785475 -0.01676645  0.04656175 -0.06391887  0.04424374 -0.08388983 -0.06907445
                   Z  0.28689288 -0.13509607  0.14816838 -0.07505464 -0.18413332  0.31338201  0.23765660  0.16710996  0.39173943
  4   C            X -0.06595468 -0.06157885  0.08993605  0.00894564  0.02823564 -0.03493986  0.03238906 -0.07976203  0.11915560
                   Y -0.00124967 -0.04869429 -0.04149018 -0.00625735  0.01911195 -0.01192824  0.02030645 -0.02997777 -0.03650293
                   Z -0.05789594  0.00919090 -0.06189845  0.08398252  0.00426348 -0.05690897 -0.02796632 -0.00943015 -0.03355286

 TRANS. SAYVETZ    X  0.02692151  0.02853914 -0.03594899  0.00389392  0.03337145  0.00411483  0.01533436  0.02334947 -0.00836761
                   Y  0.01150354 -0.02217207  0.02677689  0.03509662  0.04309464  0.01568360  0.01805776  0.02066674 -0.00801329
                   Z  0.00774759  0.00240772  0.00336540 -0.00211745  0.00102919 -0.00791561 -0.01306513  0.00312892  0.01245331

               TOTAL  0.03028406  0.03621989  0.04495172  0.03537540  0.05451478  0.01804339  0.02705407  0.03133851  0.01700925

   ROT. SAYVETZ    X -0.59706936  0.36914336 -0.01310802 -0.14392716  0.02186111  0.21758524  0.00168581 -0.08141964 -0.13161552
                   Y  0.55791302 -0.04306691  0.10187054 -0.23221808  0.16533779 -0.12633235  0.09130534 -0.03123664 -0.02749576
                   Z -0.05463445  0.16744376  0.46214627  0.00821074 -0.15478475 -0.01003048 -0.10790792  0.10913322 -0.21735641

               TOTAL  0.81898943  0.40762604  0.47342222  0.27332706  0.22753640  0.25180113  0.14136346  0.13969590  0.25558261

 REFERENCE ON SAYVETZ CONDITIONS - A. SAYVETZ, J. CHEM. PHYS., 7, 383-389 (1939).
	*/
 
	while((err = fgets(line, 300, file)) != NULL
		  && (notFound = strncmp(line,"      FREQUENCY:", 16)) != 0) ;
 
	if(notFound) {
		fprintf(stderr, "Error reading GAMESS frequencies: unable to find initial coordinates\n");
		return 0;
	}
 
	/* Read frequencies */
	numFreqs = 0;
	while(err != NULL) { 
		/* Count number of columns of data in current set of frequencies */
		numColumns = 0;
		p = strtok(line, " \n\t");
		if(p == NULL)  break;
		if(p && strncmp(p, "FREQUENCY:", 10) != 0)  break;
		/* Skip first token: "FREQUENCY:" */
		p = strtok(NULL, " \n\t");
		if(p && *p != ' ') {
			if(!isdigit(*p))  break;
			freqs[numFreqs+numColumns].value = strtod(p, &p2);
			if(p2 != NULL && *(p2+1) == 'I') {
				p = strtok(NULL, " \n\t");
				freqs[numFreqs+numColumns].value = -freqs[numFreqs+numColumns].value;
			}
			numColumns++;
			while((p = strtok(NULL, " \n\t")) != NULL) {
				freqs[numFreqs+numColumns].value = strtod(p, &p2);
				if(p2 != NULL && *(p2+1) == 'I') {
					p = strtok(NULL, " \n\t");
					freqs[numFreqs+numColumns].value = -freqs[numFreqs+numColumns].value;
				}
				numColumns++;
			}
		}
		if(numColumns <= 0) {
			fprintf(stderr, "Error reading GAMESS frequencies: unable to count columns\n");
			return 0;
		}

		/* Skip to top of vectors */
		err = fgets(line, 300, file);
		err = fgets(line, 300, file);
		if(err == NULL) {
			fprintf(stderr, "Error reading GAMESS frequencies\n");
			return 0;
		}
	 
		for(j=0; j < numAtoms; j++) {
			if(fscanf(file, "%*s %*s %*s") == EOF) {
				fprintf(stderr, "Error reading GAMESS frequencies: error on first line of atom %d\n", j);
				return 0;
			}
			for(i=0; i < numColumns; i++) {
				if(fscanf(file, "%lf", &(freqs[numFreqs+i].coordinates[j].x)) == EOF) {
					fprintf(stderr, "Error reading GAMESS frequencies\n");
					return 0;
				}
			}
			if(fscanf(file, "%*s") == EOF) {
				fprintf(stderr, "Error reading GAMESS frequencies\n");
				return 0;
			}
			for(i=0; i < numColumns; i++) {
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[j].y) == EOF) {
					fprintf(stderr, "Error reading GAMESS frequencies\n");
					return 0;
				}
			}
			if(fscanf(file, "%*s") == EOF) {
				fprintf(stderr, "Error reading GAMESS frequencies\n");
				return 0;
			}
			for(i=0; i < numColumns; i++) {
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[j].z) == EOF) {
					fprintf(stderr, "Error reading GAMESS frequencies\n");
					return 0;
				}
			}
		}
	
		for(i=0; i < 16; i++) {
			err = fgets(line, 300, file);
		}
		if(err == NULL) {
			fprintf(stderr, "Error reading GAMESS frequencies\n");
			return 0;
		}
		numFreqs += numColumns;
	}

	return numFreqs;
}
 
int gamessCountAtoms(FILE* file)
{
	char line[300];
	int numAtoms;
	int notFound;
	double tmpDouble;
	int atomicNumber;
	char* p;

	numAtoms = 0; 
	notFound = 1;
	/* Find initial coordinates.  For example:
 ATOM      ATOMIC                      COORDINATES (BOHR)
           CHARGE         X                   Y                   Z
 C           6.0    -0.6825841446       -2.2557337862       -0.5523839137
 C           6.0     1.9677905683       -2.1875543623       -0.1960401740
 H           1.0     5.2440255207        0.2405281032        0.0105352224
 N           7.0    -3.9086846666       -0.8317610038        1.4705280719
 H           1.0    -1.7347344417       -3.9525017430       -1.0103797939

          INTERNUCLEAR DISTANCES (ANGS.)
          ------------------------------
	*/
	while(fgets(line, 300, file) != NULL
		&& (notFound = strncmp(line, " ATOM      ATOMIC                      COORDINATES (BOHR)", 45)) != 0) ;
	
	if(notFound) {
		fprintf(stderr, "Error counting GAMESS atoms: unable to find initial coordinates\n");
		return 0;
	}
	
	/* Initial coordinates found.	 Read one more header lines.	*/
	if(!(fgets(line, 300, file) != NULL)) {
		fprintf(stderr, "Error counting GAMESS atoms\n");
		return 0;
	}
	
	/* Count atoms */
	while(fgets(line, 300, file) != NULL) {
		/* If line has no tokens (i.e., blank line), end of atoms found */
		p =	strtok(line, " \n\t");
		if(!p || *p == ' ')  break;
		p = strtok(NULL, " \n\t");
		if(atof(p) != 0.0)  numAtoms++;
	}
	return(numAtoms);
}

double aces2ReadEnergy(FILE* file)
{
	char line[300];
	double energy;
	int notFound = 1;

	/* Search for SCF energy.  For example:
             E(SCF)                = -130.976617544133 a.u.
	*/
	while(fgets(line, 300, file) != NULL
		  && (notFound = strncmp(line,"              E(SCF)                =", 37)) != 0) ;
	  
	if(notFound) {
	fprintf(stderr, "Error reading ACES2 energy: unable to find SCF energy\n");
		return 0.0;
	}
	sscanf(line, "%*s %*s %lf", &energy);
	return energy;
}

int aces2ReadCoordinates(FILE* file, Atom* atoms)
{
  char line[300];
  char s1[30], s2[30], s3[30], s4[30];
  int i, j, k, numAtoms, notFound;
  double coor;
  
  numAtoms = 0; 
  notFound = 1;
  /* Find initial coordinates.  For example:
         -----------------------------------------------
         Cartesian coordinates corresponding to internal 
                 coordinate input (Bohr) 
 ----------------------------------------------------------------
 Z-matrix   Atomic            C o o r d i n a t e s
  Symbol    Number           X              Y              Z
 ----------------------------------------------------------------
     X         0         0.00000000     0.00000000     3.36831426
     N         7         0.00000000     0.00000000     1.47858773
     C         6         0.00000000     1.28781929    -0.73812957
     C         6         0.00000000    -1.28781929    -0.73812957
     H         1         0.00000000     3.22348136    -1.48322270
     H         1         0.00000000    -3.22348136    -1.48322270
 ----------------------------------------------------------------
  */
  while(fgets(line, 300, file) != NULL
	&& (notFound = strcmp(line," Z-matrix   Atomic            C o o r d i n a t e s\n")) != 0) ;
  
  if(notFound) {
    fprintf(stderr, "Error reading ACES2 coordinates: unable to find initial coordinates\n");
    return 0;
  }
  
  /* Initial coordinates found.  Read two more header lines.  */
  if(!(fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL)) {
    fprintf(stderr, "Error reading ACES2 coordinates\n");
    return 0;
  }
  
  /* Read atomic numbers and count atoms */
  while(fgets(line, 300, file) != NULL) {
    sscanf(line, "%s %d %lf %lf %lf", line, &atoms[numAtoms].atomicNumber,
	   &atoms[numAtoms].x,
	   &atoms[numAtoms].y,
	   &atoms[numAtoms].z);
    if(strncmp(line, "--", 2) == 0) {
      /* End of coordinates reached */
      break;
    }
    /* Record only real atoms (e.g., skip dummy atoms) */
    if(atoms[numAtoms].atomicNumber > 0) {
      atoms[numAtoms].x *= angstromPerBohr;
      atoms[numAtoms].y *= angstromPerBohr;
      atoms[numAtoms].z *= angstromPerBohr;
      numAtoms++;
    }
  }
  return(numAtoms);
}

int aces2ReadFrequencies(FILE* file, int numAtoms, Freq freqs[])
{
	char line[300];
	char valueLine[300];
	int atomIndex;
	int notFound = 1;
	int numFreqs;
	int numColumns;
	char* err;
	char* p;
	char* p2;
	int i;

	/* Find normal coordinates.  For example:
 ----------------------------------------------------------------
 
                                    Normal Coordinates 
                          [Dimensions are Mass**-1/2 Distance] 

                B1                        A1                        B2
               843.48i                    927.15                    966.97 
             VIBRATION                 VIBRATION                 VIBRATION 
         X       Y       Z         X       Y       Z         X       Y       Z
N     0.1181  0.0000  0.0000    0.0000  0.0000  0.3279    0.0000  0.2361  0.0000
C    -0.2535  0.0000  0.0000    0.0000 -0.1155 -0.0033    0.0000 -0.1841 -0.2383
C    -0.2535  0.0000  0.0000    0.0000  0.1155 -0.0033    0.0000 -0.1841  0.2383
H     0.6548  0.0000  0.0000    0.0000 -0.2702 -0.5999    0.0000  0.1950  0.5860
H     0.6548  0.0000  0.0000    0.0000  0.2702 -0.5999    0.0000  0.1950 -0.5860

                A2                        B2           
               976.13                   1142.74        
             VIBRATION                 VIBRATION       
         X       Y       Z         X       Y       Z   
N     0.0000  0.0000  0.0000    0.0000  0.5594  0.0000 
C     0.4152  0.0000  0.0000    0.0000 -0.2642  0.5038 
C    -0.4152  0.0000  0.0000    0.0000 -0.2642 -0.5038 
H    -0.5724  0.0000  0.0000    0.0000 -0.1309  0.0527 
H     0.5724  0.0000  0.0000    0.0000 -0.1309 -0.0527 

                      Normal modes in internal coordinates 
---------------------------------------------------------------------------
	*/
	while(fgets(line, 300, file) != NULL
		  && (notFound = strcmp(line,"                                   Normal Coordinates \n")) != 0) ;
 
	if(notFound) {
		fprintf(stderr, "Error reading ACES2 coordinates: unable to find initial coordinates\n");
		return 0;
	}
 
	/* Normal coordinates found.  Read two more header lines.  */
	if(!(fgets(line, 300, file) != NULL
	   && fgets(line, 300, file) != NULL)) {
		fprintf(stderr, "Error reading ACES2 coordinates\n");
		return 0;
	}
 
	/* Read normal coordinates */
	numFreqs = 0;
	err = fgets(line, 300, file);
	err = fgets(line, 300, file);
	while(err != NULL) {
		/* Count number of columns of data in current set of frequencies */
		numColumns = 0;
		p =	strtok(line, " \n\t");
		if(p && *p != ' ') {
			if(!isdigit(*p))  break;
			freqs[numFreqs+numColumns].value = strtod(p, &p2);
			if(p2 != NULL && *p2 == 'i') {
				freqs[numFreqs+numColumns].value = -freqs[numFreqs+numColumns].value;
			}
			numColumns++;
			while((p = strtok(NULL, " \n\t")) != NULL) {
				freqs[numFreqs+numColumns].value = strtod(p, &p2);
				if(p2 != NULL && *p2 == 'i') {
					freqs[numFreqs+numColumns].value = -freqs[numFreqs+numColumns].value;
				}
				numColumns++;
			}
		}
		if(numColumns <= 0) {
			fprintf(stderr, "Error reading ACES2 frequencies: unable to count columns\n");
			return 0;
		}

		/* Skip to top of vectors */
		if(!(fgets(line, 300, file) != NULL
		   && fgets(line, 300, file) != NULL)) {
			fprintf(stderr, "Error reading ACES2 coordinates\n");
			return 0;
		}

		for(atomIndex = 0; atomIndex < numAtoms; atomIndex++) {
				if(fscanf(file, "%*s") == EOF) {
					fprintf(stderr, "Error reading ACES2 frequencies: error on first line of atom %d\n", atomIndex);
					return 0;
				}
			for(i=0; i < numColumns; i++) {
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[atomIndex].x) == EOF) {
					fprintf(stderr, "Error reading ACES2 frequencies\n");
					return 0;
				}
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[atomIndex].y) == EOF) {
					fprintf(stderr, "Error reading ACES2 frequencies\n");
					return 0;
				}
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[atomIndex].z) == EOF) {
					fprintf(stderr, "Error reading ACES2 frequencies\n");
					return 0;
				}
			}
		}
		numFreqs += numColumns;

		/* Skip to next set of frequencies */
		err = fgets(line, 300, file);
		err = fgets(line, 300, file);
		err = fgets(line, 300, file);
		err = fgets(line, 300, file);
	}
	return numFreqs;
}

int aces2CountAtoms(FILE* file)
{
  char line[300];
  int numAtoms, notFound;
  int atomicNumber;

  numAtoms = 0; 
  notFound = 1;
  /* Find initial coordinates.  For example:
         -----------------------------------------------
         Cartesian coordinates corresponding to internal 
                 coordinate input (Bohr) 
 ----------------------------------------------------------------
 Z-matrix   Atomic            C o o r d i n a t e s
  Symbol    Number           X              Y              Z
 ----------------------------------------------------------------
     X         0         0.00000000     0.00000000     3.36831426
     N         7         0.00000000     0.00000000     1.47858773
     C         6         0.00000000     1.28781929    -0.73812957
     C         6         0.00000000    -1.28781929    -0.73812957
     H         1         0.00000000     3.22348136    -1.48322270
     H         1         0.00000000    -3.22348136    -1.48322270
 ----------------------------------------------------------------
  */
  while(fgets(line, 300, file) != NULL
	&& (notFound = strcmp(line," Z-matrix   Atomic            C o o r d i n a t e s\n")) != 0) ;
  
  if(notFound) {
    fprintf(stderr, "Error counting ACES2 atoms: unable to find initial coordinates\n");
    return 0;
  }
  
  /* Initial coordinates found.  Read two more header lines.  */
  if(!(fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL)) {
    fprintf(stderr, "Error counting ACES2 atoms\n");
    return 0;
  }
  
  /* Read atomic numbers and count atoms */
  while(fgets(line, 300, file) != NULL) {
    sscanf(line, "%s %d %*lf %*lf %*lf", line, &atomicNumber);
    if(strncmp(line, "--", 2) == 0) {
      /* End of coordinates reached */
      break;
    }
    /* Record only real atoms (e.g., skip dummy atoms) */
    if(atomicNumber > 0) {
      numAtoms++;
    }
  }
  return(numAtoms);
}

double g94ReadEnergy(FILE* file)
{
	char line[300];
	double energy;
	int notFound = 1;

	/* Search for SCF energy.  For example:
 SCF Done:  E(RHF) =  -284.418325039     A.U. after    1 cycles
	*/
	while(fgets(line, 300, file) != NULL
		  && (notFound = strncmp(line," SCF Done:", 10)) != 0) ;
	  
	if(notFound) {
	fprintf(stderr, "Error reading Gaussian94 energy: unable to find SCF energy\n");
		return 0.0;
	}
	sscanf(line, "%*s %*s %*s %*s %lf", &energy);
	return energy;
}

int g94ReadCoordinates(FILE* file, Atom* atoms)
{
  char line[300];
  char s1[30], s2[30], s3[30], s4[30];
  int i, j, k, numAtoms, notFound;
  double coor;
  
  numAtoms = 0; 
  notFound = 1;
 	/* Find initial coordinates. For example:
                   Standard orientation:
 ----------------------------------------------------------
 Center     Atomic              Coordinates (Angstroms)
 Number     Number             X           Y           Z
 ----------------------------------------------------------
    1          6           0.000000    0.000000    1.043880
    2          6           0.000000    1.215604    0.344031
    3          6           0.000000    1.191141   -1.037543
    4          6           0.000000    0.000000   -1.744922
    5          7           0.000000    0.000000    2.388568
    6          1           0.000000    2.146842    0.878573
    7          1           0.000000    2.128718   -1.564954
    8          1           0.000000    0.000000   -2.818815
    9          6           0.000000   -1.215604    0.344031
   10          6           0.000000   -1.191141   -1.037543
   11          1           0.000000   -2.146842    0.878573
   12          1           0.000000   -2.128718   -1.564954
 ----------------------------------------------------------
	*/
  while(fgets(line, 300, file) != NULL
	&& (notFound = strcmp(line,"                   Standard orientation:\n")) != 0) ;

  if(notFound) {
    fprintf(stderr, "Error reading Gaussian94 coordinates: unable to find initial coordinates\n");
    return 0;
  }
  
  /* Initial coordinates found.  Read four more header lines.  */
  if(!(fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL)) {
    fprintf(stderr, "Error reading Gaussian94 coordinates\n");
    return 0;
  }
  
  /* Read coordinates and count atoms */
  while(fgets(line, 300, file) != NULL) {
    sscanf(line, "%s %d %lf %lf %lf", line, &atoms[numAtoms].atomicNumber,
	   &atoms[numAtoms].x,
	   &atoms[numAtoms].y,
	   &atoms[numAtoms].z);
    if(strncmp(line, "--", 2) == 0) {
      /* End of coordinates reached */
      break;
    }
    /* Record only real atoms (e.g., skip dummy atoms) */
    if(atoms[numAtoms].atomicNumber > 0) {
      numAtoms++;
    }
  }
  return(numAtoms);
}

int g94ReadFrequencies(FILE* file, int numAtoms, Freq freqs[])
{
	char line[300];
	char valueLine[300];
	int atomIndex;
	int notFound = 1;
	int numFreqs;
	int numColumns;
	char* err;
	char* p;
	int i;

	/* Find normal coordinates. For example:
                     1                      2                      3
                    B1                     B2                     A2
 Frequencies --   251.6760               306.9127               496.9935
 Red. masses --     5.2279                 7.3813                 3.0687
 Frc consts  --     0.1951                 0.4097                 0.4466
 IR Inten    --     0.1737                 4.0142                 0.0000
 Raman Activ --     1.5230                 1.2659                 0.0383
 Depolar     --     0.7500                 0.7500                 0.7500
 Atom AN      X      Y      Z        X      Y      Z        X      Y      Z
   1   6    -0.12   0.00   0.00     0.00  -0.29   0.00     0.00   0.00   0.00
   2   6    -0.27   0.00   0.00     0.00  -0.19   0.11     0.22   0.00   0.00
   3   6    -0.01   0.00   0.00     0.00   0.00   0.16    -0.21   0.00   0.00
   4   6     0.28   0.00   0.00     0.00   0.07   0.00     0.00   0.00   0.00
                     4                      5                      6
                    A1                     B1                     B2
 Frequencies --   554.8730               560.1715               671.5923
 Red. masses --     8.4053                 2.9412                 6.3917
 Frc consts  --     1.5247                 0.5438                 1.6985
 IR Inten    --     1.4165                 8.4297                 0.2472
 Raman Activ --     4.8232                 0.0160                 3.7362
 Depolar     --     0.6340                 0.7500                 0.7500
 Atom AN      X      Y      Z        X      Y      Z        X      Y      Z
   1   6     0.00   0.00   0.31     0.30   0.00   0.00     0.00   0.14   0.00
   2   6     0.00  -0.21  -0.07     0.01   0.00   0.00     0.00   0.22   0.23
   3   6     0.00  -0.16  -0.14    -0.13   0.00   0.00     0.00  -0.24   0.25
   4   6     0.00   0.00  -0.37     0.19   0.00   0.00     0.00  -0.15   0.00

 -------------------
	*/
	while((err = fgets(line, 300, file)) != NULL
		  && (notFound = strncmp(line," Frequencies -- ", 16)) != 0) ;
 
	if(notFound) {
		fprintf(stderr, "Error reading Gaussian94 coordinates: unable to find initial coordinates\n");
		return 0;
	}

	/* Read normal coordinates */
	numFreqs = 0;
	while(err != NULL) {
		/* Count number of columns of data in current set of frequencies */
		numColumns = 0;
		p =	strtok(line, " \n\t");
		/* Skip first two tokens: "Frequencies", "--" */
		p =	strtok(NULL, " \n\t");
		p =	strtok(NULL, " \n\t");
		if(p && *p != ' ') {
		  if(isdigit(*p) || *p == '-') {
		    freqs[numFreqs+numColumns].value = atof(p);
		    numColumns++;
		    while((p = strtok(NULL, " \n\t")) != NULL) {
		      freqs[numFreqs+numColumns].value = atof(p);
		      numColumns++;
		    }
		  }
		}
		if(numColumns <= 0) {
			fprintf(stderr, "Error reading Gaussian94 frequencies: unable to count columns\n");
			return 0;
		}

		/* Skip to top of vectors */
		if(!(fgets(line, 300, file) != NULL
		   && fgets(line, 300, file) != NULL
		   && fgets(line, 300, file) != NULL
		   && fgets(line, 300, file) != NULL
		   && fgets(line, 300, file) != NULL
		   && fgets(line, 300, file) != NULL)) {
			fprintf(stderr, "Error reading Gaussian94 coordinates\n");
			return 0;
		}

		for(atomIndex = 0; atomIndex < numAtoms; atomIndex++) {
				if(fscanf(file, "%*d %*d") == EOF) {
					fprintf(stderr, "Error reading Gaussian94 frequencies: error on first line of atom %d\n", atomIndex);
					return 0;
				}
			for(i=0; i < numColumns; i++) {
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[atomIndex].x) == EOF) {
					fprintf(stderr, "Error reading Gaussian94 frequencies\n");
					return 0;
				}
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[atomIndex].y) == EOF) {
					fprintf(stderr, "Error reading Gaussian94 frequencies\n");
					return 0;
				}
				if(fscanf(file, "%lf", &freqs[numFreqs+i].coordinates[atomIndex].z) == EOF) {
					fprintf(stderr, "Error reading Gaussian94 frequencies\n");
					return 0;
				}
			}
		}
		numFreqs += numColumns;

		/* Skip to next set of frequencies */
	while((err = fgets(line, 300, file)) != NULL
		  && strncmp(line," Frequencies -- ", 16) != 0) ;
	}
	return numFreqs;
}

int g94CountAtoms(FILE* file)
{
  char line[300];
  int numAtoms, notFound;
  int atomicNumber;

  numAtoms = 0; 
  notFound = 1;
 	/* Find initial coordinates. For example:
                   Standard orientation:
 ----------------------------------------------------------
 Center     Atomic              Coordinates (Angstroms)
 Number     Number             X           Y           Z
 ----------------------------------------------------------
    1          6           0.000000    0.000000    1.043880
    2          6           0.000000    1.215604    0.344031
    3          6           0.000000    1.191141   -1.037543
    4          6           0.000000    0.000000   -1.744922
    5          7           0.000000    0.000000    2.388568
    6          1           0.000000    2.146842    0.878573
    7          1           0.000000    2.128718   -1.564954
    8          1           0.000000    0.000000   -2.818815
    9          6           0.000000   -1.215604    0.344031
   10          6           0.000000   -1.191141   -1.037543
   11          1           0.000000   -2.146842    0.878573
   12          1           0.000000   -2.128718   -1.564954
 ----------------------------------------------------------
	*/
  while(fgets(line, 300, file) != NULL
	&& (notFound = strcmp(line,"                   Standard orientation:\n")) != 0) ;
  
  if(notFound) {
    fprintf(stderr, "Error counting Gaussian94 atoms: unable to find initial coordinates\n");
    return 0;
  }
  
  /* Initial coordinates found.  Read four more header lines.  */
  if(!(fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL
       && fgets(line, 300, file) != NULL)) {
    fprintf(stderr, "Error counting Gaussian94 atoms\n");
    return 0;
  }
  
  /* Count atoms */
  while(fgets(line, 300, file) != NULL) {
    sscanf(line, "%s %d %*lf %*lf %*lf", line, &atomicNumber);
    if(strncmp(line, "--", 2) == 0) {
      /* End of coordinates reached */
      break;
    }
    /* Record only real atoms (e.g., skip dummy atoms) */
    if(atomicNumber > 0) {
      numAtoms++;
    }
  }
  return(numAtoms);
}

Modified: Wed Aug 13 16:00:00 1997 GMT
Page accessed 2135 times since Sat Apr 17 21:33:47 1999 GMT