Skip to content

Commit

Permalink
Adding in HFX Workflow functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongarrison committed Nov 20, 2024
1 parent 1ff4cb9 commit e33e40b
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 15 deletions.
49 changes: 41 additions & 8 deletions jobmanager/psi4_utils/psi4_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def run_b3lyp(self, rundir="./", return_wfn=True,
return success

def run_general(self, functional="b3lyp", rundir="./", return_wfn=False,
psi4_scr='./', filename='output', verbose=True):
psi4_scr='./', filename='output', verbose=False):
"""
From a directory, launches calculations with other functionals from the .wfn specified in the functional input.
Does so in subdirectories with names corresponding to the functional names.
Expand Down Expand Up @@ -502,7 +502,8 @@ def run_general_hfx(self, functional, hfx, wfn, return_wfn=True,
os.remove(filename)
return success

def run_with_check(self, method, functional='b3lyp'):
def run_with_check(self, method, functional='b3lyp', rundir="./", return_wfn=False,
psi4_scr='./', filename='output', verbose=False, retry_scf=False):
"""
Will run a psi4 calculation using the method specified in method, using the
functional specified in functional.
Expand All @@ -512,6 +513,20 @@ def run_with_check(self, method, functional='b3lyp'):
Either run_b3lyp or run_general, depending on what calculation is being run.
functional: str
Name of the functional one wants to use in the calculation.
rundir: str
Path where functional calculations are run from.
Results will be stored in the path rundir+functional.
return_wfn: bool
Whether or not the wfn file should be written after the calculation.
psi4_scr: str
Path of the Psi4 scratch directory.
filename: str
Name out the output .dat file containing results.
verbose: bool
If true, will print wfn the calculation is started from (for run_general).
retry_scf: bool
If true, will retry a calculation if it failed due to SCF iterations reached.
Should
Returns:
success: bool
Expand All @@ -536,9 +551,12 @@ def run_with_check(self, method, functional='b3lyp'):
#If the corresponding folder not present, run function from molden/b3lyp reference
if not os.path.isdir(functional):
if functional == 'b3lyp':
success = runfunc(rundir='./')
success = runfunc(rundir=rundir, return_wfn=return_wfn,
psi4_scr=psi4_scr, filename=filename)
else:
success = runfunc(rundir='./', functional=functional)
success = runfunc(functional=functional, rundir=rundir,
return_wfn=return_wfn, psi4_scr=psi4_scr,
filename=filename, verbose=verbose)
print(f'Success: {success}')
else:
#If calculation already attempted, check for convergence
Expand All @@ -555,9 +573,12 @@ def run_with_check(self, method, functional='b3lyp'):
if resubed:
print("previous errored out. resubmitting...")
if functional == 'b3lyp':
success = runfunc(rundir="./")
success = runfunc(rundir=rundir, return_wfn=return_wfn,
psi4_scr=psi4_scr, filename=filename)
else:
success = runfunc(rundir='./', functional=functional)
success = runfunc(functional=functional, rundir=rundir,
return_wfn=return_wfn, psi4_scr=psi4_scr,
filename=filename, verbose=verbose)
print("success: ", success)
else:
#If checks above pass, ensure no SCF error in calculation and that .wfn written
Expand All @@ -566,7 +587,19 @@ def run_with_check(self, method, functional='b3lyp'):
#Checking for the wfn only for if return_wfn=True, but False by default for run_general
if 'PsiException: Could not converge SCF iterations' not in txt: # and os.path.isfile(functional + "/wfn.180.npy"):
success = True
print("success: ", success)
else: #Did not converge in the given number of SCF iterations
if retry_scf:
if functional == 'b3lyp':
success = runfunc(rundir=rundir, return_wfn=return_wfn,
psi4_scr=psi4_scr, filename=filename)
else:
success = runfunc(functional=functional, rundir=rundir,
return_wfn=return_wfn, psi4_scr=psi4_scr,
filename=filename, verbose=verbose)
else:
success = False
print("success: ", success)


return success

