def run_OH_DVR(cut_dict, extrapolate=0, NumPts=1000, desiredEnergies=3, plotPhasedWfns=False): """ Runs anharmonic DVR over the OH coordinate at every degree value.""" from Converter import Constants, Potentials1D dvr_1D = DVR("ColbertMiller1D") degrees = np.array(list(cut_dict.keys())) potential_array = np.zeros((len(cut_dict), NumPts, 2)) energies_array = np.zeros((len(cut_dict), desiredEnergies)) wavefunctions_array = np.zeros((len(cut_dict), NumPts, desiredEnergies)) mO = Constants.mass("O", to_AU=True) mH = Constants.mass("H", to_AU=True) muOH = 1/(1/mO + 1/mH) for j, n in enumerate(cut_dict): x = Constants.convert(cut_dict[n][:, 0], "angstroms", to_AU=True) en = cut_dict[n][:, 1] - np.min(cut_dict[n][:, 1]) # subtract minimum at each cut to eliminate the electronic component since we fit our adiabats without it. res = dvr_1D.run(potential_function=Potentials1D().potlint(x, en), mass=muOH, divs=NumPts, domain=(min(x)-extrapolate, max(x)+extrapolate), num_wfns=desiredEnergies) potential = Constants.convert(res.potential_energy.diagonal(), "wavenumbers", to_AU=False) grid = Constants.convert(res.grid, "angstroms", to_AU=False) potential_array[j, :, 0] = grid potential_array[j, :, 1] = potential ens = Constants.convert(res.wavefunctions.energies, "wavenumbers", to_AU=False) energies_array[j, :] = ens wavefunctions_array[j, :, :] = res.wavefunctions.wavefunctions epsilon_pots = np.column_stack((degrees, energies_array[:, :desiredEnergies+1])) # data saved in wavenumbers/degrees wavefuns_array = wfn_flipper(wavefunctions_array, plotPhasedWfns=plotPhasedWfns, pot_array=potential_array) return potential_array, epsilon_pots, wavefuns_array
def find_FancyF(FD_file, woo=None, woh=None): from Converter import Constants from McUtils.Zachary import finite_difference mO = Constants.mass("O", to_AU=True) mH = Constants.mass("H", to_AU=True) freqoo = Constants.convert(woo, "wavenumbers", to_AU=True) muOO = mO / 2 freqoh = Constants.convert(woh, "wavenumbers", to_AU=True) muOH = ((2 * mO) * mH) / ((2 * mO) + mH) finite_vals = np.loadtxt(FD_file, skiprows=7) finite_vals = finite_vals[:, 2:] finite_vals[:, 0] *= 2 ens = finite_vals[:, 2] print( "Energy Difference from Minimum: ", Constants.convert(finite_vals[:, 2] - min(finite_vals[:, 2]), "wavenumbers", to_AU=False)) ohDiffs = np.array([ ens[1] - ens[0], ens[6] - ens[5], ens[11] - ens[10], ens[16] - ens[15], ens[21] - ens[20] ]) print("OH energy differences: ", Constants.convert(ohDiffs, "wavenumbers", to_AU=False)) finite_vals[:, :2] = Constants.convert( finite_vals[:, :2], "angstroms", to_AU=True) # convert to bohr for math idx = np.lexsort( (finite_vals[:, 0], finite_vals[:, 1])) # resort so same oh different oo finite_vals = finite_vals[idx] finite_vals = finite_vals.reshape((5, 5, 3)) FR = np.zeros(5) # compute first derivative wrt oo FR for j in range(finite_vals.shape[0]): x = finite_vals[j, :, 0] # roos y = finite_vals[j, :, 2] # energies print("OO energy difference: ", Constants.convert((y[1] - y[0]), "wavenumbers", to_AU=False)) FR[j] = finite_difference(x, y, 1, end_point_precision=0, stencil=5, only_center=True)[0] print(f"FR: {FR}") # compute mixed derivative FrrR FrrR = finite_difference(finite_vals[:, 1, 1], FR, 2, end_point_precision=0, stencil=5, only_center=True)[0] print(f"FrrR: {FrrR}") Qoo = np.sqrt(1 / muOO / freqoo) Qoh = np.sqrt(1 / muOH / freqoh) fancyF = FrrR * Qoh**2 * Qoo return Constants.convert(fancyF, "wavenumbers", to_AU=False)
def get_reducedmass(self): from Converter import Constants mO = Constants.mass("O", to_AU=True) mH = Constants.mass("H", to_AU=True) massdict = dict() muXH = ((2 * mO) * mH) / ((2 * mO) + mH) massdict["muXH"] = muXH muOH = 1 / (1 / mO + 1 / mH) massdict["muOH"] = muOH muOO = mO / 2 massdict["muOO"] = muOO return massdict
def get_reducedmass(self): mO = Constants.mass("O", to_AU=True) mH = Constants.mass("H", to_AU=True) mD = Constants.mass("D", to_AU=True) massdict = dict() muOOH = ((2 * mO) * mH) / ((2 * mO) + mH) massdict["muOOH"] = muOOH muOOD = ((2 * mO) * mD) / ((2 * mO) + mD) massdict["muOOD"] = muOOD muOH = 1 / (1 / mO + 1 / mH) massdict["muOH"] = muOH muOO = mO / 2 massdict["muOO"] = muOO return massdict
def mass_array(self): from Converter import Constants if self._mass_array is None: m = np.array( [Constants.mass(x, to_AU=True) for x in self.atom_array]) self._mass_array = m # returns masses in AMU return self._mass_array
def run_DVR(Epot_array, extrapolate=0, NumPts=1000, desiredEnergies=3): """ Runs anharmonic DVR over the OH coordinate at every degree value.""" from Converter import Constants, Potentials1D dvr_1D = DVR("ColbertMiller1D") mO = Constants.mass("O", to_AU=True) mH = Constants.mass("H", to_AU=True) muOH = 1/(1/mO + 1/mH) x = Constants.convert(Epot_array[:, 0], "angstroms", to_AU=True) en = Epot_array[:, 1] - np.min(Epot_array[:, 1]) res = dvr_1D.run(potential_function=Potentials1D().potlint(x, en), mass=muOH, divs=NumPts, domain=(min(x)-extrapolate, max(x)+extrapolate), num_wfns=desiredEnergies) ens = Constants.convert(res.wavefunctions.energies, "wavenumbers", to_AU=False) energies_array = ens # wavenumbers wavefunctions_array = np.column_stack((res.grid, res.wavefunctions.wavefunctions)) # bohr # np.savetxt("EqTOR_wfns_forMark.dat", wavefunctions_array) return energies_array, wavefunctions_array
def find_FancyF(self): import os from Converter import Constants from McUtils.Zachary import finite_difference mO = Constants.mass("O", to_AU=True) mH = Constants.mass("H", to_AU=True) freqoo = Constants.convert(self.omegaOO, "wavenumbers", to_AU=True) muOO = mO / 2 freqoh = Constants.convert(self.omegaOH, "wavenumbers", to_AU=True) muOH = ((2 * mO) * mH) / ((2 * mO) + mH) fs_dir = os.path.join(self.molecule.mol_dir, "Finite Scan Data", "twoD") if self.molecule.MoleculeName == "H9O4pls": finite_vals = np.loadtxt(f"{fs_dir}/2D_finiteSPEtet_01_008.dat", skiprows=7) elif self.molecule.MoleculeName == "H7O3pls": finite_vals = np.loadtxt(f"{fs_dir}/2D_finiteSPEtri_01_008.dat", skiprows=7) else: raise Exception("Can't compute FancyF of that molecule") finite_vals = finite_vals[:, 2:] finite_vals[:, 0] *= 2 # multiply OO/2 by 2 for OO values finite_vals[:, :2] = Constants.convert( finite_vals[:, :2], "angstroms", to_AU=True) # convert OO/OH to bohr finite_vals[:, 2] -= min( finite_vals[:, 2]) # shift minimum to 0 so that energies match FDgrid = np.array( np.meshgrid(np.unique(finite_vals[:, 0]), np.unique(finite_vals[:, 1]))).T # create mesh OO/OH FDvalues = np.reshape(finite_vals[:, 2], (5, 5)) FrrR = finite_difference(FDgrid, FDvalues, (1, 2), stencil=(5, 5), accuracy=0, end_point_precision=0, only_center=True)[0, 0] Qoo = np.sqrt(1 / muOO / freqoo) Qoh = np.sqrt(1 / muOH / freqoh) fancyF = FrrR * Qoh**2 * Qoo return Constants.convert(fancyF, "wavenumbers", to_AU=False)
def getMass(self): """Uses self.atom_str and Converter.py to create a mass array based off of the molecule. """ from Converter import Constants masses = np.array([Constants.mass(a, to_AU=True) for a in self.atom_str]) return masses