/usr/share/psi/python/qcdb/libmintsbasissetparser.py is in psi4-data 1:0.3-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | import os
import re
from exceptions import *
from libmintsgshell import *
class Gaussian94BasisSetParser(object):
"""Class for parsing basis sets from a text file in Gaussian 94
format. Translated directly from the Psi4 libmints class written
by Justin M. Turney and Andrew C. Simmonett.
"""
def __init__(self, forced_puream=None):
"""Constructor"""
# If the parser needs to force spherical or cartesian (e.g., loading old guess)
self.force_puream_or_cartesian = False if forced_puream is None else True
# Is the forced value to use puream? (Otherwise force Cartesian).
self.forced_is_puream = False if forced_puream is None else forced_puream
# string filename
self.filename = None
def load_file(self, filename, basisname=None):
"""Load and return the file to be used by parse. Return only
portion of *filename* pertaining to *basisname* if specified (for
multi-basisset files) otherwise entire file as list of strings.
"""
# string filename
self.filename = filename
given_basisname = False if basisname is None else True
found_basisname = False
basis_separator = re.compile(r'^\s*\[\s*(.*?)\s*\]\s*$')
# Loads an entire file.
try:
infile = open(filename, 'r')
except IOError:
raise BasisSetFileNotFound("""BasisSetParser::parse: Unable to open basis set file: %s""" % (filename))
if os.stat(filename).st_size == 0:
raise ValidationError("""BasisSetParser::parse: given filename '%s' is blank.""" % (filename))
contents = infile.readlines()
lines = []
for text in contents:
text = text.strip()
# If no basisname was given always save the line.
if given_basisname is False:
lines.append(text)
if found_basisname:
# If we find another [*] we're done.
if basis_separator.match(text):
what = basis_separator.match(text).group(1)
break
lines.append(text)
continue
# If the user gave a basisname AND text matches the basisname we want to trigger to retain
if given_basisname and basis_separator.match(text):
if basisname == basis_separator.match(text).group(1):
found_basisname = True
return lines
def parse(self, symbol, dataset):
"""Given a string, parse for the basis set needed for atom.
* @param symbol atom symbol to look for in dataset
* @param dataset data set to look through
dataset can be list of lines or a single string which will be converted to list of lines
"""
if isinstance(dataset, basestring):
lines = dataset.split('\n')
else:
lines = dataset
# Regular expressions that we'll be checking for.
cartesian = re.compile(r'^\s*cartesian\s*', re.IGNORECASE)
spherical = re.compile(r'^\s*spherical\s*', re.IGNORECASE)
comment = re.compile(r'^\s*\!.*') # line starts with !
separator = re.compile(r'^\s*\*\*\*\*') # line starts with ****
ATOM = '(([A-Z]{1,3}\d*)|([A-Z]{1,3}_\w+))' # match 'C 0', 'Al c 0', 'P p88 p_pass 0' not 'Ofail 0', 'h99_text 0'
atom_array = re.compile(r'^\s*((' + ATOM + '\s+)+)0\s*$', re.IGNORECASE) # array of atomic symbols terminated by 0
shell = re.compile(r'^\s*(\w+)\s*(\d+)\s*(-?\d+\.\d+)') # Match beginning of contraction
blank = re.compile(r'^\s*$')
NUMBER = "((?:[-+]?\\d*\\.\\d+(?:[DdEe][-+]?\\d+)?)|(?:[-+]?\\d+\\.\\d*(?:[DdEe][-+]?\\d+)?))"
primitives1 = re.compile(r'^\s*' + NUMBER + '\s+' + NUMBER + '.*') # Match s, p, d, f, g, ... functions
primitives2 = re.compile(r'^\s*' + NUMBER + '\s+' + NUMBER + '\s+' + NUMBER + '.*') # match sp functions
# s, p and s, p, d can be grouped together in Pople-style basis sets
sp = 'SP'
spd = 'SPD'
# a b c d e f g h i j k l m n o p q r s t u v w x y z
#shell_to_am = [-1,-1,-1, 2,-1, 3, 4, 5, 6,-1, 7, 8, 9,10,11, 1,12,13, 0,14,15,16,17,18,19,20]
alpha = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
angmo = [-1, -1, -1, 2, -1, 3, 4, 5, 6, -1, 7, 8,
9, 10, 11, 1, 12, 13, 0, 14, 15, 16, 17, 18, 19, 20]
shell_to_am = dict(zip(alpha, angmo))
# Basis type.
gaussian_type = 'Pure'
if self.force_puream_or_cartesian:
if self.forced_is_puream == False:
gaussian_type = 'Cartesian'
# Need a dummy center for the shell.
center = [0.0, 0.0, 0.0]
shell_list = []
lineno = 0
found = False
while lineno < len(lines):
line = lines[lineno]
lineno += 1
# Ignore blank lines
if blank.match(line):
continue
# Look for Cartesian or Spherical
if not self.force_puream_or_cartesian:
if cartesian.match(line):
gaussian_type = 'Cartesian'
#TODO if psi4.get_global_option('PUREAM').has_changed():
#TODO gaussian_type = 'Pure' if int(psi4.get_global('PUREAM')) else 'Cartesian'
continue
elif spherical.match(line):
gaussian_type = 'Pure'
#TODO if psi4.get_global_option('PUREAM').has_changed():
#TODO gaussian_type = 'Pure' if int(psi4.get_global('PUREAM')) else 'Cartesian'
continue
#end case where puream setting wasn't forced by caller
# Do some matches
if comment.match(line):
continue
if separator.match(line):
continue
# Match: H 0
# or: H O... 0
if atom_array.match(line):
what = atom_array.match(line).group(1).split()
# Check the captures and see if this basis set is for the atom we need.
found = False
if symbol in [x.upper() for x in what]:
found = True
msg = """line %5d""" % (lineno)
# Read in the next line
line = lines[lineno]
lineno += 1
# Need to do the following until we match a "****" which is the end of the basis set
while not separator.match(line):
# Match shell information
if shell.match(line):
what = shell.match(line)
shell_type = str(what.group(1)).upper()
nprimitive = int(what.group(2))
scale = float(what.group(3))
if len(shell_type) == 1:
am = shell_to_am[shell_type[0]]
exponents = [0.0] * nprimitive
contractions = [0.0] * nprimitive
for p in range(nprimitive):
line = lines[lineno]
lineno += 1
line = line.replace('D', 'e', 2)
line = line.replace('d', 'e', 2)
what = primitives1.match(line)
# Must match primitives1; will work on the others later
if not what:
raise ValidationError("""Gaussian94BasisSetParser::parse: Unable to match an exponent with one contraction: line %d: %s""" % (lineno, line))
exponent = float(what.group(1))
contraction = float(what.group(2))
# Scale the contraction and save the information
contraction *= scale
exponents[p] = exponent
contractions[p] = contraction
# We have a full shell, push it to the basis set
shell_list.append(ShellInfo(am, contractions, exponents,
gaussian_type, 0, center, 0, 'Unnormalized'))
elif len(shell_type) == 2:
# This is to handle instances of SP, PD, DF, FG, ...
am1 = shell_to_am[shell_type[0]]
am2 = shell_to_am[shell_type[1]]
exponents = [0.0] * nprimitive
contractions1 = [0.0] * nprimitive
contractions2 = [0.0] * nprimitive
for p in range(nprimitive):
line = lines[lineno]
lineno += 1
line = line.replace('D', 'e', 2)
line = line.replace('d', 'e', 2)
what = primitives2.match(line)
# Must match primitivies2
if not what:
raise ValidationError("Gaussian94BasisSetParser::parse: Unable to match an exponent with two contractions: line %d: %s" % (lineno, line))
exponent = float(what.group(1))
contraction = float(what.group(2))
# Scale the contraction and save the information
contraction *= scale
exponents[p] = exponent
contractions1[p] = contraction
# Do the other contraction
contraction = float(what.group(3))
# Scale the contraction and save the information
contraction *= scale
contractions2[p] = contraction
shell_list.append(ShellInfo(am1, contractions1, exponents,
gaussian_type, 0, center, 0, 'Unnormalized'))
shell_list.append(ShellInfo(am2, contractions2, exponents,
gaussian_type, 0, center, 0, 'Unnormalized'))
else:
raise ValidationError("""Gaussian94BasisSetParser::parse: Unable to parse basis sets with spd, or higher grouping""")
else:
raise ValidationError("""Gaussian94BasisSetParser::parse: Expected shell information, but got: line %d: %s""" % (lineno, line))
line = lines[lineno]
lineno += 1
break
if not found:
#raise BasisSetNotFound("Gaussian94BasisSetParser::parser: Unable to find the basis set for %s in %s" % \
# (symbol, self.filename), silent=True)
return None, None
return shell_list, msg
|