Exemplo n.º 1
0
def check_solve(ham, scf_solver, occ_model, lf, olp, kin, na, *exps):
    guess_core_hamiltonian(olp, kin, na, *exps)
    if scf_solver.kind == 'exp':
        occ_model.assign(*exps)
        assert scf_solver.error(ham, lf, olp, *exps) > scf_solver.threshold
        scf_solver(ham, lf, olp, occ_model, *exps)
        assert scf_solver.error(ham, lf, olp, *exps) < scf_solver.threshold
    else:
        occ_model.assign(*exps)
        dms = [exp.to_dm() for exp in exps]
        assert scf_solver.error(ham, lf, olp, *dms) > scf_solver.threshold
        scf_solver(ham, lf, olp, occ_model, *dms)
        assert scf_solver.error(ham, lf, olp, *dms) < scf_solver.threshold
        focks = [lf.create_two_index() for i in xrange(ham.ndm)]
        ham.compute_fock(*focks)
        for i in xrange(ham.ndm):
            exps[i].from_fock(focks[i], olp)
        occ_model.assign(*exps)
Exemplo n.º 2
0
def check_solve(ham, scf_solver, occ_model, lf, olp, kin, na, *exps):
    guess_core_hamiltonian(olp, kin, na, *exps)
    if scf_solver.kind == 'exp':
        occ_model.assign(*exps)
        assert scf_solver.error(ham, lf, olp, *exps) > scf_solver.threshold
        scf_solver(ham, lf, olp, occ_model, *exps)
        assert scf_solver.error(ham, lf, olp, *exps) < scf_solver.threshold
    else:
        occ_model.assign(*exps)
        dms = [exp.to_dm() for exp in exps]
        assert scf_solver.error(ham, lf, olp, *dms) > scf_solver.threshold
        scf_solver(ham, lf, olp, occ_model, *dms)
        assert scf_solver.error(ham, lf, olp, *dms) < scf_solver.threshold
        focks = [lf.create_two_index() for i in xrange(ham.ndm)]
        ham.compute_fock(*focks)
        for i in xrange(ham.ndm):
            exps[i].from_fock(focks[i], olp)
        occ_model.assign(*exps)
Exemplo n.º 3
0
def check_solve(ham, scf_solver, occ_model, olp, kin, na, *orbs):
    guess_core_hamiltonian(olp, kin+na, *orbs)
    if scf_solver.kind == 'orb':
        occ_model.assign(*orbs)
        assert scf_solver.error(ham, olp, *orbs) > scf_solver.threshold
        scf_solver(ham, olp, occ_model, *orbs)
        assert scf_solver.error(ham, olp, *orbs) < scf_solver.threshold
    else:
        occ_model.assign(*orbs)
        dms = [orb.to_dm() for orb in orbs]
        assert scf_solver.error(ham, olp, *dms) > scf_solver.threshold
        scf_solver(ham, olp, occ_model, *dms)
        assert scf_solver.error(ham, olp, *dms) < scf_solver.threshold
        focks = [np.zeros(dms[0].shape) for i in xrange(ham.ndm)]
        ham.compute_fock(*focks)
        for i in xrange(ham.ndm):
            orbs[i].from_fock(focks[i], olp)
        occ_model.assign(*orbs)
Exemplo n.º 4
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)
Exemplo n.º 5
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)
Exemplo n.º 6
0
def check_interpolation(ham, lf, olp, kin, na, exps, do_plot=False):
    dm0s = [exp.to_dm() for exp in exps]
    guess_core_hamiltonian(olp, kin, na, *exps)
    dm1s = [exp.to_dm() for exp in exps]
    check_cubic_wrapper(ham, dm0s, dm1s, do_plot)
