NWChem/contrib/python/nwchem_tddft_spectrum.py
2026-06-29 15:24:48 -07:00

171 lines
5.2 KiB
Python
Executable file

#!/usr/bin/env python
"""
nwchem_tddft_spectrum.py - Extract the tddft data from an NWChem output
file and plot it in the form of a absorption
spectrum.
Usage:
nwchem_tddft_spectrum.py (options) (files)
Options:
-a value Use value as the Gaussian exponent to generate the plot
(default=10000)
-b Print both spectra
-h Print this help
-s Print the singlet spectrum (default)
-t Print the triplet spectrum
-o Print the open-shell spectrum
-u value Use value as the units. Must be in [h,eV,kcal/mol]; default eV
Send any errors or additions to Rick Muller, rmuller@sandia.gov.
"""
defaults = {
'alpha' : 10000,
'plot_singlet': True,
'plot_triplet': False,
'plot_unrestricted': False,
'plot_zeros': False, # Show zero oscillator strengths as slight negative blips
'units': 'eV',
}
from pylab import *
def parse_nwchem_output(fname):
import re
from pprint import pprint
singlet_pat = re.compile(r'\s+Root\s+\d+\s+singlet')
triplet_pat = re.compile(r'\s+Root\s+\d+\s+triplet')
unrestricted_pat = re.compile(r'\s+Root\s+\d')
singlets = []
triplets = []
unrestricted = []
f = open(fname)
while 1:
line = f.readline()
if not line: break
if singlet_pat.search(line):
energy,osc,trans_mom = parse_element(line,f)
singlets.append((energy,osc))
if triplet_pat.search(line):
energy,osc,trans_mom = parse_element(line,f)
triplets.append((energy,osc))
if unrestricted_pat.search(line):
energy,osc,trans_mom = parse_element(line,f)
unrestricted.append((energy,osc))
#pprint(singlets)
#pprint(triplets)
return singlets,triplets,unrestricted
def parse_element(line,f):
import re
oscillator_pat = re.compile(r'\s+Oscillator')
words = line.split()
try:
energy = float(words[4])
except:
energy = float(words[3])
line = f.readline() # skip ----
line = f.readline()
words = line.split()
try:
txyz = float(words[3]),float(words[5]),float(words[7])
except:
txyz = (0,0,0)
line = f.readline()
words = line.split()
while None == oscillator_pat.search(line):
line = f.readline()
words = line.split()
try:
osc = float(words[3])
except:
osc = 0
return energy,osc,txyz
def to_plot(data,**kwargs):
alpha = kwargs.get('alpha',defaults['alpha'])
plot_zeros = kwargs.get('plot_zeros',defaults['plot_zeros'])
abmin_floor = kwargs.get('abmin',0.001)
Emin = min(E for E,ab in data)
Emax = max(E for E,ab in data)
abmin = min([0] + [ab for E,ab in data if ab > 0])
abmin = max(abmin,abmin_floor)
Edel = Emax-Emin
Es = linspace(Emin-Edel/10.,Emax+Edel/10.,2000)
Spectrum = zeros(Es.shape,'d')
for E,ab in data:
if ab > 0:
Spectrum += ab*exp(-alpha*(Es-E)**2)
elif plot_zeros:
Spectrum -= abmin*exp(-alpha*(Es-E)**2)
return Es,Spectrum
def nwchem_tddft_spectrum(fname,**kwargs):
from os.path import basename
thetitle = kwargs.get('title',basename(fname))
units = kwargs.get('units',defaults['units'])
assert units in ['h','eV','ev','kcal/mol','kcm']
if units in ['eV','ev']:
conv = 27.211
elif units in ['kcal/mol','kcm']:
conv = 627.51
else:
conv = 1.0 # h
singlet,triplet,unrestricted = parse_nwchem_output(fname)
if thetitle: title(thetitle)
if kwargs['plot_singlet']:
Es0,Spectrum0 = to_plot(singlet,**kwargs)
plot(Es0*conv,Spectrum0,label='sing')
if kwargs['plot_triplet']:
Es1,Spectrum1 = to_plot(triplet,**kwargs)
plot(Es1*conv,Spectrum1,label='trip')
if kwargs['plot_unrestricted']:
Es1,Spectrum1 = to_plot(unrestricted,**kwargs)
plot(Es1*conv,Spectrum1,label='open')
legend()
xlabel('Energy (%s)' % units)
ylabel('Oscillator Strength')
if fname.endswith('.out'):
oname = fname.replace('.out','.png')
else:
oname = fname + ".png"
savefig(oname)
show()
return
if __name__ == '__main__':
from getopt import getopt
opts,args = getopt(sys.argv[1:],'hstoa:b')
kwargs = defaults
for key,val in opts:
if key == '-a':
kwargs['alpha'] = float(val)
if key == '-b':
kwargs['plot_singlet'] = True
kwargs['plot_triplet'] = True
kwargs['plot_unrestricted'] = False
if key == '-s':
kwargs['plot_singlet'] = True
kwargs['plot_triplet'] = False
kwargs['plot_unrestricted'] = False
if key == '-t':
kwargs['plot_singlet'] = False
kwargs['plot_triplet'] = True
kwargs['plot_unrestricted'] = False
if key == '-o':
kwargs['plot_singlet'] = False
kwargs['plot_triplet'] = False
kwargs['plot_unrestricted'] = True
if key == '-h':
print(__doc__)
sys.exit()
if len(args) == 0:
print(__doc__)
sys.exit()
for fname in args:
nwchem_tddft_spectrum(fname,**kwargs)