Chemistry::ESPT::Glog - Gaussian log file object.


Chemistry-ESPT documentation Contained in the Chemistry-ESPT distribution.

Index


Code Index:

NAME

Top

Chemistry::ESPT::Glog - Gaussian log file object.

SYNOPSIS

Top

   use Chemistry::ESPT::Glog;

   my $log = Chemistry::ESPT::Glog->new();

DESCRIPTION

Top

This module provides methods to quickly access data contained in a Gaussian log file. Guassian log files can only be read currently.

ATTRIBUTES

Top

All attributes are currently read-only and get populated by reading the assigned ESS file. Attribute values are accessible through the $Glog->get() method.

BASISLABELS

Rank two tensor containing the labels for each basis function.

C

A rank three tensor containing the NBASIS x NBASIS coefficient matrices. The coefficients correspond to Alpha or Beta depending upon what spin was passesd to $Glog->analyze().

COMPILE

Architecture for which the employed version of Gaussian was compiled.

COMPILEDATE

Date when the employed version of Gaussian was compiled.

EELEC

Electronic energy for the theory level employed.

ESCF

Array of SCF energies. This will be either the Hartree-Fock or the DFT energy.

EIGEN

A rank two tensor containing the eigenvalues. The eigenvalues correspond to Alpha or Beta depending upon what spin was passesd to $Glog->analyze().

ETHERM

Thermal corrections to energy.

EZPE

Current zero-point energy.

FUNCTIONAL

String containing the DFT functional utlized in this job.

GSOLV

Current Delta G of solvation.

GTHERM

Thermal corrections to G.

HOMO

Number corresponding to the highest occupied molecular orbital. The value corresponds to either Alpha or Beta electrons depending upon what spin was passesd to $Glog->analyze().

HTHERM

Thermal corrections to H.

KEYWORDS

Array containing Gaussian keywords used in this job.

LINK0

Array containing the Gaussian Link0 commands. Only the value passed to the Link0 command is stored. This data will be accessible via a Link0 method in future releases. The contents of the array positions are as follows:

0

%nproc or %nprocshared

1

%mem

2

%chk

3

%subst

4

%nproclinda or %lindaworkers

5

%save - stored as 1 if present, 0 otherwise

6

%nosave - stored as 1 if present, 0 otherwise

7

%kjob

8

%rwf

9

%int

10

%d2e

MOSYMM

A rank two tensor containing the symmmetry labels for each molecular orbital.

NCARTESIAN

Current number of Cartesian basis functions.

NPRIMITIVE

Current number of primitive Guassians in the basis set.

OCC

Rank two tensor containing the molecular orbital occupations.

OPTIMIZED

Flag indicating successful optimization (1). Defaults to 0.

PG

Array of molecular point group values.

REVISION

Gaussian revision label.

ROUTE

Gaussian route line

RUNTIME

Date when the calculation was run.

SADDLEPOINT

Current Saddle-point order. Ground states are order 0 and transition states are order 1.

SSQUARED

Array of <S**2> expectation values.

VERSION

Gaussian version.

METHODS

Top

Method parameters denoted in [] are optional.

$log->new()

Creates a new Glog object

$log->analyze(filename [spin])

Analyze the spin results in file called filename. Spin defaults to Alpha.

VERSION

Top

0.07

SEE ALSO

Top

Chemistry::ESPT::ESSfile, Chemistry::ESPT::Glib, http://www.gaussian.com

AUTHOR

Top

Dr. Jason L. Sonnenberg, <sonnenberg.11@osu.edu>

COPYRIGHT AND LICENSE

Top


Chemistry-ESPT documentation Contained in the Chemistry-ESPT distribution.
package Chemistry::ESPT::Glog;

use base qw(Chemistry::ESPT::ESSfile);
use Chemistry::ESPT::Glib 0.01;
use strict;
use warnings;

our $VERSION = '0.08';

## the object constructor **

