Skip to content

Commit

Permalink
Checkout test from yannick/fix_sad
Browse files Browse the repository at this point in the history
  • Loading branch information
YAY-C committed Apr 22, 2024
1 parent eeb1faa commit 84ee0e5
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 99 deletions.
104 changes: 5 additions & 99 deletions qstack/spahm/guesses.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
import sys
import warnings
import numpy
import scipy
import pyscf
import pyscf.dft
from qstack.spahm.LB2020guess import LB2020guess as LB20

def hcore(mol, *_):
"""Uses the diagonalization of the core to compute the guess Hamiltonian.
Args:
mol (pyscf Mole): pyscf Mole object.
Returns:
A numpy ndarray containing the computed approximate Hamiltonian.
"""
h = mol.intor_symmetric('int1e_kin')
h += mol.intor_symmetric('int1e_nuc')
return h

def GWH(mol, *_):
"""Uses the generalized Wolfsberg-Helmholtz to compute the guess Hamiltonian.
Args:
mol (pyscf Mole): pyscf Mole object.
Returns:
A numpy ndarray containing the computed approximate Hamiltonian.
"""
h = hcore(mol)
S = mol.intor_symmetric('int1e_ovlp')
K = 1.75 # See J. Chem. Phys. 1952, 20, 837
Expand All @@ -41,109 +24,45 @@ def GWH(mol, *_):
return h_gwh

def SAD(mol, func):
"""Uses the superposition of atomic densities to compute the guess Hamiltonian.
Args:
mol (pyscf Mole): pyscf Mole object.
func (str): Exchange-correlation functional.
Returns:
A numpy ndarray containing the computed approximate Hamiltonian.
"""
hc = hcore(mol)
print(f"SAD-Hcore = {hc.shape}")
dm = pyscf.scf.hf.init_guess_by_atom(mol)
print(f"SAD-DM = {dm.shape}")
mf = pyscf.dft.RKS(mol)
mf.xc = func
vhf = mf.get_veff(dm=dm)
print(f"XC-dunc = {func} (converged = {mf.converged})")
print(f"SAD-vhf = {vhf.shape}")
fock = hc + vhf
return fock

def SAP(mol, *_):
"""Uses the superposition of atomic potentials to compute the guess Hamiltonian.
Args:
mol (pyscf Mole): pyscf Mole object.
Returns:
A numpy ndarray containing the computed approximate Hamiltonian.
"""
mf = pyscf.dft.RKS(mol)
vsap = mf.get_vsap()
t = mol.intor_symmetric('int1e_kin')
fock = t + vsap
return fock

def LB(mol, *_):
"""Uses the Laikov-Briling model with HF-based parameters to compute the guess Hamiltonian.
Args:
mol (pyscf Mole): pyscf Mole object.
Returns:
A numpy ndarray containing the computed approximate Hamiltonian.
"""
return LB20(parameters='HF').Heff(mol)

def LB_HFS(mol, *_):
""" Laikov-Briling using HFS-based parameters
Args:
mol (pyscf Mole): pyscf Mole object.
Returns:
A numpy ndarray containing the computed approximate Hamiltonian.
"""
return LB20(parameters='HFS').Heff(mol)

def solveF(mol, fock):
"""Computes the eigenvalues and eigenvectors corresponding to the given Hamiltonian.
Args:
mol (pyscf Mole): pyscf Mole object.
fock (numpy ndarray): Approximate Hamiltonian.
"""
s1e = mol.intor_symmetric('int1e_ovlp')
print(f"1e-overlap = {s1e.shape}, Fock = {fock.shape}")
return scipy.linalg.eigh(fock, s1e)

def get_guess(arg):
"""Returns the function of the method selected to compute the approximate hamiltoninan
Args:
arg (str): Approximate Hamiltonian
Returns:
The function of the selected method.
"""
arg = arg.lower()
guesses = {'core':hcore, 'sad':SAD, 'sap':SAP, 'gwh':GWH, 'lb':LB, 'huckel':'huckel', 'lb-hfs':LB_HFS}
if arg not in guesses.keys():
print('Unknown guess. Available guesses:', list(guesses.keys()), file=sys.stderr);
exit(1)
return guesses[arg]


