Ejemplo n.º 1
0
def compute_sr_potential(nbasis, er_sr, dms, whichpot):
    """
    Add Short-Range Hartree or Exchange Potential to one-electron integrals
    using Horton.

    Arguments:
    ----------
    nbasis: int
        Number of basis functions
    er_sr: np.ndarray((nbasis, nbasis, nbasis, nbasis))
        Short-Range two-electron integrals
    dms: list, np.ndarray((nbasis, nbasis))
        Density matrices
    whichpot: str
        Type of potential to be computed. Options are:
        'exchange' for the exchange potential
        'hartree' for the Hartree potential
    """
    if len(dms) == 1:
        # Restricted case
        if whichpot == 'hartree':
            ham = REffHam([RDirectTerm(er_sr, 'hartree')])
        elif whichpot == 'exchange':
            ham = REffHam([RExchangeTerm(er_sr, 'x')])
        ham.reset(dms[0])
    elif len(dms) == 2:
        # Unrestricted case
        if whichpot == 'hartree':
            ham = UEffHam([UDirectTerm(er_sr, 'hartree')])
        else:
            ham = UEffHam([UExchangeTerm(er_sr, 'x')])
        ham.reset(dms)
    sr_potential = np.zeros((nbasis, nbasis))
    ham.compute_fock(sr_potential)
    return sr_potential
Ejemplo n.º 2
0
def check_hf_cs_hf(scf_solver):
    fn_fchk = context.get_fn('test/hf_sto3g.fchk')
    mol = IOData.from_file(fn_fchk)

    olp = mol.obasis.compute_overlap()
    kin = mol.obasis.compute_kinetic()
    na = mol.obasis.compute_nuclear_attraction(mol.coordinates, mol.pseudo_numbers)
    er = mol.obasis.compute_electron_repulsion()
    external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)}
    terms = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RExchangeTerm(er, 'x_hf'),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham = REffHam(terms, external)
    occ_model = AufbauOccModel(5)

    check_solve(ham, scf_solver, occ_model, olp, kin, na, mol.orb_alpha)

    # test orbital energies
    expected_energies = np.array([
        -2.59083334E+01, -1.44689996E+00, -5.57467136E-01, -4.62288194E-01,
        -4.62288194E-01, 5.39578910E-01,
    ])
    assert abs(mol.orb_alpha.energies - expected_energies).max() < 1e-5

    ham.compute_energy()
    # compare with g09
    assert abs(ham.cache['energy'] - -9.856961609951867E+01) < 1e-8
    assert abs(ham.cache['energy_kin'] - 9.766140786239E+01) < 2e-7
    assert abs(ham.cache['energy_hartree'] + ham.cache['energy_x_hf'] - 4.561984106482E+01) < 1e-6
    assert abs(ham.cache['energy_ne'] - -2.465756615329E+02) < 1e-6
    assert abs(ham.cache['energy_nn'] - 4.7247965053) < 1e-8
Ejemplo n.º 3
0
def compute_hf_energy(mol):
    olp = mol.obasis.compute_overlap(mol.lf)
    kin = mol.obasis.compute_kinetic(mol.lf)
    na = mol.obasis.compute_nuclear_attraction(mol.coordinates,
                                               mol.pseudo_numbers, mol.lf)
    er = mol.obasis.compute_electron_repulsion(mol.lf)
    external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)}
    if hasattr(mol, 'exp_beta'):
        # assuming unrestricted
        terms = [
            UTwoIndexTerm(kin, 'kin'),
            UDirectTerm(er, 'hartree'),
            UExchangeTerm(er, 'x_hf'),
            UTwoIndexTerm(na, 'ne'),
        ]
        ham = UEffHam(terms, external)
        dm_alpha = mol.exp_alpha.to_dm()
        dm_beta = mol.exp_beta.to_dm()
        ham.reset(dm_alpha, dm_beta)
    else:
        # assuming restricted
        terms = [
            RTwoIndexTerm(kin, 'kin'),
            RDirectTerm(er, 'hartree'),
            RExchangeTerm(er, 'x_hf'),
            RTwoIndexTerm(na, 'ne'),
        ]
        ham = REffHam(terms, external)
        dm_alpha = mol.exp_alpha.to_dm()
        ham.reset(dm_alpha)
    return ham.compute_energy()
