1#!/usr/bin/env python
2# Copyright 2014-2018,2021 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: Timothy Berkelbach <tim.berkelbach@gmail.com>
17#
18
19'''
20parse CP2K format
21'''
22
23import re
24from pyscf.gto.basis import parse_nwchem
25from pyscf import __config__
26
27DISABLE_EVAL = getattr(__config__, 'DISABLE_EVAL', False)
28
29MAXL = 8
30
31def parse(string, optimize=False):
32    '''Parse the basis text which is in CP2K format, return an internal
33    basis format which can be assigned to :attr:`Mole.basis`
34    Lines started with # are ignored.
35    '''
36    bastxt = []
37    for dat in string.splitlines():
38        x = dat.split('#')[0].strip()
39        if (x and not x.startswith('END') and not x.startswith('BASIS')):
40            bastxt.append(x)
41    return _parse(bastxt, optimize)
42
43def load(basisfile, symb, optimize=False):
44    return _parse(search_seg(basisfile, symb), optimize)
45
46def _parse(blines, optimize=False):
47    header_ln = blines.pop(0)  # noqa: F841
48    nsets = int(blines.pop(0))
49    basis = []
50    for n in range(nsets):
51        comp = [int(p) for p in blines.pop(0).split()]
52        lmin, lmax, nexps, ncontractions = comp[1], comp[2], comp[3], comp[4:]
53        basis_n = [[l] for l in range(lmin,lmax+1)]
54        for nexp in range(nexps):
55            line = blines.pop(0)
56            dat = line.split()
57            try:
58                bfun = [float(x) for x in dat]
59            except ValueError:
60                if DISABLE_EVAL:
61                    raise ValueError('Failed to parse basis %s' % line)
62                else:
63                    bfun = eval(','.join(dat))
64            exp = bfun.pop(0)
65            for i,l in enumerate(range(lmin,lmax+1)):
66                cl = [exp]
67                for c in range(ncontractions[i]):
68                    cl.append(bfun.pop(0))
69                basis_n[i].append(tuple(cl))
70        basis.extend(basis_n)
71    basis_sorted = []
72    for l in range(MAXL):
73        basis_sorted.extend([b for b in basis if b[0] == l])
74
75    if optimize:
76        basis_sorted = parse_nwchem.optimize_contraction(basis_sorted)
77
78    basis_sorted = parse_nwchem.remove_zero(basis_sorted)
79    return basis_sorted
80
81BASIS_SET_DELIMITER = re.compile('# *BASIS SET.*\n')
82def search_seg(basisfile, symb):
83    with open(basisfile, 'r') as fin:
84        fdata = re.split(BASIS_SET_DELIMITER, fin.read())
85    for dat in fdata[1:]:
86        dat0 = dat.split(None, 1)
87        if dat0 and dat0[0] == symb:
88            # remove blank lines
89            return [x.strip() for x in dat.splitlines()
90                    if x.strip() and 'END' not in x]
91    raise RuntimeError('Basis not found for  %s  in  %s' % (symb, basisfile))
92
93
94