package Chemistry::ESPT::ESSfile;
use strict;
use warnings;
=head1 NAME
Chemistry::ESPT::ESSfile - Generic Electronic Structure Suite (ESS) file object.
=head1 SYNOPSIS
package Chemistry::ESPT::MyFile;
use base qw(Chemistry::ESPT::ESSfile);
package Main;
my $object = Chemistry::ESPT::MyFile->new();
$object->prepare(filename);
=head1 DESCRIPTION
This module is the base class for all of the Electronic Structure Perl Toolkit (ESPT) ESS file objects. It provides the generic
attributes, methods, and subroutines common to all ESPT file objects.
=cut
our $VERSION = '0.03';
=begin comment
### Version History ###
0.01 consolidate common properties & methods
0.02 moved to ESPT namespace, Time property
0.03 generalized get method for Rank N tensors, added CHARGE,
### To Do ###
- Move ENERGY & EINFO attributes here
- Move TIME into its own method that automatically handles time addition
=end comment
=head1 ATTRIBUTES
All attributes are currently read-only and get populated by reading the assigned ESS file. Attribute values are
accessible through the B<get()> method unless otherwise noted.
=over 10
=item ALPHA
Total number of alpha electrons.
=item ATOMS
Array of atoms stored as atomic symbols. Array length equals NATOMS.
=item BASIS
String containing the basis set employed in the calculation.
=item BETA
Total number of beta electrons.
=item CHARGE
Total molecular charge.
=item COMPLETE
Flag indicating ESS job completion (1). Defaults to 0.
=item DEBUG
Debug flag enabling or disabling (0) verbose output. Useful when writing new code.
Defaults to 0. Accessible via the B<debug()> method.
=item EINFO
Text description of the energy contained in ENERGY.
=item ENERGY
Total energy as described by EINFO.
=item FILENAME
Full name of the file, including path if passed, assigned to the object.
=item JOBTYPE
ESS job type stored as capitalized keyword(s). Current keywords are:
=back
=over 10
=over 5
=over 10
=item SP
Single Point
=item OPT
Optimization
=item OPT FREQ
Optimization & Frequency
=item OPT SP
Optimization & Single Point
=item FREQ
Frequency
=back
=back
=back
=over 10
=item MULTIPLICITY
Molecular spin multiplicity, 2S+1.
=item NATOMS
Total number of atoms.
=item NBASIS
Total number of basis functions in the basis set.
=item PROGRAM
Full name of the ESS program
=item SPIN
Type of electrons, Alpha or Beta, to analyse.
=item THEORY
Theory level used in the calculation.
=item TITLE
ESS job title.
=item TIME
Total time for all calculations perfomed in the ESS file. Stored as an array with four elements, [days, hours, minutes, seconds].
=item TYPE
File type. This usually equal to the file's extension such as log, out, fchk, etc.
=back
=head1 METHODS
Method parameters denoted in [ ] are optional.
=over 15
=item B<$object-E<gt>new()>
Creates a new ESSfile object.
=cut
## the object constructor **
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $ESSfile = {};
# Generating ESS
$ESSfile->{PROGRAM} = undef;
# File type (log, out, fchk, etc.)
$ESSfile->{TYPE} = undef;
# Analysis info
$ESSfile->{DEBUG} = 0;
$ESSfile->{FILENAME} = undef;
$ESSfile->{SPIN} = undef;
# Calculation info
$ESSfile->{BASIS} = undef;
$ESSfile->{CHARGE} = undef; # total molecular charge
$ESSfile->{COMPLETE} = 0; # flag indicating job completion
$ESSfile->{EINFO} = undef; # string description of ENERGY
$ESSfile->{ENERGY} = undef; # total energy
$ESSfile->{JOBTYPE} = undef; # type of calculation performed
$ESSfile->{MULTIPLICITY} = undef; # 2S+1
$ESSfile->{NBASIS} = undef;
$ESSfile->{THEORY} = undef;
$ESSfile->{TIME} = [ 0, 0, 0, 0 ]; # Total computation time in days [0], hours [1], minutes [2], seconds [3]
$ESSfile->{TITLE} = undef;
# Molecular info
$ESSfile->{ALPHA} = undef;
$ESSfile->{ATOMS} = undef;
$ESSfile->{BETA} = undef;
$ESSfile->{NATOMS} = undef;
bless($ESSfile, $class);
return $ESSfile;
}
### Methods ###
=item B<$object-E<gt>prepare(filename [spin])>
Set FILENAME, and SPIN. SPIN defaults to Alpha.
=cut
# set filename, spin, & debug options
sub prepare : method {
my $ESSfile = shift;
$ESSfile->{FILENAME} = shift;
$ESSfile->{SPIN} = shift;
$ESSfile->{SPIN} ||= "Alpha";
return;
}
=item B<$object-E<gt>atomconvert(atom)>
Convert atomic symbols to atomic numbers and vice versa. Atom must
be a valid atomic symbol or number.
=cut
# Convert atomic numbers to atomic symbols
sub atomconvert : method {
shift; # remove object reference
my (@num2sym, %sym2num);
#populate atomic symbols
@num2sym = ("H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne");
push @num2sym, ("Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar");
push @num2sym, ("K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr");
push @num2sym, ("Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe");
push @num2sym, ("Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu");
push @num2sym, ("Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn");
push @num2sym, ("Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr");
push @num2sym, ("Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Uub", "Uut", "Uuq", "Uup");
for (my $i=0; $i<scalar(@num2sym); $i++){
$sym2num{$num2sym[$i]} = $i+1;
}
$sym2num{D} = $sym2num{T} = 1;
my $value = shift;
# determine what was passed and return the opposite
if ( $value =~ /^[a-zA-Z]+\Z/ ){
return $sym2num{$value};
} else {
if ( $value <= $#num2sym ) {
return $num2sym[$value - 1];
} else {
return $value;
}
}
}
=item B<$object-E<gt>debug([debuglevel])>
Set or retrieve the DEBUG attribute. Passing a debuglevel equal to 1 enables standard debug
printing. Verbose debug printing can be enabled by passing integers greater than one.
=cut
sub debug : method {
my $ESSfile = shift;
my $debug = shift;
if (defined $debug && $debug =~ /\d+/ ) {
$ESSfile->{DEBUG} = $debug;
return;
} else {
return $ESSfile->{DEBUG};
}
}
=item B<$object-E<gt>get(attribute [index1] [index2] ... [indexN])>
Get attribute data stored in an N dimensional tensor. If the tensor indicies are
not passed, then the last value for that attribute will be passesd. If a requested
attribute is not present, then a null string is returned. If the requested datum is
not present then undef will be returned as a string.
=cut
# retrieve values. for array data the last element is returned
# unless otherwise requested
sub get : method {
my $ESSfile = shift;
# required parameters : value
my $value = shift;
print "Get method called for ", $value, "\n" if $ESSfile->{DEBUG} >= 4;
# optional parameters : index values
my @index = @_;
# warn if requested property is not coded & return empty string
my $valid = 0;
foreach my $p ( keys %$ESSfile ) {
if ( $value eq $p ) {
$valid = 1;
last;
} elsif ( $value eq "DEBUG" ) {
$valid = 2;
last;
}
}
if ( $valid == 0 ) {
warn "Requested property, $value, is not currently coded.\n$!\n" if $ESSfile->{DEBUG} == 1;
return "";
} elsif ( $valid ==2 ) {
warn "Please use the debug() method to access the DEBUG attribute.\n$!\n";
return "";
}
# build hard reference
my $reference = \$ESSfile->{$value};
# undef if no scalar value is present
return "undef" unless ( defined $ESSfile->{$value} );
# check for multidimensional array in a nested
# manner to avoid autovivification problems.
my $i =0;
while ( ref $$reference eq "ARRAY" ) {
# get array length
$index [$i] ||= scalar(@{$$reference}) - 1 unless ( defined $index[$i] );
return "undef" unless ( defined @{$$reference} [$index[$i]] );
# update reference
$reference = \@{$$reference} [$index[$i]];
return $$reference unless ( ref $$reference eq "ARRAY" );
$i++;
}
# scalar values
return $$reference;
}
=item B<$object-E<gt>MOdecoder(MO)>
Return the molecular orbital number for the requested MO. MO may be HOMO, LUMO or SHOMO.
=cut
# decode homo, shomo & lumo
# correct for arrays starting with 0
sub MOdecoder : method {
my $ESSfile = shift;
my $MO = lc(shift);
if ($MO eq "homo") {
return $ESSfile->{HOMO} - 1;
} elsif ($MO eq "lumo") {
return $ESSfile->{HOMO};
} elsif ($MO eq "shomo") {
return $ESSfile->{HOMO} - 2;
} else {
return $MO - 1;
}
}
### Utilities ###
sub printattributes : method {
# print out object attributes
my $ESSfile = shift;
foreach my $p ( sort keys %$ESSfile ) {
print "$p\n";
}
}
1;
__END__
=back
=head1 VERSION
0.03
=head1 AUTHOR
Dr. Jason L. Sonnenberg, E<lt>sonnenberg.11@osu.eduE<gt>
=head1 COPYRIGHT
Copyright 2008 by Dr. Jason L. Sonnenberg
This module is free software; you can redistribute it and/or modify
it under the same terms as Perl itself. I would like to hear of any
suggestions for improvement.
=cut