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
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
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(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, [ 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, mol.lf, olp, mol.exp_alpha) < 3e-5 # Recompute the orbitals and orbital energies. This should be reasonably OK. dm_alpha = mol.exp_alpha.to_dm() ham.reset(dm_alpha) ham.compute_energy() fock_alpha = mol.lf.create_two_index() ham.compute_fock(fock_alpha) mol.exp_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.exp_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, mol.lf, olp, kin, na, mol.exp_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
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