|
/**********************************************************
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);
}
|