Ejemplo n.º 4
0
def check_co_cs_pbe(scf_solver):
    fn_fchk = context.get_fn('test/co_pbe_sto3g.fchk')
    mol = IOData.from_file(fn_fchk)
    grid = BeckeMolGrid(mol.coordinates,
                        mol.numbers,
                        mol.pseudo_numbers,
                        'fine',
                        random_rotate=False)
    olp = mol.obasis.compute_overlap(mol.lf)
    kin = mol.obasis.compute_kinetic(mol.lf)
    na = mol.obasis.compute_nuclear_attraction(mol.coordinates,
                                               mol.pseudo_numbers, mol.lf)
    er = mol.obasis.compute_electron_repulsion(mol.lf)
    external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)}
    terms = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RGridGroup(mol.obasis, grid, [
            RLibXCGGA('x_pbe'),
            RLibXCGGA('c_pbe'),
        ]),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham = REffHam(terms, external)

    # Test energy before scf
    energy, focks = helper_compute(ham, mol.lf, mol.exp_alpha)
    assert abs(energy - -1.116465967841901E+02) < 1e-4

    # The convergence should be reasonable, not perfect because of limited
    # precision in Gaussian fchk file:
    assert convergence_error_eigen(ham, mol.lf, olp, mol.exp_alpha) < 1e-5

    # Converge from scratch
    occ_model = AufbauOccModel(7)
    check_solve(ham, scf_solver, occ_model, mol.lf, olp, kin, na,
                mol.exp_alpha)

    # test orbital energies
    expected_energies = np.array([
        -1.86831122E+01, -9.73586915E+00, -1.03946082E+00, -4.09331776E-01,
        -3.48686522E-01, -3.48686522E-01, -2.06049056E-01, 5.23730418E-02,
        5.23730418E-02, 6.61093726E-01
    ])
    assert abs(mol.exp_alpha.energies - expected_energies).max() < 1e-2

    ham.compute_energy()
    # compare with g09
    assert abs(ham.cache['energy_ne'] - -3.072370116827E+02) < 1e-2
    assert abs(ham.cache['energy_kin'] - 1.103410779827E+02) < 1e-2
    assert abs(ham.cache['energy_hartree'] +
               ham.cache['energy_libxc_gga_x_pbe'] +
               ham.cache['energy_libxc_gga_c_pbe'] - 6.273115782683E+01) < 1e-2
    assert abs(ham.cache['energy'] - -1.116465967841901E+02) < 1e-4
    assert abs(ham.cache['energy_nn'] - 22.5181790889) < 1e-7
Ejemplo n.º 5
0
def check_water_cs_m05(scf_solver):
    """Try to converge the SCF for the water molecule with the M05 functional.

    Parameters
    ----------
    scf_solver : one of the SCFSolver types in HORTON
                 A configured SCF solver that must be tested.
    """
    fn_fchk = context.get_fn('test/water_m05_321g.fchk')
    mol = IOData.from_file(fn_fchk)
    grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, 'fine',
                        random_rotate=False)
    olp = mol.obasis.compute_overlap()
    kin = mol.obasis.compute_kinetic()
    na = mol.obasis.compute_nuclear_attraction(mol.coordinates, mol.pseudo_numbers)
    er = mol.obasis.compute_electron_repulsion()
    external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)}
    libxc_term = RLibXCHybridMGGA('xc_m05')
    terms = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RGridGroup(mol.obasis, grid, [libxc_term]),
        RExchangeTerm(er, 'x_hf', libxc_term.get_exx_fraction()),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham = REffHam(terms, external)

    # compute the energy before converging
    dm_alpha = mol.orb_alpha.to_dm()
    ham.reset(dm_alpha)
    ham.compute_energy()
    assert abs(ham.cache['energy'] - -75.9532086800) < 1e-3

    # The convergence should be reasonable, not perfect because of limited
    # precision in the molden file:
    assert convergence_error_eigen(ham, olp, mol.orb_alpha) < 1e-3

    # keep a copy of the orbital energies
    expected_alpha_energies = mol.orb_alpha.energies.copy()

    # Converge from scratch
    occ_model = AufbauOccModel(5)
    check_solve(ham, scf_solver, occ_model, olp, kin, na, mol.orb_alpha)

    # test orbital energies
    assert abs(mol.orb_alpha.energies - expected_alpha_energies).max() < 2e-3

    ham.compute_energy()
    # compare with
    assert abs(ham.cache['energy_kin'] - 75.54463056278) < 1e-2
    assert abs(ham.cache['energy_ne'] - -198.3003887880) < 1e-2
    assert abs(ham.cache['energy_hartree'] + ham.cache['energy_x_hf'] +
               ham.cache['energy_libxc_hyb_mgga_xc_m05'] - 3.764537450376E+01) < 1e-2
    assert abs(ham.cache['energy'] - -75.9532086800) < 1e-3
    assert abs(ham.cache['energy_nn'] - 9.1571750414) < 1e-5
