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
16import copy
17import unittest
18import tempfile
19from functools import reduce
20import numpy
21import scipy.linalg
22from pyscf import gto
23from pyscf import lib
24import pyscf.lib.parameters as param
25from pyscf.lib.exceptions import BasisNotFoundError, PointGroupSymmetryError
26
27mol0 = gto.Mole()
28mol0.atom = [
29    [1  , (0.,1.,1.)],
30    ["O1", (0.,0.,0.)],
31    [1  , (1.,1.,0.)], ]
32mol0.nucmod = { "O":'gaussian', 3:'g' }
33mol0.unit = 'ang'
34mol0.basis = {
35    "O": [(0, 0, (15, 1)), ] + gto.etbs(((0, 4, 1, 1.8),
36                                         (1, 3, 2, 1.8),
37                                         (2, 2, 1, 1.8),)),
38    "H": [(0, 0, (1, 1, 0), (3, 3, 1), (5, 1, 0)),
39          (1, -2, (1, 1)), ]}
40mol0.symmetry = 1
41mol0.charge = 1
42mol0.spin = 1
43mol0.verbose = 7
44mol0.ecp = {'O1': 'lanl2dz'}
45ftmp = tempfile.NamedTemporaryFile()
46mol0.output = ftmp.name
47mol0.build()
48
49def tearDownModule():
50    global mol0, ftmp
51    mol0.stdout.close()
52    del mol0, ftmp
53
54class KnownValues(unittest.TestCase):
55    def test_intor_cross(self):
56        mol1 = mol0.unpack(mol0.pack())
57        mol1.symmetry = True
58        mol1.unit = 'Ang'
59        mol1.atom = '''
60                1    0  1  .5*2
61                O    0  0  0*np.exp(0)
62                h    1  1  0'''
63        mol1.basis = {'O': gto.basis.parse('''
64C    S
65   3047.5249000              0.0018347*1.0
66    457.3695100              0.0140373*1.0
67    103.9486900              0.0688426*1.0
68     29.2101550              0.2321844*1.0
69      9.2866630              0.4679413*1.0
70      3.1639270              0.3623120*1.0
71#     1.                     0.1
72C    SP
73      7.8682724             -0.1193324*1.0          0.0689991
74      1.8812885             -0.1608542*1.0          0.3164240
75      0.5442493              1.1434564*1.0          0.7443083
76C    SP
77      0.1687144              1.0000000              1.0000000'''),
78                      'H': '6-31g'}
79        mol1.build()
80        v = gto.mole.intor_cross('cint1e_ovlp_sph', mol0, mol1)
81        self.assertAlmostEqual(numpy.linalg.norm(v), 3.6489423434168562, 1)
82
83    def test_num_basis(self):
84        self.assertEqual(mol0.nao_nr(), 34)
85        self.assertEqual(mol0.nao_2c(), 64)
86
87    def test_time_reversal_map(self):
88        tao = [ -2,  1, -4,  3,  8, -7,  6, -5,-10,  9,-12, 11,-14, 13,-16, 15,-18, 17,
89                20,-19, 24,-23, 22,-21, 26,-25, 30,-29, 28,-27, 32,-31, 36,-35, 34,-33,
90               -40, 39,-38, 37,-46, 45,-44, 43,-42, 41,-50, 49,-48, 47,-56, 55,-54, 53,
91               -52, 51,-58, 57,-60, 59, 64,-63, 62,-61]
92        self.assertEqual(list(mol0.time_reversal_map()), tao)
93
94    def test_check_sanity(self):
95        mol1 = mol0.copy()
96        mol1.x = None
97        mol1.copy = None
98        mol1.check_sanity()
99
100    def test_nao_range(self):
101        self.assertEqual(mol0.nao_nr_range(1,4), (2, 7))
102        self.assertEqual(mol0.nao_2c_range(1,4), (4, 12))
103        self.assertEqual(numpy.dot(range(mol0.nbas+1), mol0.ao_loc_nr()), 2151)
104        self.assertEqual(numpy.dot(range(mol0.nbas+1), mol0.ao_loc_2c()), 4066)
105
106    def test_search_bas(self):
107        self.assertEqual(mol0.search_shell_id(1, 1), 7)
108        self.assertRaises(RuntimeError, mol0.search_ao_nr, 1, 1, -1, 5)
109        self.assertEqual(mol0.search_ao_nr(1, 1, -1, 4), 16)
110        mol0.cart = True
111        self.assertEqual(mol0.search_ao_nr(2, 1, -1, 1), 30)
112        mol0.cart = False
113
114    def test_atom_types(self):
115        atoms = [['H0', ( 0, 0, 0)],
116                 ['H1', ( 0, 0, 0)],
117                 ['H',  ( 0, 0, 0)],
118                 ['H3', ( 0, 0, 0)]]
119        basis = {'H':'sto3g', 'H1': '6-31g'}
120        atmgroup = gto.mole.atom_types(atoms, basis)
121        self.assertEqual(atmgroup, {'H': [0, 2, 3], 'H1': [1]})
122        atoms = [['H0', ( 0, 0, 0)],
123                 ['H1', ( 0, 0, 0)],
124                 ['H2', ( 0, 0, 0)],
125                 ['H3', ( 0, 0, 0)]]
126        basis = {'H2':'sto3g', 'H3':'6-31g', 'H0':'sto3g', 'H1': '6-31g'}
127        atmgroup = gto.mole.atom_types(atoms, basis)
128        self.assertEqual(atmgroup, {'H2': [2], 'H3': [3], 'H0': [0], 'H1': [1]})
129
130    def test_input_symmetry(self):
131        mol = gto.M(atom='H 0 0 -1; H 0 0 1', symmetry='D2h')
132        self.assertEqual(mol.irrep_id, [0, 5])
133        mol = gto.M(atom='H 0 0 -1; H 0 0 1', symmetry='D2')
134        self.assertEqual(mol.irrep_id, [0, 1])
135        mol = gto.M(atom='H 0 0 -1; H 0 0 1', symmetry='C2v')
136        self.assertEqual(mol.irrep_id, [0])
137
138    def test_dumps_loads(self):
139        import warnings
140        mol1 = gto.M()
141        mol1.x = lambda *args: None
142        with warnings.catch_warnings(record=True) as w:
143            warnings.simplefilter("always")
144            d = mol1.dumps()
145            self.assertTrue(w[0].category, UserWarning)
146        mol1.loads(mol0.dumps())
147
148    def test_symm_orb_serialization(self):
149        '''Handle the complex symmetry-adapted orbitals'''
150        mol = gto.M(atom='He', basis='ccpvdz', symmetry=True)
151        mol.loads(mol.dumps())
152
153        lz_minus = numpy.sqrt(.5) * (mol.symm_orb[3] - mol.symm_orb[2] * 1j)
154        lz_plus = -numpy.sqrt(.5) * (mol.symm_orb[3] + mol.symm_orb[2] * 1j)
155        mol.symm_orb[2] = lz_minus
156        mol.symm_orb[3] = lz_plus
157        mol.loads(mol.dumps())
158        self.assertTrue(mol.symm_orb[0].dtype == numpy.double)
159        self.assertTrue(mol.symm_orb[2].dtype == numpy.complex128)
160        self.assertTrue(mol.symm_orb[3].dtype == numpy.complex128)
161
162    def test_same_mol1(self):
163        self.assertTrue(gto.same_mol(mol0, mol0))
164        mol1 = gto.M(atom='h   0  1  1; O1  0  0  0;  h   1  1  0')
165        self.assertTrue(not gto.same_mol(mol0, mol1))
166        self.assertTrue(gto.same_mol(mol0, mol1, cmp_basis=False))
167
168        mol1 = gto.M(atom='h   0  1  1; O1  0  0  0;  h   1  1  0.01')
169        self.assertTrue(not gto.same_mol(mol0, mol1, cmp_basis=False))
170        self.assertTrue(gto.same_mol(mol0, mol1, tol=.02, cmp_basis=False))
171
172        mol1 = gto.M(atom='''H 0.0052917700 0.0000000000 -0.8746076326
173                             F 0.0000000000 0.0000000000 0.0516931447''')
174        mol2 = gto.M(atom='''H 0.0000000000 0.0000000000 -0.8746076326
175                             F 0.0000000000 0.0000000000 0.0516931447''')
176        self.assertTrue(gto.same_mol(mol1, mol2))
177        self.assertTrue(not gto.same_mol(mol1, mol2, tol=1e-6))
178        mol3 = gto.M(atom='''H 0.0000000000 0.0000000000 -0.8746076326
179                             H 0.0000000000 0.0000000000 0.0516931447''')
180        self.assertTrue(not gto.same_mol(mol3, mol2))
181
182    def test_same_mol2(self):
183        mol1 = gto.M(atom='H 0.0052917700 0.0000000000 -0.8746076326; F 0.0000000000 0.0000000000 0.0464013747')
184        mol2 = gto.M(atom='H 0.0000000000 0.0000000000 -0.8746076326; F 0.0052917700 0.0000000000 0.0464013747')
185        self.assertTrue(gto.same_mol(mol1, mol2))
186
187        mol1 = gto.M(atom='H 0.0052917700 0.0000000000 -0.8693158626; F 0.0000000000 0.0000000000 0.0464013747')
188        mol2 = gto.M(atom='H 0.0000000000 0.0052917700 -0.8693158626; F 0.0000000000 0.0000000000 0.0464013747')
189        mol3 = gto.M(atom='H 0.0000000000 0.0000000000 -0.8693158626; F 0.0052917700 0.0000000000 0.0464013747')
190        mol4 = gto.M(atom='H -0.0052917700 0.0000000000 -0.8746076326; F 0.0000000000 0.0000000000 0.0411096047')
191        mols = (mol1, mol2, mol3, mol4)
192        for i,mi in enumerate(mols):
193            for j in range(i):
194                self.assertTrue(gto.same_mol(mols[i], mols[j]))
195
196        mol1 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000
197          H 0.9497795800 1.3265673200 0.0000000000
198          H 0.9444878100 -1.3265673200 0.0000000000
199          H1 -0.9444878100 0.0000000000 1.3265673200
200          H1 -0.9444878100 0.0000000000 -1.3265673200''', basis={'H':'sto3g', 'H1':'sto3g'}, charge=1)
201        mol2 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000
202          H 0.9444878100 1.3265673200 0.0000000000
203          H 0.9497795800 -1.3265673200 0.0000000000
204          H1 -0.9444878100 0.0000000000 1.3265673200
205          H1 -0.9444878100 0.0000000000 -1.3265673200''', basis={'H':'sto3g', 'H1':'sto3g'}, charge=1)
206        self.assertTrue(gto.same_mol(mol1, mol2))
207        self.assertEqual(len(gto.atom_types(mol1._atom)), 2)
208        mol3 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000
209          H1 0.9497795800 1.3265673200 0.0000000000
210          H1 0.9444878100 -1.3265673200 0.0000000000
211          H1 -0.9444878100 0.0000000000 1.3265673200
212          H1 -0.9444878100 0.0000000000 -1.3265673200''', basis={'H':'sto3g', 'H1':'321g'}, charge=1)
213        self.assertTrue(not gto.same_mol(mol3, mol2))
214
215    def test_inertia_momentum(self):
216        mol1 = gto.Mole()
217        mol1.atom = mol0.atom
218        mol1.nucmod = 'G'
219        mol1.verbose = 5
220        mol1.nucprop = {'H': {'mass': 3}}
221        mol1.output = '/dev/null'
222        mol1.build(False, False)
223        self.assertAlmostEqual(lib.fp(gto.inertia_moment(mol1)),
224                               5.340587366981696, 9)
225
226        mass = mol0.atom_mass_list(isotope_avg=True)
227        self.assertAlmostEqual(lib.fp(gto.inertia_moment(mol1, mass)),
228                               2.1549269955776205, 9)
229
230    def test_chiral_mol(self):
231        mol1 = gto.M(atom='C 0 0 0; H 1 1 1; He -1 -1 1; Li -1 1 -1; Be 1 -1 -1')
232        mol2 = gto.M(atom='C 0 0 0; H 1 1 1; He -1 -1 1; Be -1 1 -1; Li 1 -1 -1')
233        self.assertTrue(gto.chiral_mol(mol1, mol2))
234        self.assertTrue(gto.chiral_mol(mol1))
235
236        mol1 = gto.M(atom='''H 0.9444878100 1.3265673200 0.0052917700
237                            H 0.9444878100 -1.3265673200 0.0000000000
238                            H -0.9444878100 0.0000000000 1.3265673200
239                            H -0.9444878100 0.0000000000 -1.3265673200''')
240        mol2 = gto.M(atom='''H 0.9444878100 1.3265673200 0.0000000000
241                            H 0.9444878100 -1.3265673200 0.0052917700
242                            H -0.9444878100 0.0000000000 1.3265673200
243                            H -0.9444878100 0.0000000000 -1.3265673200''')
244        self.assertTrue(gto.chiral_mol(mol1, mol2))
245
246        mol1 = gto.M(atom='''H 0.9444878100 1.3265673200 0.0052917700
247                            H 0.9444878100 -1.3265673200 0.0000000000
248                            H -0.9444878100 0.0000000000 1.3265673200
249                            H -0.9444878100 0.0000000000 -1.3265673200''')
250        self.assertTrue(gto.chiral_mol(mol1))
251
252    def test_first_argument(self):
253        mol1 = gto.Mole()
254        mol1.build('He')
255        self.assertEqual(mol1.natm, 1)
256
257    def test_atom_as_file(self):
258        ftmp = tempfile.NamedTemporaryFile('w')
259        # file in xyz format
260        ftmp.write('He 0 0 0\nHe 0 0 1\n')
261        ftmp.flush()
262        mol1 = gto.M(atom=ftmp.name)
263        self.assertEqual(mol1.natm, 2)
264
265        # file in zmatrix format
266        ftmp = tempfile.NamedTemporaryFile('w')
267        ftmp.write('He\nHe 1 1.5\n')
268        ftmp.flush()
269        mol1 = gto.M(atom=ftmp.name)
270        self.assertEqual(mol1.natm, 2)
271
272    def test_format_atom(self):
273        atoms = [['h' , 0,1,1], "O1  0. 0. 0.", [1, 1.,1.,0.],]
274        self.assertTrue(numpy.allclose(gto.mole.format_atom(atoms, unit='Ang')[0][1],
275                                       [0.0, 1.8897261245650618, 1.8897261245650618]))
276        atoms = '''h 0 1 1
277        O1 0 0 0; 1 1 1 0; #H 0 0 3'''
278        self.assertTrue(numpy.allclose(gto.mole.format_atom(atoms, unit=1)[0][1],
279                                       [0.0, 1., 1.]))
280        atoms = 'O1; h 1 1; 1 1 1 2 90'
281        atoms = gto.mole.format_atom(atoms, unit=1)[2]
282        self.assertEqual(atoms[0], 'H')
283        self.assertTrue(numpy.allclose(atoms[1], [0, 0, 1.]))
284
285    def test_format_basis(self):
286        mol = gto.M(atom = '''O 0 0 0; 1 0 1 0; H 0 0 1''',
287                    basis = {8: 'ccpvdz'})
288        self.assertEqual(mol.nao_nr(), 14)
289
290        mol = gto.M(atom = '''O 0 0 0; H:1 0 1 0; H@2 0 0 1''',
291                    basis = {'O': 'ccpvdz', 'H:1': 'sto3g', 'H': 'unc-iglo3'})
292        self.assertEqual(mol.nao_nr(), 32)
293
294        mol = gto.M(
295            atom = '''O 0 0 0; H1 0 1 0; H2 0 0 1''',
296            basis = {'default': ('6-31g', [[0, [.05, 1.]], []]), 'H2': 'sto3g'}
297        )
298        self.assertEqual(mol.nao_nr(), 14)
299
300        mol = gto.M(
301            atom = '''O 0 0 0; H1 0 1 0; H2 0 0 1''',
302            basis = {'H1': gto.parse('''
303# Parse NWChem format basis string (see https://bse.pnl.gov/bse/portal).
304# Comment lines are ignored
305#BASIS SET: (6s,3p) -> [2s,1p]
306        H    S
307              2.9412494             -0.09996723
308              0.6834831              0.39951283
309              0.2222899              0.70011547
310        H    S
311              2.9412494             0.15591627
312              0.6834831             0.60768372
313              0.2222899             0.39195739
314                                    ''', optimize=True),
315                     'O': 'unc-ccpvdz',
316                     'H2': gto.load('sto-3g', 'He')  # or use basis of another atom
317                    }
318        )
319        self.assertEqual(mol.nao_nr(), 29)
320
321        mol = gto.M(
322            atom = '''O 0 0 0; H1 0 1 0; H2 0 0 1''',
323            basis = {'H': ['sto3g', '''unc
324        C    S
325             71.6168370              0.15432897
326             13.0450960              0.53532814
327              3.5305122              0.44463454
328        C    SP
329              2.9412494             -0.09996723             0.15591627
330              0.6834831              0.39951283             0.60768372
331              0.2222899              0.70011547             0.39195739
332        '''],
333                     'O': mol.expand_etbs([(0, 4, 1.5, 2.2),  # s-function
334                                           (1, 2, 0.5, 2.2)]) # p-function
335                    }
336        )
337        self.assertEqual(mol.nao_nr(), 42)
338
339        mol = gto.M(
340            atom = '''O 0 0 0; H1 0 1 0; H2 0 0 1''',
341            basis = ('sto3g', 'ccpvdz', '3-21g',
342                     gto.etbs([(0, 4, 1.5, 2.2), (1, 2, 0.5, 2.2)]),
343                    [[0, numpy.array([1e3, 1.])]])
344        )
345        self.assertEqual(mol.nao_nr(), 77)
346
347        mol.atom = 'Hg'
348        mol.basis = 'ccpvdz'
349        self.assertRaises(RuntimeError, mol.build)
350
351    def test_default_basis(self):
352        mol = gto.M(atom=[['h' , 0,1,1], ["O1", (0.,0.,0.)], [1, 1.,1.,0.],],
353                    basis={'default':'321g', 'O1': 'sto3g'})
354        self.assertEqual(sorted(mol._basis.keys()), ['H', 'O1'])
355
356    def test_parse_pople_basis(self):
357        self.assertEqual(len(gto.basis.load('6-31G(d)'      , 'H')), 2)
358        self.assertEqual(len(gto.basis.load('6-31G(d)'      , 'C')), 6)
359        self.assertEqual(len(gto.basis.load('6-31Gs'        , 'C')), 6)
360        self.assertEqual(len(gto.basis.load('6-31G*'        , 'C')), 6)
361        self.assertEqual(len(gto.basis.load('6-31G(d,p)'    , 'H')), 3)
362        self.assertEqual(len(gto.basis.load('6-31G(d,p)'    , 'C')), 6)
363        self.assertEqual(len(gto.basis.load('6-31G(2d,2p)'  , 'H')), 4)
364        self.assertEqual(len(gto.basis.load('6-31G(2d,2p)'  , 'C')), 7)
365        self.assertEqual(len(gto.basis.load('6-31G(3df,3pd)', 'H')), 6)
366        self.assertEqual(len(gto.basis.load('6-31G(3df,3pd)', 'C')), 9)
367
368    def test_parse_basis(self):
369        mol = gto.M(atom='''
370                    6        0    0   -0.5
371                    8        0    0    0.5
372                    1        1    0   -1.0
373                    1       -1    0   -1.0''',
374                    basis='''
375#BASIS SET: (3s) -> [2s]
376H    S
377      5.4471780              0.1562849787
378      0.82454724             0.9046908767
379H    S
380      0.18319158             1.0000000
381#BASIS SET: (6s,3p) -> [3s,2p]
382C    S
383    172.2560000              0.0617669
384     25.9109000              0.3587940
385      5.5333500              0.7007130
386C    SP
387      3.6649800             -0.3958970              0.2364600
388      0.7705450              1.2158400              0.8606190
389C    SP
390      0.1958570              1.0000000              1.0000000
391#BASIS SET: (6s,3p) -> [3s,2p]
392O    S
393    322.0370000              0.0592394
394     48.4308000              0.3515000
395     10.4206000              0.7076580
396O    SP
397      7.4029400             -0.4044530              0.2445860
398      1.5762000              1.2215600              0.8539550
399O    SP
400      0.3736840              1.0000000              1.0000000
401''')
402        self.assertTrue(mol.nao_nr() == 22)
403
404    def test_ghost(self):
405        mol = gto.M(
406            atom = 'C 0 0 0; ghost 0 0 2',
407            basis = {'C': 'sto3g', 'ghost': gto.basis.load('sto3g', 'H')}
408        )
409        self.assertEqual(mol.nao_nr(), 6)
410
411        mol = gto.M(atom='''
412        ghost-O     0.000000000     0.000000000     2.500000000
413        X_H        -0.663641000    -0.383071000     3.095377000
414        ghost.H     0.663588000     0.383072000     3.095377000
415        O     1.000000000     0.000000000     2.500000000
416        H    -1.663641000    -0.383071000     3.095377000
417        H     1.663588000     0.383072000     3.095377000
418        ''',
419        basis='631g')
420        self.assertEqual(mol.nao_nr(), 26)
421
422        mol = gto.M(atom='''
423        ghost-O     0.000000000     0.000000000     2.500000000
424        X_H        -0.663641000    -0.383071000     3.095377000
425        ghost.H     0.663588000     0.383072000     3.095377000
426        O     1.000000000     0.000000000     2.500000000
427        ''',
428                basis={'H': '3-21g', 'o': '3-21g', 'ghost-O': 'sto3g'})
429        self.assertEqual(mol.nao_nr(), 18) # 5 + 2 + 2 + 9
430
431        mol = gto.M(atom='Zn 0 0 0; ghost-Fe 0 0 1',
432                    basis='lanl2dz', ecp='lanl2dz')
433        self.assertTrue(len(mol._ecp) == 1)  # only Zn ecp
434
435        mol = gto.M(atom='Zn 0 0 0; ghost-Fe 0 0 1',
436                    basis='lanl2dz', ecp={'Zn': 'lanl2dz', 'ghost-Fe': 'lanl2dz'})
437        self.assertTrue(len(mol._ecp) == 2)  # Zn and ghost-Fe in ecp
438
439    def test_nucmod(self):
440        gto.filatov_nuc_mod(80)
441        self.assertEqual(gto.mole._parse_nuc_mod(1), gto.NUC_GAUSS)
442        self.assertEqual(gto.mole._parse_nuc_mod('Gaussian'), gto.NUC_GAUSS)
443        mol1 = gto.Mole()
444        mol1.atom = mol0.atom
445        mol1.nucmod = 'G'
446        mol1.verbose = 5
447        mol1.nucprop = {'H': {'mass': 3}}
448        mol1.output = '/dev/null'
449        mol1.build(False, False)
450        mol1.set_nuc_mod(0, 2)
451        self.assertTrue(mol1._atm[1,gto.NUC_MOD_OF] == gto.NUC_GAUSS)
452        self.assertAlmostEqual(mol1._env[mol1._atm[0,gto.PTR_ZETA]], 2, 9)
453        self.assertAlmostEqual(mol1._env[mol1._atm[1,gto.PTR_ZETA]], 586314366.54656982, 4)
454
455        mol1.set_nuc_mod(1, 0)
456        self.assertTrue(mol1._atm[1,gto.NUC_MOD_OF] == gto.NUC_POINT)
457
458        mol1.nucmod = None
459        mol1.build(False, False)
460        self.assertTrue(mol1._atm[1,gto.NUC_MOD_OF] == gto.NUC_POINT)
461
462        mol1.nucmod = {'H': gto.filatov_nuc_mod}
463        mol1.build(False, False)
464        self.assertTrue(mol1._atm[0,gto.NUC_MOD_OF] == gto.NUC_GAUSS)
465        self.assertTrue(mol1._atm[1,gto.NUC_MOD_OF] == gto.NUC_POINT)
466        self.assertTrue(mol1._atm[2,gto.NUC_MOD_OF] == gto.NUC_GAUSS)
467
468    def test_zmat(self):
469        coord = numpy.array((
470            (0.200000000000, -1.889726124565,  0.000000000000),
471            (1.300000000000, -1.889726124565,  0.000000000000),
472            (2.400000000000, -1.889726124565,  0.000000000000),
473            (3.500000000000, -1.889726124565,  0.000000000000),
474            (0.000000000000,  0.000000000000, -1.889726124565),
475            (0.000000000000,  1.889726124565,  0.000000000000),
476            (0.200000000000, -0.800000000000,  0.000000000000),
477            (1.889726124565,  0.000000000000,  1.133835674739)))
478        zstr0 = gto.cart2zmat(coord)
479        zstr = '\n'.join(['H '+x for x in zstr0.splitlines()])
480        atoms = gto.zmat2cart(zstr)
481        zstr1 = gto.cart2zmat([x[1] for x in atoms])
482        self.assertTrue(zstr0 == zstr1)
483
484        numpy.random.seed(1)
485        coord = numpy.random.random((6,3))
486        zstr0 = gto.cart2zmat(coord)
487        zstr = '\n'.join(['H '+x for x in zstr0.splitlines()])
488        atoms = gto.zmat2cart(zstr)
489        zstr1 = gto.cart2zmat([x[1] for x in atoms])
490        self.assertTrue(zstr0 == zstr1)
491
492    def test_c2s(self):  # Transformation of cart <-> sph, sph <-> spinor
493        c = mol0.sph2spinor_coeff()
494        s0 = mol0.intor('int1e_ovlp_spinor')
495        s1 = mol0.intor('int1e_ovlp_sph')
496        sa = reduce(numpy.dot, (c[0].T.conj(), s1, c[0]))
497        sa+= reduce(numpy.dot, (c[1].T.conj(), s1, c[1]))
498        mol0.cart = True
499        s2 = mol0.intor('int1e_ovlp')
500        mol0.cart = False
501        self.assertAlmostEqual(abs(s0 - sa).max(), 0, 12)
502        c = mol0.cart2sph_coeff()
503        sa = reduce(numpy.dot, (c.T.conj(), s2, c))
504        self.assertAlmostEqual(abs(s1 - sa).max(), 0, 12)
505
506        c0 = gto.mole.cart2sph(1)
507        ca, cb = gto.mole.cart2spinor_l(1)
508        ua, ub = gto.mole.sph2spinor_l(1)
509        self.assertAlmostEqual(abs(c0.dot(ua)-ca).max(), 0, 9)
510        self.assertAlmostEqual(abs(c0.dot(ub)-cb).max(), 0, 9)
511
512        c0 = gto.mole.cart2sph(0, normalized='sp')
513        ca, cb = gto.mole.cart2spinor_kappa(-1, 0, normalized='sp')
514        ua, ub = gto.mole.sph2spinor_kappa(-1, 0)
515        self.assertAlmostEqual(abs(c0.dot(ua)-ca).max(), 0, 9)
516        self.assertAlmostEqual(abs(c0.dot(ub)-cb).max(), 0, 9)
517
518        c1 = gto.mole.cart2sph(0, numpy.eye(1))
519        self.assertAlmostEqual(abs(c0*0.282094791773878143-c1).max(), 0, 12)
520
521        c0 = gto.mole.cart2sph(1, normalized='sp')
522        ca, cb = gto.mole.cart2spinor_kappa(1, 1, normalized='sp')
523        ua, ub = gto.mole.sph2spinor_kappa(1, 1)
524        self.assertAlmostEqual(abs(c0.dot(ua)-ca).max(), 0, 9)
525        self.assertAlmostEqual(abs(c0.dot(ub)-cb).max(), 0, 9)
526
527        c1 = gto.mole.cart2sph(1, numpy.eye(3).T)
528        self.assertAlmostEqual(abs(c0*0.488602511902919921-c1).max(), 0, 12)
529
530    def test_bas_method(self):
531        self.assertEqual([mol0.bas_len_cart(x) for x in range(mol0.nbas)],
532                         [1, 3, 1, 1, 1, 1, 1, 3, 3, 3, 6, 6, 1, 3])
533        self.assertEqual([mol0.bas_len_spinor(x) for x in range(mol0.nbas)],
534                         [2, 4, 2, 2, 2, 2, 2, 6, 6, 6, 10, 10, 2, 4])
535        c0 = mol0.bas_ctr_coeff(0)
536        self.assertAlmostEqual(abs(c0[:,0]/c0[0,0] - (1,3,1)).max(), 0, 9)
537        self.assertAlmostEqual(abs(c0[:,1] - (0,1,0)).max(), 0, 9)
538
539        self.assertRaises(ValueError, mol0.gto_norm, -1, 1.)
540
541    def test_nelectron(self):
542        mol = gto.Mole()
543        mol.atom = [
544            [1  , (0.,1.,1.)],
545            ["O1", (0.,0.,0.)],
546            [1  , (1.,1.,0.)], ]
547        mol.charge = 1
548        self.assertEqual(mol.nelectron, 9)
549
550        mol0.nelectron = mol0.nelectron
551        mol0.nelectron = mol0.nelectron
552        mol0.spin = 2
553        self.assertRaises(RuntimeError, lambda *args: mol0.nelec)
554        mol0.spin = 1
555
556        mol1 = copy.copy(mol0)
557        self.assertEqual(mol1.nelec, (5, 4))
558        mol1.nelec = (3, 6)
559        self.assertEqual(mol1.nelec, (3, 6))
560
561    def test_multiplicity(self):
562        mol1 = copy.copy(mol0)
563        self.assertEqual(mol1.multiplicity, 2)
564        mol1.multiplicity = 5
565        self.assertEqual(mol1.multiplicity, 5)
566        self.assertEqual(mol1.spin, 4)
567        self.assertRaises(RuntimeError, lambda:mol1.nelec)
568
569    def test_ms(self):
570        mol1 = copy.copy(mol0)
571        self.assertEqual(mol1.ms, 0.5)
572        mol1.ms = 1
573        self.assertEqual(mol1.multiplicity, 3)
574        self.assertEqual(mol1.spin, 2)
575        self.assertRaises(RuntimeError, lambda:mol1.nelec)
576
577    def test_basis_not_found(self):
578        mol = gto.M(atom='''
579        H     -0.663641000    -0.383071000     3.095377000
580        H     0.663588000     0.383072000     3.095377000
581        O     0.000000000     0.000000000     2.500000000
582        H     -0.663641000    -0.383071000     3.095377000
583        H     0.663588000     0.383072000     3.095377000
584        O     1.000000000     0.000000000     2.500000000
585        H     -0.663641000    -0.383071000     3.095377000
586        H     0.663588000     0.383072000     3.095377000
587        ''', basis={'O': '3-21g'})
588        #TODO: assert the warning "Warn: Basis not found for atom 1 H"
589        self.assertEqual(mol.nao_nr(), 18)
590
591        aoslice = mol.aoslice_by_atom()
592        self.assertEqual(aoslice[:,0].tolist(), [0, 0, 0, 5, 5, 5,10,10])
593        self.assertEqual(aoslice[:,1].tolist(), [0, 0, 5, 5, 5,10,10,10])
594
595    def test_atom_method(self):
596        aoslice = mol0.aoslice_by_atom()
597        for i in range(mol0.natm):
598            symb = mol0.atom_pure_symbol(i)
599            shls = mol0.atom_shell_ids(i)
600            nshls = aoslice[i][1] - aoslice[i][0]
601            self.assertEqual(shls[0], aoslice[i][0])
602            self.assertEqual(len(shls), nshls)
603            self.assertEqual(mol0.atom_nshells(i), nshls)
604        aoslice = mol0.aoslice_2c_by_atom()
605        mol0.elements  # test property(elements) in Mole
606        self.assertEqual([x[2] for x in aoslice], [0, 8, 56])
607        self.assertEqual([x[3] for x in aoslice], [8, 56, 64])
608
609    def test_dump_loads_skip(self):
610        import json
611        with tempfile.NamedTemporaryFile() as tmpfile:
612            lib.chkfile.save_mol(mol0, tmpfile.name)
613            mol1 = gto.Mole()
614            mol1.update(tmpfile.name)
615            # dumps() may produce different orders in different runs
616            self.assertEqual(json.loads(mol1.dumps()), json.loads(mol0.dumps()))
617        mol1.loads(mol1.dumps())
618        mol1.loads_(mol0.dumps())
619        mol1.unpack(mol1.pack())
620        mol1.unpack_(mol0.pack())
621
622    def test_set_geom(self):
623        mol1 = gto.Mole()
624        mol1.verbose = 5
625        mol1.set_geom_(mol0._atom, 'B', symmetry=True)
626        mol1.set_geom_(mol0.atom_coords(), 'B', inplace=False)
627
628        mol1.symmetry = False
629        mol1.set_geom_(mol0.atom_coords(), 'B')
630        mol1.set_geom_(mol0.atom_coords(), inplace=False)
631        mol1.set_geom_(mol0.atom_coords(), unit=1.)
632        mol1.set_geom_(mol0.atom_coords(), unit='Ang', inplace=False)
633
634    def test_apply(self):
635        from pyscf import scf, mp
636        self.assertTrue(isinstance(mol0.apply('RHF'), scf.rohf.ROHF))
637        self.assertTrue(isinstance(mol0.apply('MP2'), mp.ump2.UMP2))
638        self.assertTrue(isinstance(mol0.apply(scf.RHF), scf.rohf.ROHF))
639        self.assertTrue(isinstance(mol0.apply(scf.uhf.UHF), scf.uhf.UHF))
640
641    def test_with_MoleContext(self):
642        mol1 = mol0.copy()
643        with mol1.with_rinv_at_nucleus(1):
644            self.assertTrue(mol1._env[gto.PTR_RINV_ZETA] != 0)
645            self.assertAlmostEqual(abs(mol1._env[gto.PTR_RINV_ORIG+2]), 0, 9)
646        self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ZETA], 0, 9)
647        self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ORIG+2], 0, 9)
648        with mol1.with_rinv_at_nucleus(0):
649            self.assertAlmostEqual(abs(mol1._env[gto.PTR_RINV_ORIG+2]), 1.8897261245650618, 9)
650        self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ORIG+2], 0, 9)
651
652        with mol1.with_rinv_zeta(20):
653            self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ZETA], 20, 9)
654            mol1.set_rinv_zeta(3.)
655        self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ZETA], 0, 9)
656
657        with mol1.with_rinv_origin((1,2,3)):
658            self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ORIG+2], 3, 9)
659        self.assertAlmostEqual(mol1._env[gto.PTR_RINV_ORIG+2], 0, 9)
660
661        with mol1.with_range_coulomb(20):
662            self.assertAlmostEqual(mol1._env[gto.PTR_RANGE_OMEGA], 20, 9)
663            mol1.set_range_coulomb(2.)
664        self.assertAlmostEqual(mol1._env[gto.PTR_RANGE_OMEGA], 0, 9)
665
666        with mol1.with_common_origin((1,2,3)):
667            self.assertAlmostEqual(mol1._env[gto.PTR_COMMON_ORIG+2], 3, 9)
668        self.assertAlmostEqual(mol1._env[gto.PTR_COMMON_ORIG+2], 0, 9)
669
670        mol1.set_f12_zeta(2.)
671
672    def test_input_symmetry1(self):
673        mol1 = gto.Mole()
674        mol1.atom = 'H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1'
675        mol1.unit = 'B'
676        mol1.symmetry = True
677        mol1.verbose = 5
678        mol1.output = '/dev/null'
679        mol1.build()
680        self.assertAlmostEqual(lib.fp(mol1.atom_coords()), 3.4708548731841296, 9)
681
682        mol1 = gto.Mole()
683        mol1.atom = 'H 0 0 -1; H 0 0 1'
684        mol1.cart = True
685        mol1.unit = 'B'
686        mol1.symmetry = 'Dooh'
687        mol1.verbose = 5
688        mol1.output = '/dev/null'
689        mol1.build()
690        self.assertAlmostEqual(lib.fp(mol1.atom_coords()), 0.69980902201036865, 9)
691
692        mol1 = gto.Mole()
693        mol1.atom = 'H 0 -1 0; H 0 1 0'
694        mol1.unit = 'B'
695        mol1.symmetry = True
696        mol1.symmetry_subgroup = 'D2h'
697        mol1.build()
698        self.assertAlmostEqual(lib.fp(mol1.atom_coords()), -1.1939459267317516, 9)
699
700        mol1.atom = 'H 0 0 -1; H 0 0 1'
701        mol1.unit = 'B'
702        mol1.symmetry = 'Coov'
703        mol1.symmetry_subgroup = 'C2'
704        mol1.build()
705        self.assertAlmostEqual(lib.fp(mol1.atom_coords()), 0.69980902201036865, 9)
706
707        mol1.atom = 'H 1 0 -1; H 0 0 1; He 0 0 2'
708        mol1.symmetry = 'Coov'
709        self.assertRaises(PointGroupSymmetryError, mol1.build)
710
711        mol1.atom = '''
712        C 0. 0. 0.7264
713        C 0. 0. -.7264
714        H 0.92419 0. 1.29252
715        H -.92419 0. 1.29252
716        H 0. 0.92419 -1.29252
717        H 0. -.92419 -1.29252'''
718        mol1.symmetry = True
719        mol1.symmetry_subgroup = 'C2v'
720        mol1.build()
721        self.assertAlmostEqual(lib.fp(mol1.atom_coords()), 2.9413856643164618, 9)
722
723        mol1 = gto.Mole()
724        mol1.atom = [
725            ["O" , (0. , 0.     , 0.)],
726            ["H" , (0. , -0.757 , 0.587)],
727            ["H" , (0. , 0.757  , 0.587)]]
728        mol1.symmetry = "C3"
729        self.assertRaises(PointGroupSymmetryError, mol1.build)
730
731    def test_symm_orb(self):
732        rs = numpy.array([[.1, -.3, -.2],
733                          [.3,  .1,  .8]])
734        mol = gto.M(atom=[('H', c) for c in rs], unit='Bohr',
735                    basis={'H': [[0, (1, 1)], [1, (.9, 1)], [2, (.8, 1)], [3, (.7, 1)]]})
736
737        numpy.random.seed(1)
738        u, w, vh = numpy.linalg.svd(numpy.random.random((3,3)))
739        rs1 = rs.dot(u) + numpy.array([-.5, -.3, .9])
740        mol1 = gto.M(atom=[('H', c) for c in rs1], unit='Bohr',
741                     basis={'H': [[0, (1, 1)], [1, (.9, 1)], [2, (.8, 1)], [3, (.7, 1)]]})
742
743        mol.symmetry = 1
744        mol.build()
745        mol1.symmetry = 1
746        mol1.build()
747
748        s0 = mol.intor('int1e_ovlp')
749        s0 = [abs(c.T.dot(s0).dot(c)) for c in mol.symm_orb]
750        s1 = mol1.intor('int1e_ovlp')
751        s1 = [abs(c.T.dot(s1).dot(c)) for c in mol1.symm_orb]
752        self.assertTrue(all(abs(s0[i]-s1[i]).max()<1e-12 for i in range(len(mol.symm_orb))))
753
754        mol.cart = True
755        mol.symmetry = 1
756        mol.build()
757        mol1.cart = True
758        mol1.symmetry = 1
759        mol1.build()
760
761        s0 = mol.intor('int1e_ovlp')
762        s0 = [abs(c.T.dot(s0).dot(c)) for c in mol.symm_orb]
763        s1 = mol1.intor('int1e_ovlp')
764        s1 = [abs(c.T.dot(s1).dot(c)) for c in mol1.symm_orb]
765        self.assertTrue(all(abs(s0[i]-s1[i]).max()<1e-12 for i in range(len(mol.symm_orb))))
766
767    def test_search_ao_label(self):
768        mol1 = mol0.copy()
769        mol1.atom = mol0.atom + ['Mg 1,1,1']
770        mol1.ecp['Mg'] = 'lanl2dz'
771        mol1.basis['Mg'] = 'lanl2dz'
772        mol1.build(0, 0)
773        self.assertEqual(list(mol1.search_ao_label('O.*2p')), [10,11,12])
774        self.assertEqual(list(mol1.search_ao_label('O1 2p')), [10,11,12])
775        self.assertEqual(list(mol1.search_ao_label(['O.*2p','0 H 1s'])), [0, 10,11,12])
776        self.assertEqual(list(mol1.search_ao_label([10,11,12])), [10,11,12])
777        self.assertEqual(list(mol1.search_ao_label(lambda x: '4d' in x)), [24,25,26,27,28])
778        mol1.ao_labels(fmt='%s%s%s%s')
779        mol1.sph_labels(fmt=None)
780        mol1.cart = True
781        self.assertEqual(list(mol1.search_ao_label('4d')), [25,26,27,28,29,30])
782        mol1.ao_labels(fmt='%s%s%s%s')
783        mol1.ao_labels(fmt=None)
784        mol1.cart = False
785        mol1.spinor_labels()
786        mol1.spinor_labels(fmt='%s%s%s%s')
787        mol1.spinor_labels(fmt=None)
788
789    def test_input_ecp(self):
790        mol1 = gto.Mole()
791        mol1.atom = mol0.atom
792        mol1.ecp = 'lanl2dz'
793        mol1.build(False, False)
794        gto.basis.load_ecp('lanl08', 'O')
795        gto.format_ecp({'O':'lanl08', 1:'lanl2dz'})
796        self.assertRaises(BasisNotFoundError, gto.format_ecp, {'H':'lan2ldz'})
797
798    def test_condense_to_shell(self):
799        mol1 = mol0.copy()
800        mol1.symmetry = False
801        mol1.build(False, False)
802        v = gto.condense_to_shell(mol1, mol1.intor('int1e_ovlp'), numpy.max)
803        self.assertAlmostEqual(lib.fp(v), 5.7342530154117846, 9)
804
805    def test_input_ghost_atom(self):
806        mol = gto.M(
807            atom = 'C 0 0 0; ghost 0 0 2',
808            basis = {'C': 'sto3g', 'ghost': gto.basis.load('sto3g', 'H')}
809        )
810
811        mol = gto.M(atom='''
812        ghost1     0.000000000     0.000000000     2.500000000
813        ghost2    -0.663641000    -0.383071000     3.095377000
814        ghost2     0.663588000     0.383072000     3.095377000
815        O     1.000000000     0.000000000     2.500000000
816        H    -1.663641000    -0.383071000     3.095377000
817        H     1.663588000     0.383072000     3.095377000
818        ''',
819                    basis={'ghost1':gto.basis.load('sto3g', 'O'),
820                           'ghost2':gto.basis.load('631g', 'H'),
821                           'O':'631g', 'H':'631g'}
822        )
823
824        mol = gto.M(atom='''
825        ghost-O     0.000000000     0.000000000     2.500000000
826        ghost_H    -0.663641000    -0.383071000     3.095377000
827        ghost:H     0.663588000     0.383072000     3.095377000
828        O     1.000000000     0.000000000     2.500000000
829        H    -1.663641000    -0.383071000     3.095377000
830        H     1.663588000     0.383072000     3.095377000
831        ''', basis='631g')
832
833        mol = gto.M(atom='''
834        X1     0.000000000     0.000000000     2.500000000
835        X2    -0.663641000    -0.383071000     3.095377000
836        X2     0.663588000     0.383072000     3.095377000
837        O     1.000000000     0.000000000     2.500000000
838        H    -1.663641000    -0.383071000     3.095377000
839        H     1.663588000     0.383072000     3.095377000
840        ''',
841                    basis={'X1':gto.basis.load('sto3g', 'O'),
842                           'X2':gto.basis.load('631g', 'H'),
843                           'O':'631g', 'H':'631g'}
844        )
845
846        mol = gto.M(atom='''
847        X-O     0.000000000     0.000000000     2.500000000
848        X_H1   -0.663641000    -0.383071000     3.095377000
849        X:H     0.663588000     0.383072000     3.095377000
850        O     1.000000000     0.000000000     2.500000000
851        H    -1.663641000    -0.383071000     3.095377000
852        H     1.663588000     0.383072000     3.095377000
853        ''', basis='631g')
854
855    def test_conc_mole(self):
856        mol1 = gto.M(atom='Mg', ecp='LANL2DZ', basis='lanl2dz')
857        mol2 = mol1 + mol0
858        self.assertEqual(mol2.natm, 4)
859        self.assertEqual(mol2.nbas, 18)
860        self.assertEqual(mol2.nao_nr(), 42)
861        mol2 = mol0 + mol1
862        self.assertEqual(mol2.natm, 4)
863        self.assertEqual(mol2.nbas, 18)
864        self.assertEqual(mol2.nao_nr(), 42)
865        n0 = mol0.npgto_nr()
866        n1 = mol1.npgto_nr()
867        self.assertEqual(mol2.npgto_nr(), n0+n1)
868        mol2 = mol2 + mol2
869        mol2.cart = True
870        self.assertEqual(mol2.npgto_nr(), 100)
871
872    def test_intor_cross_cart(self):
873        mol1 = gto.M(atom='He', basis={'He': [(2,(1.,1))]}, cart=True)
874        s0 = gto.intor_cross('int1e_ovlp', mol1, mol0)
875        self.assertEqual(s0.shape, (6, 34))
876        s0 = gto.intor_cross('int1e_ovlp', mol0, mol1)
877        self.assertEqual(s0.shape, (34, 6))
878        s0 = gto.intor_cross('int1e_ovlp_cart', mol0, mol1)
879        self.assertEqual(s0.shape, (36, 6))
880
881    def test_energy_nuc(self):
882        self.assertAlmostEqual(mol0.get_enuc(), 6.3611415029455705, 9)
883        self.assertAlmostEqual(gto.M().energy_nuc(), 0, 9)
884
885    def test_fakemol(self):
886        numpy.random.seed(1)
887        coords = numpy.random.random((6,3))*4
888        vref = 0
889        mol = mol0.copy()
890        for c in coords:
891            mol.set_rinv_origin(c)
892            vref += mol.intor('int1e_rinv')
893
894        fakemol = gto.fakemol_for_charges(coords)
895        pmol = mol + fakemol
896        shls_slice = (0, mol.nbas, 0, mol.nbas, mol.nbas, pmol.nbas)
897        v = pmol.intor('int3c2e', comp=1, shls_slice=shls_slice)
898        v = numpy.einsum('pqk->pq', v)
899        self.assertAlmostEqual(abs(vref-v).max(), 0, 12)
900
901    def test_to_uncontracted_cartesian_basis(self):
902        pmol, ctr_coeff = mol0.to_uncontracted_cartesian_basis()
903        c = scipy.linalg.block_diag(*ctr_coeff)
904        s = reduce(numpy.dot, (c.T, pmol.intor('int1e_ovlp'), c))
905        self.assertAlmostEqual(abs(s-mol0.intor('int1e_ovlp')).max(), 0, 9)
906
907        mol0.cart = True
908        pmol, ctr_coeff = mol0.to_uncontracted_cartesian_basis()
909        c = scipy.linalg.block_diag(*ctr_coeff)
910        s = reduce(numpy.dot, (c.T, pmol.intor('int1e_ovlp'), c))
911        self.assertAlmostEqual(abs(s-mol0.intor('int1e_ovlp')).max(), 0, 9)
912        mol0.cart = False
913
914    def test_getattr(self):
915        from pyscf import scf, dft, ci, tdscf
916        mol = gto.M(atom='He')
917        self.assertEqual(mol.HF().__class__, scf.HF(mol).__class__)
918        self.assertEqual(mol.KS().__class__, dft.KS(mol).__class__)
919        self.assertEqual(mol.UKS().__class__, dft.UKS(mol).__class__)
920        self.assertEqual(mol.CISD().__class__, ci.cisd.RCISD)
921        self.assertEqual(mol.TDA().__class__, tdscf.rhf.TDA)
922        self.assertEqual(mol.dTDA().__class__, tdscf.rks.dTDA)
923        self.assertEqual(mol.TDBP86().__class__, tdscf.rks.TDDFTNoHybrid)
924        self.assertEqual(mol.TDB3LYP().__class__, tdscf.rks.TDDFT)
925        self.assertRaises(AttributeError, lambda: mol.xyz)
926        self.assertRaises(AttributeError, lambda: mol.TDxyz)
927
928    def test_ao2mo(self):
929        mol = gto.M(atom='He')
930        nao = mol.nao
931        eri = mol.ao2mo(numpy.eye(nao))
932        self.assertAlmostEqual(eri[0,0], 1.0557129427350722, 12)
933
934    def test_tofile(self):
935        tmpfile = tempfile.NamedTemporaryFile()
936        mol = gto.M(atom=[[1  , (0.,1.,1.)],
937                          ["O1", (0.,0.,0.)],
938                          [1  , (1.,1.,0.)], ])
939        out1 = mol.tofile(tmpfile.name, format='xyz')
940        ref = '''3
941XYZ from PySCF
942H           0.00000        1.00000        1.00000
943O           0.00000        0.00000        0.00000
944H           1.00000        1.00000        0.00000
945'''
946        with open(tmpfile.name, 'r') as f:
947            self.assertEqual(f.read(), ref)
948        self.assertEqual(out1, ref[:-1])
949
950        tmpfile = tempfile.NamedTemporaryFile(suffix='.zmat')
951        str1 = mol.tofile(tmpfile.name, format='zmat')
952        #FIXME:self.assertEqual(mol._atom, mol.fromfile(tmpfile.name))
953
954    def test_frac_particles(self):
955        mol = gto.M(atom=[['h', (0.,1.,1.)],
956                          ['O', (0.,0.,0.)],
957                          ['h', (1.,1.,0.)],],
958                     basis='sto3g')
959        mol._atm[1, gto.NUC_MOD_OF] = gto.NUC_FRAC_CHARGE
960        mol._env[mol._atm[1, gto.PTR_FRAC_CHARGE]] = 2.5
961        self.assertAlmostEqual(mol.atom_charges().sum(), 4.5, 12)
962        self.assertAlmostEqual(mol.atom_charge(1), 2.5, 12)
963
964        # Add test after updating cint
965        ref = 0
966        for ia in range(mol.natm):
967            with mol.with_rinv_origin(mol.atom_coord(ia)):
968                ref -= mol.intor('int1e_rinv') * mol.atom_charge(ia)
969        v = mol.intor('int1e_nuc')
970        self.assertAlmostEqual(abs(ref-v).max(), 0, 12)
971
972    def test_fromstring(self):
973        mol = gto.Mole()
974        mol.fromstring('2\n\nH 0 0 1\nH 0 -1 0')
975        print(mol._atom == [('H', [0.0, 0.0, 1.8897261245650618]), ('H', [0.0, -1.8897261245650618, 0.0])])
976        print(mol.atom == [('H', [0.0, 0.0, 1.0]), ('H', [0.0, -1.0, 0.0])])
977        print(mol.unit == 'Angstrom')
978
979    def test_fromfile(self):
980        with tempfile.NamedTemporaryFile(mode='w+', suffix='.xyz') as f:
981            f.write('2\n\nH 0 0 1; H 0 -1 0')
982            f.flush()
983            mol = gto.Mole()
984            mol.fromfile(f.name)
985            print(mol._atom == [('H', [0.0, 0.0, 1.8897261245650618]), ('H', [0.0, -1.8897261245650618, 0.0])])
986            print(mol.atom == [('H', [0.0, 0.0, 1.0]), ('H', [0.0, -1.0, 0.0])])
987            print(mol.unit == 'Angstrom')
988
989    def test_uncontract(self):
990        basis = gto.basis.parse('''
991H    S
9920.9  0.8  0
9930.5  0.5  0.6
9940.3  0.5  0.8
995H    S
9960.3  1
997H    P
9980.9  0.6
9990.5  0.6
10000.3  0.6
1001''')
1002        self.assertEqual(gto.uncontract(basis),
1003                         [[0, [0.9, 1]], [0, [0.5, 1]], [0, [0.3, 1]],
1004                          [1, [0.9, 1]], [1, [0.5, 1]], [1, [0.3, 1]]])
1005
1006        basis = [[1, 0, [0.9, .7], [0.5, .7]], [1, [0.5, .8], [0.3, .6]], [1, [0.3, 1]]]
1007        self.assertEqual(gto.uncontract(basis),
1008                         [[1, [0.9, 1]], [1, [0.5, 1]], [1, [0.3, 1]]])
1009
1010        basis = [[1, -2, [0.9, .7], [0.5, .7]], [1, [0.5, .8], [0.3, .6]], [1, [0.3, 1]]]
1011        self.assertEqual(gto.uncontract(basis),
1012                         [[1, -2, [0.9, 1]], [1, -2, [0.5, 1]], [1, [0.3, 1]]])
1013
1014        # FIXME:
1015        #basis = [[1, [0.9, .7], [0.5, .7]], [1, -2, [0.5, .8], [0.3, .6]], [1, [0.3, 1]]]
1016        #serl.assertEqual(gto.uncontract(basis),
1017        #                 [[1, [0.9, 1]], [1, [0.5, 1]], [1, [0.3, 1]]])
1018
1019if __name__ == "__main__":
1020    print("test mole.py")
1021    unittest.main()
1022