Exemplo n.º 7
0
def check_dot_hessian_polynomial(olp,
                                 core,
                                 ham,
                                 exps,
                                 is_hf=True,
                                 extent=1.0,
                                 threshold=1e-2,
                                 do_plot=False):
    """Test dot_hessian by making a quadratic energy approximation.

    The quadratic model is used to interpolate the energy between the given solution
    (exps) and the core Hamiltonian guess.

    Parameters
    ----------
    olp : TwoIndex
        The overlap matrix.
    core : TwoIndex
        The core Hamiltonian.
    ham : EffHam
        An effective Hamiltonian.
    exps : Expansion
        A set of orbitals (one for restricted, two for unrestricted)
    is_hf : bool
        Set to True when testing with pure HF.
    extent : float
        The extent of the interpolation. 1.0 is whole range.
    threshold : float
        The allowed error between the energies.
    do_plot : bool
        When True, some plots will be made. Useful for debugging.
    """
    # First alpha density matrix is the given matrix
    dms1 = [exp.to_dm() for exp in exps]

    # Second alpha density matrix is that from the core Hamiltonian
    guess_core_hamiltonian(olp, core, *exps)
    dms2 = [exp.to_dm() for exp in exps]

    # Test quadratic interpolation of the energy. This should match very well
    # with normal energy calculations as the energy is quadratic in the
    # density matrix.
    npoint = 11
    xs = np.linspace(0.0, extent, npoint)

    def check(dms_a, dms_b):
        """Check quadratic energy model between two dms."""
        ham.reset(*dms_a)
        energy_a_0 = ham.compute_energy()
        focks_a = [dm_a.new() for dm_a in dms_a]
        ham.compute_fock(*focks_a)

        delta_dms = []
        for idm in xrange(ham.ndm):
            delta_dm = dms_b[idm].copy()
            delta_dm.iadd(dms_a[idm], -1)
            delta_dms.append(delta_dm)
        ham.reset_delta(*delta_dms)
        dots_a = [dm_a.new() for dm_a in dms_a]
        ham.compute_dot_hessian(*dots_a)

        energy_a_1 = 0.0
        energy_a_2 = 0.0
        for idm in xrange(ham.ndm):
            energy_a_1 += focks_a[idm].contract_two(
                'ab,ba', delta_dms[idm]) * ham.deriv_scale
            energy_a_2 += dots_a[idm].contract_two(
                'ab,ba', delta_dms[idm]) * ham.deriv_scale**2

        # print 'energy_a_0', energy_a_0
        # print 'energy_a_1', energy_a_1
        # print 'energy_a_2', energy_a_2

        # Compute interpolation and compare
        energies_x = np.zeros(npoint)
        energies_2nd_order = np.zeros(npoint)
        derivs_x = np.zeros(npoint)
        derivs_2nd_order = np.zeros(npoint)
        for ipoint in xrange(npoint):
            x = xs[ipoint]
            dms_x = []
            for idm in xrange(ham.ndm):
                dm_x = dms_a[idm].copy()
                dm_x.iscale(1 - x)
                dm_x.iadd(dms_b[idm], x)
                dms_x.append(dm_x)
            ham.reset(*dms_x)
            energies_x[ipoint] = ham.compute_energy()
            ham.compute_fock(*focks_a)
            for idm in xrange(ham.ndm):
                derivs_x[ipoint] += focks_a[idm].contract_two('ab,ba', delta_dms[idm]) * \
                                    ham.deriv_scale

            energies_2nd_order[
                ipoint] = energy_a_0 + x * energy_a_1 + 0.5 * x * x * energy_a_2
            derivs_2nd_order[ipoint] = energy_a_1 + x * energy_a_2
            # print '%5.2f %15.8f %15.8f' % (x, energies_x[ipoint], energies_2nd_order[ipoint])

        if do_plot:  # pragma: no cover
            import matplotlib.pyplot as pt
            pt.clf()
            pt.plot(xs, energies_x, 'ro')
            pt.plot(xs, energies_2nd_order, 'k-')
            pt.savefig('test_energies.png')
            pt.clf()
            pt.plot(xs, derivs_x, 'ro')
            pt.plot(xs, derivs_2nd_order, 'k-')
            pt.savefig('test_derivs.png')

        assert abs(energies_x -
                   energies_2nd_order).max() / np.ptp(energies_x) < threshold
        assert abs(derivs_x -
                   derivs_2nd_order).max() / np.ptp(derivs_x) < threshold
        return energy_a_0, energy_a_1, energy_a_2

    # 1) using dms1 as reference point
    _energy1_0, _energy1_1, energy1_2 = check(dms1, dms2)

    # 2) using dms2 as reference point
    _energy2_0, _energy2_1, energy2_2 = check(dms2, dms1)

    if is_hf:
        # Final check: curvature should be the same in the HF case.
        assert abs(energy1_2 - energy2_2) < threshold
Exemplo n.º 8
0
def check_interpolation(ham, lf, olp, kin, na, exps, do_plot=False):
    dm0s = [exp.to_dm() for exp in exps]
    guess_core_hamiltonian(olp, kin, na, *exps)
    dm1s = [exp.to_dm() for exp in exps]
    check_cubic_wrapper(ham, dm0s, dm1s, do_plot)
Exemplo n.º 9
0
def check_interpolation(ham, olp, kin, na, orbs, do_plot=False):
    dm0s = [orb.to_dm() for orb in orbs]
    guess_core_hamiltonian(olp, kin+na, *orbs)
    dm1s = [orb.to_dm() for orb in orbs]
    check_cubic_wrapper(ham, dm0s, dm1s, do_plot)
