CCL Home Page
Up Directory CCL G90modes.perl
#!/usr/local/bin/perl

# Script to extract nomrmal modes from the G90 output file.
# The OUT file may be the result of single calculations with
# link line (like example 6.15 in G90 manual) or a result of
# a separate restart with FREQ keyword from checkpoint file.
# The first task is to find out if OUT contains two runs
# (geometry optimization followed by frequences) or just one.
# Then if 2 runs, skip the portion of file up to and including
# first @ (it ends the result summary portion for geometry optimization).
# Then search for "Z-Matrix orientation:" string (if C1 symmetry
# and for "Standard orientation:" if symmetry used. Skip
# 4 lines and collect cartesian coordinates in the array
# until you reach line of "--------------". Count the atoms.
# Then search for the "Frequencies ---" string, which
# starts first portion of the table of frequences and
# normal modes. It looks like:
#       Frequencies ---   278.9971  314.8132  452.1797  864.0812  962.6147
#    Reduced masses ---     1.0702    1.1263    2.7343    1.0824    2.1573
#   Force constants ---     0.0491    0.0658    0.3294    0.4761    1.1778
#    IR Intensities ---    16.3380  137.0003   14.8384    2.4492    9.6849
#  Raman Activities ---     0.4115    2.3307    0.7819    0.2060   11.2770
#   Depolarizations ---     0.7439    0.7405    0.4521    0.6779    0.2744
# Coord Atom Element:
#   6     1     6          0.00129  -0.00502   0.07478  -0.03799  -0.05805
#   6     1     6         -0.00805   0.03163   0.11205   0.02176  -0.08881
#   6     1     6          0.00304  -0.01473  -0.15222   0.00036   0.19568
#  etc.
# The Coord column is probably the (frequency number - 1) for first column
# but beats me. There are 5 columns in each portion. Skip first column. Next is
# an atom number (X, Y, Z for each atom, correspond to succesive rows, I
# presume), then the atomic number), then normal modes. These need to be
# collected in arrays. The 2nd and 3rd column can be used for consistency
# checking. There should be 3N rows in each portion of the matrix.
# Then you search for another "Frequencies ---" and check if you have
# all 5 columns or if this is a last portion with less columns.
# There is a second version of this table in G90 output file, which
# lists 3 frequences and XYZ modes for each atom, but normal modes
# have only two digits after decimal point.
# Now how the data are printed? They are printed as required by xmol
# to display frequences. Each normal mode is printed as a separate file
# with an extension nu1 ... nu(3N-6). The root of file name is taken from
# as everything from the beginning of output file name from GAUSSIAN up to
# first period. The OUT file name from G90 is given on the command line.
#

die "You did not give G90 output file name as argument\n" if $#ARGV < 0;
die "You need only one parameter --- G90 output file name\n" if $#ARGV > 0;

