Esempio n. 1
0
def test_mulliken_populations_newbasis():
    """Test orbstools.mulliken.mulliken_populations_newabasis."""
    with path("chemtools.data", "naclo4_coeff_ab_mo.npy") as fname:
        coeff_ab_mo = np.load(str(fname))
    with path("chemtools.data", "naclo4_olp_ab_ab.npy") as fname:
        olp_ab_ab = np.load(str(fname))
    with path("chemtools.data", "naclo4_occupations.npy") as fname:
        occupations = np.load(str(fname))
    with path("chemtools.data", "naclo4_ab_atom_indices.npy") as fname:
        ab_atom_indices = np.load(str(fname))

    assert np.allclose(
        mulliken_populations_newbasis(coeff_ab_mo, occupations, olp_ab_ab, 6,
                                      np.identity(124), ab_atom_indices),
        mulliken_populations(coeff_ab_mo, occupations, olp_ab_ab, 6,
                             ab_atom_indices),
    )

    coeff_ab_rand = np.linalg.svd(np.random.rand(124, 124))[0].T
    rand_atom_indices = (np.random.rand(124) * 6 // 1).astype(int)
    # normalize
    olp_rand_rand = coeff_ab_rand.T.dot(olp_ab_ab).dot(coeff_ab_rand)
    coeff_ab_rand *= np.diag(olp_rand_rand)**(-0.5)
    olp_rand_rand = coeff_ab_rand.T.dot(olp_ab_ab).dot(coeff_ab_rand)
    coeff_rand_mo = project(olp_rand_rand,
                            coeff_ab_rand.T.dot(olp_ab_ab).dot(coeff_ab_mo))
    assert np.allclose(coeff_ab_rand.dot(coeff_rand_mo), coeff_ab_mo)
    assert np.allclose(
        mulliken_populations_newbasis(coeff_ab_mo, occupations, olp_ab_ab, 6,
                                      coeff_ab_rand, rand_atom_indices),
        mulliken_populations(coeff_rand_mo, occupations, olp_rand_rand, 6,
                             rand_atom_indices),
    )
Esempio n. 2
0
def test_quambo():
    """Test orbstools.quasi.quambo against literature value for Mulliken populations.

    References
    ----------
    .. [1] Janowski, T. Near equivalence of intrinsic atomic orbitals and quasiatomic orbitals.
        JCTC, 2014, 10, 3085-3091.

    """
    with path("chemtools.data", "naclo4_coeff_ab_mo.npy") as fname:
        coeff_ab_mo = np.load(str(fname))
    with path("chemtools.data", "naclo4_olp_ab_ab.npy") as fname:
        olp_ab_ab = np.load(str(fname))
    with path("chemtools.data", "naclo4_olp_aao_ab.npy") as fname:
        olp_aao_ab = np.load(str(fname))
    with path("chemtools.data", "naclo4_occupations.npy") as fname:
        occupations = np.load(str(fname))
    indices_span = occupations > 0
    with path("chemtools.data", "naclo4_qab_atom_indices.npy") as fname:
        ab_atom_indices = np.load(str(fname))

    olp_ab_omo = olp_ab_ab.dot(coeff_ab_mo[:, indices_span])

    coeff_ab_quambo = quambo(olp_ab_ab, olp_aao_ab, coeff_ab_mo, indices_span)
    olp_quambo_quambo = coeff_ab_quambo.T.dot(olp_ab_ab).dot(coeff_ab_quambo)
    olp_quambo_omo = coeff_ab_quambo.T.dot(olp_ab_omo)
    coeff_quambo_omo = project(olp_quambo_quambo, olp_quambo_omo)
    pop = mulliken_populations(coeff_quambo_omo, occupations[indices_span],
                               olp_quambo_quambo, 6, ab_atom_indices)
    partial_pop = np.array([11, 17, 8, 8, 8, 8]) - pop
    assert np.allclose(partial_pop,
                       np.array([0.968, 2.454, -0.807, -0.904, -0.904,
                                 -0.807]),
                       atol=1e-3)
Esempio n. 3
0
    def compute_charges(self, scheme="mulliken"):
        """Return the partial charges at each atom using the given population analysis method.

        Parameters
        ----------
        scheme : {"lowdin", "mulliken"}
            Type of population analysis.
            Default is Mulliken population analysis.

        Returns
        -------
        populations : np.ndarray(N,)
            Number of electrons in each atom according the population analysis.

        """
        coeff_ab_mo_alpha, coeff_ab_mo_beta = self._molecule.mo.coefficient
        occupations_alpha, occupations_beta = self._molecule.mo.occupation
        olp_ab_ab = self._molecule.ao.compute_overlap()
        atomic_charges = self._molecule.numbers
        num_atoms = len(self._molecule.numbers)
        ab_atom_indices = self._molecule._ind_basis_center

        if scheme == "mulliken":
            pop = mulliken_populations(
                coeff_ab_mo_alpha, occupations_alpha, olp_ab_ab, num_atoms, ab_atom_indices
            )
            pop += mulliken_populations(
                coeff_ab_mo_beta, occupations_beta, olp_ab_ab, num_atoms, ab_atom_indices
            )
        elif scheme == "lowdin":
            pop = lowdin_populations(
                coeff_ab_mo_alpha, occupations_alpha, olp_ab_ab, num_atoms, ab_atom_indices
            )
            pop += lowdin_populations(
                coeff_ab_mo_beta, occupations_beta, olp_ab_ab, num_atoms, ab_atom_indices
            )
        else:
            raise ValueError("`scheme` must be one of 'mulliken' or 'lowdin'.")

        return atomic_charges - pop
Esempio n. 4
0
def test_mulliken_populations():
    """Test orbstools.mulliken.mulliken_populations."""
    # Model system
    coeff_ab_mo = np.identity(10)
    occupations = np.array([2] * 4 + [0] * 6)
    olp_ab_ab = np.identity(10)
    num_atoms = 2
    ab_atom_indices = np.array([0, 0, 1, 1, 0, 0, 1, 1, 0, 1])
    assert np.allclose(
        np.array([4, 4]),
        mulliken_populations(coeff_ab_mo, occupations, olp_ab_ab, num_atoms,
                             ab_atom_indices),
    )
    # H2O RHF/STO-3G
    coeff_ab_mo = np.array([
        [
            9.94099882e-01,
            -2.32889095e-01,
            1.65502866e-08,
            1.00235366e-01,
            6.55422174e-16,
            -1.35631600e-01,
            5.67656304e-08,
        ],
        [
            2.67799213e-02,
            8.31788042e-01,
            -9.03020278e-08,
            -5.23423149e-01,
            -3.01062443e-15,
            9.08581133e-01,
            -4.29452063e-07,
        ],
        [
            3.46630004e-03,
            1.03349385e-01,
            -3.46565859e-01,
            6.48259144e-01,
            3.74502802e-15,
            5.83295647e-01,
            5.82525068e-01,
        ],
        [
            2.72896277e-16,
            -2.21764760e-16,
            4.92555323e-16,
            -6.18875097e-15,
            1.00000000e00,
            1.62509738e-16,
            -6.76860125e-17,
        ],
        [
            2.45105601e-03,
            7.30794097e-02,
            4.90116062e-01,
            4.58390414e-01,
            2.54192740e-15,
            4.12453695e-01,
            -8.23811720e-01,
        ],
        [
            -6.08393842e-03,
            1.60223990e-01,
            4.41542336e-01,
            2.69085788e-01,
            1.34551715e-15,
            -8.07337352e-01,
            8.42614916e-01,
        ],
        [
            -6.08393693e-03,
            1.60223948e-01,
            -4.41542341e-01,
            2.69085849e-01,
            1.99471214e-15,
            -8.07337875e-01,
            -8.42614243e-01,
        ],
    ])
    occupations = np.array([2, 2, 2, 2, 2, 0, 0])
    olp_ab_ab = np.array([
        [1.0, 0.23670392, 0.0, 0.0, 0.0, 0.05490733, 0.05490732],
        [0.23670392, 1.0, 0.0, 0.0, 0.0, 0.47954331, 0.47954323],
        [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.37329955],
        [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 1.0, 0.39594342, -0.13197959],
        [0.05490733, 0.47954331, 0.0, 0.0, 0.39594342, 1.0, 0.23846113],
        [
            0.05490732, 0.47954323, 0.37329955, 0.0, -0.13197959, 0.23846113,
            1.0
        ],
    ])
    num_atoms = 3
    ab_atom_indices = np.array([0, 0, 0, 0, 0, 1, 2])
    assert np.allclose(
        np.array([-0.38189777, 0.1909489, 0.19094886]),
        np.array([8, 1, 1]) - mulliken_populations(
            coeff_ab_mo, occupations, olp_ab_ab, num_atoms, ab_atom_indices),
    )
Esempio n. 5
0
def test_mulliken_populations_input():
    """Test input checks in the orbstools.mulliken.mulliken_populations."""
    # get random unitary matrix
    unitary = np.linalg.svd(np.random.rand(20, 20))[0]
    # get random olp_ab_ab
    olp_ab_ab = (unitary * np.random.rand(20)).dot(unitary.T)
    norm = np.diag(olp_ab_ab)**(-0.5)
    olp_ab_ab *= norm[:, None]
    olp_ab_ab *= norm[None, :]
    # get random mo's
    coeff_ab_mo = np.random.rand(20, 15) - 0.5
    coeff_ab_mo *= np.diag(
        coeff_ab_mo.T.dot(olp_ab_ab).dot(coeff_ab_mo))**(-0.5)
    occupations = np.random.rand(15)
    num_atoms = 4
    ab_atom_indices = np.array(
        [0, 1, 2, 1, 1, 0, 2, 1, 0, 2, 1, 2, 0, 1, 2, 0, 3, 3, 1, 0])
    atom_weights = np.random.rand(4, 20, 20)
    atom_weights += np.swapaxes(atom_weights, 1, 2)
    atom_weights /= np.sum(atom_weights, axis=0)[None, :, :]

    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo.tolist(),
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo.ravel(),
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo.astype(int),
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )

    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations.tolist(),
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations[:, None],
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations.astype(bool),
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )

    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab.tolist(),
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab.ravel(),
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab.astype(int),
        num_atoms,
        ab_atom_indices,
    )

    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab,
        float(num_atoms),
        ab_atom_indices,
    )

    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices.tolist(),
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices[:, None],
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices.astype(float),
    )

    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        olp_ab_ab.reshape(10, 40),
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo.reshape(15, 20),
        occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        np.random.rand(20),
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        np.random.rand(20, 20),
        num_atoms,
        ab_atom_indices.tolist(),
    )

    rand_olp_ab_ab = np.random.rand(20, 20)
    rand_olp_ab_ab += rand_olp_ab_ab.T
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        rand_olp_ab_ab,
        num_atoms,
        ab_atom_indices.tolist(),
    )

    rand_olp_ab_ab = np.random.rand(20, 20)
    rand_olp_ab_ab += rand_olp_ab_ab.T
    rand_norm = np.diag(rand_olp_ab_ab)**(-0.5)
    rand_olp_ab_ab *= rand_norm[:, None]
    rand_olp_ab_ab *= rand_norm[None, :]
    assert_raises(
        TypeError,
        mulliken_populations,
        coeff_ab_mo,
        occupations,
        rand_olp_ab_ab,
        num_atoms,
        ab_atom_indices.tolist(),
    )

    rand_occupations = np.random.rand(15)
    rand_occupations[6] = -1
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        rand_occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
    )

    # not sure how to check that the warning is raised but the following code prints the warning
    rand_occupations = np.random.rand(15)
    rand_occupations[6] = 2
    mulliken_populations(coeff_ab_mo, rand_occupations, olp_ab_ab, num_atoms,
                         ab_atom_indices)

    rand_weights = np.random.rand(3, 20, 20)
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        rand_occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
        atom_weights=rand_weights,
    )
    rand_weights = np.random.rand(4, 20, 19)
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        rand_occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
        atom_weights=rand_weights,
    )
    rand_weights = np.random.rand(4, 20, 20)
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        rand_occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
        atom_weights=rand_weights,
    )
    rand_weights = np.random.rand(4, 20, 20)
    rand_weights += np.swapaxes(rand_weights, 1, 2)
    assert_raises(
        ValueError,
        mulliken_populations,
        coeff_ab_mo,
        rand_occupations,
        olp_ab_ab,
        num_atoms,
        ab_atom_indices,
        atom_weights=rand_weights,
    )