Exemplo n.º 10
0
def check_dot_hessian_polynomial(olp, core, ham, orbs, is_hf=True, extent=1.0,
                                 threshold=1e-2, do_plot=False):
    """Test dot_hessian by making a quadratic energy approximation.

    The quadratic model is used to interpolate the energy between the given solution
    (orbs) and the core Hamiltonian guess.

    Parameters
    ----------
    olp : TwoIndex
        The overlap matrix.
    core : TwoIndex
        The core Hamiltonian.
    ham : EffHam
        An effective Hamiltonian.
    orbs : list of Orbitals objects.
        A set of orbitals (one for restricted, two for unrestricted)
    is_hf : bool
        Set to True when testing with pure HF.
    extent : float
        The extent of the interpolation. 1.0 is whole range.
    threshold : float
        The allowed error between the energies.
    do_plot : bool
        When True, some plots will be made. Useful for debugging.
    """
    # First alpha density matrix is the given matrix
    dms1 = [orb.to_dm() for orb in orbs]

    # Second alpha density matrix is that from the core Hamiltonian
    guess_core_hamiltonian(olp, core, *orbs)
    dms2 = [orb.to_dm() for orb in orbs]

    # Test quadratic interpolation of the energy. This should match very well
    # with normal energy calculations as the energy is quadratic in the
    # density matrix.
    npoint = 11
    xs = np.linspace(0.0, extent, npoint)

    def check(dms_a, dms_b):
        """Check quadratic energy model between two dms."""
        ham.reset(*dms_a)
        energy_a_0 = ham.compute_energy()
        focks_a = [np.zeros(dm_a.shape) for dm_a in dms_a]
        ham.compute_fock(*focks_a)

        delta_dms = []
        for idm in xrange(ham.ndm):
            delta_dms.append(dms_b[idm] - dms_a[idm])
        ham.reset_delta(*delta_dms)
        dots_a = [np.zeros(dm_a.shape) for dm_a in dms_a]
        ham.compute_dot_hessian(*dots_a)

        energy_a_1 = 0.0
        energy_a_2 = 0.0
        for idm in xrange(ham.ndm):
            energy_a_1 += np.einsum('ab,ba', focks_a[idm], delta_dms[idm])*ham.deriv_scale
            energy_a_2 += np.einsum('ab,ba', dots_a[idm], delta_dms[idm])*ham.deriv_scale**2

        # print 'energy_a_0', energy_a_0
        # print 'energy_a_1', energy_a_1
        # print 'energy_a_2', energy_a_2

        # Compute interpolation and compare
        energies_x = np.zeros(npoint)
        energies_2nd_order = np.zeros(npoint)
        derivs_x = np.zeros(npoint)
        derivs_2nd_order = np.zeros(npoint)
        for ipoint in xrange(npoint):
            x = xs[ipoint]
            dms_x = []
            for idm in xrange(ham.ndm):
                dm_x = dms_a[idm]*(1-x) + dms_b[idm]*x
                dms_x.append(dm_x)
            ham.reset(*dms_x)
            energies_x[ipoint] = ham.compute_energy()
            ham.compute_fock(*focks_a)
            for idm in xrange(ham.ndm):
                derivs_x[ipoint] += np.einsum('ab,ba', focks_a[idm], delta_dms[idm]) * \
                                    ham.deriv_scale

            energies_2nd_order[ipoint] = energy_a_0 + x*energy_a_1 + 0.5*x*x*energy_a_2
            derivs_2nd_order[ipoint] = energy_a_1 + x*energy_a_2
            # print '%5.2f %15.8f %15.8f' % (x, energies_x[ipoint], energies_2nd_order[ipoint])

        if do_plot:  # pragma: no cover
            import matplotlib.pyplot as pt
            pt.clf()
            pt.plot(xs, energies_x, 'ro')
            pt.plot(xs, energies_2nd_order, 'k-')
            pt.savefig('test_energies.png')
            pt.clf()
            pt.plot(xs, derivs_x, 'ro')
            pt.plot(xs, derivs_2nd_order, 'k-')
            pt.savefig('test_derivs.png')

        assert abs(energies_x - energies_2nd_order).max()/np.ptp(energies_x) < threshold
        assert abs(derivs_x - derivs_2nd_order).max()/np.ptp(derivs_x) < threshold
        return energy_a_0, energy_a_1, energy_a_2

    # 1) using dms1 as reference point
    _energy1_0, _energy1_1, energy1_2 = check(dms1, dms2)

    # 2) using dms2 as reference point
    _energy2_0, _energy2_1, energy2_2 = check(dms2, dms1)

    if is_hf:
        # Final check: curvature should be the same in the HF case.
        assert abs(energy1_2 - energy2_2) < threshold