1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2017, the cclib development team
4#
5# This file is part of cclib (http://cclib.github.io) and is distributed under
6# the terms of the BSD 3-Clause License.
7
8"""Test logfiles related to basis sets"""
9
10import os
11import unittest
12
13from skip import skipForParser
14
15__filedir__ = os.path.realpath(os.path.dirname(__file__))
16
17
18class GenericBasisTest(unittest.TestCase):
19    """Generic basis set unittest"""
20
21    # The number of contraction per atom, by atom number.
22    contractions = { 1: 1, 6: 3 }
23
24    # Number of components in each contraction by subshell type,
25    # so that we can infer nbasis from gbasis. Note how we assume
26    # the basis set is not is spherical representation.
27    names = ['S', 'P', 'D', 'F', 'G']
28    multiple = {'S': 1, 'P': 3, 'D': 6, 'F': 10, 'G': 15}
29    multiple_spher = {'S': 1, 'P': 3, 'D': 5, 'F': 7, 'G': 9}
30    spherical = False
31
32    # These are the expected exponents and coefficients for the first
33    # Gaussians in particular shells for hydrogen and carbon atoms.
34    gbasis_H_1s_func0 = [3.42525, 0.15433]
35    gbasis_C_2s_func0 = [2.9412, -0.1000]
36    gbasis_C_2p_func0 = [2.9412, 0.1559]
37
38    @skipForParser('Turbomole','The parser is still being developed so we skip this test')
39    def testgbasis(self):
40        """Is gbasis the right length?"""
41        self.assertEqual(self.data.natom, len(self.data.gbasis))
42
43    @skipForParser('Turbomole','The parser is still being developed so we skip this test')
44    def testnames(self):
45        """Are the name of basis set functions acceptable?"""
46        for atom in self.data.gbasis:
47            for fns in atom:
48                self.assertTrue(fns[0] in self.names,
49                             "%s not one of S or P" % fns[0])
50
51    @skipForParser('Turbomole','The parser is still being developed so we skip this test')
52    def testsizeofbasis(self):
53        """Is the basis set the correct size?"""
54
55        total = 0
56        multiple = self.multiple_spher if self.spherical else self.multiple
57        for atom in self.data.gbasis:
58            for (ftype, contraction) in atom:
59                total += multiple[ftype]
60
61        self.assertEqual(self.data.nbasis, total)
62
63    @skipForParser('Turbomole','The parser is still being developed so we skip this test')
64    def testcontractions(self):
65        """Are the number of contractions on all atoms correct?"""
66        for iatom, atom in enumerate(self.data.gbasis):
67            atomno = self.data.atomnos[iatom]
68            self.assertEqual(len(atom), self.contractions[atomno])
69
70    @skipForParser('Turbomole','The parser is still being developed so we skip this test')
71    def testprimitives(self):
72        """Are all primitives 2-tuples?"""
73        for atom in self.data.gbasis:
74            for ftype, contraction in atom:
75                for primitive in contraction:
76                    self.assertEqual(len(primitive), 2)
77
78    @skipForParser('Turbomole','The parser is still being developed so we skip this test')
79    def testcoeffs(self):
80        """Are the atomic basis set exponents and coefficients correct?"""
81
82        for iatom,atom in enumerate(self.data.gbasis):
83            if self.data.atomnos[iatom] == 1:
84                coeffs = atom[0][1]
85                self.assertAlmostEqual(coeffs[0][0], self.gbasis_H_1s_func0[0], 4)
86                self.assertAlmostEqual(coeffs[0][1], self.gbasis_H_1s_func0[1], 4)
87            else:
88                s_coeffs = atom[1][1]
89                p_coeffs = atom[2][1]
90                self.assertAlmostEqual(s_coeffs[0][0], self.gbasis_C_2s_func0[0], 4)
91                self.assertAlmostEqual(p_coeffs[0][0], self.gbasis_C_2p_func0[0], 4)
92                self.assertAlmostEqual(s_coeffs[0][1], self.gbasis_C_2s_func0[1], 4)
93                self.assertAlmostEqual(p_coeffs[0][1], self.gbasis_C_2p_func0[1], 4)
94
95
96class JaguarBasisTest(GenericBasisTest):
97    """Customized basis set unittest"""
98
99    # For some reason, Jaguar seems to use slightly different coefficients for
100    # contractions in the STO-3G basis set. Or perhaps we don't understand something.
101    gbasis_H_1s_func0 = [3.42525, 0.24050]
102    gbasis_C_2s_func0 = [2.941249, -0.29565]
103    gbasis_C_2p_func0 = [2.941249, 0.22135]
104
105
106class GenericBigBasisTest(GenericBasisTest):
107    """Generic big basis set unittest"""
108
109    contractions = { 6: 20 }
110
111    @unittest.skip('Write up a new test, and/or revise the one inherited.')
112    def testcoeffs(self):
113        """Are the basis set coefficients correct?"""
114        self.assertEqual(1, 1)
115
116    @unittest.skip('# of contractions is 20 for VQZ, but 29 for CVQZ; unify files first.')
117    def testcontractions(self):
118        """"""
119        self.assertEqual(1, 1)
120
121
122class DALTONBigBasisTest(GenericBigBasisTest):
123    """Customized big basis set unittest"""
124    spherical = True
125
126
127class GaussianBigBasisTest(GenericBigBasisTest):
128    """Customized big basis set unittest"""
129    spherical = True
130
131
132class JaguarBigBasisTest(GenericBigBasisTest):
133    """Customized big basis set unittest"""
134
135    spherical = True
136
137    # Jaguar only goes up to F functions.
138    names = ['S', 'P', 'D', 'F']
139
140
141class MolcasBigBasisTest(GenericBigBasisTest):
142    """Customized big basis set unittest"""
143    spherical = True
144
145
146class MolproBigBasisTest(GenericBigBasisTest):
147    """Customized big basis set unittest"""
148    spherical = True
149
150
151class Psi4BigBasisTest(GenericBigBasisTest):
152    """Customized big basis set unittest"""
153    spherical = True
154
155
156class QChemBigBasisTest(GenericBigBasisTest):
157    """Customized big basis set unittest"""
158    spherical = True
159
160
161if __name__=="__main__":
162
163    import sys
164    sys.path.insert(1, os.path.join(__filedir__, ".."))
165
166    from test_data import DataSuite
167    suite = DataSuite(['Basis'])
168    suite.testall()
169