Ejemplo n.º 6
0
def check_water_cs_hfs(scf_solver):
    fn_fchk = context.get_fn('test/water_hfs_321g.fchk')
    mol = IOData.from_file(fn_fchk)

    grid = BeckeMolGrid(mol.coordinates, mol.numbers, mol.pseudo_numbers, random_rotate=False)
    olp = mol.obasis.compute_overlap()
    kin = mol.obasis.compute_kinetic()
    na = mol.obasis.compute_nuclear_attraction(mol.coordinates, mol.pseudo_numbers)
    er = mol.obasis.compute_electron_repulsion()
    external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)}
    terms = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RGridGroup(mol.obasis, grid, [
            RDiracExchange(),
        ]),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham = REffHam(terms, external)

    # The convergence should be reasonable, not perfect because of limited
    # precision in Gaussian fchk file and different integration grids:
    assert convergence_error_eigen(ham, olp, mol.orb_alpha) < 3e-5

    # Recompute the orbitals and orbital energies. This should be reasonably OK.
    dm_alpha = mol.orb_alpha.to_dm()
    ham.reset(dm_alpha)
    ham.compute_energy()
    fock_alpha = np.zeros(dm_alpha.shape)
    ham.compute_fock(fock_alpha)
    mol.orb_alpha.from_fock(fock_alpha, olp)

    expected_energies = np.array([
        -1.83691041E+01, -8.29412411E-01, -4.04495188E-01, -1.91740814E-01,
        -1.32190590E-01, 1.16030419E-01, 2.08119657E-01, 9.69825207E-01,
        9.99248500E-01, 1.41697384E+00, 1.47918828E+00, 1.61926596E+00,
        2.71995350E+00
    ])

    assert abs(mol.orb_alpha.energies - expected_energies).max() < 2e-4
    assert abs(ham.cache['energy_ne'] - -1.977921986200E+02) < 1e-7
    assert abs(ham.cache['energy_kin'] - 7.525067610865E+01) < 1e-9
    assert abs(ham.cache['energy_hartree'] + ham.cache['energy_x_dirac'] - 3.864299848058E+01) < 2e-4
    assert abs(ham.cache['energy'] - -7.474134898935590E+01) < 2e-4
    assert abs(ham.cache['energy_nn'] - 9.1571750414) < 2e-8

    # Converge from scratch and check energies
    occ_model = AufbauOccModel(5)
    check_solve(ham, scf_solver, occ_model, olp, kin, na, mol.orb_alpha)

    ham.compute_energy()
    assert abs(ham.cache['energy_ne'] - -1.977921986200E+02) < 1e-4
    assert abs(ham.cache['energy_kin'] - 7.525067610865E+01) < 1e-4
    assert abs(ham.cache['energy_hartree'] + ham.cache['energy_x_dirac'] - 3.864299848058E+01) < 2e-4
    assert abs(ham.cache['energy'] - -7.474134898935590E+01) < 2e-4
Ejemplo n.º 7
0
def check_vanadium_sc_hf(scf_solver):
    """Try to converge the SCF for the neutral vanadium atom with fixe fractional occupations.

    Parameters
    ----------
    scf_solver : one of the SCFSolver types in HORTON
                 A configured SCF solver that must be tested.
    """
    # vanadium atoms
    numbers = np.array([23])
    pseudo_numbers = numbers.astype(float)
    coordinates = np.zeros((1, 3), float)

    # Simple basis set
    obasis = get_gobasis(coordinates, numbers, 'def2-tzvpd')

    # Dense matrices
    lf = DenseLinalgFactory(obasis.nbasis)

    # Compute integrals
    olp = obasis.compute_overlap(lf)
    kin = obasis.compute_kinetic(lf)
    na = obasis.compute_nuclear_attraction(coordinates, pseudo_numbers, lf)
    er = obasis.compute_electron_repulsion(lf)

    # Setup of restricted HF Hamiltonian
    terms = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RExchangeTerm(er, 'x_hf'),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham = REffHam(terms)

    # Define fractional occupations of interest. (Spin-compensated case)
    occ_model = FixedOccModel(
        np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5]))

    # Allocate orbitals and make the initial guess
    exp_alpha = lf.create_expansion(obasis.nbasis)
    guess_core_hamiltonian(olp, kin, na, exp_alpha)

    # SCF test
    check_solve(ham, scf_solver, occ_model, lf, olp, kin, na, exp_alpha)