def check_nelec(nelec, nao):
""" Checks if there is enough orbitals
for the electrons"""
if numpy.any(numpy.array(nelec) > nao):
raise RuntimeError(f'Too many electrons ({nelec}) for {nao} orbitals')
elif numpy.any(numpy.array(nelec) == nao):
msg = f'{nelec} electrons for {nao} orbitals. Is the input intended to have a complete shell?'
warnings.warn(msg)


def get_occ(e, nelec, spin):
"""Returns the occupied subset of e
Args:
e (numpy ndarray): Energy eigenvalues.
nelec(tuple): Number of alpha and beta electrons.
spin(int): Spin.
Returns:
A numpy ndarray containing the occupied eigenvalues.
"""
check_nelec(nelec, e.shape[0])
if spin==None:
nocc = nelec[0]
return e[:nocc,...]
Expand All @@ -154,20 +73,7 @@ def get_occ(e, nelec, spin):
e1[1,:nocc[1],...] = e[:nocc[1],...]
return e1


def get_dm(v, nelec, spin):
"""Computes the density matrix.
Args:
v (numpy ndarray): Eigenvectors of a previously solve Hamiltoinan.
nelec(tuple): Number of alpha and beta electrons.
spin(int): Spin.
Return:
A numpy ndarray containing the density matrix computed using the guess Hamiltonian.
"""

check_nelec(nelec, len(v))
if spin==None:
nocc = nelec[0]
dm = v[:,:nocc] @ v[:,:nocc].T
Expand Down
20 changes: 20 additions & 0 deletions tests/data/645688c7c139c6414b5c0b00.xyz
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
18
## STRUCTURE-ID: 645688c7c139c6414b5c0b00 ; CHARGE = -1; SPIN = 3
I -1.4436121126949015 0.42029126592817107 -1.6632891671244727
C -3.33580743801813 -0.15353604789979267 -0.7339542845183026
H -3.1287423587721643 -0.9434022824024976 -0.01933696409311693
H -3.9964207871651225 -0.4901283664418908 -1.5229488133526843
H -3.7274422375299143 0.7217041183959343 -0.2282996045106841
O 2.7223903943392993 0.8261760398398512 1.3050834155297588
C 0.9888087204630703 -2.379094167649743 -0.5398992858009954
H 1.6940986505047444 -3.152743685891341 -0.26448601467465105
H 1.4948333510508294 -1.5155711156764566 -0.9595290502133175
H 0.23509595271835407 -2.753118014964276 -1.2220792965839438
H 3.6453537356643806 0.6064576399990429 1.069461740053683
Rh 0.014459630959218359 0.9679146681456635 0.7456381302221328
I -1.880589614365632 1.6750428531997783 2.5349367788411588
I -0.030250731343837742 -1.749134256908 1.27855077077407
O 2.4116878114136866 0.7236029720756493 -0.9162960476741423
C 1.9293704614065443 0.9262914436358692 0.19859748723285423
O 1.6398052199498723 3.5271918982221226 0.580225781514007
C 0.766961351419702 2.742055038391913 0.35762442437864966
35 changes: 35 additions & 0 deletions tests/test_SAD.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python3

import os
import numpy as np
from qstack import compound
from qstack.spahm.rho import atom


def test_water():
print("Running water-test")
path = os.path.dirname(os.path.realpath(__file__))
mol = compound.xyz_to_mol(path+'/data/H2O.xyz', 'sto3g', charge=0, spin=0)

Xsad = atom.get_repr(mol, ["H", "O"], 0, 0, dm=None,
xc = 'hf', guess='sad', model='lowdin-long-x', auxbasis='ccpvdzjkfit')

print(np.array([*Xsad[:,1]]).shape)
return 0


def test_other():
print("Running weird-test")
path = os.path.dirname(os.path.realpath(__file__))
mol = compound.xyz_to_mol(path+'/data/645688c7c139c6414b5c0b00.xyz', 'sto3g', charge=-1, spin=2)

Xsad = atom.get_repr(mol, ["H", "O", "C", "I", "Rh"], -1, 2, dm=None,
xc = 'hf', guess='sad', model='lowdin-long-x', auxbasis='def2tzvpjkfit')

print(np.array([*Xsad[:,1]]).shape)
return 0


if __name__ == '__main__':
test_water()
test_other()

0 comments on commit 84ee0e5

Please sign in to comment.