sub new {
	my $invocant = shift;
	my $class = ref($invocant) || $invocant;
	my $log = Chemistry::ESPT::ESSfile->new();

	$log->{TYPE} = "log";

	# program info
	$log->{PROGRAM} = "Gaussian";
	$log->{VERSION} = undef;
	$log->{REVISION} = undef;
	$log->{COMPILE} = undef;
	$log->{COMPILEDATE} = undef;
	
	# Link 0 & Route commands
	$log->{LINK0} = [];
	$log->{KEYWORDS} = [];
	$log->{ROUTE} = undef;

	# calc info
	$log->{FUNCTIONAL} = undef;
	$log->{NPRIMITIVE} = undef;
	$log->{NCARTESIAN} = undef;
	$log->{OPTIMIZED} = undef;	# flag indicating successful optimization
	$log->{RUNTIME} = undef;
	
	# molecular info
	$log->{BASISLABELS} = [];
	$log->{C} = [];			# coefficient matrix
	$log->{EELEC} = undef;		# electronic energy for the current method
	$log->{ETHERM} = undef;		# Thermal corrections to E
	$log->{EIGEN} = [];
	$log->{EINFO} = "E(elec)";	# total energy description
	$log->{ESCF} = [];		# SCF electronic energy
	$log->{EZPE} = undef;		# ZPE
	$log->{GSOLV} = undef;		# Delta G of Solvation
	$log->{GTHERM} = undef;		# Thermal corrections to G
	$log->{HOMO} = undef;
	$log->{HTHERM} = undef;		# Thermal corrections to H
	$log->{MOSYMM} = [];
	$log->{SADDLEPOINT} = undef;	# Saddle-point Order
	$log->{OCC} =[];		# MO occupation info 
	$log->{PG} = [];
	$log->{SSQUARED} = [];		# S squared values

	bless($log, $class);
	return $log;
}


## methods ##

# set filename & spin then digest the file
sub analyze : method {
	my $log = shift;
	$log->prepare(@_);
	$log->_digest();
	return;
}


