def run_gpu_dfcc(name, **kwargs): """Function encoding sequence of PSI module calls for a GPU-accelerated DF-CCSD(T) computation. >>> energy('df-ccsd(t)') """ lowername = name.lower() kwargs = kwargs_lower(kwargs) # stash user options optstash = OptionsState( ['GPU_DFCC','COMPUTE_TRIPLES'], ['GPU_DFCC','DFCC'], ['GPU_DFCC','NAT_ORBS'], ['SCF','DF_INTS_IO'], ['SCF','SCF_TYPE']) psi4.set_local_option('SCF','DF_INTS_IO', 'SAVE') psi4.set_local_option('GPU_DFCC','DFCC', True) # throw an exception for open-shells if (psi4.get_option('SCF','REFERENCE') != 'RHF' ): raise ValidationError("Error: %s requires \"reference rhf\"." % lowername) # override symmetry: molecule = psi4.get_active_molecule() molecule.update_geometry() molecule.reset_point_group('c1') molecule.fix_orientation(1) molecule.update_geometry() # triples? if (lowername == 'gpu-df-ccsd'): psi4.set_local_option('GPU_DFCC','COMPUTE_TRIPLES', False) if (lowername == 'gpu-df-ccsd(t)'): psi4.set_local_option('GPU_DFCC','COMPUTE_TRIPLES', True) #if (lowername == 'fno-df-ccsd'): # psi4.set_local_option('GPU_DFCC','COMPUTE_TRIPLES', False) # psi4.set_local_option('GPU_DFCC','NAT_ORBS', True) #if (lowername == 'fno-df-ccsd(t)'): # psi4.set_local_option('GPU_DFCC','COMPUTE_TRIPLES', True) # psi4.set_local_option('GPU_DFCC','NAT_ORBS', True) # set scf-type to df unless the user wants something else if psi4.has_option_changed('SCF','SCF_TYPE') == False: psi4.set_local_option('SCF','SCF_TYPE', 'DF') if psi4.get_option('GPU_DFCC','DF_BASIS_CC') == '': basis = psi4.get_global_option('BASIS') dfbasis = corresponding_rifit(basis) psi4.set_local_option('GPU_DFCC','DF_BASIS_CC',dfbasis) scf_helper(name,**kwargs) psi4.plugin('gpu_dfcc.so') # restore options optstash.restore() return psi4.get_variable("CURRENT ENERGY")
def scf_set_reference_local(name): """ Figures out the correct SCF reference to set locally """ optstash = p4util.OptionsState( ['SCF', 'DFT_FUNCTIONAL'], ['SCF', 'SCF_TYPE'], ['SCF', 'REFERENCE']) # Alter default algorithm if not psi4.has_option_changed('SCF', 'SCF_TYPE'): psi4.set_local_option('SCF', 'SCF_TYPE', 'DF') if name == 'hf': if psi4.get_option('SCF','REFERENCE') == 'RKS': psi4.set_local_option('SCF','REFERENCE','RHF') elif psi4.get_option('SCF','REFERENCE') == 'UKS': psi4.set_local_option('SCF','REFERENCE','UHF') elif name == 'scf': if psi4.get_option('SCF','REFERENCE') == 'RKS': if (len(psi4.get_option('SCF', 'DFT_FUNCTIONAL')) > 0) or psi4.get_option('SCF', 'DFT_CUSTOM_FUNCTIONAL') is not None: pass else: psi4.set_local_option('SCF','REFERENCE','RHF') elif psi4.get_option('SCF','REFERENCE') == 'UKS': if (len(psi4.get_option('SCF', 'DFT_FUNCTIONAL')) > 0) or psi4.get_option('SCF', 'DFT_CUSTOM_FUNCTIONAL') is not None: pass else: psi4.set_local_option('SCF','REFERENCE','UHF') return optstash
def scf_set_reference_local(name): """ Figures out the correct SCF reference to set locally """ optstash = p4util.OptionsState(["SCF", "DFT_FUNCTIONAL"], ["SCF", "SCF_TYPE"], ["SCF", "REFERENCE"]) # Alter default algorithm if not psi4.has_option_changed("SCF", "SCF_TYPE"): psi4.set_local_option("SCF", "SCF_TYPE", "DF") if name == "hf": if psi4.get_option("SCF", "REFERENCE") == "RKS": psi4.set_local_option("SCF", "REFERENCE", "RHF") elif psi4.get_option("SCF", "REFERENCE") == "UKS": psi4.set_local_option("SCF", "REFERENCE", "UHF") elif name == "scf": if psi4.get_option("SCF", "REFERENCE") == "RKS": if (len(psi4.get_option("SCF", "DFT_FUNCTIONAL")) > 0) or psi4.get_option( "SCF", "DFT_CUSTOM_FUNCTIONAL" ) is not None: pass else: psi4.set_local_option("SCF", "REFERENCE", "RHF") elif psi4.get_option("SCF", "REFERENCE") == "UKS": if (len(psi4.get_option("SCF", "DFT_FUNCTIONAL")) > 0) or psi4.get_option( "SCF", "DFT_CUSTOM_FUNCTIONAL" ) is not None: pass else: psi4.set_local_option("SCF", "REFERENCE", "UHF") return optstash
def scf_set_reference_local(name): """ Figures out the correct SCF reference to set locally """ optstash = p4util.OptionsState(['SCF', 'DFT_FUNCTIONAL'], ['SCF', 'SCF_TYPE'], ['SCF', 'REFERENCE']) # Alter default algorithm if not psi4.has_option_changed('SCF', 'SCF_TYPE'): psi4.set_local_option('SCF', 'SCF_TYPE', 'DF') if name == 'hf': if psi4.get_option('SCF', 'REFERENCE') == 'RKS': psi4.set_local_option('SCF', 'REFERENCE', 'RHF') elif psi4.get_option('SCF', 'REFERENCE') == 'UKS': psi4.set_local_option('SCF', 'REFERENCE', 'UHF') elif name == 'scf': if psi4.get_option('SCF', 'REFERENCE') == 'RKS': if (len(psi4.get_option( 'SCF', 'DFT_FUNCTIONAL')) > 0) or psi4.get_option( 'SCF', 'DFT_CUSTOM_FUNCTIONAL') is not None: pass else: psi4.set_local_option('SCF', 'REFERENCE', 'RHF') elif psi4.get_option('SCF', 'REFERENCE') == 'UKS': if (len(psi4.get_option( 'SCF', 'DFT_FUNCTIONAL')) > 0) or psi4.get_option( 'SCF', 'DFT_CUSTOM_FUNCTIONAL') is not None: pass else: psi4.set_local_option('SCF', 'REFERENCE', 'UHF') return optstash
def run_plugin_mp2(name, **kwargs): r"""Function encoding sequence of PSI module and plugin calls so that mollerplesset2 can be called via :py:func:`~driver.energy`. >>> energy('mollerplesset2') """ lowername = name.lower() kwargs = p4util.kwargs_lower(kwargs) # Your plugin's psi4 run sequence goes here psi4.set_local_option('MOLLERPLESSET2', 'PRINT', 1) scf_wfn = scf_helper(lowername) # Need to semicanonicalize the ROHF orbitals if psi4.get_global_option('REFERENCE') == 'ROHF': scf_wfn.semicanonicalize() # Ensure IWL files have been written when not using DF/CD proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), scf_wfn) #psi4.set_legacy_wavefunction(scf_wfn) returnvalue = psi4.plugin('mollerplesset2.so', scf_wfn) return returnvalue
def run_v2rdm_casscf(name, **kwargs): r"""Function encoding sequence of PSI module and plugin calls so that v2rdm_casscf can be called via :py:func:`~driver.energy`. For post-scf plugins. >>> energy('v2rdm_casscf') """ lowername = name.lower() kwargs = p4util.kwargs_lower(kwargs) optstash = p4util.OptionsState(['SCF', 'DF_INTS_IO']) psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE') # Your plugin's psi4 run sequence goes here scf_wfn = scf_helper(name, **kwargs) # if restarting from a checkpoint file, this file # needs to be in scratch with the correct name filename = psi4.get_option("V2RDM_CASSCF", "RESTART_FROM_CHECKPOINT_FILE") # todo PSIF_V2RDM_CHECKPOINT should be definied in psifiles.h if (filename != ""): molname = psi4.wavefunction().molecule().name() p4util.copy_file_to_scratch(filename, 'psi', molname, 269, False) returnvalue = psi4.plugin('v2rdm_casscf.so', scf_wfn) #psi4.set_variable('CURRENT ENERGY', returnvalue) return psi4.get_variable('CURRENT ENERGY')
def run_v2rdm_casscf(name, **kwargs): r"""Function encoding sequence of PSI module and plugin calls so that v2rdm_casscf can be called via :py:func:`~driver.energy`. For post-scf plugins. >>> energy('v2rdm_casscf') """ lowername = name.lower() kwargs = p4util.kwargs_lower(kwargs) optstash = p4util.OptionsState( ['SCF', 'DF_INTS_IO']) psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE') # Your plugin's psi4 run sequence goes here scf_wfn = scf_helper(name, **kwargs) # if restarting from a checkpoint file, this file # needs to be in scratch with the correct name filename = psi4.get_option("V2RDM_CASSCF","RESTART_FROM_CHECKPOINT_FILE") # todo PSIF_V2RDM_CHECKPOINT should be definied in psifiles.h if ( filename != "" ): molname = psi4.wavefunction().molecule().name() p4util.copy_file_to_scratch(filename,'psi',molname,269,False) returnvalue = psi4.plugin('v2rdm_casscf.so',scf_wfn) #psi4.set_variable('CURRENT ENERGY', returnvalue) return psi4.get_variable('CURRENT ENERGY')
def dft_set_reference_local(name): """ Figures out the correct DFT reference to set locally """ optstash = p4util.OptionsState( ['SCF', 'DFT_FUNCTIONAL'], ['SCF', 'REFERENCE'], ['SCF', 'SCF_TYPE'], ['DF_BASIS_MP2'], ['DFMP2', 'MP2_OS_SCALE'], ['DFMP2', 'MP2_SS_SCALE']) # Alter default algorithm if not psi4.has_option_changed('SCF', 'SCF_TYPE'): psi4.set_local_option('SCF', 'SCF_TYPE', 'DF') psi4.set_local_option('SCF', 'DFT_FUNCTIONAL', name) user_ref = psi4.get_option('SCF', 'REFERENCE') if (user_ref == 'RHF'): psi4.set_local_option('SCF', 'REFERENCE', 'RKS') elif (user_ref == 'UHF'): psi4.set_local_option('SCF', 'REFERENCE', 'UKS') elif (user_ref == 'ROHF'): raise ValidationError('ROHF reference for DFT is not available.') elif (user_ref == 'CUHF'): raise ValidationError('CUHF reference for DFT is not available.') return optstash
def dft_set_reference_local(name): """ Figures out the correct DFT reference to set locally """ optstash = p4util.OptionsState(['SCF', 'DFT_FUNCTIONAL'], ['SCF', 'REFERENCE'], ['SCF', 'SCF_TYPE'], ['DF_BASIS_MP2'], ['DFMP2', 'MP2_OS_SCALE'], ['DFMP2', 'MP2_SS_SCALE']) # Alter default algorithm if not psi4.has_option_changed('SCF', 'SCF_TYPE'): psi4.set_local_option('SCF', 'SCF_TYPE', 'DF') psi4.set_local_option('SCF', 'DFT_FUNCTIONAL', name) user_ref = psi4.get_option('SCF', 'REFERENCE') if (user_ref == 'RHF'): psi4.set_local_option('SCF', 'REFERENCE', 'RKS') elif (user_ref == 'UHF'): psi4.set_local_option('SCF', 'REFERENCE', 'UKS') elif (user_ref == 'ROHF'): raise ValidationError('ROHF reference for DFT is not available.') elif (user_ref == 'CUHF'): raise ValidationError('CUHF reference for DFT is not available.') return optstash
def synthesize_opt_rot(db, opt_rot_list): length = [] velocity = [] for job in db['job_status']: with open('{}/output.dat'.format(job)) as outfile: mygauge = psi4.get_option('CCRESPONSE', 'GAUGE') if mygauge == 'LENGTH': length.append( grab_psi4_matrix(outfile, 'Optical Rotation Tensor (Length Gauge)', 3)) elif mygauge == 'VELOCITY': velocity.append( grab_psi4_matrix( outfile, 'Optical Rotation Tensor (Modified Velocity Gauge)', 3)) elif mygauge == 'BOTH': length.append( grab_psi4_matrix(outfile, 'Optical Rotation Tensor (Length Gauge)', 3)) velocity.append( grab_psi4_matrix( outfile, 'Optical Rotation Tensor (Modified Velocity Gauge)', 3)) else: print( "There is no optical rotation tensor - something is wrong." ) if length: opt_rot_list.append(length) if velocity: opt_rot_list.append(velocity)
def make_gauge_list(gauge_list): mygauge = psi4.get_option('CCRESPONSE', 'GAUGE') if mygauge == 'LENGTH': gauge_list.append('Length Gauge Results') elif mygauge == 'VELOCITY': gauge_list.append('Modified Velocity Gauge Results') elif mygauge == 'BOTH': gauge_list.append('Length Gauge Results') gauge_list.append('Modified Velocity Gauge Results') else: print("There is no optical rotation tensor - something is wrong.") ################################ ### ### ### DATABASE STRUCTURE ### ### ### ################################ #Dict of dicts #inputs_generated (boolean) #job_status: job_list: status #jobs_complete #roa_computed # #data ? #data: dipole_polarizability # : optical_rotation # : dipole_quadrupole_polarizability
def dft_set_reference_local(name): """ Figures out the correct DFT reference to set locally """ optstash = p4util.OptionsState( ["SCF", "DFT_FUNCTIONAL"], ["SCF", "REFERENCE"], ["SCF", "SCF_TYPE"], ["DF_BASIS_MP2"], ["DFMP2", "MP2_OS_SCALE"], ["DFMP2", "MP2_SS_SCALE"], ) # Alter default algorithm if not psi4.has_option_changed("SCF", "SCF_TYPE"): psi4.set_local_option("SCF", "SCF_TYPE", "DF") psi4.set_local_option("SCF", "DFT_FUNCTIONAL", name) user_ref = psi4.get_option("SCF", "REFERENCE") if user_ref == "RHF": psi4.set_local_option("SCF", "REFERENCE", "RKS") elif user_ref == "UHF": psi4.set_local_option("SCF", "REFERENCE", "UKS") elif user_ref == "ROHF": raise ValidationError("ROHF reference for DFT is not available.") elif user_ref == "CUHF": raise ValidationError("CUHF reference for DFT is not available.") return optstash
def check_non_symmetric_jk_density(name): """ Ensure non-symmetric density matrices are supported for the selected JK routine. """ scf_type = psi4.get_option('SCF', 'SCF_TYPE') supp_jk_type = ['DF', 'CD', 'PK', 'DIRECT', 'OUT_OF_CORE'] supp_string = ', '.join(supp_jk_type[:-1]) + ', or ' + supp_jk_type[-1] + '.' if scf_type not in supp_jk_type: raise ValidationError("Method %s: Requires support for non-symmetric density matrices.\n" " Please set SCF_TYPE to %s" % (name, supp_string))
def make_gauge_list(gauge_list): mygauge = psi4.get_option('CCRESPONSE', 'GAUGE') if mygauge == 'LENGTH': gauge_list.append('Length Gauge Results') elif mygauge == 'VELOCITY': gauge_list.append('Modified Velocity Gauge Results') elif mygauge == 'BOTH': gauge_list.append('Length Gauge Results') gauge_list.append('Modified Velocity Gauge Results') else: print("There is no optical rotation tensor - something is wrong.")
def run_v2rdm_casscf(name, **kwargs): r"""Function encoding sequence of PSI module and plugin calls so that v2rdm_casscf can be called via :py:func:`~driver.energy`. For post-scf plugins. >>> energy('v2rdm_casscf') """ lowername = name.lower() kwargs = p4util.kwargs_lower(kwargs) optstash = p4util.OptionsState( ['SCF', 'DF_INTS_IO']) psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE') # Your plugin's psi4 run sequence goes here ref_wfn = kwargs.get('ref_wfn', None) if ref_wfn is None: ref_wfn = driver.scf_helper(name, **kwargs) # if restarting from a checkpoint file, this file # needs to be in scratch with the correct name filename = psi4.get_option("V2RDM_CASSCF","RESTART_FROM_CHECKPOINT_FILE") # todo PSIF_V2RDM_CHECKPOINT should be definied in psifiles.h if ( filename != "" ): molname = ref_wfn.molecule().name() p4util.copy_file_to_scratch(filename,'psi',molname,269,False) # Ensure IWL files have been written when not using DF/CD scf_type = psi4.get_option('SCF', 'SCF_TYPE') if ( scf_type == 'PK' or scf_type == 'DIRECT' ): proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn) returnvalue = psi4.plugin('v2rdm_casscf.so', ref_wfn) #psi4.set_variable('CURRENT ENERGY', returnvalue) #return psi4.get_variable('CURRENT ENERGY') return returnvalue
def check_non_symmetric_jk_density(name): """ Ensure non-symmetric density matrices are supported for the selected JK routine. """ scf_type = psi4.get_option("SCF", "SCF_TYPE") supp_jk_type = ["DF", "CD", "PK", "DIRECT", "OUT_OF_CORE"] supp_string = ", ".join(supp_jk_type[:-1]) + ", or " + supp_jk_type[-1] + "." if scf_type not in supp_jk_type: raise ValidationError( "Method %s: Requires support for non-symmetric density matrices.\n" " Please set SCF_TYPE to %s" % (name, supp_string) )
def fitScf(self): """Function to run scf and fit a system of diffuse charges to resulting density. """ basisChanged = psi4.has_option_changed("BASIS") ribasisChanged = psi4.has_option_changed("DF_BASIS_SCF") scftypeChanged = psi4.has_option_changed("SCF_TYPE") basis = psi4.get_option("BASIS") ribasis = psi4.get_option("DF_BASIS_SCF") scftype = psi4.get_option("SCF_TYPE") psi4.print_out(" => Diffuse SCF (Determines Da) <=\n\n") activate(self.molecule) psi4.set_global_option("BASIS", self.basisname) psi4.set_global_option("DF_BASIS_SCF", self.ribasisname) psi4.set_global_option("SCF_TYPE", "DF") energy('scf') psi4.print_out("\n") self.fitGeneral() psi4.clean() psi4.set_global_option("BASIS", basis) psi4.set_global_option("DF_BASIS_SCF", ribasis) psi4.set_global_option("SCF_TYPE", scftype) if not basisChanged: psi4.revoke_option_changed("BASIS") if not ribasisChanged: psi4.revoke_option_changed("DF_BASIS_SCF") if not scftypeChanged: psi4.revoke_option_changed("SCF_TYPE")
def synthesize_opt_rot(db, opt_rot_list): length = [] velocity = [] for job in db['job_status']: with open('{}/output.dat'.format(job)) as outfile: mygauge = psi4.get_option('CCRESPONSE', 'GAUGE') if mygauge == 'LENGTH': length.append(grab_psi4_matrix(outfile, 'Optical Rotation Tensor (Length Gauge)', 3)) elif mygauge == 'VELOCITY': velocity.append(grab_psi4_matrix(outfile, 'Optical Rotation Tensor (Modified Velocity Gauge)', 3)) elif mygauge == 'BOTH': length.append(grab_psi4_matrix(outfile, 'Optical Rotation Tensor (Length Gauge)', 3)) velocity.append(grab_psi4_matrix(outfile, 'Optical Rotation Tensor (Modified Velocity Gauge)', 3)) else: print("There is no optical rotation tensor - something is wrong.") if length: opt_rot_list.append(length) if velocity: opt_rot_list.append(velocity)
def __init__(self, option, module=None): self.option = option.upper() if module: self.module = module.upper() else: self.module = None self.value_global = psi4.get_global_option(option) self.haschanged_global = psi4.has_global_option_changed(option) if self.module: self.value_local = psi4.get_local_option(self.module, option) self.haschanged_local = psi4.has_local_option_changed(self.module, option) self.value_used = psi4.get_option(self.module, option) self.haschanged_used = psi4.has_option_changed(self.module, option) else: self.value_local = None self.haschanged_local = None self.value_used = None self.haschanged_used = None
def run_ccambit(name, **kwargs): r"""Function encoding sequence of PSI module and plugin calls so that ccambit can be called via :py:func:`~driver.energy`. For post-scf plugins. >>> energy('ccambit') """ lowername = name.lower() kwargs = p4util.kwargs_lower(kwargs) # Your plugin's psi4 run sequence goes here if ('wfn' in kwargs): if (kwargs['wfn'] == 'ccsd'): psi4.set_global_option('WFN', 'CCSD') elif (kwargs['wfn'] == 'ccsd(t)'): psi4.set_global_option('WFN', 'CCSD_T') scf_wfn = kwargs.get('ref_wfn', None) if scf_wfn is None: scf_wfn = driver.scf_helper(name, **kwargs) check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), scf_wfn) return psi4.plugin('ccambit.so', scf_wfn)
def compute_energy(self): # copy over object attributes to avoid having to write "self." a lot h, g, D, X, Vnu, nocc = self.h, self.g, self.D, self.X, self.Vnu, self.nocc self.E = 0.0 for i in range(psi4.get_option('SCF', 'MAXITER')): v = np.einsum('mrns,sr', g, D) # e- field v_mu,nu = sum_rh,si <mu rh||mu si> D_si,rh f = h + v # build fock matrix tf = X*f*X # transform to orthogonalized AO basis e, tC = la.eigh(tf) # diagonalize C = X * tC # backtransform oC = C[:,:nocc] # get occupied MO coefficients D = oC * oC.T # build density matrix E = np.trace((h + v/2)*D) + Vnu # compute energy by tracing with density matrix dE = E - self.E # get change in energy self.E, self.C, self.e = E, C, e # save these for later print('UHF {:-3d}{:20.15f}{:20.15f}'.format(i, E, dE)) # print progress if(np.fabs(dE) < psi4.get_global_option('E_CONVERGENCE')): break # quit if converged return self.E
def get_maxiter(): # get max # of iterations return psi4.get_option('SCF','MAXITER')
def run_roa(name, **kwargs): # Get list of omega values -> Make sure we only have one wavelength # Catch this now before any real work gets done omega = psi4.get_option('CCRESPONSE','OMEGA') if len(omega) > 2: raise Exception('ROA scattering can only be performed for one wavelength.') else: pass psi4.print_out('Running ROA computation. Subdirectories for each ' 'required displaced geometry have been created.\n\n') ### Initialize database db = shelve.open('database',writeback=True) if 'inputs_generated' not in db: initialize_database(db) ### Generate input files if not db['inputs_generated']: generate_inputs(name, db) db['inputs_generated'] = True ### If 'serial' calculation, proceed with subdir execution ### Check job status if db['inputs_generated'] and not db['jobs_complete']: print('Checking status') roa_stat(db) for job,status in db['job_status'].items(): print("{} --> {}".format(job,status)) ### Compute ROA Scattering if db['jobs_complete']: # SAVE this for when multiple wavelengths works # # Get list of omega values # omega = psi4.get_option('CCRESPONSE','OMEGA') # if len(omega) > 1: # units = copy.copy(omega[-1]) # omega.pop() # else: # units = 'atomic' # wavelength = copy.copy(omega[0]) # # Set up units for scatter.cc # if units == 'NM': # wavelength = (psi_c * psi_h * 1*(10**-9))/(wavelength * psi_hartree2J) # if units == 'HZ': # wavelength = wavelength * psi_h / psi_hartree2J # if units == 'EV': # wavelength = wavelength / psi_hartree2ev # if units == 'atomic': # pass # Initialize tensor lists dip_polar_list = [] opt_rot_list = [] dip_quad_polar_list = [] gauge_list = [] make_gauge_list(gauge_list) # Gather data synthesize_dipole_polar(db,dip_polar_list) synthesize_opt_rot(db,opt_rot_list) synthesize_dip_quad_polar(db,dip_quad_polar_list) # Compute Scattering # Run new function (src/bin/ccresponse/scatter.cc) psi4.print_out('Running scatter function') step = psi4.get_local_option('FINDIF','DISP_SIZE') for gauge in opt_rot_list: g_idx = opt_rot_list.index(gauge) # print('\n\n----------------------------------------------------------------------') # print('\t%%%%%%%%%% {} %%%%%%%%%%'.format(gauge_list[g_idx])) # print('----------------------------------------------------------------------\n\n') psi4.print_out('\n\n----------------------------------------------------------------------\n') psi4.print_out('\t%%%%%%%%%% {} %%%%%%%%%%\n'.format(gauge_list[g_idx])) psi4.print_out('----------------------------------------------------------------------\n\n') print('roa.py:85 I am not being passed a molecule, grabbing from global :(') psi4.scatter(psi4.get_active_molecule(), step, dip_polar_list, gauge, dip_quad_polar_list) db.close()
def _set_convergence_criterion(ptype, method_name, scf_Ec, pscf_Ec, scf_Dc, pscf_Dc, gen_Ec, verbose=1): r""" This function will set local SCF and global energy convergence criterion to the defaults listed at: http://www.psicode.org/psi4manual/master/scf.html#convergence-and- algorithm-defaults. SCF will be converged more tightly if a post-SCF method is select (pscf_Ec, and pscf_Dc) else the looser (scf_Ec, and scf_Dc convergence criterion will be used). ptype - Procedure type (energy, gradient, etc). Nearly always test on procedures['energy'] since that's guaranteed to exist for a method. method_name - Name of the method scf_Ec - E convergence criterion for scf target method pscf_Ec - E convergence criterion for scf of post-scf target method scf_Dc - D convergence criterion for scf target method pscf_Dc - D convergence criterion for scf of post-scf target method gen_Ec - E convergence criterion for post-scf target method """ optstash = p4util.OptionsState( ['SCF', 'E_CONVERGENCE'], ['SCF', 'D_CONVERGENCE'], ['E_CONVERGENCE']) # Kind of want to move this out of here _method_exists(ptype, method_name) if verbose >= 2: print(' Setting convergence', end=' ') # Set method-dependent scf convergence criteria, check against energy routines if not psi4.has_option_changed('SCF', 'E_CONVERGENCE'): if procedures['energy'][method_name] in [proc.run_scf, proc.run_dft]: psi4.set_local_option('SCF', 'E_CONVERGENCE', scf_Ec) if verbose >= 2: print(scf_Ec, end=' ') else: psi4.set_local_option('SCF', 'E_CONVERGENCE', pscf_Ec) if verbose >= 2: print(pscf_Ec, end=' ') else: if verbose >= 2: print('CUSTOM', psi4.get_option('SCF', 'E_CONVERGENCE'), end=' ') if not psi4.has_option_changed('SCF', 'D_CONVERGENCE'): if procedures['energy'][method_name] in [proc.run_scf, proc.run_dft]: psi4.set_local_option('SCF', 'D_CONVERGENCE', scf_Dc) if verbose >= 2: print(scf_Dc, end=' ') else: psi4.set_local_option('SCF', 'D_CONVERGENCE', pscf_Dc) if verbose >= 2: print(pscf_Dc, end=' ') else: if verbose >= 2: print('CUSTOM', psi4.get_option('SCF', 'D_CONVERGENCE'), end=' ') # Set post-scf convergence criteria (global will cover all correlated modules) if not psi4.has_global_option_changed('E_CONVERGENCE'): if procedures['energy'][method_name] not in [proc.run_scf, proc.run_dft]: psi4.set_global_option('E_CONVERGENCE', gen_Ec) if verbose >= 2: print(gen_Ec, end=' ') else: if procedures['energy'][method_name] not in [proc.run_scf, proc.run_dft]: if verbose >= 2: print('CUSTOM', psi4.get_global_option('E_CONVERGENCE'), end=' ') if verbose >= 2: print('') return optstash
def run_dftd3(self, func=None, dashlvl=None, dashparam=None, dertype=None, verbose=False): """Function to call Grimme's dftd3 program (http://toc.uni-muenster.de/DFTD3/) to compute the -D correction of level *dashlvl* using parameters for the functional *func*. The dictionary *dashparam* can be used to supply a full set of dispersion parameters in the absense of *func* or to supply individual overrides in the presence of *func*. Returns energy if *dertype* is 0, gradient if *dertype* is 1, else tuple of energy and gradient if *dertype* unspecified. The dftd3 executable must be independently compiled and found in :envvar:`PATH` or :envvar:`PSIPATH`. *self* may be either a qcdb.Molecule (sensibly) or a psi4.Molecule (works b/c psi4.Molecule has been extended by this method py-side and only public interface fns used) or a string that can be instantiated into a qcdb.Molecule. """ # Create (if necessary) and update qcdb.Molecule if isinstance(self, Molecule): # called on a qcdb.Molecule pass elif isinstance(self, psi4.Molecule): # called on a python export of a psi4.Molecule (py-side through Psi4's driver) self.create_psi4_string_from_molecule() elif isinstance(self, basestring): # called on a string representation of a psi4.Molecule (c-side through psi4.Dispersion) self = Molecule(self) else: raise ValidationError("""Argument mol must be psi4string or qcdb.Molecule""") self.update_geometry() # Validate arguments dashlvl = dashlvl.lower() dashlvl = dash_alias['-' + dashlvl][1:] if ('-' + dashlvl) in dash_alias.keys() else dashlvl if dashlvl not in dashcoeff.keys(): raise ValidationError("""-D correction level %s is not available. Choose among %s.""" % (dashlvl, dashcoeff.keys())) if dertype is None: dertype = -1 elif der0th.match(str(dertype)): dertype = 0 elif der1st.match(str(dertype)): dertype = 1 elif der2nd.match(str(dertype)): raise ValidationError('Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) else: raise ValidationError('Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) if func is None: if dashparam is None: # defunct case raise ValidationError("""Parameters for -D correction missing. Provide a func or a dashparam kwarg.""") else: # case where all param read from dashparam dict (which must have all correct keys) func = 'custom' dashcoeff[dashlvl][func] = {} dashparam = dict((k.lower(), v) for k, v in dashparam.iteritems()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] else: raise ValidationError("""Parameter %s is missing from dashparam dict %s.""" % (key, dashparam)) else: func = func.lower() if func not in dashcoeff[dashlvl].keys(): raise ValidationError("""Functional %s is not available for -D level %s.""" % (func, dashlvl)) if dashparam is None: # (normal) case where all param taken from dashcoeff above pass else: # case where items in dashparam dict can override param taken from dashcoeff above dashparam = dict((k.lower(), v) for k, v in dashparam.iteritems()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] # Move ~/.dftd3par.<hostname> out of the way so it won't interfere defaultfile = os.path.expanduser('~') + '/.dftd3par.' + socket.gethostname() defmoved = False if os.path.isfile(defaultfile): os.rename(defaultfile, defaultfile + '_hide') defmoved = True # Find environment by merging PSIPATH and PATH environment variables lenv = { 'PATH': ':'.join([os.path.abspath(x) for x in os.environ.get('PSIPATH', '').split(':') if x != '']) + \ ':' + os.environ.get('PATH'), 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH') } # Find out if running from Psi4 for scratch details and such try: psi4.version() except NameError: isP4regime = False else: isP4regime = True # Setup unique scratch directory and move in current_directory = os.getcwd() if isP4regime: psioh = psi4.IOManager.shared_object() psio = psi4.IO.shared_object() os.chdir(psioh.get_default_path()) dftd3_tmpdir = 'psi.' + str(os.getpid()) + '.' + psio.get_default_namespace() + \ '.dftd3.' + str(random.randint(0, 99999)) else: dftd3_tmpdir = os.environ['HOME'] + os.sep + 'dftd3_' + str(random.randint(0, 99999)) if os.path.exists(dftd3_tmpdir) is False: os.mkdir(dftd3_tmpdir) os.chdir(dftd3_tmpdir) # Write dftd3_parameters file that governs dispersion calc paramcontents = dash_server(func, dashlvl, 'dftd3') paramfile1 = 'dftd3_parameters' # older patched name with open(paramfile1, 'w') as handle: handle.write(paramcontents) paramfile2 = '.dftd3par.local' # new mainline name with open(paramfile2, 'w') as handle: handle.write(paramcontents) # Write dftd3_geometry file that supplies geometry to dispersion calc numAtoms = self.natom() geom = self.save_string_xyz() reals = [] for line in geom.splitlines(): lline = line.split() if len(lline) != 4: continue if lline[0] == 'Gh': numAtoms -= 1 else: reals.append(line) geomtext = str(numAtoms) + '\n\n' for line in reals: geomtext += line.strip() + '\n' geomfile = './dftd3_geometry.xyz' with open(geomfile, 'w') as handle: handle.write(geomtext) # TODO somehow the variations on save_string_xyz and # whether natom and chgmult does or doesn't get written # have gotten all tangled. I fear this doesn't work # the same btwn libmints and qcdb or for ghosts # Call dftd3 program command = ['dftd3', geomfile] if dertype != 0: command.append('-grad') try: dashout = subprocess.Popen(command, stdout=subprocess.PIPE, env=lenv) except OSError as e: raise ValidationError('Program dftd3 not found in path. %s' % e) out, err = dashout.communicate() # Parse output (could go further and break into E6, E8, E10 and Cn coeff) success = False for line in out.splitlines(): if re.match(' Edisp /kcal,au', line): sline = line.split() dashd = float(sline[3]) if re.match(' normal termination of dftd3', line): success = True if not success: os.chdir(current_directory) raise Dftd3Error("""Unsuccessful run. Possibly -D variant not available in dftd3 version.""") # Parse grad output if dertype != 0: derivfile = './dftd3_gradient' dfile = open(derivfile, 'r') dashdderiv = [] for line in geom.splitlines(): lline = line.split() if len(lline) != 4: continue if lline[0] == 'Gh': dashdderiv.append([0.0, 0.0, 0.0]) else: dashdderiv.append([float(x.replace('D', 'E')) for x in dfile.readline().split()]) dfile.close() if len(dashdderiv) != self.natom(): raise ValidationError('Program dftd3 gradient file has %d atoms- %d expected.' % \ (len(dashdderiv), self.natom())) # Prepare results for Psi4 if isP4regime and dertype != 0: psi4.set_variable('DISPERSION CORRECTION ENERGY', dashd) psi_dashdderiv = psi4.Matrix(self.natom(), 3) psi_dashdderiv.set(dashdderiv) # Print program output to file if verbose if isP4regime: verbose = True if psi4.get_option('SCF', 'PRINT') >= 3 else False if verbose: text = '\n ==> DFTD3 Output <==\n' text += out if dertype != 0: with open(derivfile, 'r') as handle: text += handle.read().replace('D', 'E') text += '\n' if isP4regime: psi4.print_out(text) else: print(text) # Clean up files and remove scratch directory os.unlink(paramfile1) os.unlink(paramfile2) os.unlink(geomfile) if dertype != 0: os.unlink(derivfile) if defmoved is True: os.rename(defaultfile + '_hide', defaultfile) os.chdir('..') try: shutil.rmtree(dftd3_tmpdir) except OSError as e: ValidationError('Unable to remove dftd3 temporary directory %s' % e) os.chdir(current_directory) # return -D & d(-D)/dx if dertype == -1: return dashd, dashdderiv elif dertype == 0: return dashd elif dertype == 1: return psi_dashdderiv
def run_gaussian_2(name, **kwargs): # throw an exception for open-shells if (psi4.get_option('SCF', 'REFERENCE') != 'RHF'): raise ValidationError("""g2 computations require "reference rhf".""") # stash user options: optstash = p4util.OptionsState(['FNOCC', 'COMPUTE_TRIPLES'], ['FNOCC', 'COMPUTE_MP4_TRIPLES'], ['FREEZE_CORE'], ['MP2_TYPE'], ['SCF', 'SCF_TYPE']) # override default scf_type psi4.set_local_option('SCF', 'SCF_TYPE', 'PK') # optimize geometry at scf level psi4.clean() psi4.set_global_option('BASIS', "6-31G(D)") driver.optimize('scf') psi4.clean() # scf frequencies for zpe # NOTE This line should not be needed, but without it there's a seg fault scf_e, ref = driver.frequency('scf', return_wfn=True) # thermodynamic properties du = psi4.get_variable('INTERNAL ENERGY CORRECTION') dh = psi4.get_variable('ENTHALPY CORRECTION') dg = psi4.get_variable('GIBBS FREE ENERGY CORRECTION') freqs = ref.frequencies() nfreq = freqs.dim(0) freqsum = 0.0 for i in range(0, nfreq): freqsum += freqs.get(i) zpe = freqsum / p4const.psi_hartree2wavenumbers * 0.8929 * 0.5 psi4.clean() # optimize geometry at mp2 (no frozen core) level # note: freeze_core isn't an option in MP2 psi4.set_global_option('FREEZE_CORE', "FALSE") psi4.set_global_option('MP2_TYPE', 'CONV') driver.optimize('mp2') psi4.clean() # qcisd(t) psi4.set_local_option('FNOCC', 'COMPUTE_MP4_TRIPLES', "TRUE") psi4.set_global_option('FREEZE_CORE', "TRUE") psi4.set_global_option('BASIS', "6-311G(D_P)") ref = driver.proc.run_fnocc('qcisd(t)', return_wfn=True, **kwargs) # HLC: high-level correction based on number of valence electrons nirrep = ref.nirrep() frzcpi = ref.frzcpi() nfzc = 0 for i in range(0, nirrep): nfzc += frzcpi[i] nalpha = ref.nalpha() - nfzc nbeta = ref.nbeta() - nfzc # hlc of gaussian-2 hlc = -0.00481 * nalpha - 0.00019 * nbeta # hlc of gaussian-1 hlc1 = -0.00614 * nalpha eqci_6311gdp = psi4.get_variable("QCISD(T) TOTAL ENERGY") emp4_6311gd = psi4.get_variable("MP4 TOTAL ENERGY") emp2_6311gd = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() # correction for diffuse functions psi4.set_global_option('BASIS', "6-311+G(D_P)") driver.energy('mp4') emp4_6311pg_dp = psi4.get_variable("MP4 TOTAL ENERGY") emp2_6311pg_dp = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() # correction for polarization functions psi4.set_global_option('BASIS', "6-311G(2DF_P)") driver.energy('mp4') emp4_6311g2dfp = psi4.get_variable("MP4 TOTAL ENERGY") emp2_6311g2dfp = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() # big basis mp2 psi4.set_global_option('BASIS', "6-311+G(3DF_2P)") #run_fnocc('_mp2',**kwargs) driver.energy('mp2') emp2_big = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() eqci = eqci_6311gdp e_delta_g2 = emp2_big + emp2_6311gd - emp2_6311g2dfp - emp2_6311pg_dp e_plus = emp4_6311pg_dp - emp4_6311gd e_2df = emp4_6311g2dfp - emp4_6311gd eg2 = eqci + e_delta_g2 + e_plus + e_2df eg2_mp2_0k = eqci + (emp2_big - emp2_6311gd) + hlc + zpe psi4.print_out('\n') psi4.print_out(' ==> G1/G2 Energy Components <==\n') psi4.print_out('\n') psi4.print_out(' QCISD(T): %20.12lf\n' % eqci) psi4.print_out(' E(Delta): %20.12lf\n' % e_delta_g2) psi4.print_out(' E(2DF): %20.12lf\n' % e_2df) psi4.print_out(' E(+): %20.12lf\n' % e_plus) psi4.print_out(' E(G1 HLC): %20.12lf\n' % hlc1) psi4.print_out(' E(G2 HLC): %20.12lf\n' % hlc) psi4.print_out(' E(ZPE): %20.12lf\n' % zpe) psi4.print_out('\n') psi4.print_out(' ==> 0 Kelvin Results <==\n') psi4.print_out('\n') eg2_0k = eg2 + zpe + hlc psi4.print_out(' G1: %20.12lf\n' % (eqci + e_plus + e_2df + hlc1 + zpe)) psi4.print_out(' G2(MP2): %20.12lf\n' % eg2_mp2_0k) psi4.print_out(' G2: %20.12lf\n' % eg2_0k) psi4.set_variable("G1 TOTAL ENERGY", eqci + e_plus + e_2df + hlc1 + zpe) psi4.set_variable("G2 TOTAL ENERGY", eg2_0k) psi4.set_variable("G2(MP2) TOTAL ENERGY", eg2_mp2_0k) psi4.print_out('\n') T = psi4.get_global_option('T') psi4.print_out(' ==> %3.0lf Kelvin Results <==\n' % T) psi4.print_out('\n') internal_energy = eg2_mp2_0k + du - zpe / 0.8929 enthalpy = eg2_mp2_0k + dh - zpe / 0.8929 gibbs = eg2_mp2_0k + dg - zpe / 0.8929 psi4.print_out(' G2(MP2) energy: %20.12lf\n' % internal_energy) psi4.print_out(' G2(MP2) enthalpy: %20.12lf\n' % enthalpy) psi4.print_out(' G2(MP2) free energy: %20.12lf\n' % gibbs) psi4.print_out('\n') psi4.set_variable("G2(MP2) INTERNAL ENERGY", internal_energy) psi4.set_variable("G2(MP2) ENTHALPY", enthalpy) psi4.set_variable("G2(MP2) FREE ENERGY", gibbs) internal_energy = eg2_0k + du - zpe / 0.8929 enthalpy = eg2_0k + dh - zpe / 0.8929 gibbs = eg2_0k + dg - zpe / 0.8929 psi4.print_out(' G2 energy: %20.12lf\n' % internal_energy) psi4.print_out(' G2 enthalpy: %20.12lf\n' % enthalpy) psi4.print_out(' G2 free energy: %20.12lf\n' % gibbs) psi4.set_variable("CURRENT ENERGY", eg2_0k) psi4.set_variable("G2 INTERNAL ENERGY", internal_energy) psi4.set_variable("G2 ENTHALPY", enthalpy) psi4.set_variable("G2 FREE ENERGY", gibbs) psi4.clean() optstash.restore() # return 0K g2 results return eg2_0k
def run_dftd3(self, func=None, dashlvl=None, dashparam=None, dertype=None): """Function to call Grimme's dftd3 program (http://toc.uni-muenster.de/DFTD3/) to compute the -D correction of level *dashlvl* using parameters for the functional *func*. The dictionary *dashparam* can be used to supply a full set of dispersion parameters in the absense of *func* or to supply individual overrides in the presence of *func*. Returns energy if *dertype* is 0, gradient if *dertype* is 1, else tuple of energy and gradient if *dertype* unspecified. The dftd3 executable must be independently compiled and found in :envvar:`PATH`. """ # Validate arguments if self is None: self = psi4.get_active_molecule() dashlvl = dashlvl.lower() dashlvl = dash_alias['-' + dashlvl][1:] if ('-' + dashlvl) in dash_alias.keys() else dashlvl if dashlvl not in dashcoeff.keys(): raise ValidationError("""-D correction level %s is not available. Choose among %s.""" % (dashlvl, dashcoeff.keys())) if dertype is None: dertype = -1 elif der0th.match(str(dertype)): dertype = 0 elif der1st.match(str(dertype)): dertype = 1 elif der2nd.match(str(dertype)): raise ValidationError('Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) else: raise ValidationError('Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) if func is None: if dashparam is None: # defunct case raise ValidationError("""Parameters for -D correction missing. Provide a func or a dashparam kwarg.""") else: # case where all param read from dashparam dict (which must have all correct keys) func = 'custom' dashcoeff[dashlvl][func] = {} dashparam = dict((k.lower(), v) for k, v in dashparam.items()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] else: raise ValidationError("""Parameter %s is missing from dashparam dict %s.""" % (key, dashparam)) else: func = func.lower() if func not in dashcoeff[dashlvl].keys(): raise ValidationError("""Functional %s is not available for -D level %s.""" % (func, dashlvl)) if dashparam is None: # (normal) case where all param taken from dashcoeff above pass else: # case where items in dashparam dict can override param taken from dashcoeff above dashparam = dict((k.lower(), v) for k, v in dashparam.items()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] # Move ~/.dftd3par.<hostname> out of the way so it won't interfere defaultfile = os.path.expanduser('~') + '/.dftd3par.' + socket.gethostname() defmoved = False if os.path.isfile(defaultfile): os.rename(defaultfile, defaultfile + '_hide') defmoved = True # Setup unique scratch directory and move in current_directory = os.getcwd() psioh = psi4.IOManager.shared_object() psio = psi4.IO.shared_object() os.chdir(psioh.get_default_path()) dftd3_tmpdir = 'psi.' + str(os.getpid()) + '.' + psio.get_default_namespace() + \ '.dftd3.' + str(random.randint(0, 99999)) if os.path.exists(dftd3_tmpdir) is False: os.mkdir(dftd3_tmpdir) os.chdir(dftd3_tmpdir) # Write dftd3_parameters file that governs dispersion calc paramfile = './dftd3_parameters' pfile = open(paramfile, 'w') pfile.write(dash_server(func, dashlvl, 'dftd3')) pfile.close() # Write dftd3_geometry file that supplies geometry to dispersion calc geomfile = './dftd3_geometry.xyz' gfile = open(geomfile, 'w') numAtoms = self.natom() geom = self.save_string_xyz() reals = [] for line in geom.splitlines(): if line.split()[0] == 'Gh': numAtoms -= 1 else: reals.append(line) gfile.write(str(numAtoms)+'\n') for line in reals: gfile.write(line.strip()+'\n') gfile.close() # Call dftd3 program try: dashout = subprocess.Popen(['dftd3', geomfile, '-grad'], stdout=subprocess.PIPE) except OSError: raise ValidationError('Program dftd3 not found in path.') out, err = dashout.communicate() # Parse output (could go further and break into E6, E8, E10 and Cn coeff) success = False for line in out.splitlines(): # communicate in python 3 returns a byte array rather than a string. # Convert to string--only need a simple encoding for comparison. line = line.decode('utf-8') if re.match(' Edisp /kcal,au', line): sline = line.split() dashd = float(sline[3]) if re.match(' normal termination of dftd3', line): success = True if not success: raise ValidationError('Program dftd3 did not complete successfully.') # Parse grad output derivfile = './dftd3_gradient' dfile = open(derivfile, 'r') dashdderiv = [] i = 0 for line in geom.splitlines(): if i == 0: i += 1 else: if line.split()[0] == 'Gh': dashdderiv.append([0.0, 0.0, 0.0]) else: temp = dfile.readline() dashdderiv.append([float(x.replace('D', 'E')) for x in temp.split()]) dfile.close() if len(dashdderiv) != self.natom(): raise ValidationError('Program dftd3 gradient file has %d atoms- %d expected.' % \ (len(dashdderiv), self.natom())) psi_dashdderiv = psi4.Matrix(self.natom(), 3) psi_dashdderiv.set(dashdderiv) # Print program output to file if verbose verbose = psi4.get_option('SCF', 'PRINT') if verbose >= 3: psi4.print_out('\n ==> DFTD3 Output <==\n') psi4.print_out(out) dfile = open(derivfile, 'r') psi4.print_out(dfile.read().replace('D', 'E')) dfile.close() psi4.print_out('\n') # Clean up files and remove scratch directory os.unlink(paramfile) os.unlink(geomfile) os.unlink(derivfile) if defmoved is True: os.rename(defaultfile + '_hide', defaultfile) os.chdir('..') try: shutil.rmtree(dftd3_tmpdir) except OSError as e: ValidationError('Unable to remove dftd3 temporary directory %s' % e, file=sys.stderr) os.chdir(current_directory) # return -D & d(-D)/dx psi4.set_variable('DISPERSION CORRECTION ENERGY', dashd) if dertype == -1: return dashd, dashdderiv elif dertype == 0: return dashd elif dertype == 1: return psi_dashdderiv
def run_roa(name, **kwargs): """ Main driver for managing Raman Optical activity computations with CC response theory. Uses distributed finite differences approach --> 1. Sets up a database to keep track of running/finished/waiting computations. 2. Generates separate input files for displaced geometries. 3. When all displacements are run, collects the necessary information from each displaced computation, and computes final result. """ # Get list of omega values -> Make sure we only have one wavelength # Catch this now before any real work gets done omega = psi4.get_option('CCRESPONSE', 'OMEGA') if len(omega) > 2: raise Exception('ROA scattering can only be performed for one wavelength.') else: pass psi4.print_out( 'Running ROA computation. Subdirectories for each ' 'required displaced geometry have been created.\n\n') dbno = 0 # Initialize database db = shelve.open('database', writeback=True) # Check if final result is in here # ->if we have already computed roa, back up the dict # ->copy it setting this flag to false and continue if ('roa_computed' in db) and ( db['roa_computed'] ): db2 = shelve.open('.database.bak{}'.format(dbno), writeback=True) dbno += 1 for key,value in db.iteritems(): db2[key]=value db2.close() db['roa_computed'] = False else: db['roa_computed'] = False if 'inputs_generated' not in db: findif_response_utils.initialize_database(db,name,"roa", ["roa_tensor"]) # Generate input files if not db['inputs_generated']: findif_response_utils.generate_inputs(db,name) # handled by helper db['inputs_generated'] = True # Check job status if db['inputs_generated'] and not db['jobs_complete']: print('Checking status') findif_response_utils.stat(db) for job, status in db['job_status'].items(): print("{} --> {}".format(job, status)) # Compute ROA Scattering if db['jobs_complete']: mygauge = psi4.get_option('CCRESPONSE', 'GAUGE') consider_gauge = { 'LENGTH': ['Length Gauge'], 'VELOCITY': ['Modified Velocity Gauge'], 'BOTH': ['Length Gauge', 'Modified Velocity Gauge'] } gauge_list = ["{} Results".format(x) for x in consider_gauge[mygauge]] # Gather data dip_polar_list = findif_response_utils.collect_displaced_matrix_data( db, 'Dipole Polarizability', 3) opt_rot_list = [ x for x in ( findif_response_utils.collect_displaced_matrix_data( db, "Optical Rotation Tensor ({})".format(gauge), 3 ) for gauge in consider_gauge[mygauge] ) ] dip_quad_polar_list = findif_response_utils.collect_displaced_matrix_data( db, "Electric-Dipole/Quadrupole Polarizability", 9) # Compute Scattering # Run new function (src/bin/ccresponse/scatter.cc) psi4.print_out('Running scatter function') step = psi4.get_local_option('FINDIF', 'DISP_SIZE') for g_idx, gauge in enumerate(opt_rot_list): print('\n\n----------------------------------------------------------------------') print('\t%%%%%%%%%% {} %%%%%%%%%%'.format(gauge_list[g_idx])) print('----------------------------------------------------------------------\n\n') psi4.print_out('\n\n----------------------------------------------------------------------\n') psi4.print_out('\t%%%%%%%%%% {} %%%%%%%%%%\n'.format(gauge_list[g_idx])) psi4.print_out('----------------------------------------------------------------------\n\n') print('roa.py:85 I am not being passed a molecule, grabbing from global :(') psi4.scatter(psi4.get_active_molecule(), step, dip_polar_list, gauge, dip_quad_polar_list) db['roa_computed'] = True db.close()
def run_roa(name, **kwargs): # Get list of omega values -> Make sure we only have one wavelength # Catch this now before any real work gets done omega = psi4.get_option('CCRESPONSE', 'OMEGA') if len(omega) > 2: raise Exception( 'ROA scattering can only be performed for one wavelength.') else: pass psi4.print_out('Running ROA computation. Subdirectories for each ' 'required displaced geometry have been created.\n\n') ### Initialize database db = shelve.open('database', writeback=True) if 'inputs_generated' not in db: initialize_database(db) ### Generate input files if not db['inputs_generated']: generate_inputs(name, db) db['inputs_generated'] = True ### If 'serial' calculation, proceed with subdir execution ### Check job status if db['inputs_generated'] and not db['jobs_complete']: print('Checking status') roa_stat(db) for job, status in db['job_status'].items(): print("{} --> {}".format(job, status)) ### Compute ROA Scattering if db['jobs_complete']: # SAVE this for when multiple wavelengths works # # Get list of omega values # omega = psi4.get_option('CCRESPONSE','OMEGA') # if len(omega) > 1: # units = copy.copy(omega[-1]) # omega.pop() # else: # units = 'atomic' # wavelength = copy.copy(omega[0]) # # Set up units for scatter.cc # if units == 'NM': # wavelength = (psi_c * psi_h * 1*(10**-9))/(wavelength * psi_hartree2J) # if units == 'HZ': # wavelength = wavelength * psi_h / psi_hartree2J # if units == 'EV': # wavelength = wavelength / psi_hartree2ev # if units == 'atomic': # pass # Initialize tensor lists dip_polar_list = [] opt_rot_list = [] dip_quad_polar_list = [] gauge_list = [] make_gauge_list(gauge_list) # Gather data synthesize_dipole_polar(db, dip_polar_list) synthesize_opt_rot(db, opt_rot_list) synthesize_dip_quad_polar(db, dip_quad_polar_list) # Compute Scattering # Run new function (src/bin/ccresponse/scatter.cc) psi4.print_out('Running scatter function') step = psi4.get_local_option('FINDIF', 'DISP_SIZE') for gauge in opt_rot_list: g_idx = opt_rot_list.index(gauge) # print('\n\n----------------------------------------------------------------------') # print('\t%%%%%%%%%% {} %%%%%%%%%%'.format(gauge_list[g_idx])) # print('----------------------------------------------------------------------\n\n') psi4.print_out( '\n\n----------------------------------------------------------------------\n' ) psi4.print_out('\t%%%%%%%%%% {} %%%%%%%%%%\n'.format( gauge_list[g_idx])) psi4.print_out( '----------------------------------------------------------------------\n\n' ) psi4.scatter(step, dip_polar_list, gauge, dip_quad_polar_list) db.close()
def run_dftd3(self, func=None, dashlvl=None, dashparam=None, dertype=None): """Function to call Grimme's dftd3 program (http://toc.uni-muenster.de/DFTD3/) to compute the -D correction of level *dashlvl* using parameters for the functional *func*. The dictionary *dashparam* can be used to supply a full set of dispersion parameters in the absense of *func* or to supply individual overrides in the presence of *func*. Returns energy if *dertype* is 0, gradient if *dertype* is 1, else tuple of energy and gradient if *dertype* unspecified. The dftd3 executable must be independently compiled and found in :envvar:`PATH`. """ # Validate arguments if self is None: self = psi4.get_active_molecule() dashlvl = dashlvl.lower() dashlvl = dash_alias['-' + dashlvl][1:] if ( '-' + dashlvl) in dash_alias.keys() else dashlvl if dashlvl not in dashcoeff.keys(): raise ValidationError( """-D correction level %s is not available. Choose among %s.""" % (dashlvl, dashcoeff.keys())) if dertype is None: dertype = -1 elif der0th.match(str(dertype)): dertype = 0 elif der1st.match(str(dertype)): dertype = 1 elif der2nd.match(str(dertype)): raise ValidationError( 'Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) else: raise ValidationError( 'Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) if func is None: if dashparam is None: # defunct case raise ValidationError( """Parameters for -D correction missing. Provide a func or a dashparam kwarg.""" ) else: # case where all param read from dashparam dict (which must have all correct keys) func = 'custom' dashcoeff[dashlvl][func] = {} dashparam = dict((k.lower(), v) for k, v in dashparam.iteritems()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] else: raise ValidationError( """Parameter %s is missing from dashparam dict %s.""" % (key, dashparam)) else: func = func.lower() if func not in dashcoeff[dashlvl].keys(): raise ValidationError( """Functional %s is not available for -D level %s.""" % (func, dashlvl)) if dashparam is None: # (normal) case where all param taken from dashcoeff above pass else: # case where items in dashparam dict can override param taken from dashcoeff above dashparam = dict((k.lower(), v) for k, v in dashparam.iteritems()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] # Move ~/.dftd3par.<hostname> out of the way so it won't interfere defaultfile = os.path.expanduser( '~') + '/.dftd3par.' + socket.gethostname() defmoved = False if os.path.isfile(defaultfile): os.rename(defaultfile, defaultfile + '_hide') defmoved = True # Setup unique scratch directory and move in current_directory = os.getcwd() psioh = psi4.IOManager.shared_object() psio = psi4.IO.shared_object() os.chdir(psioh.get_default_path()) dftd3_tmpdir = 'psi.' + str(os.getpid()) + '.' + psio.get_default_namespace() + \ '.dftd3.' + str(random.randint(0, 99999)) if os.path.exists(dftd3_tmpdir) is False: os.mkdir(dftd3_tmpdir) os.chdir(dftd3_tmpdir) # Write dftd3_parameters file that governs dispersion calc paramfile = './dftd3_parameters' pfile = open(paramfile, 'w') pfile.write(dash_server(func, dashlvl, 'dftd3')) pfile.close() # Write dftd3_geometry file that supplies geometry to dispersion calc geomfile = './dftd3_geometry.xyz' gfile = open(geomfile, 'w') numAtoms = self.natom() geom = self.save_string_xyz() reals = [] for line in geom.splitlines(): if line.split()[0] == 'Gh': numAtoms -= 1 else: reals.append(line) gfile.write(str(numAtoms) + '\n') for line in reals: gfile.write(line.strip() + '\n') gfile.close() # Call dftd3 program try: dashout = subprocess.Popen(['dftd3', geomfile, '-grad'], stdout=subprocess.PIPE) except OSError: raise ValidationError('Program dftd3 not found in path.') out, err = dashout.communicate() # Parse output (could go further and break into E6, E8, E10 and Cn coeff) success = False for line in out.splitlines(): if re.match(' Edisp /kcal,au', line): sline = line.split() dashd = float(sline[3]) if re.match(' normal termination of dftd3', line): success = True if not success: raise ValidationError('Program dftd3 did not complete successfully.') # Parse grad output derivfile = './dftd3_gradient' dfile = open(derivfile, 'r') dashdderiv = [] i = 0 for line in geom.splitlines(): if i == 0: i += 1 else: if line.split()[0] == 'Gh': dashdderiv.append([0.0, 0.0, 0.0]) else: temp = dfile.readline() dashdderiv.append( [float(x.replace('D', 'E')) for x in temp.split()]) dfile.close() if len(dashdderiv) != self.natom(): raise ValidationError('Program dftd3 gradient file has %d atoms- %d expected.' % \ (len(dashdderiv), self.natom())) psi_dashdderiv = psi4.Matrix(self.natom(), 3) psi_dashdderiv.set(dashdderiv) # Print program output to file if verbose verbose = psi4.get_option('SCF', 'PRINT') if verbose >= 3: psi4.print_out('\n ==> DFTD3 Output <==\n') psi4.print_out(out) dfile = open(derivfile, 'r') psi4.print_out(dfile.read().replace('D', 'E')) dfile.close() psi4.print_out('\n') # Clean up files and remove scratch directory os.unlink(paramfile) os.unlink(geomfile) os.unlink(derivfile) if defmoved is True: os.rename(defaultfile + '_hide', defaultfile) os.chdir('..') try: shutil.rmtree(dftd3_tmpdir) except OSError as e: ValidationError('Unable to remove dftd3 temporary directory %s' % e, file=sys.stderr) os.chdir(current_directory) # return -D & d(-D)/dx psi4.set_variable('DISPERSION CORRECTION ENERGY', dashd) if dertype == -1: return dashd, dashdderiv elif dertype == 0: return dashd elif dertype == 1: return psi_dashdderiv
def run_dftd3(self, func=None, dashlvl=None, dashparam=None, dertype=None, verbose=False): """Function to call Grimme's dftd3 program (http://toc.uni-muenster.de/DFTD3/) to compute the -D correction of level *dashlvl* using parameters for the functional *func*. The dictionary *dashparam* can be used to supply a full set of dispersion parameters in the absense of *func* or to supply individual overrides in the presence of *func*. Returns energy if *dertype* is 0, gradient if *dertype* is 1, else tuple of energy and gradient if *dertype* unspecified. The dftd3 executable must be independently compiled and found in :envvar:`PATH` or :envvar:`PSIPATH`. *self* may be either a qcdb.Molecule (sensibly) or a psi4.Molecule (works b/c psi4.Molecule has been extended by this method py-side and only public interface fns used) or a string that can be instantiated into a qcdb.Molecule. """ # Create (if necessary) and update qcdb.Molecule if isinstance(self, Molecule): # called on a qcdb.Molecule pass elif isinstance(self, psi4.Molecule): # called on a python export of a psi4.Molecule (py-side through Psi4's driver) self.create_psi4_string_from_molecule() elif isinstance(self, basestring): # called on a string representation of a psi4.Molecule (c-side through psi4.Dispersion) self = Molecule(self) else: raise ValidationError( """Argument mol must be psi4string or qcdb.Molecule""") self.update_geometry() # Validate arguments dashlvl = dashlvl.lower() dashlvl = dash_alias['-' + dashlvl][1:] if ( '-' + dashlvl) in dash_alias.keys() else dashlvl if dashlvl not in dashcoeff.keys(): raise ValidationError( """-D correction level %s is not available. Choose among %s.""" % (dashlvl, dashcoeff.keys())) if dertype is None: dertype = -1 elif der0th.match(str(dertype)): dertype = 0 elif der1st.match(str(dertype)): dertype = 1 elif der2nd.match(str(dertype)): raise ValidationError( 'Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) else: raise ValidationError( 'Requested derivative level \'dertype\' %s not valid for run_dftd3.' % (dertype)) if func is None: if dashparam is None: # defunct case raise ValidationError( """Parameters for -D correction missing. Provide a func or a dashparam kwarg.""" ) else: # case where all param read from dashparam dict (which must have all correct keys) func = 'custom' dashcoeff[dashlvl][func] = {} dashparam = dict((k.lower(), v) for k, v in dashparam.iteritems()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] else: raise ValidationError( """Parameter %s is missing from dashparam dict %s.""" % (key, dashparam)) else: func = func.lower() if func not in dashcoeff[dashlvl].keys(): raise ValidationError( """Functional %s is not available for -D level %s.""" % (func, dashlvl)) if dashparam is None: # (normal) case where all param taken from dashcoeff above pass else: # case where items in dashparam dict can override param taken from dashcoeff above dashparam = dict((k.lower(), v) for k, v in dashparam.iteritems()) for key in dashcoeff[dashlvl]['b3lyp'].keys(): if key in dashparam.keys(): dashcoeff[dashlvl][func][key] = dashparam[key] # Move ~/.dftd3par.<hostname> out of the way so it won't interfere defaultfile = os.path.expanduser( '~') + '/.dftd3par.' + socket.gethostname() defmoved = False if os.path.isfile(defaultfile): os.rename(defaultfile, defaultfile + '_hide') defmoved = True # Find environment by merging PSIPATH and PATH environment variables lenv = { 'PATH': ':'.join([os.path.abspath(x) for x in os.environ.get('PSIPATH', '').split(':') if x != '']) + \ ':' + os.environ.get('PATH'), 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH') } # Filter out None values as subprocess will fault on them lenv = {k: v for k, v in lenv.items() if v is not None} # Find out if running from Psi4 for scratch details and such try: psi4.version() except NameError: isP4regime = False else: isP4regime = True # Setup unique scratch directory and move in current_directory = os.getcwd() if isP4regime: psioh = psi4.IOManager.shared_object() psio = psi4.IO.shared_object() os.chdir(psioh.get_default_path()) dftd3_tmpdir = 'psi.' + str(os.getpid()) + '.' + psio.get_default_namespace() + \ '.dftd3.' + str(random.randint(0, 99999)) else: dftd3_tmpdir = os.environ['HOME'] + os.sep + 'dftd3_' + str( random.randint(0, 99999)) if os.path.exists(dftd3_tmpdir) is False: os.mkdir(dftd3_tmpdir) os.chdir(dftd3_tmpdir) # Write dftd3_parameters file that governs dispersion calc paramcontents = dash_server(func, dashlvl, 'dftd3') paramfile1 = 'dftd3_parameters' # older patched name with open(paramfile1, 'w') as handle: handle.write(paramcontents) paramfile2 = '.dftd3par.local' # new mainline name with open(paramfile2, 'w') as handle: handle.write(paramcontents) # Write dftd3_geometry file that supplies geometry to dispersion calc numAtoms = self.natom() geom = self.save_string_xyz() reals = [] for line in geom.splitlines(): lline = line.split() if len(lline) != 4: continue if lline[0] == 'Gh': numAtoms -= 1 else: reals.append(line) geomtext = str(numAtoms) + '\n\n' for line in reals: geomtext += line.strip() + '\n' geomfile = './dftd3_geometry.xyz' with open(geomfile, 'w') as handle: handle.write(geomtext) # TODO somehow the variations on save_string_xyz and # whether natom and chgmult does or doesn't get written # have gotten all tangled. I fear this doesn't work # the same btwn libmints and qcdb or for ghosts # Call dftd3 program command = ['dftd3', geomfile] if dertype != 0: command.append('-grad') try: dashout = subprocess.Popen(command, stdout=subprocess.PIPE, env=lenv) except OSError as e: raise ValidationError('Program dftd3 not found in path. %s' % e) out, err = dashout.communicate() # Parse output (could go further and break into E6, E8, E10 and Cn coeff) success = False for line in out.splitlines(): if re.match(' Edisp /kcal,au', line): sline = line.split() dashd = float(sline[3]) if re.match(' normal termination of dftd3', line): success = True if not success: os.chdir(current_directory) raise Dftd3Error( """Unsuccessful run. Possibly -D variant not available in dftd3 version.""" ) # Parse grad output if dertype != 0: derivfile = './dftd3_gradient' dfile = open(derivfile, 'r') dashdderiv = [] for line in geom.splitlines(): lline = line.split() if len(lline) != 4: continue if lline[0] == 'Gh': dashdderiv.append([0.0, 0.0, 0.0]) else: dashdderiv.append([ float(x.replace('D', 'E')) for x in dfile.readline().split() ]) dfile.close() if len(dashdderiv) != self.natom(): raise ValidationError('Program dftd3 gradient file has %d atoms- %d expected.' % \ (len(dashdderiv), self.natom())) # Prepare results for Psi4 if isP4regime and dertype != 0: psi4.set_variable('DISPERSION CORRECTION ENERGY', dashd) psi_dashdderiv = psi4.Matrix(self.natom(), 3) psi_dashdderiv.set(dashdderiv) # Print program output to file if verbose if isP4regime: verbose = True if psi4.get_option('SCF', 'PRINT') >= 3 else False if verbose: text = '\n ==> DFTD3 Output <==\n' text += out if dertype != 0: with open(derivfile, 'r') as handle: text += handle.read().replace('D', 'E') text += '\n' if isP4regime: psi4.print_out(text) else: print(text) # Clean up files and remove scratch directory os.unlink(paramfile1) os.unlink(paramfile2) os.unlink(geomfile) if dertype != 0: os.unlink(derivfile) if defmoved is True: os.rename(defaultfile + '_hide', defaultfile) os.chdir('..') try: shutil.rmtree(dftd3_tmpdir) except OSError as e: ValidationError('Unable to remove dftd3 temporary directory %s' % e) os.chdir(current_directory) # return -D & d(-D)/dx if dertype == -1: return dashd, dashdderiv elif dertype == 0: return dashd elif dertype == 1: return psi_dashdderiv
def run_gaussian_2(name, **kwargs): # throw an exception for open-shells if (psi4.get_option('SCF','REFERENCE') != 'RHF' ): raise ValidationError("""g2 computations require "reference rhf".""") # stash user options: optstash = p4util.OptionsState( ['FNOCC','COMPUTE_TRIPLES'], ['FNOCC','COMPUTE_MP4_TRIPLES'], ['FREEZE_CORE'], ['MP2_TYPE'], ['SCF','SCF_TYPE']) # override default scf_type psi4.set_local_option('SCF','SCF_TYPE','PK') # optimize geometry at scf level psi4.clean() psi4.set_global_option('BASIS',"6-31G(D)") driver.optimize('scf') psi4.clean() # scf frequencies for zpe # NOTE This line should not be needed, but without it there's a seg fault scf_e, ref = driver.frequency('scf', return_wfn=True) # thermodynamic properties du = psi4.get_variable('INTERNAL ENERGY CORRECTION') dh = psi4.get_variable('ENTHALPY CORRECTION') dg = psi4.get_variable('GIBBS FREE ENERGY CORRECTION') freqs = ref.frequencies() nfreq = freqs.dim(0) freqsum = 0.0 for i in range(0, nfreq): freqsum += freqs.get(i) zpe = freqsum / p4const.psi_hartree2wavenumbers * 0.8929 * 0.5 psi4.clean() # optimize geometry at mp2 (no frozen core) level # note: freeze_core isn't an option in MP2 psi4.set_global_option('FREEZE_CORE',"FALSE") psi4.set_global_option('MP2_TYPE', 'CONV') driver.optimize('mp2') psi4.clean() # qcisd(t) psi4.set_local_option('FNOCC','COMPUTE_MP4_TRIPLES',"TRUE") psi4.set_global_option('FREEZE_CORE',"TRUE") psi4.set_global_option('BASIS',"6-311G(D_P)") ref = driver.proc.run_fnocc('qcisd(t)', return_wfn=True, **kwargs) # HLC: high-level correction based on number of valence electrons nirrep = ref.nirrep() frzcpi = ref.frzcpi() nfzc = 0 for i in range (0,nirrep): nfzc += frzcpi[i] nalpha = ref.nalpha() - nfzc nbeta = ref.nbeta() - nfzc # hlc of gaussian-2 hlc = -0.00481 * nalpha -0.00019 * nbeta # hlc of gaussian-1 hlc1 = -0.00614 * nalpha eqci_6311gdp = psi4.get_variable("QCISD(T) TOTAL ENERGY") emp4_6311gd = psi4.get_variable("MP4 TOTAL ENERGY") emp2_6311gd = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() # correction for diffuse functions psi4.set_global_option('BASIS',"6-311+G(D_P)") driver.energy('mp4') emp4_6311pg_dp = psi4.get_variable("MP4 TOTAL ENERGY") emp2_6311pg_dp = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() # correction for polarization functions psi4.set_global_option('BASIS',"6-311G(2DF_P)") driver.energy('mp4') emp4_6311g2dfp = psi4.get_variable("MP4 TOTAL ENERGY") emp2_6311g2dfp = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() # big basis mp2 psi4.set_global_option('BASIS',"6-311+G(3DF_2P)") #run_fnocc('_mp2',**kwargs) driver.energy('mp2') emp2_big = psi4.get_variable("MP2 TOTAL ENERGY") psi4.clean() eqci = eqci_6311gdp e_delta_g2 = emp2_big + emp2_6311gd - emp2_6311g2dfp - emp2_6311pg_dp e_plus = emp4_6311pg_dp - emp4_6311gd e_2df = emp4_6311g2dfp - emp4_6311gd eg2 = eqci + e_delta_g2 + e_plus + e_2df eg2_mp2_0k = eqci + (emp2_big - emp2_6311gd) + hlc + zpe psi4.print_out('\n') psi4.print_out(' ==> G1/G2 Energy Components <==\n') psi4.print_out('\n') psi4.print_out(' QCISD(T): %20.12lf\n' % eqci) psi4.print_out(' E(Delta): %20.12lf\n' % e_delta_g2) psi4.print_out(' E(2DF): %20.12lf\n' % e_2df) psi4.print_out(' E(+): %20.12lf\n' % e_plus) psi4.print_out(' E(G1 HLC): %20.12lf\n' % hlc1) psi4.print_out(' E(G2 HLC): %20.12lf\n' % hlc) psi4.print_out(' E(ZPE): %20.12lf\n' % zpe) psi4.print_out('\n') psi4.print_out(' ==> 0 Kelvin Results <==\n') psi4.print_out('\n') eg2_0k = eg2 + zpe + hlc psi4.print_out(' G1: %20.12lf\n' % (eqci + e_plus + e_2df + hlc1 + zpe)) psi4.print_out(' G2(MP2): %20.12lf\n' % eg2_mp2_0k) psi4.print_out(' G2: %20.12lf\n' % eg2_0k) psi4.set_variable("G1 TOTAL ENERGY",eqci + e_plus + e_2df + hlc1 + zpe) psi4.set_variable("G2 TOTAL ENERGY",eg2_0k) psi4.set_variable("G2(MP2) TOTAL ENERGY",eg2_mp2_0k) psi4.print_out('\n') T = psi4.get_global_option('T') psi4.print_out(' ==> %3.0lf Kelvin Results <==\n'% T) psi4.print_out('\n') internal_energy = eg2_mp2_0k + du - zpe / 0.8929 enthalpy = eg2_mp2_0k + dh - zpe / 0.8929 gibbs = eg2_mp2_0k + dg - zpe / 0.8929 psi4.print_out(' G2(MP2) energy: %20.12lf\n' % internal_energy ) psi4.print_out(' G2(MP2) enthalpy: %20.12lf\n' % enthalpy) psi4.print_out(' G2(MP2) free energy: %20.12lf\n' % gibbs) psi4.print_out('\n') psi4.set_variable("G2(MP2) INTERNAL ENERGY",internal_energy) psi4.set_variable("G2(MP2) ENTHALPY",enthalpy) psi4.set_variable("G2(MP2) FREE ENERGY",gibbs) internal_energy = eg2_0k + du - zpe / 0.8929 enthalpy = eg2_0k + dh - zpe / 0.8929 gibbs = eg2_0k + dg - zpe / 0.8929 psi4.print_out(' G2 energy: %20.12lf\n' % internal_energy ) psi4.print_out(' G2 enthalpy: %20.12lf\n' % enthalpy) psi4.print_out(' G2 free energy: %20.12lf\n' % gibbs) psi4.set_variable("CURRENT ENERGY",eg2_0k) psi4.set_variable("G2 INTERNAL ENERGY",internal_energy) psi4.set_variable("G2 ENTHALPY",enthalpy) psi4.set_variable("G2 FREE ENERGY",gibbs) psi4.clean() optstash.restore() # return 0K g2 results return eg2_0k
def run_roa(name, **kwargs): """ Main driver for managing Raman Optical activity computations with CC response theory. Uses distributed finite differences approach --> 1. Sets up a database to keep track of running/finished/waiting computations. 2. Generates separate input files for displaced geometries. 3. When all displacements are run, collects the necessary information from each displaced computation, and computes final result. """ # Get list of omega values -> Make sure we only have one wavelength # Catch this now before any real work gets done omega = psi4.get_option('CCRESPONSE', 'OMEGA') if len(omega) > 2: raise Exception( 'ROA scattering can only be performed for one wavelength.') else: pass psi4.print_out('Running ROA computation. Subdirectories for each ' 'required displaced geometry have been created.\n\n') dbno = 0 # Initialize database db = shelve.open('database', writeback=True) # Check if final result is in here # ->if we have already computed roa, back up the dict # ->copy it setting this flag to false and continue if ('roa_computed' in db) and (db['roa_computed']): db2 = shelve.open('.database.bak{}'.format(dbno), writeback=True) dbno += 1 for key, value in db.iteritems(): db2[key] = value db2.close() db['roa_computed'] = False else: db['roa_computed'] = False if 'inputs_generated' not in db: findif_response_utils.initialize_database(db, name, "roa", ["roa_tensor"]) # Generate input files if not db['inputs_generated']: findif_response_utils.generate_inputs(db, name) # handled by helper db['inputs_generated'] = True # Check job status if db['inputs_generated'] and not db['jobs_complete']: print('Checking status') findif_response_utils.stat(db) for job, status in db['job_status'].items(): print("{} --> {}".format(job, status)) # Compute ROA Scattering if db['jobs_complete']: mygauge = psi4.get_option('CCRESPONSE', 'GAUGE') consider_gauge = { 'LENGTH': ['Length Gauge'], 'VELOCITY': ['Modified Velocity Gauge'], 'BOTH': ['Length Gauge', 'Modified Velocity Gauge'] } gauge_list = ["{} Results".format(x) for x in consider_gauge[mygauge]] # Gather data dip_polar_list = findif_response_utils.collect_displaced_matrix_data( db, 'Dipole Polarizability', 3) opt_rot_list = [ x for x in (findif_response_utils.collect_displaced_matrix_data( db, "Optical Rotation Tensor ({})".format(gauge), 3) for gauge in consider_gauge[mygauge]) ] dip_quad_polar_list = findif_response_utils.collect_displaced_matrix_data( db, "Electric-Dipole/Quadrupole Polarizability", 9) # Compute Scattering # Run new function (src/bin/ccresponse/scatter.cc) psi4.print_out('Running scatter function') step = psi4.get_local_option('FINDIF', 'DISP_SIZE') for g_idx, gauge in enumerate(opt_rot_list): print( '\n\n----------------------------------------------------------------------' ) print('\t%%%%%%%%%% {} %%%%%%%%%%'.format(gauge_list[g_idx])) print( '----------------------------------------------------------------------\n\n' ) psi4.print_out( '\n\n----------------------------------------------------------------------\n' ) psi4.print_out('\t%%%%%%%%%% {} %%%%%%%%%%\n'.format( gauge_list[g_idx])) psi4.print_out( '----------------------------------------------------------------------\n\n' ) print( 'roa.py:85 I am not being passed a molecule, grabbing from global :(' ) psi4.scatter(psi4.get_active_molecule(), step, dip_polar_list, gauge, dip_quad_polar_list) db['roa_computed'] = True db.close()