1# Copyright 2014-2018 The PySCF Developers. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import unittest
16import numpy
17from pyscf import gto
18from pyscf.pbc import gto as pbcgto
19from pyscf.pbc import tools
20from pyscf.pbc.scf import khf
21from pyscf import lib
22
23
24class KnownValues(unittest.TestCase):
25    def test_coulG_ws(self):
26        cell = pbcgto.Cell()
27        cell.unit = 'A'
28        cell.atom = 'C 0.,  0.,  0.; C 0.8917,  0.8917,  0.8917'
29        cell.a = '''0.      1.7834  1.7834
30                    1.7834  0.      1.7834
31                    1.7834  1.7834  0.    '''
32        cell.basis = 'gth-szv'
33        cell.pseudo = 'gth-pade'
34        cell.mesh = [11]*3
35        cell.verbose = 5
36        cell.output = '/dev/null'
37        cell.build()
38        mf = khf.KRHF(cell, exxdiv='vcut_ws')
39        mf.kpts = cell.make_kpts([2,2,2])
40        coulG = tools.get_coulG(cell, mf.kpts[2], True, mf, gs=[5,5,5])
41        self.assertAlmostEqual(lib.fp(coulG), 1.3245365170998518+0j, 9)
42
43    def test_unconventional_ws_cell(self):
44        cell = pbcgto.Cell()
45        cell.atom = 'He'
46        cell.basis = [[0, (1, 1)]]
47        cell.a = '''4.3, 0.7, 1.2
48                    0.4, 2.0, 0.1
49                    0.5, 0  , 1.8'''
50        cell.build()
51        kpts = cell.make_kpts([1,1,1])
52        self.assertRaises(RuntimeError, tools.precompute_exx, cell, kpts)
53
54    def test_coulG(self):
55        numpy.random.seed(19)
56        kpt = numpy.random.random(3)
57        cell = pbcgto.Cell()
58        cell.unit = 'A'
59        cell.atom = 'C 0.,  0.,  0.; C 0.8917,  0.8917,  0.8917'
60        cell.a = numpy.array(((0.    , 1.7834, 1.7834),
61                              (1.7834, 0.    , 1.7834),
62                              (1.7834, 1.7834, 0.    ),)) + numpy.random.random((3,3)).T
63        cell.basis = 'gth-szv'
64        cell.pseudo = 'gth-pade'
65        cell.mesh = [11,9,7]
66        cell.verbose = 5
67        cell.output = '/dev/null'
68        cell.build()
69        coulG = tools.get_coulG(cell, kpt)
70        self.assertAlmostEqual(lib.fp(coulG), 62.75448804333378, 9)
71
72        cell.a = numpy.eye(3)
73        cell.unit = 'B'
74        coulG = tools.get_coulG(cell, numpy.array([0, numpy.pi, 0]))
75        self.assertAlmostEqual(lib.fp(coulG), 4.6737453679713905, 9)
76        coulG = tools.get_coulG(cell, numpy.array([0, numpy.pi, 0]),
77                                wrap_around=False)
78        self.assertAlmostEqual(lib.fp(coulG), 4.5757877990664744, 9)
79        coulG = tools.get_coulG(cell, exx='ewald')
80        self.assertAlmostEqual(lib.fp(coulG), 4.888843468914021, 9)
81
82    #def test_coulG_2d(self):
83    #    cell = pbcgto.Cell()
84    #    cell.a = numpy.eye(3)
85    #    cell.a[2] = numpy.array((0, 0, 20))
86    #    cell.atom = 'He 0 0 0'
87    #    cell.unit = 'B'
88    #    cell.mesh = [9,9,40]
89    #    cell.verbose = 5
90    #    cell.dimension = 2
91    #    cell.output = '/dev/null'
92    #    cell.build()
93    #    coulG = tools.get_coulG(cell)
94    #    self.assertAlmostEqual(lib.fp(coulG), -4.7118365257800496, 9)
95
96
97    def test_get_lattice_Ls(self):
98        numpy.random.seed(2)
99        cl1 = pbcgto.M(a = numpy.random.random((3,3))*3,
100                       mesh = [3]*3,
101                       atom ='''He .1 .0 .0''',
102                       basis = 'ccpvdz')
103        Ls = tools.get_lattice_Ls(cl1)
104        self.assertEqual(Ls.shape, (2099,3))
105
106        Ls = tools.get_lattice_Ls(cl1, rcut=0)
107        self.assertEqual(Ls.shape, (1,3))
108
109    def test_get_lattice_Ls1(self):
110        cell = pbcgto.Cell()
111        cell.verbose = 0
112        cell.a = '''
113-10.11124892   0.          10.11124892
114  0.          10.11124892  10.11124892
115-10.11124892  10.11124892   0.        '''
116        cell.atom = '''
117C   0.          0.          0.
118C  13.48166522  6.74083261  6.74083261
119C  15.16687337  8.42604076  8.42604076
120C  13.48166522 10.11124892 10.11124892
121C  15.16687337 11.79645707 11.79645707
122C  10.11124892 13.48166522 10.11124892
123C  11.79645707 15.16687337 11.79645707
124C  13.48166522 13.48166522 13.48166522
125C  15.16687337 15.16687337 15.16687337
126'''
127        cell.unit= 'B'
128        cell.basis = 'gth-dzvp'
129        cell.pseudo = 'gth-pade'
130        cell.precision = 1e-10
131        cell.build()
132        Ls = cell.get_lattice_Ls()
133        self.assertTrue(Ls.shape[0] > 140)
134
135        S = cell.pbc_intor('int1e_ovlp')
136        w, v = numpy.linalg.eigh(S)
137        self.assertTrue(w.min() > 0)
138        self.assertAlmostEqual(abs(S - S.T.conj()).max(), 0, 13)
139        self.assertAlmostEqual(w.min(), 0.0007176363230, 8)
140
141    def test_super_cell(self):
142        numpy.random.seed(2)
143        cl1 = pbcgto.M(a = numpy.random.random((3,3))*3,
144                       mesh = [3]*3,
145                       atom ='''He .1 .0 .0''',
146                       basis = 'ccpvdz')
147        cl2 = tools.super_cell(cl1, [2,3,4])
148        self.assertAlmostEqual(lib.fp(cl2.atom_coords()), -18.946080642714836, 9)
149        self.assertAlmostEqual(lib.fp(cl2._bas[:,gto.ATOM_OF]), 16.515144238434807, 9)
150
151    def test_cell_plus_imgs(self):
152        numpy.random.seed(2)
153        cl1 = pbcgto.M(a = numpy.random.random((3,3))*3,
154                       mesh = [3]*3,
155                       atom ='''He .1 .0 .0''',
156                       basis = 'ccpvdz')
157        self.assertTrue(numpy.all(cl1.nimgs == numpy.array([8, 15, 11])))
158        cl2 = tools.cell_plus_imgs(cl1, [3,4,5])
159        self.assertAlmostEqual(lib.fp(cl2.atom_coords()), 4.791699273649499, 9)
160        self.assertAlmostEqual(lib.fp(cl2._bas[:,gto.ATOM_OF]), -681.993543446207, 9)
161
162    def test_madelung(self):
163        cell = pbcgto.Cell()
164        cell.atom = 'He 0 0 0'
165        cell.a = '''0.      1.7834  1.7834
166                    1.7834  0.      1.7834
167                    1.7834  1.7834  0.    '''
168        cell.build()
169        scell = tools.super_cell(cell, [2,3,5])
170        mad0 = tools.madelung(scell, [0,0,0])
171        kpts = cell.make_kpts([2,3,5])
172        mad1 = tools.madelung(cell, kpts)
173        self.assertAlmostEqual(mad0-mad1, 0, 9)
174
175    def test_fft(self):
176        n = 31
177        a = numpy.random.random([2,n,n,n])
178        ref = numpy.fft.fftn(a, axes=(1,2,3)).ravel()
179        v = tools.fft(a, [n,n,n]).ravel()
180        self.assertAlmostEqual(abs(ref-v).max(), 0, 10)
181
182        a = numpy.random.random([2,n,n,8])
183        ref = numpy.fft.fftn(a, axes=(1,2,3)).ravel()
184        v = tools.fft(a, [n,n,8]).ravel()
185        self.assertAlmostEqual(abs(ref-v).max(), 0, 10)
186
187        a = numpy.random.random([2,8,n,8])
188        ref = numpy.fft.fftn(a, axes=(1,2,3)).ravel()
189        v = tools.fft(a, [8,n,8]).ravel()
190        self.assertAlmostEqual(abs(ref-v).max(), 0, 10)
191
192    def test_ifft(self):
193        n = 31
194        a = numpy.random.random([2,n,n,n])
195        ref = numpy.fft.ifftn(a, axes=(1,2,3)).ravel()
196        v = tools.ifft(a, [n,n,n]).ravel()
197        self.assertAlmostEqual(abs(ref-v).max(), 0, 10)
198
199        a = numpy.random.random([2,n,n,8])
200        ref = numpy.fft.ifftn(a, axes=(1,2,3)).ravel()
201        v = tools.ifft(a, [n,n,8]).ravel()
202        self.assertAlmostEqual(abs(ref-v).max(), 0, 10)
203
204        a = numpy.random.random([2,8,n,8])
205        ref = numpy.fft.ifftn(a, axes=(1,2,3)).ravel()
206        v = tools.ifft(a, [8,n,8]).ravel()
207        self.assertAlmostEqual(abs(ref-v).max(), 0, 10)
208
209
210if __name__ == '__main__':
211    print("Full Tests for pbc.tools")
212    unittest.main()
213