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 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_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_cfour(name, **kwargs): """Function that prepares environment and input files for a calculation calling Stanton and Gauss's CFOUR code. Also processes results back into Psi4 format. This function is not called directly but is instead called by :py:func:`~driver.energy` or :py:func:`~driver.optimize` when a Cfour method is requested (through *name* argument). In order to function correctly, the Cfour executable ``xcfour`` must be present in :envvar:`PATH` or :envvar:`PSIPATH`. .. hlist:: :columns: 1 * Many :ref:`PSI Variables <apdx:cfour_psivar>` extracted from the Cfour output * Python dictionary of associated file constants accessible as ``P4C4_INFO['zmat']``, ``P4C4_INFO['output']``, ``P4C4_INFO['grd']``, *etc.* :type name: string :param name: ``'c4-scf'`` || ``'c4-ccsd(t)'`` || ``'cfour'`` || etc. First argument, usually unlabeled. Indicates the computational method to be applied to the system. :type keep: :ref:`boolean <op_py_boolean>` :param keep: ``'on'`` || |dl| ``'off'`` |dr| Indicates whether to delete the Cfour scratch directory upon completion of the Cfour job. :type path: string :param path: Indicates path to Cfour scratch directory (with respect to Psi4 scratch directory). Otherwise, the default is a subdirectory within the Psi4 scratch directory. If specified, GENBAS and/or ZMAT within will be used. :type genbas: string :param genbas: Indicates that contents should be used for GENBAS file. GENBAS is a complicated topic. It is quite unnecessary if the molecule is from a molecule {...} block and basis is set through |Psifours| BASIS keyword. In that case, a GENBAS is written from LibMints and all is well. Otherwise, a GENBAS is looked for in the usual places: PSIPATH, PATH, PSIDATADIR/basis. If path kwarg is specified, also looks there preferentially for a GENBAS. Can also specify GENBAS within an input file through a string and setting the genbas kwarg. Note that due to the input parser's aggression, blank lines need to be replaced by the text blankline. """ lowername = name.lower() internal_p4c4_info = {} optstash = p4util.OptionsState(['CFOUR', 'TRANSLATE_PSI4']) # Determine calling function and hence dertype calledby = inspect.stack()[1][3] dertype = ['energy', 'gradient', 'hessian'].index(calledby) #print('I am %s called by %s called by %s.\n' % # (inspect.stack()[0][3], inspect.stack()[1][3], inspect.stack()[2][3])) # Save submission directory current_directory = os.getcwd() # Move into job scratch directory psioh = psi4.IOManager.shared_object() psio = psi4.IO.shared_object() os.chdir(psioh.get_default_path()) # Construct and move into cfour subdirectory of job scratch directory cfour_tmpdir = kwargs['path'] if 'path' in kwargs else \ 'psi.' + str(os.getpid()) + '.' + psio.get_default_namespace() + \ '.cfour.' + str(random.randint(0, 99999)) if not os.path.exists(cfour_tmpdir): os.mkdir(cfour_tmpdir) os.chdir(cfour_tmpdir) # 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') + \ ':' + psi4.Process.environment["PSIDATADIR"] + '/basis' + \ ':' + psi4.psi_top_srcdir() + '/share/basis', 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH') } if 'path' in kwargs: lenv['PATH'] = kwargs['path'] + ':' + lenv['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} # Load the GENBAS file genbas_path = qcdb.search_file('GENBAS', lenv['PATH']) if genbas_path: try: shutil.copy2(genbas_path, psioh.get_default_path() + cfour_tmpdir) except shutil.Error: # should only fail if src and dest equivalent pass psi4.print_out("\n GENBAS loaded from %s\n" % (genbas_path)) psi4.print_out(" CFOUR to be run from %s\n" % (psioh.get_default_path() + cfour_tmpdir)) else: message = """ GENBAS file for CFOUR interface not found. Either: [1] Supply a GENBAS by placing it in PATH or PSIPATH [1a] Use cfour {} block with molecule and basis directives. [1b] Use molecule {} block and CFOUR_BASIS keyword. [2] Allow Psi4's internal basis sets to convert to GENBAS [2a] Use molecule {} block and BASIS keyword. """ psi4.print_out(message) psi4.print_out(' Search path that was tried:\n') psi4.print_out(lenv['PATH'].replace(':', ', ')) # Generate the ZMAT input file in scratch if 'path' in kwargs and os.path.isfile('ZMAT'): psi4.print_out(" ZMAT loaded from %s\n" % (psioh.get_default_path() + kwargs['path'] + '/ZMAT')) else: with open('ZMAT', 'w') as cfour_infile: cfour_infile.write(write_zmat(lowername, dertype)) internal_p4c4_info['zmat'] = open('ZMAT', 'r').read() #psi4.print_out('\n====== Begin ZMAT input for CFOUR ======\n') #psi4.print_out(open('ZMAT', 'r').read()) #psi4.print_out('======= End ZMAT input for CFOUR =======\n\n') #print('\n====== Begin ZMAT input for CFOUR ======') #print(open('ZMAT', 'r').read()) #print('======= End ZMAT input for CFOUR =======\n') if 'genbas' in kwargs: with open('GENBAS', 'w') as cfour_basfile: cfour_basfile.write(kwargs['genbas'].replace( '\nblankline\n', '\n\n')) psi4.print_out(' GENBAS loaded from kwargs string\n') # Close psi4 output file and reopen with filehandle print('output in', current_directory + '/' + psi4.outfile_name()) psi4.close_outfile() pathfill = '' if os.path.isabs( psi4.outfile_name()) else current_directory + os.path.sep p4out = open(pathfill + psi4.outfile_name(), 'a') # Handle user's OMP_NUM_THREADS and CFOUR_OMP_NUM_THREADS omp_num_threads_found = 'OMP_NUM_THREADS' in os.environ if omp_num_threads_found == True: omp_num_threads_user = os.environ['OMP_NUM_THREADS'] if psi4.has_option_changed('CFOUR', 'CFOUR_OMP_NUM_THREADS') == True: os.environ['OMP_NUM_THREADS'] = str( psi4.get_option('CFOUR', 'CFOUR_OMP_NUM_THREADS')) #print("""\n\n<<<<< RUNNING CFOUR ... >>>>>\n\n""") # Call executable xcfour, directing cfour output to the psi4 output file cfour_executable = kwargs['c4exec'] if 'c4exec' in kwargs else 'xcfour' try: retcode = subprocess.Popen([cfour_executable], bufsize=0, stdout=subprocess.PIPE, env=lenv) except OSError as e: sys.stderr.write( 'Program %s not found in path or execution failed: %s\n' % (cfour_executable, e.strerror)) p4out.write('Program %s not found in path or execution failed: %s\n' % (cfour_executable, e.strerror)) message = ('Program %s not found in path or execution failed: %s\n' % (cfour_executable, e.strerror)) raise ValidationError(message) c4out = '' while True: data = retcode.stdout.readline() if not data: break if psi4.outfile_name() == 'stdout': sys.stdout.write(data) else: p4out.write(data) p4out.flush() c4out += data internal_p4c4_info['output'] = c4out # Restore user's OMP_NUM_THREADS if omp_num_threads_found == True: if psi4.has_option_changed('CFOUR', 'CFOUR_OMP_NUM_THREADS') == True: os.environ['OMP_NUM_THREADS'] = omp_num_threads_user c4files = {} p4out.write('\n') for item in ['GRD', 'FCMFINAL', 'DIPOL']: try: with open(psioh.get_default_path() + cfour_tmpdir + '/' + item, 'r') as handle: c4files[item] = handle.read() p4out.write(' CFOUR scratch file %s has been read\n' % (item)) p4out.write('%s\n' % c4files[item]) internal_p4c4_info[item.lower()] = c4files[item] except IOError: pass p4out.write('\n') molecule = psi4.get_active_molecule() if molecule.name() == 'blank_molecule_psi4_yo': qcdbmolecule = None else: molecule.update_geometry() qcdbmolecule = qcdb.Molecule( molecule.create_psi4_string_from_molecule()) qcdbmolecule.update_geometry() # c4mol, if it exists, is dinky, just a clue to geometry of cfour results psivar, c4grad, c4mol = qcdb.cfour.harvest(qcdbmolecule, c4out, **c4files) # Absorb results into psi4 data structures for key in psivar.keys(): psi4.set_variable(key.upper(), float(psivar[key])) if qcdbmolecule is None and c4mol is not None: molecule = geometry(c4mol.create_psi4_string_from_molecule(), name='blank_molecule_psi4_yo') molecule.update_geometry() # This case arises when no Molecule going into calc (cfour {} block) but want # to know the orientation at which grad, properties, etc. are returned (c4mol). # c4mol is dinky, w/o chg, mult, dummies and retains name # blank_molecule_psi4_yo so as to not interfere with future cfour {} blocks if c4grad: mat = psi4.Matrix(len(c4grad), 3) mat.set(c4grad) psi4.set_gradient(mat) #print ' <<< [3] C4-GRD-GRAD >>>' #mat.print() # exit(1) # # Things needed psi4.so module to do # collect c4out string # read GRD # read FCMFINAL # see if theres an active molecule # # Things delegatable to qcdb # parsing c4out # reading GRD and FCMFINAL strings # reconciling p4 and c4 molecules (orient) # reconciling c4out and GRD and FCMFINAL results # transforming frame of results back to p4 # # Things run_cfour needs to have back # psivar # qcdb.Molecule of c4? # coordinates? # gradient in p4 frame # # Process the cfour output # psivar, c4coord, c4grad = qcdb.cfour.cfour_harvest(c4out) # for key in psivar.keys(): # psi4.set_variable(key.upper(), float(psivar[key])) # # # Awful Hack - Go Away TODO # if c4grad: # molecule = psi4.get_active_molecule() # molecule.update_geometry() # # if molecule.name() == 'blank_molecule_psi4_yo': # p4grad = c4grad # p4coord = c4coord # else: # qcdbmolecule = qcdb.Molecule(molecule.create_psi4_string_from_molecule()) # #p4grad = qcdbmolecule.deorient_array_from_cfour(c4coord, c4grad) # #p4coord = qcdbmolecule.deorient_array_from_cfour(c4coord, c4coord) # # with open(psioh.get_default_path() + cfour_tmpdir + '/GRD', 'r') as cfour_grdfile: # c4outgrd = cfour_grdfile.read() # print('GRD\n',c4outgrd) # c4coordGRD, c4gradGRD = qcdb.cfour.cfour_harvest_files(qcdbmolecule, grd=c4outgrd) # # p4mat = psi4.Matrix(len(p4grad), 3) # p4mat.set(p4grad) # psi4.set_gradient(p4mat) # print(' <<< P4 PSIVAR >>>') # for item in psivar: # print(' %30s %16.8f' % (item, psivar[item])) #print(' <<< P4 COORD >>>') #for item in p4coord: # print(' %16.8f %16.8f %16.8f' % (item[0], item[1], item[2])) # print(' <<< P4 GRAD >>>') # for item in c4grad: # print(' %16.8f %16.8f %16.8f' % (item[0], item[1], item[2])) # Clean up cfour scratch directory unless user instructs otherwise keep = yes.match(str(kwargs['keep'])) if 'keep' in kwargs else False os.chdir('..') try: if keep or ('path' in kwargs): p4out.write('\n CFOUR scratch files have been kept in %s\n' % (psioh.get_default_path() + cfour_tmpdir)) else: shutil.rmtree(cfour_tmpdir) except OSError as e: print('Unable to remove CFOUR temporary directory %s' % e, file=sys.stderr) exit(1) # Return to submission directory and reopen output file os.chdir(current_directory) p4out.close() psi4.reopen_outfile() psi4.print_out('\n') p4util.banner(' Cfour %s %s Results ' % (name.lower(), calledby.capitalize())) psi4.print_variables() if c4grad: psi4.get_gradient().print_out() psi4.print_out('\n') p4util.banner(' Cfour %s %s Results ' % (name.lower(), calledby.capitalize())) psi4.print_variables() if c4grad: psi4.get_gradient().print_out() # Quit if Cfour threw error if psi4.get_variable('CFOUR ERROR CODE'): raise ValidationError("""Cfour exited abnormally.""") P4C4_INFO.clear() P4C4_INFO.update(internal_p4c4_info) optstash.restore()
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 _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 core.has_option_changed('SCF', 'E_CONVERGENCE'): if procedures['energy'][method_name] in [proc.run_scf, proc.run_dft]: core.set_local_option('SCF', 'E_CONVERGENCE', scf_Ec) if verbose >= 2: print(scf_Ec, end=' ') else: core.set_local_option('SCF', 'E_CONVERGENCE', pscf_Ec) if verbose >= 2: print(pscf_Ec, end=' ') else: if verbose >= 2: print('CUSTOM', core.get_option('SCF', 'E_CONVERGENCE'), end=' ') if not core.has_option_changed('SCF', 'D_CONVERGENCE'): if procedures['energy'][method_name] in [proc.run_scf, proc.run_dft]: core.set_local_option('SCF', 'D_CONVERGENCE', scf_Dc) if verbose >= 2: print(scf_Dc, end=' ') else: core.set_local_option('SCF', 'D_CONVERGENCE', pscf_Dc) if verbose >= 2: print(pscf_Dc, end=' ') else: if verbose >= 2: print('CUSTOM', core.get_option('SCF', 'D_CONVERGENCE'), end=' ') # Set post-scf convergence criteria (global will cover all correlated modules) if not core.has_global_option_changed('E_CONVERGENCE'): if procedures['energy'][method_name] not in [ proc.run_scf, proc.run_dft ]: core.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', core.get_global_option('E_CONVERGENCE'), end=' ') if verbose >= 2: print('') return optstash