Ejemplo n.º 8
0
def check_n2_cs_hfs(scf_solver):
    fn_fchk = context.get_fn('test/n2_hfs_sto3g.fchk')
    mol = IOData.from_file(fn_fchk)
    grid = BeckeMolGrid(mol.coordinates,
                        mol.numbers,
                        mol.pseudo_numbers,
                        'veryfine',
                        random_rotate=False)
    olp = mol.obasis.compute_overlap(mol.lf)
    kin = mol.obasis.compute_kinetic(mol.lf)
    na = mol.obasis.compute_nuclear_attraction(mol.coordinates,
                                               mol.pseudo_numbers, mol.lf)
    er = mol.obasis.compute_electron_repulsion(mol.lf)
    external = {'nn': compute_nucnuc(mol.coordinates, mol.pseudo_numbers)}

    libxc_term = RLibXCLDA('x')
    terms1 = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RGridGroup(mol.obasis, grid, [libxc_term]),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham1 = REffHam(terms1, external)

    builtin_term = RDiracExchange()
    terms2 = [
        RTwoIndexTerm(kin, 'kin'),
        RDirectTerm(er, 'hartree'),
        RGridGroup(mol.obasis, grid, [builtin_term]),
        RTwoIndexTerm(na, 'ne'),
    ]
    ham2 = REffHam(terms2, external)

    # Compare the potential computed by libxc with the builtin implementation
    energy1, focks1 = helper_compute(ham1, mol.lf, mol.exp_alpha)
    energy2, focks2 = helper_compute(ham2, mol.lf, mol.exp_alpha)
    libxc_pot = ham1.cache.load('pot_libxc_lda_x_alpha')
    builtin_pot = ham2.cache.load('pot_x_dirac_alpha')
    # Libxc apparently approximates values of the potential below 1e-4 with zero.
    assert abs(libxc_pot - builtin_pot).max() < 1e-4
    # Check of the libxc energy matches our implementation
    assert abs(energy1 - energy2) < 1e-10
    ex1 = ham1.cache['energy_libxc_lda_x']
    ex2 = ham2.cache['energy_x_dirac']
    assert abs(ex1 - ex2) < 1e-10

    # The convergence should be reasonable, not perfect because of limited
    # precision in Gaussian fchk file:
    assert convergence_error_eigen(ham1, mol.lf, olp, mol.exp_alpha) < 1e-5
    assert convergence_error_eigen(ham2, mol.lf, olp, mol.exp_alpha) < 1e-5

    occ_model = AufbauOccModel(7)
    for ham in ham1, ham2:
        # Converge from scratch
        check_solve(ham, scf_solver, occ_model, mol.lf, olp, kin, na,
                    mol.exp_alpha)

        # test orbital energies
        expected_energies = np.array([
            -1.37107053E+01,
            -1.37098006E+01,
            -9.60673085E-01,
            -3.57928483E-01,
            -3.16017655E-01,
            -3.16017655E-01,
            -2.12998316E-01,
            6.84030479E-02,
            6.84030479E-02,
            7.50192517E-01,
        ])
        assert abs(mol.exp_alpha.energies - expected_energies).max() < 3e-5

        ham.compute_energy()
        assert abs(ham.cache['energy_ne'] - -2.981579553570E+02) < 1e-5
        assert abs(ham.cache['energy_kin'] - 1.061620887711E+02) < 1e-5
        assert abs(ham.cache['energy'] - -106.205213597) < 1e-4
        assert abs(ham.cache['energy_nn'] - 23.3180604505) < 1e-8
    assert abs(ham1.cache['energy_hartree'] +
               ham1.cache['energy_libxc_lda_x'] - 6.247259253877E+01) < 1e-4
    assert abs(ham2.cache['energy_hartree'] + ham2.cache['energy_x_dirac'] -
               6.247259253877E+01) < 1e-4