diff --git a/README.md b/README.md
index 43d92e1..2c9d6bc 100644
--- a/README.md
+++ b/README.md
@@ -70,10 +70,10 @@ This correction from 1 atm to 1 mol/l is responsible for the addition 1.89 kcal/
#### Example 4: Analyzing the Gibbs energy across an interval of temperatures 300-1000 K with a stepsize of 100 K, applying a (Truhlar type) cut-off of 100 cm-1
```python
-python GoodVibes.py examples/methylaniline.out –ti 300,1000,100 –qh truhlar –f 100
+python GoodVibes.py examples/methylaniline.out –-ti '300,1000,100' –q truhlar –f 100
H/au T.S/au T.qh-S/au G(T)/au qh-G(T)/au
- ***************************************************************************************************************************
+ **********************************************************************************************************
o examples/methylaniline.out @ 300.0 -326.514399 0.040005 0.040005 -326.554404 -326.554404
o examples/methylaniline.out @ 400.0 -326.508735 0.059816 0.059816 -326.568551 -326.568551
o examples/methylaniline.out @ 500.0 -326.501670 0.082625 0.082625 -326.584296 -326.584296
@@ -85,7 +85,7 @@ o examples/methylaniline.out @ 1000.0 -326.452307 0.232169 0.232169
```
-Note that the energy and ZPE are not printed in this instance since they are temperature-independent. The Truhlar-type quasiharmonic correction sets all frequencies below than 100 cm-1 to a value of 100.
+Note that the energy and ZPE are not printed in this instance since they are temperature-independent. The Truhlar-type quasiharmonic correction sets all frequencies below than 100 cm-1 to a value of 100. Constant pressure is assumed, so that the concentration is recomputed at each temperature.
#### Example 5: Analyzing the Gibbs Energy using scaled vibrational frequencies
```python
diff --git a/goodvibes/GoodVibes.py b/goodvibes/GoodVibes.py
index f977a06..de5f5af 100755
--- a/goodvibes/GoodVibes.py
+++ b/goodvibes/GoodVibes.py
@@ -183,7 +183,7 @@ def calc_rotational_entropy(zpe, linear, symmno, roconst, temperature):
Strans = 0 (atomic) ; R(Ln(q)+1) (linear); R(Ln(q)+3/2) (non-linear)
"""
# monatomic
- if roconst == [0.0,0.0,0.0]: return 0.0
+ if roconst == [0.0,0.0,0.0] or zpe == 0.0: entropy = 0.0
rotemp = [const * PLANCK_CONSTANT * 1e9 / BOLTZMANN_CONSTANT for const in roconst]
# diatomic
@@ -196,8 +196,6 @@ def calc_rotational_entropy(zpe, linear, symmno, roconst, temperature):
qrot = qrot/symmno
- if zpe == 0.0: entropy = 0.0 # monatomic
-
if linear == 1: entropy = GAS_CONSTANT * (math.log(qrot) + 1)
else: entropy = GAS_CONSTANT * (math.log(qrot) + 1.5)
return entropy
@@ -261,16 +259,8 @@ def __init__(self, file, QH, FREQ_CUTOFF, temperature, conc, freq_scale_factor,
# if spc specified will take last Energy from file, otherwise will break after freq calc
if link > freqloc and spc == False: break
-<<<<<<< Updated upstream
- # Iterate over output
- #for line in g09_output:
- # look for low frequencies
- #if line.find("Proceeding to internal job step")!= -1: frequency_wn = [] #resets the array if frequencies have been calculated more than once
- if line.startswith(' Frequencies --'):
-=======
# Iterate over output: look out for low frequencies
if line.strip().startswith('Frequencies --'):
->>>>>>> Stashed changes
for i in range(2,5):
try:
x = float(line.strip().split()[i])
@@ -299,21 +289,21 @@ def __init__(self, file, QH, FREQ_CUTOFF, temperature, conc, freq_scale_factor,
cutoffs = [FREQ_CUTOFF for freq in frequency_wn]
# Translational and electronic contributions to the energy and entropy do not depend on frequencies
- Utrans = calc_translational_energy(options.temperature)
- Strans = calc_translational_entropy(molecular_mass, conc, options.temperature, solv)
+ Utrans = calc_translational_energy(temperature)
+ Strans = calc_translational_entropy(molecular_mass, conc, temperature, solv)
Selec = calc_electronic_entropy(mult)
# Rotational and Vibrational contributions to the energy entropy
if len(frequency_wn) > 0:
ZPE = calc_zeropoint_energy(frequency_wn, freq_scale_factor)
- Urot = calc_rotational_energy(self.zero_point_corr, symmno, options.temperature, linear_mol)
- Uvib = calc_vibrational_energy(frequency_wn, options.temperature, freq_scale_factor)
- Srot = calc_rotational_entropy(self.zero_point_corr, linear_mol, symmno, roconst, options.temperature)
+ Urot = calc_rotational_energy(self.zero_point_corr, symmno, temperature, linear_mol)
+ Uvib = calc_vibrational_energy(frequency_wn, temperature, freq_scale_factor)
+ Srot = calc_rotational_entropy(self.zero_point_corr, linear_mol, symmno, roconst, temperature)
# Calculate harmonic entropy, free-rotor entropy and damping function for each frequency
- Svib_rrho = calc_rrho_entropy(frequency_wn, options.temperature, freq_scale_factor)
- if FREQ_CUTOFF > 0.0: Svib_rrqho = calc_rrho_entropy(cutoffs, options.temperature,1.0)
- Svib_free_rot = calc_freerot_entropy(frequency_wn, options.temperature, freq_scale_factor)
+ Svib_rrho = calc_rrho_entropy(frequency_wn, temperature, freq_scale_factor)
+ if FREQ_CUTOFF > 0.0: Svib_rrqho = calc_rrho_entropy(cutoffs, temperature, 1.0)
+ Svib_free_rot = calc_freerot_entropy(frequency_wn, temperature, freq_scale_factor)
damp = calc_damp(frequency_wn, FREQ_CUTOFF)
# Compute entropy (cal/mol/K) using the two values and damping function
@@ -326,21 +316,23 @@ def __init__(self, file, QH, FREQ_CUTOFF, temperature, conc, freq_scale_factor,
else: vib_entropy.append(Svib_rrqho[j])
else: vib_entropy.append(Svib_rrho[j])
qh_Svib, h_Svib = sum(vib_entropy), sum(Svib_rrho)
- # for monatomic species only
+
+ # monatomic species have no vibrational or rotational degrees of freedom
else: ZPE, Urot, Uvib, Srot, h_Svib, qh_Svib = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
# Add all terms (au) to get Free energy - perform separately for harmonic and quasi-harmonic values out of interest
# All units are converted to a.u. here
- self.enthalpy = self.scf_energy + (Utrans + Urot + Uvib + GAS_CONSTANT * options.temperature) / j_to_au
+ self.enthalpy = self.scf_energy + (Utrans + Urot + Uvib + GAS_CONSTANT * temperature) / j_to_au
self.zpe = ZPE / j_to_au
self.entropy = (Strans + Srot + h_Svib + Selec) / j_to_au
self.qh_entropy = (Strans + Srot + qh_Svib + Selec) / j_to_au
- self.gibbs_free_energy = self.enthalpy - options.temperature * self.entropy
- self.qh_gibbs_free_energy = self.enthalpy - options.temperature * self.qh_entropy
+ self.gibbs_free_energy = self.enthalpy - temperature * self.entropy
+ self.qh_gibbs_free_energy = self.enthalpy - temperature * self.qh_entropy
if __name__ == "__main__":
# Takes arguments: gaussian_output_files
log = Logger("Goodvibes","dat", "output")
+
# get command line inputs
parser = OptionParser(usage="Usage: %prog [options] .log .log ...")
parser.add_option("-t", dest="temperature", action="store",
@@ -357,18 +349,18 @@ def __init__(self, file, QH, FREQ_CUTOFF, temperature, conc, freq_scale_factor,
help="Solvent (H2O, toluene, DMF, AcOH, chloroform) (default none)", default="none", type="string", metavar="SOLV")
parser.add_option("--spc", dest="spc", action="store_true",
help="Indicates linked single point corrections (default False)", default=False, metavar="SOLV")
+ parser.add_option("--ti", dest="temperature_interval", action="store",
+ help="initial temp, final temp, step size (K)", default=False, metavar="TI")
+ parser.add_option("--ci", dest="conc_interval", action="store",
+ help="initial conc, final conc, step size (mol/l)", default=False, metavar="CI")
(options, args) = parser.parse_args()
# case insensitive
options.QH = options.QH.lower()
# Default variables
- files, temperature_interval, conc_interval = [], [], []
+ files = []
if len(sys.argv) > 1:
- for elem, next_elem in zip(sys.argv[1:], sys.argv[2:]):
- if elem == "-ti": temperature_interval = list(eval(next_elem))
- elif elem == "-ci": conc = list(next_elem)
-
# get the filenames
for elem in sys.argv[1:]:
try:
@@ -378,13 +370,13 @@ def __init__(self, file, QH, FREQ_CUTOFF, temperature, conc, freq_scale_factor,
start = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
log.Write(" GoodVibes v" + __version__ + " " + start)
- log.Write("\n REF: " + goodvibes_ref +"\n")
+ log.Write("\n REF: " + goodvibes_ref +"\n\n")
- log.Write("\n Temperature = "+str(options.temperature)+" Kelvin")
+ if options.temperature_interval == False: log.Write(" Temperature = "+str(options.temperature)+" Kelvin")
# If not at standard temp, need to correct the molarity of 1 atmosphere
if options.conc == 0.040876:
options.conc = atmos/(GAS_CONSTANT*options.temperature)
- log.Write(" Concn = 1 atm"); conc_ini="None"
+ log.Write(" Pressure = 1 atm"); conc_ini="None"
else: log.Write(" Concn = "+str(options.conc)+" mol/l"); conc_ini="None"
# attempts to automatically obtain frequency scale factor. Requires all outputs to be same level of theory
@@ -414,7 +406,7 @@ def all_same(items): return all(x == items[0] for x in items)
if options.spc == "True": log.Write("\n Link job: combining final single point energy with thermal corrections")
# Standard mode: tabulate thermochemistry ouput from file(s) at a single temperature and concentration
- if len(temperature_interval) == 0 and len(conc_interval) == 0:
+ if options.temperature_interval == False and options.conc_interval == False:
#log.Write("\n\n "+"Structure".ljust(39))
log.Write("\n\n " + '{:<39} {:>13} {:>10} {:>13} {:>10} {:>10} {:>13} {:>13}'.format("Structure", "E/au", "ZPE/au", "H/au", "T.S/au", "T.qh-S/au", "G(T)/au", "qh-G(T)/au"))
log.Write("\n"+stars)
@@ -429,26 +421,27 @@ def all_same(items): return all(x == items[0] for x in items)
log.Write("\n"+stars+"\n")
#Running a variable temperature analysis of the enthalpy, entropy and the free energy
- if len(temperature_interval) != 0:
+ elif options.temperature_interval != False:
+ temperature_interval = [float(temp) for temp in options.temperature_interval.split(',')]
# If no temperature step was defined, divide the region into 10
if len(temperature_interval) == 2: temperature_interval.append((temperature_interval[1]-temperature_interval[0])/10.0)
- log.Write("\n\n Running a temperature analysis of the enthalpy, entropy and the entropy between")
+ log.Write("\n\n Variable-Temperature analysis of the enthalpy, entropy and the entropy at a constant pressure between")
log.Write("\n T_init: %.1f, T_final: %.1f, T_interval: %.1f" % (temperature_interval[0], temperature_interval[1], temperature_interval[2]))
- temperature = float(temperature_interval[0])
log.Write("\n\n "+"Structure".ljust(39))
- log.Write('{:>13} {:>13} {:>10} {:>10} {:>13} {:>13}'.format("Temp/K", "H/au", "T.S/au", "T.qh-S/au", "G(T)/au", "qh-G(T)/au"))
+ log.Write("\n\n " + '{:<39} {:>13} {:>24} {:>10} {:>10} {:>13} {:>13}'.format("Structure", "Temp/K", "H/au", "T.S/au", "T.qh-S/au", "G(T)/au", "qh-G(T)/au"))
+
for file in files:
- log.Write("\n"+stars[:120])
+ log.Write("\n"+stars)
for i in range(int(temperature_interval[0]), int(temperature_interval[1]+1), int(temperature_interval[2])):
- temperature = float(i)
- log.Write("\no "+file.ljust(39))
- log.Write('{:13.1f}'.format(temperature))
- if conc_ini == "None": options.conc = atmos/(GAS_CONSTANT*temperature)
- bbe = calc_bbe(file, options.QH, options.freq_cutoff, temperature, options.conc, freq_scale_factor, solv, options.spc)
+ temp, conc = float(i), atmos / GAS_CONSTANT / float(i)
+ log.Write("\no "+'{:<39} {:13.1f}'.format(file.split(".")[0], temp))
+ bbe = calc_bbe(file, options.QH, options.freq_cutoff, temp, conc, options.freq_scale_factor, options.solv, options.spc)
if not hasattr(bbe,"gibbs_free_energy"): log.Write("Warning! Couldn't find frequency information ...\n")
else:
if all(getattr(bbe, attrib) for attrib in ["enthalpy", "entropy", "qh_entropy", "gibbs_free_energy", "qh_gibbs_free_energy"]):
- log.Write('{:13.6f} {:10.6f} {:10.6f} {:13.6f} {:13.6f}'.format(bbe.enthalpy, (temperature * bbe.entropy), (temperature * bbe.qh_entropy), bbe.gibbs_free_energy, bbe.qh_gibbs_free_energy))
- log.Write("\n"+stars[:120]+"\n")
+ log.Write(' {:24.6f} {:10.6f} {:10.6f} {:13.6f} {:13.6f}'.format(bbe.enthalpy, (temp * bbe.entropy), (temp * bbe.qh_entropy), bbe.gibbs_free_energy, bbe.qh_gibbs_free_energy))
+ log.Write("\n"+stars+"\n")
+
+ # close the log
log.Finalize()