I am interested in the use case described in this old post: Save orbitals and restart SCF
Namely, restarting a failed SCF job, with the old calculation as the wavefunction guess, but adding slow-and-steady convergence options such as SOSCF or damping.
The code included in that post (translated to Python) does not work for me; in fact, GUESS: READ
seems to do nothing when a restart is initiated in this way. The SCF restart happens, but I just get SCF Guess: Superposition of Atomic Densities via on-the-fly atomic UHF (no occupation information)
as usual, without even an error message saying there is no wavefunction file (there is, I checked using os.path.exists()
).
This example code should be complete and runnable. Note that, when this code is run, the second SCF run in the resulting file does not use the guess from the first. SOSCF does kick in, as desired, but it seems quite wasteful not to use the existing wavefunction guess.
'''
Test psi4 SCF restart capabilities
'''
import os
import time
import numpy as np
import psi4
def run_psi4(name, atomic_numbers, xyz, net_charge=0, theory='wB97X-D3BJ/def2-TZVPD',
ram_gb=4.0):
'''
Run psi4
'''
outfile = name + '.psi4'
psi4.core.set_output_file(outfile, False)
atomic_numbers = np.array(atomic_numbers)
n_electrons = np.sum(atomic_numbers) - net_charge
psi4.set_memory('%f GiB' % ram_gb)
geom_string = '\n'.join(['%d %.8f %.8f %.8f' % (e, x, y, z) for e, (x, y, z) in zip(atomic_numbers, xyz)])
geom_string = str(net_charge) + ' 1\n' + geom_string
mol = psi4.geometry(geom_string) # in angstroms by default
settings = {
'scf_type': 'DF', # density fitting, may use RAM or disk (needs fast disk)
'maxiter': 10, # for testing, make sure we don't converge first time
}
psi4.set_options(settings)
start_time = time.time()
try: # allow SCF failure without crashing
grad, wfn = psi4.gradient(theory, return_wfn=True) # in Hartree/Bohr
except psi4.driver.SCFConvergenceError as ex:
print(repr(ex), '- retrying', flush=True)
# try all obvious ways of writing the wfn file
wfn_file = ex.wfn.get_scratch_filename(180)
ex.wfn.to_file(wfn_file)
wfn_file = ex.wfn.get_scratch_filename(180) + '.npy'
ex.wfn.to_file(wfn_file)
print(f'{wfn_file = }, {os.path.exists(wfn_file) = }', flush=True)
psi4.set_options({
'SOSCF': True, # 2-3x slower, but steadier convergence
'guess': 'read',
'maxiter': 100,
})
try: # try again with new options
grad = psi4.gradient(theory) # in Hartree/Bohr
except psi4.driver.SCFConvergenceError as ex:
psi4.core.clean()
psi4.core.clean_options()
print(repr(ex), '- stopping', flush=True)
return # skip this system
psi4.core.print_variables() # list variables explicitly in output file
psi4.core.clean() # clean up old data & files for next round
psi4.core.clean_options()
elapsed_time = time.time() - start_time
print(name, n_electrons, 'electrons', elapsed_time, 'seconds', flush=True)
if __name__ == '__main__':
n_cores = 8
ram_gb = 32.0
psi4.set_num_threads(n_cores)
name = 'Li-metal-cluster'
atomic_numbers = np.array([3] * 16)
xyz = np.array([[ 4.00, 0.00, 0.25],
[-2.00, -0.00, -1.75],
[-2.00, -0.00, 2.25],
[-4.00, -0.00, 0.25],
[-2.00, 2.00, 0.25],
[-2.00, -2.00, 0.25],
[ 2.00, 0.00, -1.75],
[ 0.00, 0.00, -3.75],
[-0.00, 2.00, -1.75],
[ 0.00, -2.00, -1.75],
[ 2.00, 0.00, 2.25],
[ 0.00, 0.00, 0.25],
[-0.00, 2.00, 2.25],
[ 2.00, 2.00, 0.25],
[ 0.00, -2.00, 2.25],
[ 2.00, -2.00, 0.25]])
net_charge = 0
run_psi4(name, atomic_numbers, xyz, net_charge,
'wB97X-D3/cc-pVTZ', ram_gb)
To be honest, I have been struggling with the Psi4 restart functionality since I first started using Psi4 a couple of years ago. As far as I have searched, documentation for the 180 file and wavefunction guesses is still not complete, despite similar forum posts like Read in from scf with psi4.core.Wavefunction.from_file()? - #2 by jmisiewicz.