File: testhirshfeld.py

package info (click to toggle)
cclib 1.8.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,412 kB
  • sloc: python: 23,605; makefile: 75; sh: 31
file content (138 lines) | stat: -rw-r--r-- 5,017 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Copyright (c) 2024, the cclib development team
#
# This file is part of cclib (http://cclib.github.io) and is distributed under
# the terms of the BSD 3-Clause License.

"""Test the Hirshfeld Method in cclib"""

import os

from cclib.io import ccread
from cclib.method import Hirshfeld, volume
from cclib.method.calculationmethod import MissingAttributeError
from cclib.parser import Psi4
from cclib.parser.utils import find_package

import numpy
import pytest
from numpy.testing import assert_allclose

from ..test_data import getdatafile

_found_pyquante = find_package("PyQuante")

class HirshfeldTest:
    """Hirshfeld method tests."""

    def setup_method(self) -> None:
        self.parse()

    def parse(self) -> None:
        self.data, self.logfile = getdatafile(Psi4, "basicPsi4-1.2.1", ["water_mp2.out"])
        self.volume = volume.Volume((-4, -4, -4), (4, 4, 4), (0.2, 0.2, 0.2))

    def testmissingrequiredattributes(self):
        """Is an error raised when required attributes are missing?"""
        for missing_attribute in Hirshfeld.required_attrs:
            self.parse()
            delattr(self.data, missing_attribute)
            with pytest.raises(MissingAttributeError):
                trialBader = Hirshfeld(
                    self.data, self.volume, os.path.dirname(os.path.realpath(__file__))
                )

    def test_proatom_read(self):
        """Are proatom densities imported correctly?"""

        self.parse()
        self.analysis = Hirshfeld(
            self.data, self.volume, os.path.dirname(os.path.realpath(__file__))
        )

        refH_den = [
            2.66407645e-01,
            2.66407645e-01,
            2.66407643e-01,
            2.66407612e-01,
            2.66407322e-01,
        ]  # Hydrogen first five densities
        refH_r = [
            1.17745807e-07,
            4.05209491e-06,
            3.21078677e-05,
            1.39448474e-04,
            4.35643929e-04,
        ]  # Hydrogen first five radii
        refO_den = [
            2.98258510e02,
            2.98258510e02,
            2.98258509e02,
            2.98258487e02,
            2.98258290e02,
        ]  # Oxygen first five densities
        refO_r = [
            5.70916728e-09,
            1.97130512e-07,
            1.56506399e-06,
            6.80667366e-06,
            2.12872046e-05,
        ]  # Oxygen first five radii

        assert_allclose(self.analysis.proatom_density[0][0:5], refO_den, rtol=1e-3)
        assert_allclose(self.analysis.proatom_density[1][0:5], refH_den, rtol=1e-3)
        assert_allclose(self.analysis.proatom_density[2][0:5], refH_den, rtol=1e-3)

    def test_water_charges(self):
        """Are Hirshfeld charges calculated correctly for water?

        Note. Table 1 in doi:10.1007/BF01113058 reports Hirshfeld charge for Hydrogen atom as
              0.11 when STO-3G basis set was used and
              0.18 when 6-311G** basis set was used.
              Here, Psi4 calculation was done using STO-3G.
        """

        self.parse()
        # use precalculated fine cube file
        imported_vol = volume.read_from_cube(
            os.path.join(os.path.dirname(os.path.realpath(__file__)), "water_fine.cube")
        )

        analysis = Hirshfeld(self.data, imported_vol, os.path.dirname(os.path.realpath(__file__)))
        analysis.calculate()

        # Check assigned charges
        assert_allclose(analysis.fragcharges, [-0.29084274, 0.14357639, 0.14357639], atol=0.1)

    def test_chgsum_h2(self):
        """Are Hirshfeld charges for hydrogen atoms in nonpolar H2 small as expected?"""

        h2path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "h2.out")
        data = ccread(h2path)
        vol = volume.Volume((-3, -3, -3), (3, 3, 3), (0.1, 0.1, 0.1))
        analysis = Hirshfeld(data, vol, os.path.dirname(os.path.realpath(__file__)))
        if not _found_pyquante:
            pytest.skip("analysis.calculate() requires PyQuante")
        analysis.calculate()

        assert abs(numpy.sum(analysis.fragcharges) - 0) < 1e-2
        assert abs(analysis.fragcharges[0] - analysis.fragcharges[1]) < 1e-6

    def test_chgsum_co(self):
        """Are Hirshfeld charges for carbon monoxide reported as expected?

        Note. Table 1 in doi:10.1007/BF01113058 reports Hirshfeld charge for Carbon atom as
              0.06 when STO-3G basis set was used and
              0.14 when 6-311G** basis set was used.
              Here, Psi4 calculation was done using STO-3G.
        """

        copath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "co.out")
        data = ccread(copath)
        vol = volume.read_from_cube(
            os.path.join(os.path.dirname(os.path.realpath(__file__)), "co.cube")
        )
        analysis = Hirshfeld(data, vol, os.path.dirname(os.path.realpath(__file__)))
        analysis.calculate()

        assert abs(numpy.sum(analysis.fragcharges)) < 1e-2
        assert_allclose(analysis.fragcharges, [0.10590126, -0.11277786], atol=1e-3)