## subroutines ##
sub _digest {
# Files larger than 1Mb should be converted to binary and then
# processed to ensure maximum speed. -D. Ennis, OSC

# For items with multiple occurances, the last value is reported 

my $log = shift;

# flags & counters
my $Cflag = 0;
my $symmflag = 0;
my $rparsed = 0;
my $Sflag = 0;
my $Scount = 0;
my $Ccount = 0;
my $dcount = 0;
my $eigcount = 0;
my $Ecount = 0;
my $ESTATEcount = 0;
my $orbcount = -1;
my $MOcount = 0;
my $PGcount = 0;

# open filename for reading or display error
open(LOGFILE,$log->{FILENAME}) || die "Could not read $log->{FILENAME}\n$!\n";

# grab everything which may be useful
while (<LOGFILE>){
	# skip blank lines
	next if /^$/;

	# dashed line (signaling route, title, etc)
	if ( /^\s-{4,}$/ ) {
		++$dcount;
		next;
	}
	# parse route
	if ( $rparsed == 0 && $dcount >= 4 ){
		rparser($log);
		$rparsed = 1;
	}
        # version info
        if ( /^\s+Gaussian\s+([0-9DV]+):\s+([a-zA-Z0-9-]+)-G\1Rev([a-zA-Z]+\.[\d\+]+)\s+(\d{1,2}-[a-zA-Z]+-\d{4})\s*/ ) {
		$log->{VERSION} = $1;
              	$log->{REVISON} = $3;
               	$log->{COMPILE} = $2;
        	$log->{COMPILEDATE} = $4;
		next;
        }
        # run date
        if ( /^\s+(\d{1,2}-[a-zA-Z]+-\d{4})\s*/ ) {
        	$log->{RUNTIME} = $1;
		next;
	}
	# % commands
        if ( /^\s+\%nproc(?:shared)*=(\d+)/ ) {
		$log->{LINK0} [0] = $_;
		next;
	}
	if ( /^\s+\%mem=(\d+)/ ) { 
		$log->{LINK0} [1] = $1;
		next;
	}
	if ( /^\s+\%chk=(.+)/ ) { 
		$log->{LINK0} [2] = $1;
		next;
	}
	if ( /^\s+\%subst\s+(L.+)/ ) { 
		$log->{LINK0} [3] = $1;
		next;
	}
	if ( /^\s+\%(?:nproc)*linda(?:workers)*=(\d+)/ ) { 
		$log->{LINK0} [4] = $1;
		next;
	}
	if ( /^\s+\%save/ ) { 
		$log->{LINK0} [5] = 1;
		next;
	}
	if ( /^\s+\%nosave/ ) { 
		$log->{LINK0} [6] = 1;
		next;
	}
	if ( /^\s+\%kjob\s+(.+)/ ) { 
		$log->{LINK0} [7] = $1;
		next;
	}
	if ( /^\s+\%rwf=(.+)/ ) { 
		$log->{LINK0} [8] = $1;
		next;
	}
	if ( /^\s+\%int=(.+)/ ) { 
		$log->{LINK0} [9] = $1;
		next;
	}
	if ( /^\s+\%d2e=(.+)/ ) { 
		$log->{LINK0} [10] = $1;
		next;
	}
	# route card
	if ( /^\s(#\s*[\+\/a-zA-Z0-9\*=\(\-,\)\s]+)\Z/ ) {
		$log->{ROUTE} = lc($1);
		$log->{ROUTE}=~ s/\s+$//;
		next;
	}
	elsif ( /^\s([\+\/a-zA-Z0-9=\(\-,\)\s]+)\Z/ && $dcount == 3 ) {
		$log->{ROUTE} = $log->{ROUTE}.$1;
		$log->{ROUTE}=~ s/\s+$//;
		next;
	}
        # charge & multiplicity (multiple values and occurances)
        if ( /^\s+Charge\s+=\s+(-*\d+)\s+Multiplicity\s+=\s+(\d+)\s*/ ) {   
                $log->{CHARGE} = $1;
                $log->{MULTIPLICITY} = $2;
		next;
        }
        # full point group (multiple occurances)
        if ( /^\s+Full\s+point\s+group\s+([CDSIOT])([0-9DHISV\*]+)\s+.*/ ) {
		$log->{PG} [$PGcount] = "$1($2)";
		$PGcount++;
		next;
	}
        # basis functions (multiple occurances)
        if ( /^\s+(\d+)\s+basis functions,*\s+(\d+)\s+primitive gaussians,*\s*(\d+)*\s*(cartesian basis functions)*\s*/ ) {
		$log->{NBASIS} = $1;
                $log->{NPRIMITIVE} = $2;
		$log->{NCARTESIAN} = $3;
		next;
        }
        # electrons (multiple occurances)
	# figure HOMO & LUMO, alphas fill first
        if ( /^\s+(\d+)\s+alpha electrons\s+(\d+)\s+beta electrons/ ) {
                $log->{ALPHA} = $1;
                $log->{BETA} = $2;
		$log->{HOMO} = $log->{uc($log->{SPIN})};
		next;
        }
                                                                                                        
        # orbital symmetries (multiple occurances)
        if ( /^\s+Orbital (?i:S)ymmetries:\s*/ || /^\s+$log->{SPIN}\s+Orbitals:\s*/ ) {
		$symmflag = 1;
		$orbcount++;
		next;
	} 
        if ( $symmflag == 1 && /^\s+(\w*)\s+(?:\([123ABDEGHILMPSTU\?'"]{1,4}\)\s*){1,}$/ ) {
                (my $junk, my $tmp) = split /^\s+\w*/;
                $tmp =~ s/\s|\(//g;
                $tmp =~ tr/A-Z/a-z/;
                my @sym = split /\)/, $tmp;
		$orbcount++ if $orbcount == -1;  	# temporary hack
                for (my $i=0; $i<scalar(@sym); $i++) {
                        $log->{MOSYMM} [$orbcount] [$MOcount] = $sym[$i];
			$MOcount++;
                        $MOcount = $symmflag = 0 if ($MOcount == $log->{NBASIS} -1 && $log->{VERSION} eq "98");
                        $MOcount = $symmflag = 0 if $MOcount == $log->{NBASIS};
               }
                next;                                     
        }
	# SCF electronic energy (multiple occurances)
	if ( /^\s+SCF\s+Done:\s+.*\s+=\s+(-*\d+\.\d+)/ ) {
		$log->{ESCF} [$Ecount]= $1;
		$log->{EELEC} = $1;
		$log->{ENERGY} = $1;
		$Ecount++;
		next;
	}
	# <S^2> vlaue (multiple occurances)
	# generally not printed for closed shell theories
	if ( /^\s+.*?<*S\*\*2>*\s*=\s+(\d+\.\d+)/ ) {
		$log->{SSQUARED} [$Scount] = $1;
		$Scount++;
		next;
	}
	# Delta G of solvation (occurs each SCF cycle on SCRF jobs)
	if ( /^\s+DeltaG\s+\(solv\)\s+\(kcal\/mol\)\s+=\s+(-*\d+\.\d+)/ ) {
		$log->{GSOLV} = $1;
		next;
	}
	# Optimization completion
	if ( /^\s+Optimization\s+completed\./ ){
		$log->{OPTIMIZED} = 1;
		next;
	}
	# Electronic State (multiple occurances)
	if ( /^\s+The\s+electronic\s+state\s+is\s+(\d+-[123ABDEGHILMPSTU\?'"]{1,3})/ ) {
		$log->{ESTATE} [$ESTATEcount] = $1;
		$ESTATEcount++;
		next;
	}
        # eigenvalues
        if ( /^\s+$log->{SPIN}\s+([ocvirt]+\.)\s+eigenvalues\s+--\s+(?:-*\d+\.\d+\s*){1,}$/ ) {
		my $pop = $1;
                (my $junk,my $tmp) = split /^\s+$log->{SPIN}\s+\w+\.\s+eigenvalues\s+--\s+/;              
		$tmp =~ s/(\d)-(\d)/$1 -$2/;	# separate large negative eigenvalues 
		my @eig = split /\s+/, $tmp;
		$orbcount++ if $orbcount == -1;
                for (my $i=0; $i<scalar(@eig); $i++) {
                       	$log->{EIGEN} [$orbcount] [$eigcount] = $eig[$i];
			$log->{OCC} [$orbcount] [$eigcount] = $pop;
			$eigcount++;
                        $eigcount = 0 if ($eigcount == $log->{NBASIS}-1 && $log->{VERSION} eq "98");
                        $eigcount = 0 if $eigcount == $log->{NBASIS};
                }
		next;
        }
	# MO coeffients (square matrix, multiple occurances)
	if ( /\s+($log->{SPIN})*Molecular Orbital Coefficients/ ) {
		$Cflag = 1;
		$log->{C} = undef;
		next;
	}
	if ( $Cflag == 1 && /\s*(\d+)\s(\d+)\s*(\w+)\s+(\d+[A-Z]+\s?\-?\+?[0-9]*)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*/ ) {
		$log->{BASISLABELS}[$Ccount] = [$1, $2, $3, $4];
		push @{ $log->{C}[$Ccount] }, $5, $6, $7, $8, $9;
		$Ccount++;
		$Ccount = 0 if $Ccount == $log->{NBASIS};
		next;
	} elsif ( $Cflag == 1 && /\s*(\d+)\s*(\d+[A-Z]+\s?\-?\+?[0-9]*)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*(\-*\d+\.\d+)\s*/ ) {
              	$log->{BASISLABELS}[$Ccount] = [$1, $log->{BASISLABELS}[$Ccount - 1] [1], $log->{BASISLABELS}[$Ccount - 1] [2], $2];
		push @{ $log->{C}[$Ccount] }, $3, $4, $5, $6, $7;
               	$Ccount++;
               	$Ccount = 0 if $Ccount == $log->{NBASIS};
		next;
	}
	# density matrix
        if (/\s+DENSITY MATRIX./){
                $Cflag = 0;
		next;
        }
	# Saddle-point Order
	# appears only in freq runs that are not minima
	if ( /^\s+\*+\s+(\d+)\s+imaginary\sfrequencies\s\(negative\sSigns\)\s+\*+/ ){
		$log->{SADDLEPOINT} = $1;
		next;
	}
	# ZPE (frequency runs only)
	if ( /^\s+Zero-point\s+correction=\s+(-*\d*.\d+)/ ){
		$log->{EZPE} = $1;
		$log->{ENERGY} = $log->get("ESCF") + $log->{EZPE};
		$log->{EINFO} = "E(elec) + E(ZPE)";
		next;
	}
	# Thermal corrections to E (freq runs only)
	if ( /^\s+Thermal\scorrection\sto\sEnergy=\s+(\d\.\d+)/ ) {
		$log->{ETHERM} = $1;
		next;
	}
	# Thermal corrections to H (freq runs only)
	if ( /^\s+Thermal\scorrection\sto\sEnthalpy=\s+(\d\.\d+)/ ) {
		$log->{HTHERM} = $1;
		next;
	}
	# Thermal corrections to G (freq runs only)
	if ( /^\s+Thermal\scorrection\sto\sGibbs\sFree\sEnergy=\s+(\d\.\d+)/ ) {
		$log->{GTHERM} = $1;
		next;
	}
	# Successful Job completion
	if ( /^\s+Normal\s+termination\s+of\s+$log->{PROGRAM}/ ){
		$log->{COMPLETE} = 1;
		next;
	}
	# Calculation time stored as days, hours, minutes, seconds.
	# add code for tracking individual times.
	if ( /\s+Job\s+cpu\s+time:\s+(\d+)\s+days\s+(\d+)\s+hours\s+(\d+)\s+minutes\s+(\d+\.\d)\s+seconds/ ) {
		$log->{TIME} [0] = $1 + $log->{TIME} [0];
		$log->{TIME} [1] = $2 + $log->{TIME} [1];
		$log->{TIME} [2] = $3 + $log->{TIME} [2];
		$log->{TIME} [3] = $4 + $log->{TIME} [3];
		next;
	}
}

# Saddle-point Order for minima
if ( $log->get("JOBTYPE") =~ /FREQ/ && $log->{COMPLETE} == 1 ){
	$log->{SADDLEPOINT} = 0 unless defined $log->{SADDLEPOINT};
}

# C(1) symmetry label hack
if ( $log->{"PG"} eq "C(1)" ) {
	if ( $log->{VERSION} eq "98" ) {
		for (my $i=0; $i<$log->{NBASIS}-1; $i++) {
			$log->{MOSYMM} [0] [$i] = "a";
		}
	} else {
		for (my $i=0; $i<$log->{NBASIS}; $i++) {
			$log->{MOSYMM} [0] [$i] = "a";
		}
	}		
}
}

1;
__END__