#!/usr/bin/perl -wi

#
# GAMESSPLUS solubility utility program, based on GAMESSPLUS v2009
#

#
# Parse input file
# 
$rungmsdir='./rungmsplus';

open(IN, "<$ARGV[0]");@line="";@line=<IN>;close(IN);
$prefix = $ARGV[0]; $prefix =~ s/\.inp//i;

for $i (0 .. $#line) {
   chomp($line[$i]); $line[$i] = uc($line[$i]);
   if ($line[$i] =~ m/\$VAPOR/) {
     $vapor = $line[$i] ;
     $vapor =~ s/\$VAPOR//i;
     if ($line[$i]=~ m/\$END/) { 
     }  else {
       for $j ($i+1 .. $#line) {
          chomp($line[$j]);$line[$j] = uc($line[$j]);
          if ($line[$j] =~ m/\$END/) {
             $vapor = "$vapor \n $line[$j]";
             last;
          } else {
             $vapor = "$vapor\n$line[$j]";
          }
       }
     }  
   }
   if ($line[$i] =~ m/\$DGS/) {
     $dgs = $line[$i];
     $dgs =~ s/\$DGS//i;
     if ($line[$i]=~ m/\$END/) {
     }  else {
       for $j ($i+1 .. $#line) {
          chomp($line[$j]);
          if ($line[$j] =~ m/\$END/) {
             $dgs = "$dgs \n$line[$j]";
             last;
          } else {
             $dgs = "$dgs\n$line[$j]";
          }
       }
     }
   }
}
#
# Check to make sure $DGS and $VAPOR have everything, they should both have:
# IAQU if IAQU=0, and when IAQU=0, they should also have
# SolN, SolA, SolB, SOlC, SolG, SolH, and Dielec
if ($vapor =~ m/IAQU=0/) {
   if ($vapor =~ m/SOLA/) { } else {

   print "Error: SOLA not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
   if ($vapor =~ m/SOLG/) { } else { 

   print "Error: SOLG not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
   if ($vapor =~ m/SOLB/) { } else { 

   print "Error: SOLB not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
   if ($vapor =~ m/SOLC/) { } else { 

   print "Error: SOLC not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
   if ($vapor =~ m/SOLH/) { } else { 

   print "Error: SOLH not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
   if ($vapor =~ m/DIELEC/) { } else { 

   print "Error: DIELEC not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
   if ($vapor =~ m/SOLN/) { } else { 

   print "Error: SOLN not found in \$VAPOR namelist.\n";
   print "Add it to \$VAPOR and resubmit this solubility calculation.\n";
   exit;
   }
}
#
# Get density, stop if not found in input
#
if ($vapor =~ m/DENSITY/) {}else {print <<"EOF";
   Error: Density of solute not found in  \$VAPOR

   Specifiy the density of the solute (in mol/L) with the
   DENSITY keyword.
EOF
exit;
}
($dum,$temp) = split/ITY=/,$vapor;
($density,$dum) = split/\s+/,$temp;
$vapor =~ s/DENSITY=\d*\.\d+//g;
$vapor =~ s/\$END//i;
#
# Find out if PRESSURE keyword is used in $VAPOR
# If it is, we don't need the free energy of
# self-solvation
#
$pcalc = 0;
$unit = "PA";
if ($vapor =~ m/PRESSURE=/) {
   $pcalc = 1;
   ($dum,$pvap) = split/RESSURE=/,$vapor;($pvap,$dum) = split/\s+/,$pvap;
   if ($vapor =~ m/=/) {
      ($dum,$unit) = split/NITS=/,$vapor;($unit,$dum) = split/\s+/,$unit;
   }
   if ($unit ne "PA") {
      if ($unit eq "ATM") { $pvap = $pvap*101325;}
      elsif ($unit eq "TORR") {$pvap = ($pvap/760)*101325;} 
      elsif ($unit eq "BAR")  {$pvap = $pvap*100000;}
   }
}
#
# PRESSURE is not used, look in $VAPOR for ISCRF and ICDS
#
if ($pcalc == 0) { 
#
# Add ICMD to namelist.  If ICDS is not present, set both
# ICMD and ICDS to 1.
#
if ($vapor =~ m/ICDS=/){
  ($dum,$icdsv) = split/CDS=/,$vapor;($icdsv,$dum) = split/\s+/,$icdsv;
  $vapor = "\n$vapor\n ICMD=$icdsv\n";
} else {
  $vapor = "\n$vapor\nICMD=1 ICDS=1\n";
}
#
# Look for ISCRF   
# If not present, set it equal to 1  
#
if ($vapor =~ m/ISCRF/) {
} else {$vapor = "$vapor \n ISCRF=1\n";
}
#
# Make $GMSOL namelist for free energy of self-solvation calc.
# Make correspond GAMESSPLUS input file and run it
#
  $vapor = " \$GMSOL \n $vapor\$END";
  open(OUT ,">vapor.$prefix.inp"); 
  print OUT "$vapor\n";
  for $i (0 .. $#line) {
     print OUT "$line[$i]\n";
  }
  close(OUT);

  system("$rungmsdir vapor.$prefix 1 1 >& vapor.$prefix.log 2>&1");
#
# Make sure free energy of self-solvation calc. ran correctly
# If not, stop
#
  if (`grep "DeltaG-S\(liq\) free energy of  solvation" vapor.$prefix.log`) {
  }  else { 
     print "The free energy of self-solvation calculation did not run properly.\n";
     print "Check the output file, called vapor.$prefix.log,for more details.\n";
     exit;
  }
}
#
# Process $DGS namelist: 
# Look for ICDS and ISCRF, if not there, set to default of 1
#
$dgs =~ s/\$END//i;
if ($dgs =~ m/ICDS=/){
   ($dum,$icdss) = split/CDS=/,$dgs;($icdss,$dum) = split/\s+/,$icdss; 
   $dgs = "\n$dgs\n ICMD=$icdss\n";
}  else {
   $dgs = "\n$dgs\nICMD=1 ICDS=1\n";
}

if ($dgs =~ m/ISCRF/) {
} else {$dgs = "$dgs \n ISCRF=1\n";
}
#
# Make $GMSOL namelist for free energy of solvation calc.
# Make corresponding output file and run it
#
$dgs = " \$GMSOL \n $dgs \$END";
open(OUT ,">dgs.$prefix.inp");
print OUT "$dgs\n";
for $i (0 .. $#line) {
   print OUT "$line[$i]\n";
}
 system("$rungmsdir dgs.$prefix 1 1 >& dgs.$prefix.log 2>&1");
#
# Make sure calc. ran fine
#
if (`grep "DeltaG-S\(liq\) free energy of  solvation" dgs.$prefix.log`) {
}  else {
   print "The free energy of solvation in the saturated solution calculation\n";
   print " did not run properly.\n";
   print "Check the output file, called dgs.$prefix.log,for more details.\n";
   exit;
}
#
# Parse output files from free energy of self-solvation and 
# free energy of solvation calc.
#
if ($pcalc == 0) {
  open(IN,"<vapor.$prefix.log");
  while(<IN>) {
    if (/\(2\)  G-P\(liq\) polarization free energy of solvation\s+([-]?\d*\.\d+)\s*/){
      $gpvap=$1;
    }
    if (/\(4\)  G-CDS\(liq\) cavity-dispersion-solvent structure\s+([-]?\d*\.\d+)\s*/){
      $cdsvap=$1;
    }
    if (/     energy of solute molecule \(7\) = \(1\) - \(0\)\s+([-]?\d*\.\d+)\s*/){
      $devap = $1;
    }
    if (/     \(9\) = \(6\) - \(0\)\s+([-]?\d*\.\d+)\s*/) {
      $gself = $1;
    }
  }
  close(IN);
}

open(IN,"<dgs.$prefix.log");
while(<IN>) {
  if (/\(2\)  G-P\(liq\) polarization free energy of solvation\s+([-]?\d*\.\d+)\s*/){
    $gpsol=$1;
  }
  if (/\(4\)  G-CDS\(liq\) cavity-dispersion-solvent structure\s+([-]?\d*\.\d+)\s*/){
    $cdssol=$1;
  }
  if (/     energy of solute molecule \(7\) = \(1\) - \(0\)\s+([-]?\d*\.\d+)\s*/
){
    $desol = $1;
  }
  if (/     \(9\) = \(6\) - \(0\)\s+([-]?\d*\.\d+)\s*/) {
    $gsol = $1;
  }
}
close(IN);
#
# Compute pure-solute vapor pressure and solubility
#
#$pgas = 24.45; # in atmoshpheres
 $pgas = 2477396.25; # in Pascals
 $rt = 0.592189532; # in kcal/mol
 if ($pcalc == 0) {$pvap = $pgas*$density*exp($gself/$rt);}
 $patm = $pvap/101325;
 $ppas = $pvap;
 $ptor = ($pvap/101325)*760;
 $pbar = $pvap/100000;
 $solub = ($pvap/$pgas)*exp(-$gsol/$rt); 
 $logs = log($solub)/log(10);
 $dandt = localtime;
#
# Now we're ready to print
#
 open(OUT, ">$prefix.log");
 print OUT << "EOF";

GAMESSPLUS Solubility Utility calculation
based on GAMESSPLUS v2009

$dandt

      ------ Summary of Solubility Calculation ------

EOF

if ($pcalc == 0) {
 print OUT << "EOF";
 Standard-state free energy of self-solvation of solute:

 DeltaE-EN(liq) elect-nuc reorganization:         $devap kcal/mol
 G-P(liq) polarization free energy of solvation:  $gpvap kcal/mol
 G-CDS(liq) cavity-dispersion-solvent structure:  $cdsvap kcal/mol
 Free energy of self-solvation:                   $gself kcal/mol
EOF
} else {
 print OUT << "EOF";
 A value of the pure-solute vapor pressure was supplied by the user,
 so no information regarding the free energy of self-solvation is available.
EOF
}  
print OUT << "EOF";

 Standard-state free energy of solvation of solute:

 DeltaE-EN(liq) elect-nuc reorganization:         $desol kcal/mol
 G-P(liq) polarization free energy of solvation:  $gpsol kcal/mol
 G-CDS(liq) cavity-dispersion-solvent structure:  $cdssol kcal/mol
 Free energy of self-solvation:                   $gsol kcal/mol

 Density of Solute:                               $density mol/L
EOF
print OUT " Vapor pressure of solute:                        ";
print OUT "\n";
printf OUT "%54.2f",$patm;print OUT "atm\n";
printf OUT "%54.2f",$ppas;print OUT "Pa\n";
printf OUT "%54.2f",$ptor;print OUT "torr\n";
printf OUT "%54.2f",$pbar;print OUT "bar\n";
print OUT "\n";
print OUT " Solubility of solute:                            ";
printf OUT "%3.4f", $solub; 
print OUT " mol/L\n";
print OUT " Logarithm (base10) of solubility of solute:      ";
printf OUT "%3.2f", $logs;


