1#!/usr/bin/env python 2# Copyright 2014-2020 The PySCF Developers. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16# Author: Qiming Sun <osirpt.sun@gmail.com> 17# 18 19''' 20Parsers for basis set in Gaussian program format 21''' 22 23__all__ = ['parse', 'load'] 24 25try: 26 from pyscf.gto.basis.parse_nwchem import optimize_contraction 27 from pyscf.gto.basis.parse_nwchem import remove_zero 28except ImportError: 29 optimize_contraction = lambda basis: basis 30 remove_zero = lambda basis: basis 31 32MAXL = 12 33SPDF = 'SPDFGHIJKLMN' 34MAPSPDF = {key: l for l, key in enumerate(SPDF)} 35 36DELIMETER = '****' 37 38def parse(string, optimize=True): 39 '''Parse the basis text which is in NWChem format, return an internal 40 basis format which can be assigned to :attr:`Mole.basis` 41 Lines started with # are ignored. 42 ''' 43 raw_basis = [] 44 for dat in string.splitlines(): 45 x = dat.split('!', 1)[0].strip() 46 if x and x != DELIMETER: 47 raw_basis.append(x) 48 return _parse(raw_basis, optimize) 49 50def load(basisfile, symb, optimize=True): 51 raw_basis = search_seg(basisfile, symb) 52 #if not raw_basis: 53 # raise BasisNotFoundError('Basis not found for %s in %s' % (symb, basisfile)) 54 return _parse(raw_basis, optimize) 55 56def search_seg(basisfile, symb): 57 with open(basisfile, 'r') as fin: 58 59 def _seek(test_str): 60 raw_basis = [] 61 dat = fin.readline() 62 while dat: 63 if test_str in dat: 64 return True, raw_basis 65 elif dat.strip(): # Skip empty lines 66 raw_basis.append(dat) 67 dat = fin.readline() 68 return False, raw_basis 69 70 has_delimeter, raw_basis = _seek(DELIMETER) 71 if has_delimeter: 72 dat = fin.readline() 73 while dat: 74 if dat.strip().split(' ', 1)[0].upper() == symb.upper(): 75 raw_basis = _seek(DELIMETER)[1] 76 break 77 else: 78 _seek(DELIMETER) 79 dat = fin.readline() 80 return raw_basis 81 82def _parse(raw_basis, optimize=True): 83 basis_add = [] 84 for line in raw_basis: 85 dat = line.strip() 86 if dat.startswith('!'): 87 continue 88 elif dat[0].isalpha(): 89 key = dat.split() 90 if len(key) == 2: 91 # skip the line which has only two items. It's the line for 92 # element symbol 93 continue 94 elif key[0] == 'SP': 95 basis_add.append([0]) 96 basis_add.append([1]) 97 elif len(key[0])>2 and key[0][:2] in ['l=', 'L=']: 98 # Angular momentum defined explicitly 99 basis_add.append([int(key[0][2:])]) 100 else: 101 basis_add.append([MAPSPDF[key[0]]]) 102 else: 103 line = [float(x) for x in dat.replace('D','e').split()] 104 if key[0] == 'SP': 105 basis_add[-2].append([line[0], line[1]]) 106 basis_add[-1].append([line[0], line[2]]) 107 else: 108 basis_add[-1].append(line) 109 basis_sorted = [] 110 for l in range(MAXL): 111 basis_sorted.extend([b for b in basis_add if b[0] == l]) 112 113 if optimize: 114 basis_sorted = optimize_contraction(basis_sorted) 115 116 basis_sorted = remove_zero(basis_sorted) 117 return basis_sorted 118 119if __name__ == '__main__': 120 print(load('def2-qzvp-jkfit.gbs', 'C')) 121