Expand Down Expand Up @@ -607,7 +640,7 @@ def rescue_with_check(self, functional='b3lyp', wfnpath='b3lyp/wfn.180.npy', alp
if "==> Iterations <==" not in txt:
resubed = True
#Resubmit calculation using the specified wavefunction
if resubed and os.path.isfile(wfn):
if resubed and os.path.isfile(wfnpath):
print("previously errored out. resubmitting...")
success = self.run_general_hfx(functional, hfx=alpha, wfn=wfnpath)
print("success: ", success)
Expand Down
67 changes: 60 additions & 7 deletions jobmanager/psi4_utils/run_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ def loop_hfx_jobs(self, rundir='$SGE_O_WORKDIR'):
For each specified functional, calculates the value at each of the HFX percentages specified.
Starts each calculation from the converged wavefunction of the previous calculation.
Runs multiple sweeps: first a naive sweep where a 20% HFX result is done from the B3LYP wfn,
and then the program steps down and up from that calculation to the specified values.
Then, attempts several schemes to address points that did not converge:
(1) Start from the 0% result and step up, which allows different initial guesses for HFX<20 and retries calculations above.
(2) Start from the 100% result and step down, which allows different initial guesses for HFX>100 and retries calculations below.
Parameters:
rundir: str
Directory where the calculations are run from.
Expand All @@ -179,8 +185,9 @@ def loop_hfx_jobs(self, rundir='$SGE_O_WORKDIR'):
success_count += success

#Get and sort the HFX levels desired in the calculation
#Unsorted to allow different orders if desired
hfx_amounts = psi4_config['hfx_levels']
hfx_amounts = sorted(psi4_config['hfx_levels'])
below_20 = [alpha for alpha in hfx_amounts if alpha < 20][::-1] #reversed since you want to step down from 20
above_20 = [alpha for alpha in hfx_amounts if alpha > 20]

#for all other functionals
for ii, base_functional in enumerate(psi4_config["functional"]):
Expand All @@ -189,14 +196,60 @@ def loop_hfx_jobs(self, rundir='$SGE_O_WORKDIR'):
#psi4_utils to get the right parameters
psi4_config["wfnfile"] = b3lyp_wfn_dir
psi4_utils = Psi4Utils(psi4_config)
base_20_wfn = '' #to store the path of the 20% result

print('Pass 1: Starting from 20 and stepping up/down:')
#converge 20% result
functional = base_functional + '_hfx_20'
success = psi4_utils.run_with_check('run_general', functional, return_wfn=True, verbose=True, retry_scf=True)
if success:
#If success, want the next calculation to be run from the wfn of this calculation
#Otherwise, run it from the last converged calculation
base_20_wfn = functional.replace("(", "l-").replace(")", "-r") + '/wfn.180.npy'
psi4_config["wfnfile"] = base_20_wfn
psi4_utils = Psi4Utils(psi4_config)
print('Wfn updated!')
#Converge calculations below 20%
for jj, alpha in enumerate(below_20):
functional = base_functional + '_hfx_' + str(alpha)
success = psi4_utils.run_with_check('run_general', functional, return_wfn=True, verbose=True, retry_scf=True)
if success:
psi4_config["wfnfile"] = functional.replace("(", "l-").replace(")", "-r") + '/wfn.180.npy'
psi4_utils = Psi4Utils(psi4_config)
print('Wfn updated!')
#Get 20% wfn for other half of checks (if 20% did not converge, use B3LYP result)
psi4_config["wfnfile"] = base_20_wfn if base_20_wfn != '' else b3lyp_wfn_dir
psi4_utils = Psi4Utils(psi4_config)
#Converge calculations above 20%
for jj, alpha in enumerate(above_20):
functional = base_functional + '_hfx_' + str(alpha)
success = psi4_utils.run_with_check('run_general', functional, return_wfn=True, verbose=True, retry_scf=True)
if success:
psi4_config["wfnfile"] = functional.replace("(", "l-").replace(")", "-r") + '/wfn.180.npy'
psi4_utils = Psi4Utils(psi4_config)
print('Wfn updated!')

print('Pass 2: Starting from 0 and stepping up:')
#Start from the B3LYP wavefunction if not converged already
psi4_config["wfnfile"] = b3lyp_wfn_dir
psi4_utils = Psi4Utils(psi4_config)
for jj, alpha in enumerate(hfx_amounts):
#functional you want to run is base functional plus the HFX level
functional = base_functional + '_hfx_' + str(alpha)
success = psi4_utils.run_with_check('run_general', functional)
success_count += success
success = psi4_utils.run_with_check('run_general', functional, return_wfn=True, verbose=True, retry_scf=True)
if success:
psi4_config["wfnfile"] = functional.replace("(", "l-").replace(")", "-r") + '/wfn.180.npy'
psi4_utils = Psi4Utils(psi4_config)
print('Wfn updated!')

print('Pass 3: Starting from 100 and stepping down:')
#Start from the B3LYP wavefunction if not converged already
psi4_config["wfnfile"] = b3lyp_wfn_dir
psi4_utils = Psi4Utils(psi4_config)
for jj, alpha in enumerate(hfx_amounts[::-1]):
functional = base_functional + '_hfx_' + str(alpha)
success = psi4_utils.run_with_check('run_general', functional, return_wfn=True, verbose=True, retry_scf=True)
success_count += success #only include on final pass to get accurate count
if success:
#If success, want the next calculation to be run from the wfn of this calculation
#Otherwise, run it from the last converged calculation
psi4_config["wfnfile"] = functional.replace("(", "l-").replace(")", "-r") + '/wfn.180.npy'
psi4_utils = Psi4Utils(psi4_config)
print('Wfn updated!')
Expand Down

0 comments on commit e33e40b

Please sign in to comment.