$G90OUT = $ARGV[0];
$G90OUT =~ /([\w\/+#-]+)/;
$OUT_root = $1;

@at_symbols = ('H ', 'He',
               'Li', 'Be', 'B ', 'C ', 'N ', 'O ', 'F ', 'Ne',
               'Na', 'Mg', 'Al', 'Si', 'P ', 'S ', 'Cl', 'Ar',
               'K ', 'Ca',
               'Ti', 'V ', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn',
                           'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'X ');



open(G90OUT,"<$G90OUT") || die "Could not open $G90OUT\n";

#check if 1 or 2 @ signes in the file. Check is symmetry
$n_runs = 0;
$symmetry = 1;   #default is symmetry
while() {
  $n_runs++ if /@/;
  $symmetry = 0 if /FULL\s+POINT\s+GROUP\s+C1/;
  }

die "No @ sign found in the G90 output file\n" if $n_runs == 0;

seek(G90OUT, 0, 1);  #clean EOF status
seek(G90OUT, 0, 0);  #rewind G90OUT file

if($n_runs == 2) {  #skipp after 1st @ if 2 runs
  while ($_ = ) {
    last if ($_ =~ /@/);
    }
  }

#now search for "Z-Matrix orientation:" line if no symmetry
#or Standard orientation: is symmetry
while () {
  if($symmetry == 0) {
    last if /Z-Matrix orientation:/;
    }
  else {
    last if /Standard orientation:/;
    }
  }

#skip 4 lines
for ($i = 0; $i < 4; $i++ ) {
  $line = ;
  }

#now collect cartesian coordinates in an array
$n_at = 0;
while ($line = ) {
  last if ($line =~ /--------------------/);  # when last line
  $n_at++;
  $line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/;
  die "Unstandard format of G90 output file\n" if $1 != $n_at;
  if($2 < $#at_symbols) {
    $at_symb[$n_at] = $at_symbols[$2-1];
    }
  else {
    $at_symb[$n_at] = $at_symbols[$#at_symbols];
    }
  $at_num[$n_at] = $2;
  $x_coor[$n_at] = $3;
  $y_coor[$n_at] = $4;
  $z_coor[$n_at] = $5;
  }

#search for line: "Low frequencies ---" which starts frequences block
while ($line = ) {
  last if ($line =~ /Low frequencies ---/);
  }

$n_cols = 3*$n_at-6;  #will be decremented by number of processed modes
$n_col_num = 0;
while($n_cols > 0) {
  if($n_cols >= 5) {
    $n_curr_cols = 5;
    }
  else {
    $n_curr_cols = $n_cols;
    }
  #open files for modes in the xmol format
  if($n_curr_cols >= 1) {
    $k = $n_col_num + 1;    # Which frequency we are"
    $temp = sprintf("%d",$k);
    $NU1F = $OUT_root . '.nu' . $temp;
    open(NU1F,">$NU1F") || die "Could not open $NU1F\n";
    }

  #open files for modes in the xmol format
  if($n_curr_cols >= 2) {
    $k = $n_col_num + 2;    # Which frequency we are"
    $temp = sprintf("%d",$k);
    $NU2F = $OUT_root . '.nu' . $temp;
    open(NU2F,">$NU2F") || die "Could not open $NU2F\n";
    }

  #open files for modes in the xmol format
  if($n_curr_cols >= 3) {
    $k = $n_col_num + 3;    # Which frequency we are"
    $temp = sprintf("%d",$k);
    $NU3F = $OUT_root . '.nu' . $temp;
    open(NU3F,">$NU3F") || die "Could not open $NU3F\n";
    }

  #open files for modes in the xmol format
  if($n_curr_cols >= 4) {
    $k = $n_col_num + 4;    # Which frequency we are"
    $temp = sprintf("%d",$k);
    $NU4F = $OUT_root . '.nu' . $temp;
    open(NU4F,">$NU4F") || die "Could not open $NU4F\n";
    }

  #open files for modes in the xmol format
  if($n_curr_cols >= 5) {
    $k = $n_col_num + 5;    # Which frequency we are"
    $temp = sprintf("%d",$k);
    $NU5F = $OUT_root . '.nu' . $temp;
    open(NU5F,">$NU5F") || die "Could not open $NU5F\n";
    }

  $search_expr = 'Frequencies ---' . ('\s+(\S+)' x $n_curr_cols);
  $i = 0;
  while ($line = ) {
    $i++;
    if($i > 10) {
      die "Could not find Frequencies --- in OUT file\n";
      }
    if($line =~ /$search_expr/) {
      if($n_curr_cols >= 1) {
        $vib_freq[1] = $1; 
        printf NU1F "%d\nNU=%f\n",$n_at, $vib_freq[1];
        }
      if($n_curr_cols >= 2) {
        $vib_freq[2] = $2;
        printf NU2F "%d\nNU=%f\n",$n_at, $vib_freq[2];
        }
      if($n_curr_cols >= 3) {
        $vib_freq[3] = $3;
        printf NU3F "%d\nNU=%f\n",$n_at, $vib_freq[3];
        }
      if($n_curr_cols >= 4) {
        $vib_freq[4] = $4;
        printf NU4F "%d\nNU=%f\n",$n_at, $vib_freq[4];
        }
      if($n_curr_cols >= 5) {
        $vib_freq[5] = $5;
        printf NU5F "%d\nNU=%f\n",$n_at, $vib_freq[5];
        }
      last;
      }
    }

  $i = 0;
  while ($line = ) {
    $i++;
    if($i > 10) {
      die "Could not find Coord Atom Element: in OUT file\n";
      }
    if($line =~ /Coord Atom Element:/) {
      last;
      }
    }

  $search_expr = '\S+\s+(\S+)\s+(\S+)' . ('\s+(\S+)' x $n_curr_cols);

  for ($n = 1; $n <= $n_at; $n++)  {
    if($n_curr_cols >= 1) {
      printf(NU1F "  %2s  %11.5f %11.5f %11.5f", $at_symb[$n],
             $x_coor[$n], $y_coor[$n], $z_coor[$n]);
      }

    if($n_curr_cols >= 2) {
      printf(NU2F "  %2s  %11.5f %11.5f %11.5f", $at_symb[$n],
             $x_coor[$n], $y_coor[$n], $z_coor[$n]);
      }

    if($n_curr_cols >= 3) {
      printf(NU3F "  %2s  %11.5f %11.5f %11.5f", $at_symb[$n],
             $x_coor[$n], $y_coor[$n], $z_coor[$n]);
      }

    if($n_curr_cols >= 4) {
      printf(NU4F "  %2s  %11.5f %11.5f %11.5f", $at_symb[$n],
             $x_coor[$n], $y_coor[$n], $z_coor[$n]);
      }

    if($n_curr_cols >= 5) {
      printf(NU5F "  %2s  %11.5f %11.5f %11.5f", $at_symb[$n],
             $x_coor[$n], $y_coor[$n], $z_coor[$n]);
      }

    for ($i = 1; $i <= 3; $i++) {
      $line = ;
      if( !($line =~ $search_expr)) {
	  die "Unstandard format of G90 OUTPUT file\n";
        }

      if($n != $1) {
        die "Unstandard format of G90 OUTPUT file --- mode line\n";
        }

      if($at_num[$n] != $2) {
        die "Unstandard format of G90 OUTPUT file --- at. num. wrong\n";
        }

      if($n_curr_cols >= 1) {
        $f =  $3;
        printf NU1F "  %11.5f", $f;
        }
      
    
      if($n_curr_cols >= 2) {
        $f =  $4;
        printf NU2F "  %11.5f", $f;
        }
      
    
      if($n_curr_cols >= 3) {
        $f =  $5;
        printf NU3F "  %11.5f", $f;
        }
      
    
      if($n_curr_cols >= 4) {
        $f =  $6;
        printf NU4F "  %11.5f", $f;
        }

      if($n_curr_cols >= 5) {
        $f = $7;
        printf NU5F "  %11.5f", $f;
        }
      }  # for $i

    if($n_curr_cols >= 1) {
      printf NU1F "\n";
      }

    if($n_curr_cols >= 2) {
      printf NU2F "\n";
      }

    if($n_curr_cols >= 3) {
      printf NU3F "\n";
      }

    if($n_curr_cols >= 4) {
      printf NU4F "\n";
      }

    if($n_curr_cols >= 5) {
      printf NU5F "\n";
      }

    }  # for $n

  if($n_curr_cols >= 1) {
    close(NU1F);
    }

  if($n_curr_cols >= 2) {
    close(NU2F);
    }

  if($n_curr_cols >= 3) {
    close(NU3F);
    }

  if($n_curr_cols >= 4) {
    close(NU4F);
    }

  if($n_curr_cols >= 5) {
    close(NU5F);
    }

  $n_col_num += $n_curr_cols;
  $n_cols -= $n_curr_cols;
  }  # while

close(G90OUT);



Modified: Thu Oct 1 16:00:00 1992 GMT
Page accessed 9333 times since Sat Apr 17 21:23:00 1999 GMT