def write_orbitals(self, filename='None'): # Assign filename depending if it is given as an input # or if it has to be generated from the elements. if filename == 'None': filename = '../data/molden-fchk_files/' + self.scheme[ 0] + '/' + self.generate_molname() else: filename = '../data/molden-fchk_files/' + filename # Write out the molden file using psi4 psi4.molden(self.model.wavefunction, filename + '.molden') # Using IOData, we load in the molden file. We alter the # values of the coefficients using the localized coefficients. # Finally we write them out to a FCHK file and remove the molden file molecule = load_one(filename + '.molden') molecule_mo = molecule.mo mo_coeffs = molecule_mo.coeffs # replace the occupied orbital coefficients with the localized ones. self.L_occ = np.dot(self.C_occ, self.W) mo_coeffs[:, :self.N_occ] = self.L_occ molecule_mo.coeffs = mo_coeffs dump_one(molecule, filename + '.fchk') os.remove(filename + '.molden')
dRMS = 0.5 * (mean(diis_r_a**2)**0.5 + mean(diis_r_b**2) * 0.5) print( 'SCF Iteration {:3d}: Energy = {: 4.16f} dE = {: 1.5e} dRMS = {:1.5e}'. format(scf_iter + 1, SCF_E, dE, dRMS)) if (abs(dE) < E_conv) and (dRMS < D_conv): break E_old = SCF_E if scf_iter >= 2: Fa = diis_xtrap(F_list_a, R_list_a) Fb = diis_xtrap(F_list_b, R_list_b) Ca, Pa, epa = diag_F(Fa, nalpha) Cb, Pb, epb = diag_F(Fb, nbeta) if scf_iter == maxiter: psi4.core.clean() raise Exception("Maximum number of SCF iterations exceeded.") print('\nSCF Converged.') print('Final UHF Energy: {: .8f} [Eh]'.format(SCF_E)) SCF_E_psi, wfn = psi4.energy('SCF', return_wfn=True) psi4.compare_values(SCF_E_psi, SCF_E, 6, 'SCF Energy') # create molden file os.system('rm -f {}.uhf.molden'.format(cmpd)) psi4.molden(wfn, '{}.uhf.molden'.format(cmpd)) psi4.fchk(wfn, 'heh+.fchk')
def psi4_calculation(conf, dih, conf_name, angle_deg, spe_method, spe_basis, geom_opt_technique, opt_method, opt_basis, geom_maxiter=100, **psi4opts): dih_atoms = [x for x in dih.GetAtoms()] dih_string = " ".join(["{}".format(x.GetIdx() + 1) for x in dih_atoms]) psi4_log_filename = "psi4_" + conf_name + ".dat" psi4.core.set_output_file(psi4_log_filename, False) psi_mol = get_psi4_mol_from_conf(conf) wf_filename = None if geom_opt_technique == "QM": logging.info("Start geometry optimization on conformer %s angle %d", conf_name, angle_deg) geom_opt_start = time.time() logging.debug("Frozen Dihedral: '%s'", dih_string) psi4.set_options({ "frozen_dihedral": dih_string, "geom_maxiter": geom_maxiter, "dynamic_level": 1, }) psi_mol.update_geometry() calc_value, wavefcn = run_psi4("optimize", psi_mol, opt_method, opt_basis, **psi4opts) if calc_value is None: logging.warning( "Failed to optimize geometry for conformer %s angle %d.", conf_name, angle_deg, ) # get logfile to help debug failures try: psi4.core.flush_outfile() with open(psi4_log_filename, "r") as fptr: psi4_log_data = fptr.read() conf.SetData("PSI4_LOG", psi4_log_data) except IOError as e: print( "Unable to retrieve psi4 log data ", psi4_log_filename, " because of error: ", e, ) raise ValueError( "Failed to optimize geometry for conformer %s angle %.1f.", conf_name, angle_deg, ) logging.info( "Optimized geometry for conformer %s angle %d in %.1f s.", conf_name, angle_deg, time.time() - geom_opt_start, ) calc_value *= psi4.constants.hartree2kcalmol # write wavefuction wf_filename = "{}_{}.molden".format("wavefcn_opt", conf_name) psi4.molden(wavefcn, wf_filename) elif geom_opt_technique == "MM": # TODO: Implement molecular mechanics-based optimization pass else: pass if ((geom_opt_technique == "None") or (opt_method != spe_method) or (opt_basis != spe_basis)): logging.info( "Calculate single point energy of conformer %s angle %d", conf_name, angle_deg, ) spe_start = time.time() calc_value, wavefcn = run_psi4("energy", psi_mol, spe_method, spe_basis, **psi4opts) if calc_value is None: logging.error( "Failed to calculate single point energy for conformer %s angle %d.", conf_name, angle_deg, ) raise ValueError( "Failed to calculate single point energy for conformer %s angle %d.", conf_name, angle_deg, ) logging.info( "Calculated single point energy for conformer %s angle %d in %.1f s.", conf_name, angle_deg, time.time() - spe_start, ) calc_value *= psi4.constants.hartree2kcalmol # attached psi4 log to each file try: # extract minimal geometry optimization data for success psi4.core.flush_outfile() with open(psi4_log_filename, "r") as fptr: psi4_log_str = str() for line in fptr.readlines(): if (line.find("~") > 0 or line.find("Exception") > 0 or line.find("Optimization") > 0): psi4_log_str += line conf.SetData("PSI4_LOG", psi4_log_str) except IOError as e: print("Unable to save psi4 log data ", psi4_log_filename, " because of error: ", e) return calc_value, psi_mol, wavefcn
if SORTandRENAME: listOfFiles = os.listdir(baseFileName) listOfFiles.sort(key=sortFunction) for i in range(len(listOfFiles)): os.rename(baseFileName + '/' + listOfFiles[i], baseFileName + '/irc-' + str(i) + '.com') if PSI4LOAD and xyzOUTPUT and CALCWF: # set psi4 stuff psi4.set_memory('500 MB') psi4.set_options({'PARALLEL': True, 'reference': 'rhf'}) geometries = {} energies = {} wavefunctions = {} for file in outFileList: if file.split('.')[-1] != 'xyz': print('remove ' + file + ' from list, because it is no xyz file') outFileList.remove(file) else: with open(file) as f: geometries[file] = psi4.geometry(f.read()) print('calc wfn for ' + file) energies[file], wavefunctions[file] = psi4.energy( 'mp2/cc-pvdz', molecule=geometries[file], return_wfn=True) outFileName = file.split('.')[0] + '.molden' print('save molden file: ' + outFileName) psi4.molden(wavefunctions[file], outFileName)
def do_bloch(wfn, n_sites, site_list=None, site_list_orbs=None, molden_file='orbs.molden', skip_localization=False, neutral=False): """ Bloch effective Hamiltonian solver. Solves the Bloch effective Hamiltonian and returns a matrix containing J coupling information. Sites are designated using ``site_list`` or ``site_list_orbs``; if neither of these keywords are specified, each orbital in the CAS/RAS2 space is assumed to be its own site. A Molden file containing the orbitals is written to ``orbs.molden`` (or whichever file is specified by the user). The J coupling values are also written to standard output. Parameters ---------- sf_wfn : sf_wfn SF-IP-EA wfn object containing info about the calculation. n_sites : int The number of sites. site_list : list List of which atoms are "sites". If this is not given, the program assumes one orbital per site. Atomic center ordering starts at zero. Optional. site_list_orbs : list A list of sites, using lists of orbitals rather than atomic centers. (It's a list of lists. For example, for a two-site case where MOs 55, 56, and 59 are on one site and the remaining orbitals are on the other, use ``[[55,56,59],[57,58,60]]``.) Note that ordering starts at 1, not zero, so it follows the same indexing as the MO printing in the Psi4 output files. Optional. molden_file : string Molden filename to which orbitals are written. Optional. Defaults to ``orbs.molden``. skip_localization : bool Whether to skip orbital localization. If true, the user should localize the orbitals in wfn.wfn beforehand! Optional. Defaults to False. neutral : bool Indicates that the RAS eigenvectors passed in were calculated in the neutral determinant space only. Optional. Defaults to False. Returns ------- numpy.ndarray NumPy matrix of J coupling values """ np.set_printoptions(suppress=True) print("Doing Bloch Hamiltonian analysis...") # Put input vector into block form (only need CAS-1SF block!!) n_SF = wfn.n_SF ras1 = wfn.ras1 ras2 = wfn.ras2 e = wfn.e.copy() vecs = wfn.vecs # special case for unpacking neutral determinant space if (neutral): newvecs = np.zeros((ras2, ras2, n_sites)) for i in range(ras2): for n in range(n_sites): newvecs[i, i, n] = wfn.vecs[i, n] newvecs = np.reshape(newvecs, (ras2 * ras2, n_sites)) vecs = newvecs v_b1 = vecs[:(ras2 * ras2), :n_sites].copy() n_roots = v_b1.shape[1] v_b1 = np.reshape(v_b1, (ras2, ras2, n_roots)) # v[i,a] # Obtain info for orbital localization and localize v psi4_wfn = wfn.wfn C = psi4.core.Matrix.to_array(psi4_wfn.Ca(), copy=True) # Allow user to skip our localization and use their own if needed if (not skip_localization): ras1_C = C[:, :ras1] ras2_C = C[:, ras1:ras1 + ras2] ras3_C = C[:, ras1 + ras2:] loc = psi4.core.Localizer.build('BOYS', psi4_wfn.basisset(), psi4.core.Matrix.from_array(ras2_C)) loc.localize() U = psi4.core.Matrix.to_array(loc.U, copy=True) # localize vects v_b1 = np.einsum("ji,jbn->ibn", U, v_b1) v_b1 = np.einsum("ba,ibn->ian", U, v_b1) wfn.local_vecs = np.reshape(v_b1, (ras2 * ras2, n_roots)) # write localized orbitals to wfn and molden C_full_loc = psi4.core.Matrix.from_array( np.column_stack( (ras1_C, psi4.core.Matrix.to_array(loc.L), ras3_C))) psi4_wfn.Ca().copy(C_full_loc) psi4_wfn.Cb().copy(C_full_loc) # write Molden file psi4.molden(psi4_wfn, molden_file) # Extract i=a part (neutral determinants only!!) v_n = None for i in range(v_b1.shape[2]): v_new = np.diagonal(v_b1[:, :, i]) if (type(v_n) == type(None)): v_n = v_new else: v_n = np.vstack((v_n, v_new)) v_n = v_n.T # make sure columns are states rather than rows # Obtain S # S should be I if states are orthonormal orbs_per_site = [] # Handle grouping orbitals if needed if (type(site_list) != type(None)): # Construct density N for sites N = np.zeros((len(site_list), ras2)) bas = psi4_wfn.basisset() S = psi4.core.Matrix.to_array(psi4_wfn.S()) C = psi4.core.Matrix.to_array(psi4_wfn.Ca()) CS = np.einsum("vi,vu->ui", C, S) for atom, A in enumerate(site_list): for i in range(ras2): for mu in range(C.shape[1]): if (bas.function_to_center(mu) == A): N[atom, i] += C[mu, ras1 + i] * CS[mu, ras1 + i] # Reorder v_n rows so they're grouped by site perm = [] for i in range(ras2): diff = abs(N[:, i] - 1) perm.append(np.argmin(diff)) print("Reordering RAS2 determinants as follows:") print(perm) v_n = v_n[np.argsort(perm), :] # permute! # construct coeff matrix R = np.zeros((ras2, len(site_list))) tmp, orbs_per_site = np.unique(perm, return_counts=True) for i, site in enumerate(np.sort(perm)): R[i, site] = 1.0 / math.sqrt(orbs_per_site[site]) # orthonormalize (SVD) v_n = np.dot(R.T, v_n) elif (type(site_list_orbs) != type(None)): # Reorder v_n rows so they're grouped by site perm = [] for site in site_list_orbs: for orb in site: perm.append(orb - ras1 - 1) print("Reordering RAS2 determinants as follows:") print(perm) v_n = v_n[perm, :] # permute! # construct coeff matrix # construct coeff matrix R = np.zeros((ras2, len(site_list_orbs))) ind = 0 for s, site in enumerate(site_list_orbs): orbs_per_site.append(len(site)) for i in range(len(site)): R[ind, s] = 1.0 / math.sqrt(len(site)) ind = ind + 1 # orthonormalize (SVD) v_n = np.dot(R.T, v_n) # Else, assume 1 orbital per site else: orbs_per_site = n_sites * [1] #v_orth = v_n v_orth = lowdin_orth(v_n) S = np.dot(v_orth.T, v_orth) print("Orthogonalized Orbital Overlap:") print(S) # Build Bloch Hamiltonian #H = np.dot(S, v_orth) H = v_orth H = np.dot(H, np.diag(e)) H = np.dot(H, v_orth.T) # invert v_orth J = np.zeros(H.shape) print("Effective Hamiltonian") print(H) print("Orbs Per Site") print(orbs_per_site) print("J Couplings:") for i in range(n_sites): for j in range(i): Sa = orbs_per_site[i] / 2.0 Sb = orbs_per_site[j] / 2.0 J[i, j] = J[j, i] = -1.0 * H[i, j] / (2.0 * math.sqrt(Sa * Sb)) print("\tJ%i%i = %6.6f" % (i, j, J[i, j])) return J
0.0053000000 1.00000000 **** """ return basstrings nstates = 15 psi4.qcdb.libmintsbasisset.basishorde[ 'ANONYMOUS03952CBD'] = basisspec_psi4_yo__anonymous03952cbd psi4.core.set_global_option("BASIS", "anonymous03952cbd") E, wfn = psi4.energy('scf', return_wfn=True) mints = psi4.core.MintsHelper(wfn.basisset()) S_mat = np.asarray(mints.ao_overlap()) n_bas = S_mat.shape[0] so2ao = mints.petite_list().sotoao() psi4.molden(wfn, 'h2.molden') # add 7F to molden file, psi4 doesn't write it for some reason with open("h2.molden", "a") as myfile: myfile.write("\n [7F] \n") molden_dict = {"basis_file": "h2.molden", "molecule": "molden"} s = pyopencap.System(molden_dict) s.check_overlap_mat(S_mat, "psi4") cap_dict = { "cap_type": "box", "cap_x": "6.00", "cap_y": "6.00", "cap_z": "6.7", } pc = pyopencap.CAP(s, cap_dict, nstates)
def run_psi4(self): core.set_output_file(self.output + '.dat') import psi4 psi4.set_memory('1 GB') psi_molecule = psi4.geometry(self.psi_geom) psi4.set_options({ 'basis': self.basis, 'molden_write': False, 'WRITER_FILE_LABEL': str(self.output) + '.dat', 'maxiter': 500, 'fail_on_maxiter': False }) if self.multiplicity != 1: psi4.set_options({'reference': 'ROHF'}) e, wfn = psi4.energy('scf', return_wfn=True) self.molecule.hf_energy = e if os.path.exists('./scr.molden'): os.system('rm scr.molden') if self.active != None: cb = wfn.Cb().to_array() ca = wfn.Ca().to_array() self.molecule.n_orbitals = len(ca) ca[:, self.active + self.reorder] = ca[:, self.reorder + self.active] cb[:, self.active + self.reorder] = cb[:, self.reorder + self.active] if self.loc == 'True': acs = psi4.core.Matrix('null') acs = acs.from_array(ca[:, self.active]) Local = psi4.core.Localizer.build("BOYS", wfn.basisset(), acs) Local.localize() acs = Local.L ca[:, self.active] = acs acs2 = psi4.core.Matrix('null2') acs2 = acs2.from_array(cb[:, self.active]) Local = psi4.core.Localizer.build("BOYS", wfn.basisset(), acs2) Local.localize() acs2 = Local.L cb[:, self.active] = acs2 ca = psi4.core.Matrix.from_array(ca) cb = psi4.core.Matrix.from_array(cb) wfn.Cb().copy(cb) wfn.Ca().copy(ca) psi4.molden(wfn, 'scr.molden') psi4.set_options({'frozen_docc': [self.n_fdoccs]}) self.n_fnoccs = self.molecule.n_orbitals - self.n_fdoccs - len( self.active) psi4.set_options({'frozen_uocc': [self.n_fnoccs]}) self.CASCI = psi4.energy('fci', ref_wfn=wfn) self.molecule.CASCI = self.CASCI self.fci_energy = self.CASCI self.molecule.fci_energy = self.CASCI else: self.CASCI = psi4.energy('fci', ref_wfn=wfn) self.molecule.CASCI = self.CASCI self.fci_energy = self.CASCI self.molecule.fci_energy = self.CASCI self.molecule.n_orbitals = len(wfn.Ca().to_array()) psi4.molden(wfn, 'scr.molden') self.molecule.nuclear_repulsion = psi_molecule.nuclear_repulsion_energy( ) self.molecule.canonical_orbitals = np.asarray(wfn.Ca()) if self.active == None: self.active = [i for i in range(0, self.molecule.n_orbitals)] self.molecule.overlap_integrals = np.asarray(wfn.S()) self.molecule.n_qubits = 2 * self.molecule.n_orbitals self.molecule.orbital_energies = np.asarray(wfn.epsilon_a()) self.molecule.fock_matrix = np.asarray(wfn.Fa()) mints = psi4.core.MintsHelper(wfn.basisset()) self.molecule.one_body_integrals = general_basis_change( np.asarray(mints.ao_kinetic()), self.molecule.canonical_orbitals, (1, 0)) self.molecule.one_body_integrals += general_basis_change( np.asarray(mints.ao_potential()), self.molecule.canonical_orbitals, (1, 0)) two_body_integrals = np.asarray(mints.ao_eri()) two_body_integrals.reshape( (self.molecule.n_orbitals, self.molecule.n_orbitals, self.molecule.n_orbitals, self.molecule.n_orbitals)) two_body_integrals = np.einsum('psqr', two_body_integrals) two_body_integrals = general_basis_change( two_body_integrals, self.molecule.canonical_orbitals, (1, 1, 0, 0)) self.molecule.two_body_integrals = two_body_integrals doccs = [i for i in range(0, self.n_fdoccs)] if self.active != None: self.molecule.n_orbitals = len(self.active) self.molecule.n_qubits = 2 * self.molecule.n_orbitals else: self.molecule.n_orbitals = len(self.molecule.canonical_orbitals) self.molecule.n_qubits = 2 * self.molecule.n_orbitals self.molecule.n_fdoccs = self.n_fdoccs self.molecule.hamiltonian = self.molecule.get_molecular_hamiltonian( occupied_indices=doccs, active_indices=self.active) self.molecule.save() return self.molecule
D 1 1.00 0.0755000 1.0000000 D 1 1.00 0.0377500 1.0000000 D 1 1.00 0.0188750 1.0000000 **** """ return basstrings psi4.qcdb.libmintsbasisset.basishorde[ 'ANONYMOUS03952CBD'] = basisspec_psi4_yo__anonymous03952cbd psi4.core.set_global_option("BASIS", "anonymous03952cbd") E, wfn = psi4.energy('scf', return_wfn=True) psi4.molden(wfn, 'n2.molden') # add 7F to molden file, psi4 doesn't write it for some reason with open("n2.molden", "a") as myfile: myfile.write("\n [7F] \n") # checking overlap matrix mints = psi4.core.MintsHelper(wfn.basisset()) S_mat = np.asarray(mints.ao_overlap()) molden_dict = {"basis_file": "n2.molden", "molecule": "molden"} s = pyopencap.System(molden_dict) s.check_overlap_mat(S_mat, "psi4") print('', end='', flush=True) cap_dict = { "cap_type": "box", "cap_x": "2.76", "cap_y": "2.76",
Ca, Cb, mapping = tcmolden2psi4wfn_ao_mapping(d_molden, restricted=restricted) wfn_minimal_np = np.load("wfn-1step.180.npy", allow_pickle=True) wfn_minimal_np[()]['matrix']["Ca"] = Ca if not restricted: wfn_minimal_np[()]['matrix']["Cb"] = Cb else: wfn_minimal_np[()]['matrix']["Cb"] = Ca np.save("wfn-1step-tc.180.npy", wfn_minimal_np) # ----copy wfn file to the right place with a right name--- print("wfn copying...") pid = str(os.getpid()) targetfile = psi4_scr + filename + '.default.' + pid + '.180.npy' shutil.copyfile("wfn-1step-tc.180.npy", targetfile) # ---final scf--- print("final scf...") psi4.set_options({ 'SOSCF': False, "SOSCF_MAX_ITER": 40, }) psi4.set_options({ "maxiter": 250, "D_CONVERGENCE": 1e-6, "E_CONVERGENCE": 1e-6, "fail_on_maxiter": True }) e, wfn = psi4.energy('b3lyp', molecule=mol, return_wfn=True) wfn.to_file("wfn.180") psi4.molden(wfn, "geo.molden")
def write_molden(wfn): psi4.molden(wfn, 'h2.molden') # add 7F to molden file, psi4 doesn't write it for some reason with open('h2.molden', "a") as myfile: myfile.write("\n [7F] \n")
def calculate_energy(mol, dih, spe_method="SCF", spe_basis="6-31G", geom_opt_technique="None", opt_method="SCF", opt_basis="6-31G", geom_maxiter=100, only_selected_conf=False, molden_output=False, **psi4opts): """Calculates the energy for a single conformer at a single dihedral angle. """ # Argument validation if geom_opt_technique not in ["None", "QM", "MM"]: geom_opt_technique = "None" parent_torsion_tag = "TORSION_ATOMS_ParentMol" torsion_atoms_in_parent = get_sd_data(mol, parent_torsion_tag).split() dih_name = mol.GetTitle() + "_" + "_".join(torsion_atoms_in_parent) if only_selected_conf: conf_selection_tag = "SELECTED_CONFORMER" if not mol.HasData(conf_selection_tag): raise ValueError("Could not find 'SELECTED_CONFORMER' Tag in %s.", dih_name) key_conf_id = mol.GetIntData(conf_selection_tag) for conf in mol.GetConfs(): if only_selected_conf: if conf.GetIdx() != key_conf_id: continue conf_name = get_sd_data(conf, "CONFORMER_LABEL") if only_selected_conf: logging.debug("Only running psi4 calculation for %s" % conf_name) else: logging.debug("Running psi4 calculation for %s" % conf_name) angle_deg = conf.GetDoubleData("TORSION_ANGLE") normalize_coordinates(conf, dih) try: energy, psi_mol, wavefcn = psi4_calculation( conf, dih, conf_name, angle_deg, spe_method, spe_basis, geom_opt_technique, opt_method, opt_basis, geom_maxiter, **psi4opts) except ValueError as e: logging.error(e) raise ValueError( "Failed to run calculation for conformer %s angle %d.", conf_name, angle_deg, ) PSI4_OPT_METHOD_KEY = "PSI4_OPT_METHOD" PSI4_OPT_BASIS_KEY = "PSI4_OPT_BASIS" prev_opt_method = oechem.OEGetSDData(conf, PSI4_OPT_METHOD_KEY) if len(prev_opt_method) > 0: prev_opt_method += "_" prev_opt_basis = oechem.OEGetSDData(conf, PSI4_OPT_BASIS_KEY) if len(prev_opt_basis) > 0: prev_opt_basis += "_" complete_opt_method = prev_opt_method + str(opt_method) complete_opt_basis = prev_opt_basis + str(opt_basis) get_conf_from_psi4_mol(mol, psi_mol, conf) logging.debug("Completed psi4 calculation for %s with energy %f" % (conf_name, energy)) conf.SetEnergy(energy) oechem.OESetSDData(conf, "PSI4_ENERGY", str(energy)) conf.SetDoubleData("PSI4_ENERGY", energy) if geom_opt_technique == "QM": oechem.OESetSDData(conf, PSI4_OPT_METHOD_KEY, complete_opt_method) oechem.OESetSDData(conf, PSI4_OPT_BASIS_KEY, complete_opt_basis) oechem.OESetSDData(conf, "PSI4_SPE_METHOD", str(spe_method)) oechem.OESetSDData(conf, "PSI4_SPE_BASIS", str(spe_basis)) # write wavefuction if molden_output: wf_filename = "{}_{}.molden".format("wavefcn", conf_name) psi4.molden(wavefcn, wf_filename) try: with open(wf_filename, "r") as fptr: molden_data = fptr.read() conf.SetData("MOLDEN_DATA", molden_data) except IOError as e: print( "Unable to save wave function data ", wf_filename, " because of error: ", e, ) if psi4opts: save_sddata(mol, psi4opts)