File Coverage

blib/lib/Chemistry/ESPT/Gfchk.pm
Criterion Covered Total %
statement 46 325 14.1
branch 0 136 0.0
condition 1 45 2.2
subroutine 5 8 62.5
pod 2 3 66.6
total 54 517 10.4


line stmt bran cond sub pod time code
1             package Chemistry::ESPT::Gfchk;
2              
3 1     1   22401 use base qw(Chemistry::ESPT::ESSfile);
  1         3  
  1         606  
4 1     1   1455 use Chemistry::ESPT::Glib 0.01;
  1         37  
  1         90  
5 1     1   5 use strict;
  1         2  
  1         31  
6 1     1   5 use warnings;
  1         1  
  1         3662  
7              
8             =head1 NAME
9              
10             Chemistry::ESPT::Gfchk - Gaussian formatted checkpoint file object.
11              
12             =head1 SYNOPSIS
13              
14             use Chemistry::ESPT::Gfchk;
15              
16             my $fchk = Chemistry::ESPT::Gfchk->new();
17              
18             =head1 DESCRIPTION
19              
20             This module provides methods to quickly access data contained in a Gaussian
21             formatted checkpoint file. Guassian formatted checkpoint files can
22             only be read currently.
23              
24             =begin comment
25              
26             ### Version History ###
27             0.01 digest opt freq fchk files
28             0.02 use ESPT namespace
29             use Chemistry::ESPT::Glib module; redundant internal
30             coordinates, gradient and H; SCF and total energies
31             0.03 redundant internal gradient & Hessian
32              
33             ### NOTE ###
34             Gaussian stores all values in a.u. and standard orientation in the fchk file
35              
36             Distance = bohrs
37             Energy = hartree
38             Gradient = hartree/bohr
39             Hessian = hartree/bohr^2
40              
41             ### To Do ###
42             -Store only lower triangle of square matrices and
43             have the get or accessor method return upper triangle as requested.
44             -Ability to disable multiple value collection
45             -ONIOM data
46             -Digest scan data
47            
48             =end comment
49              
50             =cut
51              
52             our $VERSION = '0.03';
53              
54              
55             =head1 ATTRIBUTES
56              
57             All attributes are currently read-only and get populated by reading the assigned ESS file. Attribute values
58             are accessible through the B<$Gfchk-Eget()> method.
59              
60             =over 15
61              
62             =item C
63              
64             NBASIS x NBASIS coefficient matrix. The coefficients correspond to Alpha or
65             Beta depending upon what spin was passesd to B<$Gfchk-Eanalyze()>.
66              
67             =item CARTCOORD
68              
69             NATOMS x 3 matrix containing the current Cartesian coordinates
70              
71             =item EELEC
72              
73             Electronic energy for the theroy level employed.
74              
75             =item ESCF
76              
77             SCF energy. This will be either the Hartree-Fock or the DFT energy. See Gaussian documentation
78             for more information.
79              
80             =item EIGEN
81              
82             Array with length NBASIS, containing the eigenvalues. The eigenvalues correspond to Alpha or
83             Beta depending upon what spin was passesd to B<$Gfchk-Eanalyze()>.
84              
85             =item FUNCTIONAL
86              
87             String containing the DFT functional utlized in this job.
88              
89             =item GRADIENT
90              
91             Array containing the Cartesian gradients.
92              
93             =item HESSIAN
94              
95             Lower-triangular matrix containing the Cartesian Hessian.
96              
97             =item HOMO
98              
99             Number corresponding to the highest occupied molecular orbital. The value corresponds
100             to either Alpha or Beta electrons depending upon what spin was passesd to
101             B<$Gfchk-Eanalyze()>.
102              
103             =item IRCCOORD
104              
105             A rank three tensor containing Cartesian coordinates for each IRC geometry.
106              
107             =item IRCENERGY
108              
109             Array, with length IRCPOINTS, containing the electronic energy at each IRC geometry.
110              
111             =item IRCGRADIENT
112              
113             Cartesian gradients for each IRC geometry stored as a rank two tensor.
114              
115             =item IRCPOINTS
116              
117             Total number of IRC steps.
118              
119             =item IRCSTEP
120              
121             Array of reaction coordinate values for each IRC step.
122              
123             =item KEYWORDS
124              
125             Array containing Gaussian keywords used in this job.
126              
127             =item MASS
128              
129             Array with length NATOMS, containing the atomic masses.
130              
131             =item NREDINT
132              
133             Total number of redundant internal coordinates.
134              
135             =item REDINTANGLE
136              
137             Number of redundant internal angles.
138              
139             =item REDINTBOND
140              
141             Number of redundant internal bonds.
142              
143             =item REDINTCOORD
144              
145             NREDINT x 4 matrix containing the redundant internal coordinates. Each coordinate
146             is defined by four integers corresponding to the atom numbers. Bond coordinates
147             have zeros in columns 3 & 4. Bond angle coordinates have a zero in column 4.
148              
149             =item REDINTDIHEDRAL
150              
151             Number of redundant internal dihedrals.
152              
153             =item REDINTGRADIENT
154              
155             Array containing the redundant internal gradient.
156              
157             =item REDINTHESSIAN
158              
159             Lower-triangular matrix containing the redundant internal Hessian.
160              
161             =item ROUTE
162              
163             Gaussian route line
164              
165             =item SSQUARED
166              
167             expectation value.
168              
169             =back
170              
171             =head1 METHODS
172              
173             Method parameters denoted in [] are optional.
174              
175             =over 15
176              
177             =item B<$fchk-Enew()>
178              
179             Creates a new Gfchk object
180              
181             =cut
182              
183             ## the object constructor **
184              
185             sub new {
186 1     1 1 12 my $invocant = shift;
187 1   33     10 my $class = ref($invocant) || $invocant;
188 1         8 my $fchk = Chemistry::ESPT::ESSfile->new();
189              
190 1         6 $fchk->{PROGRAM} = "Gaussian";
191 1         3 $fchk->{TYPE} = "fchk";
192              
193             # Link 0 & Route commands
194 1         2 $fchk->{ROUTE} = undef;
195 1         16 $fchk->{KEYWORDS} = [];
196              
197             # calc info
198 1         3 $fchk->{FUNCTIONAL} = undef;
199              
200             # IRC data
201 1         2 $fchk->{IRCCOORD} = []; # Coordinates for each IRC Geometry
202 1         3 $fchk->{IRCENERGY} = []; # Energy at each IRC Geometry
203 1         2 $fchk->{IRCSTEP} = []; # Reaction coordinate value at each IRC step
204 1         2 $fchk->{IRCGRADIENT} = []; # Gradient at each IRC Geometry
205 1         2 $fchk->{IRCPOINTS} = 0; # Total number of IRC Geometries
206              
207             # molecular info
208 1         2 $fchk->{C} = []; # coefficient matrix
209 1         2 $fchk->{CARTCOORD} = []; # Current cartesian coordinates
210 1         2 $fchk->{CHARGE} = undef;
211 1         2 $fchk->{EIGEN} = [];
212 1         3 $fchk->{EELEC} = undef; # electronic energy
213 1         2 $fchk->{ESCF} = undef; # SCF energy
214 1         2 $fchk->{EINFO} = "E(elec)"; # total energy description
215 1         2 $fchk->{GRADIENT} = [];
216 1         2 $fchk->{HESSIAN} = []; # lower triangle only
217 1         2 $fchk->{HOMO} = undef;
218 1         2 $fchk->{MASS} = undef; # atomic masses
219 1         1 $fchk->{NREDINT} = 0; # number of red. internals
220 1         2 $fchk->{REDINTANGLE} = 0; # Redundant internal angles
221 1         2 $fchk->{REDINTBOND} = 0; # Redundant internal bonds
222 1         2 $fchk->{REDINTCOORD} = []; # Redundant internal coordinates
223 1         2 $fchk->{REDINTDIHEDRAL} = 0; # Redundant internal dihedrals
224 1         2 $fchk->{REDINTGRADIENT} = []; # Redundant internal gradient
225 1         2 $fchk->{REDINTHESSIAN} = []; # Redundant internal hessian
226 1         2 $fchk->{SSQUARED} = []; #
227              
228 1         3 bless($fchk, $class);
229 1         3 return $fchk;
230             }
231              
232              
233             ## methods ##
234              
235             =item B<$fchk-Eanalyze(filename [spin])>
236            
237             Analyze the spin results in file called filename. Spin defaults to Alpha.
238              
239             =cut
240              
241             # set filename & spin then digest the file
242             sub analyze : method {
243 0     0 1   my $fchk = shift;
244 0           $fchk->prepare(@_);
245 0           $fchk->_digest();
246 0           return;
247             }
248              
249              
250             ## subroutines ##
251              
252             sub _digest {
253              
254 0     0     my $fchk = shift;
255              
256             # flags & counters
257 0           my $atomflag = 0;
258 0           my $atomtot = 0;
259 0           my $cartflag = 0;
260 0           my $carttot = 0;
261 0           my $col = 0;
262 0           my $counter = 0;
263 0           my $eigenflag = 0;
264 0           my $eigentot = 0;
265 0           my $geomcount = 0;
266 0           my $gradientflag = 0;
267 0           my $hessflag = 0;
268 0           my $hesstot = 0;
269 0           my $irccoord = 0;
270 0           my $ircdata = 0;
271 0           my $ircflag = 0;
272 0           my $ircgeomflag = 0;
273 0           my $ircgradientflag = 0;
274 0           my $ircresults = 0;
275 0           my $ircresultsflag = 0;
276 0           my $redinttot = 0;
277 0           my $redintflag = 0;
278 0           my $redintgradientflag = 0;
279 0           my $redinthessflag = 0;
280 0           my $redinthesstot = 0;
281 0           my $row = 0;
282 0           my $rparsed = 0;
283 0           my $Titleflag = 0;
284 0           my $Cflag = 0;
285 0           my $weightflag = 0;
286              
287             # open filename for reading or display error
288 0 0         open(FCHKFILE,$fchk->{FILENAME}) || die "Could not read $fchk->{FILENAME}\n$!\n";
289              
290             # quick check for IRC data since IRC data ends up at
291             # the end of the fchk file. This is not the most
292             # elegant way to do this, but works for now. -JLS
293 0           while () {
294             # skip blank lines
295 0 0         next if /^$/;
296              
297             # check for IRC data and get # of IRC points
298             # grow IRC arrays according to results
299             # remember that arrays indices start at 0
300 0 0         if ( /^IRC\sNumber\sof\sgeometries\s+I\s+N=\s+\d+/ ) {
301 0           $ircflag = 1;
302 0           next;
303             }
304 0 0 0       if ( $ircflag == 1 && /^\s+(\d+)/ ) {
305 0           $ircflag = 0;
306 0           $fchk->{IRCPOINTS} = $1;
307 0           $#{$fchk->{IRCCOORD}} = $1 - 1;
  0            
308 0           $#{$fchk->{IRCGRADIENT}} = $1 - 1;
  0            
309 0           last;
310             }
311             }
312              
313             # rewind file
314 0           seek(FCHKFILE, 0, 0);
315              
316             # grab everything which may be useful
317 0           while (){
318             # skip blank lines
319 0 0         next if /^$/;
320              
321             # title which is the first line
322             # only the first 72 characters are present as of G03
323 0 0         if ( $Titleflag == 0 ) {
324 0           chomp($_);
325 0           s/\s+$//;
326 0           $fchk->{TITLE} = $_;
327 0           $Titleflag = 1;
328 0           next;
329             }
330             # Job Type, Method, & Basis
331 0 0 0       if ( $rparsed == 0 && /^[SPOFIRCMADBVGa-z=]+/ ){
332 0           chomp($fchk->{ROUTE} = lc($_));
333 0           rparser($fchk);
334 0           $rparsed = 1;
335 0           next;
336             }
337             # Number of Atoms
338 0 0         if ( /^Number\s+of\s+atoms\s+I\s+(\d+)/ ) {
339 0           $fchk->{NATOMS} = $1;
340 0           next;
341             }
342             # charge
343 0 0         if ( /^Charge\s+I\s+(-*\d+)/ ) {
344 0           $fchk->{CHARGE} = $1;
345 0           next;
346             }
347             # multiplicity
348 0 0         if ( /^Multiplicity\s+I\s+(\d+)/ ) {
349 0           $fchk->{MULTIPLICITY} = $1;
350 0           next;
351             }
352             # electrons
353             # figure HOMO & LUMO, alphas fill first
354 0 0         if ( /^Number\s+of\s+alpha\s+electrons\s+I\s+(\d+)/ ) {
355 0           $fchk->{ALPHA} = $1;
356 0           next;
357             }
358 0 0         if ( /^Number\s+of\s+beta\s+electrons\s+I\s+(\d+)/ ) {
359 0           $fchk->{BETA} = $1;
360 0           next;
361             }
362             # basis functions
363 0 0         if ( /^Number\s+of\s+basis\s+functions\s+I\s+(\d+)/ ) {
364 0           $fchk->{NBASIS} = $1;
365 0           next;
366             }
367             # SCF energy
368 0 0         if ( /^SCF\s+Energy\s+R\s+(-*\d+\.\d+E-*\+*\d{2,})/ ) {
369 0           $fchk->{ESCF} = $1;
370 0           next;
371             }
372             # Total electronic energy
373 0 0         if ( /^Total\s+Energy\s+R\s+(-*\d+\.\d+E-*\+*\d{2,})/ ) {
374 0           $fchk->{EELEC} = $1;
375 0           $fchk->{ENERGY} = $1;
376 0           next;
377             }
378             # ; use 2D array to conform with other ESPT modules
379 0 0         if ( /^S\*\*2\s+R\s+(\d\.\d+E\+\d{2,})/ ) {
380 0           $fchk->{SSQUARED} [0] = $1;
381 0           next;
382             }
383             # Atoms; stored as atomic numbers
384 0 0         if ( /^Atomic\s+numbers\s+I\s+N=\s+(\d+)/ ) {
385 0           $atomtot = $1;
386 0           $atomflag = 1;
387 0           $counter = 0;
388 0           next;
389             }
390 0 0 0       if ( $atomflag == 1 && /^\s+((?:\d+\s+){1,6})/ ) {
391 0           my @atomnum = split /\s+/, $1;
392 0           for (my $i=0; $i
393 0           $fchk->{ATOMS} [$counter] = $fchk->atomconvert($atomnum[$i]);
394 0           $counter++;
395 0 0         $atomflag = 0 if $counter == $atomtot;
396             }
397 0           next;
398             }
399             # Redundant internal coordinates
400             # not present for all calculations
401 0 0         if ( /^Number\sof\sredundant\sinternal\sbonds\s+I\s+(\d+)/ ) {
402 0           $fchk->{REDINTBOND} = $1;
403 0           $fchk->{NREDINT} = $1;
404 0           next;
405             }
406 0 0         if ( /^Number\sof\sredundant\sinternal\sangles\s+I\s+(\d+)/ ) {
407 0           $fchk->{REDINTANGLE} = $1;
408 0           $fchk->{NREDINT} = $fchk->{NREDINT} + $1;
409 0           next;
410             }
411 0 0         if ( /^Number\sof\sredundant\sinternal\sdihedrals\s+I\s+(\d+)/ ) {
412 0           $fchk->{REDINTDIHEDRAL} = $1;
413 0           $fchk->{NREDINT} = $fchk->{NREDINT} + $1;
414 0           next;
415             }
416 0 0         if ( /^Redundant\sinternal\scoordinate\sindices\s+I\s+N=\s+(\d+)/ ) {
417 0           $redinttot= $1;
418 0           $redintflag = 1;
419 0           $counter=0;
420 0           next;
421             }
422 0 0 0       if ( $redintflag == 1 && /^\s+((?:-*\d+\s+){1,6})/ ) {
423 0           my @ints = split /\s+/, $1;
424 0           for (my $i=0; $i
425 0           push @{$fchk->{REDINTCOORD} [$counter] }, $ints[$i];
  0            
426 0 0         $counter++ if $#{$fchk->{REDINTCOORD} [$counter]} == 3;
  0            
427 0 0         $redintflag = 0 if $counter*4 == $redinttot;
428             }
429 0           next;
430             }
431             # current cartesian coordinates
432             # store in an N x 3 array
433 0 0         if ( /^Current\s+cartesian\s+coordinates\s+R\s+N=\s+(\d+)/ ) {
434 0           $carttot = $1;
435 0           $cartflag = 1;
436 0           $counter = 0;
437 0           next;
438             }
439 0 0 0       if ( $cartflag == 1 && /^\s+((?:-*\d\.\d+E[-\+]\d{2,}\s+){1,5})/ ) {
440 0           my @carts = split /\s+/, $1;
441 0           for (my $i=0; $i
442 0           push @{ $fchk->{CARTCOORD} [$counter] }, $carts[$i];
  0            
443 0 0         $counter++ if $#{$fchk->{CARTCOORD} [$counter]} == 2;
  0            
444 0 0         $cartflag = 0 if $counter*3 == $carttot;
445             }
446 0           next;
447             }
448             # Real atomic weights
449 0 0         if ( /Real\s+atomic\s+weights\s+R\s+N=\s+(\d+)$/ ) {
450 0           $weightflag = 1;
451 0           $counter = 0;
452 0           next;
453             }
454 0 0 0       if ( $weightflag ==1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
455 0           my @weights = split /\s+/, $1;
456 0           for (my $i=0; $i
457 0           $fchk->{MASS} [$counter] = $weights[$i];
458 0           $counter++;
459 0 0         $weightflag = 0 if $counter == $fchk->{NATOMS};
460             }
461 0           next;
462             }
463             # Eigenvalues; occur only once per spin
464             # must still use 2D array to stay in line with other ESPT modules
465 0 0         if ( /^$fchk->{SPIN}\s+Orbital\s+Energies\s+R\s+N=\s+(\d+)$/ ) {
466 0           $eigentot = $1;
467 0           $eigenflag = 1;
468 0           $counter = 0;
469 0           next;
470             }
471 0 0 0       if ( $eigenflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/) {
472 0           my @eig = split /\s+/, $1;
473 0           for (my $i=0; $i
474 0           $fchk->{EIGEN} [0] [$counter] = $eig[$i];
475 0           $counter++;
476 0 0         $eigenflag = 0 if $counter == $eigentot;
477             }
478 0           next;
479             }
480             #Fix # MO coeffients (square matrix, multiple occurances)
481             # if ( /\s+($fchk->{SPIN})*Molecular Orbital Coefficients/ ) {
482             # $Cflag = 1;
483             # $fchk->{C} = undef;
484             # $counter = 0;
485             # next;
486             # }
487             # 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*/ ) {
488             # $fchk->{BASISLABELS}[$counter] = [$1, $2, $3, $4];
489             # push @{ $fchk->{C}[$counter] }, $5, $6, $7, $8, $9;
490             # $counter++;
491             # $counter = 0 if $counter == $fchk->{NBASIS};
492             # next;
493             # } 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*/ ) {
494             # $fchk->{BASISLABELS}[$counter] = [$1, $fchk->{BASISLABELS}[$counter - 1] [1], $fchk->{BASISLABELS}[$counter - 1] [2], $2];
495             # push @{ $fchk->{C}[$counter] }, $3, $4, $5, $6, $7;
496             # $counter++;
497             # $counter = 0 if $counter == $fchk->{NBASIS};
498             # next;
499             # }
500             # Cartesian Gradient (3*NATOMS x 1 vector)
501 0 0         if ( /Cartesian\s+Gradient\s+R\s+N=\s+(\d+)$/ ) {
502 0           $gradientflag = 1;
503 0           $counter = 0;
504 0           next;
505             }
506 0 0 0       if ( $gradientflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
507 0           my @gradients = split /\s+/, $1;
508 0           for (my $i=0; $i
509 0           $fchk->{GRADIENT} [$counter] = $gradients[$i];
510 0           $counter++;
511 0 0         $gradientflag = 0 if $counter == 3*$fchk->{NATOMS};
512             }
513 0           next;
514             }
515             # Redundant internal Gradient (NREDINT x 1 vector)
516 0 0         if ( /Redundant\s+Internal\s+Gradient\s+R\s+N=\s+(\d+)$/ ) {
517 0           $redintgradientflag = 1;
518 0           $counter = 0;
519 0           next;
520             }
521 0 0 0       if ( $redintgradientflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
522 0           my @redintgradients = split /\s+/, $1;
523 0           for (my $i=0; $i
524 0           $fchk->{REDINTGRADIENT} [$counter] = $redintgradients[$i];
525 0           $counter++;
526 0 0         $redintgradientflag = 0 if $counter == $fchk->{NREDINT};
527             }
528 0           next;
529             }
530             # Cartesian Hessian
531             # 3*NATOMS x 3*NATOMS matrix delivered as a lower
532             # triangular matrix (3*NATOMS)(3*NATOMS+1)(1/2) elements
533 0 0         if ( /Cartesian\s+Force\s+Constants\s+R\s+N=\s+(\d+)$/ ) {
534 0           $hesstot = $1;
535 0           $hessflag = 1;
536 0           $counter = $row = $col = 0;
537 0           next;
538             }
539 0 0 0       if ( $hessflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
540 0           my @hessian = split /\s+/, $1;
541 0           for (my $i=0; $i
542 0           $fchk->{HESSIAN} [$row] [$col] = $hessian[$i];
543 0 0         $fchk->{HESSIAN} [$col] [$row] = $hessian[$i] unless $row == $col;
544 0           $counter++;
545 0 0         if ( $row == $col ) {
546 0           $col++;
547 0           $row = -1;
548             }
549 0           $row++;
550 0 0         $hessflag = 0 if $counter == $hesstot;
551             }
552 0           next;
553             }
554             # Redundant internal Hessian
555             # NREDINT X NREDINT matrix delivered as a lower
556             # triangular matrix (NREDINT)(NREDINT+1)(1/2) elements
557 0 0         if ( /Redundant\s+Internal\s+Force\s+Constants\s+R\s+N=\s+(\d+)$/ ) {
558 0           $redinthesstot = $1;
559 0           $redinthessflag = 1;
560 0           $counter = $row = $col = 0;
561 0           next;
562             }
563 0 0 0       if ( $redinthessflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
564 0           my @redinthessian = split /\s+/, $1;
565 0           for (my $i=0; $i
566 0           $fchk->{REDINTHESSIAN} [$row] [$col] = $redinthessian[$i];
567 0 0         $fchk->{REDINTHESSIAN} [$col] [$row] = $redinthessian[$i] unless $row == $col;
568 0           $counter++;
569 0 0         if ( $row == $col ) {
570 0           $col++;
571 0           $row = -1;
572             }
573 0           $row++;
574 0 0         $redinthessflag = 0 if $counter == $redinthesstot;
575             }
576 0           next;
577             }
578             # IRC data per geom
579 0 0         if ( /^IRC\sNum\sresults\sper\sgeometry\s+I\s+(\d+)/ ) {
580 0           $ircresults = $1;
581 0           next;
582             }
583             # IRC # of coordinates
584 0 0         if ( /^IRC\sNum\sgeometry\svariables\s+I\s+(\d+)/ ) {
585 0           $irccoord = $1;
586 0           next;
587             }
588             # IRC energy and step value
589             # These steps are sequential and proceed either
590             # forward or backward from the TS which is 0.0
591             # along the IRC. Energies come first followed by
592             # the cooresponging IRC value. Currently all IRC
593             # values are given as positive regardless of whether
594             # the displacement is towards products or reactants.
595 0 0         if ( /^IRC\spoint\s+\d+\sResults\sfor\seach\sgeom.*\s+R\s+N=\s+\d+/ ) {
596 0           $ircresultsflag = 1;
597 0           $counter = 0;
598 0           next;
599             }
600 0 0 0       if ( $ircresultsflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
601 0           my @results = split /\s+/, $1;
602 0           for (my $i=0; $i
603 0           $counter++;
604             # use modulo math to determine if this is an energy or step value
605 0 0         if ( $counter % 2 ) {
606 0           push(@{$fchk->{IRCENERGY}}, $results[$i]);
  0            
607             } else {
608 0           push(@{$fchk->{IRCSTEP}}, $results[$i]);
  0            
609              
610             }
611             }
612 0 0         $ircresultsflag = 0 if $counter == $ircresults * $fchk->{IRCPOINTS};
613 0           next;
614             }
615             # IRC geometries
616 0 0         if ( /^IRC\spoint\s+\d+\sGeometries\s+R\s+N=\s+\d+/ ) {
617 0           $ircgeomflag = 1;
618 0           $geomcount = 0;
619 0           $counter = 0;
620 0           next;
621             }
622 0 0 0       if ( $ircgeomflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
623 0           my @coords = split /\s+/, $1;
624 0           for (my $i=0; $i
625 0           push @{ $fchk->{IRCCOORD} [$geomcount] [$counter] }, $coords[$i];
  0            
626 0 0         $counter++ if $#{$fchk->{IRCCOORD}[$geomcount] [$counter]} == 2;
  0            
627 0 0         if ( $counter == $fchk->{NATOMS} ) {
628 0           $geomcount++;
629 0           $counter = 0;
630             }
631 0 0         $ircgeomflag = 0 if $geomcount == $fchk->{IRCPOINTS};
632             }
633 0           next;
634             }
635             # IRC gradients (3*NATOMS x 1 vector)
636 0 0         if ( /IRC\spoint\s+\d+\sGradient\sat\seach\sgeom.*\s+R\s+N=\s+\d+/ ) {
637 0           $ircgradientflag = 1;
638 0           $geomcount = 0;
639 0           $counter = 0;
640 0           next;
641             }
642 0 0 0       if ( $ircgradientflag == 1 && /^\s+((?:-*\d\.\d+E-*\+*\d{2,}\s+){1,5})/ ) {
643 0           my @gradients = split /\s+/, $1;
644 0           for (my $i=0; $i
645 0           $fchk->{IRCGRADIENT} [$geomcount] [$counter] = $gradients[$i];
646 0           $counter++;
647 0 0         if ( $counter == 3*$fchk->{NATOMS} ) {
648 0           $geomcount++;
649 0           $counter = 0;
650             }
651 0 0         $ircgradientflag = 0 if $geomcount == $fchk->{IRCPOINTS};
652             }
653 0           next;
654             }
655             }
656              
657             # set HOMO
658 0           $fchk->{HOMO} = $fchk->{uc($fchk->{SPIN})};
659             }
660              
661              
662             # convert Scientific notation to decimals
663             sub sci2dec {
664 0     0 0   my $value = shift;
665 0 0         return unless defined $value;
666            
667 0           my $dec = 1*$value;
668 0           return $dec;
669             }
670              
671             1;
672             __END__